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

net/sched: act_mpls: Add action to push MPLS LSE before Ethernet header

Define the MAC_PUSH action which pushes an MPLS LSE before the mac
header (instead of between the mac and the network headers as the
plain PUSH action does).

The only special case is when the skb has an offloaded VLAN. In that
case, it has to be inlined before pushing the MPLS header.

Signed-off-by: Guillaume Nault <gnault@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Guillaume Nault and committed by
David S. Miller
a45294af 19fbcb36

+19
+1
include/uapi/linux/tc_act/tc_mpls.h
··· 10 10 #define TCA_MPLS_ACT_PUSH 2 11 11 #define TCA_MPLS_ACT_MODIFY 3 12 12 #define TCA_MPLS_ACT_DEC_TTL 4 13 + #define TCA_MPLS_ACT_MAC_PUSH 5 13 14 14 15 struct tc_mpls { 15 16 tc_gen; /* generic TC action fields. */
+18
net/sched/act_mpls.c
··· 87 87 skb->dev && skb->dev->type == ARPHRD_ETHER)) 88 88 goto drop; 89 89 break; 90 + case TCA_MPLS_ACT_MAC_PUSH: 91 + if (skb_vlan_tag_present(skb)) { 92 + if (__vlan_insert_inner_tag(skb, skb->vlan_proto, 93 + skb_vlan_tag_get(skb), 94 + ETH_HLEN) < 0) 95 + goto drop; 96 + 97 + skb->protocol = skb->vlan_proto; 98 + __vlan_hwaccel_clear_tag(skb); 99 + } 100 + 101 + new_lse = tcf_mpls_get_lse(NULL, p, mac_len || 102 + !eth_p_mpls(skb->protocol)); 103 + 104 + if (skb_mpls_push(skb, new_lse, p->tcfm_proto, 0, false)) 105 + goto drop; 106 + break; 90 107 case TCA_MPLS_ACT_MODIFY: 91 108 new_lse = tcf_mpls_get_lse(mpls_hdr(skb), p, false); 92 109 if (skb_mpls_update_lse(skb, new_lse)) ··· 205 188 } 206 189 break; 207 190 case TCA_MPLS_ACT_PUSH: 191 + case TCA_MPLS_ACT_MAC_PUSH: 208 192 if (!tb[TCA_MPLS_LABEL]) { 209 193 NL_SET_ERR_MSG_MOD(extack, "Label is required for MPLS push"); 210 194 return -EINVAL;