aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched')
-rw-r--r--net/sched/act_api.c43
-rw-r--r--net/sched/act_csum.c24
-rw-r--r--net/sched/act_gact.c27
-rw-r--r--net/sched/act_ipt.c39
-rw-r--r--net/sched/act_mirred.c32
-rw-r--r--net/sched/act_nat.c25
-rw-r--r--net/sched/act_pedit.c25
-rw-r--r--net/sched/act_police.c10
-rw-r--r--net/sched/act_simple.c39
-rw-r--r--net/sched/act_skbedit.c29
10 files changed, 112 insertions, 181 deletions
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 72bdc7166345..4f2b807b3621 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -27,8 +27,11 @@
27#include <net/act_api.h> 27#include <net/act_api.h>
28#include <net/netlink.h> 28#include <net/netlink.h>
29 29
30void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo) 30void tcf_hash_destroy(struct tc_action *a)
31{ 31{
32 struct tcf_common *p = a->priv;
33 struct tcf_hashinfo *hinfo = a->ops->hinfo;
34
32 spin_lock_bh(&hinfo->lock); 35 spin_lock_bh(&hinfo->lock);
33 hlist_del(&p->tcfc_head); 36 hlist_del(&p->tcfc_head);
34 spin_unlock_bh(&hinfo->lock); 37 spin_unlock_bh(&hinfo->lock);
@@ -42,9 +45,9 @@ void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo)
42} 45}
43EXPORT_SYMBOL(tcf_hash_destroy); 46EXPORT_SYMBOL(tcf_hash_destroy);
44 47
45int tcf_hash_release(struct tcf_common *p, int bind, 48int tcf_hash_release(struct tc_action *a, int bind)
46 struct tcf_hashinfo *hinfo)
47{ 49{
50 struct tcf_common *p = a->priv;
48 int ret = 0; 51 int ret = 0;
49 52
50 if (p) { 53 if (p) {
@@ -53,7 +56,7 @@ int tcf_hash_release(struct tcf_common *p, int bind,
53 56
54 p->tcfc_refcnt--; 57 p->tcfc_refcnt--;
55 if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) { 58 if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) {
56 tcf_hash_destroy(p, hinfo); 59 tcf_hash_destroy(a);
57 ret = 1; 60 ret = 1;
58 } 61 }
59 } 62 }
@@ -127,7 +130,8 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a)
127 for (i = 0; i < (hinfo->hmask + 1); i++) { 130 for (i = 0; i < (hinfo->hmask + 1); i++) {
128 head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; 131 head = &hinfo->htab[tcf_hash(i, hinfo->hmask)];
129 hlist_for_each_entry_safe(p, n, head, tcfc_head) { 132 hlist_for_each_entry_safe(p, n, head, tcfc_head) {
130 if (ACT_P_DELETED == tcf_hash_release(p, 0, hinfo)) { 133 a->priv = p;
134 if (ACT_P_DELETED == tcf_hash_release(a, 0)) {
131 module_put(a->ops->owner); 135 module_put(a->ops->owner);
132 n_i++; 136 n_i++;
133 } 137 }
@@ -198,7 +202,7 @@ int tcf_hash_search(struct tc_action *a, u32 index)
198} 202}
199EXPORT_SYMBOL(tcf_hash_search); 203EXPORT_SYMBOL(tcf_hash_search);
200 204
201struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a, int bind) 205int tcf_hash_check(u32 index, struct tc_action *a, int bind)
202{ 206{
203 struct tcf_hashinfo *hinfo = a->ops->hinfo; 207 struct tcf_hashinfo *hinfo = a->ops->hinfo;
204 struct tcf_common *p = NULL; 208 struct tcf_common *p = NULL;
@@ -207,19 +211,30 @@ struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a, int bind)
207 p->tcfc_bindcnt++; 211 p->tcfc_bindcnt++;
208 p->tcfc_refcnt++; 212 p->tcfc_refcnt++;
209 a->priv = p; 213 a->priv = p;
214 return 1;
210 } 215 }
211 return p; 216 return 0;
212} 217}
213EXPORT_SYMBOL(tcf_hash_check); 218EXPORT_SYMBOL(tcf_hash_check);
214 219
215struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est, 220void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est)
216 struct tc_action *a, int size, int bind) 221{
222 struct tcf_common *pc = a->priv;
223 if (est)
224 gen_kill_estimator(&pc->tcfc_bstats,
225 &pc->tcfc_rate_est);
226 kfree_rcu(pc, tcfc_rcu);
227}
228EXPORT_SYMBOL(tcf_hash_cleanup);
229
230int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a,
231 int size, int bind)
217{ 232{
218 struct tcf_hashinfo *hinfo = a->ops->hinfo; 233 struct tcf_hashinfo *hinfo = a->ops->hinfo;
219 struct tcf_common *p = kzalloc(size, GFP_KERNEL); 234 struct tcf_common *p = kzalloc(size, GFP_KERNEL);
220 235
221 if (unlikely(!p)) 236 if (unlikely(!p))
222 return ERR_PTR(-ENOMEM); 237 return -ENOMEM;
223 p->tcfc_refcnt = 1; 238 p->tcfc_refcnt = 1;
224 if (bind) 239 if (bind)
225 p->tcfc_bindcnt = 1; 240 p->tcfc_bindcnt = 1;
@@ -234,17 +249,19 @@ struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est,
234 &p->tcfc_lock, est); 249 &p->tcfc_lock, est);
235 if (err) { 250 if (err) {
236 kfree(p); 251 kfree(p);
237 return ERR_PTR(err); 252 return err;
238 } 253 }
239 } 254 }
240 255
241 a->priv = (void *) p; 256 a->priv = (void *) p;
242 return p; 257 return 0;
243} 258}
244EXPORT_SYMBOL(tcf_hash_create); 259EXPORT_SYMBOL(tcf_hash_create);
245 260
246void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo) 261void tcf_hash_insert(struct tc_action *a)
247{ 262{
263 struct tcf_common *p = a->priv;
264 struct tcf_hashinfo *hinfo = a->ops->hinfo;
248 unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); 265 unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask);
249 266
250 spin_lock_bh(&hinfo->lock); 267 spin_lock_bh(&hinfo->lock);
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index 2210187c45c2..f0f6e7a625d1 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -48,7 +48,6 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est,
48{ 48{
49 struct nlattr *tb[TCA_CSUM_MAX + 1]; 49 struct nlattr *tb[TCA_CSUM_MAX + 1];
50 struct tc_csum *parm; 50 struct tc_csum *parm;
51 struct tcf_common *pc;
52 struct tcf_csum *p; 51 struct tcf_csum *p;
53 int ret = 0, err; 52 int ret = 0, err;
54 53
@@ -63,38 +62,31 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est,
63 return -EINVAL; 62 return -EINVAL;
64 parm = nla_data(tb[TCA_CSUM_PARMS]); 63 parm = nla_data(tb[TCA_CSUM_PARMS]);
65 64
66 pc = tcf_hash_check(parm->index, a, bind); 65 if (!tcf_hash_check(parm->index, a, bind)) {
67 if (!pc) { 66 ret = tcf_hash_create(parm->index, est, a, sizeof(*p), bind);
68 pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind); 67 if (ret)
69 if (IS_ERR(pc)) 68 return ret;
70 return PTR_ERR(pc);
71 ret = ACT_P_CREATED; 69 ret = ACT_P_CREATED;
72 } else { 70 } else {
73 if (bind)/* dont override defaults */ 71 if (bind)/* dont override defaults */
74 return 0; 72 return 0;
75 tcf_hash_release(pc, bind, a->ops->hinfo); 73 tcf_hash_release(a, bind);
76 if (!ovr) 74 if (!ovr)
77 return -EEXIST; 75 return -EEXIST;
78 } 76 }
79 77
80 p = to_tcf_csum(pc); 78 p = to_tcf_csum(a);
81 spin_lock_bh(&p->tcf_lock); 79 spin_lock_bh(&p->tcf_lock);
82 p->tcf_action = parm->action; 80 p->tcf_action = parm->action;
83 p->update_flags = parm->update_flags; 81 p->update_flags = parm->update_flags;
84 spin_unlock_bh(&p->tcf_lock); 82 spin_unlock_bh(&p->tcf_lock);
85 83
86 if (ret == ACT_P_CREATED) 84 if (ret == ACT_P_CREATED)
87 tcf_hash_insert(pc, a->ops->hinfo); 85 tcf_hash_insert(a);
88 86
89 return ret; 87 return ret;
90} 88}
91 89
92static int tcf_csum_cleanup(struct tc_action *a, int bind)
93{
94 struct tcf_csum *p = a->priv;
95 return tcf_hash_release(&p->common, bind, &csum_hash_info);
96}
97
98/** 90/**
99 * tcf_csum_skb_nextlayer - Get next layer pointer 91 * tcf_csum_skb_nextlayer - Get next layer pointer
100 * @skb: sk_buff to use 92 * @skb: sk_buff to use
@@ -574,7 +566,7 @@ static struct tc_action_ops act_csum_ops = {
574 .owner = THIS_MODULE, 566 .owner = THIS_MODULE,
575 .act = tcf_csum, 567 .act = tcf_csum,
576 .dump = tcf_csum_dump, 568 .dump = tcf_csum_dump,
577 .cleanup = tcf_csum_cleanup, 569 .cleanup = tcf_hash_release,
578 .init = tcf_csum_init, 570 .init = tcf_csum_init,
579}; 571};
580 572
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index a0eed30d5811..af6c0acd9bf1 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -57,7 +57,6 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
57 struct nlattr *tb[TCA_GACT_MAX + 1]; 57 struct nlattr *tb[TCA_GACT_MAX + 1];
58 struct tc_gact *parm; 58 struct tc_gact *parm;
59 struct tcf_gact *gact; 59 struct tcf_gact *gact;
60 struct tcf_common *pc;
61 int ret = 0; 60 int ret = 0;
62 int err; 61 int err;
63#ifdef CONFIG_GACT_PROB 62#ifdef CONFIG_GACT_PROB
@@ -86,21 +85,20 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
86 } 85 }
87#endif 86#endif
88 87
89 pc = tcf_hash_check(parm->index, a, bind); 88 if (!tcf_hash_check(parm->index, a, bind)) {
90 if (!pc) { 89 ret = tcf_hash_create(parm->index, est, a, sizeof(*gact), bind);
91 pc = tcf_hash_create(parm->index, est, a, sizeof(*gact), bind); 90 if (ret)
92 if (IS_ERR(pc)) 91 return ret;
93 return PTR_ERR(pc);
94 ret = ACT_P_CREATED; 92 ret = ACT_P_CREATED;
95 } else { 93 } else {
96 if (bind)/* dont override defaults */ 94 if (bind)/* dont override defaults */
97 return 0; 95 return 0;
98 tcf_hash_release(pc, bind, a->ops->hinfo); 96 tcf_hash_release(a, bind);
99 if (!ovr) 97 if (!ovr)
100 return -EEXIST; 98 return -EEXIST;
101 } 99 }
102 100
103 gact = to_gact(pc); 101 gact = to_gact(a);
104 102
105 spin_lock_bh(&gact->tcf_lock); 103 spin_lock_bh(&gact->tcf_lock);
106 gact->tcf_action = parm->action; 104 gact->tcf_action = parm->action;
@@ -113,19 +111,10 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
113#endif 111#endif
114 spin_unlock_bh(&gact->tcf_lock); 112 spin_unlock_bh(&gact->tcf_lock);
115 if (ret == ACT_P_CREATED) 113 if (ret == ACT_P_CREATED)
116 tcf_hash_insert(pc, a->ops->hinfo); 114 tcf_hash_insert(a);
117 return ret; 115 return ret;
118} 116}
119 117
120static int tcf_gact_cleanup(struct tc_action *a, int bind)
121{
122 struct tcf_gact *gact = a->priv;
123
124 if (gact)
125 return tcf_hash_release(&gact->common, bind, a->ops->hinfo);
126 return 0;
127}
128
129static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, 118static int tcf_gact(struct sk_buff *skb, const struct tc_action *a,
130 struct tcf_result *res) 119 struct tcf_result *res)
131{ 120{
@@ -196,7 +185,7 @@ static struct tc_action_ops act_gact_ops = {
196 .owner = THIS_MODULE, 185 .owner = THIS_MODULE,
197 .act = tcf_gact, 186 .act = tcf_gact,
198 .dump = tcf_gact_dump, 187 .dump = tcf_gact_dump,
199 .cleanup = tcf_gact_cleanup, 188 .cleanup = tcf_hash_release,
200 .init = tcf_gact_init, 189 .init = tcf_gact_init,
201}; 190};
202 191
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 0a6d62174027..f5e69782d400 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -69,8 +69,9 @@ static void ipt_destroy_target(struct xt_entry_target *t)
69 module_put(par.target->me); 69 module_put(par.target->me);
70} 70}
71 71
72static int tcf_ipt_release(struct tcf_ipt *ipt, int bind) 72static int tcf_ipt_release(struct tc_action *a, int bind)
73{ 73{
74 struct tcf_ipt *ipt = to_ipt(a);
74 int ret = 0; 75 int ret = 0;
75 if (ipt) { 76 if (ipt) {
76 if (bind) 77 if (bind)
@@ -80,7 +81,7 @@ static int tcf_ipt_release(struct tcf_ipt *ipt, int bind)
80 ipt_destroy_target(ipt->tcfi_t); 81 ipt_destroy_target(ipt->tcfi_t);
81 kfree(ipt->tcfi_tname); 82 kfree(ipt->tcfi_tname);
82 kfree(ipt->tcfi_t); 83 kfree(ipt->tcfi_t);
83 tcf_hash_destroy(&ipt->common, &ipt_hash_info); 84 tcf_hash_destroy(a);
84 ret = ACT_P_DELETED; 85 ret = ACT_P_DELETED;
85 } 86 }
86 } 87 }
@@ -99,7 +100,6 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,
99{ 100{
100 struct nlattr *tb[TCA_IPT_MAX + 1]; 101 struct nlattr *tb[TCA_IPT_MAX + 1];
101 struct tcf_ipt *ipt; 102 struct tcf_ipt *ipt;
102 struct tcf_common *pc;
103 struct xt_entry_target *td, *t; 103 struct xt_entry_target *td, *t;
104 char *tname; 104 char *tname;
105 int ret = 0, err; 105 int ret = 0, err;
@@ -125,21 +125,20 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,
125 if (tb[TCA_IPT_INDEX] != NULL) 125 if (tb[TCA_IPT_INDEX] != NULL)
126 index = nla_get_u32(tb[TCA_IPT_INDEX]); 126 index = nla_get_u32(tb[TCA_IPT_INDEX]);
127 127
128 pc = tcf_hash_check(index, a, bind); 128 if (!tcf_hash_check(index, a, bind) ) {
129 if (!pc) { 129 ret = tcf_hash_create(index, est, a, sizeof(*ipt), bind);
130 pc = tcf_hash_create(index, est, a, sizeof(*ipt), bind); 130 if (ret)
131 if (IS_ERR(pc)) 131 return ret;
132 return PTR_ERR(pc);
133 ret = ACT_P_CREATED; 132 ret = ACT_P_CREATED;
134 } else { 133 } else {
135 if (bind)/* dont override defaults */ 134 if (bind)/* dont override defaults */
136 return 0; 135 return 0;
137 tcf_ipt_release(to_ipt(pc), bind); 136 tcf_ipt_release(a, bind);
138 137
139 if (!ovr) 138 if (!ovr)
140 return -EEXIST; 139 return -EEXIST;
141 } 140 }
142 ipt = to_ipt(pc); 141 ipt = to_ipt(a);
143 142
144 hook = nla_get_u32(tb[TCA_IPT_HOOK]); 143 hook = nla_get_u32(tb[TCA_IPT_HOOK]);
145 144
@@ -170,7 +169,7 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est,
170 ipt->tcfi_hook = hook; 169 ipt->tcfi_hook = hook;
171 spin_unlock_bh(&ipt->tcf_lock); 170 spin_unlock_bh(&ipt->tcf_lock);
172 if (ret == ACT_P_CREATED) 171 if (ret == ACT_P_CREATED)
173 tcf_hash_insert(pc, a->ops->hinfo); 172 tcf_hash_insert(a);
174 return ret; 173 return ret;
175 174
176err3: 175err3:
@@ -178,21 +177,11 @@ err3:
178err2: 177err2:
179 kfree(tname); 178 kfree(tname);
180err1: 179err1:
181 if (ret == ACT_P_CREATED) { 180 if (ret == ACT_P_CREATED)
182 if (est) 181 tcf_hash_cleanup(a, est);
183 gen_kill_estimator(&pc->tcfc_bstats,
184 &pc->tcfc_rate_est);
185 kfree_rcu(pc, tcfc_rcu);
186 }
187 return err; 182 return err;
188} 183}
189 184
190static int tcf_ipt_cleanup(struct tc_action *a, int bind)
191{
192 struct tcf_ipt *ipt = a->priv;
193 return tcf_ipt_release(ipt, bind);
194}
195
196static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a, 185static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a,
197 struct tcf_result *res) 186 struct tcf_result *res)
198{ 187{
@@ -289,7 +278,7 @@ static struct tc_action_ops act_ipt_ops = {
289 .owner = THIS_MODULE, 278 .owner = THIS_MODULE,
290 .act = tcf_ipt, 279 .act = tcf_ipt,
291 .dump = tcf_ipt_dump, 280 .dump = tcf_ipt_dump,
292 .cleanup = tcf_ipt_cleanup, 281 .cleanup = tcf_ipt_release,
293 .init = tcf_ipt_init, 282 .init = tcf_ipt_init,
294}; 283};
295 284
@@ -300,7 +289,7 @@ static struct tc_action_ops act_xt_ops = {
300 .owner = THIS_MODULE, 289 .owner = THIS_MODULE,
301 .act = tcf_ipt, 290 .act = tcf_ipt,
302 .dump = tcf_ipt_dump, 291 .dump = tcf_ipt_dump,
303 .cleanup = tcf_ipt_cleanup, 292 .cleanup = tcf_ipt_release,
304 .init = tcf_ipt_init, 293 .init = tcf_ipt_init,
305}; 294};
306 295
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 0b2c6d39d396..3edeecafba2f 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -33,8 +33,9 @@
33static LIST_HEAD(mirred_list); 33static LIST_HEAD(mirred_list);
34static struct tcf_hashinfo mirred_hash_info; 34static struct tcf_hashinfo mirred_hash_info;
35 35
36static int tcf_mirred_release(struct tcf_mirred *m, int bind) 36static int tcf_mirred_release(struct tc_action *a, int bind)
37{ 37{
38 struct tcf_mirred *m = to_mirred(a);
38 if (m) { 39 if (m) {
39 if (bind) 40 if (bind)
40 m->tcf_bindcnt--; 41 m->tcf_bindcnt--;
@@ -43,7 +44,7 @@ static int tcf_mirred_release(struct tcf_mirred *m, int bind)
43 list_del(&m->tcfm_list); 44 list_del(&m->tcfm_list);
44 if (m->tcfm_dev) 45 if (m->tcfm_dev)
45 dev_put(m->tcfm_dev); 46 dev_put(m->tcfm_dev);
46 tcf_hash_destroy(&m->common, &mirred_hash_info); 47 tcf_hash_destroy(a);
47 return 1; 48 return 1;
48 } 49 }
49 } 50 }
@@ -61,7 +62,6 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
61 struct nlattr *tb[TCA_MIRRED_MAX + 1]; 62 struct nlattr *tb[TCA_MIRRED_MAX + 1];
62 struct tc_mirred *parm; 63 struct tc_mirred *parm;
63 struct tcf_mirred *m; 64 struct tcf_mirred *m;
64 struct tcf_common *pc;
65 struct net_device *dev; 65 struct net_device *dev;
66 int ret, ok_push = 0; 66 int ret, ok_push = 0;
67 67
@@ -101,21 +101,20 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
101 dev = NULL; 101 dev = NULL;
102 } 102 }
103 103
104 pc = tcf_hash_check(parm->index, a, bind); 104 if (!tcf_hash_check(parm->index, a, bind)) {
105 if (!pc) {
106 if (dev == NULL) 105 if (dev == NULL)
107 return -EINVAL; 106 return -EINVAL;
108 pc = tcf_hash_create(parm->index, est, a, sizeof(*m), bind); 107 ret = tcf_hash_create(parm->index, est, a, sizeof(*m), bind);
109 if (IS_ERR(pc)) 108 if (ret)
110 return PTR_ERR(pc); 109 return ret;
111 ret = ACT_P_CREATED; 110 ret = ACT_P_CREATED;
112 } else { 111 } else {
113 if (!ovr) { 112 if (!ovr) {
114 tcf_mirred_release(to_mirred(pc), bind); 113 tcf_mirred_release(a, bind);
115 return -EEXIST; 114 return -EEXIST;
116 } 115 }
117 } 116 }
118 m = to_mirred(pc); 117 m = to_mirred(a);
119 118
120 spin_lock_bh(&m->tcf_lock); 119 spin_lock_bh(&m->tcf_lock);
121 m->tcf_action = parm->action; 120 m->tcf_action = parm->action;
@@ -131,21 +130,12 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
131 spin_unlock_bh(&m->tcf_lock); 130 spin_unlock_bh(&m->tcf_lock);
132 if (ret == ACT_P_CREATED) { 131 if (ret == ACT_P_CREATED) {
133 list_add(&m->tcfm_list, &mirred_list); 132 list_add(&m->tcfm_list, &mirred_list);
134 tcf_hash_insert(pc, a->ops->hinfo); 133 tcf_hash_insert(a);
135 } 134 }
136 135
137 return ret; 136 return ret;
138} 137}
139 138
140static int tcf_mirred_cleanup(struct tc_action *a, int bind)
141{
142 struct tcf_mirred *m = a->priv;
143
144 if (m)
145 return tcf_mirred_release(m, bind);
146 return 0;
147}
148
149static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a, 139static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
150 struct tcf_result *res) 140 struct tcf_result *res)
151{ 141{
@@ -259,7 +249,7 @@ static struct tc_action_ops act_mirred_ops = {
259 .owner = THIS_MODULE, 249 .owner = THIS_MODULE,
260 .act = tcf_mirred, 250 .act = tcf_mirred,
261 .dump = tcf_mirred_dump, 251 .dump = tcf_mirred_dump,
262 .cleanup = tcf_mirred_cleanup, 252 .cleanup = tcf_mirred_release,
263 .init = tcf_mirred_init, 253 .init = tcf_mirred_init,
264}; 254};
265 255
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index 81f0404bb335..ce9a3914ed4a 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -44,7 +44,6 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
44 struct tc_nat *parm; 44 struct tc_nat *parm;
45 int ret = 0, err; 45 int ret = 0, err;
46 struct tcf_nat *p; 46 struct tcf_nat *p;
47 struct tcf_common *pc;
48 47
49 if (nla == NULL) 48 if (nla == NULL)
50 return -EINVAL; 49 return -EINVAL;
@@ -57,20 +56,19 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
57 return -EINVAL; 56 return -EINVAL;
58 parm = nla_data(tb[TCA_NAT_PARMS]); 57 parm = nla_data(tb[TCA_NAT_PARMS]);
59 58
60 pc = tcf_hash_check(parm->index, a, bind); 59 if (!tcf_hash_check(parm->index, a, bind)) {
61 if (!pc) { 60 ret = tcf_hash_create(parm->index, est, a, sizeof(*p), bind);
62 pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind); 61 if (ret)
63 if (IS_ERR(pc)) 62 return ret;
64 return PTR_ERR(pc);
65 ret = ACT_P_CREATED; 63 ret = ACT_P_CREATED;
66 } else { 64 } else {
67 if (bind) 65 if (bind)
68 return 0; 66 return 0;
69 tcf_hash_release(pc, bind, a->ops->hinfo); 67 tcf_hash_release(a, bind);
70 if (!ovr) 68 if (!ovr)
71 return -EEXIST; 69 return -EEXIST;
72 } 70 }
73 p = to_tcf_nat(pc); 71 p = to_tcf_nat(a);
74 72
75 spin_lock_bh(&p->tcf_lock); 73 spin_lock_bh(&p->tcf_lock);
76 p->old_addr = parm->old_addr; 74 p->old_addr = parm->old_addr;
@@ -82,18 +80,11 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
82 spin_unlock_bh(&p->tcf_lock); 80 spin_unlock_bh(&p->tcf_lock);
83 81
84 if (ret == ACT_P_CREATED) 82 if (ret == ACT_P_CREATED)
85 tcf_hash_insert(pc, a->ops->hinfo); 83 tcf_hash_insert(a);
86 84
87 return ret; 85 return ret;
88} 86}
89 87
90static int tcf_nat_cleanup(struct tc_action *a, int bind)
91{
92 struct tcf_nat *p = a->priv;
93
94 return tcf_hash_release(&p->common, bind, &nat_hash_info);
95}
96
97static int tcf_nat(struct sk_buff *skb, const struct tc_action *a, 88static int tcf_nat(struct sk_buff *skb, const struct tc_action *a,
98 struct tcf_result *res) 89 struct tcf_result *res)
99{ 90{
@@ -298,7 +289,7 @@ static struct tc_action_ops act_nat_ops = {
298 .owner = THIS_MODULE, 289 .owner = THIS_MODULE,
299 .act = tcf_nat, 290 .act = tcf_nat,
300 .dump = tcf_nat_dump, 291 .dump = tcf_nat_dump,
301 .cleanup = tcf_nat_cleanup, 292 .cleanup = tcf_hash_release,
302 .init = tcf_nat_init, 293 .init = tcf_nat_init,
303}; 294};
304 295
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index be3f0f6875bb..091ced38a376 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -39,7 +39,6 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
39 struct tc_pedit *parm; 39 struct tc_pedit *parm;
40 int ret = 0, err; 40 int ret = 0, err;
41 struct tcf_pedit *p; 41 struct tcf_pedit *p;
42 struct tcf_common *pc;
43 struct tc_pedit_key *keys = NULL; 42 struct tc_pedit_key *keys = NULL;
44 int ksize; 43 int ksize;
45 44
@@ -57,26 +56,22 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
57 if (nla_len(tb[TCA_PEDIT_PARMS]) < sizeof(*parm) + ksize) 56 if (nla_len(tb[TCA_PEDIT_PARMS]) < sizeof(*parm) + ksize)
58 return -EINVAL; 57 return -EINVAL;
59 58
60 pc = tcf_hash_check(parm->index, a, bind); 59 if (!tcf_hash_check(parm->index, a, bind)) {
61 if (!pc) {
62 if (!parm->nkeys) 60 if (!parm->nkeys)
63 return -EINVAL; 61 return -EINVAL;
64 pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind); 62 ret = tcf_hash_create(parm->index, est, a, sizeof(*p), bind);
65 if (IS_ERR(pc)) 63 if (ret)
66 return PTR_ERR(pc); 64 return ret;
67 p = to_pedit(pc); 65 p = to_pedit(a);
68 keys = kmalloc(ksize, GFP_KERNEL); 66 keys = kmalloc(ksize, GFP_KERNEL);
69 if (keys == NULL) { 67 if (keys == NULL) {
70 if (est) 68 tcf_hash_cleanup(a, est);
71 gen_kill_estimator(&pc->tcfc_bstats,
72 &pc->tcfc_rate_est);
73 kfree_rcu(pc, tcfc_rcu);
74 return -ENOMEM; 69 return -ENOMEM;
75 } 70 }
76 ret = ACT_P_CREATED; 71 ret = ACT_P_CREATED;
77 } else { 72 } else {
78 p = to_pedit(pc); 73 p = to_pedit(a);
79 tcf_hash_release(pc, bind, a->ops->hinfo); 74 tcf_hash_release(a, bind);
80 if (bind) 75 if (bind)
81 return 0; 76 return 0;
82 if (!ovr) 77 if (!ovr)
@@ -100,7 +95,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
100 memcpy(p->tcfp_keys, parm->keys, ksize); 95 memcpy(p->tcfp_keys, parm->keys, ksize);
101 spin_unlock_bh(&p->tcf_lock); 96 spin_unlock_bh(&p->tcf_lock);
102 if (ret == ACT_P_CREATED) 97 if (ret == ACT_P_CREATED)
103 tcf_hash_insert(pc, a->ops->hinfo); 98 tcf_hash_insert(a);
104 return ret; 99 return ret;
105} 100}
106 101
@@ -110,7 +105,7 @@ static int tcf_pedit_cleanup(struct tc_action *a, int bind)
110 105
111 if (p) { 106 if (p) {
112 struct tc_pedit_key *keys = p->tcfp_keys; 107 struct tc_pedit_key *keys = p->tcfp_keys;
113 if (tcf_hash_release(&p->common, bind, &pedit_hash_info)) { 108 if (tcf_hash_release(a, bind)) {
114 kfree(keys); 109 kfree(keys);
115 return 1; 110 return 1;
116 } 111 }
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 1778209a332f..4695d02bd249 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -253,14 +253,6 @@ failure:
253 return err; 253 return err;
254} 254}
255 255
256static int tcf_act_police_cleanup(struct tc_action *a, int bind)
257{
258 struct tcf_police *p = a->priv;
259 if (p)
260 return tcf_hash_release(&p->common, bind, &police_hash_info);
261 return 0;
262}
263
264static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a, 256static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a,
265 struct tcf_result *res) 257 struct tcf_result *res)
266{ 258{
@@ -362,7 +354,7 @@ static struct tc_action_ops act_police_ops = {
362 .owner = THIS_MODULE, 354 .owner = THIS_MODULE,
363 .act = tcf_act_police, 355 .act = tcf_act_police,
364 .dump = tcf_act_police_dump, 356 .dump = tcf_act_police_dump,
365 .cleanup = tcf_act_police_cleanup, 357 .cleanup = tcf_hash_release,
366 .init = tcf_act_police_locate, 358 .init = tcf_act_police_locate,
367 .walk = tcf_act_police_walker 359 .walk = tcf_act_police_walker
368}; 360};
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 8ef2f1fcbfba..11c2922bb900 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -47,8 +47,9 @@ static int tcf_simp(struct sk_buff *skb, const struct tc_action *a,
47 return d->tcf_action; 47 return d->tcf_action;
48} 48}
49 49
50static int tcf_simp_release(struct tcf_defact *d, int bind) 50static int tcf_simp_release(struct tc_action *a, int bind)
51{ 51{
52 struct tcf_defact *d = to_defact(a);
52 int ret = 0; 53 int ret = 0;
53 if (d) { 54 if (d) {
54 if (bind) 55 if (bind)
@@ -56,7 +57,7 @@ static int tcf_simp_release(struct tcf_defact *d, int bind)
56 d->tcf_refcnt--; 57 d->tcf_refcnt--;
57 if (d->tcf_bindcnt <= 0 && d->tcf_refcnt <= 0) { 58 if (d->tcf_bindcnt <= 0 && d->tcf_refcnt <= 0) {
58 kfree(d->tcfd_defdata); 59 kfree(d->tcfd_defdata);
59 tcf_hash_destroy(&d->common, &simp_hash_info); 60 tcf_hash_destroy(a);
60 ret = 1; 61 ret = 1;
61 } 62 }
62 } 63 }
@@ -94,7 +95,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
94 struct nlattr *tb[TCA_DEF_MAX + 1]; 95 struct nlattr *tb[TCA_DEF_MAX + 1];
95 struct tc_defact *parm; 96 struct tc_defact *parm;
96 struct tcf_defact *d; 97 struct tcf_defact *d;
97 struct tcf_common *pc;
98 char *defdata; 98 char *defdata;
99 int ret = 0, err; 99 int ret = 0, err;
100 100
@@ -114,29 +114,25 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
114 parm = nla_data(tb[TCA_DEF_PARMS]); 114 parm = nla_data(tb[TCA_DEF_PARMS]);
115 defdata = nla_data(tb[TCA_DEF_DATA]); 115 defdata = nla_data(tb[TCA_DEF_DATA]);
116 116
117 pc = tcf_hash_check(parm->index, a, bind); 117 if (!tcf_hash_check(parm->index, a, bind)) {
118 if (!pc) { 118 ret = tcf_hash_create(parm->index, est, a, sizeof(*d), bind);
119 pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind); 119 if (ret)
120 if (IS_ERR(pc)) 120 return ret;
121 return PTR_ERR(pc);
122 121
123 d = to_defact(pc); 122 d = to_defact(a);
124 ret = alloc_defdata(d, defdata); 123 ret = alloc_defdata(d, defdata);
125 if (ret < 0) { 124 if (ret < 0) {
126 if (est) 125 tcf_hash_cleanup(a, est);
127 gen_kill_estimator(&pc->tcfc_bstats,
128 &pc->tcfc_rate_est);
129 kfree_rcu(pc, tcfc_rcu);
130 return ret; 126 return ret;
131 } 127 }
132 d->tcf_action = parm->action; 128 d->tcf_action = parm->action;
133 ret = ACT_P_CREATED; 129 ret = ACT_P_CREATED;
134 } else { 130 } else {
135 d = to_defact(pc); 131 d = to_defact(a);
136 132
137 if (bind) 133 if (bind)
138 return 0; 134 return 0;
139 tcf_simp_release(d, bind); 135 tcf_simp_release(a, bind);
140 if (!ovr) 136 if (!ovr)
141 return -EEXIST; 137 return -EEXIST;
142 138
@@ -144,19 +140,10 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
144 } 140 }
145 141
146 if (ret == ACT_P_CREATED) 142 if (ret == ACT_P_CREATED)
147 tcf_hash_insert(pc, a->ops->hinfo); 143 tcf_hash_insert(a);
148 return ret; 144 return ret;
149} 145}
150 146
151static int tcf_simp_cleanup(struct tc_action *a, int bind)
152{
153 struct tcf_defact *d = a->priv;
154
155 if (d)
156 return tcf_simp_release(d, bind);
157 return 0;
158}
159
160static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, 147static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
161 int bind, int ref) 148 int bind, int ref)
162{ 149{
@@ -192,7 +179,7 @@ static struct tc_action_ops act_simp_ops = {
192 .owner = THIS_MODULE, 179 .owner = THIS_MODULE,
193 .act = tcf_simp, 180 .act = tcf_simp,
194 .dump = tcf_simp_dump, 181 .dump = tcf_simp_dump,
195 .cleanup = tcf_simp_cleanup, 182 .cleanup = tcf_simp_release,
196 .init = tcf_simp_init, 183 .init = tcf_simp_init,
197}; 184};
198 185
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 98725080b5aa..71fd2d499109 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -65,7 +65,6 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
65 struct nlattr *tb[TCA_SKBEDIT_MAX + 1]; 65 struct nlattr *tb[TCA_SKBEDIT_MAX + 1];
66 struct tc_skbedit *parm; 66 struct tc_skbedit *parm;
67 struct tcf_skbedit *d; 67 struct tcf_skbedit *d;
68 struct tcf_common *pc;
69 u32 flags = 0, *priority = NULL, *mark = NULL; 68 u32 flags = 0, *priority = NULL, *mark = NULL;
70 u16 *queue_mapping = NULL; 69 u16 *queue_mapping = NULL;
71 int ret = 0, err; 70 int ret = 0, err;
@@ -100,19 +99,18 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
100 99
101 parm = nla_data(tb[TCA_SKBEDIT_PARMS]); 100 parm = nla_data(tb[TCA_SKBEDIT_PARMS]);
102 101
103 pc = tcf_hash_check(parm->index, a, bind); 102 if (!tcf_hash_check(parm->index, a, bind)) {
104 if (!pc) { 103 ret = tcf_hash_create(parm->index, est, a, sizeof(*d), bind);
105 pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind); 104 if (ret)
106 if (IS_ERR(pc)) 105 return ret;
107 return PTR_ERR(pc);
108 106
109 d = to_skbedit(pc); 107 d = to_skbedit(a);
110 ret = ACT_P_CREATED; 108 ret = ACT_P_CREATED;
111 } else { 109 } else {
112 d = to_skbedit(pc); 110 d = to_skbedit(a);
113 if (bind) 111 if (bind)
114 return 0; 112 return 0;
115 tcf_hash_release(pc, bind, a->ops->hinfo); 113 tcf_hash_release(a, bind);
116 if (!ovr) 114 if (!ovr)
117 return -EEXIST; 115 return -EEXIST;
118 } 116 }
@@ -132,19 +130,10 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
132 spin_unlock_bh(&d->tcf_lock); 130 spin_unlock_bh(&d->tcf_lock);
133 131
134 if (ret == ACT_P_CREATED) 132 if (ret == ACT_P_CREATED)
135 tcf_hash_insert(pc, a->ops->hinfo); 133 tcf_hash_insert(a);
136 return ret; 134 return ret;
137} 135}
138 136
139static int tcf_skbedit_cleanup(struct tc_action *a, int bind)
140{
141 struct tcf_skbedit *d = a->priv;
142
143 if (d)
144 return tcf_hash_release(&d->common, bind, &skbedit_hash_info);
145 return 0;
146}
147
148static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, 137static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
149 int bind, int ref) 138 int bind, int ref)
150{ 139{
@@ -191,7 +180,7 @@ static struct tc_action_ops act_skbedit_ops = {
191 .owner = THIS_MODULE, 180 .owner = THIS_MODULE,
192 .act = tcf_skbedit, 181 .act = tcf_skbedit,
193 .dump = tcf_skbedit_dump, 182 .dump = tcf_skbedit_dump,
194 .cleanup = tcf_skbedit_cleanup, 183 .cleanup = tcf_hash_release,
195 .init = tcf_skbedit_init, 184 .init = tcf_skbedit_init,
196}; 185};
197 186