net: sched: update action implementations to support flags
authorVlad Buslov <vladbu@mellanox.com>
Wed, 30 Oct 2019 14:09:06 +0000 (16:09 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 31 Oct 2019 01:07:51 +0000 (18:07 -0700)
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: Vlad Buslov <vladbu@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
21 files changed:
include/net/act_api.h
net/sched/act_api.c
net/sched/act_bpf.c
net/sched/act_connmark.c
net/sched/act_csum.c
net/sched/act_ct.c
net/sched/act_ctinfo.c
net/sched/act_gact.c
net/sched/act_ife.c
net/sched/act_ipt.c
net/sched/act_mirred.c
net/sched/act_mpls.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_sample.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/act_skbmod.c
net/sched/act_tunnel_key.c
net/sched/act_vlan.c

index 85e95c44c7f9e008ce969d6020918ff2683c8209..0495bdc034d20d5c38ee3832ca3d2e637fdc5f38 100644 (file)
@@ -41,6 +41,7 @@ struct tc_action {
        struct gnet_stats_queue __percpu *cpu_qstats;
        struct tc_cookie        __rcu *act_cookie;
        struct tcf_chain        __rcu *goto_chain;
+       u32                     tcfa_flags;
 };
 #define tcf_index      common.tcfa_index
 #define tcf_refcnt     common.tcfa_refcnt
@@ -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_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
                   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_cleanup(struct tc_action_net *tn, u32 index);
index 92c00207d5a122f6184e833f4053856f1f24484c..6284c552e943d1ffa45d59a28eac2c37152e4875 100644 (file)
@@ -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,
                   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 tcf_idrinfo *idrinfo = tn->idrinfo;
@@ -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.lastuse = jiffies;
        p->tcfa_tm.firstuse = 0;
+       p->tcfa_flags = flags;
        if (est) {
                err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats,
                                        &p->tcfa_rate_est,
@@ -451,6 +452,17 @@ err1:
 }
 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)
 {
        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)
        }
        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);
        if (nest == NULL)
                goto nla_put_failure;
index 9e8cb43bc3fe581087fe5871c190cdd0b4fc5ef8..46f47e58b3bea0b13461408db42f75e31da34ebd 100644 (file)
@@ -304,7 +304,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
        ret = tcf_idr_check_alloc(tn, &index, act, bind);
        if (!ret) {
                ret = tcf_idr_create(tn, index, est, act,
-                                    &act_bpf_ops, bind, true);
+                                    &act_bpf_ops, bind, true, 0);
                if (ret < 0) {
                        tcf_idr_cleanup(tn, index);
                        return ret;
index 2e0ec6f80458499a4b1d7260f5477f71c84da28f..43a243081e7d2a86624d31029dae20957f78f11c 100644 (file)
@@ -121,7 +121,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
        ret = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!ret) {
                ret = tcf_idr_create(tn, index, est, a,
-                                    &act_connmark_ops, bind, false);
+                                    &act_connmark_ops, bind, false, 0);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        return ret;
index 66e54fada44c1f2c320e59e286d2aa6f2bb960c0..16e67e1c1db1981768bea8f2b8bef2451fd0c71f 100644 (file)
@@ -68,8 +68,8 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
        index = parm->index;
        err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!err) {
-               ret = tcf_idr_create(tn, index, est, a,
-                                    &act_csum_ops, bind, true);
+               ret = tcf_idr_create_from_flags(tn, index, est, a,
+                                               &act_csum_ops, bind, flags);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        return ret;
index 92ec0bdb0547ae00feae9950372f58c1026478c3..68d6af56b243f3475d1f1fc2c10afd74fe62ed4b 100644 (file)
@@ -688,8 +688,8 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,
                return err;
 
        if (!err) {
-               err = tcf_idr_create(tn, index, est, a,
-                                    &act_ct_ops, bind, true);
+               err = tcf_idr_create_from_flags(tn, index, est, a,
+                                               &act_ct_ops, bind, flags);
                if (err) {
                        tcf_idr_cleanup(tn, index);
                        return err;
index 2205b2a934cc954f8de9507c0b2da1353abb6a48..b1e6010072427b512750fc1b1da388c630f0ed31 100644 (file)
@@ -210,7 +210,7 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,
        err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!err) {
                ret = tcf_idr_create(tn, index, est, a,
-                                    &act_ctinfo_ops, bind, false);
+                                    &act_ctinfo_ops, bind, false, 0);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        return ret;
index c3dc89160f3ab1308e1c5dcef51dcb1bbb9758fe..41606577271968c7dd03ecd99f040bec63199297 100644 (file)
@@ -99,8 +99,8 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
 
        err = tcf_idr_check_alloc(tn, &index, a, bind);
        if (!err) {
-               ret = tcf_idr_create(tn, index, est, a,
-                                    &act_gact_ops, bind, true);
+               ret = tcf_idr_create_from_flags(tn, index, est, a,
+                                               &act_gact_ops, bind, flags);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        return ret;
index f38d2a5fd608884d21c816988da392aa853c6934..d562c88cccbe35dc9608ec3dd0787cf0ae539173 100644 (file)
@@ -523,7 +523,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
 
        if (!exists) {
                ret = tcf_idr_create(tn, index, est, a, &act_ife_ops,
-                                    bind, true);
+                                    bind, true, 0);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        kfree(p);
index fbab7078747790f54452004685bbcb507ad931f3..400a2cfe84522aea743b8a350f33129da6edca7a 100644 (file)
@@ -144,7 +144,7 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
 
        if (!exists) {
                ret = tcf_idr_create(tn, index, est, a, ops, bind,
-                                    false);
+                                    false, 0);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        return ret;
index 17ed19d6dff4f0588354fa8037629a97d76a54fe..b6e1b5bbb4da0c6316fdc4b936064342e7a857f9 100644 (file)
@@ -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");
                        return -EINVAL;
                }
-               ret = tcf_idr_create(tn, index, est, a,
-                                    &act_mirred_ops, bind, true);
+               ret = tcf_idr_create_from_flags(tn, index, est, a,
+                                               &act_mirred_ops, bind, flags);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        return ret;
index efd7fe07141b5ceafc88f0536ecb5b9f124e6e44..4d8c822b6acada80a81b4a4b9ccedb59aebfeaa0 100644 (file)
@@ -225,7 +225,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla,
 
        if (!exists) {
                ret = tcf_idr_create(tn, index, est, a,
-                                    &act_mpls_ops, bind, true);
+                                    &act_mpls_ops, bind, true, 0);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        return ret;
index 51d631cef92c5213116dc142aed925c55e3b3853..88a1b79a1848f84a057269c1f2765d2e96a7a36e 100644 (file)
@@ -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);
        if (!err) {
                ret = tcf_idr_create(tn, index, est, a,
-                                    &act_nat_ops, bind, false);
+                                    &act_nat_ops, bind, false, 0);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        return ret;
index adf1cbd6ae46e7cdf635d3a5409a2ea356b37f64..d5eff6ac17a91d25e90d8a38d4cabe64fe060591 100644 (file)
@@ -191,7 +191,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
                        goto out_free;
                }
                ret = tcf_idr_create(tn, index, est, a,
-                                    &act_pedit_ops, bind, false);
+                                    &act_pedit_ops, bind, false, 0);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        goto out_free;
index 7437b001f493027eaeeeb193a39543c18f16a62c..d96271590268403c19c66d62ad1a01336be2a6d8 100644 (file)
@@ -87,7 +87,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
 
        if (!exists) {
                ret = tcf_idr_create(tn, index, NULL, a,
-                                    &act_police_ops, bind, true);
+                                    &act_police_ops, bind, true, 0);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        return ret;
index 6f9a745c309595798468cbd5eea730389fad6cdd..29b23bfaf10ddc1f27dc6391997e0e63cd98152d 100644 (file)
@@ -69,7 +69,7 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla,
 
        if (!exists) {
                ret = tcf_idr_create(tn, index, est, a,
-                                    &act_sample_ops, bind, true);
+                                    &act_sample_ops, bind, true, 0);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        return ret;
index b18890f3eb6774edf03b0f8009653c9d7be8c155..97639b259cd7d1995727385bf8c69a4ee4737fca 100644 (file)
@@ -128,7 +128,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
 
        if (!exists) {
                ret = tcf_idr_create(tn, index, est, a,
-                                    &act_simp_ops, bind, false);
+                                    &act_simp_ops, bind, false, 0);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        return ret;
index 25f3b7b56beaf1ca81ddb1ca29a0a278bc8ae13e..5f7ca7f89ca2d393de6c6e59e4d49d59057cf2c1 100644 (file)
@@ -165,7 +165,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
 
        if (!exists) {
                ret = tcf_idr_create(tn, index, est, a,
-                                    &act_skbedit_ops, bind, true);
+                                    &act_skbedit_ops, bind, true, 0);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        return ret;
index 8e1dc0d6b4b0cc384f804f461ae29bed5e974ce0..39e6d94cfafbf7a199cb1a5fe2279fe59f37e1c4 100644 (file)
@@ -143,7 +143,7 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,
 
        if (!exists) {
                ret = tcf_idr_create(tn, index, est, a,
-                                    &act_skbmod_ops, bind, true);
+                                    &act_skbmod_ops, bind, true, 0);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        return ret;
index b25e5124f571b2207dfce77d6f598454678e3694..cb34e5d57aaa09692bad26023786cd30c60e3f2a 100644 (file)
@@ -347,8 +347,9 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
        }
 
        if (!exists) {
-               ret = tcf_idr_create(tn, index, est, a,
-                                    &act_tunnel_key_ops, bind, true);
+               ret = tcf_idr_create_from_flags(tn, index, est, a,
+                                               &act_tunnel_key_ops, bind,
+                                               act_flags);
                if (ret) {
                        NL_SET_ERR_MSG(extack, "Cannot create TC IDR");
                        goto release_tun_meta;
index 4b4000338a0974e9536b63131be13923b49d3880..b6939abc61ebef96e4eda5991854363125a30b16 100644 (file)
@@ -189,8 +189,8 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
        action = parm->v_action;
 
        if (!exists) {
-               ret = tcf_idr_create(tn, index, est, a,
-                                    &act_vlan_ops, bind, true);
+               ret = tcf_idr_create_from_flags(tn, index, est, a,
+                                               &act_vlan_ops, bind, flags);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        return ret;