hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/net/sched/act_api.c
....@@ -1,14 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * net/sched/act_api.c Packet action API.
34 *
4
- * This program is free software; you can redistribute it and/or
5
- * modify it under the terms of the GNU General Public License
6
- * as published by the Free Software Foundation; either version
7
- * 2 of the License, or (at your option) any later version.
8
- *
95 * Author: Jamal Hadi Salim
10
- *
11
- *
126 */
137
148 #include <linux/types.h>
....@@ -21,8 +15,6 @@
2115 #include <linux/kmod.h>
2216 #include <linux/err.h>
2317 #include <linux/module.h>
24
-#include <linux/rhashtable.h>
25
-#include <linux/list.h>
2618 #include <net/net_namespace.h>
2719 #include <net/sock.h>
2820 #include <net/sch_generic.h>
....@@ -30,27 +22,10 @@
3022 #include <net/act_api.h>
3123 #include <net/netlink.h>
3224
33
-static int tcf_action_goto_chain_init(struct tc_action *a, struct tcf_proto *tp)
34
-{
35
- u32 chain_index = a->tcfa_action & TC_ACT_EXT_VAL_MASK;
36
-
37
- if (!tp)
38
- return -EINVAL;
39
- a->goto_chain = tcf_chain_get_by_act(tp->chain->block, chain_index);
40
- if (!a->goto_chain)
41
- return -ENOMEM;
42
- return 0;
43
-}
44
-
45
-static void tcf_action_goto_chain_fini(struct tc_action *a)
46
-{
47
- tcf_chain_put_by_act(a->goto_chain);
48
-}
49
-
5025 static void tcf_action_goto_chain_exec(const struct tc_action *a,
5126 struct tcf_result *res)
5227 {
53
- const struct tcf_chain *chain = a->goto_chain;
28
+ const struct tcf_chain *chain = rcu_dereference_bh(a->goto_chain);
5429
5530 res->goto_tp = rcu_dereference_bh(chain->filter_chain);
5631 }
....@@ -73,6 +48,51 @@
7348 call_rcu(&old->rcu, tcf_free_cookie_rcu);
7449 }
7550
51
+int tcf_action_check_ctrlact(int action, struct tcf_proto *tp,
52
+ struct tcf_chain **newchain,
53
+ struct netlink_ext_ack *extack)
54
+{
55
+ int opcode = TC_ACT_EXT_OPCODE(action), ret = -EINVAL;
56
+ u32 chain_index;
57
+
58
+ if (!opcode)
59
+ ret = action > TC_ACT_VALUE_MAX ? -EINVAL : 0;
60
+ else if (opcode <= TC_ACT_EXT_OPCODE_MAX || action == TC_ACT_UNSPEC)
61
+ ret = 0;
62
+ if (ret) {
63
+ NL_SET_ERR_MSG(extack, "invalid control action");
64
+ goto end;
65
+ }
66
+
67
+ if (TC_ACT_EXT_CMP(action, TC_ACT_GOTO_CHAIN)) {
68
+ chain_index = action & TC_ACT_EXT_VAL_MASK;
69
+ if (!tp || !newchain) {
70
+ ret = -EINVAL;
71
+ NL_SET_ERR_MSG(extack,
72
+ "can't goto NULL proto/chain");
73
+ goto end;
74
+ }
75
+ *newchain = tcf_chain_get_by_act(tp->chain->block, chain_index);
76
+ if (!*newchain) {
77
+ ret = -ENOMEM;
78
+ NL_SET_ERR_MSG(extack,
79
+ "can't allocate goto_chain");
80
+ }
81
+ }
82
+end:
83
+ return ret;
84
+}
85
+EXPORT_SYMBOL(tcf_action_check_ctrlact);
86
+
87
+struct tcf_chain *tcf_action_set_ctrlact(struct tc_action *a, int action,
88
+ struct tcf_chain *goto_chain)
89
+{
90
+ a->tcfa_action = action;
91
+ goto_chain = rcu_replace_pointer(a->goto_chain, goto_chain, 1);
92
+ return goto_chain;
93
+}
94
+EXPORT_SYMBOL(tcf_action_set_ctrlact);
95
+
7696 /* XXX: For standalone actions, we don't need a RCU grace period either, because
7797 * actions are always connected to filters and filters are already destroyed in
7898 * RCU callbacks, so after a RCU grace period actions are already disconnected
....@@ -80,12 +100,15 @@
80100 */
81101 static void free_tcf(struct tc_action *p)
82102 {
103
+ struct tcf_chain *chain = rcu_dereference_protected(p->goto_chain, 1);
104
+
83105 free_percpu(p->cpu_bstats);
106
+ free_percpu(p->cpu_bstats_hw);
84107 free_percpu(p->cpu_qstats);
85108
86109 tcf_set_action_cookie(&p->act_cookie, NULL);
87
- if (p->goto_chain)
88
- tcf_action_goto_chain_fini(p);
110
+ if (chain)
111
+ tcf_chain_put_by_act(chain);
89112
90113 kfree(p);
91114 }
....@@ -103,11 +126,11 @@
103126 {
104127 struct tcf_idrinfo *idrinfo = p->idrinfo;
105128
106
- if (refcount_dec_and_lock(&p->tcfa_refcnt, &idrinfo->lock)) {
129
+ if (refcount_dec_and_mutex_lock(&p->tcfa_refcnt, &idrinfo->lock)) {
107130 if (bind)
108131 atomic_dec(&p->tcfa_bindcnt);
109132 idr_remove(&idrinfo->action_idr, p->tcfa_index);
110
- spin_unlock(&idrinfo->lock);
133
+ mutex_unlock(&idrinfo->lock);
111134
112135 tcf_action_cleanup(p);
113136 return 1;
....@@ -119,7 +142,7 @@
119142 return 0;
120143 }
121144
122
-int __tcf_idr_release(struct tc_action *p, bool bind, bool strict)
145
+static int __tcf_idr_release(struct tc_action *p, bool bind, bool strict)
123146 {
124147 int ret = 0;
125148
....@@ -145,7 +168,18 @@
145168
146169 return ret;
147170 }
148
-EXPORT_SYMBOL(__tcf_idr_release);
171
+
172
+int tcf_idr_release(struct tc_action *a, bool bind)
173
+{
174
+ const struct tc_action_ops *ops = a->ops;
175
+ int ret;
176
+
177
+ ret = __tcf_idr_release(a, bind, false);
178
+ if (ret == ACT_P_DELETED)
179
+ module_put(ops->owner);
180
+ return ret;
181
+}
182
+EXPORT_SYMBOL(tcf_idr_release);
149183
150184 static size_t tcf_action_shared_attrs_size(const struct tc_action *act)
151185 {
....@@ -162,9 +196,13 @@
162196 return nla_total_size(0) /* action number nested */
163197 + nla_total_size(IFNAMSIZ) /* TCA_ACT_KIND */
164198 + cookie_len /* TCA_ACT_COOKIE */
199
+ + nla_total_size(sizeof(struct nla_bitfield32)) /* TCA_ACT_HW_STATS */
165200 + nla_total_size(0) /* TCA_ACT_STATS nested */
201
+ + nla_total_size(sizeof(struct nla_bitfield32)) /* TCA_ACT_FLAGS */
166202 /* TCA_STATS_BASIC */
167203 + nla_total_size_64bit(sizeof(struct gnet_stats_basic))
204
+ /* TCA_STATS_PKT64 */
205
+ + nla_total_size_64bit(sizeof(u64))
168206 /* TCA_STATS_QUEUE */
169207 + nla_total_size_64bit(sizeof(struct gnet_stats_queue))
170208 + nla_total_size(0) /* TCA_OPTIONS nested */
....@@ -198,14 +236,17 @@
198236 struct idr *idr = &idrinfo->action_idr;
199237 struct tc_action *p;
200238 unsigned long id = 1;
239
+ unsigned long tmp;
201240
202
- spin_lock(&idrinfo->lock);
241
+ mutex_lock(&idrinfo->lock);
203242
204243 s_i = cb->args[0];
205244
206
- idr_for_each_entry_ul(idr, p, id) {
245
+ idr_for_each_entry_ul(idr, p, tmp, id) {
207246 index++;
208247 if (index < s_i)
248
+ continue;
249
+ if (IS_ERR(p))
209250 continue;
210251
211252 if (jiffy_since &&
....@@ -213,7 +254,7 @@
213254 (unsigned long)p->tcfa_tm.lastuse))
214255 continue;
215256
216
- nest = nla_nest_start(skb, n_i);
257
+ nest = nla_nest_start_noflag(skb, n_i);
217258 if (!nest) {
218259 index--;
219260 goto nla_put_failure;
....@@ -234,7 +275,7 @@
234275 if (index >= 0)
235276 cb->args[0] = index + 1;
236277
237
- spin_unlock(&idrinfo->lock);
278
+ mutex_unlock(&idrinfo->lock);
238279 if (n_i) {
239280 if (act_flags & TCA_FLAG_LARGE_DUMP_ON)
240281 cb->args[1] = n_i;
....@@ -246,8 +287,23 @@
246287 goto done;
247288 }
248289
290
+static int tcf_idr_release_unsafe(struct tc_action *p)
291
+{
292
+ if (atomic_read(&p->tcfa_bindcnt) > 0)
293
+ return -EPERM;
294
+
295
+ if (refcount_dec_and_test(&p->tcfa_refcnt)) {
296
+ idr_remove(&p->idrinfo->action_idr, p->tcfa_index);
297
+ tcf_action_cleanup(p);
298
+ return ACT_P_DELETED;
299
+ }
300
+
301
+ return 0;
302
+}
303
+
249304 static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb,
250
- const struct tc_action_ops *ops)
305
+ const struct tc_action_ops *ops,
306
+ struct netlink_ext_ack *extack)
251307 {
252308 struct nlattr *nest;
253309 int n_i = 0;
....@@ -255,23 +311,36 @@
255311 struct idr *idr = &idrinfo->action_idr;
256312 struct tc_action *p;
257313 unsigned long id = 1;
314
+ unsigned long tmp;
258315
259
- nest = nla_nest_start(skb, 0);
316
+ nest = nla_nest_start_noflag(skb, 0);
260317 if (nest == NULL)
261318 goto nla_put_failure;
262319 if (nla_put_string(skb, TCA_KIND, ops->kind))
263320 goto nla_put_failure;
264321
265
- idr_for_each_entry_ul(idr, p, id) {
266
- ret = __tcf_idr_release(p, false, true);
267
- if (ret == ACT_P_DELETED) {
322
+ ret = 0;
323
+ mutex_lock(&idrinfo->lock);
324
+ idr_for_each_entry_ul(idr, p, tmp, id) {
325
+ if (IS_ERR(p))
326
+ continue;
327
+ ret = tcf_idr_release_unsafe(p);
328
+ if (ret == ACT_P_DELETED)
268329 module_put(ops->owner);
269
- n_i++;
270
- } else if (ret < 0) {
271
- goto nla_put_failure;
272
- }
330
+ else if (ret < 0)
331
+ break;
332
+ n_i++;
273333 }
274
- if (nla_put_u32(skb, TCA_FCNT, n_i))
334
+ mutex_unlock(&idrinfo->lock);
335
+ if (ret < 0) {
336
+ if (n_i)
337
+ NL_SET_ERR_MSG(extack, "Unable to flush all TC actions");
338
+ else
339
+ goto nla_put_failure;
340
+ }
341
+
342
+ ret = nla_put_u32(skb, TCA_FCNT, n_i);
343
+ if (ret)
275344 goto nla_put_failure;
276345 nla_nest_end(skb, nest);
277346
....@@ -289,7 +358,7 @@
289358 struct tcf_idrinfo *idrinfo = tn->idrinfo;
290359
291360 if (type == RTM_DELACTION) {
292
- return tcf_del_walker(idrinfo, skb, ops);
361
+ return tcf_del_walker(idrinfo, skb, ops, extack);
293362 } else if (type == RTM_GETACTION) {
294363 return tcf_dump_walker(idrinfo, skb, cb);
295364 } else {
....@@ -305,13 +374,13 @@
305374 struct tcf_idrinfo *idrinfo = tn->idrinfo;
306375 struct tc_action *p;
307376
308
- spin_lock(&idrinfo->lock);
377
+ mutex_lock(&idrinfo->lock);
309378 p = idr_find(&idrinfo->action_idr, index);
310379 if (IS_ERR(p))
311380 p = NULL;
312381 else if (p)
313382 refcount_inc(&p->tcfa_refcnt);
314
- spin_unlock(&idrinfo->lock);
383
+ mutex_unlock(&idrinfo->lock);
315384
316385 if (p) {
317386 *a = p;
....@@ -326,10 +395,10 @@
326395 struct tc_action *p;
327396 int ret = 0;
328397
329
- spin_lock(&idrinfo->lock);
398
+ mutex_lock(&idrinfo->lock);
330399 p = idr_find(&idrinfo->action_idr, index);
331400 if (!p) {
332
- spin_unlock(&idrinfo->lock);
401
+ mutex_unlock(&idrinfo->lock);
333402 return -ENOENT;
334403 }
335404
....@@ -339,7 +408,7 @@
339408
340409 WARN_ON(p != idr_remove(&idrinfo->action_idr,
341410 p->tcfa_index));
342
- spin_unlock(&idrinfo->lock);
411
+ mutex_unlock(&idrinfo->lock);
343412
344413 tcf_action_cleanup(p);
345414 module_put(owner);
....@@ -350,13 +419,13 @@
350419 ret = -EPERM;
351420 }
352421
353
- spin_unlock(&idrinfo->lock);
422
+ mutex_unlock(&idrinfo->lock);
354423 return ret;
355424 }
356425
357426 int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
358427 struct tc_action **a, const struct tc_action_ops *ops,
359
- int bind, bool cpustats)
428
+ int bind, bool cpustats, u32 flags)
360429 {
361430 struct tc_action *p = kzalloc(ops->size, GFP_KERNEL);
362431 struct tcf_idrinfo *idrinfo = tn->idrinfo;
....@@ -372,29 +441,36 @@
372441 p->cpu_bstats = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
373442 if (!p->cpu_bstats)
374443 goto err1;
444
+ p->cpu_bstats_hw = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu);
445
+ if (!p->cpu_bstats_hw)
446
+ goto err2;
375447 p->cpu_qstats = alloc_percpu(struct gnet_stats_queue);
376448 if (!p->cpu_qstats)
377
- goto err2;
449
+ goto err3;
378450 }
379451 spin_lock_init(&p->tcfa_lock);
380452 p->tcfa_index = index;
381453 p->tcfa_tm.install = jiffies;
382454 p->tcfa_tm.lastuse = jiffies;
383455 p->tcfa_tm.firstuse = 0;
456
+ p->tcfa_flags = flags;
384457 if (est) {
385458 err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats,
386459 &p->tcfa_rate_est,
387460 &p->tcfa_lock, NULL, est);
388461 if (err)
389
- goto err3;
462
+ goto err4;
390463 }
391464
392465 p->idrinfo = idrinfo;
466
+ __module_get(ops->owner);
393467 p->ops = ops;
394468 *a = p;
395469 return 0;
396
-err3:
470
+err4:
397471 free_percpu(p->cpu_qstats);
472
+err3:
473
+ free_percpu(p->cpu_bstats_hw);
398474 err2:
399475 free_percpu(p->cpu_bstats);
400476 err1:
....@@ -403,16 +479,16 @@
403479 }
404480 EXPORT_SYMBOL(tcf_idr_create);
405481
406
-void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a)
482
+int tcf_idr_create_from_flags(struct tc_action_net *tn, u32 index,
483
+ struct nlattr *est, struct tc_action **a,
484
+ const struct tc_action_ops *ops, int bind,
485
+ u32 flags)
407486 {
408
- struct tcf_idrinfo *idrinfo = tn->idrinfo;
409
-
410
- spin_lock(&idrinfo->lock);
411
- /* Replace ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc */
412
- WARN_ON(!IS_ERR(idr_replace(&idrinfo->action_idr, a, a->tcfa_index)));
413
- spin_unlock(&idrinfo->lock);
487
+ /* Set cpustats according to actions flags. */
488
+ return tcf_idr_create(tn, index, est, a, ops, bind,
489
+ !(flags & TCA_ACT_FLAGS_NO_PERCPU_STATS), flags);
414490 }
415
-EXPORT_SYMBOL(tcf_idr_insert);
491
+EXPORT_SYMBOL(tcf_idr_create_from_flags);
416492
417493 /* Cleanup idr index that was allocated but not initialized. */
418494
....@@ -420,10 +496,10 @@
420496 {
421497 struct tcf_idrinfo *idrinfo = tn->idrinfo;
422498
423
- spin_lock(&idrinfo->lock);
499
+ mutex_lock(&idrinfo->lock);
424500 /* Remove ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc */
425501 WARN_ON(!IS_ERR(idr_remove(&idrinfo->action_idr, index)));
426
- spin_unlock(&idrinfo->lock);
502
+ mutex_unlock(&idrinfo->lock);
427503 }
428504 EXPORT_SYMBOL(tcf_idr_cleanup);
429505
....@@ -441,14 +517,14 @@
441517 int ret;
442518
443519 again:
444
- spin_lock(&idrinfo->lock);
520
+ mutex_lock(&idrinfo->lock);
445521 if (*index) {
446522 p = idr_find(&idrinfo->action_idr, *index);
447523 if (IS_ERR(p)) {
448524 /* This means that another process allocated
449525 * index but did not assign the pointer yet.
450526 */
451
- spin_unlock(&idrinfo->lock);
527
+ mutex_unlock(&idrinfo->lock);
452528 goto again;
453529 }
454530
....@@ -461,7 +537,7 @@
461537 } else {
462538 *a = NULL;
463539 ret = idr_alloc_u32(&idrinfo->action_idr, NULL, index,
464
- *index, GFP_ATOMIC);
540
+ *index, GFP_KERNEL);
465541 if (!ret)
466542 idr_replace(&idrinfo->action_idr,
467543 ERR_PTR(-EBUSY), *index);
....@@ -470,12 +546,12 @@
470546 *index = 1;
471547 *a = NULL;
472548 ret = idr_alloc_u32(&idrinfo->action_idr, NULL, index,
473
- UINT_MAX, GFP_ATOMIC);
549
+ UINT_MAX, GFP_KERNEL);
474550 if (!ret)
475551 idr_replace(&idrinfo->action_idr, ERR_PTR(-EBUSY),
476552 *index);
477553 }
478
- spin_unlock(&idrinfo->lock);
554
+ mutex_unlock(&idrinfo->lock);
479555 return ret;
480556 }
481557 EXPORT_SYMBOL(tcf_idr_check_alloc);
....@@ -487,8 +563,9 @@
487563 struct tc_action *p;
488564 int ret;
489565 unsigned long id = 1;
566
+ unsigned long tmp;
490567
491
- idr_for_each_entry_ul(idr, p, id) {
568
+ idr_for_each_entry_ul(idr, p, tmp, id) {
492569 ret = __tcf_idr_release(p, false, true);
493570 if (ret == ACT_P_DELETED)
494571 module_put(ops->owner);
....@@ -521,7 +598,7 @@
521598
522599 write_lock(&act_mod_lock);
523600 list_for_each_entry(a, &act_base, head) {
524
- if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) {
601
+ if (act->id == a->id || (strcmp(act->kind, a->kind) == 0)) {
525602 write_unlock(&act_mod_lock);
526603 unregister_pernet_subsys(ops);
527604 return -EEXIST;
....@@ -641,6 +718,10 @@
641718 return TC_ACT_OK;
642719 }
643720 } else if (TC_ACT_EXT_CMP(ret, TC_ACT_GOTO_CHAIN)) {
721
+ if (unlikely(!rcu_access_pointer(a->goto_chain))) {
722
+ net_warn_ratelimited("can't go to NULL chain!\n");
723
+ return TC_ACT_SHOT;
724
+ }
644725 tcf_action_goto_chain_exec(a, res);
645726 }
646727
....@@ -671,13 +752,6 @@
671752 return ret;
672753 }
673754
674
-static int tcf_action_destroy_1(struct tc_action *a, int bind)
675
-{
676
- struct tc_action *actions[] = { a, NULL };
677
-
678
- return tcf_action_destroy(actions, bind);
679
-}
680
-
681755 static int tcf_action_put(struct tc_action *p)
682756 {
683757 return __tcf_action_put(p, false);
....@@ -706,12 +780,10 @@
706780 return a->ops->dump(skb, a, bind, ref);
707781 }
708782
709
-int
710
-tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
783
+static int
784
+tcf_action_dump_terse(struct sk_buff *skb, struct tc_action *a)
711785 {
712
- int err = -EINVAL;
713786 unsigned char *b = skb_tail_pointer(skb);
714
- struct nlattr *nest;
715787 struct tc_cookie *cookie;
716788
717789 if (nla_put_string(skb, TCA_KIND, a->ops->kind))
....@@ -729,7 +801,39 @@
729801 }
730802 rcu_read_unlock();
731803
732
- nest = nla_nest_start(skb, TCA_OPTIONS);
804
+ return 0;
805
+
806
+nla_put_failure:
807
+ nlmsg_trim(skb, b);
808
+ return -1;
809
+}
810
+
811
+int
812
+tcf_action_dump_1(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
813
+{
814
+ int err = -EINVAL;
815
+ unsigned char *b = skb_tail_pointer(skb);
816
+ struct nlattr *nest;
817
+
818
+ if (tcf_action_dump_terse(skb, a))
819
+ goto nla_put_failure;
820
+
821
+ if (a->hw_stats != TCA_ACT_HW_STATS_ANY &&
822
+ nla_put_bitfield32(skb, TCA_ACT_HW_STATS,
823
+ a->hw_stats, TCA_ACT_HW_STATS_ANY))
824
+ goto nla_put_failure;
825
+
826
+ if (a->used_hw_stats_valid &&
827
+ nla_put_bitfield32(skb, TCA_ACT_USED_HW_STATS,
828
+ a->used_hw_stats, TCA_ACT_HW_STATS_ANY))
829
+ goto nla_put_failure;
830
+
831
+ if (a->tcfa_flags &&
832
+ nla_put_bitfield32(skb, TCA_ACT_FLAGS,
833
+ a->tcfa_flags, a->tcfa_flags))
834
+ goto nla_put_failure;
835
+
836
+ nest = nla_nest_start_noflag(skb, TCA_OPTIONS);
733837 if (nest == NULL)
734838 goto nla_put_failure;
735839 err = tcf_action_dump_old(skb, a, bind, ref);
....@@ -745,7 +849,7 @@
745849 EXPORT_SYMBOL(tcf_action_dump_1);
746850
747851 int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[],
748
- int bind, int ref)
852
+ int bind, int ref, bool terse)
749853 {
750854 struct tc_action *a;
751855 int err = -EINVAL, i;
....@@ -753,10 +857,11 @@
753857
754858 for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) {
755859 a = actions[i];
756
- nest = nla_nest_start(skb, i + 1);
860
+ nest = nla_nest_start_noflag(skb, i + 1);
757861 if (nest == NULL)
758862 goto nla_put_failure;
759
- err = tcf_action_dump_1(skb, a, bind, ref);
863
+ err = terse ? tcf_action_dump_terse(skb, a) :
864
+ tcf_action_dump_1(skb, a, bind, ref);
760865 if (err < 0)
761866 goto errout;
762867 nla_nest_end(skb, nest);
....@@ -787,63 +892,79 @@
787892 return c;
788893 }
789894
790
-static bool tcf_action_valid(int action)
895
+static u8 tcf_action_hw_stats_get(struct nlattr *hw_stats_attr)
791896 {
792
- int opcode = TC_ACT_EXT_OPCODE(action);
897
+ struct nla_bitfield32 hw_stats_bf;
793898
794
- if (!opcode)
795
- return action <= TC_ACT_VALUE_MAX;
796
- return opcode <= TC_ACT_EXT_OPCODE_MAX || action == TC_ACT_UNSPEC;
899
+ /* If the user did not pass the attr, that means he does
900
+ * not care about the type. Return "any" in that case
901
+ * which is setting on all supported types.
902
+ */
903
+ if (!hw_stats_attr)
904
+ return TCA_ACT_HW_STATS_ANY;
905
+ hw_stats_bf = nla_get_bitfield32(hw_stats_attr);
906
+ return hw_stats_bf.value;
797907 }
798908
799
-struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
800
- struct nlattr *nla, struct nlattr *est,
801
- char *name, int ovr, int bind,
802
- bool rtnl_held,
803
- struct netlink_ext_ack *extack)
909
+static const struct nla_policy tcf_action_policy[TCA_ACT_MAX + 1] = {
910
+ [TCA_ACT_KIND] = { .type = NLA_STRING },
911
+ [TCA_ACT_INDEX] = { .type = NLA_U32 },
912
+ [TCA_ACT_COOKIE] = { .type = NLA_BINARY,
913
+ .len = TC_COOKIE_MAX_SIZE },
914
+ [TCA_ACT_OPTIONS] = { .type = NLA_NESTED },
915
+ [TCA_ACT_FLAGS] = NLA_POLICY_BITFIELD32(TCA_ACT_FLAGS_NO_PERCPU_STATS),
916
+ [TCA_ACT_HW_STATS] = NLA_POLICY_BITFIELD32(TCA_ACT_HW_STATS_ANY),
917
+};
918
+
919
+void tcf_idr_insert_many(struct tc_action *actions[])
804920 {
805
- struct tc_action *a;
806
- struct tc_action_ops *a_o;
807
- struct tc_cookie *cookie = NULL;
808
- char act_name[IFNAMSIZ];
921
+ int i;
922
+
923
+ for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
924
+ struct tc_action *a = actions[i];
925
+ struct tcf_idrinfo *idrinfo;
926
+
927
+ if (!a)
928
+ continue;
929
+ idrinfo = a->idrinfo;
930
+ mutex_lock(&idrinfo->lock);
931
+ /* Replace ERR_PTR(-EBUSY) allocated by tcf_idr_check_alloc if
932
+ * it is just created, otherwise this is just a nop.
933
+ */
934
+ idr_replace(&idrinfo->action_idr, a, a->tcfa_index);
935
+ mutex_unlock(&idrinfo->lock);
936
+ }
937
+}
938
+
939
+struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla,
940
+ bool rtnl_held,
941
+ struct netlink_ext_ack *extack)
942
+{
809943 struct nlattr *tb[TCA_ACT_MAX + 1];
944
+ struct tc_action_ops *a_o;
945
+ char act_name[IFNAMSIZ];
810946 struct nlattr *kind;
811947 int err;
812948
813949 if (name == NULL) {
814
- err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
950
+ err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla,
951
+ tcf_action_policy, extack);
815952 if (err < 0)
816
- goto err_out;
953
+ return ERR_PTR(err);
817954 err = -EINVAL;
818955 kind = tb[TCA_ACT_KIND];
819956 if (!kind) {
820957 NL_SET_ERR_MSG(extack, "TC action kind must be specified");
821
- goto err_out;
958
+ return ERR_PTR(err);
822959 }
823960 if (nla_strlcpy(act_name, kind, IFNAMSIZ) >= IFNAMSIZ) {
824961 NL_SET_ERR_MSG(extack, "TC action name too long");
825
- goto err_out;
826
- }
827
- if (tb[TCA_ACT_COOKIE]) {
828
- int cklen = nla_len(tb[TCA_ACT_COOKIE]);
829
-
830
- if (cklen > TC_COOKIE_MAX_SIZE) {
831
- NL_SET_ERR_MSG(extack, "TC cookie size above the maximum");
832
- goto err_out;
833
- }
834
-
835
- cookie = nla_memdup_cookie(tb);
836
- if (!cookie) {
837
- NL_SET_ERR_MSG(extack, "No memory to generate TC cookie");
838
- err = -ENOMEM;
839
- goto err_out;
840
- }
962
+ return ERR_PTR(err);
841963 }
842964 } else {
843965 if (strlcpy(act_name, name, IFNAMSIZ) >= IFNAMSIZ) {
844966 NL_SET_ERR_MSG(extack, "TC action name too long");
845
- err = -EINVAL;
846
- goto err_out;
967
+ return ERR_PTR(-EINVAL);
847968 }
848969 }
849970
....@@ -865,57 +986,67 @@
865986 * indicate this using -EAGAIN.
866987 */
867988 if (a_o != NULL) {
868
- err = -EAGAIN;
869
- goto err_mod;
989
+ module_put(a_o->owner);
990
+ return ERR_PTR(-EAGAIN);
870991 }
871992 #endif
872993 NL_SET_ERR_MSG(extack, "Failed to load TC action module");
873
- err = -ENOENT;
874
- goto err_out;
994
+ return ERR_PTR(-ENOENT);
875995 }
876996
997
+ return a_o;
998
+}
999
+
1000
+struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp,
1001
+ struct nlattr *nla, struct nlattr *est,
1002
+ char *name, int ovr, int bind,
1003
+ struct tc_action_ops *a_o, int *init_res,
1004
+ bool rtnl_held,
1005
+ struct netlink_ext_ack *extack)
1006
+{
1007
+ struct nla_bitfield32 flags = { 0, 0 };
1008
+ u8 hw_stats = TCA_ACT_HW_STATS_ANY;
1009
+ struct nlattr *tb[TCA_ACT_MAX + 1];
1010
+ struct tc_cookie *cookie = NULL;
1011
+ struct tc_action *a;
1012
+ int err;
1013
+
8771014 /* backward compatibility for policer */
878
- if (name == NULL)
1015
+ if (name == NULL) {
1016
+ err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla,
1017
+ tcf_action_policy, extack);
1018
+ if (err < 0)
1019
+ return ERR_PTR(err);
1020
+ if (tb[TCA_ACT_COOKIE]) {
1021
+ cookie = nla_memdup_cookie(tb);
1022
+ if (!cookie) {
1023
+ NL_SET_ERR_MSG(extack, "No memory to generate TC cookie");
1024
+ err = -ENOMEM;
1025
+ goto err_out;
1026
+ }
1027
+ }
1028
+ hw_stats = tcf_action_hw_stats_get(tb[TCA_ACT_HW_STATS]);
1029
+ if (tb[TCA_ACT_FLAGS])
1030
+ flags = nla_get_bitfield32(tb[TCA_ACT_FLAGS]);
1031
+
8791032 err = a_o->init(net, tb[TCA_ACT_OPTIONS], est, &a, ovr, bind,
880
- rtnl_held, extack);
881
- else
1033
+ rtnl_held, tp, flags.value, extack);
1034
+ } else {
8821035 err = a_o->init(net, nla, est, &a, ovr, bind, rtnl_held,
883
- extack);
1036
+ tp, flags.value, extack);
1037
+ }
8841038 if (err < 0)
885
- goto err_mod;
1039
+ goto err_out;
1040
+ *init_res = err;
8861041
8871042 if (!name && tb[TCA_ACT_COOKIE])
8881043 tcf_set_action_cookie(&a->act_cookie, cookie);
8891044
890
- /* module count goes up only when brand new policy is created
891
- * if it exists and is only bound to in a_o->init() then
892
- * ACT_P_CREATED is not returned (a zero is).
893
- */
894
- if (err != ACT_P_CREATED)
895
- module_put(a_o->owner);
896
-
897
- if (TC_ACT_EXT_CMP(a->tcfa_action, TC_ACT_GOTO_CHAIN)) {
898
- err = tcf_action_goto_chain_init(a, tp);
899
- if (err) {
900
- tcf_action_destroy_1(a, bind);
901
- NL_SET_ERR_MSG(extack, "Failed to init TC action chain");
902
- return ERR_PTR(err);
903
- }
904
- }
905
-
906
- if (!tcf_action_valid(a->tcfa_action)) {
907
- tcf_action_destroy_1(a, bind);
908
- NL_SET_ERR_MSG(extack, "Invalid control action value");
909
- return ERR_PTR(-EINVAL);
910
- }
911
-
912
- if (!bind && ovr && err == ACT_P_CREATED)
913
- refcount_set(&a->tcfa_refcnt, 2);
1045
+ if (!name)
1046
+ a->hw_stats = hw_stats;
9141047
9151048 return a;
9161049
917
-err_mod:
918
- module_put(a_o->owner);
9191050 err_out:
9201051 if (cookie) {
9211052 kfree(cookie->data);
....@@ -928,39 +1059,84 @@
9281059
9291060 int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
9301061 struct nlattr *est, char *name, int ovr, int bind,
931
- struct tc_action *actions[], size_t *attr_size,
1062
+ struct tc_action *actions[], int init_res[], size_t *attr_size,
9321063 bool rtnl_held, struct netlink_ext_ack *extack)
9331064 {
1065
+ struct tc_action_ops *ops[TCA_ACT_MAX_PRIO] = {};
9341066 struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
9351067 struct tc_action *act;
9361068 size_t sz = 0;
9371069 int err;
9381070 int i;
9391071
940
- err = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
1072
+ err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX_PRIO, nla, NULL,
1073
+ extack);
9411074 if (err < 0)
9421075 return err;
9431076
9441077 for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
1078
+ struct tc_action_ops *a_o;
1079
+
1080
+ a_o = tc_action_load_ops(name, tb[i], rtnl_held, extack);
1081
+ if (IS_ERR(a_o)) {
1082
+ err = PTR_ERR(a_o);
1083
+ goto err_mod;
1084
+ }
1085
+ ops[i - 1] = a_o;
1086
+ }
1087
+
1088
+ for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) {
9451089 act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind,
946
- rtnl_held, extack);
1090
+ ops[i - 1], &init_res[i - 1], rtnl_held,
1091
+ extack);
9471092 if (IS_ERR(act)) {
9481093 err = PTR_ERR(act);
9491094 goto err;
9501095 }
951
- act->order = i;
9521096 sz += tcf_action_fill_size(act);
9531097 /* Start from index 0 */
9541098 actions[i - 1] = act;
9551099 }
9561100
1101
+ /* We have to commit them all together, because if any error happened in
1102
+ * between, we could not handle the failure gracefully.
1103
+ */
1104
+ tcf_idr_insert_many(actions);
1105
+
9571106 *attr_size = tcf_action_full_attrs_size(sz);
958
- return i - 1;
1107
+ err = i - 1;
1108
+ goto err_mod;
9591109
9601110 err:
9611111 tcf_action_destroy(actions, bind);
1112
+err_mod:
1113
+ for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
1114
+ if (ops[i])
1115
+ module_put(ops[i]->owner);
1116
+ }
9621117 return err;
9631118 }
1119
+
1120
+void tcf_action_update_stats(struct tc_action *a, u64 bytes, u64 packets,
1121
+ u64 drops, bool hw)
1122
+{
1123
+ if (a->cpu_bstats) {
1124
+ _bstats_cpu_update(this_cpu_ptr(a->cpu_bstats), bytes, packets);
1125
+
1126
+ this_cpu_ptr(a->cpu_qstats)->drops += drops;
1127
+
1128
+ if (hw)
1129
+ _bstats_cpu_update(this_cpu_ptr(a->cpu_bstats_hw),
1130
+ bytes, packets);
1131
+ return;
1132
+ }
1133
+
1134
+ _bstats_update(&a->tcfa_bstats, bytes, packets);
1135
+ a->tcfa_qstats.drops += drops;
1136
+ if (hw)
1137
+ _bstats_update(&a->tcfa_bstats_hw, bytes, packets);
1138
+}
1139
+EXPORT_SYMBOL(tcf_action_update_stats);
9641140
9651141 int tcf_action_copy_stats(struct sk_buff *skb, struct tc_action *p,
9661142 int compat_mode)
....@@ -991,6 +1167,8 @@
9911167 goto errout;
9921168
9931169 if (gnet_stats_copy_basic(NULL, &d, p->cpu_bstats, &p->tcfa_bstats) < 0 ||
1170
+ gnet_stats_copy_basic_hw(NULL, &d, p->cpu_bstats_hw,
1171
+ &p->tcfa_bstats_hw) < 0 ||
9941172 gnet_stats_copy_rate_est(&d, &p->tcfa_rate_est) < 0 ||
9951173 gnet_stats_copy_queue(&d, p->cpu_qstats,
9961174 &p->tcfa_qstats,
....@@ -1023,11 +1201,11 @@
10231201 t->tca__pad1 = 0;
10241202 t->tca__pad2 = 0;
10251203
1026
- nest = nla_nest_start(skb, TCA_ACT_TAB);
1204
+ nest = nla_nest_start_noflag(skb, TCA_ACT_TAB);
10271205 if (!nest)
10281206 goto out_nlmsg_trim;
10291207
1030
- if (tcf_action_dump(skb, actions, bind, ref) < 0)
1208
+ if (tcf_action_dump(skb, actions, bind, ref, false) < 0)
10311209 goto out_nlmsg_trim;
10321210
10331211 nla_nest_end(skb, nest);
....@@ -1070,7 +1248,8 @@
10701248 int index;
10711249 int err;
10721250
1073
- err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
1251
+ err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla,
1252
+ tcf_action_policy, extack);
10741253 if (err < 0)
10751254 goto err_out;
10761255
....@@ -1085,12 +1264,14 @@
10851264 err = -EINVAL;
10861265 ops = tc_lookup_action(tb[TCA_ACT_KIND]);
10871266 if (!ops) { /* could happen in batch of actions */
1088
- NL_SET_ERR_MSG(extack, "Specified TC action not found");
1267
+ NL_SET_ERR_MSG(extack, "Specified TC action kind not found");
10891268 goto err_out;
10901269 }
10911270 err = -ENOENT;
1092
- if (ops->lookup(net, &a, index, extack) == 0)
1271
+ if (ops->lookup(net, &a, index) == 0) {
1272
+ NL_SET_ERR_MSG(extack, "TC action with specified index not found");
10931273 goto err_mod;
1274
+ }
10941275
10951276 module_put(ops->owner);
10961277 return a;
....@@ -1122,7 +1303,8 @@
11221303
11231304 b = skb_tail_pointer(skb);
11241305
1125
- err = nla_parse_nested(tb, TCA_ACT_MAX, nla, NULL, extack);
1306
+ err = nla_parse_nested_deprecated(tb, TCA_ACT_MAX, nla,
1307
+ tcf_action_policy, extack);
11261308 if (err < 0)
11271309 goto err_out;
11281310
....@@ -1145,7 +1327,7 @@
11451327 t->tca__pad1 = 0;
11461328 t->tca__pad2 = 0;
11471329
1148
- nest = nla_nest_start(skb, TCA_ACT_TAB);
1330
+ nest = nla_nest_start_noflag(skb, TCA_ACT_TAB);
11491331 if (!nest) {
11501332 NL_SET_ERR_MSG(extack, "Failed to add new netlink message");
11511333 goto out_module_put;
....@@ -1251,7 +1433,8 @@
12511433 size_t attr_size = 0;
12521434 struct tc_action *actions[TCA_ACT_MAX_PRIO] = {};
12531435
1254
- ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
1436
+ ret = nla_parse_nested_deprecated(tb, TCA_ACT_MAX_PRIO, nla, NULL,
1437
+ extack);
12551438 if (ret < 0)
12561439 return ret;
12571440
....@@ -1319,12 +1502,13 @@
13191502 struct netlink_ext_ack *extack)
13201503 {
13211504 size_t attr_size = 0;
1322
- int loop, ret;
1505
+ int loop, ret, i;
13231506 struct tc_action *actions[TCA_ACT_MAX_PRIO] = {};
1507
+ int init_res[TCA_ACT_MAX_PRIO] = {};
13241508
13251509 for (loop = 0; loop < 10; loop++) {
13261510 ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0,
1327
- actions, &attr_size, true, extack);
1511
+ actions, init_res, &attr_size, true, extack);
13281512 if (ret != -EAGAIN)
13291513 break;
13301514 }
....@@ -1332,16 +1516,18 @@
13321516 if (ret < 0)
13331517 return ret;
13341518 ret = tcf_add_notify(net, n, actions, portid, attr_size, extack);
1335
- if (ovr)
1336
- tcf_action_put_many(actions);
1519
+
1520
+ /* only put existing actions */
1521
+ for (i = 0; i < TCA_ACT_MAX_PRIO; i++)
1522
+ if (init_res[i] == ACT_P_CREATED)
1523
+ actions[i] = NULL;
1524
+ tcf_action_put_many(actions);
13371525
13381526 return ret;
13391527 }
13401528
1341
-static u32 tcaa_root_flags_allowed = TCA_FLAG_LARGE_DUMP_ON;
13421529 static const struct nla_policy tcaa_policy[TCA_ROOT_MAX + 1] = {
1343
- [TCA_ROOT_FLAGS] = { .type = NLA_BITFIELD32,
1344
- .validation_data = &tcaa_root_flags_allowed },
1530
+ [TCA_ROOT_FLAGS] = NLA_POLICY_BITFIELD32(TCA_FLAG_LARGE_DUMP_ON),
13451531 [TCA_ROOT_TIME_DELTA] = { .type = NLA_U32 },
13461532 };
13471533
....@@ -1350,15 +1536,15 @@
13501536 {
13511537 struct net *net = sock_net(skb->sk);
13521538 struct nlattr *tca[TCA_ROOT_MAX + 1];
1353
- u32 portid = skb ? NETLINK_CB(skb).portid : 0;
1539
+ u32 portid = NETLINK_CB(skb).portid;
13541540 int ret = 0, ovr = 0;
13551541
13561542 if ((n->nlmsg_type != RTM_GETACTION) &&
13571543 !netlink_capable(skb, CAP_NET_ADMIN))
13581544 return -EPERM;
13591545
1360
- ret = nlmsg_parse(n, sizeof(struct tcamsg), tca, TCA_ROOT_MAX, NULL,
1361
- extack);
1546
+ ret = nlmsg_parse_deprecated(n, sizeof(struct tcamsg), tca,
1547
+ TCA_ROOT_MAX, NULL, extack);
13621548 if (ret < 0)
13631549 return ret;
13641550
....@@ -1406,13 +1592,12 @@
14061592 if (tb1 == NULL)
14071593 return NULL;
14081594
1409
- if (nla_parse(tb, TCA_ACT_MAX_PRIO, nla_data(tb1),
1410
- NLMSG_ALIGN(nla_len(tb1)), NULL, NULL) < 0)
1595
+ if (nla_parse_deprecated(tb, TCA_ACT_MAX_PRIO, nla_data(tb1), NLMSG_ALIGN(nla_len(tb1)), NULL, NULL) < 0)
14111596 return NULL;
14121597
14131598 if (tb[1] == NULL)
14141599 return NULL;
1415
- if (nla_parse_nested(tb2, TCA_ACT_MAX, tb[1], NULL, NULL) < 0)
1600
+ if (nla_parse_nested_deprecated(tb2, TCA_ACT_MAX, tb[1], tcf_action_policy, NULL) < 0)
14161601 return NULL;
14171602 kind = tb2[TCA_ACT_KIND];
14181603
....@@ -1436,8 +1621,8 @@
14361621 u32 msecs_since = 0;
14371622 u32 act_count = 0;
14381623
1439
- ret = nlmsg_parse(cb->nlh, sizeof(struct tcamsg), tb, TCA_ROOT_MAX,
1440
- tcaa_policy, NULL);
1624
+ ret = nlmsg_parse_deprecated(cb->nlh, sizeof(struct tcamsg), tb,
1625
+ TCA_ROOT_MAX, tcaa_policy, cb->extack);
14411626 if (ret < 0)
14421627 return ret;
14431628
....@@ -1478,7 +1663,7 @@
14781663 if (!count_attr)
14791664 goto out_module_put;
14801665
1481
- nest = nla_nest_start(skb, TCA_ACT_TAB);
1666
+ nest = nla_nest_start_noflag(skb, TCA_ACT_TAB);
14821667 if (nest == NULL)
14831668 goto out_module_put;
14841669
....@@ -1507,227 +1692,8 @@
15071692 return skb->len;
15081693 }
15091694
1510
-struct tcf_action_net {
1511
- struct rhashtable egdev_ht;
1512
-};
1513
-
1514
-static unsigned int tcf_action_net_id;
1515
-
1516
-struct tcf_action_egdev_cb {
1517
- struct list_head list;
1518
- tc_setup_cb_t *cb;
1519
- void *cb_priv;
1520
-};
1521
-
1522
-struct tcf_action_egdev {
1523
- struct rhash_head ht_node;
1524
- const struct net_device *dev;
1525
- unsigned int refcnt;
1526
- struct list_head cb_list;
1527
-};
1528
-
1529
-static const struct rhashtable_params tcf_action_egdev_ht_params = {
1530
- .key_offset = offsetof(struct tcf_action_egdev, dev),
1531
- .head_offset = offsetof(struct tcf_action_egdev, ht_node),
1532
- .key_len = sizeof(const struct net_device *),
1533
-};
1534
-
1535
-static struct tcf_action_egdev *
1536
-tcf_action_egdev_lookup(const struct net_device *dev)
1537
-{
1538
- struct net *net = dev_net(dev);
1539
- struct tcf_action_net *tan = net_generic(net, tcf_action_net_id);
1540
-
1541
- return rhashtable_lookup_fast(&tan->egdev_ht, &dev,
1542
- tcf_action_egdev_ht_params);
1543
-}
1544
-
1545
-static struct tcf_action_egdev *
1546
-tcf_action_egdev_get(const struct net_device *dev)
1547
-{
1548
- struct tcf_action_egdev *egdev;
1549
- struct tcf_action_net *tan;
1550
-
1551
- egdev = tcf_action_egdev_lookup(dev);
1552
- if (egdev)
1553
- goto inc_ref;
1554
-
1555
- egdev = kzalloc(sizeof(*egdev), GFP_KERNEL);
1556
- if (!egdev)
1557
- return NULL;
1558
- INIT_LIST_HEAD(&egdev->cb_list);
1559
- egdev->dev = dev;
1560
- tan = net_generic(dev_net(dev), tcf_action_net_id);
1561
- rhashtable_insert_fast(&tan->egdev_ht, &egdev->ht_node,
1562
- tcf_action_egdev_ht_params);
1563
-
1564
-inc_ref:
1565
- egdev->refcnt++;
1566
- return egdev;
1567
-}
1568
-
1569
-static void tcf_action_egdev_put(struct tcf_action_egdev *egdev)
1570
-{
1571
- struct tcf_action_net *tan;
1572
-
1573
- if (--egdev->refcnt)
1574
- return;
1575
- tan = net_generic(dev_net(egdev->dev), tcf_action_net_id);
1576
- rhashtable_remove_fast(&tan->egdev_ht, &egdev->ht_node,
1577
- tcf_action_egdev_ht_params);
1578
- kfree(egdev);
1579
-}
1580
-
1581
-static struct tcf_action_egdev_cb *
1582
-tcf_action_egdev_cb_lookup(struct tcf_action_egdev *egdev,
1583
- tc_setup_cb_t *cb, void *cb_priv)
1584
-{
1585
- struct tcf_action_egdev_cb *egdev_cb;
1586
-
1587
- list_for_each_entry(egdev_cb, &egdev->cb_list, list)
1588
- if (egdev_cb->cb == cb && egdev_cb->cb_priv == cb_priv)
1589
- return egdev_cb;
1590
- return NULL;
1591
-}
1592
-
1593
-static int tcf_action_egdev_cb_call(struct tcf_action_egdev *egdev,
1594
- enum tc_setup_type type,
1595
- void *type_data, bool err_stop)
1596
-{
1597
- struct tcf_action_egdev_cb *egdev_cb;
1598
- int ok_count = 0;
1599
- int err;
1600
-
1601
- list_for_each_entry(egdev_cb, &egdev->cb_list, list) {
1602
- err = egdev_cb->cb(type, type_data, egdev_cb->cb_priv);
1603
- if (err) {
1604
- if (err_stop)
1605
- return err;
1606
- } else {
1607
- ok_count++;
1608
- }
1609
- }
1610
- return ok_count;
1611
-}
1612
-
1613
-static int tcf_action_egdev_cb_add(struct tcf_action_egdev *egdev,
1614
- tc_setup_cb_t *cb, void *cb_priv)
1615
-{
1616
- struct tcf_action_egdev_cb *egdev_cb;
1617
-
1618
- egdev_cb = tcf_action_egdev_cb_lookup(egdev, cb, cb_priv);
1619
- if (WARN_ON(egdev_cb))
1620
- return -EEXIST;
1621
- egdev_cb = kzalloc(sizeof(*egdev_cb), GFP_KERNEL);
1622
- if (!egdev_cb)
1623
- return -ENOMEM;
1624
- egdev_cb->cb = cb;
1625
- egdev_cb->cb_priv = cb_priv;
1626
- list_add(&egdev_cb->list, &egdev->cb_list);
1627
- return 0;
1628
-}
1629
-
1630
-static void tcf_action_egdev_cb_del(struct tcf_action_egdev *egdev,
1631
- tc_setup_cb_t *cb, void *cb_priv)
1632
-{
1633
- struct tcf_action_egdev_cb *egdev_cb;
1634
-
1635
- egdev_cb = tcf_action_egdev_cb_lookup(egdev, cb, cb_priv);
1636
- if (WARN_ON(!egdev_cb))
1637
- return;
1638
- list_del(&egdev_cb->list);
1639
- kfree(egdev_cb);
1640
-}
1641
-
1642
-static int __tc_setup_cb_egdev_register(const struct net_device *dev,
1643
- tc_setup_cb_t *cb, void *cb_priv)
1644
-{
1645
- struct tcf_action_egdev *egdev = tcf_action_egdev_get(dev);
1646
- int err;
1647
-
1648
- if (!egdev)
1649
- return -ENOMEM;
1650
- err = tcf_action_egdev_cb_add(egdev, cb, cb_priv);
1651
- if (err)
1652
- goto err_cb_add;
1653
- return 0;
1654
-
1655
-err_cb_add:
1656
- tcf_action_egdev_put(egdev);
1657
- return err;
1658
-}
1659
-int tc_setup_cb_egdev_register(const struct net_device *dev,
1660
- tc_setup_cb_t *cb, void *cb_priv)
1661
-{
1662
- int err;
1663
-
1664
- rtnl_lock();
1665
- err = __tc_setup_cb_egdev_register(dev, cb, cb_priv);
1666
- rtnl_unlock();
1667
- return err;
1668
-}
1669
-EXPORT_SYMBOL_GPL(tc_setup_cb_egdev_register);
1670
-
1671
-static void __tc_setup_cb_egdev_unregister(const struct net_device *dev,
1672
- tc_setup_cb_t *cb, void *cb_priv)
1673
-{
1674
- struct tcf_action_egdev *egdev = tcf_action_egdev_lookup(dev);
1675
-
1676
- if (WARN_ON(!egdev))
1677
- return;
1678
- tcf_action_egdev_cb_del(egdev, cb, cb_priv);
1679
- tcf_action_egdev_put(egdev);
1680
-}
1681
-void tc_setup_cb_egdev_unregister(const struct net_device *dev,
1682
- tc_setup_cb_t *cb, void *cb_priv)
1683
-{
1684
- rtnl_lock();
1685
- __tc_setup_cb_egdev_unregister(dev, cb, cb_priv);
1686
- rtnl_unlock();
1687
-}
1688
-EXPORT_SYMBOL_GPL(tc_setup_cb_egdev_unregister);
1689
-
1690
-int tc_setup_cb_egdev_call(const struct net_device *dev,
1691
- enum tc_setup_type type, void *type_data,
1692
- bool err_stop)
1693
-{
1694
- struct tcf_action_egdev *egdev = tcf_action_egdev_lookup(dev);
1695
-
1696
- if (!egdev)
1697
- return 0;
1698
- return tcf_action_egdev_cb_call(egdev, type, type_data, err_stop);
1699
-}
1700
-EXPORT_SYMBOL_GPL(tc_setup_cb_egdev_call);
1701
-
1702
-static __net_init int tcf_action_net_init(struct net *net)
1703
-{
1704
- struct tcf_action_net *tan = net_generic(net, tcf_action_net_id);
1705
-
1706
- return rhashtable_init(&tan->egdev_ht, &tcf_action_egdev_ht_params);
1707
-}
1708
-
1709
-static void __net_exit tcf_action_net_exit(struct net *net)
1710
-{
1711
- struct tcf_action_net *tan = net_generic(net, tcf_action_net_id);
1712
-
1713
- rhashtable_destroy(&tan->egdev_ht);
1714
-}
1715
-
1716
-static struct pernet_operations tcf_action_net_ops = {
1717
- .init = tcf_action_net_init,
1718
- .exit = tcf_action_net_exit,
1719
- .id = &tcf_action_net_id,
1720
- .size = sizeof(struct tcf_action_net),
1721
-};
1722
-
17231695 static int __init tc_action_init(void)
17241696 {
1725
- int err;
1726
-
1727
- err = register_pernet_subsys(&tcf_action_net_ops);
1728
- if (err)
1729
- return err;
1730
-
17311697 rtnl_register(PF_UNSPEC, RTM_NEWACTION, tc_ctl_action, NULL, 0);
17321698 rtnl_register(PF_UNSPEC, RTM_DELACTION, tc_ctl_action, NULL, 0);
17331699 rtnl_register(PF_UNSPEC, RTM_GETACTION, tc_ctl_action, tc_dump_action,