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:
parent
f199b13bc1
commit
7e64a9cabb
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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_len = eth_strip_vlan_ex(iov, iovcnt, iovoff,
|
||||
strip_vlan_index, vet, vet_ext,
|
||||
&pkt->ehdr_buf,
|
||||
&ploff, &tci);
|
||||
} else {
|
||||
pkt->ehdr_buf_len = 0;
|
||||
}
|
||||
|
||||
pkt->tci = tci;
|
||||
|
||||
|
@ -225,16 +225,17 @@ void net_rx_pkt_attach_iovec(struct NetRxPkt *pkt,
|
||||
*
|
||||
* @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
|
||||
* @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);
|
||||
size_t iovoff, int strip_vlan_index,
|
||||
uint16_t vet, uint16_t vet_ext);
|
||||
|
||||
/**
|
||||
* attach data to rx packet
|
||||
|
@ -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
|
||||
|
44
net/eth.c
44
net/eth.c
@ -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 < new_ehdr_size || be16_to_cpu(*new_ehdr_proto) != vet) {
|
||||
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->h_proto = vlan_hdr.h_proto;
|
||||
|
||||
*new_ehdr_proto = vlan_hdr.h_proto;
|
||||
*payload_offset = iovoff + new_ehdr_size + sizeof(vlan_hdr);
|
||||
*tci = be16_to_cpu(vlan_hdr.h_tci);
|
||||
*payload_offset = iovoff + sizeof(*new_ehdr) + sizeof(vlan_hdr);
|
||||
return sizeof(struct eth_header);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return new_ehdr_size;
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user