summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorEric Garver <e@erig.me>2016-10-04 10:14:46 -0400
committerBen Pfaff <blp@ovn.org>2016-10-04 08:47:18 -0700
commit1ebdc7eb8112a89f924061f36d015e5f275e071f (patch)
tree8417d4074b9640f160670245838c442b31d7c131 /lib
parent47d5c1e0524330b852a0abbf6a64142175fc3d3c (diff)
downloadopenvswitch-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.c14
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;
}