Commit 34df6a8a authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'tc_action_ops-refactor'



Zhengchao Shao says:

====================
net: refactor the walk and lookup hook functions in tc_action_ops

The implementation logic of the walk/lookup hook function in each action
module is the same. Therefore, the two functions can be reconstructed.
When registering tc_action_ops of each action module, the corresponding
net_id is saved to tc_action_ops. In this way, the net_id of the
corresponding module can be directly obtained in act_api without executing
the specific walk and lookup hook functions. Then, generic functions can
be added to replace the walk and lookup hook functions of each action
module. Last, modify each action module in alphabetical order.

Reserve the walk and lookup interfaces and delete them when they are no
longer used.

This patchset has been tested by using TDC, and I will add selftest in
other patchset.

Last, thanks to Jamal Hadi Salim and Cong Wang for their advice.
---
v3: remove hole from the structure tc_action_ops
v2: save the net_id of each TC action module to the tc_action_ops structure
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents dd14043a 6d13a65d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ struct tc_action_ops {
	struct list_head head;
	char    kind[IFNAMSIZ];
	enum tca_id  id; /* identifier should match kind */
	unsigned int	net_id;
	size_t	size;
	struct module		*owner;
	int     (*act)(struct sk_buff *, const struct tc_action *,
+29 −4
Original line number Diff line number Diff line
@@ -676,6 +676,31 @@ int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index)
}
EXPORT_SYMBOL(tcf_idr_search);

static int __tcf_generic_walker(struct net *net, struct sk_buff *skb,
				struct netlink_callback *cb, int type,
				const struct tc_action_ops *ops,
				struct netlink_ext_ack *extack)
{
	struct tc_action_net *tn = net_generic(net, ops->net_id);

	if (unlikely(ops->walk))
		return ops->walk(net, skb, cb, type, ops, extack);

	return tcf_generic_walker(tn, skb, cb, type, ops, extack);
}

static int __tcf_idr_search(struct net *net,
			    const struct tc_action_ops *ops,
			    struct tc_action **a, u32 index)
{
	struct tc_action_net *tn = net_generic(net, ops->net_id);

	if (unlikely(ops->lookup))
		return ops->lookup(net, a, index);

	return tcf_idr_search(tn, a, index);
}

static int tcf_idr_delete_index(struct tcf_idrinfo *idrinfo, u32 index)
{
	struct tc_action *p;
@@ -926,7 +951,7 @@ int tcf_register_action(struct tc_action_ops *act,
	struct tc_action_ops *a;
	int ret;

	if (!act->act || !act->dump || !act->init || !act->walk || !act->lookup)
	if (!act->act || !act->dump || !act->init)
		return -EINVAL;

	/* We have to register pernet ops before making the action ops visible,
@@ -1638,7 +1663,7 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
		goto err_out;
	}
	err = -ENOENT;
	if (ops->lookup(net, &a, index) == 0) {
	if (__tcf_idr_search(net, ops, &a, index) == 0) {
		NL_SET_ERR_MSG(extack, "TC action with specified index not found");
		goto err_mod;
	}
@@ -1703,7 +1728,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
		goto out_module_put;
	}

	err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops, extack);
	err = __tcf_generic_walker(net, skb, &dcb, RTM_DELACTION, ops, extack);
	if (err <= 0) {
		nla_nest_cancel(skb, nest);
		goto out_module_put;
@@ -2121,7 +2146,7 @@ static int tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
	if (nest == NULL)
		goto out_module_put;

	ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o, NULL);
	ret = __tcf_generic_walker(net, skb, cb, RTM_GETACTION, a_o, NULL);
	if (ret < 0)
		goto out_module_put;

+4 −24
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ struct tcf_bpf_cfg {
	bool is_ebpf;
};

static unsigned int bpf_net_id;
static struct tc_action_ops act_bpf_ops;

static int tcf_bpf_act(struct sk_buff *skb, const struct tc_action *act,
@@ -280,7 +279,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
			struct tcf_proto *tp, u32 flags,
			struct netlink_ext_ack *extack)
{
	struct tc_action_net *tn = net_generic(net, bpf_net_id);
	struct tc_action_net *tn = net_generic(net, act_bpf_ops.net_id);
	bool bind = flags & TCA_ACT_FLAGS_BIND;
	struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
	struct tcf_chain *goto_ch = NULL;
@@ -390,23 +389,6 @@ static void tcf_bpf_cleanup(struct tc_action *act)
	tcf_bpf_cfg_cleanup(&tmp);
}

static int tcf_bpf_walker(struct net *net, struct sk_buff *skb,
			  struct netlink_callback *cb, int type,
			  const struct tc_action_ops *ops,
			  struct netlink_ext_ack *extack)
{
	struct tc_action_net *tn = net_generic(net, bpf_net_id);

	return tcf_generic_walker(tn, skb, cb, type, ops, extack);
}

static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index)
{
	struct tc_action_net *tn = net_generic(net, bpf_net_id);

	return tcf_idr_search(tn, a, index);
}

static struct tc_action_ops act_bpf_ops __read_mostly = {
	.kind		=	"bpf",
	.id		=	TCA_ID_BPF,
@@ -415,27 +397,25 @@ static struct tc_action_ops act_bpf_ops __read_mostly = {
	.dump		=	tcf_bpf_dump,
	.cleanup	=	tcf_bpf_cleanup,
	.init		=	tcf_bpf_init,
	.walk		=	tcf_bpf_walker,
	.lookup		=	tcf_bpf_search,
	.size		=	sizeof(struct tcf_bpf),
};

static __net_init int bpf_init_net(struct net *net)
{
	struct tc_action_net *tn = net_generic(net, bpf_net_id);
	struct tc_action_net *tn = net_generic(net, act_bpf_ops.net_id);

	return tc_action_net_init(net, tn, &act_bpf_ops);
}

static void __net_exit bpf_exit_net(struct list_head *net_list)
{
	tc_action_net_exit(net_list, bpf_net_id);
	tc_action_net_exit(net_list, act_bpf_ops.net_id);
}

static struct pernet_operations bpf_net_ops = {
	.init = bpf_init_net,
	.exit_batch = bpf_exit_net,
	.id   = &bpf_net_id,
	.id   = &act_bpf_ops.net_id,
	.size = sizeof(struct tc_action_net),
};

+4 −24
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_zones.h>

static unsigned int connmark_net_id;
static struct tc_action_ops act_connmark_ops;

static int tcf_connmark_act(struct sk_buff *skb, const struct tc_action *a,
@@ -99,7 +98,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
			     struct tcf_proto *tp, u32 flags,
			     struct netlink_ext_ack *extack)
{
	struct tc_action_net *tn = net_generic(net, connmark_net_id);
	struct tc_action_net *tn = net_generic(net, act_connmark_ops.net_id);
	struct nlattr *tb[TCA_CONNMARK_MAX + 1];
	bool bind = flags & TCA_ACT_FLAGS_BIND;
	struct tcf_chain *goto_ch = NULL;
@@ -200,23 +199,6 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
	return -1;
}

static int tcf_connmark_walker(struct net *net, struct sk_buff *skb,
			       struct netlink_callback *cb, int type,
			       const struct tc_action_ops *ops,
			       struct netlink_ext_ack *extack)
{
	struct tc_action_net *tn = net_generic(net, connmark_net_id);

	return tcf_generic_walker(tn, skb, cb, type, ops, extack);
}

static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 index)
{
	struct tc_action_net *tn = net_generic(net, connmark_net_id);

	return tcf_idr_search(tn, a, index);
}

static struct tc_action_ops act_connmark_ops = {
	.kind		=	"connmark",
	.id		=	TCA_ID_CONNMARK,
@@ -224,27 +206,25 @@ static struct tc_action_ops act_connmark_ops = {
	.act		=	tcf_connmark_act,
	.dump		=	tcf_connmark_dump,
	.init		=	tcf_connmark_init,
	.walk		=	tcf_connmark_walker,
	.lookup		=	tcf_connmark_search,
	.size		=	sizeof(struct tcf_connmark_info),
};

static __net_init int connmark_init_net(struct net *net)
{
	struct tc_action_net *tn = net_generic(net, connmark_net_id);
	struct tc_action_net *tn = net_generic(net, act_connmark_ops.net_id);

	return tc_action_net_init(net, tn, &act_connmark_ops);
}

static void __net_exit connmark_exit_net(struct list_head *net_list)
{
	tc_action_net_exit(net_list, connmark_net_id);
	tc_action_net_exit(net_list, act_connmark_ops.net_id);
}

static struct pernet_operations connmark_net_ops = {
	.init = connmark_init_net,
	.exit_batch = connmark_exit_net,
	.id   = &connmark_net_id,
	.id   = &act_connmark_ops.net_id,
	.size = sizeof(struct tc_action_net),
};

+4 −24
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = {
	[TCA_CSUM_PARMS] = { .len = sizeof(struct tc_csum), },
};

static unsigned int csum_net_id;
static struct tc_action_ops act_csum_ops;

static int tcf_csum_init(struct net *net, struct nlattr *nla,
@@ -45,7 +44,7 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
			 struct tcf_proto *tp,
			 u32 flags, struct netlink_ext_ack *extack)
{
	struct tc_action_net *tn = net_generic(net, csum_net_id);
	struct tc_action_net *tn = net_generic(net, act_csum_ops.net_id);
	bool bind = flags & TCA_ACT_FLAGS_BIND;
	struct tcf_csum_params *params_new;
	struct nlattr *tb[TCA_CSUM_MAX + 1];
@@ -673,23 +672,6 @@ static void tcf_csum_cleanup(struct tc_action *a)
		kfree_rcu(params, rcu);
}

static int tcf_csum_walker(struct net *net, struct sk_buff *skb,
			   struct netlink_callback *cb, int type,
			   const struct tc_action_ops *ops,
			   struct netlink_ext_ack *extack)
{
	struct tc_action_net *tn = net_generic(net, csum_net_id);

	return tcf_generic_walker(tn, skb, cb, type, ops, extack);
}

static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index)
{
	struct tc_action_net *tn = net_generic(net, csum_net_id);

	return tcf_idr_search(tn, a, index);
}

static size_t tcf_csum_get_fill_size(const struct tc_action *act)
{
	return nla_total_size(sizeof(struct tc_csum));
@@ -722,8 +704,6 @@ static struct tc_action_ops act_csum_ops = {
	.dump		= tcf_csum_dump,
	.init		= tcf_csum_init,
	.cleanup	= tcf_csum_cleanup,
	.walk		= tcf_csum_walker,
	.lookup		= tcf_csum_search,
	.get_fill_size  = tcf_csum_get_fill_size,
	.offload_act_setup = tcf_csum_offload_act_setup,
	.size		= sizeof(struct tcf_csum),
@@ -731,20 +711,20 @@ static struct tc_action_ops act_csum_ops = {

static __net_init int csum_init_net(struct net *net)
{
	struct tc_action_net *tn = net_generic(net, csum_net_id);
	struct tc_action_net *tn = net_generic(net, act_csum_ops.net_id);

	return tc_action_net_init(net, tn, &act_csum_ops);
}

static void __net_exit csum_exit_net(struct list_head *net_list)
{
	tc_action_net_exit(net_list, csum_net_id);
	tc_action_net_exit(net_list, act_csum_ops.net_id);
}

static struct pernet_operations csum_net_ops = {
	.init = csum_init_net,
	.exit_batch = csum_exit_net,
	.id   = &csum_net_id,
	.id   = &act_csum_ops.net_id,
	.size = sizeof(struct tc_action_net),
};

Loading