Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: Fixed updating of ethertype in skb_mpls_push()

The skb_mpls_push 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_push 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(0x0800),ipv4(tos=0/0xfc,ttl=64,frag=no),
actions:push_eth(src=00:00:00:00:00:00,dst=00:00:00:00:00:00),
push_mpls(label=13,tc=0,ttl=64,bos=1,eth_type=0x8847),4

Fixes: 8822e270d697 ("net: core: move push MPLS functionality from OvS to core helper")
Signed-off-by: Martin Varghese <martin.varghese@nokia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Martin Varghese and committed by
David S. Miller
d04ac224 099ffd7e

+7 -5
+1 -1
include/linux/skbuff.h
··· 3529 3529 int skb_vlan_pop(struct sk_buff *skb); 3530 3530 int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci); 3531 3531 int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto, 3532 - int mac_len); 3532 + int mac_len, bool ethernet); 3533 3533 int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len, 3534 3534 bool ethernet); 3535 3535 int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse);
+2 -2
net/core/skbuff.c
··· 5484 5484 * Returns 0 on success, -errno otherwise. 5485 5485 */ 5486 5486 int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto, 5487 - int mac_len) 5487 + int mac_len, bool ethernet) 5488 5488 { 5489 5489 struct mpls_shim_hdr *lse; 5490 5490 int err; ··· 5515 5515 lse->label_stack_entry = mpls_lse; 5516 5516 skb_postpush_rcsum(skb, lse, MPLS_HLEN); 5517 5517 5518 - if (skb->dev && skb->dev->type == ARPHRD_ETHER) 5518 + if (ethernet) 5519 5519 skb_mod_eth_type(skb, eth_hdr(skb), mpls_proto); 5520 5520 skb->protocol = mpls_proto; 5521 5521
+2 -1
net/openvswitch/actions.c
··· 166 166 int err; 167 167 168 168 err = skb_mpls_push(skb, mpls->mpls_lse, mpls->mpls_ethertype, 169 - skb->mac_len); 169 + skb->mac_len, 170 + ovs_key_mac_proto(key) == MAC_PROTO_ETHERNET); 170 171 if (err) 171 172 return err; 172 173
+2 -1
net/sched/act_mpls.c
··· 83 83 break; 84 84 case TCA_MPLS_ACT_PUSH: 85 85 new_lse = tcf_mpls_get_lse(NULL, p, !eth_p_mpls(skb->protocol)); 86 - if (skb_mpls_push(skb, new_lse, p->tcfm_proto, mac_len)) 86 + if (skb_mpls_push(skb, new_lse, p->tcfm_proto, mac_len, 87 + skb->dev && skb->dev->type == ARPHRD_ETHER)) 87 88 goto drop; 88 89 break; 89 90 case TCA_MPLS_ACT_MODIFY: