diff options
author | Akihiko Odaki <akihiko.odaki@daynix.com> | 2023-05-23 11:43:29 +0900 |
---|---|---|
committer | Jason Wang <jasowang@redhat.com> | 2023-05-23 15:20:15 +0800 |
commit | 7e64a9cabb6b8fe12d315e355e0c362e1453f227 (patch) | |
tree | 0aeab89dc78e4a682a068db32d1da82949c0cc44 /net | |
parent | f199b13bc113c46eaddcf9f375d13f1e400b4e35 (diff) | |
download | qemu-7e64a9cabb6b8fe12d315e355e0c362e1453f227.zip qemu-7e64a9cabb6b8fe12d315e355e0c362e1453f227.tar.gz qemu-7e64a9cabb6b8fe12d315e355e0c362e1453f227.tar.bz2 |
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/eth.c | 52 |
1 files changed, 33 insertions, 19 deletions
@@ -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; - - size_t copied = iov_to_buf(iov, iovcnt, iovoff, - new_ehdr, sizeof(*new_ehdr)); - - if (copied < sizeof(*new_ehdr)) { - return 0; - } + uint16_t *new_ehdr_proto; + size_t new_ehdr_size; + size_t copied; - if (be16_to_cpu(new_ehdr->h_proto) == vet) { - copied = iov_to_buf(iov, iovcnt, iovoff + sizeof(*new_ehdr), - &vlan_hdr, sizeof(vlan_hdr)); + 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(vlan_hdr)) { + 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; - new_ehdr->h_proto = vlan_hdr.h_proto; + default: + return 0; + } - *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; + } + + copied = iov_to_buf(iov, iovcnt, iovoff + new_ehdr_size, + &vlan_hdr, sizeof(vlan_hdr)); + if (copied < sizeof(vlan_hdr)) { + return 0; } - 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 |