aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched
diff options
context:
space:
mode:
authorWANG Cong <xiyou.wangcong@gmail.com>2016-07-25 19:09:41 -0400
committerDavid S. Miller <davem@davemloft.net>2016-07-26 00:49:19 -0400
commita85a970af265f156740977168b542234511b28a8 (patch)
tree19866c37883917b1ec6964fcbae76335f9de0139 /net/sched
parentb93dd49c1a35884864027abd707889b795637f7a (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.c149
-rw-r--r--net/sched/act_bpf.c26
-rw-r--r--net/sched/act_connmark.c24
-rw-r--r--net/sched/act_csum.c22
-rw-r--r--net/sched/act_gact.c24
-rw-r--r--net/sched/act_ife.c38
-rw-r--r--net/sched/act_ipt.c48
-rw-r--r--net/sched/act_mirred.c26
-rw-r--r--net/sched/act_nat.c22
-rw-r--r--net/sched/act_pedit.c28
-rw-r--r--net/sched/act_police.c45
-rw-r--r--net/sched/act_simple.c29
-rw-r--r--net/sched/act_skbedit.c26
-rw-r--r--net/sched/act_vlan.c28
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
39static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *a) 39static void tcf_hash_destroy(struct tcf_hashinfo *hinfo, struct tc_action *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
55int __tcf_hash_release(struct tc_action *a, bool bind, bool strict) 55int __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)
77EXPORT_SYMBOL(__tcf_hash_release); 78EXPORT_SYMBOL(__tcf_hash_release);
78 79
79static int tcf_dump_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, 80static 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
127static int tcf_del_walker(struct tcf_hashinfo *hinfo, struct sk_buff *skb, 127static 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
164int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb, 164int 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}
211EXPORT_SYMBOL(tcf_hash_new_index); 209EXPORT_SYMBOL(tcf_hash_new_index);
212 210
213int tcf_hash_search(struct tc_action_net *tn, struct tc_action *a, u32 index) 211int 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}
225EXPORT_SYMBOL(tcf_hash_search); 222EXPORT_SYMBOL(tcf_hash_search);
226 223
227bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a, 224bool 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
244void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est) 240void 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)
252EXPORT_SYMBOL(tcf_hash_cleanup); 248EXPORT_SYMBOL(tcf_hash_cleanup);
253 249
254int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est, 250int 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}
301EXPORT_SYMBOL(tcf_hash_create); 300EXPORT_SYMBOL(tcf_hash_create);
302 301
303void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a) 302void 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);
315void tcf_hashinfo_destroy(const struct tc_action_ops *ops, 314void 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
608err_free:
609 kfree(a);
610err_mod: 593err_mod:
611 module_put(a_o->owner); 594 module_put(a_o->owner);
612err_out: 595err_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
743static struct tc_action *create_a(int i)
744{
745 struct tc_action *act;
746
747 act = kzalloc(sizeof(*act), GFP_KERNEL);
748 if (act == NULL) {
749 pr_debug("create_a: failed to alloc!\n");
750 return NULL;
751 }
752 act->order = i;
753 INIT_LIST_HEAD(&act->list);
754 return act;
755}
756
757static struct tc_action *tcf_action_get_1(struct net *net, struct nlattr *nla, 726static 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
791err_mod: 756err_mod:
792 module_put(a->ops->owner); 757 module_put(ops->owner);
793err_free:
794 kfree(a);
795err_out: 758err_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
874out_module_put: 835out_module_put:
875 module_put(a.ops->owner); 836 module_put(ops->owner);
876err_out: 837err_out:
877noflush_out: 838noflush_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
36static int bpf_net_id; 36static int bpf_net_id;
37static struct tc_action_ops act_bpf_ops;
37 38
38static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act, 39static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act,
39 struct tcf_result *res) 40 struct tcf_result *res)
40{ 41{
41 struct tcf_bpf *prog = act->priv; 42 struct tcf_bpf *prog = to_bpf(act);
42 struct bpf_prog *filter; 43 struct bpf_prog *filter;
43 int action, filter_res; 44 int action, filter_res;
44 bool at_ingress = G_TC_AT(skb->tc_verd) & AT_INGRESS; 45 bool at_ingress = G_TC_AT(skb->tc_verd) & AT_INGRESS;
@@ -134,7 +135,7 @@ static int tcf_bpf_dump(struct sk_buff *skb, struct tc_action *act,
134 int bind, int ref) 135 int bind, int ref)
135{ 136{
136 unsigned char *tp = skb_tail_pointer(skb); 137 unsigned char *tp = skb_tail_pointer(skb);
137 struct tcf_bpf *prog = act->priv; 138 struct tcf_bpf *prog = to_bpf(act);
138 struct tc_act_bpf opt = { 139 struct tc_act_bpf opt = {
139 .index = prog->tcf_index, 140 .index = prog->tcf_index,
140 .refcnt = prog->tcf_refcnt - ref, 141 .refcnt = prog->tcf_refcnt - ref,
@@ -270,7 +271,7 @@ static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf *prog,
270} 271}
271 272
272static int tcf_bpf_init(struct net *net, struct nlattr *nla, 273static int tcf_bpf_init(struct net *net, struct nlattr *nla,
273 struct nlattr *est, struct tc_action *act, 274 struct nlattr *est, struct tc_action **act,
274 int replace, int bind) 275 int replace, int bind)
275{ 276{
276 struct tc_action_net *tn = net_generic(net, bpf_net_id); 277 struct tc_action_net *tn = net_generic(net, bpf_net_id);
@@ -295,7 +296,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
295 296
296 if (!tcf_hash_check(tn, parm->index, act, bind)) { 297 if (!tcf_hash_check(tn, parm->index, act, bind)) {
297 ret = tcf_hash_create(tn, parm->index, est, act, 298 ret = tcf_hash_create(tn, parm->index, est, act,
298 sizeof(*prog), bind, true); 299 &act_bpf_ops, bind, true);
299 if (ret < 0) 300 if (ret < 0)
300 return ret; 301 return ret;
301 302
@@ -305,7 +306,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
305 if (bind) 306 if (bind)
306 return 0; 307 return 0;
307 308
308 tcf_hash_release(act, bind); 309 tcf_hash_release(*act, bind);
309 if (!replace) 310 if (!replace)
310 return -EEXIST; 311 return -EEXIST;
311 } 312 }
@@ -325,7 +326,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
325 if (ret < 0) 326 if (ret < 0)
326 goto out; 327 goto out;
327 328
328 prog = to_bpf(act); 329 prog = to_bpf(*act);
329 ASSERT_RTNL(); 330 ASSERT_RTNL();
330 331
331 if (res != ACT_P_CREATED) 332 if (res != ACT_P_CREATED)
@@ -343,7 +344,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
343 rcu_assign_pointer(prog->filter, cfg.filter); 344 rcu_assign_pointer(prog->filter, cfg.filter);
344 345
345 if (res == ACT_P_CREATED) { 346 if (res == ACT_P_CREATED) {
346 tcf_hash_insert(tn, act); 347 tcf_hash_insert(tn, *act);
347 } else { 348 } else {
348 /* make sure the program being replaced is no longer executing */ 349 /* make sure the program being replaced is no longer executing */
349 synchronize_rcu(); 350 synchronize_rcu();
@@ -353,7 +354,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,
353 return res; 354 return res;
354out: 355out:
355 if (res == ACT_P_CREATED) 356 if (res == ACT_P_CREATED)
356 tcf_hash_cleanup(act, est); 357 tcf_hash_cleanup(*act, est);
357 358
358 return ret; 359 return ret;
359} 360}
@@ -362,20 +363,20 @@ static void tcf_bpf_cleanup(struct tc_action *act, int bind)
362{ 363{
363 struct tcf_bpf_cfg tmp; 364 struct tcf_bpf_cfg tmp;
364 365
365 tcf_bpf_prog_fill_cfg(act->priv, &tmp); 366 tcf_bpf_prog_fill_cfg(to_bpf(act), &tmp);
366 tcf_bpf_cfg_cleanup(&tmp); 367 tcf_bpf_cfg_cleanup(&tmp);
367} 368}
368 369
369static int tcf_bpf_walker(struct net *net, struct sk_buff *skb, 370static int tcf_bpf_walker(struct net *net, struct sk_buff *skb,
370 struct netlink_callback *cb, int type, 371 struct netlink_callback *cb, int type,
371 struct tc_action *a) 372 const struct tc_action_ops *ops)
372{ 373{
373 struct tc_action_net *tn = net_generic(net, bpf_net_id); 374 struct tc_action_net *tn = net_generic(net, bpf_net_id);
374 375
375 return tcf_generic_walker(tn, skb, cb, type, a); 376 return tcf_generic_walker(tn, skb, cb, type, ops);
376} 377}
377 378
378static int tcf_bpf_search(struct net *net, struct tc_action *a, u32 index) 379static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index)
379{ 380{
380 struct tc_action_net *tn = net_generic(net, bpf_net_id); 381 struct tc_action_net *tn = net_generic(net, bpf_net_id);
381 382
@@ -392,6 +393,7 @@ static struct tc_action_ops act_bpf_ops __read_mostly = {
392 .init = tcf_bpf_init, 393 .init = tcf_bpf_init,
393 .walk = tcf_bpf_walker, 394 .walk = tcf_bpf_walker,
394 .lookup = tcf_bpf_search, 395 .lookup = tcf_bpf_search,
396 .size = sizeof(struct tcf_bpf),
395}; 397};
396 398
397static __net_init int bpf_init_net(struct net *net) 399static __net_init int bpf_init_net(struct net *net)
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 35a5270f289d..eae07a2e774d 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -31,6 +31,7 @@
31#define CONNMARK_TAB_MASK 3 31#define CONNMARK_TAB_MASK 3
32 32
33static int connmark_net_id; 33static int connmark_net_id;
34static struct tc_action_ops act_connmark_ops;
34 35
35static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a, 36static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a,
36 struct tcf_result *res) 37 struct tcf_result *res)
@@ -38,7 +39,7 @@ static int tcf_connmark(struct sk_buff *skb, const struct tc_action *a,
38 const struct nf_conntrack_tuple_hash *thash; 39 const struct nf_conntrack_tuple_hash *thash;
39 struct nf_conntrack_tuple tuple; 40 struct nf_conntrack_tuple tuple;
40 enum ip_conntrack_info ctinfo; 41 enum ip_conntrack_info ctinfo;
41 struct tcf_connmark_info *ca = a->priv; 42 struct tcf_connmark_info *ca = to_connmark(a);
42 struct nf_conntrack_zone zone; 43 struct nf_conntrack_zone zone;
43 struct nf_conn *c; 44 struct nf_conn *c;
44 int proto; 45 int proto;
@@ -96,7 +97,7 @@ static const struct nla_policy connmark_policy[TCA_CONNMARK_MAX + 1] = {
96}; 97};
97 98
98static int tcf_connmark_init(struct net *net, struct nlattr *nla, 99static int tcf_connmark_init(struct net *net, struct nlattr *nla,
99 struct nlattr *est, struct tc_action *a, 100 struct nlattr *est, struct tc_action **a,
100 int ovr, int bind) 101 int ovr, int bind)
101{ 102{
102 struct tc_action_net *tn = net_generic(net, connmark_net_id); 103 struct tc_action_net *tn = net_generic(net, connmark_net_id);
@@ -116,22 +117,22 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla,
116 117
117 if (!tcf_hash_check(tn, parm->index, a, bind)) { 118 if (!tcf_hash_check(tn, parm->index, a, bind)) {
118 ret = tcf_hash_create(tn, parm->index, est, a, 119 ret = tcf_hash_create(tn, parm->index, est, a,
119 sizeof(*ci), bind, false); 120 &act_connmark_ops, bind, false);
120 if (ret) 121 if (ret)
121 return ret; 122 return ret;
122 123
123 ci = to_connmark(a); 124 ci = to_connmark(*a);
124 ci->tcf_action = parm->action; 125 ci->tcf_action = parm->action;
125 ci->net = net; 126 ci->net = net;
126 ci->zone = parm->zone; 127 ci->zone = parm->zone;
127 128
128 tcf_hash_insert(tn, a); 129 tcf_hash_insert(tn, *a);
129 ret = ACT_P_CREATED; 130 ret = ACT_P_CREATED;
130 } else { 131 } else {
131 ci = to_connmark(a); 132 ci = to_connmark(*a);
132 if (bind) 133 if (bind)
133 return 0; 134 return 0;
134 tcf_hash_release(a, bind); 135 tcf_hash_release(*a, bind);
135 if (!ovr) 136 if (!ovr)
136 return -EEXIST; 137 return -EEXIST;
137 /* replacing action and zone */ 138 /* replacing action and zone */
@@ -146,7 +147,7 @@ static inline int tcf_connmark_dump(struct sk_buff *skb, struct tc_action *a,
146 int bind, int ref) 147 int bind, int ref)
147{ 148{
148 unsigned char *b = skb_tail_pointer(skb); 149 unsigned char *b = skb_tail_pointer(skb);
149 struct tcf_connmark_info *ci = a->priv; 150 struct tcf_connmark_info *ci = to_connmark(a);
150 151
151 struct tc_connmark opt = { 152 struct tc_connmark opt = {
152 .index = ci->tcf_index, 153 .index = ci->tcf_index,
@@ -173,14 +174,14 @@ nla_put_failure:
173 174
174static int tcf_connmark_walker(struct net *net, struct sk_buff *skb, 175static int tcf_connmark_walker(struct net *net, struct sk_buff *skb,
175 struct netlink_callback *cb, int type, 176 struct netlink_callback *cb, int type,
176 struct tc_action *a) 177 const struct tc_action_ops *ops)
177{ 178{
178 struct tc_action_net *tn = net_generic(net, connmark_net_id); 179 struct tc_action_net *tn = net_generic(net, connmark_net_id);
179 180
180 return tcf_generic_walker(tn, skb, cb, type, a); 181 return tcf_generic_walker(tn, skb, cb, type, ops);
181} 182}
182 183
183static int tcf_connmark_search(struct net *net, struct tc_action *a, u32 index) 184static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 index)
184{ 185{
185 struct tc_action_net *tn = net_generic(net, connmark_net_id); 186 struct tc_action_net *tn = net_generic(net, connmark_net_id);
186 187
@@ -196,6 +197,7 @@ static struct tc_action_ops act_connmark_ops = {
196 .init = tcf_connmark_init, 197 .init = tcf_connmark_init,
197 .walk = tcf_connmark_walker, 198 .walk = tcf_connmark_walker,
198 .lookup = tcf_connmark_search, 199 .lookup = tcf_connmark_search,
200 .size = sizeof(struct tcf_connmark_info),
199}; 201};
200 202
201static __net_init int connmark_init_net(struct net *net) 203static __net_init int connmark_init_net(struct net *net)
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index dcd9ababd351..b5dbf633a863 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -43,9 +43,10 @@ static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = {
43}; 43};
44 44
45static int csum_net_id; 45static int csum_net_id;
46static struct tc_action_ops act_csum_ops;
46 47
47static int tcf_csum_init(struct net *net, struct nlattr *nla, 48static int tcf_csum_init(struct net *net, struct nlattr *nla,
48 struct nlattr *est, struct tc_action *a, int ovr, 49 struct nlattr *est, struct tc_action **a, int ovr,
49 int bind) 50 int bind)
50{ 51{
51 struct tc_action_net *tn = net_generic(net, csum_net_id); 52 struct tc_action_net *tn = net_generic(net, csum_net_id);
@@ -67,26 +68,26 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla,
67 68
68 if (!tcf_hash_check(tn, parm->index, a, bind)) { 69 if (!tcf_hash_check(tn, parm->index, a, bind)) {
69 ret = tcf_hash_create(tn, parm->index, est, a, 70 ret = tcf_hash_create(tn, parm->index, est, a,
70 sizeof(*p), bind, false); 71 &act_csum_ops, bind, false);
71 if (ret) 72 if (ret)
72 return ret; 73 return ret;
73 ret = ACT_P_CREATED; 74 ret = ACT_P_CREATED;
74 } else { 75 } else {
75 if (bind)/* dont override defaults */ 76 if (bind)/* dont override defaults */
76 return 0; 77 return 0;
77 tcf_hash_release(a, bind); 78 tcf_hash_release(*a, bind);
78 if (!ovr) 79 if (!ovr)
79 return -EEXIST; 80 return -EEXIST;
80 } 81 }
81 82
82 p = to_tcf_csum(a); 83 p = to_tcf_csum(*a);
83 spin_lock_bh(&p->tcf_lock); 84 spin_lock_bh(&p->tcf_lock);
84 p->tcf_action = parm->action; 85 p->tcf_action = parm->action;
85 p->update_flags = parm->update_flags; 86 p->update_flags = parm->update_flags;
86 spin_unlock_bh(&p->tcf_lock); 87 spin_unlock_bh(&p->tcf_lock);
87 88
88 if (ret == ACT_P_CREATED) 89 if (ret == ACT_P_CREATED)
89 tcf_hash_insert(tn, a); 90 tcf_hash_insert(tn, *a);
90 91
91 return ret; 92 return ret;
92} 93}
@@ -496,7 +497,7 @@ fail:
496static int tcf_csum(struct sk_buff *skb, 497static int tcf_csum(struct sk_buff *skb,
497 const struct tc_action *a, struct tcf_result *res) 498 const struct tc_action *a, struct tcf_result *res)
498{ 499{
499 struct tcf_csum *p = a->priv; 500 struct tcf_csum *p = to_tcf_csum(a);
500 int action; 501 int action;
501 u32 update_flags; 502 u32 update_flags;
502 503
@@ -534,7 +535,7 @@ static int tcf_csum_dump(struct sk_buff *skb,
534 struct tc_action *a, int bind, int ref) 535 struct tc_action *a, int bind, int ref)
535{ 536{
536 unsigned char *b = skb_tail_pointer(skb); 537 unsigned char *b = skb_tail_pointer(skb);
537 struct tcf_csum *p = a->priv; 538 struct tcf_csum *p = to_tcf_csum(a);
538 struct tc_csum opt = { 539 struct tc_csum opt = {
539 .update_flags = p->update_flags, 540 .update_flags = p->update_flags,
540 .index = p->tcf_index, 541 .index = p->tcf_index,
@@ -560,14 +561,14 @@ nla_put_failure:
560 561
561static int tcf_csum_walker(struct net *net, struct sk_buff *skb, 562static int tcf_csum_walker(struct net *net, struct sk_buff *skb,
562 struct netlink_callback *cb, int type, 563 struct netlink_callback *cb, int type,
563 struct tc_action *a) 564 const struct tc_action_ops *ops)
564{ 565{
565 struct tc_action_net *tn = net_generic(net, csum_net_id); 566 struct tc_action_net *tn = net_generic(net, csum_net_id);
566 567
567 return tcf_generic_walker(tn, skb, cb, type, a); 568 return tcf_generic_walker(tn, skb, cb, type, ops);
568} 569}
569 570
570static int tcf_csum_search(struct net *net, struct tc_action *a, u32 index) 571static int tcf_csum_search(struct net *net, struct tc_action **a, u32 index)
571{ 572{
572 struct tc_action_net *tn = net_generic(net, csum_net_id); 573 struct tc_action_net *tn = net_generic(net, csum_net_id);
573 574
@@ -583,6 +584,7 @@ static struct tc_action_ops act_csum_ops = {
583 .init = tcf_csum_init, 584 .init = tcf_csum_init,
584 .walk = tcf_csum_walker, 585 .walk = tcf_csum_walker,
585 .lookup = tcf_csum_search, 586 .lookup = tcf_csum_search,
587 .size = sizeof(struct tcf_csum),
586}; 588};
587 589
588static __net_init int csum_init_net(struct net *net) 590static __net_init int csum_init_net(struct net *net)
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 19058a7f3e5c..e24a4093d6f6 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -26,6 +26,7 @@
26#define GACT_TAB_MASK 15 26#define GACT_TAB_MASK 15
27 27
28static int gact_net_id; 28static int gact_net_id;
29static struct tc_action_ops act_gact_ops;
29 30
30#ifdef CONFIG_GACT_PROB 31#ifdef CONFIG_GACT_PROB
31static int gact_net_rand(struct tcf_gact *gact) 32static int gact_net_rand(struct tcf_gact *gact)
@@ -56,7 +57,7 @@ static const struct nla_policy gact_policy[TCA_GACT_MAX + 1] = {
56}; 57};
57 58
58static int tcf_gact_init(struct net *net, struct nlattr *nla, 59static int tcf_gact_init(struct net *net, struct nlattr *nla,
59 struct nlattr *est, struct tc_action *a, 60 struct nlattr *est, struct tc_action **a,
60 int ovr, int bind) 61 int ovr, int bind)
61{ 62{
62 struct tc_action_net *tn = net_generic(net, gact_net_id); 63 struct tc_action_net *tn = net_generic(net, gact_net_id);
@@ -93,19 +94,19 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
93 94
94 if (!tcf_hash_check(tn, parm->index, a, bind)) { 95 if (!tcf_hash_check(tn, parm->index, a, bind)) {
95 ret = tcf_hash_create(tn, parm->index, est, a, 96 ret = tcf_hash_create(tn, parm->index, est, a,
96 sizeof(*gact), bind, true); 97 &act_gact_ops, bind, true);
97 if (ret) 98 if (ret)
98 return ret; 99 return ret;
99 ret = ACT_P_CREATED; 100 ret = ACT_P_CREATED;
100 } else { 101 } else {
101 if (bind)/* dont override defaults */ 102 if (bind)/* dont override defaults */
102 return 0; 103 return 0;
103 tcf_hash_release(a, bind); 104 tcf_hash_release(*a, bind);
104 if (!ovr) 105 if (!ovr)
105 return -EEXIST; 106 return -EEXIST;
106 } 107 }
107 108
108 gact = to_gact(a); 109 gact = to_gact(*a);
109 110
110 ASSERT_RTNL(); 111 ASSERT_RTNL();
111 gact->tcf_action = parm->action; 112 gact->tcf_action = parm->action;
@@ -121,14 +122,14 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla,
121 } 122 }
122#endif 123#endif
123 if (ret == ACT_P_CREATED) 124 if (ret == ACT_P_CREATED)
124 tcf_hash_insert(tn, a); 125 tcf_hash_insert(tn, *a);
125 return ret; 126 return ret;
126} 127}
127 128
128static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, 129static int tcf_gact(struct sk_buff *skb, const struct tc_action *a,
129 struct tcf_result *res) 130 struct tcf_result *res)
130{ 131{
131 struct tcf_gact *gact = a->priv; 132 struct tcf_gact *gact = to_gact(a);
132 int action = READ_ONCE(gact->tcf_action); 133 int action = READ_ONCE(gact->tcf_action);
133 134
134#ifdef CONFIG_GACT_PROB 135#ifdef CONFIG_GACT_PROB
@@ -151,7 +152,7 @@ static int tcf_gact(struct sk_buff *skb, const struct tc_action *a,
151static void tcf_gact_stats_update(struct tc_action *a, u64 bytes, u32 packets, 152static void tcf_gact_stats_update(struct tc_action *a, u64 bytes, u32 packets,
152 u64 lastuse) 153 u64 lastuse)
153{ 154{
154 struct tcf_gact *gact = a->priv; 155 struct tcf_gact *gact = to_gact(a);
155 int action = READ_ONCE(gact->tcf_action); 156 int action = READ_ONCE(gact->tcf_action);
156 struct tcf_t *tm = &gact->tcf_tm; 157 struct tcf_t *tm = &gact->tcf_tm;
157 158
@@ -166,7 +167,7 @@ static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a,
166 int bind, int ref) 167 int bind, int ref)
167{ 168{
168 unsigned char *b = skb_tail_pointer(skb); 169 unsigned char *b = skb_tail_pointer(skb);
169 struct tcf_gact *gact = a->priv; 170 struct tcf_gact *gact = to_gact(a);
170 struct tc_gact opt = { 171 struct tc_gact opt = {
171 .index = gact->tcf_index, 172 .index = gact->tcf_index,
172 .refcnt = gact->tcf_refcnt - ref, 173 .refcnt = gact->tcf_refcnt - ref,
@@ -201,14 +202,14 @@ nla_put_failure:
201 202
202static int tcf_gact_walker(struct net *net, struct sk_buff *skb, 203static int tcf_gact_walker(struct net *net, struct sk_buff *skb,
203 struct netlink_callback *cb, int type, 204 struct netlink_callback *cb, int type,
204 struct tc_action *a) 205 const struct tc_action_ops *ops)
205{ 206{
206 struct tc_action_net *tn = net_generic(net, gact_net_id); 207 struct tc_action_net *tn = net_generic(net, gact_net_id);
207 208
208 return tcf_generic_walker(tn, skb, cb, type, a); 209 return tcf_generic_walker(tn, skb, cb, type, ops);
209} 210}
210 211
211static int tcf_gact_search(struct net *net, struct tc_action *a, u32 index) 212static int tcf_gact_search(struct net *net, struct tc_action **a, u32 index)
212{ 213{
213 struct tc_action_net *tn = net_generic(net, gact_net_id); 214 struct tc_action_net *tn = net_generic(net, gact_net_id);
214 215
@@ -225,6 +226,7 @@ static struct tc_action_ops act_gact_ops = {
225 .init = tcf_gact_init, 226 .init = tcf_gact_init,
226 .walk = tcf_gact_walker, 227 .walk = tcf_gact_walker,
227 .lookup = tcf_gact_search, 228 .lookup = tcf_gact_search,
229 .size = sizeof(struct tcf_gact),
228}; 230};
229 231
230static __net_init int gact_init_net(struct net *net) 232static __net_init int gact_init_net(struct net *net)
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 845ab5119c05..141a06eeb1e5 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -37,6 +37,7 @@
37 37
38static int ife_net_id; 38static int ife_net_id;
39static int max_metacnt = IFE_META_MAX + 1; 39static int max_metacnt = IFE_META_MAX + 1;
40static struct tc_action_ops act_ife_ops;
40 41
41static const struct nla_policy ife_policy[TCA_IFE_MAX + 1] = { 42static const struct nla_policy ife_policy[TCA_IFE_MAX + 1] = {
42 [TCA_IFE_PARMS] = { .len = sizeof(struct tc_ife)}, 43 [TCA_IFE_PARMS] = { .len = sizeof(struct tc_ife)},
@@ -364,7 +365,7 @@ out_nlmsg_trim:
364/* under ife->tcf_lock */ 365/* under ife->tcf_lock */
365static void _tcf_ife_cleanup(struct tc_action *a, int bind) 366static void _tcf_ife_cleanup(struct tc_action *a, int bind)
366{ 367{
367 struct tcf_ife_info *ife = a->priv; 368 struct tcf_ife_info *ife = to_ife(a);
368 struct tcf_meta_info *e, *n; 369 struct tcf_meta_info *e, *n;
369 370
370 list_for_each_entry_safe(e, n, &ife->metalist, metalist) { 371 list_for_each_entry_safe(e, n, &ife->metalist, metalist) {
@@ -382,7 +383,7 @@ static void _tcf_ife_cleanup(struct tc_action *a, int bind)
382 383
383static void tcf_ife_cleanup(struct tc_action *a, int bind) 384static void tcf_ife_cleanup(struct tc_action *a, int bind)
384{ 385{
385 struct tcf_ife_info *ife = a->priv; 386 struct tcf_ife_info *ife = to_ife(a);
386 387
387 spin_lock_bh(&ife->tcf_lock); 388 spin_lock_bh(&ife->tcf_lock);
388 _tcf_ife_cleanup(a, bind); 389 _tcf_ife_cleanup(a, bind);
@@ -417,7 +418,7 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb,
417} 418}
418 419
419static int tcf_ife_init(struct net *net, struct nlattr *nla, 420static int tcf_ife_init(struct net *net, struct nlattr *nla,
420 struct nlattr *est, struct tc_action *a, 421 struct nlattr *est, struct tc_action **a,
421 int ovr, int bind) 422 int ovr, int bind)
422{ 423{
423 struct tc_action_net *tn = net_generic(net, ife_net_id); 424 struct tc_action_net *tn = net_generic(net, ife_net_id);
@@ -451,25 +452,25 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
451 **/ 452 **/
452 if (!tb[TCA_IFE_TYPE]) { 453 if (!tb[TCA_IFE_TYPE]) {
453 if (exists) 454 if (exists)
454 tcf_hash_release(a, bind); 455 tcf_hash_release(*a, bind);
455 pr_info("You MUST pass etherype for encoding\n"); 456 pr_info("You MUST pass etherype for encoding\n");
456 return -EINVAL; 457 return -EINVAL;
457 } 458 }
458 } 459 }
459 460
460 if (!exists) { 461 if (!exists) {
461 ret = tcf_hash_create(tn, parm->index, est, a, sizeof(*ife), 462 ret = tcf_hash_create(tn, parm->index, est, a, &act_ife_ops,
462 bind, false); 463 bind, false);
463 if (ret) 464 if (ret)
464 return ret; 465 return ret;
465 ret = ACT_P_CREATED; 466 ret = ACT_P_CREATED;
466 } else { 467 } else {
467 tcf_hash_release(a, bind); 468 tcf_hash_release(*a, bind);
468 if (!ovr) 469 if (!ovr)
469 return -EEXIST; 470 return -EEXIST;
470 } 471 }
471 472
472 ife = to_ife(a); 473 ife = to_ife(*a);
473 ife->flags = parm->flags; 474 ife->flags = parm->flags;
474 475
475 if (parm->flags & IFE_ENCODE) { 476 if (parm->flags & IFE_ENCODE) {
@@ -507,9 +508,9 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
507 if (err) { 508 if (err) {
508metadata_parse_err: 509metadata_parse_err:
509 if (exists) 510 if (exists)
510 tcf_hash_release(a, bind); 511 tcf_hash_release(*a, bind);
511 if (ret == ACT_P_CREATED) 512 if (ret == ACT_P_CREATED)
512 _tcf_ife_cleanup(a, bind); 513 _tcf_ife_cleanup(*a, bind);
513 514
514 if (exists) 515 if (exists)
515 spin_unlock_bh(&ife->tcf_lock); 516 spin_unlock_bh(&ife->tcf_lock);
@@ -529,7 +530,7 @@ metadata_parse_err:
529 err = use_all_metadata(ife); 530 err = use_all_metadata(ife);
530 if (err) { 531 if (err) {
531 if (ret == ACT_P_CREATED) 532 if (ret == ACT_P_CREATED)
532 _tcf_ife_cleanup(a, bind); 533 _tcf_ife_cleanup(*a, bind);
533 534
534 if (exists) 535 if (exists)
535 spin_unlock_bh(&ife->tcf_lock); 536 spin_unlock_bh(&ife->tcf_lock);
@@ -541,7 +542,7 @@ metadata_parse_err:
541 spin_unlock_bh(&ife->tcf_lock); 542 spin_unlock_bh(&ife->tcf_lock);
542 543
543 if (ret == ACT_P_CREATED) 544 if (ret == ACT_P_CREATED)
544 tcf_hash_insert(tn, a); 545 tcf_hash_insert(tn, *a);
545 546
546 return ret; 547 return ret;
547} 548}
@@ -550,7 +551,7 @@ static int tcf_ife_dump(struct sk_buff *skb, struct tc_action *a, int bind,
550 int ref) 551 int ref)
551{ 552{
552 unsigned char *b = skb_tail_pointer(skb); 553 unsigned char *b = skb_tail_pointer(skb);
553 struct tcf_ife_info *ife = a->priv; 554 struct tcf_ife_info *ife = to_ife(a);
554 struct tc_ife opt = { 555 struct tc_ife opt = {
555 .index = ife->tcf_index, 556 .index = ife->tcf_index,
556 .refcnt = ife->tcf_refcnt - ref, 557 .refcnt = ife->tcf_refcnt - ref,
@@ -623,7 +624,7 @@ struct meta_tlvhdr {
623static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a, 624static int tcf_ife_decode(struct sk_buff *skb, const struct tc_action *a,
624 struct tcf_result *res) 625 struct tcf_result *res)
625{ 626{
626 struct tcf_ife_info *ife = a->priv; 627 struct tcf_ife_info *ife = to_ife(a);
627 int action = ife->tcf_action; 628 int action = ife->tcf_action;
628 struct ifeheadr *ifehdr = (struct ifeheadr *)skb->data; 629 struct ifeheadr *ifehdr = (struct ifeheadr *)skb->data;
629 u16 ifehdrln = ifehdr->metalen; 630 u16 ifehdrln = ifehdr->metalen;
@@ -695,7 +696,7 @@ static int ife_get_sz(struct sk_buff *skb, struct tcf_ife_info *ife)
695static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a, 696static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a,
696 struct tcf_result *res) 697 struct tcf_result *res)
697{ 698{
698 struct tcf_ife_info *ife = a->priv; 699 struct tcf_ife_info *ife = to_ife(a);
699 int action = ife->tcf_action; 700 int action = ife->tcf_action;
700 struct ethhdr *oethh; /* outer ether header */ 701 struct ethhdr *oethh; /* outer ether header */
701 struct ethhdr *iethh; /* inner eth header */ 702 struct ethhdr *iethh; /* inner eth header */
@@ -799,7 +800,7 @@ static int tcf_ife_encode(struct sk_buff *skb, const struct tc_action *a,
799static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a, 800static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a,
800 struct tcf_result *res) 801 struct tcf_result *res)
801{ 802{
802 struct tcf_ife_info *ife = a->priv; 803 struct tcf_ife_info *ife = to_ife(a);
803 804
804 if (ife->flags & IFE_ENCODE) 805 if (ife->flags & IFE_ENCODE)
805 return tcf_ife_encode(skb, a, res); 806 return tcf_ife_encode(skb, a, res);
@@ -819,14 +820,14 @@ static int tcf_ife_act(struct sk_buff *skb, const struct tc_action *a,
819 820
820static int tcf_ife_walker(struct net *net, struct sk_buff *skb, 821static int tcf_ife_walker(struct net *net, struct sk_buff *skb,
821 struct netlink_callback *cb, int type, 822 struct netlink_callback *cb, int type,
822 struct tc_action *a) 823 const struct tc_action_ops *ops)
823{ 824{
824 struct tc_action_net *tn = net_generic(net, ife_net_id); 825 struct tc_action_net *tn = net_generic(net, ife_net_id);
825 826
826 return tcf_generic_walker(tn, skb, cb, type, a); 827 return tcf_generic_walker(tn, skb, cb, type, ops);
827} 828}
828 829
829static int tcf_ife_search(struct net *net, struct tc_action *a, u32 index) 830static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index)
830{ 831{
831 struct tc_action_net *tn = net_generic(net, ife_net_id); 832 struct tc_action_net *tn = net_generic(net, ife_net_id);
832 833
@@ -843,6 +844,7 @@ static struct tc_action_ops act_ife_ops = {
843 .init = tcf_ife_init, 844 .init = tcf_ife_init,
844 .walk = tcf_ife_walker, 845 .walk = tcf_ife_walker,
845 .lookup = tcf_ife_search, 846 .lookup = tcf_ife_search,
847 .size = sizeof(struct tcf_ife_info),
846}; 848};
847 849
848static __net_init int ife_init_net(struct net *net) 850static __net_init int ife_init_net(struct net *net)
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index b8c50600697a..378c1c976058 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -31,8 +31,10 @@
31#define IPT_TAB_MASK 15 31#define IPT_TAB_MASK 15
32 32
33static int ipt_net_id; 33static int ipt_net_id;
34static struct tc_action_ops act_ipt_ops;
34 35
35static int xt_net_id; 36static int xt_net_id;
37static struct tc_action_ops act_xt_ops;
36 38
37static int ipt_init_target(struct xt_entry_target *t, char *table, 39static int ipt_init_target(struct xt_entry_target *t, char *table,
38 unsigned int hook) 40 unsigned int hook)
@@ -90,8 +92,8 @@ static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = {
90}; 92};
91 93
92static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla, 94static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
93 struct nlattr *est, struct tc_action *a, int ovr, 95 struct nlattr *est, struct tc_action **a,
94 int bind) 96 const struct tc_action_ops *ops, int ovr, int bind)
95{ 97{
96 struct nlattr *tb[TCA_IPT_MAX + 1]; 98 struct nlattr *tb[TCA_IPT_MAX + 1];
97 struct tcf_ipt *ipt; 99 struct tcf_ipt *ipt;
@@ -118,19 +120,19 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
118 120
119 if (tb[TCA_IPT_HOOK] == NULL || tb[TCA_IPT_TARG] == NULL) { 121 if (tb[TCA_IPT_HOOK] == NULL || tb[TCA_IPT_TARG] == NULL) {
120 if (exists) 122 if (exists)
121 tcf_hash_release(a, bind); 123 tcf_hash_release(*a, bind);
122 return -EINVAL; 124 return -EINVAL;
123 } 125 }
124 126
125 td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]); 127 td = (struct xt_entry_target *)nla_data(tb[TCA_IPT_TARG]);
126 if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) { 128 if (nla_len(tb[TCA_IPT_TARG]) < td->u.target_size) {
127 if (exists) 129 if (exists)
128 tcf_hash_release(a, bind); 130 tcf_hash_release(*a, bind);
129 return -EINVAL; 131 return -EINVAL;
130 } 132 }
131 133
132 if (!exists) { 134 if (!exists) {
133 ret = tcf_hash_create(tn, index, est, a, sizeof(*ipt), bind, 135 ret = tcf_hash_create(tn, index, est, a, ops, bind,
134 false); 136 false);
135 if (ret) 137 if (ret)
136 return ret; 138 return ret;
@@ -138,13 +140,11 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
138 } else { 140 } else {
139 if (bind)/* dont override defaults */ 141 if (bind)/* dont override defaults */
140 return 0; 142 return 0;
141 tcf_hash_release(a, bind); 143 tcf_hash_release(*a, bind);
142 144
143 if (!ovr) 145 if (!ovr)
144 return -EEXIST; 146 return -EEXIST;
145 } 147 }
146 ipt = to_ipt(a);
147
148 hook = nla_get_u32(tb[TCA_IPT_HOOK]); 148 hook = nla_get_u32(tb[TCA_IPT_HOOK]);
149 149
150 err = -ENOMEM; 150 err = -ENOMEM;
@@ -163,6 +163,8 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
163 if (err < 0) 163 if (err < 0)
164 goto err3; 164 goto err3;
165 165
166 ipt = to_ipt(*a);
167
166 spin_lock_bh(&ipt->tcf_lock); 168 spin_lock_bh(&ipt->tcf_lock);
167 if (ret != ACT_P_CREATED) { 169 if (ret != ACT_P_CREATED) {
168 ipt_destroy_target(ipt->tcfi_t); 170 ipt_destroy_target(ipt->tcfi_t);
@@ -174,7 +176,7 @@ static int __tcf_ipt_init(struct tc_action_net *tn, struct nlattr *nla,
174 ipt->tcfi_hook = hook; 176 ipt->tcfi_hook = hook;
175 spin_unlock_bh(&ipt->tcf_lock); 177 spin_unlock_bh(&ipt->tcf_lock);
176 if (ret == ACT_P_CREATED) 178 if (ret == ACT_P_CREATED)
177 tcf_hash_insert(tn, a); 179 tcf_hash_insert(tn, *a);
178 return ret; 180 return ret;
179 181
180err3: 182err3:
@@ -183,33 +185,33 @@ err2:
183 kfree(tname); 185 kfree(tname);
184err1: 186err1:
185 if (ret == ACT_P_CREATED) 187 if (ret == ACT_P_CREATED)
186 tcf_hash_cleanup(a, est); 188 tcf_hash_cleanup(*a, est);
187 return err; 189 return err;
188} 190}
189 191
190static int tcf_ipt_init(struct net *net, struct nlattr *nla, 192static int tcf_ipt_init(struct net *net, struct nlattr *nla,
191 struct nlattr *est, struct tc_action *a, int ovr, 193 struct nlattr *est, struct tc_action **a, int ovr,
192 int bind) 194 int bind)
193{ 195{
194 struct tc_action_net *tn = net_generic(net, ipt_net_id); 196 struct tc_action_net *tn = net_generic(net, ipt_net_id);
195 197
196 return __tcf_ipt_init(tn, nla, est, a, ovr, bind); 198 return __tcf_ipt_init(tn, nla, est, a, &act_ipt_ops, ovr, bind);
197} 199}
198 200
199static int tcf_xt_init(struct net *net, struct nlattr *nla, 201static int tcf_xt_init(struct net *net, struct nlattr *nla,
200 struct nlattr *est, struct tc_action *a, int ovr, 202 struct nlattr *est, struct tc_action **a, int ovr,
201 int bind) 203 int bind)
202{ 204{
203 struct tc_action_net *tn = net_generic(net, xt_net_id); 205 struct tc_action_net *tn = net_generic(net, xt_net_id);
204 206
205 return __tcf_ipt_init(tn, nla, est, a, ovr, bind); 207 return __tcf_ipt_init(tn, nla, est, a, &act_xt_ops, ovr, bind);
206} 208}
207 209
208static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a, 210static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a,
209 struct tcf_result *res) 211 struct tcf_result *res)
210{ 212{
211 int ret = 0, result = 0; 213 int ret = 0, result = 0;
212 struct tcf_ipt *ipt = a->priv; 214 struct tcf_ipt *ipt = to_ipt(a);
213 struct xt_action_param par; 215 struct xt_action_param par;
214 216
215 if (skb_unclone(skb, GFP_ATOMIC)) 217 if (skb_unclone(skb, GFP_ATOMIC))
@@ -259,7 +261,7 @@ static int tcf_ipt_dump(struct sk_buff *skb, struct tc_action *a, int bind,
259 int ref) 261 int ref)
260{ 262{
261 unsigned char *b = skb_tail_pointer(skb); 263 unsigned char *b = skb_tail_pointer(skb);
262 struct tcf_ipt *ipt = a->priv; 264 struct tcf_ipt *ipt = to_ipt(a);
263 struct xt_entry_target *t; 265 struct xt_entry_target *t;
264 struct tcf_t tm; 266 struct tcf_t tm;
265 struct tc_cnt c; 267 struct tc_cnt c;
@@ -299,14 +301,14 @@ nla_put_failure:
299 301
300static int tcf_ipt_walker(struct net *net, struct sk_buff *skb, 302static int tcf_ipt_walker(struct net *net, struct sk_buff *skb,
301 struct netlink_callback *cb, int type, 303 struct netlink_callback *cb, int type,
302 struct tc_action *a) 304 const struct tc_action_ops *ops)
303{ 305{
304 struct tc_action_net *tn = net_generic(net, ipt_net_id); 306 struct tc_action_net *tn = net_generic(net, ipt_net_id);
305 307
306 return tcf_generic_walker(tn, skb, cb, type, a); 308 return tcf_generic_walker(tn, skb, cb, type, ops);
307} 309}
308 310
309static int tcf_ipt_search(struct net *net, struct tc_action *a, u32 index) 311static int tcf_ipt_search(struct net *net, struct tc_action **a, u32 index)
310{ 312{
311 struct tc_action_net *tn = net_generic(net, ipt_net_id); 313 struct tc_action_net *tn = net_generic(net, ipt_net_id);
312 314
@@ -323,6 +325,7 @@ static struct tc_action_ops act_ipt_ops = {
323 .init = tcf_ipt_init, 325 .init = tcf_ipt_init,
324 .walk = tcf_ipt_walker, 326 .walk = tcf_ipt_walker,
325 .lookup = tcf_ipt_search, 327 .lookup = tcf_ipt_search,
328 .size = sizeof(struct tcf_ipt),
326}; 329};
327 330
328static __net_init int ipt_init_net(struct net *net) 331static __net_init int ipt_init_net(struct net *net)
@@ -348,14 +351,14 @@ static struct pernet_operations ipt_net_ops = {
348 351
349static int tcf_xt_walker(struct net *net, struct sk_buff *skb, 352static int tcf_xt_walker(struct net *net, struct sk_buff *skb,
350 struct netlink_callback *cb, int type, 353 struct netlink_callback *cb, int type,
351 struct tc_action *a) 354 const struct tc_action_ops *ops)
352{ 355{
353 struct tc_action_net *tn = net_generic(net, xt_net_id); 356 struct tc_action_net *tn = net_generic(net, xt_net_id);
354 357
355 return tcf_generic_walker(tn, skb, cb, type, a); 358 return tcf_generic_walker(tn, skb, cb, type, ops);
356} 359}
357 360
358static int tcf_xt_search(struct net *net, struct tc_action *a, u32 index) 361static int tcf_xt_search(struct net *net, struct tc_action **a, u32 index)
359{ 362{
360 struct tc_action_net *tn = net_generic(net, xt_net_id); 363 struct tc_action_net *tn = net_generic(net, xt_net_id);
361 364
@@ -372,6 +375,7 @@ static struct tc_action_ops act_xt_ops = {
372 .init = tcf_xt_init, 375 .init = tcf_xt_init,
373 .walk = tcf_xt_walker, 376 .walk = tcf_xt_walker,
374 .lookup = tcf_xt_search, 377 .lookup = tcf_xt_search,
378 .size = sizeof(struct tcf_ipt),
375}; 379};
376 380
377static __net_init int xt_init_net(struct net *net) 381static __net_init int xt_init_net(struct net *net)
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 70cfbbf96af2..6038c85d92f5 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -52,9 +52,10 @@ static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
52}; 52};
53 53
54static int mirred_net_id; 54static int mirred_net_id;
55static struct tc_action_ops act_mirred_ops;
55 56
56static int tcf_mirred_init(struct net *net, struct nlattr *nla, 57static int tcf_mirred_init(struct net *net, struct nlattr *nla,
57 struct nlattr *est, struct tc_action *a, int ovr, 58 struct nlattr *est, struct tc_action **a, int ovr,
58 int bind) 59 int bind)
59{ 60{
60 struct tc_action_net *tn = net_generic(net, mirred_net_id); 61 struct tc_action_net *tn = net_generic(net, mirred_net_id);
@@ -84,14 +85,14 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
84 break; 85 break;
85 default: 86 default:
86 if (exists) 87 if (exists)
87 tcf_hash_release(a, bind); 88 tcf_hash_release(*a, bind);
88 return -EINVAL; 89 return -EINVAL;
89 } 90 }
90 if (parm->ifindex) { 91 if (parm->ifindex) {
91 dev = __dev_get_by_index(net, parm->ifindex); 92 dev = __dev_get_by_index(net, parm->ifindex);
92 if (dev == NULL) { 93 if (dev == NULL) {
93 if (exists) 94 if (exists)
94 tcf_hash_release(a, bind); 95 tcf_hash_release(*a, bind);
95 return -ENODEV; 96 return -ENODEV;
96 } 97 }
97 switch (dev->type) { 98 switch (dev->type) {
@@ -115,16 +116,16 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
115 if (dev == NULL) 116 if (dev == NULL)
116 return -EINVAL; 117 return -EINVAL;
117 ret = tcf_hash_create(tn, parm->index, est, a, 118 ret = tcf_hash_create(tn, parm->index, est, a,
118 sizeof(*m), bind, true); 119 &act_mirred_ops, bind, true);
119 if (ret) 120 if (ret)
120 return ret; 121 return ret;
121 ret = ACT_P_CREATED; 122 ret = ACT_P_CREATED;
122 } else { 123 } else {
123 tcf_hash_release(a, bind); 124 tcf_hash_release(*a, bind);
124 if (!ovr) 125 if (!ovr)
125 return -EEXIST; 126 return -EEXIST;
126 } 127 }
127 m = to_mirred(a); 128 m = to_mirred(*a);
128 129
129 ASSERT_RTNL(); 130 ASSERT_RTNL();
130 m->tcf_action = parm->action; 131 m->tcf_action = parm->action;
@@ -142,7 +143,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
142 spin_lock_bh(&mirred_list_lock); 143 spin_lock_bh(&mirred_list_lock);
143 list_add(&m->tcfm_list, &mirred_list); 144 list_add(&m->tcfm_list, &mirred_list);
144 spin_unlock_bh(&mirred_list_lock); 145 spin_unlock_bh(&mirred_list_lock);
145 tcf_hash_insert(tn, a); 146 tcf_hash_insert(tn, *a);
146 } 147 }
147 148
148 return ret; 149 return ret;
@@ -151,7 +152,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla,
151static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a, 152static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
152 struct tcf_result *res) 153 struct tcf_result *res)
153{ 154{
154 struct tcf_mirred *m = a->priv; 155 struct tcf_mirred *m = to_mirred(a);
155 struct net_device *dev; 156 struct net_device *dev;
156 struct sk_buff *skb2; 157 struct sk_buff *skb2;
157 int retval, err; 158 int retval, err;
@@ -206,7 +207,7 @@ out:
206static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) 207static int tcf_mirred_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
207{ 208{
208 unsigned char *b = skb_tail_pointer(skb); 209 unsigned char *b = skb_tail_pointer(skb);
209 struct tcf_mirred *m = a->priv; 210 struct tcf_mirred *m = to_mirred(a);
210 struct tc_mirred opt = { 211 struct tc_mirred opt = {
211 .index = m->tcf_index, 212 .index = m->tcf_index,
212 .action = m->tcf_action, 213 .action = m->tcf_action,
@@ -232,14 +233,14 @@ nla_put_failure:
232 233
233static int tcf_mirred_walker(struct net *net, struct sk_buff *skb, 234static int tcf_mirred_walker(struct net *net, struct sk_buff *skb,
234 struct netlink_callback *cb, int type, 235 struct netlink_callback *cb, int type,
235 struct tc_action *a) 236 const struct tc_action_ops *ops)
236{ 237{
237 struct tc_action_net *tn = net_generic(net, mirred_net_id); 238 struct tc_action_net *tn = net_generic(net, mirred_net_id);
238 239
239 return tcf_generic_walker(tn, skb, cb, type, a); 240 return tcf_generic_walker(tn, skb, cb, type, ops);
240} 241}
241 242
242static int tcf_mirred_search(struct net *net, struct tc_action *a, u32 index) 243static int tcf_mirred_search(struct net *net, struct tc_action **a, u32 index)
243{ 244{
244 struct tc_action_net *tn = net_generic(net, mirred_net_id); 245 struct tc_action_net *tn = net_generic(net, mirred_net_id);
245 246
@@ -284,6 +285,7 @@ static struct tc_action_ops act_mirred_ops = {
284 .init = tcf_mirred_init, 285 .init = tcf_mirred_init,
285 .walk = tcf_mirred_walker, 286 .walk = tcf_mirred_walker,
286 .lookup = tcf_mirred_search, 287 .lookup = tcf_mirred_search,
288 .size = sizeof(struct tcf_mirred),
287}; 289};
288 290
289static __net_init int mirred_init_net(struct net *net) 291static __net_init int mirred_init_net(struct net *net)
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index 06ccb03f25da..8e8b0cc30704 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -32,13 +32,14 @@
32#define NAT_TAB_MASK 15 32#define NAT_TAB_MASK 15
33 33
34static int nat_net_id; 34static int nat_net_id;
35static struct tc_action_ops act_nat_ops;
35 36
36static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = { 37static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
37 [TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) }, 38 [TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) },
38}; 39};
39 40
40static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, 41static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
41 struct tc_action *a, int ovr, int bind) 42 struct tc_action **a, int ovr, int bind)
42{ 43{
43 struct tc_action_net *tn = net_generic(net, nat_net_id); 44 struct tc_action_net *tn = net_generic(net, nat_net_id);
44 struct nlattr *tb[TCA_NAT_MAX + 1]; 45 struct nlattr *tb[TCA_NAT_MAX + 1];
@@ -59,18 +60,18 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
59 60
60 if (!tcf_hash_check(tn, parm->index, a, bind)) { 61 if (!tcf_hash_check(tn, parm->index, a, bind)) {
61 ret = tcf_hash_create(tn, parm->index, est, a, 62 ret = tcf_hash_create(tn, parm->index, est, a,
62 sizeof(*p), bind, false); 63 &act_nat_ops, bind, false);
63 if (ret) 64 if (ret)
64 return ret; 65 return ret;
65 ret = ACT_P_CREATED; 66 ret = ACT_P_CREATED;
66 } else { 67 } else {
67 if (bind) 68 if (bind)
68 return 0; 69 return 0;
69 tcf_hash_release(a, bind); 70 tcf_hash_release(*a, bind);
70 if (!ovr) 71 if (!ovr)
71 return -EEXIST; 72 return -EEXIST;
72 } 73 }
73 p = to_tcf_nat(a); 74 p = to_tcf_nat(*a);
74 75
75 spin_lock_bh(&p->tcf_lock); 76 spin_lock_bh(&p->tcf_lock);
76 p->old_addr = parm->old_addr; 77 p->old_addr = parm->old_addr;
@@ -82,7 +83,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
82 spin_unlock_bh(&p->tcf_lock); 83 spin_unlock_bh(&p->tcf_lock);
83 84
84 if (ret == ACT_P_CREATED) 85 if (ret == ACT_P_CREATED)
85 tcf_hash_insert(tn, a); 86 tcf_hash_insert(tn, *a);
86 87
87 return ret; 88 return ret;
88} 89}
@@ -90,7 +91,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est,
90static int tcf_nat(struct sk_buff *skb, const struct tc_action *a, 91static int tcf_nat(struct sk_buff *skb, const struct tc_action *a,
91 struct tcf_result *res) 92 struct tcf_result *res)
92{ 93{
93 struct tcf_nat *p = a->priv; 94 struct tcf_nat *p = to_tcf_nat(a);
94 struct iphdr *iph; 95 struct iphdr *iph;
95 __be32 old_addr; 96 __be32 old_addr;
96 __be32 new_addr; 97 __be32 new_addr;
@@ -248,7 +249,7 @@ static int tcf_nat_dump(struct sk_buff *skb, struct tc_action *a,
248 int bind, int ref) 249 int bind, int ref)
249{ 250{
250 unsigned char *b = skb_tail_pointer(skb); 251 unsigned char *b = skb_tail_pointer(skb);
251 struct tcf_nat *p = a->priv; 252 struct tcf_nat *p = to_tcf_nat(a);
252 struct tc_nat opt = { 253 struct tc_nat opt = {
253 .old_addr = p->old_addr, 254 .old_addr = p->old_addr,
254 .new_addr = p->new_addr, 255 .new_addr = p->new_addr,
@@ -278,14 +279,14 @@ nla_put_failure:
278 279
279static int tcf_nat_walker(struct net *net, struct sk_buff *skb, 280static int tcf_nat_walker(struct net *net, struct sk_buff *skb,
280 struct netlink_callback *cb, int type, 281 struct netlink_callback *cb, int type,
281 struct tc_action *a) 282 const struct tc_action_ops *ops)
282{ 283{
283 struct tc_action_net *tn = net_generic(net, nat_net_id); 284 struct tc_action_net *tn = net_generic(net, nat_net_id);
284 285
285 return tcf_generic_walker(tn, skb, cb, type, a); 286 return tcf_generic_walker(tn, skb, cb, type, ops);
286} 287}
287 288
288static int tcf_nat_search(struct net *net, struct tc_action *a, u32 index) 289static int tcf_nat_search(struct net *net, struct tc_action **a, u32 index)
289{ 290{
290 struct tc_action_net *tn = net_generic(net, nat_net_id); 291 struct tc_action_net *tn = net_generic(net, nat_net_id);
291 292
@@ -301,6 +302,7 @@ static struct tc_action_ops act_nat_ops = {
301 .init = tcf_nat_init, 302 .init = tcf_nat_init,
302 .walk = tcf_nat_walker, 303 .walk = tcf_nat_walker,
303 .lookup = tcf_nat_search, 304 .lookup = tcf_nat_search,
305 .size = sizeof(struct tcf_nat),
304}; 306};
305 307
306static __net_init int nat_init_net(struct net *net) 308static __net_init int nat_init_net(struct net *net)
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 82d3c1479029..b54d56d4959b 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -26,13 +26,14 @@
26#define PEDIT_TAB_MASK 15 26#define PEDIT_TAB_MASK 15
27 27
28static int pedit_net_id; 28static int pedit_net_id;
29static struct tc_action_ops act_pedit_ops;
29 30
30static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = { 31static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = {
31 [TCA_PEDIT_PARMS] = { .len = sizeof(struct tc_pedit) }, 32 [TCA_PEDIT_PARMS] = { .len = sizeof(struct tc_pedit) },
32}; 33};
33 34
34static int tcf_pedit_init(struct net *net, struct nlattr *nla, 35static int tcf_pedit_init(struct net *net, struct nlattr *nla,
35 struct nlattr *est, struct tc_action *a, 36 struct nlattr *est, struct tc_action **a,
36 int ovr, int bind) 37 int ovr, int bind)
37{ 38{
38 struct tc_action_net *tn = net_generic(net, pedit_net_id); 39 struct tc_action_net *tn = net_generic(net, pedit_net_id);
@@ -61,23 +62,23 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
61 if (!parm->nkeys) 62 if (!parm->nkeys)
62 return -EINVAL; 63 return -EINVAL;
63 ret = tcf_hash_create(tn, parm->index, est, a, 64 ret = tcf_hash_create(tn, parm->index, est, a,
64 sizeof(*p), bind, false); 65 &act_pedit_ops, bind, false);
65 if (ret) 66 if (ret)
66 return ret; 67 return ret;
67 p = to_pedit(a); 68 p = to_pedit(*a);
68 keys = kmalloc(ksize, GFP_KERNEL); 69 keys = kmalloc(ksize, GFP_KERNEL);
69 if (keys == NULL) { 70 if (keys == NULL) {
70 tcf_hash_cleanup(a, est); 71 tcf_hash_cleanup(*a, est);
71 return -ENOMEM; 72 return -ENOMEM;
72 } 73 }
73 ret = ACT_P_CREATED; 74 ret = ACT_P_CREATED;
74 } else { 75 } else {
75 if (bind) 76 if (bind)
76 return 0; 77 return 0;
77 tcf_hash_release(a, bind); 78 tcf_hash_release(*a, bind);
78 if (!ovr) 79 if (!ovr)
79 return -EEXIST; 80 return -EEXIST;
80 p = to_pedit(a); 81 p = to_pedit(*a);
81 if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) { 82 if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) {
82 keys = kmalloc(ksize, GFP_KERNEL); 83 keys = kmalloc(ksize, GFP_KERNEL);
83 if (keys == NULL) 84 if (keys == NULL)
@@ -96,13 +97,13 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla,
96 memcpy(p->tcfp_keys, parm->keys, ksize); 97 memcpy(p->tcfp_keys, parm->keys, ksize);
97 spin_unlock_bh(&p->tcf_lock); 98 spin_unlock_bh(&p->tcf_lock);
98 if (ret == ACT_P_CREATED) 99 if (ret == ACT_P_CREATED)
99 tcf_hash_insert(tn, a); 100 tcf_hash_insert(tn, *a);
100 return ret; 101 return ret;
101} 102}
102 103
103static void tcf_pedit_cleanup(struct tc_action *a, int bind) 104static void tcf_pedit_cleanup(struct tc_action *a, int bind)
104{ 105{
105 struct tcf_pedit *p = a->priv; 106 struct tcf_pedit *p = to_pedit(a);
106 struct tc_pedit_key *keys = p->tcfp_keys; 107 struct tc_pedit_key *keys = p->tcfp_keys;
107 kfree(keys); 108 kfree(keys);
108} 109}
@@ -110,7 +111,7 @@ static void tcf_pedit_cleanup(struct tc_action *a, int bind)
110static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a, 111static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a,
111 struct tcf_result *res) 112 struct tcf_result *res)
112{ 113{
113 struct tcf_pedit *p = a->priv; 114 struct tcf_pedit *p = to_pedit(a);
114 int i; 115 int i;
115 unsigned int off; 116 unsigned int off;
116 117
@@ -177,7 +178,7 @@ static int tcf_pedit_dump(struct sk_buff *skb, struct tc_action *a,
177 int bind, int ref) 178 int bind, int ref)
178{ 179{
179 unsigned char *b = skb_tail_pointer(skb); 180 unsigned char *b = skb_tail_pointer(skb);
180 struct tcf_pedit *p = a->priv; 181 struct tcf_pedit *p = to_pedit(a);
181 struct tc_pedit *opt; 182 struct tc_pedit *opt;
182 struct tcf_t t; 183 struct tcf_t t;
183 int s; 184 int s;
@@ -216,14 +217,14 @@ nla_put_failure:
216 217
217static int tcf_pedit_walker(struct net *net, struct sk_buff *skb, 218static int tcf_pedit_walker(struct net *net, struct sk_buff *skb,
218 struct netlink_callback *cb, int type, 219 struct netlink_callback *cb, int type,
219 struct tc_action *a) 220 const struct tc_action_ops *ops)
220{ 221{
221 struct tc_action_net *tn = net_generic(net, pedit_net_id); 222 struct tc_action_net *tn = net_generic(net, pedit_net_id);
222 223
223 return tcf_generic_walker(tn, skb, cb, type, a); 224 return tcf_generic_walker(tn, skb, cb, type, ops);
224} 225}
225 226
226static int tcf_pedit_search(struct net *net, struct tc_action *a, u32 index) 227static int tcf_pedit_search(struct net *net, struct tc_action **a, u32 index)
227{ 228{
228 struct tc_action_net *tn = net_generic(net, pedit_net_id); 229 struct tc_action_net *tn = net_generic(net, pedit_net_id);
229 230
@@ -240,6 +241,7 @@ static struct tc_action_ops act_pedit_ops = {
240 .init = tcf_pedit_init, 241 .init = tcf_pedit_init,
241 .walk = tcf_pedit_walker, 242 .walk = tcf_pedit_walker,
242 .lookup = tcf_pedit_search, 243 .lookup = tcf_pedit_search,
244 .size = sizeof(struct tcf_pedit),
243}; 245};
244 246
245static __net_init int pedit_init_net(struct net *net) 247static __net_init int pedit_init_net(struct net *net)
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 1e8ede3955f4..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
58static int police_net_id; 58static int police_net_id;
59static struct tc_action_ops act_police_ops;
59 60
60static int tcf_act_police_walker(struct net *net, struct sk_buff *skb, 61static int tcf_act_police_walker(struct net *net, struct sk_buff *skb,
61 struct netlink_callback *cb, int type, 62 struct netlink_callback *cb, int type,
62 struct tc_action *a) 63 const struct tc_action_ops *ops)
63{ 64{
64 struct tc_action_net *tn = net_generic(net, police_net_id); 65 struct tc_action_net *tn = net_generic(net, police_net_id);
65 struct tcf_hashinfo *hinfo = tn->hinfo; 66 struct tcf_hashinfo *hinfo = tn->hinfo;
66 struct hlist_head *head;
67 struct tcf_common *p;
68 int err = 0, index = -1, i = 0, s_i = 0, n_i = 0; 67 int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
69 struct nlattr *nest; 68 struct nlattr *nest;
70 69
@@ -73,21 +72,22 @@ static int tcf_act_police_walker(struct net *net, struct sk_buff *skb,
73 s_i = cb->args[0]; 72 s_i = cb->args[0];
74 73
75 for (i = 0; i < (POL_TAB_MASK + 1); i++) { 74 for (i = 0; i < (POL_TAB_MASK + 1); i++) {
75 struct hlist_head *head;
76 struct 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
118static int tcf_act_police_init(struct net *net, struct nlattr *nla, 118static int tcf_act_police_init(struct net *net, struct nlattr *nla,
119 struct nlattr *est, struct tc_action *a, 119 struct nlattr *est, struct tc_action **a,
120 int ovr, int bind) 120 int ovr, int bind)
121{ 121{
122 int ret = 0, err; 122 int ret = 0, err;
@@ -142,13 +142,7 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
142 parm = nla_data(tb[TCA_POLICE_TBF]); 142 parm = nla_data(tb[TCA_POLICE_TBF]);
143 143
144 if (parm->index) { 144 if (parm->index) {
145 if (tcf_hash_search(tn, a, parm->index)) { 145 if (tcf_hash_check(tn, parm->index, a, bind)) {
146 police = to_police(a);
147 if (bind) {
148 police->tcf_bindcnt += 1;
149 police->tcf_refcnt += 1;
150 return 0;
151 }
152 if (ovr) 146 if (ovr)
153 goto override; 147 goto override;
154 /* not replacing */ 148 /* not replacing */
@@ -156,14 +150,14 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,
156 } 150 }
157 } else { 151 } else {
158 ret = tcf_hash_create(tn, parm->index, NULL, a, 152 ret = tcf_hash_create(tn, parm->index, NULL, a,
159 sizeof(*police), bind, false); 153 &act_police_ops, bind, false);
160 if (ret) 154 if (ret)
161 return ret; 155 return ret;
162 ret = ACT_P_CREATED; 156 ret = ACT_P_CREATED;
163 } 157 }
164 158
165 police = to_police(a);
166override: 159override:
160 police = to_police(*a);
167 if (parm->rate.rate) { 161 if (parm->rate.rate) {
168 err = -ENOMEM; 162 err = -ENOMEM;
169 R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]); 163 R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]);
@@ -235,7 +229,7 @@ override:
235 return ret; 229 return ret;
236 230
237 police->tcfp_t_c = ktime_get_ns(); 231 police->tcfp_t_c = ktime_get_ns();
238 tcf_hash_insert(tn, a); 232 tcf_hash_insert(tn, *a);
239 233
240 return ret; 234 return ret;
241 235
@@ -245,14 +239,14 @@ failure:
245 qdisc_put_rtab(P_tab); 239 qdisc_put_rtab(P_tab);
246 qdisc_put_rtab(R_tab); 240 qdisc_put_rtab(R_tab);
247 if (ret == ACT_P_CREATED) 241 if (ret == ACT_P_CREATED)
248 tcf_hash_cleanup(a, est); 242 tcf_hash_cleanup(*a, est);
249 return err; 243 return err;
250} 244}
251 245
252static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a, 246static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a,
253 struct tcf_result *res) 247 struct tcf_result *res)
254{ 248{
255 struct tcf_police *police = a->priv; 249 struct tcf_police *police = to_police(a);
256 s64 now; 250 s64 now;
257 s64 toks; 251 s64 toks;
258 s64 ptoks = 0; 252 s64 ptoks = 0;
@@ -311,7 +305,7 @@ static int
311tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) 305tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
312{ 306{
313 unsigned char *b = skb_tail_pointer(skb); 307 unsigned char *b = skb_tail_pointer(skb);
314 struct tcf_police *police = a->priv; 308 struct tcf_police *police = to_police(a);
315 struct tc_police opt = { 309 struct tc_police opt = {
316 .index = police->tcf_index, 310 .index = police->tcf_index,
317 .action = police->tcf_action, 311 .action = police->tcf_action,
@@ -349,7 +343,7 @@ nla_put_failure:
349 return -1; 343 return -1;
350} 344}
351 345
352static int tcf_police_search(struct net *net, struct tc_action *a, u32 index) 346static int tcf_police_search(struct net *net, struct tc_action **a, u32 index)
353{ 347{
354 struct tc_action_net *tn = net_generic(net, police_net_id); 348 struct tc_action_net *tn = net_generic(net, police_net_id);
355 349
@@ -369,6 +363,7 @@ static struct tc_action_ops act_police_ops = {
369 .init = tcf_act_police_init, 363 .init = tcf_act_police_init,
370 .walk = tcf_act_police_walker, 364 .walk = tcf_act_police_walker,
371 .lookup = tcf_police_search, 365 .lookup = tcf_police_search,
366 .size = sizeof(struct tcf_police),
372}; 367};
373 368
374static __net_init int police_init_net(struct net *net) 369static __net_init int police_init_net(struct net *net)
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 318328d34d12..289af6f9bb3b 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -27,12 +27,13 @@
27#define SIMP_TAB_MASK 7 27#define SIMP_TAB_MASK 7
28 28
29static int simp_net_id; 29static int simp_net_id;
30static struct tc_action_ops act_simp_ops;
30 31
31#define SIMP_MAX_DATA 32 32#define SIMP_MAX_DATA 32
32static int tcf_simp(struct sk_buff *skb, const struct tc_action *a, 33static int tcf_simp(struct sk_buff *skb, const struct tc_action *a,
33 struct tcf_result *res) 34 struct tcf_result *res)
34{ 35{
35 struct tcf_defact *d = a->priv; 36 struct tcf_defact *d = to_defact(a);
36 37
37 spin_lock(&d->tcf_lock); 38 spin_lock(&d->tcf_lock);
38 tcf_lastuse_update(&d->tcf_tm); 39 tcf_lastuse_update(&d->tcf_tm);
@@ -79,7 +80,7 @@ static const struct nla_policy simple_policy[TCA_DEF_MAX + 1] = {
79}; 80};
80 81
81static int tcf_simp_init(struct net *net, struct nlattr *nla, 82static int tcf_simp_init(struct net *net, struct nlattr *nla,
82 struct nlattr *est, struct tc_action *a, 83 struct nlattr *est, struct tc_action **a,
83 int ovr, int bind) 84 int ovr, int bind)
84{ 85{
85 struct tc_action_net *tn = net_generic(net, simp_net_id); 86 struct tc_action_net *tn = net_generic(net, simp_net_id);
@@ -100,7 +101,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
100 if (tb[TCA_DEF_PARMS] == NULL) 101 if (tb[TCA_DEF_PARMS] == NULL)
101 return -EINVAL; 102 return -EINVAL;
102 103
103
104 parm = nla_data(tb[TCA_DEF_PARMS]); 104 parm = nla_data(tb[TCA_DEF_PARMS]);
105 exists = tcf_hash_check(tn, parm->index, a, bind); 105 exists = tcf_hash_check(tn, parm->index, a, bind);
106 if (exists && bind) 106 if (exists && bind)
@@ -108,7 +108,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
108 108
109 if (tb[TCA_DEF_DATA] == NULL) { 109 if (tb[TCA_DEF_DATA] == NULL) {
110 if (exists) 110 if (exists)
111 tcf_hash_release(a, bind); 111 tcf_hash_release(*a, bind);
112 return -EINVAL; 112 return -EINVAL;
113 } 113 }
114 114
@@ -116,22 +116,22 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
116 116
117 if (!exists) { 117 if (!exists) {
118 ret = tcf_hash_create(tn, parm->index, est, a, 118 ret = tcf_hash_create(tn, parm->index, est, a,
119 sizeof(*d), bind, false); 119 &act_simp_ops, bind, false);
120 if (ret) 120 if (ret)
121 return ret; 121 return ret;
122 122
123 d = to_defact(a); 123 d = to_defact(*a);
124 ret = alloc_defdata(d, defdata); 124 ret = alloc_defdata(d, defdata);
125 if (ret < 0) { 125 if (ret < 0) {
126 tcf_hash_cleanup(a, est); 126 tcf_hash_cleanup(*a, est);
127 return ret; 127 return ret;
128 } 128 }
129 d->tcf_action = parm->action; 129 d->tcf_action = parm->action;
130 ret = ACT_P_CREATED; 130 ret = ACT_P_CREATED;
131 } else { 131 } else {
132 d = to_defact(a); 132 d = to_defact(*a);
133 133
134 tcf_hash_release(a, bind); 134 tcf_hash_release(*a, bind);
135 if (!ovr) 135 if (!ovr)
136 return -EEXIST; 136 return -EEXIST;
137 137
@@ -139,7 +139,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
139 } 139 }
140 140
141 if (ret == ACT_P_CREATED) 141 if (ret == ACT_P_CREATED)
142 tcf_hash_insert(tn, a); 142 tcf_hash_insert(tn, *a);
143 return ret; 143 return ret;
144} 144}
145 145
@@ -147,7 +147,7 @@ static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
147 int bind, int ref) 147 int bind, int ref)
148{ 148{
149 unsigned char *b = skb_tail_pointer(skb); 149 unsigned char *b = skb_tail_pointer(skb);
150 struct tcf_defact *d = a->priv; 150 struct tcf_defact *d = to_defact(a);
151 struct tc_defact opt = { 151 struct tc_defact opt = {
152 .index = d->tcf_index, 152 .index = d->tcf_index,
153 .refcnt = d->tcf_refcnt - ref, 153 .refcnt = d->tcf_refcnt - ref,
@@ -172,14 +172,14 @@ nla_put_failure:
172 172
173static int tcf_simp_walker(struct net *net, struct sk_buff *skb, 173static int tcf_simp_walker(struct net *net, struct sk_buff *skb,
174 struct netlink_callback *cb, int type, 174 struct netlink_callback *cb, int type,
175 struct tc_action *a) 175 const struct tc_action_ops *ops)
176{ 176{
177 struct tc_action_net *tn = net_generic(net, simp_net_id); 177 struct tc_action_net *tn = net_generic(net, simp_net_id);
178 178
179 return tcf_generic_walker(tn, skb, cb, type, a); 179 return tcf_generic_walker(tn, skb, cb, type, ops);
180} 180}
181 181
182static int tcf_simp_search(struct net *net, struct tc_action *a, u32 index) 182static int tcf_simp_search(struct net *net, struct tc_action **a, u32 index)
183{ 183{
184 struct tc_action_net *tn = net_generic(net, simp_net_id); 184 struct tc_action_net *tn = net_generic(net, simp_net_id);
185 185
@@ -196,6 +196,7 @@ static struct tc_action_ops act_simp_ops = {
196 .init = tcf_simp_init, 196 .init = tcf_simp_init,
197 .walk = tcf_simp_walker, 197 .walk = tcf_simp_walker,
198 .lookup = tcf_simp_search, 198 .lookup = tcf_simp_search,
199 .size = sizeof(struct tcf_defact),
199}; 200};
200 201
201static __net_init int simp_init_net(struct net *net) 202static __net_init int simp_init_net(struct net *net)
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 8e573c0f8742..a133dcb82132 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -30,11 +30,12 @@
30#define SKBEDIT_TAB_MASK 15 30#define SKBEDIT_TAB_MASK 15
31 31
32static int skbedit_net_id; 32static int skbedit_net_id;
33static struct tc_action_ops act_skbedit_ops;
33 34
34static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a, 35static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a,
35 struct tcf_result *res) 36 struct tcf_result *res)
36{ 37{
37 struct tcf_skbedit *d = a->priv; 38 struct tcf_skbedit *d = to_skbedit(a);
38 39
39 spin_lock(&d->tcf_lock); 40 spin_lock(&d->tcf_lock);
40 tcf_lastuse_update(&d->tcf_tm); 41 tcf_lastuse_update(&d->tcf_tm);
@@ -63,7 +64,7 @@ static const struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
63}; 64};
64 65
65static int tcf_skbedit_init(struct net *net, struct nlattr *nla, 66static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
66 struct nlattr *est, struct tc_action *a, 67 struct nlattr *est, struct tc_action **a,
67 int ovr, int bind) 68 int ovr, int bind)
68{ 69{
69 struct tc_action_net *tn = net_generic(net, skbedit_net_id); 70 struct tc_action_net *tn = net_generic(net, skbedit_net_id);
@@ -114,21 +115,21 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
114 return 0; 115 return 0;
115 116
116 if (!flags) { 117 if (!flags) {
117 tcf_hash_release(a, bind); 118 tcf_hash_release(*a, bind);
118 return -EINVAL; 119 return -EINVAL;
119 } 120 }
120 121
121 if (!exists) { 122 if (!exists) {
122 ret = tcf_hash_create(tn, parm->index, est, a, 123 ret = tcf_hash_create(tn, parm->index, est, a,
123 sizeof(*d), bind, false); 124 &act_skbedit_ops, bind, false);
124 if (ret) 125 if (ret)
125 return ret; 126 return ret;
126 127
127 d = to_skbedit(a); 128 d = to_skbedit(*a);
128 ret = ACT_P_CREATED; 129 ret = ACT_P_CREATED;
129 } else { 130 } else {
130 d = to_skbedit(a); 131 d = to_skbedit(*a);
131 tcf_hash_release(a, bind); 132 tcf_hash_release(*a, bind);
132 if (!ovr) 133 if (!ovr)
133 return -EEXIST; 134 return -EEXIST;
134 } 135 }
@@ -150,7 +151,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,
150 spin_unlock_bh(&d->tcf_lock); 151 spin_unlock_bh(&d->tcf_lock);
151 152
152 if (ret == ACT_P_CREATED) 153 if (ret == ACT_P_CREATED)
153 tcf_hash_insert(tn, a); 154 tcf_hash_insert(tn, *a);
154 return ret; 155 return ret;
155} 156}
156 157
@@ -158,7 +159,7 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,
158 int bind, int ref) 159 int bind, int ref)
159{ 160{
160 unsigned char *b = skb_tail_pointer(skb); 161 unsigned char *b = skb_tail_pointer(skb);
161 struct tcf_skbedit *d = a->priv; 162 struct tcf_skbedit *d = to_skbedit(a);
162 struct tc_skbedit opt = { 163 struct tc_skbedit opt = {
163 .index = d->tcf_index, 164 .index = d->tcf_index,
164 .refcnt = d->tcf_refcnt - ref, 165 .refcnt = d->tcf_refcnt - ref,
@@ -194,14 +195,14 @@ nla_put_failure:
194 195
195static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb, 196static int tcf_skbedit_walker(struct net *net, struct sk_buff *skb,
196 struct netlink_callback *cb, int type, 197 struct netlink_callback *cb, int type,
197 struct tc_action *a) 198 const struct tc_action_ops *ops)
198{ 199{
199 struct tc_action_net *tn = net_generic(net, skbedit_net_id); 200 struct tc_action_net *tn = net_generic(net, skbedit_net_id);
200 201
201 return tcf_generic_walker(tn, skb, cb, type, a); 202 return tcf_generic_walker(tn, skb, cb, type, ops);
202} 203}
203 204
204static int tcf_skbedit_search(struct net *net, struct tc_action *a, u32 index) 205static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index)
205{ 206{
206 struct tc_action_net *tn = net_generic(net, skbedit_net_id); 207 struct tc_action_net *tn = net_generic(net, skbedit_net_id);
207 208
@@ -217,6 +218,7 @@ static struct tc_action_ops act_skbedit_ops = {
217 .init = tcf_skbedit_init, 218 .init = tcf_skbedit_init,
218 .walk = tcf_skbedit_walker, 219 .walk = tcf_skbedit_walker,
219 .lookup = tcf_skbedit_search, 220 .lookup = tcf_skbedit_search,
221 .size = sizeof(struct tcf_skbedit),
220}; 222};
221 223
222static __net_init int skbedit_init_net(struct net *net) 224static __net_init int skbedit_init_net(struct net *net)
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index db9b7ed570ba..691409de3e1a 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -22,11 +22,12 @@
22#define VLAN_TAB_MASK 15 22#define VLAN_TAB_MASK 15
23 23
24static int vlan_net_id; 24static int vlan_net_id;
25static struct tc_action_ops act_vlan_ops;
25 26
26static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a, 27static int tcf_vlan(struct sk_buff *skb, const struct tc_action *a,
27 struct tcf_result *res) 28 struct tcf_result *res)
28{ 29{
29 struct tcf_vlan *v = a->priv; 30 struct tcf_vlan *v = to_vlan(a);
30 int action; 31 int action;
31 int err; 32 int err;
32 33
@@ -67,7 +68,7 @@ static const struct nla_policy vlan_policy[TCA_VLAN_MAX + 1] = {
67}; 68};
68 69
69static int tcf_vlan_init(struct net *net, struct nlattr *nla, 70static int tcf_vlan_init(struct net *net, struct nlattr *nla,
70 struct nlattr *est, struct tc_action *a, 71 struct nlattr *est, struct tc_action **a,
71 int ovr, int bind) 72 int ovr, int bind)
72{ 73{
73 struct tc_action_net *tn = net_generic(net, vlan_net_id); 74 struct tc_action_net *tn = net_generic(net, vlan_net_id);
@@ -100,13 +101,13 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
100 case TCA_VLAN_ACT_PUSH: 101 case TCA_VLAN_ACT_PUSH:
101 if (!tb[TCA_VLAN_PUSH_VLAN_ID]) { 102 if (!tb[TCA_VLAN_PUSH_VLAN_ID]) {
102 if (exists) 103 if (exists)
103 tcf_hash_release(a, bind); 104 tcf_hash_release(*a, bind);
104 return -EINVAL; 105 return -EINVAL;
105 } 106 }
106 push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]); 107 push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]);
107 if (push_vid >= VLAN_VID_MASK) { 108 if (push_vid >= VLAN_VID_MASK) {
108 if (exists) 109 if (exists)
109 tcf_hash_release(a, bind); 110 tcf_hash_release(*a, bind);
110 return -ERANGE; 111 return -ERANGE;
111 } 112 }
112 113
@@ -125,25 +126,25 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
125 break; 126 break;
126 default: 127 default:
127 if (exists) 128 if (exists)
128 tcf_hash_release(a, bind); 129 tcf_hash_release(*a, bind);
129 return -EINVAL; 130 return -EINVAL;
130 } 131 }
131 action = parm->v_action; 132 action = parm->v_action;
132 133
133 if (!exists) { 134 if (!exists) {
134 ret = tcf_hash_create(tn, parm->index, est, a, 135 ret = tcf_hash_create(tn, parm->index, est, a,
135 sizeof(*v), bind, false); 136 &act_vlan_ops, bind, false);
136 if (ret) 137 if (ret)
137 return ret; 138 return ret;
138 139
139 ret = ACT_P_CREATED; 140 ret = ACT_P_CREATED;
140 } else { 141 } else {
141 tcf_hash_release(a, bind); 142 tcf_hash_release(*a, bind);
142 if (!ovr) 143 if (!ovr)
143 return -EEXIST; 144 return -EEXIST;
144 } 145 }
145 146
146 v = to_vlan(a); 147 v = to_vlan(*a);
147 148
148 spin_lock_bh(&v->tcf_lock); 149 spin_lock_bh(&v->tcf_lock);
149 150
@@ -156,7 +157,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,
156 spin_unlock_bh(&v->tcf_lock); 157 spin_unlock_bh(&v->tcf_lock);
157 158
158 if (ret == ACT_P_CREATED) 159 if (ret == ACT_P_CREATED)
159 tcf_hash_insert(tn, a); 160 tcf_hash_insert(tn, *a);
160 return ret; 161 return ret;
161} 162}
162 163
@@ -164,7 +165,7 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,
164 int bind, int ref) 165 int bind, int ref)
165{ 166{
166 unsigned char *b = skb_tail_pointer(skb); 167 unsigned char *b = skb_tail_pointer(skb);
167 struct tcf_vlan *v = a->priv; 168 struct tcf_vlan *v = to_vlan(a);
168 struct tc_vlan opt = { 169 struct tc_vlan opt = {
169 .index = v->tcf_index, 170 .index = v->tcf_index,
170 .refcnt = v->tcf_refcnt - ref, 171 .refcnt = v->tcf_refcnt - ref,
@@ -195,14 +196,14 @@ nla_put_failure:
195 196
196static int tcf_vlan_walker(struct net *net, struct sk_buff *skb, 197static int tcf_vlan_walker(struct net *net, struct sk_buff *skb,
197 struct netlink_callback *cb, int type, 198 struct netlink_callback *cb, int type,
198 struct tc_action *a) 199 const struct tc_action_ops *ops)
199{ 200{
200 struct tc_action_net *tn = net_generic(net, vlan_net_id); 201 struct tc_action_net *tn = net_generic(net, vlan_net_id);
201 202
202 return tcf_generic_walker(tn, skb, cb, type, a); 203 return tcf_generic_walker(tn, skb, cb, type, ops);
203} 204}
204 205
205static int tcf_vlan_search(struct net *net, struct tc_action *a, u32 index) 206static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index)
206{ 207{
207 struct tc_action_net *tn = net_generic(net, vlan_net_id); 208 struct tc_action_net *tn = net_generic(net, vlan_net_id);
208 209
@@ -218,6 +219,7 @@ static struct tc_action_ops act_vlan_ops = {
218 .init = tcf_vlan_init, 219 .init = tcf_vlan_init,
219 .walk = tcf_vlan_walker, 220 .walk = tcf_vlan_walker,
220 .lookup = tcf_vlan_search, 221 .lookup = tcf_vlan_search,
222 .size = sizeof(struct tcf_vlan),
221}; 223};
222 224
223static __net_init int vlan_init_net(struct net *net) 225static __net_init int vlan_init_net(struct net *net)