net_sched: move tc_action into tcf_common
authorWANG Cong <xiyou.wangcong@gmail.com>
Mon, 25 Jul 2016 23:09:41 +0000 (16:09 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 26 Jul 2016 04:49:19 +0000 (21:49 -0700)
struct tc_action is confusing, currently we use it for two purposes:
1) Pass in arguments and carry out results from helper functions
2) A generic representation for tc actions

The first one is error-prone, since we need to make sure we don't
miss anything. This patch aims to get rid of this use, by moving
tc_action into tcf_common, so that they are allocated together
in hashtable and can be cast'ed easily.

And together with the following patch, we could really make
tc_action a generic representation for all tc actions and each
type of action can inherit from it.

Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
27 files changed:
include/net/act_api.h
include/net/tc_act/tc_bpf.h
include/net/tc_act/tc_connmark.h
include/net/tc_act/tc_csum.h
include/net/tc_act/tc_defact.h
include/net/tc_act/tc_gact.h
include/net/tc_act/tc_ife.h
include/net/tc_act/tc_ipt.h
include/net/tc_act/tc_mirred.h
include/net/tc_act/tc_nat.h
include/net/tc_act/tc_pedit.h
include/net/tc_act/tc_skbedit.h
include/net/tc_act/tc_vlan.h
net/sched/act_api.c
net/sched/act_bpf.c
net/sched/act_connmark.c
net/sched/act_csum.c
net/sched/act_gact.c
net/sched/act_ife.c
net/sched/act_ipt.c
net/sched/act_mirred.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/act_vlan.c

index 0bb210635e5f23c1d5de74b8f8c200909f7c6911..8b199095ea513367263936fad77f82215e87d903 100644 (file)
 #include <net/net_namespace.h>
 #include <net/netns/generic.h>
 
+
+struct tcf_hashinfo {
+       struct hlist_head       *htab;
+       unsigned int            hmask;
+       spinlock_t              lock;
+       u32                     index;
+};
+
+struct tc_action_ops;
+
+struct tc_action {
+       const struct tc_action_ops      *ops;
+       __u32                   type; /* for backward compat(TCA_OLD_COMPAT) */
+       __u32                   order;
+       struct list_head        list;
+       struct tcf_hashinfo     *hinfo;
+};
+
 struct tcf_common {
+       struct tc_action                tcfc_act;
        struct hlist_node               tcfc_head;
        u32                             tcfc_index;
        int                             tcfc_refcnt;
@@ -26,6 +45,7 @@ struct tcf_common {
        struct gnet_stats_basic_cpu __percpu *cpu_bstats;
        struct gnet_stats_queue __percpu *cpu_qstats;
 };
+#define tcf_act                common.tcfc_act
 #define tcf_head       common.tcfc_head
 #define tcf_index      common.tcfc_index
 #define tcf_refcnt     common.tcfc_refcnt
@@ -39,13 +59,6 @@ struct tcf_common {
 #define tcf_lock       common.tcfc_lock
 #define tcf_rcu                common.tcfc_rcu
 
-struct tcf_hashinfo {
-       struct hlist_head       *htab;
-       unsigned int            hmask;
-       spinlock_t              lock;
-       u32                     index;
-};
-
 static inline unsigned int tcf_hash(u32 index, unsigned int hmask)
 {
        return index & hmask;
@@ -88,15 +101,6 @@ static inline void tcf_tm_dump(struct tcf_t *dtm, const struct tcf_t *stm)
        dtm->expires = jiffies_to_clock_t(stm->expires);
 }
 
-struct tc_action {
-       void                    *priv;
-       const struct tc_action_ops      *ops;
-       __u32                   type; /* for backward compat(TCA_OLD_COMPAT) */
-       __u32                   order;
-       struct list_head        list;
-       struct tcf_hashinfo     *hinfo;
-};
-
 #ifdef CONFIG_NET_CLS_ACT
 
 #define ACT_P_CREATED 1
@@ -106,17 +110,18 @@ struct tc_action_ops {
        struct list_head head;
        char    kind[IFNAMSIZ];
        __u32   type; /* TBD to match kind */
+       size_t  size;
        struct module           *owner;
        int     (*act)(struct sk_buff *, const struct tc_action *,
                       struct tcf_result *);
        int     (*dump)(struct sk_buff *, struct tc_action *, int, int);
        void    (*cleanup)(struct tc_action *, int bind);
-       int     (*lookup)(struct net *, struct tc_action *, u32);
+       int     (*lookup)(struct net *, struct tc_action **, u32);
        int     (*init)(struct net *net, struct nlattr *nla,
-                       struct nlattr *est, struct tc_action *act, int ovr,
+                       struct nlattr *est, struct tc_action **act, int ovr,
                        int bind);
        int     (*walk)(struct net *, struct sk_buff *,
-                       struct netlink_callback *, int, struct tc_action *);
+                       struct netlink_callback *, int, const struct tc_action_ops *);
        void    (*stats_update)(struct tc_action *, u64, u32, u64);
 };
 
@@ -152,13 +157,14 @@ static inline void tc_action_net_exit(struct tc_action_net *tn)
 
 int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
                       struct netlink_callback *cb, int type,
-                      struct tc_action *a);
-int tcf_hash_search(struct tc_action_net *tn, struct tc_action *a, u32 index);
+                      const struct tc_action_ops *ops);
+int tcf_hash_search(struct tc_action_net *tn, struct tc_action **a, u32 index);
 u32 tcf_hash_new_index(struct tc_action_net *tn);
-bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a,
+bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
                    int bind);
 int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
-                   struct tc_action *a, int size, int bind, bool cpustats);
+                   struct tc_action **a, const struct tc_action_ops *ops, int bind,
+                   bool cpustats);
 void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est);
 void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a);
 
index 958d69cfb19cc1fa5fed2f3fd64b5a2432f978b6..80a4d6f4977352948caa6b60b348e6d3430978bd 100644 (file)
@@ -23,7 +23,6 @@ struct tcf_bpf {
        struct sock_filter      *bpf_ops;
        const char              *bpf_name;
 };
-#define to_bpf(a) \
-       container_of(a->priv, struct tcf_bpf, common)
+#define to_bpf(a) ((struct tcf_bpf *)a)
 
 #endif /* __NET_TC_BPF_H */
index 02caa406611b496e6e830c9fb85b467c55875732..8a661135f4acd0ecdb0dcf6463e99277c12d5919 100644 (file)
@@ -9,7 +9,6 @@ struct tcf_connmark_info {
        u16 zone;
 };
 
-#define to_connmark(a) \
-       container_of(a->priv, struct tcf_connmark_info, common)
+#define to_connmark(a) ((struct tcf_connmark_info *)a)
 
 #endif /* __NET_TC_CONNMARK_H */
index fa8f5fac65e959bff4458cd3e7cce6005bd08533..1a9ef15d573bb5a99869b9b85c036527fe399a8c 100644 (file)
@@ -9,7 +9,6 @@ struct tcf_csum {
 
        u32 update_flags;
 };
-#define to_tcf_csum(a) \
-       container_of(a->priv,struct tcf_csum,common)
+#define to_tcf_csum(a) ((struct tcf_csum *)a)
 
 #endif /* __NET_TC_CSUM_H */
index ab9b5d6be67b8ff446a8deb647c46e984a4e18c0..e25b4eb4fc66d64da0e4883eea09d96c72787050 100644 (file)
@@ -8,7 +8,6 @@ struct tcf_defact {
        u32             tcfd_datalen;
        void            *tcfd_defdata;
 };
-#define to_defact(a) \
-       container_of(a->priv, struct tcf_defact, common)
+#define to_defact(a) ((struct tcf_defact *)a)
 
 #endif /* __NET_TC_DEF_H */
index 93c520b83d10994236c09be729dcd55dcff6dc2b..119cdb418c23152eaba1e90afba095de4fb92d8b 100644 (file)
@@ -13,8 +13,7 @@ struct tcf_gact {
        atomic_t                packets;
 #endif
 };
-#define to_gact(a) \
-       container_of(a->priv, struct tcf_gact, common)
+#define to_gact(a) ((struct tcf_gact *)a)
 
 static inline bool is_tcf_gact_shot(const struct tc_action *a)
 {
@@ -24,7 +23,7 @@ static inline bool is_tcf_gact_shot(const struct tc_action *a)
        if (a->ops && a->ops->type != TCA_ACT_GACT)
                return false;
 
-       gact = a->priv;
+       gact = to_gact(a);
        if (gact->tcf_action == TC_ACT_SHOT)
                return true;
 
index c55facd17b7ec0b4c38ecf7e3690118056a93567..7921abe42adcae03d9cd268e3dc2bbb6b8c52384 100644 (file)
@@ -16,8 +16,7 @@ struct tcf_ife_info {
        /* list of metaids allowed */
        struct list_head metalist;
 };
-#define to_ife(a) \
-       container_of(a->priv, struct tcf_ife_info, common)
+#define to_ife(a) ((struct tcf_ife_info *)a)
 
 struct tcf_meta_info {
        const struct tcf_meta_ops *ops;
index c0f4193f432c20d67234c6198ce7c6cb0a4933ac..c22ae7ab66ed90f0dbdb3d70941ebb77f9a9202c 100644 (file)
@@ -11,7 +11,6 @@ struct tcf_ipt {
        char                    *tcfi_tname;
        struct xt_entry_target  *tcfi_t;
 };
-#define to_ipt(a) \
-       container_of(a->priv, struct tcf_ipt, common)
+#define to_ipt(a) ((struct tcf_ipt *)a)
 
 #endif /* __NET_TC_IPT_H */
index 6a13a7c74e0c28cebc8fcd5d9021cd9d638cf65a..89aebd22cd79e4c8f3b76af4b2632e105e9f2e1d 100644 (file)
@@ -12,8 +12,7 @@ struct tcf_mirred {
        struct net_device __rcu *tcfm_dev;
        struct list_head        tcfm_list;
 };
-#define to_mirred(a) \
-       container_of(a->priv, struct tcf_mirred, common)
+#define to_mirred(a) ((struct tcf_mirred *)a)
 
 static inline bool is_tcf_mirred_redirect(const struct tc_action *a)
 {
index 63d8e9ca9d99e0bef223973a48d24229689de27e..a91ad3ad565e5b49e8e7a2b45e1b56ae0aa0cfa9 100644 (file)
@@ -13,9 +13,6 @@ struct tcf_nat {
        u32 flags;
 };
 
-static inline struct tcf_nat *to_tcf_nat(struct tc_action *a)
-{
-       return container_of(a->priv, struct tcf_nat, common);
-}
+#define to_tcf_nat(a) ((struct tcf_nat *)a)
 
 #endif /* __NET_TC_NAT_H */
index 5b80998879c7cf6c0bf7df280556de05b5831260..2cccfbaae8004c0f5bbf78640ba4de3f508a1b60 100644 (file)
@@ -9,7 +9,6 @@ struct tcf_pedit {
        unsigned char           tcfp_flags;
        struct tc_pedit_key     *tcfp_keys;
 };
-#define to_pedit(a) \
-       container_of(a->priv, struct tcf_pedit, common)
+#define to_pedit(a) ((struct tcf_pedit *)a)
 
 #endif /* __NET_TC_PED_H */
index d01a5d40cfb5704fabb028301f7b61710dcd7215..9e054899832770dc32524290123d7817b9f3ea66 100644 (file)
@@ -30,8 +30,7 @@ struct tcf_skbedit {
        u16             queue_mapping;
        u16             ptype;
 };
-#define to_skbedit(a) \
-       container_of(a->priv, struct tcf_skbedit, common)
+#define to_skbedit(a) ((struct tcf_skbedit *)a)
 
 /* Return true iff action is mark */
 static inline bool is_tcf_skbedit_mark(const struct tc_action *a)
index 93b70ade1ff3fb9a66ec1178d652fe3083cd338c..584b80788d52dff114e1f3e6599c849932506050 100644 (file)
@@ -21,7 +21,6 @@ struct tcf_vlan {
        u16                     tcfv_push_vid;
        __be16                  tcfv_push_proto;
 };
-#define to_vlan(a) \
-       container_of(a->priv, struct tcf_vlan, common)
+#define to_vlan(a) ((struct tcf_vlan *)a)
 
 #endif /* __NET_TC_VLAN_H */
index 47ec2305f920cb00eb26138875019b3a220d7c3c..d97419f35e7ea867993f63516f730c3dec5c93f6 100644 (file)
@@ -38,7 +38,7 @@ static void free_tcf(struct rcu_head *head)
 
 static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *a)
 {
-       struct tcf_common *p = a->priv;
+       struct tcf_common *p = (struct tcf_common *)a;
 
        spin_lock_bh(&hinfo->lock);
        hlist_del(&p->tcfc_head);
@@ -54,7 +54,7 @@ static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *a)
 
 int __tcf_hash_release(struct tc_action *a, bool bind, bool strict)
 {
-       struct tcf_common *p = a->priv;
+       struct tcf_common *p = (struct tcf_common *)a;
        int ret = 0;
 
        if (p) {
@@ -67,6 +67,7 @@ int __tcf_hash_release(struct tc_action *a, bool bind, bool strict)
                if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) {
                        if (a->ops->cleanup)
                                a->ops->cleanup(a, bind);
+                       list_del(&a->list);
                        tcf_hash_destroy(a->hinfo, a);
                        ret = ACT_P_DELETED;
                }
@@ -77,10 +78,8 @@ int __tcf_hash_release(struct tc_action *a, bool bind, bool strict)
 EXPORT_SYMBOL(__tcf_hash_release);
 
 static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
-                          struct netlink_callback *cb, struct tc_action *a)
+                          struct netlink_callback *cb)
 {
-       struct hlist_head *head;
-       struct tcf_common *p;
        int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
        struct nlattr *nest;
 
@@ -89,19 +88,20 @@ static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
        s_i = cb->args[0];
 
        for (i = 0; i < (hinfo->hmask + 1); i++) {
+               struct hlist_head *head;
+               struct tcf_common *p;
+
                head = &hinfo->htab[tcf_hash(i, hinfo->hmask)];
 
                hlist_for_each_entry_rcu(p, head, tcfc_head) {
                        index++;
                        if (index < s_i)
                                continue;
-                       a->priv = p;
-                       a->order = n_i;
 
-                       nest = nla_nest_start(skb, a->order);
+                       nest = nla_nest_start(skb, n_i);
                        if (nest == NULL)
                                goto nla_put_failure;
-                       err = tcf_action_dump_1(skb, a, 0, 0);
+                       err = tcf_action_dump_1(skb, (struct tc_action *)p, 0, 0);
                        if (err < 0) {
                                index--;
                                nlmsg_trim(skb, nest);
@@ -125,27 +125,27 @@ nla_put_failure:
 }
 
 static int tcf_del_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
-                         struct tc_action *a)
+                         const struct tc_action_ops *ops)
 {
-       struct hlist_head *head;
-       struct hlist_node *n;
-       struct tcf_common *p;
        struct nlattr *nest;
        int i = 0, n_i = 0;
        int ret = -EINVAL;
 
-       nest = nla_nest_start(skb, a->order);
+       nest = nla_nest_start(skb, 0);
        if (nest == NULL)
                goto nla_put_failure;
-       if (nla_put_string(skb, TCA_KIND, a->ops->kind))
+       if (nla_put_string(skb, TCA_KIND, ops->kind))
                goto nla_put_failure;
        for (i = 0; i < (hinfo->hmask + 1); i++) {
+               struct hlist_head *head;
+               struct hlist_node *n;
+               struct tcf_common *p;
+
                head = &hinfo->htab[tcf_hash(i, hinfo->hmask)];
                hlist_for_each_entry_safe(p, n, head, tcfc_head) {
-                       a->priv = p;
-                       ret = __tcf_hash_release(a, false, true);
+                       ret = __tcf_hash_release((struct tc_action *)p, false, true);
                        if (ret == ACT_P_DELETED) {
-                               module_put(a->ops->owner);
+                               module_put(p->tcfc_act.ops->owner);
                                n_i++;
                        } else if (ret < 0)
                                goto nla_put_failure;
@@ -163,16 +163,14 @@ nla_put_failure:
 
 int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
                       struct netlink_callback *cb, int type,
-                      struct tc_action *a)
+                      const struct tc_action_ops *ops)
 {
        struct tcf_hashinfo *hinfo = tn->hinfo;
 
-       a->hinfo = hinfo;
-
        if (type == RTM_DELACTION) {
-               return tcf_del_walker(hinfo, skb, a);
+               return tcf_del_walker(hinfo, skb, ops);
        } else if (type == RTM_GETACTION) {
-               return tcf_dump_walker(hinfo, skb, cb, a);
+               return tcf_dump_walker(hinfo, skb, cb);
        } else {
                WARN(1, "tcf_generic_walker: unknown action %d\n", type);
                return -EINVAL;
@@ -210,21 +208,20 @@ u32 tcf_hash_new_index(struct tc_action_net *tn)
 }
 EXPORT_SYMBOL(tcf_hash_new_index);
 
-int tcf_hash_search(struct tc_action_net *tn, struct tc_action *a, u32 index)
+int tcf_hash_search(struct tc_action_net *tn, struct tc_action **a, u32 index)
 {
        struct tcf_hashinfo *hinfo = tn->hinfo;
        struct tcf_common *p = tcf_hash_lookup(index, hinfo);
 
        if (p) {
-               a->priv = p;
-               a->hinfo = hinfo;
+               *a = &p->tcfc_act;
                return 1;
        }
        return 0;
 }
 EXPORT_SYMBOL(tcf_hash_search);
 
-bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a,
+bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
                    int bind)
 {
        struct tcf_hashinfo *hinfo = tn->hinfo;
@@ -233,8 +230,7 @@ bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a,
                if (bind)
                        p->tcfc_bindcnt++;
                p->tcfc_refcnt++;
-               a->priv = p;
-               a->hinfo = hinfo;
+               *a = &p->tcfc_act;
                return true;
        }
        return false;
@@ -243,7 +239,7 @@ EXPORT_SYMBOL(tcf_hash_check);
 
 void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est)
 {
-       struct tcf_common *pc = a->priv;
+       struct tcf_common *pc = (struct tcf_common *)a;
        if (est)
                gen_kill_estimator(&pc->tcfc_bstats,
                                   &pc->tcfc_rate_est);
@@ -252,9 +248,10 @@ void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est)
 EXPORT_SYMBOL(tcf_hash_cleanup);
 
 int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
-                   struct tc_action *a, int size, int bind, bool cpustats)
+                   struct tc_action **a, const struct tc_action_ops *ops,
+                   int bind, bool cpustats)
 {
-       struct tcf_common *p = kzalloc(size, GFP_KERNEL);
+       struct tcf_common *p = kzalloc(ops->size, GFP_KERNEL);
        struct tcf_hashinfo *hinfo = tn->hinfo;
        int err = -ENOMEM;
 
@@ -294,15 +291,17 @@ err2:
                }
        }
 
-       a->priv = (void *) p;
-       a->hinfo = hinfo;
+       p->tcfc_act.hinfo = hinfo;
+       p->tcfc_act.ops = ops;
+       INIT_LIST_HEAD(&p->tcfc_act.list);
+       *a = &p->tcfc_act;
        return 0;
 }
 EXPORT_SYMBOL(tcf_hash_create);
 
 void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a)
 {
-       struct tcf_common *p = a->priv;
+       struct tcf_common *p = (struct tcf_common *)a;
        struct tcf_hashinfo *hinfo = tn->hinfo;
        unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask);
 
@@ -315,10 +314,6 @@ EXPORT_SYMBOL(tcf_hash_insert);
 void tcf_hashinfo_destroy(const struct tc_action_ops *ops,
                          struct tcf_hashinfo *hinfo)
 {
-       struct tc_action a = {
-               .ops = ops,
-               .hinfo = hinfo,
-       };
        int i;
 
        for (i = 0; i < hinfo->hmask + 1; i++) {
@@ -328,8 +323,7 @@ void tcf_hashinfo_destroy(const struct tc_action_ops *ops,
                hlist_for_each_entry_safe(p, n, &hinfo->htab[i], tcfc_head) {
                        int ret;
 
-                       a.priv = p;
-                       ret = __tcf_hash_release(&a, false, true);
+                       ret = __tcf_hash_release((struct tc_action *)p, false, true);
                        if (ret == ACT_P_DELETED)
                                module_put(ops->owner);
                        else if (ret < 0)
@@ -466,8 +460,6 @@ int tcf_action_destroy(struct list_head *actions, int bind)
                        module_put(a->ops->owner);
                else if (ret < 0)
                        return ret;
-               list_del(&a->list);
-               kfree(a);
        }
        return ret;
 }
@@ -581,20 +573,13 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
                goto err_out;
        }
 
-       err = -ENOMEM;
-       a = kzalloc(sizeof(*a), GFP_KERNEL);
-       if (a == NULL)
-               goto err_mod;
-
-       a->ops = a_o;
-       INIT_LIST_HEAD(&a->list);
        /* backward compatibility for policer */
        if (name == NULL)
-               err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, a, ovr, bind);
+               err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind);
        else
-               err = a_o->init(net, nla, est, a, ovr, bind);
+               err = a_o->init(net, nla, est, &a, ovr, bind);
        if (err < 0)
-               goto err_free;
+               goto err_mod;
 
        /* module count goes up only when brand new policy is created
         * if it exists and is only bound to in a_o->init() then
@@ -605,8 +590,6 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
 
        return a;
 
-err_free:
-       kfree(a);
 err_mod:
        module_put(a_o->owner);
 err_out:
@@ -647,7 +630,7 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a,
 {
        int err = 0;
        struct gnet_dump d;
-       struct tcf_common *p = a->priv;
+       struct tcf_common *p = (struct tcf_common *)a;
 
        if (p == NULL)
                goto errout;
@@ -740,24 +723,11 @@ act_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
        return rtnl_unicast(skb, net, portid);
 }
 
-static struct tc_action *create_a(int i)
-{
-       struct tc_action *act;
-
-       act = kzalloc(sizeof(*act), GFP_KERNEL);
-       if (act == NULL) {
-               pr_debug("create_a: failed to alloc!\n");
-               return NULL;
-       }
-       act->order = i;
-       INIT_LIST_HEAD(&act->list);
-       return act;
-}
-
 static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
                                          struct nlmsghdr *n, u32 portid)
 {
        struct nlattr *tb[TCA_ACT_MAX + 1];
+       const struct tc_action_ops *ops;
        struct tc_action *a;
        int index;
        int err;
@@ -772,26 +742,19 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
                goto err_out;
        index = nla_get_u32(tb[TCA_ACT_INDEX]);
 
-       err = -ENOMEM;
-       a = create_a(0);
-       if (a == NULL)
-               goto err_out;
-
        err = -EINVAL;
-       a->ops = tc_lookup_action(tb[TCA_ACT_KIND]);
-       if (a->ops == NULL) /* could happen in batch of actions */
-               goto err_free;
+       ops = tc_lookup_action(tb[TCA_ACT_KIND]);
+       if (!ops) /* could happen in batch of actions */
+               goto err_out;
        err = -ENOENT;
-       if (a->ops->lookup(net, a, index) == 0)
+       if (ops->lookup(net, &a, index) == 0)
                goto err_mod;
 
-       module_put(a->ops->owner);
+       module_put(ops->owner);
        return a;
 
 err_mod:
-       module_put(a->ops->owner);
-err_free:
-       kfree(a);
+       module_put(ops->owner);
 err_out:
        return ERR_PTR(err);
 }
@@ -816,8 +779,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
        struct netlink_callback dcb;
        struct nlattr *nest;
        struct nlattr *tb[TCA_ACT_MAX + 1];
+       const struct tc_action_ops *ops;
        struct nlattr *kind;
-       struct tc_action a;
        int err = -ENOMEM;
 
        skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
@@ -834,10 +797,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
 
        err = -EINVAL;
        kind = tb[TCA_ACT_KIND];
-       memset(&a, 0, sizeof(struct tc_action));
-       INIT_LIST_HEAD(&a.list);
-       a.ops = tc_lookup_action(kind);
-       if (a.ops == NULL) /*some idjot trying to flush unknown action */
+       ops = tc_lookup_action(kind);
+       if (!ops) /*some idjot trying to flush unknown action */
                goto err_out;
 
        nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION,
@@ -853,7 +814,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
        if (nest == NULL)
                goto out_module_put;
 
-       err = a.ops->walk(net, skb, &dcb, RTM_DELACTION, &a);
+       err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops);
        if (err < 0)
                goto out_module_put;
        if (err == 0)
@@ -863,7 +824,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
 
        nlh->nlmsg_len = skb_tail_pointer(skb) - b;
        nlh->nlmsg_flags |= NLM_F_ROOT;
-       module_put(a.ops->owner);
+       module_put(ops->owner);
        err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
                             n->nlmsg_flags & NLM_F_ECHO);
        if (err > 0)
@@ -872,7 +833,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
        return err;
 
 out_module_put:
-       module_put(a.ops->owner);
+       module_put(ops->owner);
 err_out:
 noflush_out:
        kfree_skb(skb);
@@ -1084,7 +1045,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
        unsigned char *b = skb_tail_pointer(skb);
        struct nlattr *nest;
        struct tc_action_ops *a_o;
-       struct tc_action a;
        int ret = 0;
        struct tcamsg *t = (struct tcamsg *) nlmsg_data(cb->nlh);
        struct nlattr *kind = find_dump_kind(cb->nlh);
@@ -1098,9 +1058,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
        if (a_o == NULL)
                return 0;
 
-       memset(&a, 0, sizeof(struct tc_action));
-       a.ops = a_o;
-
        nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
                        cb->nlh->nlmsg_type, sizeof(*t), 0);
        if (!nlh)
@@ -1114,7 +1071,7 @@ 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);
+       ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o);
        if (ret < 0)
                goto out_module_put;
 
index ef74bffa610128eb8f55fe9a6ad277cc623a2129..bfa870731e74db7010ec8fe780e36ec3a3cb6eb6 100644 (file)
@@ -34,11 +34,12 @@ struct tcf_bpf_cfg {
 };
 
 static int bpf_net_id;
+static struct tc_action_ops act_bpf_ops;
 
 static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act,
                   struct tcf_result *res)
 {
-       struct tcf_bpf *prog = act->priv;
+       struct tcf_bpf *prog = to_bpf(act);
        struct bpf_prog *filter;
        int action, filter_res;
        bool at_ingress = G_TC_AT(skb->tc_verd) & AT_INGRESS;
@@ -134,7 +135,7 @@ static int tcf_bpf_dump(struct sk_buff *skb, struct tc_action *act,
                        int bind, int ref)
 {
        unsigned char *tp = skb_tail_pointer(skb);
-       struct tcf_bpf *prog = act->priv;
+       struct tcf_bpf *prog = to_bpf(act);
        struct tc_act_bpf opt = {
                .index   = prog->tcf_index,
                .refcnt  = prog->tcf_refcnt - ref,
@@ -270,7 +271,7 @@ static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf *prog,
 }
 
 static int tcf_bpf_init(struct net *net, struct nlattr *nla,
-                       struct nlattr *est, struct tc_action *act,
+                       struct nlattr *est, struct tc_action **act,
                        int replace, int bind)
 {
        struct tc_action_net *tn = net_generic(net, bpf_net_id);
@@ -295,7 +296,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
 
        if (!tcf_hash_check(tn, parm->index, act, bind)) {
                ret = tcf_hash_create(tn, parm->index, est, act,
-                                     sizeof(*prog), bind, true);
+                                     &act_bpf_ops, bind, true);
                if (ret < 0)
                        return ret;
 
@@ -305,7 +306,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
                if (bind)
                        return 0;
 
-               tcf_hash_release(act, bind);
+               tcf_hash_release(*act, bind);
                if (!replace)
                        return -EEXIST;
        }
@@ -325,7 +326,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
        if (ret < 0)
                goto out;
 
-       prog = to_bpf(act);
+       prog = to_bpf(*act);
        ASSERT_RTNL();
 
        if (res != ACT_P_CREATED)
@@ -343,7 +344,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
        rcu_assign_pointer(prog->filter, cfg.filter);
 
        if (res == ACT_P_CREATED) {
-               tcf_hash_insert(tn, act);
+               tcf_hash_insert(tn, *act);
        } else {
                /* make sure the program being replaced is no longer executing */
                synchronize_rcu();
@@ -353,7 +354,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
        return res;
 out:
        if (res == ACT_P_CREATED)
-               tcf_hash_cleanup(act, est);
+               tcf_hash_cleanup(*act, est);
 
        return ret;
 }
@@ -362,20 +363,20 @@ static void tcf_bpf_cleanup(struct tc_action *act, int bind)
 {
        struct tcf_bpf_cfg tmp;
 
-       tcf_bpf_prog_fill_cfg(act->priv, &tmp);
+       tcf_bpf_prog_fill_cfg(to_bpf(act), &tmp);
        tcf_bpf_cfg_cleanup(&tmp);
 }
 
 static int tcf_bpf_walker(struct net *net, struct sk_buff *skb,
                          struct netlink_callback *cb, int type,
-                         struct tc_action *a)
+                         const struct tc_action_ops *ops)
 {
        struct tc_action_net *tn = net_generic(net, bpf_net_id);
 
-       return tcf_generic_walker(tn, skb, cb, type, a);
+       return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_bpf_search(struct net *net, struct tc_action *a, u32 index)
+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);
 
@@ -392,6 +393,7 @@ static struct tc_action_ops act_bpf_ops __read_mostly = {
        .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)
index 35a5270f289d69c2674f40f94e57556e78d650b2..eae07a2e774d81ecfbbe444ae0f33385b6adb7a0 100644 (file)
@@ -31,6 +31,7 @@
 #define CONNMARK_TAB_MASK     3
 
 static int connmark_net_id;
+static struct tc_action_ops act_connmark_ops;
 
 static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a,
                        struct tcf_result *res)
@@ -38,7 +39,7 @@ static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a,
        const struct nf_conntrack_tuple_hash *thash;
        struct nf_conntrack_tuple tuple;
        enum ip_conntrack_info ctinfo;
-       struct tcf_connmark_info *ca = a->priv;
+       struct tcf_connmark_info *ca = to_connmark(a);
        struct nf_conntrack_zone zone;
        struct nf_conn *c;
        int proto;
@@ -96,7 +97,7 @@ static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = {
 };
 
 static int tcf_connmark_init(struct net *net, struct nlattr *nla,
-                            struct nlattr *est, struct tc_action *a,
+                            struct nlattr *est, struct tc_action **a,
                             int ovr, int bind)
 {
        struct tc_action_net *tn = net_generic(net, connmark_net_id);
@@ -116,22 +117,22 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
 
        if (!tcf_hash_check(tn, parm->index, a, bind)) {
                ret = tcf_hash_create(tn, parm->index, est, a,
-                                     sizeof(*ci), bind, false);
+                                     &act_connmark_ops, bind, false);
                if (ret)
                        return ret;
 
-               ci = to_connmark(a);
+               ci = to_connmark(*a);
                ci->tcf_action = parm->action;
                ci->net = net;
                ci->zone = parm->zone;
 
-               tcf_hash_insert(tn, a);
+               tcf_hash_insert(tn, *a);
                ret = ACT_P_CREATED;
        } else {
-               ci = to_connmark(a);
+               ci = to_connmark(*a);
                if (bind)
                        return 0;
-               tcf_hash_release(a, bind);
+               tcf_hash_release(*a, bind);
                if (!ovr)
                        return -EEXIST;
                /* replacing action and zone */
@@ -146,7 +147,7 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
                                    int bind, int ref)
 {
        unsigned char *b = skb_tail_pointer(skb);
-       struct tcf_connmark_info *ci = a->priv;
+       struct tcf_connmark_info *ci = to_connmark(a);
 
        struct tc_connmark opt = {
                .index   = ci->tcf_index,
@@ -173,14 +174,14 @@ nla_put_failure:
 
 static int tcf_connmark_walker(struct net *net, struct sk_buff *skb,
                               struct netlink_callback *cb, int type,
-                              struct tc_action *a)
+                              const struct tc_action_ops *ops)
 {
        struct tc_action_net *tn = net_generic(net, connmark_net_id);
 
-       return tcf_generic_walker(tn, skb, cb, type, a);
+       return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_connmark_search(struct net *net, struct tc_action *a, u32 index)
+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);
 
@@ -196,6 +197,7 @@ static struct tc_action_ops act_connmark_ops = {
        .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)
index dcd9ababd35162120162a6358e4e8c2c6d68d3ae..b5dbf633a86367a293bcb28f6921159398087fe0 100644 (file)
@@ -43,9 +43,10 @@ static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = {
 };
 
 static int csum_net_id;
+static struct tc_action_ops act_csum_ops;
 
 static int tcf_csum_init(struct net *net, struct nlattr *nla,
-                        struct nlattr *est, struct tc_action *a, int ovr,
+                        struct nlattr *est, struct tc_action **a, int ovr,
                         int bind)
 {
        struct tc_action_net *tn = net_generic(net, csum_net_id);
@@ -67,26 +68,26 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
 
        if (!tcf_hash_check(tn, parm->index, a, bind)) {
                ret = tcf_hash_create(tn, parm->index, est, a,
-                                     sizeof(*p), bind, false);
+                                     &act_csum_ops, bind, false);
                if (ret)
                        return ret;
                ret = ACT_P_CREATED;
        } else {
                if (bind)/* dont override defaults */
                        return 0;
-               tcf_hash_release(a, bind);
+               tcf_hash_release(*a, bind);
                if (!ovr)
                        return -EEXIST;
        }
 
-       p = to_tcf_csum(a);
+       p = to_tcf_csum(*a);
        spin_lock_bh(&p->tcf_lock);
        p->tcf_action = parm->action;
        p->update_flags = parm->update_flags;
        spin_unlock_bh(&p->tcf_lock);
 
        if (ret == ACT_P_CREATED)
-               tcf_hash_insert(tn, a);
+               tcf_hash_insert(tn, *a);
 
        return ret;
 }
@@ -496,7 +497,7 @@ fail:
 static int tcf_csum(struct sk_buff *skb,
                    const struct tc_action *a, struct tcf_result *res)
 {
-       struct tcf_csum *p = a->priv;
+       struct tcf_csum *p = to_tcf_csum(a);
        int action;
        u32 update_flags;
 
@@ -534,7 +535,7 @@ static int tcf_csum_dump(struct sk_buff *skb,
                         struct tc_action *a, int bind, int ref)
 {
        unsigned char *b = skb_tail_pointer(skb);
-       struct tcf_csum *p = a->priv;
+       struct tcf_csum *p = to_tcf_csum(a);
        struct tc_csum opt = {
                .update_flags = p->update_flags,
                .index   = p->tcf_index,
@@ -560,14 +561,14 @@ nla_put_failure:
 
 static int tcf_csum_walker(struct net *net, struct sk_buff *skb,
                           struct netlink_callback *cb, int type,
-                          struct tc_action *a)
+                          const struct tc_action_ops *ops)
 {
        struct tc_action_net *tn = net_generic(net, csum_net_id);
 
-       return tcf_generic_walker(tn, skb, cb, type, a);
+       return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_csum_search(struct net *net, struct tc_action *a, u32 index)
+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);
 
@@ -583,6 +584,7 @@ static struct tc_action_ops act_csum_ops = {
        .init           = tcf_csum_init,
        .walk           = tcf_csum_walker,
        .lookup         = tcf_csum_search,
+       .size           = sizeof(struct tcf_csum),
 };
 
 static __net_init int csum_init_net(struct net *net)
index 19058a7f3e5c7ae7d5c99acae498d335ed60ddf2..e24a4093d6f68146c84c9930621e43d44797317b 100644 (file)
@@ -26,6 +26,7 @@
 #define GACT_TAB_MASK  15
 
 static int gact_net_id;
+static struct tc_action_ops act_gact_ops;
 
 #ifdef CONFIG_GACT_PROB
 static int gact_net_rand(struct tcf_gact *gact)
@@ -56,7 +57,7 @@ static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = {
 };
 
 static int tcf_gact_init(struct net *net, struct nlattr *nla,
-                        struct nlattr *est, struct tc_action *a,
+                        struct nlattr *est, struct tc_action **a,
                         int ovr, int bind)
 {
        struct tc_action_net *tn = net_generic(net, gact_net_id);
@@ -93,19 +94,19 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
 
        if (!tcf_hash_check(tn, parm->index, a, bind)) {
                ret = tcf_hash_create(tn, parm->index, est, a,
-                                     sizeof(*gact), bind, true);
+                                     &act_gact_ops, bind, true);
                if (ret)
                        return ret;
                ret = ACT_P_CREATED;
        } else {
                if (bind)/* dont override defaults */
                        return 0;
-               tcf_hash_release(a, bind);
+               tcf_hash_release(*a, bind);
                if (!ovr)
                        return -EEXIST;
        }
 
-       gact = to_gact(a);
+       gact = to_gact(*a);
 
        ASSERT_RTNL();
        gact->tcf_action = parm->action;
@@ -121,14 +122,14 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
        }
 #endif
        if (ret == ACT_P_CREATED)
-               tcf_hash_insert(tn, a);
+               tcf_hash_insert(tn, *a);
        return ret;
 }
 
 static int tcf_gact(struct sk_buff *skb, const struct tc_action *a,
                    struct tcf_result *res)
 {
-       struct tcf_gact *gact = a->priv;
+       struct tcf_gact *gact = to_gact(a);
        int action = READ_ONCE(gact->tcf_action);
 
 #ifdef CONFIG_GACT_PROB
@@ -151,7 +152,7 @@ static int tcf_gact(struct sk_buff *skb, const struct tc_action *a,
 static void tcf_gact_stats_update(struct tc_action *a, u64 bytes, u32 packets,
                                  u64 lastuse)
 {
-       struct tcf_gact *gact = a->priv;
+       struct tcf_gact *gact = to_gact(a);
        int action = READ_ONCE(gact->tcf_action);
        struct tcf_t *tm = &gact->tcf_tm;
 
@@ -166,7 +167,7 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a,
                         int bind, int ref)
 {
        unsigned char *b = skb_tail_pointer(skb);
-       struct tcf_gact *gact = a->priv;
+       struct tcf_gact *gact = to_gact(a);
        struct tc_gact opt = {
                .index   = gact->tcf_index,
                .refcnt  = gact->tcf_refcnt - ref,
@@ -201,14 +202,14 @@ nla_put_failure:
 
 static int tcf_gact_walker(struct net *net, struct sk_buff *skb,
                           struct netlink_callback *cb, int type,
-                          struct tc_action *a)
+                          const struct tc_action_ops *ops)
 {
        struct tc_action_net *tn = net_generic(net, gact_net_id);
 
-       return tcf_generic_walker(tn, skb, cb, type, a);
+       return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_gact_search(struct net *net, struct tc_action *a, u32 index)
+static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index)
 {
        struct tc_action_net *tn = net_generic(net, gact_net_id);
 
@@ -225,6 +226,7 @@ static struct tc_action_ops act_gact_ops = {
        .init           =       tcf_gact_init,
        .walk           =       tcf_gact_walker,
        .lookup         =       tcf_gact_search,
+       .size           =       sizeof(struct tcf_gact),
 };
 
 static __net_init int gact_init_net(struct net *net)
index 845ab5119c05a19947a05f13b888b3a31c18ccbd..141a06eeb1e502ec8273de1897302cef11c07e0c 100644 (file)
@@ -37,6 +37,7 @@
 
 static int ife_net_id;
 static int max_metacnt = IFE_META_MAX + 1;
+static struct tc_action_ops act_ife_ops;
 
 static const struct nla_policy ife_policy[TCA_IFE_MAX + 1] = {
        [TCA_IFE_PARMS] = { .len = sizeof(struct tc_ife)},
@@ -364,7 +365,7 @@ out_nlmsg_trim:
 /* under ife->tcf_lock */
 static void _tcf_ife_cleanup(struct tc_action *a, int bind)
 {
-       struct tcf_ife_info *ife = a->priv;
+       struct tcf_ife_info *ife = to_ife(a);
        struct tcf_meta_info *e, *n;
 
        list_for_each_entry_safe(e, n, &ife->metalist, metalist) {
@@ -382,7 +383,7 @@ static void _tcf_ife_cleanup(struct tc_action *a, int bind)
 
 static void tcf_ife_cleanup(struct tc_action *a, int bind)
 {
-       struct tcf_ife_info *ife = a->priv;
+       struct tcf_ife_info *ife = to_ife(a);
 
        spin_lock_bh(&ife->tcf_lock);
        _tcf_ife_cleanup(a, bind);
@@ -417,7 +418,7 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb,
 }
 
 static int tcf_ife_init(struct net *net, struct nlattr *nla,
-                       struct nlattr *est, struct tc_action *a,
+                       struct nlattr *est, struct tc_action **a,
                        int ovr, int bind)
 {
        struct tc_action_net *tn = net_generic(net, ife_net_id);
@@ -451,25 +452,25 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
                **/
                if (!tb[TCA_IFE_TYPE]) {
                        if (exists)
-                               tcf_hash_release(a, bind);
+                               tcf_hash_release(*a, bind);
                        pr_info("You MUST pass etherype for encoding\n");
                        return -EINVAL;
                }
        }
 
        if (!exists) {
-               ret = tcf_hash_create(tn, parm->index, est, a, sizeof(*ife),
+               ret = tcf_hash_create(tn, parm->index, est, a, &act_ife_ops,
                                      bind, false);
                if (ret)
                        return ret;
                ret = ACT_P_CREATED;
        } else {
-               tcf_hash_release(a, bind);
+               tcf_hash_release(*a, bind);
                if (!ovr)
                        return -EEXIST;
        }
 
-       ife = to_ife(a);
+       ife = to_ife(*a);
        ife->flags = parm->flags;
 
        if (parm->flags & IFE_ENCODE) {
@@ -507,9 +508,9 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
                if (err) {
 metadata_parse_err:
                        if (exists)
-                               tcf_hash_release(a, bind);
+                               tcf_hash_release(*a, bind);
                        if (ret == ACT_P_CREATED)
-                               _tcf_ife_cleanup(a, bind);
+                               _tcf_ife_cleanup(*a, bind);
 
                        if (exists)
                                spin_unlock_bh(&ife->tcf_lock);
@@ -529,7 +530,7 @@ metadata_parse_err:
                err = use_all_metadata(ife);
                if (err) {
                        if (ret == ACT_P_CREATED)
-                               _tcf_ife_cleanup(a, bind);
+                               _tcf_ife_cleanup(*a, bind);
 
                        if (exists)
                                spin_unlock_bh(&ife->tcf_lock);
@@ -541,7 +542,7 @@ metadata_parse_err:
                spin_unlock_bh(&ife->tcf_lock);
 
        if (ret == ACT_P_CREATED)
-               tcf_hash_insert(tn, a);
+               tcf_hash_insert(tn, *a);
 
        return ret;
 }
@@ -550,7 +551,7 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind,
                        int ref)
 {
        unsigned char *b = skb_tail_pointer(skb);
-       struct tcf_ife_info *ife = a->priv;
+       struct tcf_ife_info *ife = to_ife(a);
        struct tc_ife opt = {
                .index = ife->tcf_index,
                .refcnt = ife->tcf_refcnt - ref,
@@ -623,7 +624,7 @@ struct meta_tlvhdr {
 static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a,
                          struct tcf_result *res)
 {
-       struct tcf_ife_info *ife = a->priv;
+       struct tcf_ife_info *ife = to_ife(a);
        int action = ife->tcf_action;
        struct ifeheadr *ifehdr = (struct ifeheadr *)skb->data;
        u16 ifehdrln = ifehdr->metalen;
@@ -695,7 +696,7 @@ static int ife_get_sz(struct sk_buff *skb, struct tcf_ife_info *ife)
 static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a,
                          struct tcf_result *res)
 {
-       struct tcf_ife_info *ife = a->priv;
+       struct tcf_ife_info *ife = to_ife(a);
        int action = ife->tcf_action;
        struct ethhdr *oethh;   /* outer ether header */
        struct ethhdr *iethh;   /* inner eth header */
@@ -799,7 +800,7 @@ static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a,
 static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a,
                       struct tcf_result *res)
 {
-       struct tcf_ife_info *ife = a->priv;
+       struct tcf_ife_info *ife = to_ife(a);
 
        if (ife->flags & IFE_ENCODE)
                return tcf_ife_encode(skb, a, res);
@@ -819,14 +820,14 @@ static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a,
 
 static int tcf_ife_walker(struct net *net, struct sk_buff *skb,
                          struct netlink_callback *cb, int type,
-                         struct tc_action *a)
+                         const struct tc_action_ops *ops)
 {
        struct tc_action_net *tn = net_generic(net, ife_net_id);
 
-       return tcf_generic_walker(tn, skb, cb, type, a);
+       return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_ife_search(struct net *net, struct tc_action *a, u32 index)
+static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index)
 {
        struct tc_action_net *tn = net_generic(net, ife_net_id);
 
@@ -843,6 +844,7 @@ static struct tc_action_ops act_ife_ops = {
        .init = tcf_ife_init,
        .walk = tcf_ife_walker,
        .lookup = tcf_ife_search,
+       .size = sizeof(struct tcf_ife_info),
 };
 
 static __net_init int ife_init_net(struct net *net)
index b8c50600697a8b49112c0198d8c2cc6d6ccb0246..378c1c9760583818e8ea93a3e24d13bd007b0c3d 100644 (file)
 #define IPT_TAB_MASK     15
 
 static int ipt_net_id;
+static struct tc_action_ops act_ipt_ops;
 
 static int xt_net_id;
+static struct tc_action_ops act_xt_ops;
 
 static int ipt_init_target(struct xt_entry_target *t, char *table,
                           unsigned int hook)
@@ -90,8 +92,8 @@ static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = {
 };
 
 static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
-                         struct nlattr *est, struct tc_action *a, int ovr,
-                         int bind)
+                         struct nlattr *est, struct tc_action **a,
+                         const struct tc_action_ops *ops, int ovr, int bind)
 {
        struct nlattr *tb[TCA_IPT_MAX + 1];
        struct tcf_ipt *ipt;
@@ -118,19 +120,19 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
 
        if (tb[TCA_IPT_HOOK] == NULL || tb[TCA_IPT_TARG] == NULL) {
                if (exists)
-                       tcf_hash_release(a, bind);
+                       tcf_hash_release(*a, bind);
                return -EINVAL;
        }
 
        td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]);
        if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) {
                if (exists)
-                       tcf_hash_release(a, bind);
+                       tcf_hash_release(*a, bind);
                return -EINVAL;
        }
 
        if (!exists) {
-               ret = tcf_hash_create(tn, index, est, a, sizeof(*ipt), bind,
+               ret = tcf_hash_create(tn, index, est, a, ops, bind,
                                      false);
                if (ret)
                        return ret;
@@ -138,13 +140,11 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
        } else {
                if (bind)/* dont override defaults */
                        return 0;
-               tcf_hash_release(a, bind);
+               tcf_hash_release(*a, bind);
 
                if (!ovr)
                        return -EEXIST;
        }
-       ipt = to_ipt(a);
-
        hook = nla_get_u32(tb[TCA_IPT_HOOK]);
 
        err = -ENOMEM;
@@ -163,6 +163,8 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
        if (err < 0)
                goto err3;
 
+       ipt = to_ipt(*a);
+
        spin_lock_bh(&ipt->tcf_lock);
        if (ret != ACT_P_CREATED) {
                ipt_destroy_target(ipt->tcfi_t);
@@ -174,7 +176,7 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
        ipt->tcfi_hook  = hook;
        spin_unlock_bh(&ipt->tcf_lock);
        if (ret == ACT_P_CREATED)
-               tcf_hash_insert(tn, a);
+               tcf_hash_insert(tn, *a);
        return ret;
 
 err3:
@@ -183,33 +185,33 @@ err2:
        kfree(tname);
 err1:
        if (ret == ACT_P_CREATED)
-               tcf_hash_cleanup(a, est);
+               tcf_hash_cleanup(*a, est);
        return err;
 }
 
 static int tcf_ipt_init(struct net *net, struct nlattr *nla,
-                       struct nlattr *est, struct tc_action *a, int ovr,
+                       struct nlattr *est, struct tc_action **a, int ovr,
                        int bind)
 {
        struct tc_action_net *tn = net_generic(net, ipt_net_id);
 
-       return __tcf_ipt_init(tn, nla, est, a, ovr, bind);
+       return __tcf_ipt_init(tn, nla, est, a, &act_ipt_ops, ovr, bind);
 }
 
 static int tcf_xt_init(struct net *net, struct nlattr *nla,
-                      struct nlattr *est, struct tc_action *a, int ovr,
+                      struct nlattr *est, struct tc_action **a, int ovr,
                       int bind)
 {
        struct tc_action_net *tn = net_generic(net, xt_net_id);
 
-       return __tcf_ipt_init(tn, nla, est, a, ovr, bind);
+       return __tcf_ipt_init(tn, nla, est, a, &act_xt_ops, ovr, bind);
 }
 
 static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a,
                   struct tcf_result *res)
 {
        int ret = 0, result = 0;
-       struct tcf_ipt *ipt = a->priv;
+       struct tcf_ipt *ipt = to_ipt(a);
        struct xt_action_param par;
 
        if (skb_unclone(skb, GFP_ATOMIC))
@@ -259,7 +261,7 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind,
                        int ref)
 {
        unsigned char *b = skb_tail_pointer(skb);
-       struct tcf_ipt *ipt = a->priv;
+       struct tcf_ipt *ipt = to_ipt(a);
        struct xt_entry_target *t;
        struct tcf_t tm;
        struct tc_cnt c;
@@ -299,14 +301,14 @@ nla_put_failure:
 
 static int tcf_ipt_walker(struct net *net, struct sk_buff *skb,
                          struct netlink_callback *cb, int type,
-                         struct tc_action *a)
+                         const struct tc_action_ops *ops)
 {
        struct tc_action_net *tn = net_generic(net, ipt_net_id);
 
-       return tcf_generic_walker(tn, skb, cb, type, a);
+       return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_ipt_search(struct net *net, struct tc_action *a, u32 index)
+static int tcf_ipt_search(struct net *net, struct tc_action **a, u32 index)
 {
        struct tc_action_net *tn = net_generic(net, ipt_net_id);
 
@@ -323,6 +325,7 @@ static struct tc_action_ops act_ipt_ops = {
        .init           =       tcf_ipt_init,
        .walk           =       tcf_ipt_walker,
        .lookup         =       tcf_ipt_search,
+       .size           =       sizeof(struct tcf_ipt),
 };
 
 static __net_init int ipt_init_net(struct net *net)
@@ -348,14 +351,14 @@ static struct pernet_operations ipt_net_ops = {
 
 static int tcf_xt_walker(struct net *net, struct sk_buff *skb,
                         struct netlink_callback *cb, int type,
-                        struct tc_action *a)
+                        const struct tc_action_ops *ops)
 {
        struct tc_action_net *tn = net_generic(net, xt_net_id);
 
-       return tcf_generic_walker(tn, skb, cb, type, a);
+       return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_xt_search(struct net *net, struct tc_action *a, u32 index)
+static int tcf_xt_search(struct net *net, struct tc_action **a, u32 index)
 {
        struct tc_action_net *tn = net_generic(net, xt_net_id);
 
@@ -372,6 +375,7 @@ static struct tc_action_ops act_xt_ops = {
        .init           =       tcf_xt_init,
        .walk           =       tcf_xt_walker,
        .lookup         =       tcf_xt_search,
+       .size           =       sizeof(struct tcf_ipt),
 };
 
 static __net_init int xt_init_net(struct net *net)
index 70cfbbf96af263d1d22683eff35bd005b55c6aeb..6038c85d92f565c845d29ef94bdd42b50027389b 100644 (file)
@@ -52,9 +52,10 @@ static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
 };
 
 static int mirred_net_id;
+static struct tc_action_ops act_mirred_ops;
 
 static int tcf_mirred_init(struct net *net, struct nlattr *nla,
-                          struct nlattr *est, struct tc_action *a, int ovr,
+                          struct nlattr *est, struct tc_action **a, int ovr,
                           int bind)
 {
        struct tc_action_net *tn = net_generic(net, mirred_net_id);
@@ -84,14 +85,14 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
                break;
        default:
                if (exists)
-                       tcf_hash_release(a, bind);
+                       tcf_hash_release(*a, bind);
                return -EINVAL;
        }
        if (parm->ifindex) {
                dev = __dev_get_by_index(net, parm->ifindex);
                if (dev == NULL) {
                        if (exists)
-                               tcf_hash_release(a, bind);
+                               tcf_hash_release(*a, bind);
                        return -ENODEV;
                }
                switch (dev->type) {
@@ -115,16 +116,16 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
                if (dev == NULL)
                        return -EINVAL;
                ret = tcf_hash_create(tn, parm->index, est, a,
-                                     sizeof(*m), bind, true);
+                                     &act_mirred_ops, bind, true);
                if (ret)
                        return ret;
                ret = ACT_P_CREATED;
        } else {
-               tcf_hash_release(a, bind);
+               tcf_hash_release(*a, bind);
                if (!ovr)
                        return -EEXIST;
        }
-       m = to_mirred(a);
+       m = to_mirred(*a);
 
        ASSERT_RTNL();
        m->tcf_action = parm->action;
@@ -142,7 +143,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
                spin_lock_bh(&mirred_list_lock);
                list_add(&m->tcfm_list, &mirred_list);
                spin_unlock_bh(&mirred_list_lock);
-               tcf_hash_insert(tn, a);
+               tcf_hash_insert(tn, *a);
        }
 
        return ret;
@@ -151,7 +152,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
 static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
                      struct tcf_result *res)
 {
-       struct tcf_mirred *m = a->priv;
+       struct tcf_mirred *m = to_mirred(a);
        struct net_device *dev;
        struct sk_buff *skb2;
        int retval, err;
@@ -206,7 +207,7 @@ out:
 static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
 {
        unsigned char *b = skb_tail_pointer(skb);
-       struct tcf_mirred *m = a->priv;
+       struct tcf_mirred *m = to_mirred(a);
        struct tc_mirred opt = {
                .index   = m->tcf_index,
                .action  = m->tcf_action,
@@ -232,14 +233,14 @@ nla_put_failure:
 
 static int tcf_mirred_walker(struct net *net, struct sk_buff *skb,
                             struct netlink_callback *cb, int type,
-                            struct tc_action *a)
+                            const struct tc_action_ops *ops)
 {
        struct tc_action_net *tn = net_generic(net, mirred_net_id);
 
-       return tcf_generic_walker(tn, skb, cb, type, a);
+       return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_mirred_search(struct net *net, struct tc_action *a, u32 index)
+static int tcf_mirred_search(struct net *net, struct tc_action **a, u32 index)
 {
        struct tc_action_net *tn = net_generic(net, mirred_net_id);
 
@@ -284,6 +285,7 @@ static struct tc_action_ops act_mirred_ops = {
        .init           =       tcf_mirred_init,
        .walk           =       tcf_mirred_walker,
        .lookup         =       tcf_mirred_search,
+       .size           =       sizeof(struct tcf_mirred),
 };
 
 static __net_init int mirred_init_net(struct net *net)
index 06ccb03f25da5a92c3c1ad8105fa55111eb92a8d..8e8b0cc30704e7bbf69975932d4678f2e8caf9a1 100644 (file)
 #define NAT_TAB_MASK   15
 
 static int nat_net_id;
+static struct tc_action_ops act_nat_ops;
 
 static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
        [TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) },
 };
 
 static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
-                       struct tc_action *a, int ovr, int bind)
+                       struct tc_action **a, int ovr, int bind)
 {
        struct tc_action_net *tn = net_generic(net, nat_net_id);
        struct nlattr *tb[TCA_NAT_MAX + 1];
@@ -59,18 +60,18 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
 
        if (!tcf_hash_check(tn, parm->index, a, bind)) {
                ret = tcf_hash_create(tn, parm->index, est, a,
-                                     sizeof(*p), bind, false);
+                                     &act_nat_ops, bind, false);
                if (ret)
                        return ret;
                ret = ACT_P_CREATED;
        } else {
                if (bind)
                        return 0;
-               tcf_hash_release(a, bind);
+               tcf_hash_release(*a, bind);
                if (!ovr)
                        return -EEXIST;
        }
-       p = to_tcf_nat(a);
+       p = to_tcf_nat(*a);
 
        spin_lock_bh(&p->tcf_lock);
        p->old_addr = parm->old_addr;
@@ -82,7 +83,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
        spin_unlock_bh(&p->tcf_lock);
 
        if (ret == ACT_P_CREATED)
-               tcf_hash_insert(tn, a);
+               tcf_hash_insert(tn, *a);
 
        return ret;
 }
@@ -90,7 +91,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
 static int tcf_nat(struct sk_buff *skb, const struct tc_action *a,
                   struct tcf_result *res)
 {
-       struct tcf_nat *p = a->priv;
+       struct tcf_nat *p = to_tcf_nat(a);
        struct iphdr *iph;
        __be32 old_addr;
        __be32 new_addr;
@@ -248,7 +249,7 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a,
                        int bind, int ref)
 {
        unsigned char *b = skb_tail_pointer(skb);
-       struct tcf_nat *p = a->priv;
+       struct tcf_nat *p = to_tcf_nat(a);
        struct tc_nat opt = {
                .old_addr = p->old_addr,
                .new_addr = p->new_addr,
@@ -278,14 +279,14 @@ nla_put_failure:
 
 static int tcf_nat_walker(struct net *net, struct sk_buff *skb,
                          struct netlink_callback *cb, int type,
-                         struct tc_action *a)
+                         const struct tc_action_ops *ops)
 {
        struct tc_action_net *tn = net_generic(net, nat_net_id);
 
-       return tcf_generic_walker(tn, skb, cb, type, a);
+       return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_nat_search(struct net *net, struct tc_action *a, u32 index)
+static int tcf_nat_search(struct net *net, struct tc_action **a, u32 index)
 {
        struct tc_action_net *tn = net_generic(net, nat_net_id);
 
@@ -301,6 +302,7 @@ static struct tc_action_ops act_nat_ops = {
        .init           =       tcf_nat_init,
        .walk           =       tcf_nat_walker,
        .lookup         =       tcf_nat_search,
+       .size           =       sizeof(struct tcf_nat),
 };
 
 static __net_init int nat_init_net(struct net *net)
index 82d3c147902903efd28f315a65b5014e5a15fe66..b54d56d4959b6381d35799ba84f64ea634384cce 100644 (file)
 #define PEDIT_TAB_MASK 15
 
 static int pedit_net_id;
+static struct tc_action_ops act_pedit_ops;
 
 static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = {
        [TCA_PEDIT_PARMS]       = { .len = sizeof(struct tc_pedit) },
 };
 
 static int tcf_pedit_init(struct net *net, struct nlattr *nla,
-                         struct nlattr *est, struct tc_action *a,
+                         struct nlattr *est, struct tc_action **a,
                          int ovr, int bind)
 {
        struct tc_action_net *tn = net_generic(net, pedit_net_id);
@@ -61,23 +62,23 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
                if (!parm->nkeys)
                        return -EINVAL;
                ret = tcf_hash_create(tn, parm->index, est, a,
-                                     sizeof(*p), bind, false);
+                                     &act_pedit_ops, bind, false);
                if (ret)
                        return ret;
-               p = to_pedit(a);
+               p = to_pedit(*a);
                keys = kmalloc(ksize, GFP_KERNEL);
                if (keys == NULL) {
-                       tcf_hash_cleanup(a, est);
+                       tcf_hash_cleanup(*a, est);
                        return -ENOMEM;
                }
                ret = ACT_P_CREATED;
        } else {
                if (bind)
                        return 0;
-               tcf_hash_release(a, bind);
+               tcf_hash_release(*a, bind);
                if (!ovr)
                        return -EEXIST;
-               p = to_pedit(a);
+               p = to_pedit(*a);
                if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) {
                        keys = kmalloc(ksize, GFP_KERNEL);
                        if (keys == NULL)
@@ -96,13 +97,13 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
        memcpy(p->tcfp_keys, parm->keys, ksize);
        spin_unlock_bh(&p->tcf_lock);
        if (ret == ACT_P_CREATED)
-               tcf_hash_insert(tn, a);
+               tcf_hash_insert(tn, *a);
        return ret;
 }
 
 static void tcf_pedit_cleanup(struct tc_action *a, int bind)
 {
-       struct tcf_pedit *p = a->priv;
+       struct tcf_pedit *p = to_pedit(a);
        struct tc_pedit_key *keys = p->tcfp_keys;
        kfree(keys);
 }
@@ -110,7 +111,7 @@ static void tcf_pedit_cleanup(struct tc_action *a, int bind)
 static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a,
                     struct tcf_result *res)
 {
-       struct tcf_pedit *p = a->priv;
+       struct tcf_pedit *p = to_pedit(a);
        int i;
        unsigned int off;
 
@@ -177,7 +178,7 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
                          int bind, int ref)
 {
        unsigned char *b = skb_tail_pointer(skb);
-       struct tcf_pedit *p = a->priv;
+       struct tcf_pedit *p = to_pedit(a);
        struct tc_pedit *opt;
        struct tcf_t t;
        int s;
@@ -216,14 +217,14 @@ nla_put_failure:
 
 static int tcf_pedit_walker(struct net *net, struct sk_buff *skb,
                            struct netlink_callback *cb, int type,
-                           struct tc_action *a)
+                           const struct tc_action_ops *ops)
 {
        struct tc_action_net *tn = net_generic(net, pedit_net_id);
 
-       return tcf_generic_walker(tn, skb, cb, type, a);
+       return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_pedit_search(struct net *net, struct tc_action *a, u32 index)
+static int tcf_pedit_search(struct net *net, struct tc_action **a, u32 index)
 {
        struct tc_action_net *tn = net_generic(net, pedit_net_id);
 
@@ -240,6 +241,7 @@ static struct tc_action_ops act_pedit_ops = {
        .init           =       tcf_pedit_init,
        .walk           =       tcf_pedit_walker,
        .lookup         =       tcf_pedit_search,
+       .size           =       sizeof(struct tcf_pedit),
 };
 
 static __net_init int pedit_init_net(struct net *net)
index 1e8ede3955f4e0381516b4694fe49cd35c8c41b8..123794af55c3cc2f766ab5758ecebde23c3c1683 100644 (file)
@@ -37,8 +37,8 @@ struct tcf_police {
        struct psched_ratecfg   peak;
        bool                    peak_present;
 };
-#define to_police(pc)  \
-       container_of(pc->priv, struct tcf_police, common)
+
+#define to_police(pc) ((struct tcf_police *)pc)
 
 #define POL_TAB_MASK     15
 
@@ -56,15 +56,14 @@ struct tc_police_compat {
 /* Each policer is serialized by its individual spinlock */
 
 static int police_net_id;
+static struct tc_action_ops act_police_ops;
 
 static int tcf_act_police_walker(struct net *net, struct sk_buff *skb,
                                 struct netlink_callback *cb, int type,
-                                struct tc_action *a)
+                                const struct tc_action_ops *ops)
 {
        struct tc_action_net *tn = net_generic(net, police_net_id);
        struct tcf_hashinfo *hinfo = tn->hinfo;
-       struct hlist_head *head;
-       struct tcf_common *p;
        int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
        struct nlattr *nest;
 
@@ -73,21 +72,22 @@ static int tcf_act_police_walker(struct net *net, struct sk_buff *skb,
        s_i = cb->args[0];
 
        for (i = 0; i < (POL_TAB_MASK + 1); i++) {
+               struct hlist_head *head;
+               struct tcf_common *p;
+
                head = &hinfo->htab[tcf_hash(i, POL_TAB_MASK)];
 
                hlist_for_each_entry_rcu(p, head, tcfc_head) {
                        index++;
                        if (index < s_i)
                                continue;
-                       a->priv = p;
-                       a->order = index;
-                       nest = nla_nest_start(skb, a->order);
+                       nest = nla_nest_start(skb, index);
                        if (nest == NULL)
                                goto nla_put_failure;
                        if (type == RTM_DELACTION)
-                               err = tcf_action_dump_1(skb, a, 0, 1);
+                               err = tcf_action_dump_1(skb, (struct tc_action *)p, 0, 1);
                        else
-                               err = tcf_action_dump_1(skb, a, 0, 0);
+                               err = tcf_action_dump_1(skb, (struct tc_action *)p, 0, 0);
                        if (err < 0) {
                                index--;
                                nla_nest_cancel(skb, nest);
@@ -116,7 +116,7 @@ static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
 };
 
 static int tcf_act_police_init(struct net *net, struct nlattr *nla,
-                              struct nlattr *est, struct tc_action *a,
+                              struct nlattr *est, struct tc_action **a,
                               int ovr, int bind)
 {
        int ret = 0, err;
@@ -142,13 +142,7 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
        parm = nla_data(tb[TCA_POLICE_TBF]);
 
        if (parm->index) {
-               if (tcf_hash_search(tn, a, parm->index)) {
-                       police = to_police(a);
-                       if (bind) {
-                               police->tcf_bindcnt += 1;
-                               police->tcf_refcnt += 1;
-                               return 0;
-                       }
+               if (tcf_hash_check(tn, parm->index, a, bind)) {
                        if (ovr)
                                goto override;
                        /* not replacing */
@@ -156,14 +150,14 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
                }
        } else {
                ret = tcf_hash_create(tn, parm->index, NULL, a,
-                                     sizeof(*police), bind, false);
+                                     &act_police_ops, bind, false);
                if (ret)
                        return ret;
                ret = ACT_P_CREATED;
        }
 
-       police = to_police(a);
 override:
+       police = to_police(*a);
        if (parm->rate.rate) {
                err = -ENOMEM;
                R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]);
@@ -235,7 +229,7 @@ override:
                return ret;
 
        police->tcfp_t_c = ktime_get_ns();
-       tcf_hash_insert(tn, a);
+       tcf_hash_insert(tn, *a);
 
        return ret;
 
@@ -245,14 +239,14 @@ failure:
        qdisc_put_rtab(P_tab);
        qdisc_put_rtab(R_tab);
        if (ret == ACT_P_CREATED)
-               tcf_hash_cleanup(a, est);
+               tcf_hash_cleanup(*a, est);
        return err;
 }
 
 static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a,
                          struct tcf_result *res)
 {
-       struct tcf_police *police = a->priv;
+       struct tcf_police *police = to_police(a);
        s64 now;
        s64 toks;
        s64 ptoks = 0;
@@ -311,7 +305,7 @@ static int
 tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
 {
        unsigned char *b = skb_tail_pointer(skb);
-       struct tcf_police *police = a->priv;
+       struct tcf_police *police = to_police(a);
        struct tc_police opt = {
                .index = police->tcf_index,
                .action = police->tcf_action,
@@ -349,7 +343,7 @@ nla_put_failure:
        return -1;
 }
 
-static int tcf_police_search(struct net *net, struct tc_action *a, u32 index)
+static int tcf_police_search(struct net *net, struct tc_action **a, u32 index)
 {
        struct tc_action_net *tn = net_generic(net, police_net_id);
 
@@ -369,6 +363,7 @@ static struct tc_action_ops act_police_ops = {
        .init           =       tcf_act_police_init,
        .walk           =       tcf_act_police_walker,
        .lookup         =       tcf_police_search,
+       .size           =       sizeof(struct tcf_police),
 };
 
 static __net_init int police_init_net(struct net *net)
index 318328d34d12aa7784ffd0a2de7486b02df6f399..289af6f9bb3b2b0712514d6e533d351cce288062 100644 (file)
 #define SIMP_TAB_MASK     7
 
 static int simp_net_id;
+static struct tc_action_ops act_simp_ops;
 
 #define SIMP_MAX_DATA  32
 static int tcf_simp(struct sk_buff *skb, const struct tc_action *a,
                    struct tcf_result *res)
 {
-       struct tcf_defact *d = a->priv;
+       struct tcf_defact *d = to_defact(a);
 
        spin_lock(&d->tcf_lock);
        tcf_lastuse_update(&d->tcf_tm);
@@ -79,7 +80,7 @@ static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = {
 };
 
 static int tcf_simp_init(struct net *net, struct nlattr *nla,
-                        struct nlattr *est, struct tc_action *a,
+                        struct nlattr *est, struct tc_action **a,
                         int ovr, int bind)
 {
        struct tc_action_net *tn = net_generic(net, simp_net_id);
@@ -100,7 +101,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
        if (tb[TCA_DEF_PARMS] == NULL)
                return -EINVAL;
 
-
        parm = nla_data(tb[TCA_DEF_PARMS]);
        exists = tcf_hash_check(tn, parm->index, a, bind);
        if (exists && bind)
@@ -108,7 +108,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
 
        if (tb[TCA_DEF_DATA] == NULL) {
                if (exists)
-                       tcf_hash_release(a, bind);
+                       tcf_hash_release(*a, bind);
                return -EINVAL;
        }
 
@@ -116,22 +116,22 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
 
        if (!exists) {
                ret = tcf_hash_create(tn, parm->index, est, a,
-                                     sizeof(*d), bind, false);
+                                     &act_simp_ops, bind, false);
                if (ret)
                        return ret;
 
-               d = to_defact(a);
+               d = to_defact(*a);
                ret = alloc_defdata(d, defdata);
                if (ret < 0) {
-                       tcf_hash_cleanup(a, est);
+                       tcf_hash_cleanup(*a, est);
                        return ret;
                }
                d->tcf_action = parm->action;
                ret = ACT_P_CREATED;
        } else {
-               d = to_defact(a);
+               d = to_defact(*a);
 
-               tcf_hash_release(a, bind);
+               tcf_hash_release(*a, bind);
                if (!ovr)
                        return -EEXIST;
 
@@ -139,7 +139,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
        }
 
        if (ret == ACT_P_CREATED)
-               tcf_hash_insert(tn, a);
+               tcf_hash_insert(tn, *a);
        return ret;
 }
 
@@ -147,7 +147,7 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
                         int bind, int ref)
 {
        unsigned char *b = skb_tail_pointer(skb);
-       struct tcf_defact *d = a->priv;
+       struct tcf_defact *d = to_defact(a);
        struct tc_defact opt = {
                .index   = d->tcf_index,
                .refcnt  = d->tcf_refcnt - ref,
@@ -172,14 +172,14 @@ nla_put_failure:
 
 static int tcf_simp_walker(struct net *net, struct sk_buff *skb,
                           struct netlink_callback *cb, int type,
-                          struct tc_action *a)
+                          const struct tc_action_ops *ops)
 {
        struct tc_action_net *tn = net_generic(net, simp_net_id);
 
-       return tcf_generic_walker(tn, skb, cb, type, a);
+       return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_simp_search(struct net *net, struct tc_action *a, u32 index)
+static int tcf_simp_search(struct net *net, struct tc_action **a, u32 index)
 {
        struct tc_action_net *tn = net_generic(net, simp_net_id);
 
@@ -196,6 +196,7 @@ static struct tc_action_ops act_simp_ops = {
        .init           =       tcf_simp_init,
        .walk           =       tcf_simp_walker,
        .lookup         =       tcf_simp_search,
+       .size           =       sizeof(struct tcf_defact),
 };
 
 static __net_init int simp_init_net(struct net *net)
index 8e573c0f874237b86a2c1407c62f6ee5c05c275c..a133dcb821323c45e03360b26977f292c5d50d09 100644 (file)
 #define SKBEDIT_TAB_MASK     15
 
 static int skbedit_net_id;
+static struct tc_action_ops act_skbedit_ops;
 
 static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
                       struct tcf_result *res)
 {
-       struct tcf_skbedit *d = a->priv;
+       struct tcf_skbedit *d = to_skbedit(a);
 
        spin_lock(&d->tcf_lock);
        tcf_lastuse_update(&d->tcf_tm);
@@ -63,7 +64,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
 };
 
 static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
-                           struct nlattr *est, struct tc_action *a,
+                           struct nlattr *est, struct tc_action **a,
                            int ovr, int bind)
 {
        struct tc_action_net *tn = net_generic(net, skbedit_net_id);
@@ -114,21 +115,21 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
                return 0;
 
        if (!flags) {
-               tcf_hash_release(a, bind);
+               tcf_hash_release(*a, bind);
                return -EINVAL;
        }
 
        if (!exists) {
                ret = tcf_hash_create(tn, parm->index, est, a,
-                                     sizeof(*d), bind, false);
+                                     &act_skbedit_ops, bind, false);
                if (ret)
                        return ret;
 
-               d = to_skbedit(a);
+               d = to_skbedit(*a);
                ret = ACT_P_CREATED;
        } else {
-               d = to_skbedit(a);
-               tcf_hash_release(a, bind);
+               d = to_skbedit(*a);
+               tcf_hash_release(*a, bind);
                if (!ovr)
                        return -EEXIST;
        }
@@ -150,7 +151,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
        spin_unlock_bh(&d->tcf_lock);
 
        if (ret == ACT_P_CREATED)
-               tcf_hash_insert(tn, a);
+               tcf_hash_insert(tn, *a);
        return ret;
 }
 
@@ -158,7 +159,7 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
                            int bind, int ref)
 {
        unsigned char *b = skb_tail_pointer(skb);
-       struct tcf_skbedit *d = a->priv;
+       struct tcf_skbedit *d = to_skbedit(a);
        struct tc_skbedit opt = {
                .index   = d->tcf_index,
                .refcnt  = d->tcf_refcnt - ref,
@@ -194,14 +195,14 @@ nla_put_failure:
 
 static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb,
                              struct netlink_callback *cb, int type,
-                             struct tc_action *a)
+                             const struct tc_action_ops *ops)
 {
        struct tc_action_net *tn = net_generic(net, skbedit_net_id);
 
-       return tcf_generic_walker(tn, skb, cb, type, a);
+       return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_skbedit_search(struct net *net, struct tc_action *a, u32 index)
+static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index)
 {
        struct tc_action_net *tn = net_generic(net, skbedit_net_id);
 
@@ -217,6 +218,7 @@ static struct tc_action_ops act_skbedit_ops = {
        .init           =       tcf_skbedit_init,
        .walk           =       tcf_skbedit_walker,
        .lookup         =       tcf_skbedit_search,
+       .size           =       sizeof(struct tcf_skbedit),
 };
 
 static __net_init int skbedit_init_net(struct net *net)
index db9b7ed570baa42d71c2a04257bcad19489110ff..691409de3e1a2cedf9ce0efbfa16998ebfd7856c 100644 (file)
 #define VLAN_TAB_MASK     15
 
 static int vlan_net_id;
+static struct tc_action_ops act_vlan_ops;
 
 static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a,
                    struct tcf_result *res)
 {
-       struct tcf_vlan *v = a->priv;
+       struct tcf_vlan *v = to_vlan(a);
        int action;
        int err;
 
@@ -67,7 +68,7 @@ static const struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = {
 };
 
 static int tcf_vlan_init(struct net *net, struct nlattr *nla,
-                        struct nlattr *est, struct tc_action *a,
+                        struct nlattr *est, struct tc_action **a,
                         int ovr, int bind)
 {
        struct tc_action_net *tn = net_generic(net, vlan_net_id);
@@ -100,13 +101,13 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
        case TCA_VLAN_ACT_PUSH:
                if (!tb[TCA_VLAN_PUSH_VLAN_ID]) {
                        if (exists)
-                               tcf_hash_release(a, bind);
+                               tcf_hash_release(*a, bind);
                        return -EINVAL;
                }
                push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
                if (push_vid >= VLAN_VID_MASK) {
                        if (exists)
-                               tcf_hash_release(a, bind);
+                               tcf_hash_release(*a, bind);
                        return -ERANGE;
                }
 
@@ -125,25 +126,25 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
                break;
        default:
                if (exists)
-                       tcf_hash_release(a, bind);
+                       tcf_hash_release(*a, bind);
                return -EINVAL;
        }
        action = parm->v_action;
 
        if (!exists) {
                ret = tcf_hash_create(tn, parm->index, est, a,
-                                     sizeof(*v), bind, false);
+                                     &act_vlan_ops, bind, false);
                if (ret)
                        return ret;
 
                ret = ACT_P_CREATED;
        } else {
-               tcf_hash_release(a, bind);
+               tcf_hash_release(*a, bind);
                if (!ovr)
                        return -EEXIST;
        }
 
-       v = to_vlan(a);
+       v = to_vlan(*a);
 
        spin_lock_bh(&v->tcf_lock);
 
@@ -156,7 +157,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
        spin_unlock_bh(&v->tcf_lock);
 
        if (ret == ACT_P_CREATED)
-               tcf_hash_insert(tn, a);
+               tcf_hash_insert(tn, *a);
        return ret;
 }
 
@@ -164,7 +165,7 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
                         int bind, int ref)
 {
        unsigned char *b = skb_tail_pointer(skb);
-       struct tcf_vlan *v = a->priv;
+       struct tcf_vlan *v = to_vlan(a);
        struct tc_vlan opt = {
                .index    = v->tcf_index,
                .refcnt   = v->tcf_refcnt - ref,
@@ -195,14 +196,14 @@ nla_put_failure:
 
 static int tcf_vlan_walker(struct net *net, struct sk_buff *skb,
                           struct netlink_callback *cb, int type,
-                          struct tc_action *a)
+                          const struct tc_action_ops *ops)
 {
        struct tc_action_net *tn = net_generic(net, vlan_net_id);
 
-       return tcf_generic_walker(tn, skb, cb, type, a);
+       return tcf_generic_walker(tn, skb, cb, type, ops);
 }
 
-static int tcf_vlan_search(struct net *net, struct tc_action *a, u32 index)
+static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index)
 {
        struct tc_action_net *tn = net_generic(net, vlan_net_id);
 
@@ -218,6 +219,7 @@ static struct tc_action_ops act_vlan_ops = {
        .init           =       tcf_vlan_init,
        .walk           =       tcf_vlan_walker,
        .lookup         =       tcf_vlan_search,
+       .size           =       sizeof(struct tcf_vlan),
 };
 
 static __net_init int vlan_init_net(struct net *net)