Being able to get tc_action_net by using net_id stored in tc_action_ops and execute the generic walk/search function, add __tcf_generic_walker() and __tcf_idr_search() helpers. Signed-off-by: Zhengchao Shao <shaozhengchao@xxxxxxxxxx> --- include/net/act_api.h | 1 + net/sched/act_api.c | 48 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/include/net/act_api.h b/include/net/act_api.h index 9cf6870b526e..a79d6e58519e 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -113,6 +113,7 @@ struct tc_action_ops { enum tca_id id; /* identifier should match kind */ size_t size; struct module *owner; + unsigned int *net_id; int (*act)(struct sk_buff *, const struct tc_action *, struct tcf_result *); /* called under RCU BH lock*/ int (*dump)(struct sk_buff *, struct tc_action *, int, int); diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 817065aa2833..7063d2004199 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -676,6 +676,25 @@ 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); + + 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); + + 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 +945,8 @@ 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 || + (!act->net_id && (!act->walk || !act->lookup))) return -EINVAL; /* We have to register pernet ops before making the action ops visible, @@ -1638,9 +1658,16 @@ 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) { - NL_SET_ERR_MSG(extack, "TC action with specified index not found"); - goto err_mod; + if (ops->lookup) { + if (ops->lookup(net, &a, index) == 0) { + NL_SET_ERR_MSG(extack, "TC action with specified index not found"); + goto err_mod; + } + } else { + if (__tcf_idr_search(net, ops, &a, index) == 0) { + NL_SET_ERR_MSG(extack, "TC action with specified index not found"); + goto err_mod; + } } module_put(ops->owner); @@ -1703,7 +1730,12 @@ 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); + if (ops->walk) { + err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops, extack); + } else { + 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 +2153,11 @@ 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); + if (a_o->walk) + ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o, NULL); + else + ret = __tcf_generic_walker(net, skb, cb, RTM_GETACTION, a_o, NULL); + if (ret < 0) goto out_module_put; -- 2.17.1