forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/net/sched/act_sample.c
....@@ -1,10 +1,7 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * net/sched/act_sample.c - Packet sampling tc action
34 * Copyright (c) 2017 Yotam Gigi <yotamg@mellanox.com>
4
- *
5
- * This program is free software; you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License version 2 as
7
- * published by the Free Software Foundation.
85 */
96
107 #include <linux/types.h>
....@@ -22,6 +19,7 @@
2219 #include <linux/tc_act/tc_sample.h>
2320 #include <net/tc_act/tc_sample.h>
2421 #include <net/psample.h>
22
+#include <net/pkt_cls.h>
2523
2624 #include <linux/if_arp.h>
2725
....@@ -37,13 +35,14 @@
3735
3836 static int tcf_sample_init(struct net *net, struct nlattr *nla,
3937 struct nlattr *est, struct tc_action **a, int ovr,
40
- int bind, bool rtnl_held,
41
- struct netlink_ext_ack *extack)
38
+ int bind, bool rtnl_held, struct tcf_proto *tp,
39
+ u32 flags, struct netlink_ext_ack *extack)
4240 {
4341 struct tc_action_net *tn = net_generic(net, sample_net_id);
4442 struct nlattr *tb[TCA_SAMPLE_MAX + 1];
4543 struct psample_group *psample_group;
4644 u32 psample_group_num, rate, index;
45
+ struct tcf_chain *goto_ch = NULL;
4746 struct tc_sample *parm;
4847 struct tcf_sample *s;
4948 bool exists = false;
....@@ -51,7 +50,8 @@
5150
5251 if (!nla)
5352 return -EINVAL;
54
- ret = nla_parse_nested(tb, TCA_SAMPLE_MAX, nla, sample_policy, NULL);
53
+ ret = nla_parse_nested_deprecated(tb, TCA_SAMPLE_MAX, nla,
54
+ sample_policy, NULL);
5555 if (ret < 0)
5656 return ret;
5757 if (!tb[TCA_SAMPLE_PARMS] || !tb[TCA_SAMPLE_RATE] ||
....@@ -69,7 +69,7 @@
6969
7070 if (!exists) {
7171 ret = tcf_idr_create(tn, index, est, a,
72
- &act_sample_ops, bind, true);
72
+ &act_sample_ops, bind, true, 0);
7373 if (ret) {
7474 tcf_idr_cleanup(tn, index);
7575 return ret;
....@@ -79,28 +79,31 @@
7979 tcf_idr_release(*a, bind);
8080 return -EEXIST;
8181 }
82
+ err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
83
+ if (err < 0)
84
+ goto release_idr;
8285
8386 rate = nla_get_u32(tb[TCA_SAMPLE_RATE]);
8487 if (!rate) {
8588 NL_SET_ERR_MSG(extack, "invalid sample rate");
86
- tcf_idr_release(*a, bind);
87
- return -EINVAL;
89
+ err = -EINVAL;
90
+ goto put_chain;
8891 }
8992 psample_group_num = nla_get_u32(tb[TCA_SAMPLE_PSAMPLE_GROUP]);
9093 psample_group = psample_group_get(net, psample_group_num);
9194 if (!psample_group) {
92
- tcf_idr_release(*a, bind);
93
- return -ENOMEM;
95
+ err = -ENOMEM;
96
+ goto put_chain;
9497 }
9598
9699 s = to_sample(*a);
97100
98101 spin_lock_bh(&s->tcf_lock);
99
- s->tcf_action = parm->action;
102
+ goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
100103 s->rate = rate;
101104 s->psample_group_num = psample_group_num;
102
- rcu_swap_protected(s->psample_group, psample_group,
103
- lockdep_is_held(&s->tcf_lock));
105
+ psample_group = rcu_replace_pointer(s->psample_group, psample_group,
106
+ lockdep_is_held(&s->tcf_lock));
104107
105108 if (tb[TCA_SAMPLE_TRUNC_SIZE]) {
106109 s->truncate = true;
....@@ -110,9 +113,16 @@
110113
111114 if (psample_group)
112115 psample_group_put(psample_group);
113
- if (ret == ACT_P_CREATED)
114
- tcf_idr_insert(tn, *a);
116
+ if (goto_ch)
117
+ tcf_chain_put_by_act(goto_ch);
118
+
115119 return ret;
120
+put_chain:
121
+ if (goto_ch)
122
+ tcf_chain_put_by_act(goto_ch);
123
+release_idr:
124
+ tcf_idr_release(*a, bind);
125
+ return err;
116126 }
117127
118128 static void tcf_sample_cleanup(struct tc_action *a)
....@@ -234,17 +244,40 @@
234244 return tcf_generic_walker(tn, skb, cb, type, ops, extack);
235245 }
236246
237
-static int tcf_sample_search(struct net *net, struct tc_action **a, u32 index,
238
- struct netlink_ext_ack *extack)
247
+static int tcf_sample_search(struct net *net, struct tc_action **a, u32 index)
239248 {
240249 struct tc_action_net *tn = net_generic(net, sample_net_id);
241250
242251 return tcf_idr_search(tn, a, index);
243252 }
244253
254
+static void tcf_psample_group_put(void *priv)
255
+{
256
+ struct psample_group *group = priv;
257
+
258
+ psample_group_put(group);
259
+}
260
+
261
+static struct psample_group *
262
+tcf_sample_get_group(const struct tc_action *a,
263
+ tc_action_priv_destructor *destructor)
264
+{
265
+ struct tcf_sample *s = to_sample(a);
266
+ struct psample_group *group;
267
+
268
+ group = rcu_dereference_protected(s->psample_group,
269
+ lockdep_is_held(&s->tcf_lock));
270
+ if (group) {
271
+ psample_group_take(group);
272
+ *destructor = tcf_psample_group_put;
273
+ }
274
+
275
+ return group;
276
+}
277
+
245278 static struct tc_action_ops act_sample_ops = {
246279 .kind = "sample",
247
- .type = TCA_ACT_SAMPLE,
280
+ .id = TCA_ID_SAMPLE,
248281 .owner = THIS_MODULE,
249282 .act = tcf_sample_act,
250283 .dump = tcf_sample_dump,
....@@ -252,6 +285,7 @@
252285 .cleanup = tcf_sample_cleanup,
253286 .walk = tcf_sample_walker,
254287 .lookup = tcf_sample_search,
288
+ .get_psample_group = tcf_sample_get_group,
255289 .size = sizeof(struct tcf_sample),
256290 };
257291