igb: Strip the second VLAN tag for extended VLAN

Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
Akihiko Odaki 2023-05-23 11:43:29 +09:00 committed by Jason Wang
parent f199b13bc1
commit 7e64a9cabb
6 changed files with 66 additions and 43 deletions

View file

@ -1711,7 +1711,8 @@ e1000e_receive_internal(E1000ECore *core, const struct iovec *iov, int iovcnt,
}
net_rx_pkt_attach_iovec_ex(core->rx_pkt, iov, iovcnt, iov_ofs,
e1000x_vlan_enabled(core->mac), core->mac[VET]);
e1000x_vlan_enabled(core->mac) ? 0 : -1,
core->mac[VET], 0);
e1000e_rss_parse_packet(core, core->rx_pkt, &rss_info);
e1000e_rx_ring_init(core, &rxr, rss_info.queue);

View file

@ -1611,6 +1611,7 @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt,
E1000E_RxRing rxr;
E1000E_RSSInfo rss_info;
size_t total_size;
int strip_vlan_index;
int i;
trace_e1000e_rx_receive_iov(iovcnt);
@ -1672,9 +1673,18 @@ igb_receive_internal(IGBCore *core, const struct iovec *iov, int iovcnt,
igb_rx_ring_init(core, &rxr, i);
if (!igb_rx_strip_vlan(core, rxr.i)) {
strip_vlan_index = -1;
} else if (core->mac[CTRL_EXT] & BIT(26)) {
strip_vlan_index = 1;
} else {
strip_vlan_index = 0;
}
net_rx_pkt_attach_iovec_ex(core->rx_pkt, iov, iovcnt, iov_ofs,
igb_rx_strip_vlan(core, rxr.i),
core->mac[VET] & 0xffff);
strip_vlan_index,
core->mac[VET] & 0xffff,
core->mac[VET] >> 16);
total_size = net_rx_pkt_get_total_len(core->rx_pkt) +
e1000x_fcs_len(core->mac);

View file

@ -137,20 +137,17 @@ void net_rx_pkt_attach_iovec(struct NetRxPkt *pkt,
void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt,
const struct iovec *iov, int iovcnt,
size_t iovoff, bool strip_vlan,
uint16_t vet)
size_t iovoff, int strip_vlan_index,
uint16_t vet, uint16_t vet_ext)
{
uint16_t tci = 0;
uint16_t ploff = iovoff;
assert(pkt);
if (strip_vlan) {
pkt->ehdr_buf_len = eth_strip_vlan_ex(iov, iovcnt, iovoff, vet,
&pkt->ehdr_buf,
&ploff, &tci);
} else {
pkt->ehdr_buf_len = 0;
}
pkt->ehdr_buf_len = eth_strip_vlan_ex(iov, iovcnt, iovoff,
strip_vlan_index, vet, vet_ext,
&pkt->ehdr_buf,
&ploff, &tci);
pkt->tci = tci;

View file

@ -223,18 +223,19 @@ void net_rx_pkt_attach_iovec(struct NetRxPkt *pkt,
/**
* attach scatter-gather data to rx packet
*
* @pkt: packet
* @iov: received data scatter-gather list
* @iovcnt number of elements in iov
* @iovoff data start offset in the iov
* @strip_vlan: should the module strip vlan from data
* @vet: VLAN tag Ethernet type
* @pkt: packet
* @iov: received data scatter-gather list
* @iovcnt: number of elements in iov
* @iovoff: data start offset in the iov
* @strip_vlan_index: index of Q tag if it is to be stripped. negative otherwise.
* @vet: VLAN tag Ethernet type
* @vet_ext: outer VLAN tag Ethernet type
*
*/
void net_rx_pkt_attach_iovec_ex(struct NetRxPkt *pkt,
const struct iovec *iov, int iovcnt,
size_t iovoff, bool strip_vlan,
uint16_t vet);
const struct iovec *iov, int iovcnt,
size_t iovoff, int strip_vlan_index,
uint16_t vet, uint16_t vet_ext);
/**
* attach data to rx packet

View file

@ -347,8 +347,8 @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
uint16_t *payload_offset, uint16_t *tci);
size_t
eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
uint16_t vet, void *new_ehdr_buf,
eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff, int index,
uint16_t vet, uint16_t vet_ext, void *new_ehdr_buf,
uint16_t *payload_offset, uint16_t *tci);
uint16_t

View file

@ -269,36 +269,50 @@ eth_strip_vlan(const struct iovec *iov, int iovcnt, size_t iovoff,
}
size_t
eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff,
uint16_t vet, void *new_ehdr_buf,
eth_strip_vlan_ex(const struct iovec *iov, int iovcnt, size_t iovoff, int index,
uint16_t vet, uint16_t vet_ext, void *new_ehdr_buf,
uint16_t *payload_offset, uint16_t *tci)
{
struct vlan_header vlan_hdr;
struct eth_header *new_ehdr = (struct eth_header *) new_ehdr_buf;
uint16_t *new_ehdr_proto;
size_t new_ehdr_size;
size_t copied;
size_t copied = iov_to_buf(iov, iovcnt, iovoff,
new_ehdr, sizeof(*new_ehdr));
switch (index) {
case 0:
new_ehdr_proto = &PKT_GET_ETH_HDR(new_ehdr_buf)->h_proto;
new_ehdr_size = sizeof(struct eth_header);
copied = iov_to_buf(iov, iovcnt, iovoff, new_ehdr_buf, new_ehdr_size);
break;
if (copied < sizeof(*new_ehdr)) {
case 1:
new_ehdr_proto = &PKT_GET_VLAN_HDR(new_ehdr_buf)->h_proto;
new_ehdr_size = sizeof(struct eth_header) + sizeof(struct vlan_header);
copied = iov_to_buf(iov, iovcnt, iovoff, new_ehdr_buf, new_ehdr_size);
if (be16_to_cpu(PKT_GET_ETH_HDR(new_ehdr_buf)->h_proto) != vet_ext) {
return 0;
}
break;
default:
return 0;
}
if (be16_to_cpu(new_ehdr->h_proto) == vet) {
copied = iov_to_buf(iov, iovcnt, iovoff + sizeof(*new_ehdr),
&vlan_hdr, sizeof(vlan_hdr));
if (copied < sizeof(vlan_hdr)) {
return 0;
}
new_ehdr->h_proto = vlan_hdr.h_proto;
*tci = be16_to_cpu(vlan_hdr.h_tci);
*payload_offset = iovoff + sizeof(*new_ehdr) + sizeof(vlan_hdr);
return sizeof(struct eth_header);
if (copied < new_ehdr_size || be16_to_cpu(*new_ehdr_proto) != vet) {
return 0;
}
return 0;
copied = iov_to_buf(iov, iovcnt, iovoff + new_ehdr_size,
&vlan_hdr, sizeof(vlan_hdr));
if (copied < sizeof(vlan_hdr)) {
return 0;
}
*new_ehdr_proto = vlan_hdr.h_proto;
*payload_offset = iovoff + new_ehdr_size + sizeof(vlan_hdr);
*tci = be16_to_cpu(vlan_hdr.h_tci);
return new_ehdr_size;
}
void