diff options
author | Eric Garver <e@erig.me> | 2016-10-04 10:14:46 -0400 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2016-10-04 08:47:18 -0700 |
commit | 1ebdc7eb8112a89f924061f36d015e5f275e071f (patch) | |
tree | 8417d4074b9640f160670245838c442b31d7c131 /lib | |
parent | 47d5c1e0524330b852a0abbf6a64142175fc3d3c (diff) | |
download | openvswitch-1ebdc7eb8112a89f924061f36d015e5f275e071f.tar.gz |
netdev-linux: double tagged packets should use 0x88a8
We need to check if a packet is double tagged. If so make sure to push
0x88a8 instead of 0x8100. Without this a simple port redirect of 802.1ad
frames means the outer tag gets translated from 0x88a8 to 0x8100 by the
userspace datapath.
This only affected kernels that don't use TP_STATUS_VLAN_TPID_VALID,
which is kernels < 3.14.
Signed-off-by: Eric Garver <e@erig.me>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/netdev-linux.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index e563693ad..a5a9ec1ab 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -995,12 +995,14 @@ netdev_linux_rxq_dealloc(struct netdev_rxq *rxq_) } static ovs_be16 -auxdata_to_vlan_tpid(const struct tpacket_auxdata *aux) +auxdata_to_vlan_tpid(const struct tpacket_auxdata *aux, bool double_tagged) { if (aux->tp_status & TP_STATUS_VLAN_TPID_VALID) { return htons(aux->tp_vlan_tpid); + } else if (double_tagged) { + return htons(ETH_TYPE_VLAN_8021AD); } else { - return htons(ETH_TYPE_VLAN); + return htons(ETH_TYPE_VLAN_8021Q); } } @@ -1060,11 +1062,17 @@ netdev_linux_rxq_recv_sock(int fd, struct dp_packet *buffer) aux = ALIGNED_CAST(struct tpacket_auxdata *, CMSG_DATA(cmsg)); if (auxdata_has_vlan_tci(aux)) { + struct eth_header *eth; + bool double_tagged; + if (retval < ETH_HEADER_LEN) { return EINVAL; } - eth_push_vlan(buffer, auxdata_to_vlan_tpid(aux), + eth = dp_packet_data(buffer); + double_tagged = eth->eth_type == htons(ETH_TYPE_VLAN_8021Q); + + eth_push_vlan(buffer, auxdata_to_vlan_tpid(aux, double_tagged), htons(aux->tp_vlan_tci)); break; } |