Do not always set skb->protocol to be the ethertype of the L3 header. For a packet with non-accelerated VLAN tags skb->protocol needs to be the ethertype of the outermost non-accelerated VLAN ethertype.
Any VLAN offloading is undone on the OVS netlink interface, and any VLAN tags added by userspace are non-accelerated, as are double tagged VLAN packets. Fixes: 018c1dda5f ("openvswitch: 802.1AD Flow handling, actions, vlan parsing, netlink attributes") Fixes: 5108bbaddc ("openvswitch: add processing of L3 packets") Signed-off-by: Jarno Rajahalme <ja...@ovn.org> Signed-off-by: Yi Yang <yi.y.y...@intel.com> --- datapath/datapath.c | 1 - datapath/flow.c | 42 +++++++++++++++++------------------------- 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index 1deb62d..dd19a0e 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -617,7 +617,6 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info) rcu_assign_pointer(flow->sf_acts, acts); packet->priority = flow->key.phy.priority; packet->mark = flow->key.phy.skb_mark; - packet->protocol = flow->key.eth.type; rcu_read_lock(); dp = get_dp_rcu(net, ovs_header->dp_ifindex); diff --git a/datapath/flow.c b/datapath/flow.c index 240bd00..cf35272 100644 --- a/datapath/flow.c +++ b/datapath/flow.c @@ -334,6 +334,7 @@ static int parse_vlan(struct sk_buff *skb, struct sw_flow_key *key) qp = (struct qtag_prefix *) skb->data; key->eth.tci = qp->tci | htons(VLAN_TAG_PRESENT); + key->eth.type = qp->eth_type; __skb_pull(skb, sizeof(struct qtag_prefix)); return 0; @@ -493,6 +494,7 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) return -EINVAL; skb_reset_network_header(skb); + key->eth.type = skb->protocol; } else { eth = eth_hdr(skb); ether_addr_copy(key->eth.src, eth->h_source); @@ -504,11 +506,14 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) */ key->eth.tci = 0; - if (skb_vlan_tag_present(skb)) + if (skb_vlan_tag_present(skb)) { key->eth.tci = htons(skb->vlan_tci); + key->eth.type = skb->vlan_proto; + } else if (eth->h_proto == htons(ETH_P_8021Q)) if (unlikely(parse_vlan(skb, key))) return -ENOMEM; + skb->protocol = key->eth.type; key->eth.type = parse_ethertype(skb); if (unlikely(key->eth.type == htons(0))) @@ -519,7 +524,8 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) } skb_reset_mac_len(skb); - key->eth.type = skb->protocol; + if (!eth_type_is_vlan(skb->protocol)) + skb->protocol = key->eth.type; /* Network layer. */ if (key->eth.type == htons(ETH_P_IP)) { @@ -786,29 +792,15 @@ int ovs_flow_key_extract_userspace(struct net *net, const struct nlattr *attr, if (err) return err; - if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) { - /* key_extract assumes that skb->protocol is set-up for - * layer 3 packets which is the case for other callers, - * in particular packets recieved from the network stack. - * Here the correct value can be set from the metadata - * extracted above. - */ - skb->protocol = key->eth.type; - } else { - struct ethhdr *eth; - - skb_reset_mac_header(skb); - eth = eth_hdr(skb); - - /* Normally, setting the skb 'protocol' field would be - * handled by a call to eth_type_trans(), but it assumes - * there's a sending device, which we may not have. - */ - if (eth_proto_is_802_3(eth->h_proto)) - skb->protocol = eth->h_proto; - else - skb->protocol = htons(ETH_P_802_2); - } + /* key_extract assumes that skb->protocol is set-up for + * layer 3 packets which is the case for other callers, + * in particular packets recieved from the network stack. + * Here the correct value can be set from the metadata + * extracted above. For layer 2 packets we initialize + * skb->protocol to zero and set it in key_extract() while + * parsing the L2 headers. + */ + skb->protocol = key->eth.type; return key_extract(skb, key); } -- 2.1.0 _______________________________________________ dev mailing list d...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-dev