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

Merge branch 'mpls-push-pop-fix'

Davide Caratti says:

====================
net/sched: fix wrong behavior of MPLS push/pop action

this series contains two fixes for TC 'act_mpls', that try to address
two problems that can be observed configuring simple 'push' / 'pop'
operations:
- patch 1/2 avoids dropping non-MPLS packets that pass through the MPLS
'pop' action.
- patch 2/2 fixes corruption of the L2 header that occurs when 'push'
or 'pop' actions are configured in TC egress path.

v2: - change commit message in patch 1/2 to better describe that the
patch impacts only TC, thanks to Simon Horman
- fix missing documentation of 'mac_len' in patch 2/2
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+26 -17
+3 -2
include/linux/skbuff.h
··· 3510 3510 int __skb_vlan_pop(struct sk_buff *skb, u16 *vlan_tci); 3511 3511 int skb_vlan_pop(struct sk_buff *skb); 3512 3512 int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci); 3513 - int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto); 3514 - int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto); 3513 + int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto, 3514 + int mac_len); 3515 + int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len); 3515 3516 int skb_mpls_update_lse(struct sk_buff *skb, __be32 mpls_lse); 3516 3517 int skb_mpls_dec_ttl(struct sk_buff *skb); 3517 3518 struct sk_buff *pskb_extract(struct sk_buff *skb, int off, int to_copy,
+12 -9
net/core/skbuff.c
··· 5477 5477 * @skb: buffer 5478 5478 * @mpls_lse: MPLS label stack entry to push 5479 5479 * @mpls_proto: ethertype of the new MPLS header (expects 0x8847 or 0x8848) 5480 + * @mac_len: length of the MAC header 5480 5481 * 5481 5482 * Expects skb->data at mac header. 5482 5483 * 5483 5484 * Returns 0 on success, -errno otherwise. 5484 5485 */ 5485 - int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto) 5486 + int skb_mpls_push(struct sk_buff *skb, __be32 mpls_lse, __be16 mpls_proto, 5487 + int mac_len) 5486 5488 { 5487 5489 struct mpls_shim_hdr *lse; 5488 5490 int err; ··· 5501 5499 return err; 5502 5500 5503 5501 if (!skb->inner_protocol) { 5504 - skb_set_inner_network_header(skb, skb->mac_len); 5502 + skb_set_inner_network_header(skb, mac_len); 5505 5503 skb_set_inner_protocol(skb, skb->protocol); 5506 5504 } 5507 5505 5508 5506 skb_push(skb, MPLS_HLEN); 5509 5507 memmove(skb_mac_header(skb) - MPLS_HLEN, skb_mac_header(skb), 5510 - skb->mac_len); 5508 + mac_len); 5511 5509 skb_reset_mac_header(skb); 5512 - skb_set_network_header(skb, skb->mac_len); 5510 + skb_set_network_header(skb, mac_len); 5513 5511 5514 5512 lse = mpls_hdr(skb); 5515 5513 lse->label_stack_entry = mpls_lse; ··· 5528 5526 * 5529 5527 * @skb: buffer 5530 5528 * @next_proto: ethertype of header after popped MPLS header 5529 + * @mac_len: length of the MAC header 5531 5530 * 5532 5531 * Expects skb->data at mac header. 5533 5532 * 5534 5533 * Returns 0 on success, -errno otherwise. 5535 5534 */ 5536 - int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto) 5535 + int skb_mpls_pop(struct sk_buff *skb, __be16 next_proto, int mac_len) 5537 5536 { 5538 5537 int err; 5539 5538 5540 5539 if (unlikely(!eth_p_mpls(skb->protocol))) 5541 - return -EINVAL; 5540 + return 0; 5542 5541 5543 - err = skb_ensure_writable(skb, skb->mac_len + MPLS_HLEN); 5542 + err = skb_ensure_writable(skb, mac_len + MPLS_HLEN); 5544 5543 if (unlikely(err)) 5545 5544 return err; 5546 5545 5547 5546 skb_postpull_rcsum(skb, mpls_hdr(skb), MPLS_HLEN); 5548 5547 memmove(skb_mac_header(skb) + MPLS_HLEN, skb_mac_header(skb), 5549 - skb->mac_len); 5548 + mac_len); 5550 5549 5551 5550 __skb_pull(skb, MPLS_HLEN); 5552 5551 skb_reset_mac_header(skb); 5553 - skb_set_network_header(skb, skb->mac_len); 5552 + skb_set_network_header(skb, mac_len); 5554 5553 5555 5554 if (skb->dev && skb->dev->type == ARPHRD_ETHER) { 5556 5555 struct ethhdr *hdr;
+3 -2
net/openvswitch/actions.c
··· 165 165 { 166 166 int err; 167 167 168 - err = skb_mpls_push(skb, mpls->mpls_lse, mpls->mpls_ethertype); 168 + err = skb_mpls_push(skb, mpls->mpls_lse, mpls->mpls_ethertype, 169 + skb->mac_len); 169 170 if (err) 170 171 return err; 171 172 ··· 179 178 { 180 179 int err; 181 180 182 - err = skb_mpls_pop(skb, ethertype); 181 + err = skb_mpls_pop(skb, ethertype, skb->mac_len); 183 182 if (err) 184 183 return err; 185 184
+8 -4
net/sched/act_mpls.c
··· 55 55 struct tcf_mpls *m = to_mpls(a); 56 56 struct tcf_mpls_params *p; 57 57 __be32 new_lse; 58 - int ret; 58 + int ret, mac_len; 59 59 60 60 tcf_lastuse_update(&m->tcf_tm); 61 61 bstats_cpu_update(this_cpu_ptr(m->common.cpu_bstats), skb); ··· 63 63 /* Ensure 'data' points at mac_header prior calling mpls manipulating 64 64 * functions. 65 65 */ 66 - if (skb_at_tc_ingress(skb)) 66 + if (skb_at_tc_ingress(skb)) { 67 67 skb_push_rcsum(skb, skb->mac_len); 68 + mac_len = skb->mac_len; 69 + } else { 70 + mac_len = skb_network_header(skb) - skb_mac_header(skb); 71 + } 68 72 69 73 ret = READ_ONCE(m->tcf_action); 70 74 ··· 76 72 77 73 switch (p->tcfm_action) { 78 74 case TCA_MPLS_ACT_POP: 79 - if (skb_mpls_pop(skb, p->tcfm_proto)) 75 + if (skb_mpls_pop(skb, p->tcfm_proto, mac_len)) 80 76 goto drop; 81 77 break; 82 78 case TCA_MPLS_ACT_PUSH: 83 79 new_lse = tcf_mpls_get_lse(NULL, p, !eth_p_mpls(skb->protocol)); 84 - if (skb_mpls_push(skb, new_lse, p->tcfm_proto)) 80 + if (skb_mpls_push(skb, new_lse, p->tcfm_proto, mac_len)) 85 81 goto drop; 86 82 break; 87 83 case TCA_MPLS_ACT_MODIFY: