The skb_mpls_pop was not updating ethertype of an ethernet packet if the packet was originally received from a non ARPHRD_ETHER device. In the below OVS data path flow, since the device corresponding to port 7 is an l3 device (ARPHRD_NONE) the skb_mpls_pop function does not update the ethertype of the packet even though the previous push_eth action had added an ethernet header to the packet. recirc_id(0),in_port(7),eth_type(0x8847), mpls(label=12/0xfffff,tc=0/0,ttl=0/0x0,bos=1/1), actions:push_eth(src=00:00:00:00:00:00,dst=00:00:00:00:00:00), pop_mpls(eth_type=0x800),4
Unified · Split
| @@ -3530,7 +3530,8 @@ int skb_vlan_pop(struct sk_buff *skb); · 3529 unmodified lines | |||
| 3530 | int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci); | 3530 | int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci); |
| 3531 | int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto, | 3531 | int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto, |
| 3532 | int mac_len); | 3532 | int mac_len); |
| 3533 | int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len); | 3533 | int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len, |
| 3534 | bool ethernet); | ||
| 3534 | int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse); | 3535 | int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse); |
| 3535 | int skb_mpls_dec_ttl(struct sk_buff *skb); | 3536 | int skb_mpls_dec_ttl(struct sk_buff *skb); |
| 3536 | struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy, | 3537 | struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy, |
| @@ -5529,12 +5529,14 @@ EXPORT_SYMBOL_GPL(skb_mpls_push); · 5528 unmodified lines | |||
| 5529 | * @skb: buffer | 5529 | * @skb: buffer |
| 5530 | * @next_proto: ethertype of header after popped MPLS header | 5530 | * @next_proto: ethertype of header after popped MPLS header |
| 5531 | * @mac_len: length of the MAC header | 5531 | * @mac_len: length of the MAC header |
| 5532 | * @ethernet: flag to indicate if ethernet header is present in packet | ||
| 5532 | * | 5533 | * |
| 5533 | * Expects skb->data at mac header. | 5534 | * Expects skb->data at mac header. |
| 5534 | * | 5535 | * |
| 5535 | * Returns 0 on success, -errno otherwise. | 5536 | * Returns 0 on success, -errno otherwise. |
| 5536 | */ | 5537 | */ |
| 5537 | int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len) | 5538 | int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len, |
| 5539 | bool ethernet) | ||
| 5538 | { | 5540 | { |
| 5539 | int err; | 5541 | int err; |
| 5540 | 5542 | ||
| @@ -5553,7 +5555,7 @@ int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len) · 12 unmodified lines | |||
| 5553 | skb_reset_mac_header(skb); | 5555 | skb_reset_mac_header(skb); |
| 5554 | skb_set_network_header(skb, mac_len); | 5556 | skb_set_network_header(skb, mac_len); |
| 5555 | 5557 | ||
| 5556 | if (skb->dev && skb->dev->type == ARPHRD_ETHER) { | 5558 | if (ethernet) { |
| 5557 | struct ethhdr *hdr; | 5559 | struct ethhdr *hdr; |
| 5558 | 5560 | ||
| 5559 | /* use mpls_hdr() to get ethertype to account for VLANs. */ | 5561 | /* use mpls_hdr() to get ethertype to account for VLANs. */ |
| @@ -179,7 +179,8 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key, · 178 unmodified lines | |||
| 179 | { | 179 | { |
| 180 | int err; | 180 | int err; |
| 181 | 181 | ||
| 182 | err = skb_mpls_pop(skb, ethertype, skb->mac_len); | 182 | err = skb_mpls_pop(skb, ethertype, skb->mac_len, |
| 183 | ovs_key_mac_proto(key) == MAC_PROTO_ETHERNET); | ||
| 183 | if (err) | 184 | if (err) |
| 184 | return err; | 185 | return err; |
| 185 | 186 | ||
| @@ -1,6 +1,7 @@ | |||
| 1 | // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) | 1 | // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) |
| 2 | /* Copyright (C) 2019 Netronome Systems, Inc. */ | 2 | /* Copyright (C) 2019 Netronome Systems, Inc. */ |
| 3 | 3 | ||
| 4 | #include <linux/if_arp.h> | ||
| 4 | #include <linux/init.h> | 5 | #include <linux/init.h> |
| 5 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
| 6 | #include <linux/module.h> | 7 | #include <linux/module.h> |
| @@ -76,7 +77,8 @@ static int tcf_mpls_act(struct sk_buff *skb, const struct tc_action *a, · 69 unmodified lines | |||
| 76 | 77 | ||
| 77 | switch (p->tcfm_action) { | 78 | switch (p->tcfm_action) { |
| 78 | case TCA_MPLS_ACT_POP: | 79 | case TCA_MPLS_ACT_POP: |
| 79 | if (skb_mpls_pop(skb, p->tcfm_proto, mac_len)) | 80 | if (skb_mpls_pop(skb, p->tcfm_proto, mac_len, |
| 81 | skb->dev && skb->dev->type == ARPHRD_ETHER)) | ||
| 80 | goto drop; | 82 | goto drop; |
| 81 | break; | 83 | break; |
| 82 | case TCA_MPLS_ACT_PUSH: | 84 | case TCA_MPLS_ACT_PUSH: |