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

Commit 656aae43 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-sched-multichain-filters'



Jiri Pirko says:

====================
net: sched: introduce multichain support for filters

Currently, each classful qdisc holds one chain of filters.
This chain is traversed and each filter could be matched on, which
may lead to execution of list of actions. One of such action
could be "reclassify", which would "reset" the processing of the
filter chain.

So this filter chain could be looked at as a flat table.
Sometimes it is convenient for user to configure a hierarchy
of tables. Example usecase is encapsulation.

Hierarchy of tables is a common way how it is done in HW pipelines.
So it is much more convenient to offload this.

This patchset contains two major patches:
8/10 - This patch introduces the support for having multiple
       chains of filters.
10/10 - This patch adds new control action to allow going to specified chain

The rest of the patches are smaller or bigger depencies of those 2.
Please see individual patch descriptions for details.

Corresponding iproute2 patches are appended as a reply to this cover letter.

Simple example:
$ tc qdisc add dev eth0 ingress
$ tc filter add dev eth0 parent ffff: protocol ip pref 33 flower dst_mac 52:54:00:3d:c7:6d action goto chain 11
$ tc filter add dev eth0 parent ffff: protocol ip pref 22 chain 11 flower dst_ip 192.168.40.1 action drop
$ tc filter show dev eth0 root
filter parent ffff: protocol ip pref 33 flower chain 0
filter parent ffff: protocol ip pref 33 flower chain 0 handle 0x1
  dst_mac 52:54:00:3d:c7:6d
  eth_type ipv4
        action order 1: gact action goto chain 11
         random type none pass val 0
         index 2 ref 1 bind 1

filter parent ffff: protocol ip pref 22 flower chain 11
filter parent ffff: protocol ip pref 22 flower chain 11 handle 0x1
  eth_type ipv4
  dst_ip 192.168.40.1
        action order 1: gact action drop
         random type none pass val 0
         index 3 ref 1 bind 1
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c63fbb0b db50514f
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ struct tc_action {
	struct gnet_stats_basic_cpu __percpu *cpu_bstats;
	struct gnet_stats_queue __percpu *cpu_qstats;
	struct tc_cookie	*act_cookie;
	struct tcf_chain	*goto_chain;
};
#define tcf_head	common.tcfa_head
#define tcf_index	common.tcfa_index
@@ -180,12 +181,12 @@ int tcf_unregister_action(struct tc_action_ops *a,
int tcf_action_destroy(struct list_head *actions, int bind);
int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions,
		    int nr_actions, struct tcf_result *res);
int tcf_action_init(struct net *net, struct nlattr *nla,
				  struct nlattr *est, char *n, int ovr,
				  int bind, struct list_head *);
struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
				    struct nlattr *est, char *n, int ovr,
				    int bind);
int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
		    struct nlattr *est, char *name, int ovr, int bind,
		    struct list_head *actions);
struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
				    struct nlattr *nla, struct nlattr *est,
				    char *name, int ovr, int bind);
int tcf_action_dump(struct sk_buff *skb, struct list_head *, int, int);
int tcf_action_dump_old(struct sk_buff *skb, struct tc_action *a, int, int);
int tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int, int);
+22 −2
Original line number Diff line number Diff line
@@ -18,10 +18,30 @@ int register_tcf_proto_ops(struct tcf_proto_ops *ops);
int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);

#ifdef CONFIG_NET_CLS
void tcf_destroy_chain(struct tcf_proto __rcu **fl);
struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index);
void tcf_chain_put(struct tcf_chain *chain);
int tcf_block_get(struct tcf_block **p_block,
		  struct tcf_proto __rcu **p_filter_chain);
void tcf_block_put(struct tcf_block *block);
int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
		 struct tcf_result *res, bool compat_mode);

#else
static inline void tcf_destroy_chain(struct tcf_proto __rcu **fl)
static inline
int tcf_block_get(struct tcf_block **p_block,
		  struct tcf_proto __rcu **p_filter_chain)
{
	return 0;
}

static inline void tcf_block_put(struct tcf_block *block)
{
}

static inline int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
			       struct tcf_result *res, bool compat_mode)
{
	return TC_ACT_UNSPEC;
}
#endif

+0 −3
Original line number Diff line number Diff line
@@ -113,9 +113,6 @@ static inline void qdisc_run(struct Qdisc *q)
		__qdisc_run(q);
}

int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
		struct tcf_result *res, bool compat_mode);

static inline __be16 tc_skb_protocol(const struct sk_buff *skb)
{
	/* We need to take extra care in case the skb came via
+23 −3
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <linux/pkt_cls.h>
#include <linux/percpu.h>
#include <linux/dynamic_queue_limits.h>
#include <linux/list.h>
#include <net/gen_stats.h>
#include <net/rtnetlink.h>

@@ -153,7 +154,7 @@ struct Qdisc_class_ops {
	void			(*walk)(struct Qdisc *, struct qdisc_walker * arg);

	/* Filter manipulation */
	struct tcf_proto __rcu ** (*tcf_chain)(struct Qdisc *, unsigned long);
	struct tcf_block *	(*tcf_block)(struct Qdisc *, unsigned long);
	bool			(*tcf_cl_offload)(u32 classid);
	unsigned long		(*bind_tcf)(struct Qdisc *, unsigned long,
					u32 classid);
@@ -192,9 +193,14 @@ struct Qdisc_ops {


struct tcf_result {
	union {
		struct {
			unsigned long	class;
			u32		classid;
		};
		const struct tcf_proto *goto_tp;
	};
};

struct tcf_proto_ops {
	struct list_head	head;
@@ -236,6 +242,7 @@ struct tcf_proto {
	struct Qdisc		*q;
	void			*data;
	const struct tcf_proto_ops	*ops;
	struct tcf_chain	*chain;
	struct rcu_head		rcu;
};

@@ -247,6 +254,19 @@ struct qdisc_skb_cb {
	unsigned char		data[QDISC_CB_PRIV_LEN];
};

struct tcf_chain {
	struct tcf_proto __rcu *filter_chain;
	struct tcf_proto __rcu **p_filter_chain;
	struct list_head list;
	struct tcf_block *block;
	u32 index; /* chain index */
	unsigned int refcnt;
};

struct tcf_block {
	struct list_head chain_list;
};

static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
{
	struct qdisc_skb_cb *qcb;
+1 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ enum {
	(((combined) & (~TC_ACT_EXT_VAL_MASK)) == opcode)

#define TC_ACT_JUMP __TC_ACT_EXT(1)
#define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2)

/* Action type identifiers*/
enum {
Loading