like it was previously done on TC 'csum' (see commit 2ecba2d1e45b ("net: sched: act_csum: Fix csum calc for tagged packets")), TC 'skbedit' might need to adjust the network offset, if the packet has unstripped/multiple tags: otherwise 'inheritdsfield' will just be skipped for QinQ packets.
Fixes: e7e3728bd776 ("net:sched: add action inheritdsfield to skbedit") CC: Li Shuang <shu...@redhat.com> Signed-off-by: Davide Caratti <dcara...@redhat.com> --- net/sched/act_skbedit.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c index 7ec159b95364..693a4317de6e 100644 --- a/net/sched/act_skbedit.c +++ b/net/sched/act_skbedit.c @@ -39,6 +39,7 @@ static int tcf_skbedit_act(struct sk_buff *skb, const struct tc_action *a, { struct tcf_skbedit *d = to_skbedit(a); struct tcf_skbedit_params *params; + unsigned int vlan_hdr_count = 0; int action; tcf_lastuse_update(&d->tcf_tm); @@ -50,9 +51,17 @@ static int tcf_skbedit_act(struct sk_buff *skb, const struct tc_action *a, if (params->flags & SKBEDIT_F_PRIORITY) skb->priority = params->priority; if (params->flags & SKBEDIT_F_INHERITDSFIELD) { - int wlen = skb_network_offset(skb); - - switch (tc_skb_protocol(skb)) { + __be16 proto = tc_skb_protocol(skb); + int wlen; + +again: + wlen = skb_network_offset(skb); + switch (proto) { + case htons(ETH_P_8021AD): /* Fall Through */ + case htons(ETH_P_8021Q): + if (tc_skb_pull_vlans(skb, &vlan_hdr_count, &proto)) + goto err; + goto again; case htons(ETH_P_IP): wlen += sizeof(struct iphdr); if (!pskb_may_pull(skb, wlen)) @@ -61,7 +70,7 @@ static int tcf_skbedit_act(struct sk_buff *skb, const struct tc_action *a, break; case htons(ETH_P_IPV6): - wlen += sizeof(struct ipv6hdr); + wlen += sizeof(struct ipv6hdr); if (!pskb_may_pull(skb, wlen)) goto err; skb->priority = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2; @@ -77,11 +86,18 @@ static int tcf_skbedit_act(struct sk_buff *skb, const struct tc_action *a, } if (params->flags & SKBEDIT_F_PTYPE) skb->pkt_type = params->ptype; + +out: + while (vlan_hdr_count--) { + skb_push(skb, VLAN_HLEN); + skb_reset_network_header(skb); + } return action; err: qstats_drop_inc(this_cpu_ptr(d->common.cpu_qstats)); - return TC_ACT_SHOT; + action = TC_ACT_SHOT; + goto out; } static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = { -- 2.20.1