diff options
| author | Shmulik Ladkani <shmulik.ladkani@gmail.com> | 2016-09-19 12:11:10 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2016-09-22 01:34:20 -0400 |
| commit | 45a497f2d149a4a8061c61518a79d59f1f3034b2 (patch) | |
| tree | 342f1160ba3a5491dadba70104586cf9c69a083c /net/sched | |
| parent | bfca4c520f7ea78138ddccea2de18dc062b0fefd (diff) | |
net/sched: act_vlan: Introduce TCA_VLAN_ACT_MODIFY vlan action
TCA_VLAN_ACT_MODIFY allows one to change an existing tag.
It accepts same attributes as TCA_VLAN_ACT_PUSH (protocol, id,
priority).
If packet is vlan tagged, then the tag gets overwritten according to
user specified attributes.
For example, this allows user to replace a tag's vid while preserving
its priority bits (as opposed to "action vlan pop pipe action vlan push").
Signed-off-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
| -rw-r--r-- | net/sched/act_vlan.c | 29 |
1 files changed, 28 insertions, 1 deletions
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c index 59a8d3150ae2..a95c00b119da 100644 --- a/net/sched/act_vlan.c +++ b/net/sched/act_vlan.c | |||
| @@ -30,6 +30,7 @@ static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a, | |||
| 30 | struct tcf_vlan *v = to_vlan(a); | 30 | struct tcf_vlan *v = to_vlan(a); |
| 31 | int action; | 31 | int action; |
| 32 | int err; | 32 | int err; |
| 33 | u16 tci; | ||
| 33 | 34 | ||
| 34 | spin_lock(&v->tcf_lock); | 35 | spin_lock(&v->tcf_lock); |
| 35 | tcf_lastuse_update(&v->tcf_tm); | 36 | tcf_lastuse_update(&v->tcf_tm); |
| @@ -48,6 +49,30 @@ static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a, | |||
| 48 | if (err) | 49 | if (err) |
| 49 | goto drop; | 50 | goto drop; |
| 50 | break; | 51 | break; |
| 52 | case TCA_VLAN_ACT_MODIFY: | ||
| 53 | /* No-op if no vlan tag (either hw-accel or in-payload) */ | ||
| 54 | if (!skb_vlan_tagged(skb)) | ||
| 55 | goto unlock; | ||
| 56 | /* extract existing tag (and guarantee no hw-accel tag) */ | ||
| 57 | if (skb_vlan_tag_present(skb)) { | ||
| 58 | tci = skb_vlan_tag_get(skb); | ||
| 59 | skb->vlan_tci = 0; | ||
| 60 | } else { | ||
| 61 | /* in-payload vlan tag, pop it */ | ||
| 62 | err = __skb_vlan_pop(skb, &tci); | ||
| 63 | if (err) | ||
| 64 | goto drop; | ||
| 65 | } | ||
| 66 | /* replace the vid */ | ||
| 67 | tci = (tci & ~VLAN_VID_MASK) | v->tcfv_push_vid; | ||
| 68 | /* replace prio bits, if tcfv_push_prio specified */ | ||
| 69 | if (v->tcfv_push_prio) { | ||
| 70 | tci &= ~VLAN_PRIO_MASK; | ||
| 71 | tci |= v->tcfv_push_prio << VLAN_PRIO_SHIFT; | ||
| 72 | } | ||
| 73 | /* put updated tci as hwaccel tag */ | ||
| 74 | __vlan_hwaccel_put_tag(skb, v->tcfv_push_proto, tci); | ||
| 75 | break; | ||
| 51 | default: | 76 | default: |
| 52 | BUG(); | 77 | BUG(); |
| 53 | } | 78 | } |
| @@ -102,6 +127,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, | |||
| 102 | case TCA_VLAN_ACT_POP: | 127 | case TCA_VLAN_ACT_POP: |
| 103 | break; | 128 | break; |
| 104 | case TCA_VLAN_ACT_PUSH: | 129 | case TCA_VLAN_ACT_PUSH: |
| 130 | case TCA_VLAN_ACT_MODIFY: | ||
| 105 | if (!tb[TCA_VLAN_PUSH_VLAN_ID]) { | 131 | if (!tb[TCA_VLAN_PUSH_VLAN_ID]) { |
| 106 | if (exists) | 132 | if (exists) |
| 107 | tcf_hash_release(*a, bind); | 133 | tcf_hash_release(*a, bind); |
| @@ -185,7 +211,8 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a, | |||
| 185 | if (nla_put(skb, TCA_VLAN_PARMS, sizeof(opt), &opt)) | 211 | if (nla_put(skb, TCA_VLAN_PARMS, sizeof(opt), &opt)) |
| 186 | goto nla_put_failure; | 212 | goto nla_put_failure; |
| 187 | 213 | ||
| 188 | if (v->tcfv_action == TCA_VLAN_ACT_PUSH && | 214 | if ((v->tcfv_action == TCA_VLAN_ACT_PUSH || |
| 215 | v->tcfv_action == TCA_VLAN_ACT_MODIFY) && | ||
| 189 | (nla_put_u16(skb, TCA_VLAN_PUSH_VLAN_ID, v->tcfv_push_vid) || | 216 | (nla_put_u16(skb, TCA_VLAN_PUSH_VLAN_ID, v->tcfv_push_vid) || |
| 190 | nla_put_be16(skb, TCA_VLAN_PUSH_VLAN_PROTOCOL, | 217 | nla_put_be16(skb, TCA_VLAN_PUSH_VLAN_PROTOCOL, |
| 191 | v->tcfv_push_proto) || | 218 | v->tcfv_push_proto) || |
