Commit e7e3728b authored by Qiaobin Fu's avatar Qiaobin Fu Committed by David S. Miller

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: default avatarQiaobin Fu <qiaobinf@bu.edu>
Reviewed-by: default avatarMichel Machado <michel@digirati.com.br>
Acked-by: default avatarJamal Hadi Salim <jhs@mojatatu.com>
Reviewed-by: default avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Acked-by: default avatarDavide Caratti <dcaratti@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f145b0a7
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#define SKBEDIT_F_MARK 0x4 #define SKBEDIT_F_MARK 0x4
#define SKBEDIT_F_PTYPE 0x8 #define SKBEDIT_F_PTYPE 0x8
#define SKBEDIT_F_MASK 0x10 #define SKBEDIT_F_MASK 0x10
#define SKBEDIT_F_INHERITDSFIELD 0x20
struct tc_skbedit { struct tc_skbedit {
tc_gen; tc_gen;
...@@ -45,6 +46,7 @@ enum { ...@@ -45,6 +46,7 @@ enum {
TCA_SKBEDIT_PAD, TCA_SKBEDIT_PAD,
TCA_SKBEDIT_PTYPE, TCA_SKBEDIT_PTYPE,
TCA_SKBEDIT_MASK, TCA_SKBEDIT_MASK,
TCA_SKBEDIT_FLAGS,
__TCA_SKBEDIT_MAX __TCA_SKBEDIT_MAX
}; };
#define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1) #define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
......
...@@ -23,6 +23,9 @@ ...@@ -23,6 +23,9 @@
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <net/netlink.h> #include <net/netlink.h>
#include <net/pkt_sched.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 <linux/tc_act/tc_skbedit.h>
#include <net/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, ...@@ -41,6 +44,25 @@ static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
if (d->flags & SKBEDIT_F_PRIORITY) if (d->flags & SKBEDIT_F_PRIORITY)
skb->priority = d->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 && if (d->flags & SKBEDIT_F_QUEUE_MAPPING &&
skb->dev->real_num_tx_queues > d->queue_mapping) skb->dev->real_num_tx_queues > d->queue_mapping)
skb_set_queue_mapping(skb, 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, ...@@ -53,6 +75,11 @@ static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
spin_unlock(&d->tcf_lock); spin_unlock(&d->tcf_lock);
return d->tcf_action; 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] = { 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] = { ...@@ -62,6 +89,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
[TCA_SKBEDIT_MARK] = { .len = sizeof(u32) }, [TCA_SKBEDIT_MARK] = { .len = sizeof(u32) },
[TCA_SKBEDIT_PTYPE] = { .len = sizeof(u16) }, [TCA_SKBEDIT_PTYPE] = { .len = sizeof(u16) },
[TCA_SKBEDIT_MASK] = { .len = sizeof(u32) }, [TCA_SKBEDIT_MASK] = { .len = sizeof(u32) },
[TCA_SKBEDIT_FLAGS] = { .len = sizeof(u64) },
}; };
static int tcf_skbedit_init(struct net *net, struct nlattr *nla, 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, ...@@ -114,6 +142,13 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
mask = nla_data(tb[TCA_SKBEDIT_MASK]); 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]); parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
exists = tcf_idr_check(tn, parm->index, a, bind); 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, ...@@ -178,6 +213,7 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
.action = d->tcf_action, .action = d->tcf_action,
}; };
struct tcf_t t; struct tcf_t t;
u64 pure_flags = 0;
if (nla_put(skb, TCA_SKBEDIT_PARMS, sizeof(opt), &opt)) if (nla_put(skb, TCA_SKBEDIT_PARMS, sizeof(opt), &opt))
goto nla_put_failure; goto nla_put_failure;
...@@ -196,6 +232,11 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, ...@@ -196,6 +232,11 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
if ((d->flags & SKBEDIT_F_MASK) && if ((d->flags & SKBEDIT_F_MASK) &&
nla_put_u32(skb, TCA_SKBEDIT_MASK, d->mask)) nla_put_u32(skb, TCA_SKBEDIT_MASK, d->mask))
goto nla_put_failure; 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); tcf_tm_dump(&t, &d->tcf_tm);
if (nla_put_64bit(skb, TCA_SKBEDIT_TM, sizeof(t), &t, TCA_SKBEDIT_PAD)) if (nla_put_64bit(skb, TCA_SKBEDIT_TM, sizeof(t), &t, TCA_SKBEDIT_PAD))
......
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