net:sched: add action inheritdsfield to skbedit
The new action inheritdsfield copies the field DS of IPv4 and IPv6 packets into skb->priority. This enables later classification of packets based on the DS field. v5: *Update the drop counter for TC_ACT_SHOT v4: *Not allow setting flags other than the expected ones. *Allow dumping the pure flags. v3: *Use optional flags, so that it won't break old versions of tc. *Allow users to set both SKBEDIT_F_PRIORITY and SKBEDIT_F_INHERITDSFIELD flags. v2: *Fix the style issue *Move the code from skbmod to skbedit Original idea by Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: Qiaobin Fu <qiaobinf@bu.edu> Reviewed-by: Michel Machado <michel@digirati.com.br> Acked-by: Jamal Hadi Salim <jhs@mojatatu.com> Reviewed-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Acked-by: Davide Caratti <dcaratti@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f145b0a707
commit
e7e3728bd7
2 changed files with 43 additions and 0 deletions
|
@ -30,6 +30,7 @@
|
|||
#define SKBEDIT_F_MARK 0x4
|
||||
#define SKBEDIT_F_PTYPE 0x8
|
||||
#define SKBEDIT_F_MASK 0x10
|
||||
#define SKBEDIT_F_INHERITDSFIELD 0x20
|
||||
|
||||
struct tc_skbedit {
|
||||
tc_gen;
|
||||
|
@ -45,6 +46,7 @@ enum {
|
|||
TCA_SKBEDIT_PAD,
|
||||
TCA_SKBEDIT_PTYPE,
|
||||
TCA_SKBEDIT_MASK,
|
||||
TCA_SKBEDIT_FLAGS,
|
||||
__TCA_SKBEDIT_MAX
|
||||
};
|
||||
#define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
#include <linux/rtnetlink.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/pkt_sched.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/dsfield.h>
|
||||
|
||||
#include <linux/tc_act/tc_skbedit.h>
|
||||
#include <net/tc_act/tc_skbedit.h>
|
||||
|
@ -41,6 +44,25 @@ static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
|
|||
|
||||
if (d->flags & SKBEDIT_F_PRIORITY)
|
||||
skb->priority = d->priority;
|
||||
if (d->flags & SKBEDIT_F_INHERITDSFIELD) {
|
||||
int wlen = skb_network_offset(skb);
|
||||
|
||||
switch (tc_skb_protocol(skb)) {
|
||||
case htons(ETH_P_IP):
|
||||
wlen += sizeof(struct iphdr);
|
||||
if (!pskb_may_pull(skb, wlen))
|
||||
goto err;
|
||||
skb->priority = ipv4_get_dsfield(ip_hdr(skb)) >> 2;
|
||||
break;
|
||||
|
||||
case htons(ETH_P_IPV6):
|
||||
wlen += sizeof(struct ipv6hdr);
|
||||
if (!pskb_may_pull(skb, wlen))
|
||||
goto err;
|
||||
skb->priority = ipv6_get_dsfield(ipv6_hdr(skb)) >> 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (d->flags & SKBEDIT_F_QUEUE_MAPPING &&
|
||||
skb->dev->real_num_tx_queues > d->queue_mapping)
|
||||
skb_set_queue_mapping(skb, d->queue_mapping);
|
||||
|
@ -53,6 +75,11 @@ static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
|
|||
|
||||
spin_unlock(&d->tcf_lock);
|
||||
return d->tcf_action;
|
||||
|
||||
err:
|
||||
d->tcf_qstats.drops++;
|
||||
spin_unlock(&d->tcf_lock);
|
||||
return TC_ACT_SHOT;
|
||||
}
|
||||
|
||||
static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
|
||||
|
@ -62,6 +89,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
|
|||
[TCA_SKBEDIT_MARK] = { .len = sizeof(u32) },
|
||||
[TCA_SKBEDIT_PTYPE] = { .len = sizeof(u16) },
|
||||
[TCA_SKBEDIT_MASK] = { .len = sizeof(u32) },
|
||||
[TCA_SKBEDIT_FLAGS] = { .len = sizeof(u64) },
|
||||
};
|
||||
|
||||
static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
|
||||
|
@ -114,6 +142,13 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
|
|||
mask = nla_data(tb[TCA_SKBEDIT_MASK]);
|
||||
}
|
||||
|
||||
if (tb[TCA_SKBEDIT_FLAGS] != NULL) {
|
||||
u64 *pure_flags = nla_data(tb[TCA_SKBEDIT_FLAGS]);
|
||||
|
||||
if (*pure_flags & SKBEDIT_F_INHERITDSFIELD)
|
||||
flags |= SKBEDIT_F_INHERITDSFIELD;
|
||||
}
|
||||
|
||||
parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
|
||||
|
||||
exists = tcf_idr_check(tn, parm->index, a, bind);
|
||||
|
@ -178,6 +213,7 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
|
|||
.action = d->tcf_action,
|
||||
};
|
||||
struct tcf_t t;
|
||||
u64 pure_flags = 0;
|
||||
|
||||
if (nla_put(skb, TCA_SKBEDIT_PARMS, sizeof(opt), &opt))
|
||||
goto nla_put_failure;
|
||||
|
@ -196,6 +232,11 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
|
|||
if ((d->flags & SKBEDIT_F_MASK) &&
|
||||
nla_put_u32(skb, TCA_SKBEDIT_MASK, d->mask))
|
||||
goto nla_put_failure;
|
||||
if (d->flags & SKBEDIT_F_INHERITDSFIELD)
|
||||
pure_flags |= SKBEDIT_F_INHERITDSFIELD;
|
||||
if (pure_flags != 0 &&
|
||||
nla_put(skb, TCA_SKBEDIT_FLAGS, sizeof(pure_flags), &pure_flags))
|
||||
goto nla_put_failure;
|
||||
|
||||
tcf_tm_dump(&t, &d->tcf_tm);
|
||||
if (nla_put_64bit(skb, TCA_SKBEDIT_TM, sizeof(t), &t, TCA_SKBEDIT_PAD))
|
||||
|
|
Loading…
Reference in a new issue