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
13 changes: 7 additions & 6 deletions vm/devices/net/netvsp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2610,11 +2610,10 @@ impl<T: RingMem> NetChannel<T> {
ppi = rest;
}

metadata.l2_len = if metadata.vlan.is_some() {
net_backend::ETHERNET_VLAN_HEADER_LEN
} else {
net_backend::ETHERNET_HEADER_LEN
} as u8;
// The frame data always has a 14-byte Ethernet header; when
// VLAN is present it arrives out-of-band in the PPI (not inline
// in the frame), so l2_len is unconditionally 14.
metadata.l2_len = net_backend::ETHERNET_HEADER_LEN as u8;

if metadata.flags.offload_tcp_checksum() || metadata.flags.offload_udp_checksum() {
// The offset must be set if we're handling checksums; we already know from the above logic
Expand Down Expand Up @@ -3486,7 +3485,9 @@ impl Adapter {
rndisprot::Oid::OID_GEN_MAC_OPTIONS => {
let options: u32 = rndisprot::MAC_OPTION_COPY_LOOKAHEAD_DATA
| rndisprot::MAC_OPTION_TRANSFERS_NOT_PEND
| rndisprot::MAC_OPTION_NO_LOOPBACK;
| rndisprot::MAC_OPTION_NO_LOOPBACK
| rndisprot::MAC_OPTION_8021P_PRIORITY
| rndisprot::MAC_OPTION_8021Q_VLAN;
writer.write(options.as_bytes())?;
}
rndisprot::Oid::OID_GEN_MEDIA_CONNECT_STATUS => {
Expand Down
40 changes: 19 additions & 21 deletions vm/devices/net/netvsp/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1619,7 +1619,7 @@ impl<'a> TestNicChannel<'a> {

buf_writer.write(packet.as_bytes()).unwrap();

const VLAN_TCP_HEADER_OFFSET: u16 = 38; // Ethernet (18) + IPv4 (20)
const VLAN_TCP_HEADER_OFFSET: u16 = 34; // Ethernet (14) + IPv4 (20); tag is in PPI only
if tcp_checksum || udp_checksum {
let checksum_info = rndisprot::TxTcpIpChecksumInfo::new_zeroed()
.set_is_ipv4(true)
Expand Down Expand Up @@ -6225,21 +6225,19 @@ async fn rndis_send_tcp_checksum_packet_zero_transport_header_offset_ipv6(driver
);
}

fn build_vlan_ipv4_tcp_packet(vlan_id: u16) -> Vec<u8> {
fn build_ipv4_tcp_packet() -> Vec<u8> {
let mut data = vec![0u8; 60];

data[..6].copy_from_slice(&[0x10, 0x11, 0x12, 0x13, 0x14, 0x15]);
data[6..12].copy_from_slice(&[0x20, 0x21, 0x22, 0x23, 0x24, 0x25]);
data[12..14].copy_from_slice(&0x8100u16.to_be_bytes());
data[14..16].copy_from_slice(&(vlan_id & 0x0fff).to_be_bytes());
data[16..18].copy_from_slice(&0x0800u16.to_be_bytes());
data[..6].copy_from_slice(&[0x10, 0x11, 0x12, 0x13, 0x14, 0x15]); // dst MAC
data[6..12].copy_from_slice(&[0x20, 0x21, 0x22, 0x23, 0x24, 0x25]); // src MAC
data[12..14].copy_from_slice(&0x0800u16.to_be_bytes()); // EtherType = IPv4

data[18] = 0x45; // IPv4, 20-byte header
data[20..22].copy_from_slice(&(42u16).to_be_bytes());
data[26] = 64; // TTL
data[27] = 6; // TCP
data[14] = 0x45; // IPv4, 20-byte header
data[16..18].copy_from_slice(&(46u16).to_be_bytes()); // total length
data[22] = 64; // TTL
data[23] = 6; // Protocol = TCP

data[38 + 12] = 0x50; // TCP data offset = 5 (20 bytes)
data[34 + 12] = 0x50; // TCP data offset = 5 (20 bytes)

data
}
Expand Down Expand Up @@ -6283,7 +6281,7 @@ async fn rndis_send_tcp_checksum_packet_with_vlan_ppi(driver: DefaultDriver) {
assert_eq!(initialize_complete.request_id, 123);
assert_eq!(initialize_complete.status, rndisprot::STATUS_SUCCESS);

let data = build_vlan_ipv4_tcp_packet(37);
let data = build_ipv4_tcp_packet();
let vlan_info = rndisprot::EthVlanInfo::read_from_bytes(&(37u32 << 4).to_le_bytes()).unwrap();
channel
.send_rndis_packet_offload_with_vlan(&data, true, false, false, vlan_info)
Expand All @@ -6302,12 +6300,12 @@ async fn rndis_send_tcp_checksum_packet_with_vlan_ppi(driver: DefaultDriver) {
assert!(metadata.flags.offload_ip_header_checksum());
assert!(metadata.flags.is_ipv4());
assert_eq!(
metadata.l2_len, 18,
"VLAN-tagged packets must use an 18-byte L2 header"
metadata.l2_len, 14,
"VLAN tag is in PPI only; frame data has a standard 14-byte L2 header"
);
assert_eq!(
metadata.l3_len, 20,
"VLAN-tagged IPv4 packets must keep a 20-byte L3 header"
"IPv4 packets must keep a 20-byte L3 header"
);
assert_eq!(
read_netvsp_counter(&nic.channel, "queues/0/tx_vlan_packets").await,
Expand Down Expand Up @@ -6355,7 +6353,7 @@ async fn rndis_send_lso_packet_with_vlan_ppi(driver: DefaultDriver) {
assert_eq!(initialize_complete.request_id, 123);
assert_eq!(initialize_complete.status, rndisprot::STATUS_SUCCESS);

let data = build_vlan_ipv4_tcp_packet(91);
let data = build_ipv4_tcp_packet();
let vlan_info = rndisprot::EthVlanInfo::read_from_bytes(&(91u32 << 4).to_le_bytes()).unwrap();
channel
.send_rndis_packet_offload_with_vlan(&data, false, false, true, vlan_info)
Expand All @@ -6375,12 +6373,12 @@ async fn rndis_send_lso_packet_with_vlan_ppi(driver: DefaultDriver) {
assert!(metadata.flags.offload_ip_header_checksum());
assert!(metadata.flags.is_ipv4());
assert_eq!(
metadata.l2_len, 18,
"VLAN-tagged packets must use an 18-byte L2 header"
metadata.l2_len, 14,
"VLAN tag is in PPI only; frame data has a standard 14-byte L2 header"
);
assert_eq!(
metadata.l3_len, 20,
"VLAN-tagged IPv4 packets must keep a 20-byte L3 header"
"IPv4 packets must keep a 20-byte L3 header"
);
assert_eq!(metadata.max_segment_size, 1460);
assert_eq!(
Expand Down Expand Up @@ -7315,7 +7313,7 @@ async fn vlan_tx_counter_increments(driver: DefaultDriver) {
.unwrap();

// Send a VLAN-tagged packet.
let data = build_vlan_ipv4_tcp_packet(42);
let data = build_ipv4_tcp_packet();
let vlan_info = rndisprot::EthVlanInfo::read_from_bytes(&(42u32 << 4).to_le_bytes()).unwrap();
channel
.send_rndis_packet_offload_with_vlan(&data, true, false, false, vlan_info)
Expand Down
Loading