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
 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);
 
 
 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;
        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,
 }
 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;
        }
        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;
 
        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;
 
        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 = 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;
 
                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;
 
        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;
 
 
        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;
 
 
        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);
 
 
        if (!exists) {
                ret = tcf_idr_create(tn, index, est, a, ops, bind,
-                                    false);
+                                    false, 0);
                if (ret) {
                        tcf_idr_cleanup(tn, index);
                        return ret;
 
                        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;
 
 
        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;
 
        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;
 
                        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;
 
 
        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;
 
 
        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;
 
 
        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;
 
 
        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;
 
 
        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;
 
        }
 
        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;
 
        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;