Commit a45294af authored by Guillaume Nault's avatar Guillaume Nault Committed by David S. Miller

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: default avatarGuillaume Nault <gnault@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 19fbcb36
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#define TCA_MPLS_ACT_PUSH 2 #define TCA_MPLS_ACT_PUSH 2
#define TCA_MPLS_ACT_MODIFY 3 #define TCA_MPLS_ACT_MODIFY 3
#define TCA_MPLS_ACT_DEC_TTL 4 #define TCA_MPLS_ACT_DEC_TTL 4
#define TCA_MPLS_ACT_MAC_PUSH 5
struct tc_mpls { struct tc_mpls {
tc_gen; /* generic TC action fields. */ tc_gen; /* generic TC action fields. */
......
...@@ -87,6 +87,23 @@ static int tcf_mpls_act(struct sk_buff *skb, const struct tc_action *a, ...@@ -87,6 +87,23 @@ static int tcf_mpls_act(struct sk_buff *skb, const struct tc_action *a,
skb->dev && skb->dev->type == ARPHRD_ETHER)) skb->dev && skb->dev->type == ARPHRD_ETHER))
goto drop; goto drop;
break; break;
case TCA_MPLS_ACT_MAC_PUSH:
if (skb_vlan_tag_present(skb)) {
if (__vlan_insert_inner_tag(skb, skb->vlan_proto,
skb_vlan_tag_get(skb),
ETH_HLEN) < 0)
goto drop;
skb->protocol = skb->vlan_proto;
__vlan_hwaccel_clear_tag(skb);
}
new_lse = tcf_mpls_get_lse(NULL, p, mac_len ||
!eth_p_mpls(skb->protocol));
if (skb_mpls_push(skb, new_lse, p->tcfm_proto, 0, false))
goto drop;
break;
case TCA_MPLS_ACT_MODIFY: case TCA_MPLS_ACT_MODIFY:
new_lse = tcf_mpls_get_lse(mpls_hdr(skb), p, false); new_lse = tcf_mpls_get_lse(mpls_hdr(skb), p, false);
if (skb_mpls_update_lse(skb, new_lse)) if (skb_mpls_update_lse(skb, new_lse))
...@@ -188,6 +205,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla, ...@@ -188,6 +205,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
} }
break; break;
case TCA_MPLS_ACT_PUSH: case TCA_MPLS_ACT_PUSH:
case TCA_MPLS_ACT_MAC_PUSH:
if (!tb[TCA_MPLS_LABEL]) { if (!tb[TCA_MPLS_LABEL]) {
NL_SET_ERR_MSG_MOD(extack, "Label is required for MPLS push"); NL_SET_ERR_MSG_MOD(extack, "Label is required for MPLS push");
return -EINVAL; return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment