diff options
author | WANG Cong <xiyou.wangcong@gmail.com> | 2016-07-25 19:09:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-07-26 00:49:19 -0400 |
commit | a85a970af265f156740977168b542234511b28a8 (patch) | |
tree | 19866c37883917b1ec6964fcbae76335f9de0139 /net/sched | |
parent | b93dd49c1a35884864027abd707889b795637f7a (diff) |
net_sched: move tc_action into tcf_common
struct tc_action is confusing, currently we use it for two purposes:
1) Pass in arguments and carry out results from helper functions
2) A generic representation for tc actions
The first one is error-prone, since we need to make sure we don't
miss anything. This patch aims to get rid of this use, by moving
tc_action into tcf_common, so that they are allocated together
in hashtable and can be cast'ed easily.
And together with the following patch, we could really make
tc_action a generic representation for all tc actions and each
type of action can inherit from it.
Cc: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched')
-rw-r--r-- | net/sched/act_api.c | 149 | ||||
-rw-r--r-- | net/sched/act_bpf.c | 26 | ||||
-rw-r--r-- | net/sched/act_connmark.c | 24 | ||||
-rw-r--r-- | net/sched/act_csum.c | 22 | ||||
-rw-r--r-- | net/sched/act_gact.c | 24 | ||||
-rw-r--r-- | net/sched/act_ife.c | 38 | ||||
-rw-r--r-- | net/sched/act_ipt.c | 48 | ||||
-rw-r--r-- | net/sched/act_mirred.c | 26 | ||||
-rw-r--r-- | net/sched/act_nat.c | 22 | ||||
-rw-r--r-- | net/sched/act_pedit.c | 28 | ||||
-rw-r--r-- | net/sched/act_police.c | 45 | ||||
-rw-r--r-- | net/sched/act_simple.c | 29 | ||||
-rw-r--r-- | net/sched/act_skbedit.c | 26 | ||||
-rw-r--r-- | net/sched/act_vlan.c | 28 |
14 files changed, 256 insertions, 279 deletions
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 47ec2305f920..d97419f35e7e 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c | |||
@@ -38,7 +38,7 @@ static void free_tcf(struct rcu_head *head) | |||
38 | 38 | ||
39 | static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *a) | 39 | static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *a) |
40 | { | 40 | { |
41 | struct tcf_common *p = a->priv; | 41 | struct tcf_common *p = (struct tcf_common *)a; |
42 | 42 | ||
43 | spin_lock_bh(&hinfo->lock); | 43 | spin_lock_bh(&hinfo->lock); |
44 | hlist_del(&p->tcfc_head); | 44 | hlist_del(&p->tcfc_head); |
@@ -54,7 +54,7 @@ static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *a) | |||
54 | 54 | ||
55 | int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) | 55 | int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) |
56 | { | 56 | { |
57 | struct tcf_common *p = a->priv; | 57 | struct tcf_common *p = (struct tcf_common *)a; |
58 | int ret = 0; | 58 | int ret = 0; |
59 | 59 | ||
60 | if (p) { | 60 | if (p) { |
@@ -67,6 +67,7 @@ int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) | |||
67 | if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) { | 67 | if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) { |
68 | if (a->ops->cleanup) | 68 | if (a->ops->cleanup) |
69 | a->ops->cleanup(a, bind); | 69 | a->ops->cleanup(a, bind); |
70 | list_del(&a->list); | ||
70 | tcf_hash_destroy(a->hinfo, a); | 71 | tcf_hash_destroy(a->hinfo, a); |
71 | ret = ACT_P_DELETED; | 72 | ret = ACT_P_DELETED; |
72 | } | 73 | } |
@@ -77,10 +78,8 @@ int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) | |||
77 | EXPORT_SYMBOL(__tcf_hash_release); | 78 | EXPORT_SYMBOL(__tcf_hash_release); |
78 | 79 | ||
79 | static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, | 80 | static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, |
80 | struct netlink_callback *cb, struct tc_action *a) | 81 | struct netlink_callback *cb) |
81 | { | 82 | { |
82 | struct hlist_head *head; | ||
83 | struct tcf_common *p; | ||
84 | int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; | 83 | int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; |
85 | struct nlattr *nest; | 84 | struct nlattr *nest; |
86 | 85 | ||
@@ -89,19 +88,20 @@ static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, | |||
89 | s_i = cb->args[0]; | 88 | s_i = cb->args[0]; |
90 | 89 | ||
91 | for (i = 0; i < (hinfo->hmask + 1); i++) { | 90 | for (i = 0; i < (hinfo->hmask + 1); i++) { |
91 | struct hlist_head *head; | ||
92 | struct tcf_common *p; | ||
93 | |||
92 | head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; | 94 | head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; |
93 | 95 | ||
94 | hlist_for_each_entry_rcu(p, head, tcfc_head) { | 96 | hlist_for_each_entry_rcu(p, head, tcfc_head) { |
95 | index++; | 97 | index++; |
96 | if (index < s_i) | 98 | if (index < s_i) |
97 | continue; | 99 | continue; |
98 | a->priv = p; | ||
99 | a->order = n_i; | ||
100 | 100 | ||
101 | nest = nla_nest_start(skb, a->order); | 101 | nest = nla_nest_start(skb, n_i); |
102 | if (nest == NULL) | 102 | if (nest == NULL) |
103 | goto nla_put_failure; | 103 | goto nla_put_failure; |
104 | err = tcf_action_dump_1(skb, a, 0, 0); | 104 | err = tcf_action_dump_1(skb, (struct tc_action *)p, 0, 0); |
105 | if (err < 0) { | 105 | if (err < 0) { |
106 | index--; | 106 | index--; |
107 | nlmsg_trim(skb, nest); | 107 | nlmsg_trim(skb, nest); |
@@ -125,27 +125,27 @@ nla_put_failure: | |||
125 | } | 125 | } |
126 | 126 | ||
127 | static int tcf_del_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, | 127 | static int tcf_del_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, |
128 | struct tc_action *a) | 128 | const struct tc_action_ops *ops) |
129 | { | 129 | { |
130 | struct hlist_head *head; | ||
131 | struct hlist_node *n; | ||
132 | struct tcf_common *p; | ||
133 | struct nlattr *nest; | 130 | struct nlattr *nest; |
134 | int i = 0, n_i = 0; | 131 | int i = 0, n_i = 0; |
135 | int ret = -EINVAL; | 132 | int ret = -EINVAL; |
136 | 133 | ||
137 | nest = nla_nest_start(skb, a->order); | 134 | nest = nla_nest_start(skb, 0); |
138 | if (nest == NULL) | 135 | if (nest == NULL) |
139 | goto nla_put_failure; | 136 | goto nla_put_failure; |
140 | if (nla_put_string(skb, TCA_KIND, a->ops->kind)) | 137 | if (nla_put_string(skb, TCA_KIND, ops->kind)) |
141 | goto nla_put_failure; | 138 | goto nla_put_failure; |
142 | for (i = 0; i < (hinfo->hmask + 1); i++) { | 139 | for (i = 0; i < (hinfo->hmask + 1); i++) { |
140 | struct hlist_head *head; | ||
141 | struct hlist_node *n; | ||
142 | struct tcf_common *p; | ||
143 | |||
143 | head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; | 144 | head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; |
144 | hlist_for_each_entry_safe(p, n, head, tcfc_head) { | 145 | hlist_for_each_entry_safe(p, n, head, tcfc_head) { |
145 | a->priv = p; | 146 | ret = __tcf_hash_release((struct tc_action *)p, false, true); |
146 | ret = __tcf_hash_release(a, false, true); | ||
147 | if (ret == ACT_P_DELETED) { | 147 | if (ret == ACT_P_DELETED) { |
148 | module_put(a->ops->owner); | 148 | module_put(p->tcfc_act.ops->owner); |
149 | n_i++; | 149 | n_i++; |
150 | } else if (ret < 0) | 150 | } else if (ret < 0) |
151 | goto nla_put_failure; | 151 | goto nla_put_failure; |
@@ -163,16 +163,14 @@ nla_put_failure: | |||
163 | 163 | ||
164 | int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, | 164 | int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, |
165 | struct netlink_callback *cb, int type, | 165 | struct netlink_callback *cb, int type, |
166 | struct tc_action *a) | 166 | const struct tc_action_ops *ops) |
167 | { | 167 | { |
168 | struct tcf_hashinfo *hinfo = tn->hinfo; | 168 | struct tcf_hashinfo *hinfo = tn->hinfo; |
169 | 169 | ||
170 | a->hinfo = hinfo; | ||
171 | |||
172 | if (type == RTM_DELACTION) { | 170 | if (type == RTM_DELACTION) { |
173 | return tcf_del_walker(hinfo, skb, a); | 171 | return tcf_del_walker(hinfo, skb, ops); |
174 | } else if (type == RTM_GETACTION) { | 172 | } else if (type == RTM_GETACTION) { |
175 | return tcf_dump_walker(hinfo, skb, cb, a); | 173 | return tcf_dump_walker(hinfo, skb, cb); |
176 | } else { | 174 | } else { |
177 | WARN(1, "tcf_generic_walker: unknown action %d\n", type); | 175 | WARN(1, "tcf_generic_walker: unknown action %d\n", type); |
178 | return -EINVAL; | 176 | return -EINVAL; |
@@ -210,21 +208,20 @@ u32 tcf_hash_new_index(struct tc_action_net *tn) | |||
210 | } | 208 | } |
211 | EXPORT_SYMBOL(tcf_hash_new_index); | 209 | EXPORT_SYMBOL(tcf_hash_new_index); |
212 | 210 | ||
213 | int tcf_hash_search(struct tc_action_net *tn, struct tc_action *a, u32 index) | 211 | int tcf_hash_search(struct tc_action_net *tn, struct tc_action **a, u32 index) |
214 | { | 212 | { |
215 | struct tcf_hashinfo *hinfo = tn->hinfo; | 213 | struct tcf_hashinfo *hinfo = tn->hinfo; |
216 | struct tcf_common *p = tcf_hash_lookup(index, hinfo); | 214 | struct tcf_common *p = tcf_hash_lookup(index, hinfo); |
217 | 215 | ||
218 | if (p) { | 216 | if (p) { |
219 | a->priv = p; | 217 | *a = &p->tcfc_act; |
220 | a->hinfo = hinfo; | ||
221 | return 1; | 218 | return 1; |
222 | } | 219 | } |
223 | return 0; | 220 | return 0; |
224 | } | 221 | } |
225 | EXPORT_SYMBOL(tcf_hash_search); | 222 | EXPORT_SYMBOL(tcf_hash_search); |
226 | 223 | ||
227 | bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a, | 224 | bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action **a, |
228 | int bind) | 225 | int bind) |
229 | { | 226 | { |
230 | struct tcf_hashinfo *hinfo = tn->hinfo; | 227 | struct tcf_hashinfo *hinfo = tn->hinfo; |
@@ -233,8 +230,7 @@ bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a, | |||
233 | if (bind) | 230 | if (bind) |
234 | p->tcfc_bindcnt++; | 231 | p->tcfc_bindcnt++; |
235 | p->tcfc_refcnt++; | 232 | p->tcfc_refcnt++; |
236 | a->priv = p; | 233 | *a = &p->tcfc_act; |
237 | a->hinfo = hinfo; | ||
238 | return true; | 234 | return true; |
239 | } | 235 | } |
240 | return false; | 236 | return false; |
@@ -243,7 +239,7 @@ EXPORT_SYMBOL(tcf_hash_check); | |||
243 | 239 | ||
244 | void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est) | 240 | void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est) |
245 | { | 241 | { |
246 | struct tcf_common *pc = a->priv; | 242 | struct tcf_common *pc = (struct tcf_common *)a; |
247 | if (est) | 243 | if (est) |
248 | gen_kill_estimator(&pc->tcfc_bstats, | 244 | gen_kill_estimator(&pc->tcfc_bstats, |
249 | &pc->tcfc_rate_est); | 245 | &pc->tcfc_rate_est); |
@@ -252,9 +248,10 @@ void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est) | |||
252 | EXPORT_SYMBOL(tcf_hash_cleanup); | 248 | EXPORT_SYMBOL(tcf_hash_cleanup); |
253 | 249 | ||
254 | int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est, | 250 | int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est, |
255 | struct tc_action *a, int size, int bind, bool cpustats) | 251 | struct tc_action **a, const struct tc_action_ops *ops, |
252 | int bind, bool cpustats) | ||
256 | { | 253 | { |
257 | struct tcf_common *p = kzalloc(size, GFP_KERNEL); | 254 | struct tcf_common *p = kzalloc(ops->size, GFP_KERNEL); |
258 | struct tcf_hashinfo *hinfo = tn->hinfo; | 255 | struct tcf_hashinfo *hinfo = tn->hinfo; |
259 | int err = -ENOMEM; | 256 | int err = -ENOMEM; |
260 | 257 | ||
@@ -294,15 +291,17 @@ err2: | |||
294 | } | 291 | } |
295 | } | 292 | } |
296 | 293 | ||
297 | a->priv = (void *) p; | 294 | p->tcfc_act.hinfo = hinfo; |
298 | a->hinfo = hinfo; | 295 | p->tcfc_act.ops = ops; |
296 | INIT_LIST_HEAD(&p->tcfc_act.list); | ||
297 | *a = &p->tcfc_act; | ||
299 | return 0; | 298 | return 0; |
300 | } | 299 | } |
301 | EXPORT_SYMBOL(tcf_hash_create); | 300 | EXPORT_SYMBOL(tcf_hash_create); |
302 | 301 | ||
303 | void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a) | 302 | void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a) |
304 | { | 303 | { |
305 | struct tcf_common *p = a->priv; | 304 | struct tcf_common *p = (struct tcf_common *)a; |
306 | struct tcf_hashinfo *hinfo = tn->hinfo; | 305 | struct tcf_hashinfo *hinfo = tn->hinfo; |
307 | unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); | 306 | unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); |
308 | 307 | ||
@@ -315,10 +314,6 @@ EXPORT_SYMBOL(tcf_hash_insert); | |||
315 | void tcf_hashinfo_destroy(const struct tc_action_ops *ops, | 314 | void tcf_hashinfo_destroy(const struct tc_action_ops *ops, |
316 | struct tcf_hashinfo *hinfo) | 315 | struct tcf_hashinfo *hinfo) |
317 | { | 316 | { |
318 | struct tc_action a = { | ||
319 | .ops = ops, | ||
320 | .hinfo = hinfo, | ||
321 | }; | ||
322 | int i; | 317 | int i; |
323 | 318 | ||
324 | for (i = 0; i < hinfo->hmask + 1; i++) { | 319 | for (i = 0; i < hinfo->hmask + 1; i++) { |
@@ -328,8 +323,7 @@ void tcf_hashinfo_destroy(const struct tc_action_ops *ops, | |||
328 | hlist_for_each_entry_safe(p, n, &hinfo->htab[i], tcfc_head) { | 323 | hlist_for_each_entry_safe(p, n, &hinfo->htab[i], tcfc_head) { |
329 | int ret; | 324 | int ret; |
330 | 325 | ||
331 | a.priv = p; | 326 | ret = __tcf_hash_release((struct tc_action *)p, false, true); |
332 | ret = __tcf_hash_release(&a, false, true); | ||
333 | if (ret == ACT_P_DELETED) | 327 | if (ret == ACT_P_DELETED) |
334 | module_put(ops->owner); | 328 | module_put(ops->owner); |
335 | else if (ret < 0) | 329 | else if (ret < 0) |
@@ -466,8 +460,6 @@ int tcf_action_destroy(struct list_head *actions, int bind) | |||
466 | module_put(a->ops->owner); | 460 | module_put(a->ops->owner); |
467 | else if (ret < 0) | 461 | else if (ret < 0) |
468 | return ret; | 462 | return ret; |
469 | list_del(&a->list); | ||
470 | kfree(a); | ||
471 | } | 463 | } |
472 | return ret; | 464 | return ret; |
473 | } | 465 | } |
@@ -581,20 +573,13 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla, | |||
581 | goto err_out; | 573 | goto err_out; |
582 | } | 574 | } |
583 | 575 | ||
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 */ | 576 | /* backward compatibility for policer */ |
592 | if (name == NULL) | 577 | if (name == NULL) |
593 | err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, a, ovr, bind); | 578 | err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind); |
594 | else | 579 | else |
595 | err = a_o->init(net, nla, est, a, ovr, bind); | 580 | err = a_o->init(net, nla, est, &a, ovr, bind); |
596 | if (err < 0) | 581 | if (err < 0) |
597 | goto err_free; | 582 | goto err_mod; |
598 | 583 | ||
599 | /* module count goes up only when brand new policy is created | 584 | /* 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 | 585 | * if it exists and is only bound to in a_o->init() then |
@@ -605,8 +590,6 @@ struct tc_action *tcf_action_init_1(struct net *net, struct nlattr *nla, | |||
605 | 590 | ||
606 | return a; | 591 | return a; |
607 | 592 | ||
608 | err_free: | ||
609 | kfree(a); | ||
610 | err_mod: | 593 | err_mod: |
611 | module_put(a_o->owner); | 594 | module_put(a_o->owner); |
612 | err_out: | 595 | err_out: |
@@ -647,7 +630,7 @@ int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *a, | |||
647 | { | 630 | { |
648 | int err = 0; | 631 | int err = 0; |
649 | struct gnet_dump d; | 632 | struct gnet_dump d; |
650 | struct tcf_common *p = a->priv; | 633 | struct tcf_common *p = (struct tcf_common *)a; |
651 | 634 | ||
652 | if (p == NULL) | 635 | if (p == NULL) |
653 | goto errout; | 636 | goto errout; |
@@ -740,24 +723,11 @@ act_get_notify(struct net *net, u32 portid, struct nlmsghdr *n, | |||
740 | return rtnl_unicast(skb, net, portid); | 723 | return rtnl_unicast(skb, net, portid); |
741 | } | 724 | } |
742 | 725 | ||
743 | static 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 | |||
757 | static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla, | 726 | static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla, |
758 | struct nlmsghdr *n, u32 portid) | 727 | struct nlmsghdr *n, u32 portid) |
759 | { | 728 | { |
760 | struct nlattr *tb[TCA_ACT_MAX + 1]; | 729 | struct nlattr *tb[TCA_ACT_MAX + 1]; |
730 | const struct tc_action_ops *ops; | ||
761 | struct tc_action *a; | 731 | struct tc_action *a; |
762 | int index; | 732 | int index; |
763 | int err; | 733 | int err; |
@@ -772,26 +742,19 @@ static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla, | |||
772 | goto err_out; | 742 | goto err_out; |
773 | index = nla_get_u32(tb[TCA_ACT_INDEX]); | 743 | index = nla_get_u32(tb[TCA_ACT_INDEX]); |
774 | 744 | ||
775 | err = -ENOMEM; | ||
776 | a = create_a(0); | ||
777 | if (a == NULL) | ||
778 | goto err_out; | ||
779 | |||
780 | err = -EINVAL; | 745 | err = -EINVAL; |
781 | a->ops = tc_lookup_action(tb[TCA_ACT_KIND]); | 746 | ops = tc_lookup_action(tb[TCA_ACT_KIND]); |
782 | if (a->ops == NULL) /* could happen in batch of actions */ | 747 | if (!ops) /* could happen in batch of actions */ |
783 | goto err_free; | 748 | goto err_out; |
784 | err = -ENOENT; | 749 | err = -ENOENT; |
785 | if (a->ops->lookup(net, a, index) == 0) | 750 | if (ops->lookup(net, &a, index) == 0) |
786 | goto err_mod; | 751 | goto err_mod; |
787 | 752 | ||
788 | module_put(a->ops->owner); | 753 | module_put(ops->owner); |
789 | return a; | 754 | return a; |
790 | 755 | ||
791 | err_mod: | 756 | err_mod: |
792 | module_put(a->ops->owner); | 757 | module_put(ops->owner); |
793 | err_free: | ||
794 | kfree(a); | ||
795 | err_out: | 758 | err_out: |
796 | return ERR_PTR(err); | 759 | return ERR_PTR(err); |
797 | } | 760 | } |
@@ -816,8 +779,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
816 | struct netlink_callback dcb; | 779 | struct netlink_callback dcb; |
817 | struct nlattr *nest; | 780 | struct nlattr *nest; |
818 | struct nlattr *tb[TCA_ACT_MAX + 1]; | 781 | struct nlattr *tb[TCA_ACT_MAX + 1]; |
782 | const struct tc_action_ops *ops; | ||
819 | struct nlattr *kind; | 783 | struct nlattr *kind; |
820 | struct tc_action a; | ||
821 | int err = -ENOMEM; | 784 | int err = -ENOMEM; |
822 | 785 | ||
823 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); | 786 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); |
@@ -834,10 +797,8 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
834 | 797 | ||
835 | err = -EINVAL; | 798 | err = -EINVAL; |
836 | kind = tb[TCA_ACT_KIND]; | 799 | kind = tb[TCA_ACT_KIND]; |
837 | memset(&a, 0, sizeof(struct tc_action)); | 800 | ops = tc_lookup_action(kind); |
838 | INIT_LIST_HEAD(&a.list); | 801 | 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; | 802 | goto err_out; |
842 | 803 | ||
843 | nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION, | 804 | nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION, |
@@ -853,7 +814,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
853 | if (nest == NULL) | 814 | if (nest == NULL) |
854 | goto out_module_put; | 815 | goto out_module_put; |
855 | 816 | ||
856 | err = a.ops->walk(net, skb, &dcb, RTM_DELACTION, &a); | 817 | err = ops->walk(net, skb, &dcb, RTM_DELACTION, ops); |
857 | if (err < 0) | 818 | if (err < 0) |
858 | goto out_module_put; | 819 | goto out_module_put; |
859 | if (err == 0) | 820 | if (err == 0) |
@@ -863,7 +824,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
863 | 824 | ||
864 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; | 825 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; |
865 | nlh->nlmsg_flags |= NLM_F_ROOT; | 826 | nlh->nlmsg_flags |= NLM_F_ROOT; |
866 | module_put(a.ops->owner); | 827 | module_put(ops->owner); |
867 | err = rtnetlink_send(skb, net, portid, RTNLGRP_TC, | 828 | err = rtnetlink_send(skb, net, portid, RTNLGRP_TC, |
868 | n->nlmsg_flags & NLM_F_ECHO); | 829 | n->nlmsg_flags & NLM_F_ECHO); |
869 | if (err > 0) | 830 | if (err > 0) |
@@ -872,7 +833,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
872 | return err; | 833 | return err; |
873 | 834 | ||
874 | out_module_put: | 835 | out_module_put: |
875 | module_put(a.ops->owner); | 836 | module_put(ops->owner); |
876 | err_out: | 837 | err_out: |
877 | noflush_out: | 838 | noflush_out: |
878 | kfree_skb(skb); | 839 | kfree_skb(skb); |
@@ -1084,7 +1045,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | |||
1084 | unsigned char *b = skb_tail_pointer(skb); | 1045 | unsigned char *b = skb_tail_pointer(skb); |
1085 | struct nlattr *nest; | 1046 | struct nlattr *nest; |
1086 | struct tc_action_ops *a_o; | 1047 | struct tc_action_ops *a_o; |
1087 | struct tc_action a; | ||
1088 | int ret = 0; | 1048 | int ret = 0; |
1089 | struct tcamsg *t = (struct tcamsg *) nlmsg_data(cb->nlh); | 1049 | struct tcamsg *t = (struct tcamsg *) nlmsg_data(cb->nlh); |
1090 | struct nlattr *kind = find_dump_kind(cb->nlh); | 1050 | struct nlattr *kind = find_dump_kind(cb->nlh); |
@@ -1098,9 +1058,6 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | |||
1098 | if (a_o == NULL) | 1058 | if (a_o == NULL) |
1099 | return 0; | 1059 | return 0; |
1100 | 1060 | ||
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, | 1061 | nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, |
1105 | cb->nlh->nlmsg_type, sizeof(*t), 0); | 1062 | cb->nlh->nlmsg_type, sizeof(*t), 0); |
1106 | if (!nlh) | 1063 | if (!nlh) |
@@ -1114,7 +1071,7 @@ tc_dump_action(struct sk_buff *skb, struct netlink_callback *cb) | |||
1114 | if (nest == NULL) | 1071 | if (nest == NULL) |
1115 | goto out_module_put; | 1072 | goto out_module_put; |
1116 | 1073 | ||
1117 | ret = a_o->walk(net, skb, cb, RTM_GETACTION, &a); | 1074 | ret = a_o->walk(net, skb, cb, RTM_GETACTION, a_o); |
1118 | if (ret < 0) | 1075 | if (ret < 0) |
1119 | goto out_module_put; | 1076 | goto out_module_put; |
1120 | 1077 | ||
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 | ||
36 | static int bpf_net_id; | 36 | static int bpf_net_id; |
37 | static struct tc_action_ops act_bpf_ops; | ||
37 | 38 | ||
38 | static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act, | 39 | static 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 | ||
272 | static int tcf_bpf_init(struct net *net, struct nlattr *nla, | 273 | static 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; |
354 | out: | 355 | out: |
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 | ||
369 | static int tcf_bpf_walker(struct net *net, struct sk_buff *skb, | 370 | static 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 | ||
378 | static int tcf_bpf_search(struct net *net, struct tc_action *a, u32 index) | 379 | static 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 | ||
397 | static __net_init int bpf_init_net(struct net *net) | 399 | static __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 | ||
33 | static int connmark_net_id; | 33 | static int connmark_net_id; |
34 | static struct tc_action_ops act_connmark_ops; | ||
34 | 35 | ||
35 | static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a, | 36 | static 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 | ||
98 | static int tcf_connmark_init(struct net *net, struct nlattr *nla, | 99 | static 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 | ||
174 | static int tcf_connmark_walker(struct net *net, struct sk_buff *skb, | 175 | static 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 | ||
183 | static int tcf_connmark_search(struct net *net, struct tc_action *a, u32 index) | 184 | static 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 | ||
201 | static __net_init int connmark_init_net(struct net *net) | 203 | static __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 | ||
45 | static int csum_net_id; | 45 | static int csum_net_id; |
46 | static struct tc_action_ops act_csum_ops; | ||
46 | 47 | ||
47 | static int tcf_csum_init(struct net *net, struct nlattr *nla, | 48 | static 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: | |||
496 | static int tcf_csum(struct sk_buff *skb, | 497 | static 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 | ||
561 | static int tcf_csum_walker(struct net *net, struct sk_buff *skb, | 562 | static 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 | ||
570 | static int tcf_csum_search(struct net *net, struct tc_action *a, u32 index) | 571 | static 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 | ||
588 | static __net_init int csum_init_net(struct net *net) | 590 | static __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 | ||
28 | static int gact_net_id; | 28 | static int gact_net_id; |
29 | static struct tc_action_ops act_gact_ops; | ||
29 | 30 | ||
30 | #ifdef CONFIG_GACT_PROB | 31 | #ifdef CONFIG_GACT_PROB |
31 | static int gact_net_rand(struct tcf_gact *gact) | 32 | static 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 | ||
58 | static int tcf_gact_init(struct net *net, struct nlattr *nla, | 59 | static 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 | ||
128 | static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, | 129 | static 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, | |||
151 | static void tcf_gact_stats_update(struct tc_action *a, u64 bytes, u32 packets, | 152 | static 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 | ||
202 | static int tcf_gact_walker(struct net *net, struct sk_buff *skb, | 203 | static 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 | ||
211 | static int tcf_gact_search(struct net *net, struct tc_action *a, u32 index) | 212 | static 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 | ||
230 | static __net_init int gact_init_net(struct net *net) | 232 | static __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 | ||
38 | static int ife_net_id; | 38 | static int ife_net_id; |
39 | static int max_metacnt = IFE_META_MAX + 1; | 39 | static int max_metacnt = IFE_META_MAX + 1; |
40 | static struct tc_action_ops act_ife_ops; | ||
40 | 41 | ||
41 | static const struct nla_policy ife_policy[TCA_IFE_MAX + 1] = { | 42 | static 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 */ |
365 | static void _tcf_ife_cleanup(struct tc_action *a, int bind) | 366 | static 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 | ||
383 | static void tcf_ife_cleanup(struct tc_action *a, int bind) | 384 | static 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 | ||
419 | static int tcf_ife_init(struct net *net, struct nlattr *nla, | 420 | static 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) { |
508 | metadata_parse_err: | 509 | metadata_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 { | |||
623 | static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a, | 624 | static 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) | |||
695 | static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a, | 696 | static 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, | |||
799 | static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a, | 800 | static 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 | ||
820 | static int tcf_ife_walker(struct net *net, struct sk_buff *skb, | 821 | static 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 | ||
829 | static int tcf_ife_search(struct net *net, struct tc_action *a, u32 index) | 830 | static 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 | ||
848 | static __net_init int ife_init_net(struct net *net) | 850 | static __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 | ||
33 | static int ipt_net_id; | 33 | static int ipt_net_id; |
34 | static struct tc_action_ops act_ipt_ops; | ||
34 | 35 | ||
35 | static int xt_net_id; | 36 | static int xt_net_id; |
37 | static struct tc_action_ops act_xt_ops; | ||
36 | 38 | ||
37 | static int ipt_init_target(struct xt_entry_target *t, char *table, | 39 | static 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 | ||
92 | static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, | 94 | static 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 | ||
180 | err3: | 182 | err3: |
@@ -183,33 +185,33 @@ err2: | |||
183 | kfree(tname); | 185 | kfree(tname); |
184 | err1: | 186 | err1: |
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 | ||
190 | static int tcf_ipt_init(struct net *net, struct nlattr *nla, | 192 | static 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 | ||
199 | static int tcf_xt_init(struct net *net, struct nlattr *nla, | 201 | static 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 | ||
208 | static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a, | 210 | static 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 | ||
300 | static int tcf_ipt_walker(struct net *net, struct sk_buff *skb, | 302 | static 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 | ||
309 | static int tcf_ipt_search(struct net *net, struct tc_action *a, u32 index) | 311 | static 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 | ||
328 | static __net_init int ipt_init_net(struct net *net) | 331 | static __net_init int ipt_init_net(struct net *net) |
@@ -348,14 +351,14 @@ static struct pernet_operations ipt_net_ops = { | |||
348 | 351 | ||
349 | static int tcf_xt_walker(struct net *net, struct sk_buff *skb, | 352 | static 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 | ||
358 | static int tcf_xt_search(struct net *net, struct tc_action *a, u32 index) | 361 | static 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 | ||
377 | static __net_init int xt_init_net(struct net *net) | 381 | static __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 | ||
54 | static int mirred_net_id; | 54 | static int mirred_net_id; |
55 | static struct tc_action_ops act_mirred_ops; | ||
55 | 56 | ||
56 | static int tcf_mirred_init(struct net *net, struct nlattr *nla, | 57 | static 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, | |||
151 | static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a, | 152 | static 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: | |||
206 | static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | 207 | static 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 | ||
233 | static int tcf_mirred_walker(struct net *net, struct sk_buff *skb, | 234 | static 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 | ||
242 | static int tcf_mirred_search(struct net *net, struct tc_action *a, u32 index) | 243 | static 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 | ||
289 | static __net_init int mirred_init_net(struct net *net) | 291 | static __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 | ||
34 | static int nat_net_id; | 34 | static int nat_net_id; |
35 | static struct tc_action_ops act_nat_ops; | ||
35 | 36 | ||
36 | static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = { | 37 | static 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 | ||
40 | static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, | 41 | static 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, | |||
90 | static int tcf_nat(struct sk_buff *skb, const struct tc_action *a, | 91 | static 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 | ||
279 | static int tcf_nat_walker(struct net *net, struct sk_buff *skb, | 280 | static 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 | ||
288 | static int tcf_nat_search(struct net *net, struct tc_action *a, u32 index) | 289 | static 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 | ||
306 | static __net_init int nat_init_net(struct net *net) | 308 | static __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 | ||
28 | static int pedit_net_id; | 28 | static int pedit_net_id; |
29 | static struct tc_action_ops act_pedit_ops; | ||
29 | 30 | ||
30 | static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = { | 31 | static 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 | ||
34 | static int tcf_pedit_init(struct net *net, struct nlattr *nla, | 35 | static 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 | ||
103 | static void tcf_pedit_cleanup(struct tc_action *a, int bind) | 104 | static 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) | |||
110 | static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a, | 111 | static 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 | ||
217 | static int tcf_pedit_walker(struct net *net, struct sk_buff *skb, | 218 | static 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 | ||
226 | static int tcf_pedit_search(struct net *net, struct tc_action *a, u32 index) | 227 | static 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 | ||
245 | static __net_init int pedit_init_net(struct net *net) | 247 | static __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..123794af55c3 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
@@ -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 | ||
58 | static int police_net_id; | 58 | static int police_net_id; |
59 | static struct tc_action_ops act_police_ops; | ||
59 | 60 | ||
60 | static int tcf_act_police_walker(struct net *net, struct sk_buff *skb, | 61 | static 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 tcf_common *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, tcfc_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, (struct tc_action *)p, 0, 1); |
89 | else | 89 | else |
90 | err = tcf_action_dump_1(skb, a, 0, 0); | 90 | err = tcf_action_dump_1(skb, (struct tc_action *)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 | ||
118 | static int tcf_act_police_init(struct net *net, struct nlattr *nla, | 118 | static 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); | ||
166 | override: | 159 | override: |
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 | ||
252 | static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a, | 246 | static 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 | |||
311 | tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) | 305 | tcf_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 | ||
352 | static int tcf_police_search(struct net *net, struct tc_action *a, u32 index) | 346 | static 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 | ||
374 | static __net_init int police_init_net(struct net *net) | 369 | static __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 | ||
29 | static int simp_net_id; | 29 | static int simp_net_id; |
30 | static struct tc_action_ops act_simp_ops; | ||
30 | 31 | ||
31 | #define SIMP_MAX_DATA 32 | 32 | #define SIMP_MAX_DATA 32 |
32 | static int tcf_simp(struct sk_buff *skb, const struct tc_action *a, | 33 | static 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 | ||
81 | static int tcf_simp_init(struct net *net, struct nlattr *nla, | 82 | static 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 | ||
173 | static int tcf_simp_walker(struct net *net, struct sk_buff *skb, | 173 | static 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 | ||
182 | static int tcf_simp_search(struct net *net, struct tc_action *a, u32 index) | 182 | static 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 | ||
201 | static __net_init int simp_init_net(struct net *net) | 202 | static __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 | ||
32 | static int skbedit_net_id; | 32 | static int skbedit_net_id; |
33 | static struct tc_action_ops act_skbedit_ops; | ||
33 | 34 | ||
34 | static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a, | 35 | static 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 | ||
65 | static int tcf_skbedit_init(struct net *net, struct nlattr *nla, | 66 | static 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 | ||
195 | static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb, | 196 | static 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 | ||
204 | static int tcf_skbedit_search(struct net *net, struct tc_action *a, u32 index) | 205 | static 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 | ||
222 | static __net_init int skbedit_init_net(struct net *net) | 224 | static __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 | ||
24 | static int vlan_net_id; | 24 | static int vlan_net_id; |
25 | static struct tc_action_ops act_vlan_ops; | ||
25 | 26 | ||
26 | static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a, | 27 | static 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 | ||
69 | static int tcf_vlan_init(struct net *net, struct nlattr *nla, | 70 | static 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 | ||
196 | static int tcf_vlan_walker(struct net *net, struct sk_buff *skb, | 197 | static 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 | ||
205 | static int tcf_vlan_search(struct net *net, struct tc_action *a, u32 index) | 206 | static 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 | ||
223 | static __net_init int vlan_init_net(struct net *net) | 225 | static __net_init int vlan_init_net(struct net *net) |