Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4627,6 +4627,7 @@ dependencies = [
"mesh",
"net_backend",
"pal_async",
"parking_lot",
"pci_core",
"safeatomic",
"test_with_tracing",
Expand Down
23 changes: 21 additions & 2 deletions vm/devices/net/gdma/src/bnic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ impl BufferAccess for GuestBuffers {
},
}

if let Some(vlan) = &metadata.vlan {
flags.set_rx_vlantag_present(true);
flags.set_rx_vlan_id(vlan.vlan_id as u32);
}

let packet = &mut self.rx_packets[id.0 as usize];

let cqe_type = if metadata.len > packet.len as usize {
Expand Down Expand Up @@ -548,6 +553,11 @@ impl TxRxTask {

let sge0 = sqe.sgl().first().context("no sgl")?;
let total_len: usize = sqe.sgl().iter().map(|sge| sge.size as usize).sum();
let l2_len = if oob.l_oob.inject_vlan_pri_tag() {
net_backend::ETHERNET_VLAN_HEADER_LEN
} else {
net_backend::ETHERNET_HEADER_LEN
};
let mut meta = TxMetadata {
id: TxId(0),
segment_count: sqe.sgl().len().try_into().unwrap(),
Expand All @@ -558,10 +568,19 @@ impl TxRxTask {
.with_offload_udp_checksum(oob.s_oob.comp_udp_csum())
.with_is_ipv4(oob.s_oob.is_outer_ipv4())
.with_is_ipv6(oob.s_oob.is_outer_ipv6() && !oob.s_oob.is_outer_ipv4()),
l2_len: 14,
l3_len: oob.s_oob.trans_off().clamp(14, 255) - 14,
l2_len: l2_len as u8,
l3_len: oob.s_oob.trans_off().clamp(l2_len as u16, 255) - l2_len as u16,
l4_len: 0,
transport_header_offset: 0,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oob.s_oob.trans_off() Just so that the test bnic is closely aligned with real behavior.

max_segment_size: 0,
vlan: oob
.l_oob
.inject_vlan_pri_tag()
.then(|| net_backend::VlanMetadata {
priority: oob.l_oob.pcp(),
drop_eligible_indicator: oob.l_oob.dei(),
vlan_id: oob.l_oob.vlan_id(),
}),
};

if sqe.header.params.client_oob_in_sgl() {
Expand Down
32 changes: 32 additions & 0 deletions vm/devices/net/net_backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,24 @@ pub trait BufferAccess {
}
}

pub const ETHERNET_HEADER_LEN: u32 = 14;
pub const ETHERNET_VLAN_HEADER_LEN: u32 = 18;

pub const IPV4_MIN_HEADER_LEN: u16 = 20;
pub const IPV6_MIN_HEADER_LEN: u16 = 40;

#[derive(Debug, Copy, Clone)]
pub struct VlanMetadata {
/// Priority for 802.1Q. Actually a 3-bit value.
pub priority: u8,
/// In pretty much every circumstance this is false. When
/// it is used, setting DEI will inform switches/routing infra
/// that this can be dropped before higher priority traffic.
pub drop_eligible_indicator: bool,
/// The 802.1Q ID for this transmission. Actually a 12-bit value.
pub vlan_id: u16,
}

/// A receive buffer ID.
#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
Expand Down Expand Up @@ -308,6 +326,10 @@ pub struct RxMetadata {
pub l4_checksum: RxChecksumState,
/// The L4 protocol.
pub l4_protocol: L4Protocol,
/// Information about 802.1Q VLAN tagging. When a vlan is in use, this structure
/// is populated. Only applies when traffic is being received over an L2 connection,
/// so L3-only or above traffic will not use this option.
pub vlan: Option<VlanMetadata>,
}

impl Default for RxMetadata {
Expand All @@ -318,6 +340,7 @@ impl Default for RxMetadata {
ip_checksum: RxChecksumState::Unknown,
l4_checksum: RxChecksumState::Unknown,
l4_protocol: L4Protocol::Unknown,
vlan: None,
}
}
}
Expand Down Expand Up @@ -396,10 +419,17 @@ pub struct TxMetadata {
/// The length of the TCP header. Only guaranteed to be set if various
/// offload flags are set.
pub l4_len: u8,
/// The offset into the buffer where the L4 header begins (TCP or UDP). Only
/// expected to be set if offload (checksum and/or segmentation) flags are set.
pub transport_header_offset: u16,
/// The maximum segment size, used for segmentation offload (TSO or USO).
/// Only guaranteed to be set if [`TxFlags::offload_tcp_segmentation`] or
/// [`TxFlags::offload_udp_segmentation`] is set.
pub max_segment_size: u16,
/// Information about 802.1Q VLAN tagging. When a vlan is in use, this structure
/// is populated. Only applies when traffic is being sent over an L2 connection,
/// so L3-only or above traffic will not use this option.
Comment thread
ben-zen marked this conversation as resolved.
pub vlan: Option<VlanMetadata>,
}

/// Flags affecting transmit behavior.
Expand Down Expand Up @@ -444,7 +474,9 @@ impl Default for TxMetadata {
l2_len: 0,
l3_len: 0,
l4_len: 0,
transport_header_offset: 0,
max_segment_size: 0,
vlan: None,
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions vm/devices/net/net_backend/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,10 @@ impl BufferAccess for Bufs {
*self.inner.rx_metadata[id.0 as usize].lock() = Some(*metadata);
}
}

impl Bufs {
/// Returns the [`RxMetadata`] written for the given receive buffer, if any.
pub fn rx_metadata(&self, id: RxId) -> Option<RxMetadata> {
*self.inner.rx_metadata[id.0 as usize].lock()
}
}
1 change: 1 addition & 0 deletions vm/devices/net/net_consomme/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ impl consomme::Client for Client<'_> {
} else {
L4Protocol::Unknown
},
vlan: None,
},
data,
);
Expand Down
1 change: 1 addition & 0 deletions vm/devices/net/net_mana/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ zerocopy.workspace = true
[dev-dependencies]
chipset_device.workspace = true
gdma.workspace = true
parking_lot.workspace = true
pci_core.workspace = true
test_with_tracing.workspace = true
user_driver_emulated_mock.workspace = true
Expand Down
17 changes: 15 additions & 2 deletions vm/devices/net/net_mana/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ use net_backend::TxId;
use net_backend::TxOffloadSupport;
use net_backend::TxSegment;
use net_backend::TxSegmentType;
use net_backend::VlanMetadata;
use pal_async::task::Spawn;
use safeatomic::AtomicSliceOps;
use std::collections::VecDeque;
Expand Down Expand Up @@ -965,6 +966,11 @@ impl<T: DeviceBacking + Send> Queue for ManaQueue<T> {
} else {
(L4Protocol::Unknown, RxChecksumState::Unknown)
};
let vlantag = rx_oob.flags.rx_vlantag_present().then(|| VlanMetadata {
drop_eligible_indicator: false,
priority: 0,
vlan_id: rx_oob.flags.rx_vlan_id() as u16,
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Increment the counter. Maybe here?
self.stats.rx_packets_vlan.increment();

let len = rx_oob.ppi[0].pkt_len.into();
pool.write_header(
rx.id,
Expand All @@ -974,6 +980,7 @@ impl<T: DeviceBacking + Send> Queue for ManaQueue<T> {
ip_checksum,
l4_checksum,
l4_protocol,
vlan: vlantag,
},
);
if rx.bounced_len_with_padding > 0 {
Expand Down Expand Up @@ -1163,10 +1170,16 @@ impl<T: DeviceBacking> ManaQueue<T> {
.set_comp_tcp_csum(meta.flags.offload_tcp_checksum());
oob.s_oob
.set_comp_udp_csum(meta.flags.offload_udp_checksum());
if meta.flags.offload_tcp_checksum() {
if meta.flags.offload_tcp_checksum() || meta.flags.offload_udp_checksum() {
oob.s_oob.set_trans_off(meta.l2_len as u16 + meta.l3_len);
}
let short_format = self.vp_offset <= 0xff;
if let Some(vlan) = &meta.vlan {
oob.l_oob.set_inject_vlan_pri_tag(true);
oob.l_oob.set_vlan_id(vlan.vlan_id);
oob.l_oob.set_pcp(vlan.priority);
oob.l_oob.set_dei(vlan.drop_eligible_indicator);
}
let short_format = self.vp_offset <= 0xff && meta.vlan.is_none();
if short_format {
oob.s_oob.set_pkt_fmt(MANA_SHORT_PKT_FMT);
oob.s_oob.set_short_vp_offset(self.vp_offset as u8);
Expand Down
Loading
Loading