Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -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 {
	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)
+41 −0
Original line number Original line Diff line number Diff line
@@ -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,


	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,


	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] = {
	[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,
		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,
		.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,
	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))