aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-07-26 00:49:20 -0400
committerDavid S. Miller <davem@davemloft.net>2016-07-26 00:49:20 -0400
commitc43212bb7bebe24a93a7a7d86e767e1ce295d72a (patch)
treeec43ad59bbc09fa3ddc8382f33100bd1434fe182
parentb93dd49c1a35884864027abd707889b795637f7a (diff)
parentec0595cc4495be579309b4bfd5e997af0f2ae6f9 (diff)
Merge branch 'refactor-tc_action-structs'
Cong Wang says: ==================== net_sched: refactor tc action structures These two patches factor out the struct tcf_common. v2: fix a compile warning ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/act_api.h91
-rw-r--r--include/net/tc_act/tc_bpf.h5
-rw-r--r--include/net/tc_act/tc_connmark.h5
-rw-r--r--include/net/tc_act/tc_csum.h5
-rw-r--r--include/net/tc_act/tc_defact.h5
-rw-r--r--include/net/tc_act/tc_gact.h7
-rw-r--r--include/net/tc_act/tc_ife.h5
-rw-r--r--include/net/tc_act/tc_ipt.h5
-rw-r--r--include/net/tc_act/tc_mirred.h5
-rw-r--r--include/net/tc_act/tc_nat.h7
-rw-r--r--include/net/tc_act/tc_pedit.h5
-rw-r--r--include/net/tc_act/tc_skbedit.h5
-rw-r--r--include/net/tc_act/tc_vlan.h5
-rw-r--r--net/sched/act_api.c250
-rw-r--r--net/sched/act_bpf.c26
-rw-r--r--net/sched/act_connmark.c24
-rw-r--r--net/sched/act_csum.c22
-rw-r--r--net/sched/act_gact.c24
-rw-r--r--net/sched/act_ife.c38
-rw-r--r--net/sched/act_ipt.c48
-rw-r--r--net/sched/act_mirred.c26
-rw-r--r--net/sched/act_nat.c22
-rw-r--r--net/sched/act_pedit.c28
-rw-r--r--net/sched/act_police.c49
-rw-r--r--net/sched/act_simple.c29
-rw-r--r--net/sched/act_skbedit.c26
-rw-r--r--net/sched/act_vlan.c28
27 files changed, 378 insertions, 417 deletions
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 0bb210635e5f..41e6a24a44b9 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -10,34 +10,6 @@
10#include <net/net_namespace.h> 10#include <net/net_namespace.h>
11#include <net/netns/generic.h> 11#include <net/netns/generic.h>
12 12
13struct tcf_common {
14 struct hlist_node tcfc_head;
15 u32 tcfc_index;
16 int tcfc_refcnt;
17 int tcfc_bindcnt;
18 u32 tcfc_capab;
19 int tcfc_action;
20 struct tcf_t tcfc_tm;
21 struct gnet_stats_basic_packed tcfc_bstats;
22 struct gnet_stats_queue tcfc_qstats;
23 struct gnet_stats_rate_est64 tcfc_rate_est;
24 spinlock_t tcfc_lock;
25 struct rcu_head tcfc_rcu;
26 struct gnet_stats_basic_cpu __percpu *cpu_bstats;
27 struct gnet_stats_queue __percpu *cpu_qstats;
28};
29#define tcf_head common.tcfc_head
30#define tcf_index common.tcfc_index
31#define tcf_refcnt common.tcfc_refcnt
32#define tcf_bindcnt common.tcfc_bindcnt
33#define tcf_capab common.tcfc_capab
34#define tcf_action common.tcfc_action
35#define tcf_tm common.tcfc_tm
36#define tcf_bstats common.tcfc_bstats
37#define tcf_qstats common.tcfc_qstats
38#define tcf_rate_est common.tcfc_rate_est
39#define tcf_lock common.tcfc_lock
40#define tcf_rcu common.tcfc_rcu
41 13
42struct tcf_hashinfo { 14struct tcf_hashinfo {
43 struct hlist_head *htab; 15 struct hlist_head *htab;
@@ -46,6 +18,44 @@ struct tcf_hashinfo {
46 u32 index; 18 u32 index;
47}; 19};
48 20
21struct tc_action_ops;
22
23struct tc_action {
24 const struct tc_action_ops *ops;
25 __u32 type; /* for backward compat(TCA_OLD_COMPAT) */
26 __u32 order;
27 struct list_head list;
28 struct tcf_hashinfo *hinfo;
29
30 struct hlist_node tcfa_head;
31 u32 tcfa_index;
32 int tcfa_refcnt;
33 int tcfa_bindcnt;
34 u32 tcfa_capab;
35 int tcfa_action;
36 struct tcf_t tcfa_tm;
37 struct gnet_stats_basic_packed tcfa_bstats;
38 struct gnet_stats_queue tcfa_qstats;
39 struct gnet_stats_rate_est64 tcfa_rate_est;
40 spinlock_t tcfa_lock;
41 struct rcu_head tcfa_rcu;
42 struct gnet_stats_basic_cpu __percpu *cpu_bstats;
43 struct gnet_stats_queue __percpu *cpu_qstats;
44};
45#define tcf_act common.tcfa_act
46#define tcf_head common.tcfa_head
47#define tcf_index common.tcfa_index
48#define tcf_refcnt common.tcfa_refcnt
49#define tcf_bindcnt common.tcfa_bindcnt
50#define tcf_capab common.tcfa_capab
51#define tcf_action common.tcfa_action
52#define tcf_tm common.tcfa_tm
53#define tcf_bstats common.tcfa_bstats
54#define tcf_qstats common.tcfa_qstats
55#define tcf_rate_est common.tcfa_rate_est
56#define tcf_lock common.tcfa_lock
57#define tcf_rcu common.tcfa_rcu
58
49static inline unsigned int tcf_hash(u32 index, unsigned int hmask) 59static inline unsigned int tcf_hash(u32 index, unsigned int hmask)
50{ 60{
51 return index & hmask; 61 return index & hmask;
@@ -88,15 +98,6 @@ static inline void tcf_tm_dump(struct tcf_t *dtm, const struct tcf_t *stm)
88 dtm->expires = jiffies_to_clock_t(stm->expires); 98 dtm->expires = jiffies_to_clock_t(stm->expires);
89} 99}
90 100
91struct tc_action {
92 void *priv;
93 const struct tc_action_ops *ops;
94 __u32 type; /* for backward compat(TCA_OLD_COMPAT) */
95 __u32 order;
96 struct list_head list;
97 struct tcf_hashinfo *hinfo;
98};
99
100#ifdef CONFIG_NET_CLS_ACT 101#ifdef CONFIG_NET_CLS_ACT
101 102
102#define ACT_P_CREATED 1 103#define ACT_P_CREATED 1
@@ -106,17 +107,18 @@ struct tc_action_ops {
106 struct list_head head; 107 struct list_head head;
107 char kind[IFNAMSIZ]; 108 char kind[IFNAMSIZ];
108 __u32 type; /* TBD to match kind */ 109 __u32 type; /* TBD to match kind */
110 size_t size;
109 struct module *owner; 111 struct module *owner;
110 int (*act)(struct sk_buff *, const struct tc_action *, 112 int (*act)(struct sk_buff *, const struct tc_action *,
111 struct tcf_result *); 113 struct tcf_result *);
112 int (*dump)(struct sk_buff *, struct tc_action *, int, int); 114 int (*dump)(struct sk_buff *, struct tc_action *, int, int);
113 void (*cleanup)(struct tc_action *, int bind); 115 void (*cleanup)(struct tc_action *, int bind);
114 int (*lookup)(struct net *, struct tc_action *, u32); 116 int (*lookup)(struct net *, struct tc_action **, u32);
115 int (*init)(struct net *net, struct nlattr *nla, 117 int (*init)(struct net *net, struct nlattr *nla,
116 struct nlattr *est, struct tc_action *act, int ovr, 118 struct nlattr *est, struct tc_action **act, int ovr,
117 int bind); 119 int bind);
118 int (*walk)(struct net *, struct sk_buff *, 120 int (*walk)(struct net *, struct sk_buff *,
119 struct netlink_callback *, int, struct tc_action *); 121 struct netlink_callback *, int, const struct tc_action_ops *);
120 void (*stats_update)(struct tc_action *, u64, u32, u64); 122 void (*stats_update)(struct tc_action *, u64, u32, u64);
121}; 123};
122 124
@@ -152,13 +154,14 @@ static inline void tc_action_net_exit(struct tc_action_net *tn)
152 154
153int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, 155int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
154 struct netlink_callback *cb, int type, 156 struct netlink_callback *cb, int type,
155 struct tc_action *a); 157 const struct tc_action_ops *ops);
156int tcf_hash_search(struct tc_action_net *tn, struct tc_action *a, u32 index); 158int tcf_hash_search(struct tc_action_net *tn, struct tc_action **a, u32 index);
157u32 tcf_hash_new_index(struct tc_action_net *tn); 159u32 tcf_hash_new_index(struct tc_action_net *tn);
158bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a, 160bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
159 int bind); 161 int bind);
160int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est, 162int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
161 struct tc_action *a, int size, int bind, bool cpustats); 163 struct tc_action **a, const struct tc_action_ops *ops, int bind,
164 bool cpustats);
162void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est); 165void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est);
163void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a); 166void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a);
164 167
diff --git a/include/net/tc_act/tc_bpf.h b/include/net/tc_act/tc_bpf.h
index 958d69cfb19c..2b94673a3dbc 100644
--- a/include/net/tc_act/tc_bpf.h
+++ b/include/net/tc_act/tc_bpf.h
@@ -14,7 +14,7 @@
14#include <net/act_api.h> 14#include <net/act_api.h>
15 15
16struct tcf_bpf { 16struct tcf_bpf {
17 struct tcf_common common; 17 struct tc_action common;
18 struct bpf_prog __rcu *filter; 18 struct bpf_prog __rcu *filter;
19 union { 19 union {
20 u32 bpf_fd; 20 u32 bpf_fd;
@@ -23,7 +23,6 @@ struct tcf_bpf {
23 struct sock_filter *bpf_ops; 23 struct sock_filter *bpf_ops;
24 const char *bpf_name; 24 const char *bpf_name;
25}; 25};
26#define to_bpf(a) \ 26#define to_bpf(a) ((struct tcf_bpf *)a)
27 container_of(a->priv, struct tcf_bpf, common)
28 27
29#endif /* __NET_TC_BPF_H */ 28#endif /* __NET_TC_BPF_H */
diff --git a/include/net/tc_act/tc_connmark.h b/include/net/tc_act/tc_connmark.h
index 02caa406611b..59b515d32bb4 100644
--- a/include/net/tc_act/tc_connmark.h
+++ b/include/net/tc_act/tc_connmark.h
@@ -4,12 +4,11 @@
4#include <net/act_api.h> 4#include <net/act_api.h>
5 5
6struct tcf_connmark_info { 6struct tcf_connmark_info {
7 struct tcf_common common; 7 struct tc_action common;
8 struct net *net; 8 struct net *net;
9 u16 zone; 9 u16 zone;
10}; 10};
11 11
12#define to_connmark(a) \ 12#define to_connmark(a) ((struct tcf_connmark_info *)a)
13 container_of(a->priv, struct tcf_connmark_info, common)
14 13
15#endif /* __NET_TC_CONNMARK_H */ 14#endif /* __NET_TC_CONNMARK_H */
diff --git a/include/net/tc_act/tc_csum.h b/include/net/tc_act/tc_csum.h
index fa8f5fac65e9..f31fb6331a53 100644
--- a/include/net/tc_act/tc_csum.h
+++ b/include/net/tc_act/tc_csum.h
@@ -5,11 +5,10 @@
5#include <net/act_api.h> 5#include <net/act_api.h>
6 6
7struct tcf_csum { 7struct tcf_csum {
8 struct tcf_common common; 8 struct tc_action common;
9 9
10 u32 update_flags; 10 u32 update_flags;
11}; 11};
12#define to_tcf_csum(a) \ 12#define to_tcf_csum(a) ((struct tcf_csum *)a)
13 container_of(a->priv,struct tcf_csum,common)
14 13
15#endif /* __NET_TC_CSUM_H */ 14#endif /* __NET_TC_CSUM_H */
diff --git a/include/net/tc_act/tc_defact.h b/include/net/tc_act/tc_defact.h
index ab9b5d6be67b..d47f040a3bdf 100644
--- a/include/net/tc_act/tc_defact.h
+++ b/include/net/tc_act/tc_defact.h
@@ -4,11 +4,10 @@
4#include <net/act_api.h> 4#include <net/act_api.h>
5 5
6struct tcf_defact { 6struct tcf_defact {
7 struct tcf_common common; 7 struct tc_action common;
8 u32 tcfd_datalen; 8 u32 tcfd_datalen;
9 void *tcfd_defdata; 9 void *tcfd_defdata;
10}; 10};
11#define to_defact(a) \ 11#define to_defact(a) ((struct tcf_defact *)a)
12 container_of(a->priv, struct tcf_defact, common)
13 12
14#endif /* __NET_TC_DEF_H */ 13#endif /* __NET_TC_DEF_H */
diff --git a/include/net/tc_act/tc_gact.h b/include/net/tc_act/tc_gact.h
index 93c520b83d10..b6f173910226 100644
--- a/include/net/tc_act/tc_gact.h
+++ b/include/net/tc_act/tc_gact.h
@@ -5,7 +5,7 @@
5#include <linux/tc_act/tc_gact.h> 5#include <linux/tc_act/tc_gact.h>
6 6
7struct tcf_gact { 7struct tcf_gact {
8 struct tcf_common common; 8 struct tc_action common;
9#ifdef CONFIG_GACT_PROB 9#ifdef CONFIG_GACT_PROB
10 u16 tcfg_ptype; 10 u16 tcfg_ptype;
11 u16 tcfg_pval; 11 u16 tcfg_pval;
@@ -13,8 +13,7 @@ struct tcf_gact {
13 atomic_t packets; 13 atomic_t packets;
14#endif 14#endif
15}; 15};
16#define to_gact(a) \ 16#define to_gact(a) ((struct tcf_gact *)a)
17 container_of(a->priv, struct tcf_gact, common)
18 17
19static inline bool is_tcf_gact_shot(const struct tc_action *a) 18static inline bool is_tcf_gact_shot(const struct tc_action *a)
20{ 19{
@@ -24,7 +23,7 @@ static inline bool is_tcf_gact_shot(const struct tc_action *a)
24 if (a->ops && a->ops->type != TCA_ACT_GACT) 23 if (a->ops && a->ops->type != TCA_ACT_GACT)
25 return false; 24 return false;
26 25
27 gact = a->priv; 26 gact = to_gact(a);
28 if (gact->tcf_action == TC_ACT_SHOT) 27 if (gact->tcf_action == TC_ACT_SHOT)
29 return true; 28 return true;
30 29
diff --git a/include/net/tc_act/tc_ife.h b/include/net/tc_act/tc_ife.h
index c55facd17b7e..5164bd7a38fb 100644
--- a/include/net/tc_act/tc_ife.h
+++ b/include/net/tc_act/tc_ife.h
@@ -8,7 +8,7 @@
8 8
9#define IFE_METAHDRLEN 2 9#define IFE_METAHDRLEN 2
10struct tcf_ife_info { 10struct tcf_ife_info {
11 struct tcf_common common; 11 struct tc_action common;
12 u8 eth_dst[ETH_ALEN]; 12 u8 eth_dst[ETH_ALEN];
13 u8 eth_src[ETH_ALEN]; 13 u8 eth_src[ETH_ALEN];
14 u16 eth_type; 14 u16 eth_type;
@@ -16,8 +16,7 @@ struct tcf_ife_info {
16 /* list of metaids allowed */ 16 /* list of metaids allowed */
17 struct list_head metalist; 17 struct list_head metalist;
18}; 18};
19#define to_ife(a) \ 19#define to_ife(a) ((struct tcf_ife_info *)a)
20 container_of(a->priv, struct tcf_ife_info, common)
21 20
22struct tcf_meta_info { 21struct tcf_meta_info {
23 const struct tcf_meta_ops *ops; 22 const struct tcf_meta_ops *ops;
diff --git a/include/net/tc_act/tc_ipt.h b/include/net/tc_act/tc_ipt.h
index c0f4193f432c..31309766e379 100644
--- a/include/net/tc_act/tc_ipt.h
+++ b/include/net/tc_act/tc_ipt.h
@@ -6,12 +6,11 @@
6struct xt_entry_target; 6struct xt_entry_target;
7 7
8struct tcf_ipt { 8struct tcf_ipt {
9 struct tcf_common common; 9 struct tc_action common;
10 u32 tcfi_hook; 10 u32 tcfi_hook;
11 char *tcfi_tname; 11 char *tcfi_tname;
12 struct xt_entry_target *tcfi_t; 12 struct xt_entry_target *tcfi_t;
13}; 13};
14#define to_ipt(a) \ 14#define to_ipt(a) ((struct tcf_ipt *)a)
15 container_of(a->priv, struct tcf_ipt, common)
16 15
17#endif /* __NET_TC_IPT_H */ 16#endif /* __NET_TC_IPT_H */
diff --git a/include/net/tc_act/tc_mirred.h b/include/net/tc_act/tc_mirred.h
index 6a13a7c74e0c..62770add15bd 100644
--- a/include/net/tc_act/tc_mirred.h
+++ b/include/net/tc_act/tc_mirred.h
@@ -5,15 +5,14 @@
5#include <linux/tc_act/tc_mirred.h> 5#include <linux/tc_act/tc_mirred.h>
6 6
7struct tcf_mirred { 7struct tcf_mirred {
8 struct tcf_common common; 8 struct tc_action common;
9 int tcfm_eaction; 9 int tcfm_eaction;
10 int tcfm_ifindex; 10 int tcfm_ifindex;
11 int tcfm_ok_push; 11 int tcfm_ok_push;
12 struct net_device __rcu *tcfm_dev; 12 struct net_device __rcu *tcfm_dev;
13 struct list_head tcfm_list; 13 struct list_head tcfm_list;
14}; 14};
15#define to_mirred(a) \ 15#define to_mirred(a) ((struct tcf_mirred *)a)
16 container_of(a->priv, struct tcf_mirred, common)
17 16
18static inline bool is_tcf_mirred_redirect(const struct tc_action *a) 17static inline bool is_tcf_mirred_redirect(const struct tc_action *a)
19{ 18{
diff --git a/include/net/tc_act/tc_nat.h b/include/net/tc_act/tc_nat.h
index 63d8e9ca9d99..56681a320612 100644
--- a/include/net/tc_act/tc_nat.h
+++ b/include/net/tc_act/tc_nat.h
@@ -5,7 +5,7 @@
5#include <net/act_api.h> 5#include <net/act_api.h>
6 6
7struct tcf_nat { 7struct tcf_nat {
8 struct tcf_common common; 8 struct tc_action common;
9 9
10 __be32 old_addr; 10 __be32 old_addr;
11 __be32 new_addr; 11 __be32 new_addr;
@@ -13,9 +13,6 @@ struct tcf_nat {
13 u32 flags; 13 u32 flags;
14}; 14};
15 15
16static inline struct tcf_nat *to_tcf_nat(struct tc_action *a) 16#define to_tcf_nat(a) ((struct tcf_nat *)a)
17{
18 return container_of(a->priv, struct tcf_nat, common);
19}
20 17
21#endif /* __NET_TC_NAT_H */ 18#endif /* __NET_TC_NAT_H */
diff --git a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h
index 5b80998879c7..29e38d6823df 100644
--- a/include/net/tc_act/tc_pedit.h
+++ b/include/net/tc_act/tc_pedit.h
@@ -4,12 +4,11 @@
4#include <net/act_api.h> 4#include <net/act_api.h>
5 5
6struct tcf_pedit { 6struct tcf_pedit {
7 struct tcf_common common; 7 struct tc_action common;
8 unsigned char tcfp_nkeys; 8 unsigned char tcfp_nkeys;
9 unsigned char tcfp_flags; 9 unsigned char tcfp_flags;
10 struct tc_pedit_key *tcfp_keys; 10 struct tc_pedit_key *tcfp_keys;
11}; 11};
12#define to_pedit(a) \ 12#define to_pedit(a) ((struct tcf_pedit *)a)
13 container_of(a->priv, struct tcf_pedit, common)
14 13
15#endif /* __NET_TC_PED_H */ 14#endif /* __NET_TC_PED_H */
diff --git a/include/net/tc_act/tc_skbedit.h b/include/net/tc_act/tc_skbedit.h
index d01a5d40cfb5..5767e9dbcf92 100644
--- a/include/net/tc_act/tc_skbedit.h
+++ b/include/net/tc_act/tc_skbedit.h
@@ -23,15 +23,14 @@
23#include <linux/tc_act/tc_skbedit.h> 23#include <linux/tc_act/tc_skbedit.h>
24 24
25struct tcf_skbedit { 25struct tcf_skbedit {
26 struct tcf_common common; 26 struct tc_action common;
27 u32 flags; 27 u32 flags;
28 u32 priority; 28 u32 priority;
29 u32 mark; 29 u32 mark;
30 u16 queue_mapping; 30 u16 queue_mapping;
31 u16 ptype; 31 u16 ptype;
32}; 32};
33#define to_skbedit(a) \ 33#define to_skbedit(a) ((struct tcf_skbedit *)a)
34 container_of(a->priv, struct tcf_skbedit, common)
35 34
36/* Return true iff action is mark */ 35/* Return true iff action is mark */
37static inline bool is_tcf_skbedit_mark(const struct tc_action *a) 36static inline bool is_tcf_skbedit_mark(const struct tc_action *a)
diff --git a/include/net/tc_act/tc_vlan.h b/include/net/tc_act/tc_vlan.h
index 93b70ade1ff3..e29f52e8bdf1 100644
--- a/include/net/tc_act/tc_vlan.h
+++ b/include/net/tc_act/tc_vlan.h
@@ -16,12 +16,11 @@
16#define VLAN_F_PUSH 0x2 16#define VLAN_F_PUSH 0x2
17 17
18struct tcf_vlan { 18struct tcf_vlan {
19 struct tcf_common common; 19 struct tc_action common;
20 int tcfv_action; 20 int tcfv_action;
21 u16 tcfv_push_vid; 21 u16 tcfv_push_vid;
22 __be16 tcfv_push_proto; 22 __be16 tcfv_push_proto;
23}; 23};
24#define to_vlan(a) \ 24#define to_vlan(a) ((struct tcf_vlan *)a)
25 container_of(a->priv, struct tcf_vlan, common)
26 25
27#endif /* __NET_TC_VLAN_H */ 26#endif /* __NET_TC_VLAN_H */
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 47ec2305f920..e4a5f2607ffa 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -29,45 +29,43 @@
29 29
30static void free_tcf(struct rcu_head *head) 30static void free_tcf(struct rcu_head *head)
31{ 31{
32 struct tcf_common *p = container_of(head, struct tcf_common, tcfc_rcu); 32 struct tc_action *p = container_of(head, struct tc_action, tcfa_rcu);
33 33
34 free_percpu(p->cpu_bstats); 34 free_percpu(p->cpu_bstats);
35 free_percpu(p->cpu_qstats); 35 free_percpu(p->cpu_qstats);
36 kfree(p); 36 kfree(p);
37} 37}
38 38
39static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *a) 39static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *p)
40{ 40{
41 struct tcf_common *p = a->priv;
42
43 spin_lock_bh(&hinfo->lock); 41 spin_lock_bh(&hinfo->lock);
44 hlist_del(&p->tcfc_head); 42 hlist_del(&p->tcfa_head);
45 spin_unlock_bh(&hinfo->lock); 43 spin_unlock_bh(&hinfo->lock);
46 gen_kill_estimator(&p->tcfc_bstats, 44 gen_kill_estimator(&p->tcfa_bstats,
47 &p->tcfc_rate_est); 45 &p->tcfa_rate_est);
48 /* 46 /*
49 * gen_estimator est_timer() might access p->tcfc_lock 47 * gen_estimator est_timer() might access p->tcfa_lock
50 * or bstats, wait a RCU grace period before freeing p 48 * or bstats, wait a RCU grace period before freeing p
51 */ 49 */
52 call_rcu(&p->tcfc_rcu, free_tcf); 50 call_rcu(&p->tcfa_rcu, free_tcf);
53} 51}
54 52
55int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) 53int __tcf_hash_release(struct tc_action *p, bool bind, bool strict)
56{ 54{
57 struct tcf_common *p = a->priv;
58 int ret = 0; 55 int ret = 0;
59 56
60 if (p) { 57 if (p) {
61 if (bind) 58 if (bind)
62 p->tcfc_bindcnt--; 59 p->tcfa_bindcnt--;
63 else if (strict && p->tcfc_bindcnt > 0) 60 else if (strict && p->tcfa_bindcnt > 0)
64 return -EPERM; 61 return -EPERM;
65 62
66 p->tcfc_refcnt--; 63 p->tcfa_refcnt--;
67 if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) { 64 if (p->tcfa_bindcnt <= 0 && p->tcfa_refcnt <= 0) {
68 if (a->ops->cleanup) 65 if (p->ops->cleanup)
69 a->ops->cleanup(a, bind); 66 p->ops->cleanup(p, bind);
70 tcf_hash_destroy(a->hinfo, a); 67 list_del(&p->list);
68 tcf_hash_destroy(p->hinfo, p);
71 ret = ACT_P_DELETED; 69 ret = ACT_P_DELETED;
72 } 70 }
73 } 71 }
@@ -77,10 +75,8 @@ int __tcf_hash_release(struct tc_action *a, bool bind, bool strict)
77EXPORT_SYMBOL(__tcf_hash_release); 75EXPORT_SYMBOL(__tcf_hash_release);
78 76
79static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, 77static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
80 struct netlink_callback *cb, struct tc_action *a) 78 struct netlink_callback *cb)
81{ 79{
82 struct hlist_head *head;
83 struct tcf_common *p;
84 int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; 80 int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
85 struct nlattr *nest; 81 struct nlattr *nest;
86 82
@@ -89,19 +85,20 @@ static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
89 s_i = cb->args[0]; 85 s_i = cb->args[0];
90 86
91 for (i = 0; i < (hinfo->hmask + 1); i++) { 87 for (i = 0; i < (hinfo->hmask + 1); i++) {
88 struct hlist_head *head;
89 struct tc_action *p;
90
92 head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; 91 head = &hinfo->htab[tcf_hash(i, hinfo->hmask)];
93 92
94 hlist_for_each_entry_rcu(p, head, tcfc_head) { 93 hlist_for_each_entry_rcu(p, head, tcfa_head) {
95 index++; 94 index++;
96 if (index < s_i) 95 if (index < s_i)
97 continue; 96 continue;
98 a->priv = p;
99 a->order = n_i;
100 97
101 nest = nla_nest_start(skb, a->order); 98 nest = nla_nest_start(skb, n_i);
102 if (nest == NULL) 99 if (nest == NULL)
103 goto nla_put_failure; 100 goto nla_put_failure;
104 err = tcf_action_dump_1(skb, a, 0, 0); 101 err = tcf_action_dump_1(skb, p, 0, 0);
105 if (err < 0) { 102 if (err < 0) {
106 index--; 103 index--;
107 nlmsg_trim(skb, nest); 104 nlmsg_trim(skb, nest);
@@ -125,27 +122,27 @@ nla_put_failure:
125} 122}
126 123
127static int tcf_del_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, 124static int tcf_del_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb,
128 struct tc_action *a) 125 const struct tc_action_ops *ops)
129{ 126{
130 struct hlist_head *head;
131 struct hlist_node *n;
132 struct tcf_common *p;
133 struct nlattr *nest; 127 struct nlattr *nest;
134 int i = 0, n_i = 0; 128 int i = 0, n_i = 0;
135 int ret = -EINVAL; 129 int ret = -EINVAL;
136 130
137 nest = nla_nest_start(skb, a->order); 131 nest = nla_nest_start(skb, 0);
138 if (nest == NULL) 132 if (nest == NULL)
139 goto nla_put_failure; 133 goto nla_put_failure;
140 if (nla_put_string(skb, TCA_KIND, a->ops->kind)) 134 if (nla_put_string(skb, TCA_KIND, ops->kind))
141 goto nla_put_failure; 135 goto nla_put_failure;
142 for (i = 0; i < (hinfo->hmask + 1); i++) { 136 for (i = 0; i < (hinfo->hmask + 1); i++) {
137 struct hlist_head *head;
138 struct hlist_node *n;
139 struct tc_action *p;
140
143 head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; 141 head = &hinfo->htab[tcf_hash(i, hinfo->hmask)];
144 hlist_for_each_entry_safe(p, n, head, tcfc_head) { 142 hlist_for_each_entry_safe(p, n, head, tcfa_head) {
145 a->priv = p; 143 ret = __tcf_hash_release(p, false, true);
146 ret = __tcf_hash_release(a, false, true);
147 if (ret == ACT_P_DELETED) { 144 if (ret == ACT_P_DELETED) {
148 module_put(a->ops->owner); 145 module_put(p->ops->owner);
149 n_i++; 146 n_i++;
150 } else if (ret < 0) 147 } else if (ret < 0)
151 goto nla_put_failure; 148 goto nla_put_failure;
@@ -163,16 +160,14 @@ nla_put_failure:
163 160
164int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, 161int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
165 struct netlink_callback *cb, int type, 162 struct netlink_callback *cb, int type,
166 struct tc_action *a) 163 const struct tc_action_ops *ops)
167{ 164{
168 struct tcf_hashinfo *hinfo = tn->hinfo; 165 struct tcf_hashinfo *hinfo = tn->hinfo;
169 166
170 a->hinfo = hinfo;
171
172 if (type == RTM_DELACTION) { 167 if (type == RTM_DELACTION) {
173 return tcf_del_walker(hinfo, skb, a); 168 return tcf_del_walker(hinfo, skb, ops);
174 } else if (type == RTM_GETACTION) { 169 } else if (type == RTM_GETACTION) {
175 return tcf_dump_walker(hinfo, skb, cb, a); 170 return tcf_dump_walker(hinfo, skb, cb);
176 } else { 171 } else {
177 WARN(1, "tcf_generic_walker: unknown action %d\n", type); 172 WARN(1, "tcf_generic_walker: unknown action %d\n", type);
178 return -EINVAL; 173 return -EINVAL;
@@ -180,15 +175,15 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
180} 175}
181EXPORT_SYMBOL(tcf_generic_walker); 176EXPORT_SYMBOL(tcf_generic_walker);
182 177
183static struct tcf_common *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo) 178static struct tc_action *tcf_hash_lookup(u32 index, struct tcf_hashinfo *hinfo)
184{ 179{
185 struct tcf_common *p = NULL; 180 struct tc_action *p = NULL;
186 struct hlist_head *head; 181 struct hlist_head *head;
187 182
188 spin_lock_bh(&hinfo->lock); 183 spin_lock_bh(&hinfo->lock);
189 head = &hinfo->htab[tcf_hash(index, hinfo->hmask)]; 184 head = &hinfo->htab[tcf_hash(index, hinfo->hmask)];
190 hlist_for_each_entry_rcu(p, head, tcfc_head) 185 hlist_for_each_entry_rcu(p, head, tcfa_head)
191 if (p->tcfc_index == index) 186 if (p->tcfa_index == index)
192 break; 187 break;
193 spin_unlock_bh(&hinfo->lock); 188 spin_unlock_bh(&hinfo->lock);
194 189
@@ -210,31 +205,30 @@ u32 tcf_hash_new_index(struct tc_action_net *tn)
210} 205}
211EXPORT_SYMBOL(tcf_hash_new_index); 206EXPORT_SYMBOL(tcf_hash_new_index);
212 207
213int tcf_hash_search(struct tc_action_net *tn, struct tc_action *a, u32 index) 208int tcf_hash_search(struct tc_action_net *tn, struct tc_action **a, u32 index)
214{ 209{
215 struct tcf_hashinfo *hinfo = tn->hinfo; 210 struct tcf_hashinfo *hinfo = tn->hinfo;
216 struct tcf_common *p = tcf_hash_lookup(index, hinfo); 211 struct tc_action *p = tcf_hash_lookup(index, hinfo);
217 212
218 if (p) { 213 if (p) {
219 a->priv = p; 214 *a = p;
220 a->hinfo = hinfo;
221 return 1; 215 return 1;
222 } 216 }
223 return 0; 217 return 0;
224} 218}
225EXPORT_SYMBOL(tcf_hash_search); 219EXPORT_SYMBOL(tcf_hash_search);
226 220
227bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a, 221bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
228 int bind) 222 int bind)
229{ 223{
230 struct tcf_hashinfo *hinfo = tn->hinfo; 224 struct tcf_hashinfo *hinfo = tn->hinfo;
231 struct tcf_common *p = NULL; 225 struct tc_action *p = NULL;
226
232 if (index && (p = tcf_hash_lookup(index, hinfo)) != NULL) { 227 if (index && (p = tcf_hash_lookup(index, hinfo)) != NULL) {
233 if (bind) 228 if (bind)
234 p->tcfc_bindcnt++; 229 p->tcfa_bindcnt++;
235 p->tcfc_refcnt++; 230 p->tcfa_refcnt++;
236 a->priv = p; 231 *a = p;
237 a->hinfo = hinfo;
238 return true; 232 return true;
239 } 233 }
240 return false; 234 return false;
@@ -243,26 +237,26 @@ EXPORT_SYMBOL(tcf_hash_check);
243 237
244void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est) 238void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est)
245{ 239{
246 struct tcf_common *pc = a->priv;
247 if (est) 240 if (est)
248 gen_kill_estimator(&pc->tcfc_bstats, 241 gen_kill_estimator(&a->tcfa_bstats,
249 &pc->tcfc_rate_est); 242 &a->tcfa_rate_est);
250 call_rcu(&pc->tcfc_rcu, free_tcf); 243 call_rcu(&a->tcfa_rcu, free_tcf);
251} 244}
252EXPORT_SYMBOL(tcf_hash_cleanup); 245EXPORT_SYMBOL(tcf_hash_cleanup);
253 246
254int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est, 247int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
255 struct tc_action *a, int size, int bind, bool cpustats) 248 struct tc_action **a, const struct tc_action_ops *ops,
249 int bind, bool cpustats)
256{ 250{
257 struct tcf_common *p = kzalloc(size, GFP_KERNEL); 251 struct tc_action *p = kzalloc(ops->size, GFP_KERNEL);
258 struct tcf_hashinfo *hinfo = tn->hinfo; 252 struct tcf_hashinfo *hinfo = tn->hinfo;
259 int err = -ENOMEM; 253 int err = -ENOMEM;
260 254
261 if (unlikely(!p)) 255 if (unlikely(!p))
262 return -ENOMEM; 256 return -ENOMEM;
263 p->tcfc_refcnt = 1; 257 p->tcfa_refcnt = 1;
264 if (bind) 258 if (bind)
265 p->tcfc_bindcnt = 1; 259 p->tcfa_bindcnt = 1;
266 260
267 if (cpustats) { 261 if (cpustats) {
268 p->cpu_bstats = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu); 262 p->cpu_bstats = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
@@ -278,36 +272,37 @@ err2:
278 goto err1; 272 goto err1;
279 } 273 }
280 } 274 }
281 spin_lock_init(&p->tcfc_lock); 275 spin_lock_init(&p->tcfa_lock);
282 INIT_HLIST_NODE(&p->tcfc_head); 276 INIT_HLIST_NODE(&p->tcfa_head);
283 p->tcfc_index = index ? index : tcf_hash_new_index(tn); 277 p->tcfa_index = index ? index : tcf_hash_new_index(tn);
284 p->tcfc_tm.install = jiffies; 278 p->tcfa_tm.install = jiffies;
285 p->tcfc_tm.lastuse = jiffies; 279 p->tcfa_tm.lastuse = jiffies;
286 p->tcfc_tm.firstuse = 0; 280 p->tcfa_tm.firstuse = 0;
287 if (est) { 281 if (est) {
288 err = gen_new_estimator(&p->tcfc_bstats, p->cpu_bstats, 282 err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats,
289 &p->tcfc_rate_est, 283 &p->tcfa_rate_est,
290 &p->tcfc_lock, NULL, est); 284 &p->tcfa_lock, NULL, est);
291 if (err) { 285 if (err) {
292 free_percpu(p->cpu_qstats); 286 free_percpu(p->cpu_qstats);
293 goto err2; 287 goto err2;
294 } 288 }
295 } 289 }
296 290
297 a->priv = (void *) p; 291 p->hinfo = hinfo;
298 a->hinfo = hinfo; 292 p->ops = ops;
293 INIT_LIST_HEAD(&p->list);
294 *a = p;
299 return 0; 295 return 0;
300} 296}
301EXPORT_SYMBOL(tcf_hash_create); 297EXPORT_SYMBOL(tcf_hash_create);
302 298
303void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a) 299void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a)
304{ 300{
305 struct tcf_common *p = a->priv;
306 struct tcf_hashinfo *hinfo = tn->hinfo; 301 struct tcf_hashinfo *hinfo = tn->hinfo;
307 unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); 302 unsigned int h = tcf_hash(a->tcfa_index, hinfo->hmask);
308 303
309 spin_lock_bh(&hinfo->lock); 304 spin_lock_bh(&hinfo->lock);
310 hlist_add_head(&p->tcfc_head, &hinfo->htab[h]); 305 hlist_add_head(&a->tcfa_head, &hinfo->htab[h]);
311 spin_unlock_bh(&hinfo->lock); 306 spin_unlock_bh(&hinfo->lock);
312} 307}
313EXPORT_SYMBOL(tcf_hash_insert); 308EXPORT_SYMBOL(tcf_hash_insert);
@@ -315,21 +310,16 @@ EXPORT_SYMBOL(tcf_hash_insert);
315void tcf_hashinfo_destroy(const struct tc_action_ops *ops, 310void tcf_hashinfo_destroy(const struct tc_action_ops *ops,
316 struct tcf_hashinfo *hinfo) 311 struct tcf_hashinfo *hinfo)
317{ 312{
318 struct tc_action a = {
319 .ops = ops,
320 .hinfo = hinfo,
321 };
322 int i; 313 int i;
323 314
324 for (i = 0; i < hinfo->hmask + 1; i++) { 315 for (i = 0; i < hinfo->hmask + 1; i++) {
325 struct tcf_common *p; 316 struct tc_action *p;
326 struct hlist_node *n; 317 struct hlist_node *n;
327 318
328 hlist_for_each_entry_safe(p, n, &hinfo->htab[i], tcfc_head) { 319 hlist_for_each_entry_safe(p, n, &hinfo->htab[i], tcfa_head) {
329 int ret; 320 int ret;
330 321
331 a.priv = p; 322 ret = __tcf_hash_release(p, false, true);
332 ret = __tcf_hash_release(&a, false, true);
333 if (ret == ACT_P_DELETED) 323 if (ret == ACT_P_DELETED)
334 module_put(ops->owner); 324 module_put(ops->owner);
335 else if (ret < 0) 325 else if (ret < 0)
@@ -466,8 +456,6 @@ int tcf_action_destroy(struct list_head *actions, int bind)
466 module_put(a->ops->owner); 456 module_put(a->ops->owner);
467 else if (ret < 0) 457 else if (ret < 0)
468 return ret; 458 return ret;
469 list_del(&a->list);
470 kfree(a);
471 } 459 }
472 return ret; 460 return ret;
473} 461}
@@ -581,20 +569,13 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
581 goto err_out; 569 goto err_out;
582 } 570 }
583 571
584 err = -ENOMEM;
585 a = kzalloc(sizeof(*a), GFP_KERNEL);
586 if (a == NULL)
587 goto err_mod;
588
589 a->ops = a_o;
590 INIT_LIST_HEAD(&a->list);
591 /* backward compatibility for policer */ 572 /* backward compatibility for policer */
592 if (name == NULL) 573 if (name == NULL)
593 err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, a, ovr, bind); 574 err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind);
594 else 575 else
595 err = a_o->init(net, nla, est, a, ovr, bind); 576 err = a_o->init(net, nla, est, &a, ovr, bind);
596 if (err < 0) 577 if (err < 0)
597 goto err_free; 578 goto err_mod;
598 579
599 /* module count goes up only when brand new policy is created 580 /* module count goes up only when brand new policy is created
600 * if it exists and is only bound to in a_o->init() then 581 * if it exists and is only bound to in a_o->init() then
@@ -605,8 +586,6 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla,
605 586
606 return a; 587 return a;
607 588
608err_free:
609 kfree(a);
610err_mod: 589err_mod:
611 module_put(a_o->owner); 590 module_put(a_o->owner);
612err_out: 591err_out:
@@ -642,12 +621,11 @@ err:
642 return err; 621 return err;
643} 622}
644 623
645int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, 624int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *p,
646 int compat_mode) 625 int compat_mode)
647{ 626{
648 int err = 0; 627 int err = 0;
649 struct gnet_dump d; 628 struct gnet_dump d;
650 struct tcf_common *p = a->priv;
651 629
652 if (p == NULL) 630 if (p == NULL)
653 goto errout; 631 goto errout;
@@ -656,27 +634,27 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a,
656 * to add additional backward compatibility statistic TLVs. 634 * to add additional backward compatibility statistic TLVs.
657 */ 635 */
658 if (compat_mode) { 636 if (compat_mode) {
659 if (a->type == TCA_OLD_COMPAT) 637 if (p->type == TCA_OLD_COMPAT)
660 err = gnet_stats_start_copy_compat(skb, 0, 638 err = gnet_stats_start_copy_compat(skb, 0,
661 TCA_STATS, 639 TCA_STATS,
662 TCA_XSTATS, 640 TCA_XSTATS,
663 &p->tcfc_lock, &d, 641 &p->tcfa_lock, &d,
664 TCA_PAD); 642 TCA_PAD);
665 else 643 else
666 return 0; 644 return 0;
667 } else 645 } else
668 err = gnet_stats_start_copy(skb, TCA_ACT_STATS, 646 err = gnet_stats_start_copy(skb, TCA_ACT_STATS,
669 &p->tcfc_lock, &d, TCA_ACT_PAD); 647 &p->tcfa_lock, &d, TCA_ACT_PAD);
670 648
671 if (err < 0) 649 if (err < 0)
672 goto errout; 650 goto errout;
673 651
674 if (gnet_stats_copy_basic(NULL, &d, p->cpu_bstats, &p->tcfc_bstats) < 0 || 652 if (gnet_stats_copy_basic(NULL, &d, p->cpu_bstats, &p->tcfa_bstats) < 0 ||
675 gnet_stats_copy_rate_est(&d, &p->tcfc_bstats, 653 gnet_stats_copy_rate_est(&d, &p->tcfa_bstats,
676 &p->tcfc_rate_est) < 0 || 654 &p->tcfa_rate_est) < 0 ||
677 gnet_stats_copy_queue(&d, p->cpu_qstats, 655 gnet_stats_copy_queue(&d, p->cpu_qstats,
678 &p->tcfc_qstats, 656 &p->tcfa_qstats,
679 p->tcfc_qstats.qlen) < 0) 657 p->tcfa_qstats.qlen) < 0)
680 goto errout; 658 goto errout;
681 659
682 if (gnet_stats_finish_copy(&d) < 0) 660 if (gnet_stats_finish_copy(&d) < 0)
@@ -740,24 +718,11 @@ act_get_notify(struct net *net, u32 portid, struct nlmsghdr *n,
740 return rtnl_unicast(skb, net, portid); 718 return rtnl_unicast(skb, net, portid);
741} 719}
742 720
743static struct tc_action *create_a(int i)
744{
745 struct tc_action *act;
746
747 act = kzalloc(sizeof(*act), GFP_KERNEL);
748 if (act == NULL) {
749 pr_debug("create_a: failed to alloc!\n");
750 return NULL;
751 }
752 act->order = i;
753 INIT_LIST_HEAD(&act->list);
754 return act;
755}
756
757static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla, 721static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
758 struct nlmsghdr *n, u32 portid) 722 struct nlmsghdr *n, u32 portid)
759{ 723{
760 struct nlattr *tb[TCA_ACT_MAX + 1]; 724 struct nlattr *tb[TCA_ACT_MAX + 1];
725 const struct tc_action_ops *ops;
761 struct tc_action *a; 726 struct tc_action *a;
762 int index; 727 int index;
763 int err; 728 int err;
@@ -772,26 +737,19 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla,
772 goto err_out; 737 goto err_out;
773 index = nla_get_u32(tb[TCA_ACT_INDEX]); 738 index = nla_get_u32(tb[TCA_ACT_INDEX]);
774 739
775 err = -ENOMEM;
776 a = create_a(0);
777 if (a == NULL)
778 goto err_out;
779
780 err = -EINVAL; 740 err = -EINVAL;
781 a->ops = tc_lookup_action(tb[TCA_ACT_KIND]); 741 ops = tc_lookup_action(tb[TCA_ACT_KIND]);
782 if (a->ops == NULL) /* could happen in batch of actions */ 742 if (!ops) /* could happen in batch of actions */
783 goto err_free; 743 goto err_out;
784 err = -ENOENT; 744 err = -ENOENT;
785 if (a->ops->lookup(net, a, index) == 0) 745 if (ops->lookup(net, &a, index) == 0)
786 goto err_mod; 746 goto err_mod;
787 747
788 module_put(a->ops->owner); 748 module_put(ops->owner);
789 return a; 749 return a;
790 750
791err_mod: 751err_mod:
792 module_put(a->ops->owner); 752 module_put(ops->owner);
793err_free:
794 kfree(a);
795err_out: 753err_out:
796 return ERR_PTR(err); 754 return ERR_PTR(err);
797} 755}
@@ -816,8 +774,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
816 struct netlink_callback dcb; 774 struct netlink_callback dcb;
817 struct nlattr *nest; 775 struct nlattr *nest;
818 struct nlattr *tb[TCA_ACT_MAX + 1]; 776 struct nlattr *tb[TCA_ACT_MAX + 1];
777 const struct tc_action_ops *ops;
819 struct nlattr *kind; 778 struct nlattr *kind;
820 struct tc_action a;
821 int err = -ENOMEM; 779 int err = -ENOMEM;
822 780
823 skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); 781 skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
@@ -834,10 +792,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
834 792
835 err = -EINVAL; 793 err = -EINVAL;
836 kind = tb[TCA_ACT_KIND]; 794 kind = tb[TCA_ACT_KIND];
837 memset(&a, 0, sizeof(struct tc_action)); 795 ops = tc_lookup_action(kind);
838 INIT_LIST_HEAD(&a.list); 796 if (!ops) /*some idjot trying to flush unknown action */
839 a.ops = tc_lookup_action(kind);
840 if (a.ops == NULL) /*some idjot trying to flush unknown action */
841 goto err_out; 797 goto err_out;
842 798
843 nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION, 799 nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION,
@@ -853,7 +809,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
853 if (nest == NULL) 809 if (nest == NULL)
854 goto out_module_put; 810 goto out_module_put;
855 811
856 err = a.ops->walk(net, skb, &dcb, RTM_DELACTION, &a); 812 err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops);
857 if (err < 0) 813 if (err < 0)
858 goto out_module_put; 814 goto out_module_put;
859 if (err == 0) 815 if (err == 0)
@@ -863,7 +819,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
863 819
864 nlh->nlmsg_len = skb_tail_pointer(skb) - b; 820 nlh->nlmsg_len = skb_tail_pointer(skb) - b;
865 nlh->nlmsg_flags |= NLM_F_ROOT; 821 nlh->nlmsg_flags |= NLM_F_ROOT;
866 module_put(a.ops->owner); 822 module_put(ops->owner);
867 err = rtnetlink_send(skb, net, portid, RTNLGRP_TC, 823 err = rtnetlink_send(skb, net, portid, RTNLGRP_TC,
868 n->nlmsg_flags & NLM_F_ECHO); 824 n->nlmsg_flags & NLM_F_ECHO);
869 if (err > 0) 825 if (err > 0)
@@ -872,7 +828,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla,
872 return err; 828 return err;
873 829
874out_module_put: 830out_module_put:
875 module_put(a.ops->owner); 831 module_put(ops->owner);
876err_out: 832err_out:
877noflush_out: 833noflush_out:
878 kfree_skb(skb); 834 kfree_skb(skb);
@@ -1084,7 +1040,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
1084 unsigned char *b = skb_tail_pointer(skb); 1040 unsigned char *b = skb_tail_pointer(skb);
1085 struct nlattr *nest; 1041 struct nlattr *nest;
1086 struct tc_action_ops *a_o; 1042 struct tc_action_ops *a_o;
1087 struct tc_action a;
1088 int ret = 0; 1043 int ret = 0;
1089 struct tcamsg *t = (struct tcamsg *) nlmsg_data(cb->nlh); 1044 struct tcamsg *t = (struct tcamsg *) nlmsg_data(cb->nlh);
1090 struct nlattr *kind = find_dump_kind(cb->nlh); 1045 struct nlattr *kind = find_dump_kind(cb->nlh);
@@ -1098,9 +1053,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
1098 if (a_o == NULL) 1053 if (a_o == NULL)
1099 return 0; 1054 return 0;
1100 1055
1101 memset(&a, 0, sizeof(struct tc_action));
1102 a.ops = a_o;
1103
1104 nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 1056 nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
1105 cb->nlh->nlmsg_type, sizeof(*t), 0); 1057 cb->nlh->nlmsg_type, sizeof(*t), 0);
1106 if (!nlh) 1058 if (!nlh)
@@ -1114,7 +1066,7 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb)
1114 if (nest == NULL) 1066 if (nest == NULL)
1115 goto out_module_put; 1067 goto out_module_put;
1116 1068
1117 ret = a_o->walk(net, skb, cb, RTM_GETACTION, &a); 1069 ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o);
1118 if (ret < 0) 1070 if (ret < 0)
1119 goto out_module_put; 1071 goto out_module_put;
1120 1072
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index ef74bffa6101..bfa870731e74 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -34,11 +34,12 @@ struct tcf_bpf_cfg {
34}; 34};
35 35
36static int bpf_net_id; 36static int bpf_net_id;
37static struct tc_action_ops act_bpf_ops;
37 38
38static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act, 39static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act,
39 struct tcf_result *res) 40 struct tcf_result *res)
40{ 41{
41 struct tcf_bpf *prog = act->priv; 42 struct tcf_bpf *prog = to_bpf(act);
42 struct bpf_prog *filter; 43 struct bpf_prog *filter;
43 int action, filter_res; 44 int action, filter_res;
44 bool at_ingress = G_TC_AT(skb->tc_verd) & AT_INGRESS; 45 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,
134 int bind, int ref) 135 int bind, int ref)
135{ 136{
136 unsigned char *tp = skb_tail_pointer(skb); 137 unsigned char *tp = skb_tail_pointer(skb);
137 struct tcf_bpf *prog = act->priv; 138 struct tcf_bpf *prog = to_bpf(act);
138 struct tc_act_bpf opt = { 139 struct tc_act_bpf opt = {
139 .index = prog->tcf_index, 140 .index = prog->tcf_index,
140 .refcnt = prog->tcf_refcnt - ref, 141 .refcnt = prog->tcf_refcnt - ref,
@@ -270,7 +271,7 @@ static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf *prog,
270} 271}
271 272
272static int tcf_bpf_init(struct net *net, struct nlattr *nla, 273static int tcf_bpf_init(struct net *net, struct nlattr *nla,
273 struct nlattr *est, struct tc_action *act, 274 struct nlattr *est, struct tc_action **act,
274 int replace, int bind) 275 int replace, int bind)
275{ 276{
276 struct tc_action_net *tn = net_generic(net, bpf_net_id); 277 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,
295 296
296 if (!tcf_hash_check(tn, parm->index, act, bind)) { 297 if (!tcf_hash_check(tn, parm->index, act, bind)) {
297 ret = tcf_hash_create(tn, parm->index, est, act, 298 ret = tcf_hash_create(tn, parm->index, est, act,
298 sizeof(*prog), bind, true); 299 &act_bpf_ops, bind, true);
299 if (ret < 0) 300 if (ret < 0)
300 return ret; 301 return ret;
301 302
@@ -305,7 +306,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
305 if (bind) 306 if (bind)
306 return 0; 307 return 0;
307 308
308 tcf_hash_release(act, bind); 309 tcf_hash_release(*act, bind);
309 if (!replace) 310 if (!replace)
310 return -EEXIST; 311 return -EEXIST;
311 } 312 }
@@ -325,7 +326,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
325 if (ret < 0) 326 if (ret < 0)
326 goto out; 327 goto out;
327 328
328 prog = to_bpf(act); 329 prog = to_bpf(*act);
329 ASSERT_RTNL(); 330 ASSERT_RTNL();
330 331
331 if (res != ACT_P_CREATED) 332 if (res != ACT_P_CREATED)
@@ -343,7 +344,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
343 rcu_assign_pointer(prog->filter, cfg.filter); 344 rcu_assign_pointer(prog->filter, cfg.filter);
344 345
345 if (res == ACT_P_CREATED) { 346 if (res == ACT_P_CREATED) {
346 tcf_hash_insert(tn, act); 347 tcf_hash_insert(tn, *act);
347 } else { 348 } else {
348 /* make sure the program being replaced is no longer executing */ 349 /* make sure the program being replaced is no longer executing */
349 synchronize_rcu(); 350 synchronize_rcu();
@@ -353,7 +354,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
353 return res; 354 return res;
354out: 355out:
355 if (res == ACT_P_CREATED) 356 if (res == ACT_P_CREATED)
356 tcf_hash_cleanup(act, est); 357 tcf_hash_cleanup(*act, est);
357 358
358 return ret; 359 return ret;
359} 360}
@@ -362,20 +363,20 @@ static void tcf_bpf_cleanup(struct tc_action *act, int bind)
362{ 363{
363 struct tcf_bpf_cfg tmp; 364 struct tcf_bpf_cfg tmp;
364 365
365 tcf_bpf_prog_fill_cfg(act->priv, &tmp); 366 tcf_bpf_prog_fill_cfg(to_bpf(act), &tmp);
366 tcf_bpf_cfg_cleanup(&tmp); 367 tcf_bpf_cfg_cleanup(&tmp);
367} 368}
368 369
369static int tcf_bpf_walker(struct net *net, struct sk_buff *skb, 370static int tcf_bpf_walker(struct net *net, struct sk_buff *skb,
370 struct netlink_callback *cb, int type, 371 struct netlink_callback *cb, int type,
371 struct tc_action *a) 372 const struct tc_action_ops *ops)
372{ 373{
373 struct tc_action_net *tn = net_generic(net, bpf_net_id); 374 struct tc_action_net *tn = net_generic(net, bpf_net_id);
374 375
375 return tcf_generic_walker(tn, skb, cb, type, a); 376 return tcf_generic_walker(tn, skb, cb, type, ops);
376} 377}
377 378
378static int tcf_bpf_search(struct net *net, struct tc_action *a, u32 index) 379static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index)
379{ 380{
380 struct tc_action_net *tn = net_generic(net, bpf_net_id); 381 struct tc_action_net *tn = net_generic(net, bpf_net_id);
381 382
@@ -392,6 +393,7 @@ static struct tc_action_ops act_bpf_ops __read_mostly = {
392 .init = tcf_bpf_init, 393 .init = tcf_bpf_init,
393 .walk = tcf_bpf_walker, 394 .walk = tcf_bpf_walker,
394 .lookup = tcf_bpf_search, 395 .lookup = tcf_bpf_search,
396 .size = sizeof(struct tcf_bpf),
395}; 397};
396 398
397static __net_init int bpf_init_net(struct net *net) 399static __net_init int bpf_init_net(struct net *net)
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 35a5270f289d..eae07a2e774d 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -31,6 +31,7 @@
31#define CONNMARK_TAB_MASK 3 31#define CONNMARK_TAB_MASK 3
32 32
33static int connmark_net_id; 33static int connmark_net_id;
34static struct tc_action_ops act_connmark_ops;
34 35
35static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a, 36static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a,
36 struct tcf_result *res) 37 struct tcf_result *res)
@@ -38,7 +39,7 @@ static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a,
38 const struct nf_conntrack_tuple_hash *thash; 39 const struct nf_conntrack_tuple_hash *thash;
39 struct nf_conntrack_tuple tuple; 40 struct nf_conntrack_tuple tuple;
40 enum ip_conntrack_info ctinfo; 41 enum ip_conntrack_info ctinfo;
41 struct tcf_connmark_info *ca = a->priv; 42 struct tcf_connmark_info *ca = to_connmark(a);
42 struct nf_conntrack_zone zone; 43 struct nf_conntrack_zone zone;
43 struct nf_conn *c; 44 struct nf_conn *c;
44 int proto; 45 int proto;
@@ -96,7 +97,7 @@ static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = {
96}; 97};
97 98
98static int tcf_connmark_init(struct net *net, struct nlattr *nla, 99static int tcf_connmark_init(struct net *net, struct nlattr *nla,
99 struct nlattr *est, struct tc_action *a, 100 struct nlattr *est, struct tc_action **a,
100 int ovr, int bind) 101 int ovr, int bind)
101{ 102{
102 struct tc_action_net *tn = net_generic(net, connmark_net_id); 103 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,
116 117
117 if (!tcf_hash_check(tn, parm->index, a, bind)) { 118 if (!tcf_hash_check(tn, parm->index, a, bind)) {
118 ret = tcf_hash_create(tn, parm->index, est, a, 119 ret = tcf_hash_create(tn, parm->index, est, a,
119 sizeof(*ci), bind, false); 120 &act_connmark_ops, bind, false);
120 if (ret) 121 if (ret)
121 return ret; 122 return ret;
122 123
123 ci = to_connmark(a); 124 ci = to_connmark(*a);
124 ci->tcf_action = parm->action; 125 ci->tcf_action = parm->action;
125 ci->net = net; 126 ci->net = net;
126 ci->zone = parm->zone; 127 ci->zone = parm->zone;
127 128
128 tcf_hash_insert(tn, a); 129 tcf_hash_insert(tn, *a);
129 ret = ACT_P_CREATED; 130 ret = ACT_P_CREATED;
130 } else { 131 } else {
131 ci = to_connmark(a); 132 ci = to_connmark(*a);
132 if (bind) 133 if (bind)
133 return 0; 134 return 0;
134 tcf_hash_release(a, bind); 135 tcf_hash_release(*a, bind);
135 if (!ovr) 136 if (!ovr)
136 return -EEXIST; 137 return -EEXIST;
137 /* replacing action and zone */ 138 /* replacing action and zone */
@@ -146,7 +147,7 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
146 int bind, int ref) 147 int bind, int ref)
147{ 148{
148 unsigned char *b = skb_tail_pointer(skb); 149 unsigned char *b = skb_tail_pointer(skb);
149 struct tcf_connmark_info *ci = a->priv; 150 struct tcf_connmark_info *ci = to_connmark(a);
150 151
151 struct tc_connmark opt = { 152 struct tc_connmark opt = {
152 .index = ci->tcf_index, 153 .index = ci->tcf_index,
@@ -173,14 +174,14 @@ nla_put_failure:
173 174
174static int tcf_connmark_walker(struct net *net, struct sk_buff *skb, 175static int tcf_connmark_walker(struct net *net, struct sk_buff *skb,
175 struct netlink_callback *cb, int type, 176 struct netlink_callback *cb, int type,
176 struct tc_action *a) 177 const struct tc_action_ops *ops)
177{ 178{
178 struct tc_action_net *tn = net_generic(net, connmark_net_id); 179 struct tc_action_net *tn = net_generic(net, connmark_net_id);
179 180
180 return tcf_generic_walker(tn, skb, cb, type, a); 181 return tcf_generic_walker(tn, skb, cb, type, ops);
181} 182}
182 183
183static int tcf_connmark_search(struct net *net, struct tc_action *a, u32 index) 184static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 index)
184{ 185{
185 struct tc_action_net *tn = net_generic(net, connmark_net_id); 186 struct tc_action_net *tn = net_generic(net, connmark_net_id);
186 187
@@ -196,6 +197,7 @@ static struct tc_action_ops act_connmark_ops = {
196 .init = tcf_connmark_init, 197 .init = tcf_connmark_init,
197 .walk = tcf_connmark_walker, 198 .walk = tcf_connmark_walker,
198 .lookup = tcf_connmark_search, 199 .lookup = tcf_connmark_search,
200 .size = sizeof(struct tcf_connmark_info),
199}; 201};
200 202
201static __net_init int connmark_init_net(struct net *net) 203static __net_init int connmark_init_net(struct net *net)
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index dcd9ababd351..b5dbf633a863 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -43,9 +43,10 @@ static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = {
43}; 43};
44 44
45static int csum_net_id; 45static int csum_net_id;
46static struct tc_action_ops act_csum_ops;
46 47
47static int tcf_csum_init(struct net *net, struct nlattr *nla, 48static int tcf_csum_init(struct net *net, struct nlattr *nla,
48 struct nlattr *est, struct tc_action *a, int ovr, 49 struct nlattr *est, struct tc_action **a, int ovr,
49 int bind) 50 int bind)
50{ 51{
51 struct tc_action_net *tn = net_generic(net, csum_net_id); 52 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,
67 68
68 if (!tcf_hash_check(tn, parm->index, a, bind)) { 69 if (!tcf_hash_check(tn, parm->index, a, bind)) {
69 ret = tcf_hash_create(tn, parm->index, est, a, 70 ret = tcf_hash_create(tn, parm->index, est, a,
70 sizeof(*p), bind, false); 71 &act_csum_ops, bind, false);
71 if (ret) 72 if (ret)
72 return ret; 73 return ret;
73 ret = ACT_P_CREATED; 74 ret = ACT_P_CREATED;
74 } else { 75 } else {
75 if (bind)/* dont override defaults */ 76 if (bind)/* dont override defaults */
76 return 0; 77 return 0;
77 tcf_hash_release(a, bind); 78 tcf_hash_release(*a, bind);
78 if (!ovr) 79 if (!ovr)
79 return -EEXIST; 80 return -EEXIST;
80 } 81 }
81 82
82 p = to_tcf_csum(a); 83 p = to_tcf_csum(*a);
83 spin_lock_bh(&p->tcf_lock); 84 spin_lock_bh(&p->tcf_lock);
84 p->tcf_action = parm->action; 85 p->tcf_action = parm->action;
85 p->update_flags = parm->update_flags; 86 p->update_flags = parm->update_flags;
86 spin_unlock_bh(&p->tcf_lock); 87 spin_unlock_bh(&p->tcf_lock);
87 88
88 if (ret == ACT_P_CREATED) 89 if (ret == ACT_P_CREATED)
89 tcf_hash_insert(tn, a); 90 tcf_hash_insert(tn, *a);
90 91
91 return ret; 92 return ret;
92} 93}
@@ -496,7 +497,7 @@ fail:
496static int tcf_csum(struct sk_buff *skb, 497static int tcf_csum(struct sk_buff *skb,
497 const struct tc_action *a, struct tcf_result *res) 498 const struct tc_action *a, struct tcf_result *res)
498{ 499{
499 struct tcf_csum *p = a->priv; 500 struct tcf_csum *p = to_tcf_csum(a);
500 int action; 501 int action;
501 u32 update_flags; 502 u32 update_flags;
502 503
@@ -534,7 +535,7 @@ static int tcf_csum_dump(struct sk_buff *skb,
534 struct tc_action *a, int bind, int ref) 535 struct tc_action *a, int bind, int ref)
535{ 536{
536 unsigned char *b = skb_tail_pointer(skb); 537 unsigned char *b = skb_tail_pointer(skb);
537 struct tcf_csum *p = a->priv; 538 struct tcf_csum *p = to_tcf_csum(a);
538 struct tc_csum opt = { 539 struct tc_csum opt = {
539 .update_flags = p->update_flags, 540 .update_flags = p->update_flags,
540 .index = p->tcf_index, 541 .index = p->tcf_index,
@@ -560,14 +561,14 @@ nla_put_failure:
560 561
561static int tcf_csum_walker(struct net *net, struct sk_buff *skb, 562static int tcf_csum_walker(struct net *net, struct sk_buff *skb,
562 struct netlink_callback *cb, int type, 563 struct netlink_callback *cb, int type,
563 struct tc_action *a) 564 const struct tc_action_ops *ops)
564{ 565{
565 struct tc_action_net *tn = net_generic(net, csum_net_id); 566 struct tc_action_net *tn = net_generic(net, csum_net_id);
566 567
567 return tcf_generic_walker(tn, skb, cb, type, a); 568 return tcf_generic_walker(tn, skb, cb, type, ops);
568} 569}
569 570
570static int tcf_csum_search(struct net *net, struct tc_action *a, u32 index) 571static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index)
571{ 572{
572 struct tc_action_net *tn = net_generic(net, csum_net_id); 573 struct tc_action_net *tn = net_generic(net, csum_net_id);
573 574
@@ -583,6 +584,7 @@ static struct tc_action_ops act_csum_ops = {
583 .init = tcf_csum_init, 584 .init = tcf_csum_init,
584 .walk = tcf_csum_walker, 585 .walk = tcf_csum_walker,
585 .lookup = tcf_csum_search, 586 .lookup = tcf_csum_search,
587 .size = sizeof(struct tcf_csum),
586}; 588};
587 589
588static __net_init int csum_init_net(struct net *net) 590static __net_init int csum_init_net(struct net *net)
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 19058a7f3e5c..e24a4093d6f6 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -26,6 +26,7 @@
26#define GACT_TAB_MASK 15 26#define GACT_TAB_MASK 15
27 27
28static int gact_net_id; 28static int gact_net_id;
29static struct tc_action_ops act_gact_ops;
29 30
30#ifdef CONFIG_GACT_PROB 31#ifdef CONFIG_GACT_PROB
31static int gact_net_rand(struct tcf_gact *gact) 32static int gact_net_rand(struct tcf_gact *gact)
@@ -56,7 +57,7 @@ static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = {
56}; 57};
57 58
58static int tcf_gact_init(struct net *net, struct nlattr *nla, 59static int tcf_gact_init(struct net *net, struct nlattr *nla,
59 struct nlattr *est, struct tc_action *a, 60 struct nlattr *est, struct tc_action **a,
60 int ovr, int bind) 61 int ovr, int bind)
61{ 62{
62 struct tc_action_net *tn = net_generic(net, gact_net_id); 63 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,
93 94
94 if (!tcf_hash_check(tn, parm->index, a, bind)) { 95 if (!tcf_hash_check(tn, parm->index, a, bind)) {
95 ret = tcf_hash_create(tn, parm->index, est, a, 96 ret = tcf_hash_create(tn, parm->index, est, a,
96 sizeof(*gact), bind, true); 97 &act_gact_ops, bind, true);
97 if (ret) 98 if (ret)
98 return ret; 99 return ret;
99 ret = ACT_P_CREATED; 100 ret = ACT_P_CREATED;
100 } else { 101 } else {
101 if (bind)/* dont override defaults */ 102 if (bind)/* dont override defaults */
102 return 0; 103 return 0;
103 tcf_hash_release(a, bind); 104 tcf_hash_release(*a, bind);
104 if (!ovr) 105 if (!ovr)
105 return -EEXIST; 106 return -EEXIST;
106 } 107 }
107 108
108 gact = to_gact(a); 109 gact = to_gact(*a);
109 110
110 ASSERT_RTNL(); 111 ASSERT_RTNL();
111 gact->tcf_action = parm->action; 112 gact->tcf_action = parm->action;
@@ -121,14 +122,14 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
121 } 122 }
122#endif 123#endif
123 if (ret == ACT_P_CREATED) 124 if (ret == ACT_P_CREATED)
124 tcf_hash_insert(tn, a); 125 tcf_hash_insert(tn, *a);
125 return ret; 126 return ret;
126} 127}
127 128
128static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, 129static int tcf_gact(struct sk_buff *skb, const struct tc_action *a,
129 struct tcf_result *res) 130 struct tcf_result *res)
130{ 131{
131 struct tcf_gact *gact = a->priv; 132 struct tcf_gact *gact = to_gact(a);
132 int action = READ_ONCE(gact->tcf_action); 133 int action = READ_ONCE(gact->tcf_action);
133 134
134#ifdef CONFIG_GACT_PROB 135#ifdef CONFIG_GACT_PROB
@@ -151,7 +152,7 @@ static int tcf_gact(struct sk_buff *skb, const struct tc_action *a,
151static void tcf_gact_stats_update(struct tc_action *a, u64 bytes, u32 packets, 152static void tcf_gact_stats_update(struct tc_action *a, u64 bytes, u32 packets,
152 u64 lastuse) 153 u64 lastuse)
153{ 154{
154 struct tcf_gact *gact = a->priv; 155 struct tcf_gact *gact = to_gact(a);
155 int action = READ_ONCE(gact->tcf_action); 156 int action = READ_ONCE(gact->tcf_action);
156 struct tcf_t *tm = &gact->tcf_tm; 157 struct tcf_t *tm = &gact->tcf_tm;
157 158
@@ -166,7 +167,7 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a,
166 int bind, int ref) 167 int bind, int ref)
167{ 168{
168 unsigned char *b = skb_tail_pointer(skb); 169 unsigned char *b = skb_tail_pointer(skb);
169 struct tcf_gact *gact = a->priv; 170 struct tcf_gact *gact = to_gact(a);
170 struct tc_gact opt = { 171 struct tc_gact opt = {
171 .index = gact->tcf_index, 172 .index = gact->tcf_index,
172 .refcnt = gact->tcf_refcnt - ref, 173 .refcnt = gact->tcf_refcnt - ref,
@@ -201,14 +202,14 @@ nla_put_failure:
201 202
202static int tcf_gact_walker(struct net *net, struct sk_buff *skb, 203static int tcf_gact_walker(struct net *net, struct sk_buff *skb,
203 struct netlink_callback *cb, int type, 204 struct netlink_callback *cb, int type,
204 struct tc_action *a) 205 const struct tc_action_ops *ops)
205{ 206{
206 struct tc_action_net *tn = net_generic(net, gact_net_id); 207 struct tc_action_net *tn = net_generic(net, gact_net_id);
207 208
208 return tcf_generic_walker(tn, skb, cb, type, a); 209 return tcf_generic_walker(tn, skb, cb, type, ops);
209} 210}
210 211
211static int tcf_gact_search(struct net *net, struct tc_action *a, u32 index) 212static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index)
212{ 213{
213 struct tc_action_net *tn = net_generic(net, gact_net_id); 214 struct tc_action_net *tn = net_generic(net, gact_net_id);
214 215
@@ -225,6 +226,7 @@ static struct tc_action_ops act_gact_ops = {
225 .init = tcf_gact_init, 226 .init = tcf_gact_init,
226 .walk = tcf_gact_walker, 227 .walk = tcf_gact_walker,
227 .lookup = tcf_gact_search, 228 .lookup = tcf_gact_search,
229 .size = sizeof(struct tcf_gact),
228}; 230};
229 231
230static __net_init int gact_init_net(struct net *net) 232static __net_init int gact_init_net(struct net *net)
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 845ab5119c05..141a06eeb1e5 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -37,6 +37,7 @@
37 37
38static int ife_net_id; 38static int ife_net_id;
39static int max_metacnt = IFE_META_MAX + 1; 39static int max_metacnt = IFE_META_MAX + 1;
40static struct tc_action_ops act_ife_ops;
40 41
41static const struct nla_policy ife_policy[TCA_IFE_MAX + 1] = { 42static const struct nla_policy ife_policy[TCA_IFE_MAX + 1] = {
42 [TCA_IFE_PARMS] = { .len = sizeof(struct tc_ife)}, 43 [TCA_IFE_PARMS] = { .len = sizeof(struct tc_ife)},
@@ -364,7 +365,7 @@ out_nlmsg_trim:
364/* under ife->tcf_lock */ 365/* under ife->tcf_lock */
365static void _tcf_ife_cleanup(struct tc_action *a, int bind) 366static void _tcf_ife_cleanup(struct tc_action *a, int bind)
366{ 367{
367 struct tcf_ife_info *ife = a->priv; 368 struct tcf_ife_info *ife = to_ife(a);
368 struct tcf_meta_info *e, *n; 369 struct tcf_meta_info *e, *n;
369 370
370 list_for_each_entry_safe(e, n, &ife->metalist, metalist) { 371 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)
382 383
383static void tcf_ife_cleanup(struct tc_action *a, int bind) 384static void tcf_ife_cleanup(struct tc_action *a, int bind)
384{ 385{
385 struct tcf_ife_info *ife = a->priv; 386 struct tcf_ife_info *ife = to_ife(a);
386 387
387 spin_lock_bh(&ife->tcf_lock); 388 spin_lock_bh(&ife->tcf_lock);
388 _tcf_ife_cleanup(a, bind); 389 _tcf_ife_cleanup(a, bind);
@@ -417,7 +418,7 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb,
417} 418}
418 419
419static int tcf_ife_init(struct net *net, struct nlattr *nla, 420static int tcf_ife_init(struct net *net, struct nlattr *nla,
420 struct nlattr *est, struct tc_action *a, 421 struct nlattr *est, struct tc_action **a,
421 int ovr, int bind) 422 int ovr, int bind)
422{ 423{
423 struct tc_action_net *tn = net_generic(net, ife_net_id); 424 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,
451 **/ 452 **/
452 if (!tb[TCA_IFE_TYPE]) { 453 if (!tb[TCA_IFE_TYPE]) {
453 if (exists) 454 if (exists)
454 tcf_hash_release(a, bind); 455 tcf_hash_release(*a, bind);
455 pr_info("You MUST pass etherype for encoding\n"); 456 pr_info("You MUST pass etherype for encoding\n");
456 return -EINVAL; 457 return -EINVAL;
457 } 458 }
458 } 459 }
459 460
460 if (!exists) { 461 if (!exists) {
461 ret = tcf_hash_create(tn, parm->index, est, a, sizeof(*ife), 462 ret = tcf_hash_create(tn, parm->index, est, a, &act_ife_ops,
462 bind, false); 463 bind, false);
463 if (ret) 464 if (ret)
464 return ret; 465 return ret;
465 ret = ACT_P_CREATED; 466 ret = ACT_P_CREATED;
466 } else { 467 } else {
467 tcf_hash_release(a, bind); 468 tcf_hash_release(*a, bind);
468 if (!ovr) 469 if (!ovr)
469 return -EEXIST; 470 return -EEXIST;
470 } 471 }
471 472
472 ife = to_ife(a); 473 ife = to_ife(*a);
473 ife->flags = parm->flags; 474 ife->flags = parm->flags;
474 475
475 if (parm->flags & IFE_ENCODE) { 476 if (parm->flags & IFE_ENCODE) {
@@ -507,9 +508,9 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
507 if (err) { 508 if (err) {
508metadata_parse_err: 509metadata_parse_err:
509 if (exists) 510 if (exists)
510 tcf_hash_release(a, bind); 511 tcf_hash_release(*a, bind);
511 if (ret == ACT_P_CREATED) 512 if (ret == ACT_P_CREATED)
512 _tcf_ife_cleanup(a, bind); 513 _tcf_ife_cleanup(*a, bind);
513 514
514 if (exists) 515 if (exists)
515 spin_unlock_bh(&ife->tcf_lock); 516 spin_unlock_bh(&ife->tcf_lock);
@@ -529,7 +530,7 @@ metadata_parse_err:
529 err = use_all_metadata(ife); 530 err = use_all_metadata(ife);
530 if (err) { 531 if (err) {
531 if (ret == ACT_P_CREATED) 532 if (ret == ACT_P_CREATED)
532 _tcf_ife_cleanup(a, bind); 533 _tcf_ife_cleanup(*a, bind);
533 534
534 if (exists) 535 if (exists)
535 spin_unlock_bh(&ife->tcf_lock); 536 spin_unlock_bh(&ife->tcf_lock);
@@ -541,7 +542,7 @@ metadata_parse_err:
541 spin_unlock_bh(&ife->tcf_lock); 542 spin_unlock_bh(&ife->tcf_lock);
542 543
543 if (ret == ACT_P_CREATED) 544 if (ret == ACT_P_CREATED)
544 tcf_hash_insert(tn, a); 545 tcf_hash_insert(tn, *a);
545 546
546 return ret; 547 return ret;
547} 548}
@@ -550,7 +551,7 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind,
550 int ref) 551 int ref)
551{ 552{
552 unsigned char *b = skb_tail_pointer(skb); 553 unsigned char *b = skb_tail_pointer(skb);
553 struct tcf_ife_info *ife = a->priv; 554 struct tcf_ife_info *ife = to_ife(a);
554 struct tc_ife opt = { 555 struct tc_ife opt = {
555 .index = ife->tcf_index, 556 .index = ife->tcf_index,
556 .refcnt = ife->tcf_refcnt - ref, 557 .refcnt = ife->tcf_refcnt - ref,
@@ -623,7 +624,7 @@ struct meta_tlvhdr {
623static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a, 624static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a,
624 struct tcf_result *res) 625 struct tcf_result *res)
625{ 626{
626 struct tcf_ife_info *ife = a->priv; 627 struct tcf_ife_info *ife = to_ife(a);
627 int action = ife->tcf_action; 628 int action = ife->tcf_action;
628 struct ifeheadr *ifehdr = (struct ifeheadr *)skb->data; 629 struct ifeheadr *ifehdr = (struct ifeheadr *)skb->data;
629 u16 ifehdrln = ifehdr->metalen; 630 u16 ifehdrln = ifehdr->metalen;
@@ -695,7 +696,7 @@ static int ife_get_sz(struct sk_buff *skb, struct tcf_ife_info *ife)
695static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a, 696static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a,
696 struct tcf_result *res) 697 struct tcf_result *res)
697{ 698{
698 struct tcf_ife_info *ife = a->priv; 699 struct tcf_ife_info *ife = to_ife(a);
699 int action = ife->tcf_action; 700 int action = ife->tcf_action;
700 struct ethhdr *oethh; /* outer ether header */ 701 struct ethhdr *oethh; /* outer ether header */
701 struct ethhdr *iethh; /* inner eth header */ 702 struct ethhdr *iethh; /* inner eth header */
@@ -799,7 +800,7 @@ static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a,
799static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a, 800static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a,
800 struct tcf_result *res) 801 struct tcf_result *res)
801{ 802{
802 struct tcf_ife_info *ife = a->priv; 803 struct tcf_ife_info *ife = to_ife(a);
803 804
804 if (ife->flags & IFE_ENCODE) 805 if (ife->flags & IFE_ENCODE)
805 return tcf_ife_encode(skb, a, res); 806 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,
819 820
820static int tcf_ife_walker(struct net *net, struct sk_buff *skb, 821static int tcf_ife_walker(struct net *net, struct sk_buff *skb,
821 struct netlink_callback *cb, int type, 822 struct netlink_callback *cb, int type,
822 struct tc_action *a) 823 const struct tc_action_ops *ops)
823{ 824{
824 struct tc_action_net *tn = net_generic(net, ife_net_id); 825 struct tc_action_net *tn = net_generic(net, ife_net_id);
825 826
826 return tcf_generic_walker(tn, skb, cb, type, a); 827 return tcf_generic_walker(tn, skb, cb, type, ops);
827} 828}
828 829
829static int tcf_ife_search(struct net *net, struct tc_action *a, u32 index) 830static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index)
830{ 831{
831 struct tc_action_net *tn = net_generic(net, ife_net_id); 832 struct tc_action_net *tn = net_generic(net, ife_net_id);
832 833
@@ -843,6 +844,7 @@ static struct tc_action_ops act_ife_ops = {
843 .init = tcf_ife_init, 844 .init = tcf_ife_init,
844 .walk = tcf_ife_walker, 845 .walk = tcf_ife_walker,
845 .lookup = tcf_ife_search, 846 .lookup = tcf_ife_search,
847 .size = sizeof(struct tcf_ife_info),
846}; 848};
847 849
848static __net_init int ife_init_net(struct net *net) 850static __net_init int ife_init_net(struct net *net)
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index b8c50600697a..378c1c976058 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -31,8 +31,10 @@
31#define IPT_TAB_MASK 15 31#define IPT_TAB_MASK 15
32 32
33static int ipt_net_id; 33static int ipt_net_id;
34static struct tc_action_ops act_ipt_ops;
34 35
35static int xt_net_id; 36static int xt_net_id;
37static struct tc_action_ops act_xt_ops;
36 38
37static int ipt_init_target(struct xt_entry_target *t, char *table, 39static int ipt_init_target(struct xt_entry_target *t, char *table,
38 unsigned int hook) 40 unsigned int hook)
@@ -90,8 +92,8 @@ static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = {
90}; 92};
91 93
92static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, 94static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
93 struct nlattr *est, struct tc_action *a, int ovr, 95 struct nlattr *est, struct tc_action **a,
94 int bind) 96 const struct tc_action_ops *ops, int ovr, int bind)
95{ 97{
96 struct nlattr *tb[TCA_IPT_MAX + 1]; 98 struct nlattr *tb[TCA_IPT_MAX + 1];
97 struct tcf_ipt *ipt; 99 struct tcf_ipt *ipt;
@@ -118,19 +120,19 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
118 120
119 if (tb[TCA_IPT_HOOK] == NULL || tb[TCA_IPT_TARG] == NULL) { 121 if (tb[TCA_IPT_HOOK] == NULL || tb[TCA_IPT_TARG] == NULL) {
120 if (exists) 122 if (exists)
121 tcf_hash_release(a, bind); 123 tcf_hash_release(*a, bind);
122 return -EINVAL; 124 return -EINVAL;
123 } 125 }
124 126
125 td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]); 127 td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]);
126 if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) { 128 if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) {
127 if (exists) 129 if (exists)
128 tcf_hash_release(a, bind); 130 tcf_hash_release(*a, bind);
129 return -EINVAL; 131 return -EINVAL;
130 } 132 }
131 133
132 if (!exists) { 134 if (!exists) {
133 ret = tcf_hash_create(tn, index, est, a, sizeof(*ipt), bind, 135 ret = tcf_hash_create(tn, index, est, a, ops, bind,
134 false); 136 false);
135 if (ret) 137 if (ret)
136 return ret; 138 return ret;
@@ -138,13 +140,11 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
138 } else { 140 } else {
139 if (bind)/* dont override defaults */ 141 if (bind)/* dont override defaults */
140 return 0; 142 return 0;
141 tcf_hash_release(a, bind); 143 tcf_hash_release(*a, bind);
142 144
143 if (!ovr) 145 if (!ovr)
144 return -EEXIST; 146 return -EEXIST;
145 } 147 }
146 ipt = to_ipt(a);
147
148 hook = nla_get_u32(tb[TCA_IPT_HOOK]); 148 hook = nla_get_u32(tb[TCA_IPT_HOOK]);
149 149
150 err = -ENOMEM; 150 err = -ENOMEM;
@@ -163,6 +163,8 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
163 if (err < 0) 163 if (err < 0)
164 goto err3; 164 goto err3;
165 165
166 ipt = to_ipt(*a);
167
166 spin_lock_bh(&ipt->tcf_lock); 168 spin_lock_bh(&ipt->tcf_lock);
167 if (ret != ACT_P_CREATED) { 169 if (ret != ACT_P_CREATED) {
168 ipt_destroy_target(ipt->tcfi_t); 170 ipt_destroy_target(ipt->tcfi_t);
@@ -174,7 +176,7 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
174 ipt->tcfi_hook = hook; 176 ipt->tcfi_hook = hook;
175 spin_unlock_bh(&ipt->tcf_lock); 177 spin_unlock_bh(&ipt->tcf_lock);
176 if (ret == ACT_P_CREATED) 178 if (ret == ACT_P_CREATED)
177 tcf_hash_insert(tn, a); 179 tcf_hash_insert(tn, *a);
178 return ret; 180 return ret;
179 181
180err3: 182err3:
@@ -183,33 +185,33 @@ err2:
183 kfree(tname); 185 kfree(tname);
184err1: 186err1:
185 if (ret == ACT_P_CREATED) 187 if (ret == ACT_P_CREATED)
186 tcf_hash_cleanup(a, est); 188 tcf_hash_cleanup(*a, est);
187 return err; 189 return err;
188} 190}
189 191
190static int tcf_ipt_init(struct net *net, struct nlattr *nla, 192static int tcf_ipt_init(struct net *net, struct nlattr *nla,
191 struct nlattr *est, struct tc_action *a, int ovr, 193 struct nlattr *est, struct tc_action **a, int ovr,
192 int bind) 194 int bind)
193{ 195{
194 struct tc_action_net *tn = net_generic(net, ipt_net_id); 196 struct tc_action_net *tn = net_generic(net, ipt_net_id);
195 197
196 return __tcf_ipt_init(tn, nla, est, a, ovr, bind); 198 return __tcf_ipt_init(tn, nla, est, a, &act_ipt_ops, ovr, bind);
197} 199}
198 200
199static int tcf_xt_init(struct net *net, struct nlattr *nla, 201static int tcf_xt_init(struct net *net, struct nlattr *nla,
200 struct nlattr *est, struct tc_action *a, int ovr, 202 struct nlattr *est, struct tc_action **a, int ovr,
201 int bind) 203 int bind)
202{ 204{
203 struct tc_action_net *tn = net_generic(net, xt_net_id); 205 struct tc_action_net *tn = net_generic(net, xt_net_id);
204 206
205 return __tcf_ipt_init(tn, nla, est, a, ovr, bind); 207 return __tcf_ipt_init(tn, nla, est, a, &act_xt_ops, ovr, bind);
206} 208}
207 209
208static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a, 210static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a,
209 struct tcf_result *res) 211 struct tcf_result *res)
210{ 212{
211 int ret = 0, result = 0; 213 int ret = 0, result = 0;
212 struct tcf_ipt *ipt = a->priv; 214 struct tcf_ipt *ipt = to_ipt(a);
213 struct xt_action_param par; 215 struct xt_action_param par;
214 216
215 if (skb_unclone(skb, GFP_ATOMIC)) 217 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,
259 int ref) 261 int ref)
260{ 262{
261 unsigned char *b = skb_tail_pointer(skb); 263 unsigned char *b = skb_tail_pointer(skb);
262 struct tcf_ipt *ipt = a->priv; 264 struct tcf_ipt *ipt = to_ipt(a);
263 struct xt_entry_target *t; 265 struct xt_entry_target *t;
264 struct tcf_t tm; 266 struct tcf_t tm;
265 struct tc_cnt c; 267 struct tc_cnt c;
@@ -299,14 +301,14 @@ nla_put_failure:
299 301
300static int tcf_ipt_walker(struct net *net, struct sk_buff *skb, 302static int tcf_ipt_walker(struct net *net, struct sk_buff *skb,
301 struct netlink_callback *cb, int type, 303 struct netlink_callback *cb, int type,
302 struct tc_action *a) 304 const struct tc_action_ops *ops)
303{ 305{
304 struct tc_action_net *tn = net_generic(net, ipt_net_id); 306 struct tc_action_net *tn = net_generic(net, ipt_net_id);
305 307
306 return tcf_generic_walker(tn, skb, cb, type, a); 308 return tcf_generic_walker(tn, skb, cb, type, ops);
307} 309}
308 310
309static int tcf_ipt_search(struct net *net, struct tc_action *a, u32 index) 311static int tcf_ipt_search(struct net *net, struct tc_action **a, u32 index)
310{ 312{
311 struct tc_action_net *tn = net_generic(net, ipt_net_id); 313 struct tc_action_net *tn = net_generic(net, ipt_net_id);
312 314
@@ -323,6 +325,7 @@ static struct tc_action_ops act_ipt_ops = {
323 .init = tcf_ipt_init, 325 .init = tcf_ipt_init,
324 .walk = tcf_ipt_walker, 326 .walk = tcf_ipt_walker,
325 .lookup = tcf_ipt_search, 327 .lookup = tcf_ipt_search,
328 .size = sizeof(struct tcf_ipt),
326}; 329};
327 330
328static __net_init int ipt_init_net(struct net *net) 331static __net_init int ipt_init_net(struct net *net)
@@ -348,14 +351,14 @@ static struct pernet_operations ipt_net_ops = {
348 351
349static int tcf_xt_walker(struct net *net, struct sk_buff *skb, 352static int tcf_xt_walker(struct net *net, struct sk_buff *skb,
350 struct netlink_callback *cb, int type, 353 struct netlink_callback *cb, int type,
351 struct tc_action *a) 354 const struct tc_action_ops *ops)
352{ 355{
353 struct tc_action_net *tn = net_generic(net, xt_net_id); 356 struct tc_action_net *tn = net_generic(net, xt_net_id);
354 357
355 return tcf_generic_walker(tn, skb, cb, type, a); 358 return tcf_generic_walker(tn, skb, cb, type, ops);
356} 359}
357 360
358static int tcf_xt_search(struct net *net, struct tc_action *a, u32 index) 361static int tcf_xt_search(struct net *net, struct tc_action **a, u32 index)
359{ 362{
360 struct tc_action_net *tn = net_generic(net, xt_net_id); 363 struct tc_action_net *tn = net_generic(net, xt_net_id);
361 364
@@ -372,6 +375,7 @@ static struct tc_action_ops act_xt_ops = {
372 .init = tcf_xt_init, 375 .init = tcf_xt_init,
373 .walk = tcf_xt_walker, 376 .walk = tcf_xt_walker,
374 .lookup = tcf_xt_search, 377 .lookup = tcf_xt_search,
378 .size = sizeof(struct tcf_ipt),
375}; 379};
376 380
377static __net_init int xt_init_net(struct net *net) 381static __net_init int xt_init_net(struct net *net)
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 70cfbbf96af2..6038c85d92f5 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -52,9 +52,10 @@ static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
52}; 52};
53 53
54static int mirred_net_id; 54static int mirred_net_id;
55static struct tc_action_ops act_mirred_ops;
55 56
56static int tcf_mirred_init(struct net *net, struct nlattr *nla, 57static int tcf_mirred_init(struct net *net, struct nlattr *nla,
57 struct nlattr *est, struct tc_action *a, int ovr, 58 struct nlattr *est, struct tc_action **a, int ovr,
58 int bind) 59 int bind)
59{ 60{
60 struct tc_action_net *tn = net_generic(net, mirred_net_id); 61 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,
84 break; 85 break;
85 default: 86 default:
86 if (exists) 87 if (exists)
87 tcf_hash_release(a, bind); 88 tcf_hash_release(*a, bind);
88 return -EINVAL; 89 return -EINVAL;
89 } 90 }
90 if (parm->ifindex) { 91 if (parm->ifindex) {
91 dev = __dev_get_by_index(net, parm->ifindex); 92 dev = __dev_get_by_index(net, parm->ifindex);
92 if (dev == NULL) { 93 if (dev == NULL) {
93 if (exists) 94 if (exists)
94 tcf_hash_release(a, bind); 95 tcf_hash_release(*a, bind);
95 return -ENODEV; 96 return -ENODEV;
96 } 97 }
97 switch (dev->type) { 98 switch (dev->type) {
@@ -115,16 +116,16 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
115 if (dev == NULL) 116 if (dev == NULL)
116 return -EINVAL; 117 return -EINVAL;
117 ret = tcf_hash_create(tn, parm->index, est, a, 118 ret = tcf_hash_create(tn, parm->index, est, a,
118 sizeof(*m), bind, true); 119 &act_mirred_ops, bind, true);
119 if (ret) 120 if (ret)
120 return ret; 121 return ret;
121 ret = ACT_P_CREATED; 122 ret = ACT_P_CREATED;
122 } else { 123 } else {
123 tcf_hash_release(a, bind); 124 tcf_hash_release(*a, bind);
124 if (!ovr) 125 if (!ovr)
125 return -EEXIST; 126 return -EEXIST;
126 } 127 }
127 m = to_mirred(a); 128 m = to_mirred(*a);
128 129
129 ASSERT_RTNL(); 130 ASSERT_RTNL();
130 m->tcf_action = parm->action; 131 m->tcf_action = parm->action;
@@ -142,7 +143,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
142 spin_lock_bh(&mirred_list_lock); 143 spin_lock_bh(&mirred_list_lock);
143 list_add(&m->tcfm_list, &mirred_list); 144 list_add(&m->tcfm_list, &mirred_list);
144 spin_unlock_bh(&mirred_list_lock); 145 spin_unlock_bh(&mirred_list_lock);
145 tcf_hash_insert(tn, a); 146 tcf_hash_insert(tn, *a);
146 } 147 }
147 148
148 return ret; 149 return ret;
@@ -151,7 +152,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
151static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a, 152static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
152 struct tcf_result *res) 153 struct tcf_result *res)
153{ 154{
154 struct tcf_mirred *m = a->priv; 155 struct tcf_mirred *m = to_mirred(a);
155 struct net_device *dev; 156 struct net_device *dev;
156 struct sk_buff *skb2; 157 struct sk_buff *skb2;
157 int retval, err; 158 int retval, err;
@@ -206,7 +207,7 @@ out:
206static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) 207static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
207{ 208{
208 unsigned char *b = skb_tail_pointer(skb); 209 unsigned char *b = skb_tail_pointer(skb);
209 struct tcf_mirred *m = a->priv; 210 struct tcf_mirred *m = to_mirred(a);
210 struct tc_mirred opt = { 211 struct tc_mirred opt = {
211 .index = m->tcf_index, 212 .index = m->tcf_index,
212 .action = m->tcf_action, 213 .action = m->tcf_action,
@@ -232,14 +233,14 @@ nla_put_failure:
232 233
233static int tcf_mirred_walker(struct net *net, struct sk_buff *skb, 234static int tcf_mirred_walker(struct net *net, struct sk_buff *skb,
234 struct netlink_callback *cb, int type, 235 struct netlink_callback *cb, int type,
235 struct tc_action *a) 236 const struct tc_action_ops *ops)
236{ 237{
237 struct tc_action_net *tn = net_generic(net, mirred_net_id); 238 struct tc_action_net *tn = net_generic(net, mirred_net_id);
238 239
239 return tcf_generic_walker(tn, skb, cb, type, a); 240 return tcf_generic_walker(tn, skb, cb, type, ops);
240} 241}
241 242
242static int tcf_mirred_search(struct net *net, struct tc_action *a, u32 index) 243static int tcf_mirred_search(struct net *net, struct tc_action **a, u32 index)
243{ 244{
244 struct tc_action_net *tn = net_generic(net, mirred_net_id); 245 struct tc_action_net *tn = net_generic(net, mirred_net_id);
245 246
@@ -284,6 +285,7 @@ static struct tc_action_ops act_mirred_ops = {
284 .init = tcf_mirred_init, 285 .init = tcf_mirred_init,
285 .walk = tcf_mirred_walker, 286 .walk = tcf_mirred_walker,
286 .lookup = tcf_mirred_search, 287 .lookup = tcf_mirred_search,
288 .size = sizeof(struct tcf_mirred),
287}; 289};
288 290
289static __net_init int mirred_init_net(struct net *net) 291static __net_init int mirred_init_net(struct net *net)
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index 06ccb03f25da..8e8b0cc30704 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -32,13 +32,14 @@
32#define NAT_TAB_MASK 15 32#define NAT_TAB_MASK 15
33 33
34static int nat_net_id; 34static int nat_net_id;
35static struct tc_action_ops act_nat_ops;
35 36
36static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = { 37static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
37 [TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) }, 38 [TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) },
38}; 39};
39 40
40static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, 41static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
41 struct tc_action *a, int ovr, int bind) 42 struct tc_action **a, int ovr, int bind)
42{ 43{
43 struct tc_action_net *tn = net_generic(net, nat_net_id); 44 struct tc_action_net *tn = net_generic(net, nat_net_id);
44 struct nlattr *tb[TCA_NAT_MAX + 1]; 45 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,
59 60
60 if (!tcf_hash_check(tn, parm->index, a, bind)) { 61 if (!tcf_hash_check(tn, parm->index, a, bind)) {
61 ret = tcf_hash_create(tn, parm->index, est, a, 62 ret = tcf_hash_create(tn, parm->index, est, a,
62 sizeof(*p), bind, false); 63 &act_nat_ops, bind, false);
63 if (ret) 64 if (ret)
64 return ret; 65 return ret;
65 ret = ACT_P_CREATED; 66 ret = ACT_P_CREATED;
66 } else { 67 } else {
67 if (bind) 68 if (bind)
68 return 0; 69 return 0;
69 tcf_hash_release(a, bind); 70 tcf_hash_release(*a, bind);
70 if (!ovr) 71 if (!ovr)
71 return -EEXIST; 72 return -EEXIST;
72 } 73 }
73 p = to_tcf_nat(a); 74 p = to_tcf_nat(*a);
74 75
75 spin_lock_bh(&p->tcf_lock); 76 spin_lock_bh(&p->tcf_lock);
76 p->old_addr = parm->old_addr; 77 p->old_addr = parm->old_addr;
@@ -82,7 +83,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
82 spin_unlock_bh(&p->tcf_lock); 83 spin_unlock_bh(&p->tcf_lock);
83 84
84 if (ret == ACT_P_CREATED) 85 if (ret == ACT_P_CREATED)
85 tcf_hash_insert(tn, a); 86 tcf_hash_insert(tn, *a);
86 87
87 return ret; 88 return ret;
88} 89}
@@ -90,7 +91,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
90static int tcf_nat(struct sk_buff *skb, const struct tc_action *a, 91static int tcf_nat(struct sk_buff *skb, const struct tc_action *a,
91 struct tcf_result *res) 92 struct tcf_result *res)
92{ 93{
93 struct tcf_nat *p = a->priv; 94 struct tcf_nat *p = to_tcf_nat(a);
94 struct iphdr *iph; 95 struct iphdr *iph;
95 __be32 old_addr; 96 __be32 old_addr;
96 __be32 new_addr; 97 __be32 new_addr;
@@ -248,7 +249,7 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a,
248 int bind, int ref) 249 int bind, int ref)
249{ 250{
250 unsigned char *b = skb_tail_pointer(skb); 251 unsigned char *b = skb_tail_pointer(skb);
251 struct tcf_nat *p = a->priv; 252 struct tcf_nat *p = to_tcf_nat(a);
252 struct tc_nat opt = { 253 struct tc_nat opt = {
253 .old_addr = p->old_addr, 254 .old_addr = p->old_addr,
254 .new_addr = p->new_addr, 255 .new_addr = p->new_addr,
@@ -278,14 +279,14 @@ nla_put_failure:
278 279
279static int tcf_nat_walker(struct net *net, struct sk_buff *skb, 280static int tcf_nat_walker(struct net *net, struct sk_buff *skb,
280 struct netlink_callback *cb, int type, 281 struct netlink_callback *cb, int type,
281 struct tc_action *a) 282 const struct tc_action_ops *ops)
282{ 283{
283 struct tc_action_net *tn = net_generic(net, nat_net_id); 284 struct tc_action_net *tn = net_generic(net, nat_net_id);
284 285
285 return tcf_generic_walker(tn, skb, cb, type, a); 286 return tcf_generic_walker(tn, skb, cb, type, ops);
286} 287}
287 288
288static int tcf_nat_search(struct net *net, struct tc_action *a, u32 index) 289static int tcf_nat_search(struct net *net, struct tc_action **a, u32 index)
289{ 290{
290 struct tc_action_net *tn = net_generic(net, nat_net_id); 291 struct tc_action_net *tn = net_generic(net, nat_net_id);
291 292
@@ -301,6 +302,7 @@ static struct tc_action_ops act_nat_ops = {
301 .init = tcf_nat_init, 302 .init = tcf_nat_init,
302 .walk = tcf_nat_walker, 303 .walk = tcf_nat_walker,
303 .lookup = tcf_nat_search, 304 .lookup = tcf_nat_search,
305 .size = sizeof(struct tcf_nat),
304}; 306};
305 307
306static __net_init int nat_init_net(struct net *net) 308static __net_init int nat_init_net(struct net *net)
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 82d3c1479029..b54d56d4959b 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -26,13 +26,14 @@
26#define PEDIT_TAB_MASK 15 26#define PEDIT_TAB_MASK 15
27 27
28static int pedit_net_id; 28static int pedit_net_id;
29static struct tc_action_ops act_pedit_ops;
29 30
30static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = { 31static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = {
31 [TCA_PEDIT_PARMS] = { .len = sizeof(struct tc_pedit) }, 32 [TCA_PEDIT_PARMS] = { .len = sizeof(struct tc_pedit) },
32}; 33};
33 34
34static int tcf_pedit_init(struct net *net, struct nlattr *nla, 35static int tcf_pedit_init(struct net *net, struct nlattr *nla,
35 struct nlattr *est, struct tc_action *a, 36 struct nlattr *est, struct tc_action **a,
36 int ovr, int bind) 37 int ovr, int bind)
37{ 38{
38 struct tc_action_net *tn = net_generic(net, pedit_net_id); 39 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,
61 if (!parm->nkeys) 62 if (!parm->nkeys)
62 return -EINVAL; 63 return -EINVAL;
63 ret = tcf_hash_create(tn, parm->index, est, a, 64 ret = tcf_hash_create(tn, parm->index, est, a,
64 sizeof(*p), bind, false); 65 &act_pedit_ops, bind, false);
65 if (ret) 66 if (ret)
66 return ret; 67 return ret;
67 p = to_pedit(a); 68 p = to_pedit(*a);
68 keys = kmalloc(ksize, GFP_KERNEL); 69 keys = kmalloc(ksize, GFP_KERNEL);
69 if (keys == NULL) { 70 if (keys == NULL) {
70 tcf_hash_cleanup(a, est); 71 tcf_hash_cleanup(*a, est);
71 return -ENOMEM; 72 return -ENOMEM;
72 } 73 }
73 ret = ACT_P_CREATED; 74 ret = ACT_P_CREATED;
74 } else { 75 } else {
75 if (bind) 76 if (bind)
76 return 0; 77 return 0;
77 tcf_hash_release(a, bind); 78 tcf_hash_release(*a, bind);
78 if (!ovr) 79 if (!ovr)
79 return -EEXIST; 80 return -EEXIST;
80 p = to_pedit(a); 81 p = to_pedit(*a);
81 if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) { 82 if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) {
82 keys = kmalloc(ksize, GFP_KERNEL); 83 keys = kmalloc(ksize, GFP_KERNEL);
83 if (keys == NULL) 84 if (keys == NULL)
@@ -96,13 +97,13 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
96 memcpy(p->tcfp_keys, parm->keys, ksize); 97 memcpy(p->tcfp_keys, parm->keys, ksize);
97 spin_unlock_bh(&p->tcf_lock); 98 spin_unlock_bh(&p->tcf_lock);
98 if (ret == ACT_P_CREATED) 99 if (ret == ACT_P_CREATED)
99 tcf_hash_insert(tn, a); 100 tcf_hash_insert(tn, *a);
100 return ret; 101 return ret;
101} 102}
102 103
103static void tcf_pedit_cleanup(struct tc_action *a, int bind) 104static void tcf_pedit_cleanup(struct tc_action *a, int bind)
104{ 105{
105 struct tcf_pedit *p = a->priv; 106 struct tcf_pedit *p = to_pedit(a);
106 struct tc_pedit_key *keys = p->tcfp_keys; 107 struct tc_pedit_key *keys = p->tcfp_keys;
107 kfree(keys); 108 kfree(keys);
108} 109}
@@ -110,7 +111,7 @@ static void tcf_pedit_cleanup(struct tc_action *a, int bind)
110static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a, 111static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a,
111 struct tcf_result *res) 112 struct tcf_result *res)
112{ 113{
113 struct tcf_pedit *p = a->priv; 114 struct tcf_pedit *p = to_pedit(a);
114 int i; 115 int i;
115 unsigned int off; 116 unsigned int off;
116 117
@@ -177,7 +178,7 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
177 int bind, int ref) 178 int bind, int ref)
178{ 179{
179 unsigned char *b = skb_tail_pointer(skb); 180 unsigned char *b = skb_tail_pointer(skb);
180 struct tcf_pedit *p = a->priv; 181 struct tcf_pedit *p = to_pedit(a);
181 struct tc_pedit *opt; 182 struct tc_pedit *opt;
182 struct tcf_t t; 183 struct tcf_t t;
183 int s; 184 int s;
@@ -216,14 +217,14 @@ nla_put_failure:
216 217
217static int tcf_pedit_walker(struct net *net, struct sk_buff *skb, 218static int tcf_pedit_walker(struct net *net, struct sk_buff *skb,
218 struct netlink_callback *cb, int type, 219 struct netlink_callback *cb, int type,
219 struct tc_action *a) 220 const struct tc_action_ops *ops)
220{ 221{
221 struct tc_action_net *tn = net_generic(net, pedit_net_id); 222 struct tc_action_net *tn = net_generic(net, pedit_net_id);
222 223
223 return tcf_generic_walker(tn, skb, cb, type, a); 224 return tcf_generic_walker(tn, skb, cb, type, ops);
224} 225}
225 226
226static int tcf_pedit_search(struct net *net, struct tc_action *a, u32 index) 227static int tcf_pedit_search(struct net *net, struct tc_action **a, u32 index)
227{ 228{
228 struct tc_action_net *tn = net_generic(net, pedit_net_id); 229 struct tc_action_net *tn = net_generic(net, pedit_net_id);
229 230
@@ -240,6 +241,7 @@ static struct tc_action_ops act_pedit_ops = {
240 .init = tcf_pedit_init, 241 .init = tcf_pedit_init,
241 .walk = tcf_pedit_walker, 242 .walk = tcf_pedit_walker,
242 .lookup = tcf_pedit_search, 243 .lookup = tcf_pedit_search,
244 .size = sizeof(struct tcf_pedit),
243}; 245};
244 246
245static __net_init int pedit_init_net(struct net *net) 247static __net_init int pedit_init_net(struct net *net)
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 1e8ede3955f4..b3c7e975fc9e 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -23,7 +23,7 @@
23#include <net/netlink.h> 23#include <net/netlink.h>
24 24
25struct tcf_police { 25struct tcf_police {
26 struct tcf_common common; 26 struct tc_action common;
27 int tcfp_result; 27 int tcfp_result;
28 u32 tcfp_ewma_rate; 28 u32 tcfp_ewma_rate;
29 s64 tcfp_burst; 29 s64 tcfp_burst;
@@ -37,8 +37,8 @@ struct tcf_police {
37 struct psched_ratecfg peak; 37 struct psched_ratecfg peak;
38 bool peak_present; 38 bool peak_present;
39}; 39};
40#define to_police(pc) \ 40
41 container_of(pc->priv, struct tcf_police, common) 41#define to_police(pc) ((struct tcf_police *)pc)
42 42
43#define POL_TAB_MASK 15 43#define POL_TAB_MASK 15
44 44
@@ -56,15 +56,14 @@ struct tc_police_compat {
56/* Each policer is serialized by its individual spinlock */ 56/* Each policer is serialized by its individual spinlock */
57 57
58static int police_net_id; 58static int police_net_id;
59static struct tc_action_ops act_police_ops;
59 60
60static int tcf_act_police_walker(struct net *net, struct sk_buff *skb, 61static int tcf_act_police_walker(struct net *net, struct sk_buff *skb,
61 struct netlink_callback *cb, int type, 62 struct netlink_callback *cb, int type,
62 struct tc_action *a) 63 const struct tc_action_ops *ops)
63{ 64{
64 struct tc_action_net *tn = net_generic(net, police_net_id); 65 struct tc_action_net *tn = net_generic(net, police_net_id);
65 struct tcf_hashinfo *hinfo = tn->hinfo; 66 struct tcf_hashinfo *hinfo = tn->hinfo;
66 struct hlist_head *head;
67 struct tcf_common *p;
68 int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; 67 int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
69 struct nlattr *nest; 68 struct nlattr *nest;
70 69
@@ -73,21 +72,22 @@ static int tcf_act_police_walker(struct net *net, struct sk_buff *skb,
73 s_i = cb->args[0]; 72 s_i = cb->args[0];
74 73
75 for (i = 0; i < (POL_TAB_MASK + 1); i++) { 74 for (i = 0; i < (POL_TAB_MASK + 1); i++) {
75 struct hlist_head *head;
76 struct tc_action *p;
77
76 head = &hinfo->htab[tcf_hash(i, POL_TAB_MASK)]; 78 head = &hinfo->htab[tcf_hash(i, POL_TAB_MASK)];
77 79
78 hlist_for_each_entry_rcu(p, head, tcfc_head) { 80 hlist_for_each_entry_rcu(p, head, tcfa_head) {
79 index++; 81 index++;
80 if (index < s_i) 82 if (index < s_i)
81 continue; 83 continue;
82 a->priv = p; 84 nest = nla_nest_start(skb, index);
83 a->order = index;
84 nest = nla_nest_start(skb, a->order);
85 if (nest == NULL) 85 if (nest == NULL)
86 goto nla_put_failure; 86 goto nla_put_failure;
87 if (type == RTM_DELACTION) 87 if (type == RTM_DELACTION)
88 err = tcf_action_dump_1(skb, a, 0, 1); 88 err = tcf_action_dump_1(skb, p, 0, 1);
89 else 89 else
90 err = tcf_action_dump_1(skb, a, 0, 0); 90 err = tcf_action_dump_1(skb, p, 0, 0);
91 if (err < 0) { 91 if (err < 0) {
92 index--; 92 index--;
93 nla_nest_cancel(skb, nest); 93 nla_nest_cancel(skb, nest);
@@ -116,7 +116,7 @@ static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
116}; 116};
117 117
118static int tcf_act_police_init(struct net *net, struct nlattr *nla, 118static int tcf_act_police_init(struct net *net, struct nlattr *nla,
119 struct nlattr *est, struct tc_action *a, 119 struct nlattr *est, struct tc_action **a,
120 int ovr, int bind) 120 int ovr, int bind)
121{ 121{
122 int ret = 0, err; 122 int ret = 0, err;
@@ -142,13 +142,7 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
142 parm = nla_data(tb[TCA_POLICE_TBF]); 142 parm = nla_data(tb[TCA_POLICE_TBF]);
143 143
144 if (parm->index) { 144 if (parm->index) {
145 if (tcf_hash_search(tn, a, parm->index)) { 145 if (tcf_hash_check(tn, parm->index, a, bind)) {
146 police = to_police(a);
147 if (bind) {
148 police->tcf_bindcnt += 1;
149 police->tcf_refcnt += 1;
150 return 0;
151 }
152 if (ovr) 146 if (ovr)
153 goto override; 147 goto override;
154 /* not replacing */ 148 /* not replacing */
@@ -156,14 +150,14 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
156 } 150 }
157 } else { 151 } else {
158 ret = tcf_hash_create(tn, parm->index, NULL, a, 152 ret = tcf_hash_create(tn, parm->index, NULL, a,
159 sizeof(*police), bind, false); 153 &act_police_ops, bind, false);
160 if (ret) 154 if (ret)
161 return ret; 155 return ret;
162 ret = ACT_P_CREATED; 156 ret = ACT_P_CREATED;
163 } 157 }
164 158
165 police = to_police(a);
166override: 159override:
160 police = to_police(*a);
167 if (parm->rate.rate) { 161 if (parm->rate.rate) {
168 err = -ENOMEM; 162 err = -ENOMEM;
169 R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]); 163 R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]);
@@ -235,7 +229,7 @@ override:
235 return ret; 229 return ret;
236 230
237 police->tcfp_t_c = ktime_get_ns(); 231 police->tcfp_t_c = ktime_get_ns();
238 tcf_hash_insert(tn, a); 232 tcf_hash_insert(tn, *a);
239 233
240 return ret; 234 return ret;
241 235
@@ -245,14 +239,14 @@ failure:
245 qdisc_put_rtab(P_tab); 239 qdisc_put_rtab(P_tab);
246 qdisc_put_rtab(R_tab); 240 qdisc_put_rtab(R_tab);
247 if (ret == ACT_P_CREATED) 241 if (ret == ACT_P_CREATED)
248 tcf_hash_cleanup(a, est); 242 tcf_hash_cleanup(*a, est);
249 return err; 243 return err;
250} 244}
251 245
252static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a, 246static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a,
253 struct tcf_result *res) 247 struct tcf_result *res)
254{ 248{
255 struct tcf_police *police = a->priv; 249 struct tcf_police *police = to_police(a);
256 s64 now; 250 s64 now;
257 s64 toks; 251 s64 toks;
258 s64 ptoks = 0; 252 s64 ptoks = 0;
@@ -311,7 +305,7 @@ static int
311tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) 305tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
312{ 306{
313 unsigned char *b = skb_tail_pointer(skb); 307 unsigned char *b = skb_tail_pointer(skb);
314 struct tcf_police *police = a->priv; 308 struct tcf_police *police = to_police(a);
315 struct tc_police opt = { 309 struct tc_police opt = {
316 .index = police->tcf_index, 310 .index = police->tcf_index,
317 .action = police->tcf_action, 311 .action = police->tcf_action,
@@ -349,7 +343,7 @@ nla_put_failure:
349 return -1; 343 return -1;
350} 344}
351 345
352static int tcf_police_search(struct net *net, struct tc_action *a, u32 index) 346static int tcf_police_search(struct net *net, struct tc_action **a, u32 index)
353{ 347{
354 struct tc_action_net *tn = net_generic(net, police_net_id); 348 struct tc_action_net *tn = net_generic(net, police_net_id);
355 349
@@ -369,6 +363,7 @@ static struct tc_action_ops act_police_ops = {
369 .init = tcf_act_police_init, 363 .init = tcf_act_police_init,
370 .walk = tcf_act_police_walker, 364 .walk = tcf_act_police_walker,
371 .lookup = tcf_police_search, 365 .lookup = tcf_police_search,
366 .size = sizeof(struct tcf_police),
372}; 367};
373 368
374static __net_init int police_init_net(struct net *net) 369static __net_init int police_init_net(struct net *net)
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 318328d34d12..289af6f9bb3b 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -27,12 +27,13 @@
27#define SIMP_TAB_MASK 7 27#define SIMP_TAB_MASK 7
28 28
29static int simp_net_id; 29static int simp_net_id;
30static struct tc_action_ops act_simp_ops;
30 31
31#define SIMP_MAX_DATA 32 32#define SIMP_MAX_DATA 32
32static int tcf_simp(struct sk_buff *skb, const struct tc_action *a, 33static int tcf_simp(struct sk_buff *skb, const struct tc_action *a,
33 struct tcf_result *res) 34 struct tcf_result *res)
34{ 35{
35 struct tcf_defact *d = a->priv; 36 struct tcf_defact *d = to_defact(a);
36 37
37 spin_lock(&d->tcf_lock); 38 spin_lock(&d->tcf_lock);
38 tcf_lastuse_update(&d->tcf_tm); 39 tcf_lastuse_update(&d->tcf_tm);
@@ -79,7 +80,7 @@ static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = {
79}; 80};
80 81
81static int tcf_simp_init(struct net *net, struct nlattr *nla, 82static int tcf_simp_init(struct net *net, struct nlattr *nla,
82 struct nlattr *est, struct tc_action *a, 83 struct nlattr *est, struct tc_action **a,
83 int ovr, int bind) 84 int ovr, int bind)
84{ 85{
85 struct tc_action_net *tn = net_generic(net, simp_net_id); 86 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,
100 if (tb[TCA_DEF_PARMS] == NULL) 101 if (tb[TCA_DEF_PARMS] == NULL)
101 return -EINVAL; 102 return -EINVAL;
102 103
103
104 parm = nla_data(tb[TCA_DEF_PARMS]); 104 parm = nla_data(tb[TCA_DEF_PARMS]);
105 exists = tcf_hash_check(tn, parm->index, a, bind); 105 exists = tcf_hash_check(tn, parm->index, a, bind);
106 if (exists && bind) 106 if (exists && bind)
@@ -108,7 +108,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
108 108
109 if (tb[TCA_DEF_DATA] == NULL) { 109 if (tb[TCA_DEF_DATA] == NULL) {
110 if (exists) 110 if (exists)
111 tcf_hash_release(a, bind); 111 tcf_hash_release(*a, bind);
112 return -EINVAL; 112 return -EINVAL;
113 } 113 }
114 114
@@ -116,22 +116,22 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
116 116
117 if (!exists) { 117 if (!exists) {
118 ret = tcf_hash_create(tn, parm->index, est, a, 118 ret = tcf_hash_create(tn, parm->index, est, a,
119 sizeof(*d), bind, false); 119 &act_simp_ops, bind, false);
120 if (ret) 120 if (ret)
121 return ret; 121 return ret;
122 122
123 d = to_defact(a); 123 d = to_defact(*a);
124 ret = alloc_defdata(d, defdata); 124 ret = alloc_defdata(d, defdata);
125 if (ret < 0) { 125 if (ret < 0) {
126 tcf_hash_cleanup(a, est); 126 tcf_hash_cleanup(*a, est);
127 return ret; 127 return ret;
128 } 128 }
129 d->tcf_action = parm->action; 129 d->tcf_action = parm->action;
130 ret = ACT_P_CREATED; 130 ret = ACT_P_CREATED;
131 } else { 131 } else {
132 d = to_defact(a); 132 d = to_defact(*a);
133 133
134 tcf_hash_release(a, bind); 134 tcf_hash_release(*a, bind);
135 if (!ovr) 135 if (!ovr)
136 return -EEXIST; 136 return -EEXIST;
137 137
@@ -139,7 +139,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
139 } 139 }
140 140
141 if (ret == ACT_P_CREATED) 141 if (ret == ACT_P_CREATED)
142 tcf_hash_insert(tn, a); 142 tcf_hash_insert(tn, *a);
143 return ret; 143 return ret;
144} 144}
145 145
@@ -147,7 +147,7 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
147 int bind, int ref) 147 int bind, int ref)
148{ 148{
149 unsigned char *b = skb_tail_pointer(skb); 149 unsigned char *b = skb_tail_pointer(skb);
150 struct tcf_defact *d = a->priv; 150 struct tcf_defact *d = to_defact(a);
151 struct tc_defact opt = { 151 struct tc_defact opt = {
152 .index = d->tcf_index, 152 .index = d->tcf_index,
153 .refcnt = d->tcf_refcnt - ref, 153 .refcnt = d->tcf_refcnt - ref,
@@ -172,14 +172,14 @@ nla_put_failure:
172 172
173static int tcf_simp_walker(struct net *net, struct sk_buff *skb, 173static int tcf_simp_walker(struct net *net, struct sk_buff *skb,
174 struct netlink_callback *cb, int type, 174 struct netlink_callback *cb, int type,
175 struct tc_action *a) 175 const struct tc_action_ops *ops)
176{ 176{
177 struct tc_action_net *tn = net_generic(net, simp_net_id); 177 struct tc_action_net *tn = net_generic(net, simp_net_id);
178 178
179 return tcf_generic_walker(tn, skb, cb, type, a); 179 return tcf_generic_walker(tn, skb, cb, type, ops);
180} 180}
181 181
182static int tcf_simp_search(struct net *net, struct tc_action *a, u32 index) 182static int tcf_simp_search(struct net *net, struct tc_action **a, u32 index)
183{ 183{
184 struct tc_action_net *tn = net_generic(net, simp_net_id); 184 struct tc_action_net *tn = net_generic(net, simp_net_id);
185 185
@@ -196,6 +196,7 @@ static struct tc_action_ops act_simp_ops = {
196 .init = tcf_simp_init, 196 .init = tcf_simp_init,
197 .walk = tcf_simp_walker, 197 .walk = tcf_simp_walker,
198 .lookup = tcf_simp_search, 198 .lookup = tcf_simp_search,
199 .size = sizeof(struct tcf_defact),
199}; 200};
200 201
201static __net_init int simp_init_net(struct net *net) 202static __net_init int simp_init_net(struct net *net)
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 8e573c0f8742..a133dcb82132 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -30,11 +30,12 @@
30#define SKBEDIT_TAB_MASK 15 30#define SKBEDIT_TAB_MASK 15
31 31
32static int skbedit_net_id; 32static int skbedit_net_id;
33static struct tc_action_ops act_skbedit_ops;
33 34
34static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a, 35static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
35 struct tcf_result *res) 36 struct tcf_result *res)
36{ 37{
37 struct tcf_skbedit *d = a->priv; 38 struct tcf_skbedit *d = to_skbedit(a);
38 39
39 spin_lock(&d->tcf_lock); 40 spin_lock(&d->tcf_lock);
40 tcf_lastuse_update(&d->tcf_tm); 41 tcf_lastuse_update(&d->tcf_tm);
@@ -63,7 +64,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
63}; 64};
64 65
65static int tcf_skbedit_init(struct net *net, struct nlattr *nla, 66static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
66 struct nlattr *est, struct tc_action *a, 67 struct nlattr *est, struct tc_action **a,
67 int ovr, int bind) 68 int ovr, int bind)
68{ 69{
69 struct tc_action_net *tn = net_generic(net, skbedit_net_id); 70 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,
114 return 0; 115 return 0;
115 116
116 if (!flags) { 117 if (!flags) {
117 tcf_hash_release(a, bind); 118 tcf_hash_release(*a, bind);
118 return -EINVAL; 119 return -EINVAL;
119 } 120 }
120 121
121 if (!exists) { 122 if (!exists) {
122 ret = tcf_hash_create(tn, parm->index, est, a, 123 ret = tcf_hash_create(tn, parm->index, est, a,
123 sizeof(*d), bind, false); 124 &act_skbedit_ops, bind, false);
124 if (ret) 125 if (ret)
125 return ret; 126 return ret;
126 127
127 d = to_skbedit(a); 128 d = to_skbedit(*a);
128 ret = ACT_P_CREATED; 129 ret = ACT_P_CREATED;
129 } else { 130 } else {
130 d = to_skbedit(a); 131 d = to_skbedit(*a);
131 tcf_hash_release(a, bind); 132 tcf_hash_release(*a, bind);
132 if (!ovr) 133 if (!ovr)
133 return -EEXIST; 134 return -EEXIST;
134 } 135 }
@@ -150,7 +151,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
150 spin_unlock_bh(&d->tcf_lock); 151 spin_unlock_bh(&d->tcf_lock);
151 152
152 if (ret == ACT_P_CREATED) 153 if (ret == ACT_P_CREATED)
153 tcf_hash_insert(tn, a); 154 tcf_hash_insert(tn, *a);
154 return ret; 155 return ret;
155} 156}
156 157
@@ -158,7 +159,7 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
158 int bind, int ref) 159 int bind, int ref)
159{ 160{
160 unsigned char *b = skb_tail_pointer(skb); 161 unsigned char *b = skb_tail_pointer(skb);
161 struct tcf_skbedit *d = a->priv; 162 struct tcf_skbedit *d = to_skbedit(a);
162 struct tc_skbedit opt = { 163 struct tc_skbedit opt = {
163 .index = d->tcf_index, 164 .index = d->tcf_index,
164 .refcnt = d->tcf_refcnt - ref, 165 .refcnt = d->tcf_refcnt - ref,
@@ -194,14 +195,14 @@ nla_put_failure:
194 195
195static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb, 196static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb,
196 struct netlink_callback *cb, int type, 197 struct netlink_callback *cb, int type,
197 struct tc_action *a) 198 const struct tc_action_ops *ops)
198{ 199{
199 struct tc_action_net *tn = net_generic(net, skbedit_net_id); 200 struct tc_action_net *tn = net_generic(net, skbedit_net_id);
200 201
201 return tcf_generic_walker(tn, skb, cb, type, a); 202 return tcf_generic_walker(tn, skb, cb, type, ops);
202} 203}
203 204
204static int tcf_skbedit_search(struct net *net, struct tc_action *a, u32 index) 205static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index)
205{ 206{
206 struct tc_action_net *tn = net_generic(net, skbedit_net_id); 207 struct tc_action_net *tn = net_generic(net, skbedit_net_id);
207 208
@@ -217,6 +218,7 @@ static struct tc_action_ops act_skbedit_ops = {
217 .init = tcf_skbedit_init, 218 .init = tcf_skbedit_init,
218 .walk = tcf_skbedit_walker, 219 .walk = tcf_skbedit_walker,
219 .lookup = tcf_skbedit_search, 220 .lookup = tcf_skbedit_search,
221 .size = sizeof(struct tcf_skbedit),
220}; 222};
221 223
222static __net_init int skbedit_init_net(struct net *net) 224static __net_init int skbedit_init_net(struct net *net)
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index db9b7ed570ba..691409de3e1a 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -22,11 +22,12 @@
22#define VLAN_TAB_MASK 15 22#define VLAN_TAB_MASK 15
23 23
24static int vlan_net_id; 24static int vlan_net_id;
25static struct tc_action_ops act_vlan_ops;
25 26
26static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a, 27static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a,
27 struct tcf_result *res) 28 struct tcf_result *res)
28{ 29{
29 struct tcf_vlan *v = a->priv; 30 struct tcf_vlan *v = to_vlan(a);
30 int action; 31 int action;
31 int err; 32 int err;
32 33
@@ -67,7 +68,7 @@ static const struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = {
67}; 68};
68 69
69static int tcf_vlan_init(struct net *net, struct nlattr *nla, 70static int tcf_vlan_init(struct net *net, struct nlattr *nla,
70 struct nlattr *est, struct tc_action *a, 71 struct nlattr *est, struct tc_action **a,
71 int ovr, int bind) 72 int ovr, int bind)
72{ 73{
73 struct tc_action_net *tn = net_generic(net, vlan_net_id); 74 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,
100 case TCA_VLAN_ACT_PUSH: 101 case TCA_VLAN_ACT_PUSH:
101 if (!tb[TCA_VLAN_PUSH_VLAN_ID]) { 102 if (!tb[TCA_VLAN_PUSH_VLAN_ID]) {
102 if (exists) 103 if (exists)
103 tcf_hash_release(a, bind); 104 tcf_hash_release(*a, bind);
104 return -EINVAL; 105 return -EINVAL;
105 } 106 }
106 push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]); 107 push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
107 if (push_vid >= VLAN_VID_MASK) { 108 if (push_vid >= VLAN_VID_MASK) {
108 if (exists) 109 if (exists)
109 tcf_hash_release(a, bind); 110 tcf_hash_release(*a, bind);
110 return -ERANGE; 111 return -ERANGE;
111 } 112 }
112 113
@@ -125,25 +126,25 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
125 break; 126 break;
126 default: 127 default:
127 if (exists) 128 if (exists)
128 tcf_hash_release(a, bind); 129 tcf_hash_release(*a, bind);
129 return -EINVAL; 130 return -EINVAL;
130 } 131 }
131 action = parm->v_action; 132 action = parm->v_action;
132 133
133 if (!exists) { 134 if (!exists) {
134 ret = tcf_hash_create(tn, parm->index, est, a, 135 ret = tcf_hash_create(tn, parm->index, est, a,
135 sizeof(*v), bind, false); 136 &act_vlan_ops, bind, false);
136 if (ret) 137 if (ret)
137 return ret; 138 return ret;
138 139
139 ret = ACT_P_CREATED; 140 ret = ACT_P_CREATED;
140 } else { 141 } else {
141 tcf_hash_release(a, bind); 142 tcf_hash_release(*a, bind);
142 if (!ovr) 143 if (!ovr)
143 return -EEXIST; 144 return -EEXIST;
144 } 145 }
145 146
146 v = to_vlan(a); 147 v = to_vlan(*a);
147 148
148 spin_lock_bh(&v->tcf_lock); 149 spin_lock_bh(&v->tcf_lock);
149 150
@@ -156,7 +157,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
156 spin_unlock_bh(&v->tcf_lock); 157 spin_unlock_bh(&v->tcf_lock);
157 158
158 if (ret == ACT_P_CREATED) 159 if (ret == ACT_P_CREATED)
159 tcf_hash_insert(tn, a); 160 tcf_hash_insert(tn, *a);
160 return ret; 161 return ret;
161} 162}
162 163
@@ -164,7 +165,7 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
164 int bind, int ref) 165 int bind, int ref)
165{ 166{
166 unsigned char *b = skb_tail_pointer(skb); 167 unsigned char *b = skb_tail_pointer(skb);
167 struct tcf_vlan *v = a->priv; 168 struct tcf_vlan *v = to_vlan(a);
168 struct tc_vlan opt = { 169 struct tc_vlan opt = {
169 .index = v->tcf_index, 170 .index = v->tcf_index,
170 .refcnt = v->tcf_refcnt - ref, 171 .refcnt = v->tcf_refcnt - ref,
@@ -195,14 +196,14 @@ nla_put_failure:
195 196
196static int tcf_vlan_walker(struct net *net, struct sk_buff *skb, 197static int tcf_vlan_walker(struct net *net, struct sk_buff *skb,
197 struct netlink_callback *cb, int type, 198 struct netlink_callback *cb, int type,
198 struct tc_action *a) 199 const struct tc_action_ops *ops)
199{ 200{
200 struct tc_action_net *tn = net_generic(net, vlan_net_id); 201 struct tc_action_net *tn = net_generic(net, vlan_net_id);
201 202
202 return tcf_generic_walker(tn, skb, cb, type, a); 203 return tcf_generic_walker(tn, skb, cb, type, ops);
203} 204}
204 205
205static int tcf_vlan_search(struct net *net, struct tc_action *a, u32 index) 206static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index)
206{ 207{
207 struct tc_action_net *tn = net_generic(net, vlan_net_id); 208 struct tc_action_net *tn = net_generic(net, vlan_net_id);
208 209
@@ -218,6 +219,7 @@ static struct tc_action_ops act_vlan_ops = {
218 .init = tcf_vlan_init, 219 .init = tcf_vlan_init,
219 .walk = tcf_vlan_walker, 220 .walk = tcf_vlan_walker,
220 .lookup = tcf_vlan_search, 221 .lookup = tcf_vlan_search,
222 .size = sizeof(struct tcf_vlan),
221}; 223};
222 224
223static __net_init int vlan_init_net(struct net *net) 225static __net_init int vlan_init_net(struct net *net)