Commit e3822678 authored by Vlad Buslov's avatar Vlad Buslov Committed by David S. Miller

net: sched: update action implementations to support flags

Extend struct tc_action with new "tcfa_flags" field. Set the field in
tcf_idr_create() function and provide new helper
tcf_idr_create_from_flags() that derives 'cpustats' boolean from flags
value. Update individual hardware-offloaded actions init() to pass their
"flags" argument to new helper in order to skip percpu stats allocation
when user requested it through flags.
Signed-off-by: default avatarVlad Buslov <vladbu@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent abbb0d33
...@@ -41,6 +41,7 @@ struct tc_action { ...@@ -41,6 +41,7 @@ struct tc_action {
struct gnet_stats_queue __percpu *cpu_qstats; struct gnet_stats_queue __percpu *cpu_qstats;
struct tc_cookie __rcu *act_cookie; struct tc_cookie __rcu *act_cookie;
struct tcf_chain __rcu *goto_chain; struct tcf_chain __rcu *goto_chain;
u32 tcfa_flags;
}; };
#define tcf_index common.tcfa_index #define tcf_index common.tcfa_index
#define tcf_refcnt common.tcfa_refcnt #define tcf_refcnt common.tcfa_refcnt
...@@ -154,7 +155,11 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, ...@@ -154,7 +155,11 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index); int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index);
int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
struct tc_action **a, const struct tc_action_ops *ops, struct tc_action **a, const struct tc_action_ops *ops,
int bind, bool cpustats); int bind, bool cpustats, u32 flags);
int tcf_idr_create_from_flags(struct tc_action_net *tn, u32 index,
struct nlattr *est, struct tc_action **a,
const struct tc_action_ops *ops, int bind,
u32 flags);
void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a); void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a);
void tcf_idr_cleanup(struct tc_action_net *tn, u32 index); void tcf_idr_cleanup(struct tc_action_net *tn, u32 index);
......
...@@ -399,7 +399,7 @@ static int tcf_idr_delete_index(struct tcf_idrinfo *idrinfo, u32 index) ...@@ -399,7 +399,7 @@ static int tcf_idr_delete_index(struct tcf_idrinfo *idrinfo, u32 index)
int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
struct tc_action **a, const struct tc_action_ops *ops, struct tc_action **a, const struct tc_action_ops *ops,
int bind, bool cpustats) int bind, bool cpustats, u32 flags)
{ {
struct tc_action *p = kzalloc(ops->size, GFP_KERNEL); struct tc_action *p = kzalloc(ops->size, GFP_KERNEL);
struct tcf_idrinfo *idrinfo = tn->idrinfo; struct tcf_idrinfo *idrinfo = tn->idrinfo;
...@@ -427,6 +427,7 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, ...@@ -427,6 +427,7 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
p->tcfa_tm.install = jiffies; p->tcfa_tm.install = jiffies;
p->tcfa_tm.lastuse = jiffies; p->tcfa_tm.lastuse = jiffies;
p->tcfa_tm.firstuse = 0; p->tcfa_tm.firstuse = 0;
p->tcfa_flags = flags;
if (est) { if (est) {
err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats, err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats,
&p->tcfa_rate_est, &p->tcfa_rate_est,
...@@ -451,6 +452,17 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, ...@@ -451,6 +452,17 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
} }
EXPORT_SYMBOL(tcf_idr_create); EXPORT_SYMBOL(tcf_idr_create);
int tcf_idr_create_from_flags(struct tc_action_net *tn, u32 index,
struct nlattr *est, struct tc_action **a,
const struct tc_action_ops *ops, int bind,
u32 flags)
{
/* Set cpustats according to actions flags. */
return tcf_idr_create(tn, index, est, a, ops, bind,
!(flags & TCA_ACT_FLAGS_NO_PERCPU_STATS), flags);
}
EXPORT_SYMBOL(tcf_idr_create_from_flags);
void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a) void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a)
{ {
struct tcf_idrinfo *idrinfo = tn->idrinfo; struct tcf_idrinfo *idrinfo = tn->idrinfo;
...@@ -773,6 +785,14 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref) ...@@ -773,6 +785,14 @@ tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
} }
rcu_read_unlock(); rcu_read_unlock();
if (a->tcfa_flags) {
struct nla_bitfield32 flags = { a->tcfa_flags,
a->tcfa_flags, };
if (nla_put(skb, TCA_ACT_FLAGS, sizeof(flags), &flags))
goto nla_put_failure;
}
nest = nla_nest_start_noflag(skb, TCA_OPTIONS); nest = nla_nest_start_noflag(skb, TCA_OPTIONS);
if (nest == NULL) if (nest == NULL)
goto nla_put_failure; goto nla_put_failure;
......
...@@ -304,7 +304,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, ...@@ -304,7 +304,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
ret = tcf_idr_check_alloc(tn, &index, act, bind); ret = tcf_idr_check_alloc(tn, &index, act, bind);
if (!ret) { if (!ret) {
ret = tcf_idr_create(tn, index, est, act, ret = tcf_idr_create(tn, index, est, act,
&act_bpf_ops, bind, true); &act_bpf_ops, bind, true, 0);
if (ret < 0) { if (ret < 0) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return ret; return ret;
......
...@@ -121,7 +121,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, ...@@ -121,7 +121,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
ret = tcf_idr_check_alloc(tn, &index, a, bind); ret = tcf_idr_check_alloc(tn, &index, a, bind);
if (!ret) { if (!ret) {
ret = tcf_idr_create(tn, index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_connmark_ops, bind, false); &act_connmark_ops, bind, false, 0);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return ret; return ret;
......
...@@ -68,8 +68,8 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla, ...@@ -68,8 +68,8 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
index = parm->index; index = parm->index;
err = tcf_idr_check_alloc(tn, &index, a, bind); err = tcf_idr_check_alloc(tn, &index, a, bind);
if (!err) { if (!err) {
ret = tcf_idr_create(tn, index, est, a, ret = tcf_idr_create_from_flags(tn, index, est, a,
&act_csum_ops, bind, true); &act_csum_ops, bind, flags);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return ret; return ret;
......
...@@ -688,8 +688,8 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla, ...@@ -688,8 +688,8 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
return err; return err;
if (!err) { if (!err) {
err = tcf_idr_create(tn, index, est, a, err = tcf_idr_create_from_flags(tn, index, est, a,
&act_ct_ops, bind, true); &act_ct_ops, bind, flags);
if (err) { if (err) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return err; return err;
......
...@@ -210,7 +210,7 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla, ...@@ -210,7 +210,7 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
err = tcf_idr_check_alloc(tn, &index, a, bind); err = tcf_idr_check_alloc(tn, &index, a, bind);
if (!err) { if (!err) {
ret = tcf_idr_create(tn, index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_ctinfo_ops, bind, false); &act_ctinfo_ops, bind, false, 0);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return ret; return ret;
......
...@@ -99,8 +99,8 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, ...@@ -99,8 +99,8 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
err = tcf_idr_check_alloc(tn, &index, a, bind); err = tcf_idr_check_alloc(tn, &index, a, bind);
if (!err) { if (!err) {
ret = tcf_idr_create(tn, index, est, a, ret = tcf_idr_create_from_flags(tn, index, est, a,
&act_gact_ops, bind, true); &act_gact_ops, bind, flags);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return ret; return ret;
......
...@@ -523,7 +523,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, ...@@ -523,7 +523,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, index, est, a, &act_ife_ops, ret = tcf_idr_create(tn, index, est, a, &act_ife_ops,
bind, true); bind, true, 0);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
kfree(p); kfree(p);
......
...@@ -144,7 +144,7 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla, ...@@ -144,7 +144,7 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, index, est, a, ops, bind, ret = tcf_idr_create(tn, index, est, a, ops, bind,
false); false, 0);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return ret; return ret;
......
...@@ -148,8 +148,8 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, ...@@ -148,8 +148,8 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
NL_SET_ERR_MSG_MOD(extack, "Specified device does not exist"); NL_SET_ERR_MSG_MOD(extack, "Specified device does not exist");
return -EINVAL; return -EINVAL;
} }
ret = tcf_idr_create(tn, index, est, a, ret = tcf_idr_create_from_flags(tn, index, est, a,
&act_mirred_ops, bind, true); &act_mirred_ops, bind, flags);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return ret; return ret;
......
...@@ -225,7 +225,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla, ...@@ -225,7 +225,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_mpls_ops, bind, true); &act_mpls_ops, bind, true, 0);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return ret; return ret;
......
...@@ -61,7 +61,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, ...@@ -61,7 +61,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
err = tcf_idr_check_alloc(tn, &index, a, bind); err = tcf_idr_check_alloc(tn, &index, a, bind);
if (!err) { if (!err) {
ret = tcf_idr_create(tn, index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_nat_ops, bind, false); &act_nat_ops, bind, false, 0);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return ret; return ret;
......
...@@ -191,7 +191,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, ...@@ -191,7 +191,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
goto out_free; goto out_free;
} }
ret = tcf_idr_create(tn, index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_pedit_ops, bind, false); &act_pedit_ops, bind, false, 0);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
goto out_free; goto out_free;
......
...@@ -87,7 +87,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla, ...@@ -87,7 +87,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, index, NULL, a, ret = tcf_idr_create(tn, index, NULL, a,
&act_police_ops, bind, true); &act_police_ops, bind, true, 0);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return ret; return ret;
......
...@@ -69,7 +69,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, ...@@ -69,7 +69,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_sample_ops, bind, true); &act_sample_ops, bind, true, 0);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return ret; return ret;
......
...@@ -128,7 +128,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, ...@@ -128,7 +128,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_simp_ops, bind, false); &act_simp_ops, bind, false, 0);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return ret; return ret;
......
...@@ -165,7 +165,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, ...@@ -165,7 +165,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_skbedit_ops, bind, true); &act_skbedit_ops, bind, true, 0);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return ret; return ret;
......
...@@ -143,7 +143,7 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, ...@@ -143,7 +143,7 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, index, est, a, ret = tcf_idr_create(tn, index, est, a,
&act_skbmod_ops, bind, true); &act_skbmod_ops, bind, true, 0);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return ret; return ret;
......
...@@ -347,8 +347,9 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, ...@@ -347,8 +347,9 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
} }
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, index, est, a, ret = tcf_idr_create_from_flags(tn, index, est, a,
&act_tunnel_key_ops, bind, true); &act_tunnel_key_ops, bind,
act_flags);
if (ret) { if (ret) {
NL_SET_ERR_MSG(extack, "Cannot create TC IDR"); NL_SET_ERR_MSG(extack, "Cannot create TC IDR");
goto release_tun_meta; goto release_tun_meta;
......
...@@ -189,8 +189,8 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ...@@ -189,8 +189,8 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
action = parm->v_action; action = parm->v_action;
if (!exists) { if (!exists) {
ret = tcf_idr_create(tn, index, est, a, ret = tcf_idr_create_from_flags(tn, index, est, a,
&act_vlan_ops, bind, true); &act_vlan_ops, bind, flags);
if (ret) { if (ret) {
tcf_idr_cleanup(tn, index); tcf_idr_cleanup(tn, index);
return ret; return ret;
......
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