hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/net/sched/cls_basic.c
....@@ -1,10 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * net/sched/cls_basic.c Basic Packet Classifier.
3
- *
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.
84 *
95 * Authors: Thomas Graf <tgraf@suug.ch>
106 */
....@@ -18,6 +14,7 @@
1814 #include <linux/rtnetlink.h>
1915 #include <linux/skbuff.h>
2016 #include <linux/idr.h>
17
+#include <linux/percpu.h>
2118 #include <net/netlink.h>
2219 #include <net/act_api.h>
2320 #include <net/pkt_cls.h>
....@@ -35,6 +32,7 @@
3532 struct tcf_result res;
3633 struct tcf_proto *tp;
3734 struct list_head link;
35
+ struct tc_basic_pcnt __percpu *pf;
3836 struct rcu_work rwork;
3937 };
4038
....@@ -46,8 +44,10 @@
4644 struct basic_filter *f;
4745
4846 list_for_each_entry_rcu(f, &head->flist, link) {
47
+ __this_cpu_inc(f->pf->rcnt);
4948 if (!tcf_em_tree_match(skb, &f->ematches, NULL))
5049 continue;
50
+ __this_cpu_inc(f->pf->rhit);
5151 *res = f->res;
5252 r = tcf_exts_exec(skb, &f->exts, res);
5353 if (r < 0)
....@@ -89,6 +89,7 @@
8989 tcf_exts_destroy(&f->exts);
9090 tcf_em_tree_destroy(&f->ematches);
9191 tcf_exts_put_net(&f->exts);
92
+ free_percpu(f->pf);
9293 kfree(f);
9394 }
9495
....@@ -102,7 +103,8 @@
102103 rtnl_unlock();
103104 }
104105
105
-static void basic_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack)
106
+static void basic_destroy(struct tcf_proto *tp, bool rtnl_held,
107
+ struct netlink_ext_ack *extack)
106108 {
107109 struct basic_head *head = rtnl_dereference(tp->root);
108110 struct basic_filter *f, *n;
....@@ -121,7 +123,7 @@
121123 }
122124
123125 static int basic_delete(struct tcf_proto *tp, void *arg, bool *last,
124
- struct netlink_ext_ack *extack)
126
+ bool rtnl_held, struct netlink_ext_ack *extack)
125127 {
126128 struct basic_head *head = rtnl_dereference(tp->root);
127129 struct basic_filter *f = arg;
....@@ -148,7 +150,7 @@
148150 {
149151 int err;
150152
151
- err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr, extack);
153
+ err = tcf_exts_validate(net, tp, tb, est, &f->exts, ovr, true, extack);
152154 if (err < 0)
153155 return err;
154156
....@@ -168,7 +170,7 @@
168170 static int basic_change(struct net *net, struct sk_buff *in_skb,
169171 struct tcf_proto *tp, unsigned long base, u32 handle,
170172 struct nlattr **tca, void **arg, bool ovr,
171
- struct netlink_ext_ack *extack)
173
+ bool rtnl_held, struct netlink_ext_ack *extack)
172174 {
173175 int err;
174176 struct basic_head *head = rtnl_dereference(tp->root);
....@@ -179,8 +181,8 @@
179181 if (tca[TCA_OPTIONS] == NULL)
180182 return -EINVAL;
181183
182
- err = nla_parse_nested(tb, TCA_BASIC_MAX, tca[TCA_OPTIONS],
183
- basic_policy, NULL);
184
+ err = nla_parse_nested_deprecated(tb, TCA_BASIC_MAX, tca[TCA_OPTIONS],
185
+ basic_policy, NULL);
184186 if (err < 0)
185187 return err;
186188
....@@ -193,7 +195,7 @@
193195 if (!fnew)
194196 return -ENOBUFS;
195197
196
- err = tcf_exts_init(&fnew->exts, TCA_BASIC_ACT, TCA_BASIC_POLICE);
198
+ err = tcf_exts_init(&fnew->exts, net, TCA_BASIC_ACT, TCA_BASIC_POLICE);
197199 if (err < 0)
198200 goto errout;
199201
....@@ -208,6 +210,11 @@
208210 if (err)
209211 goto errout;
210212 fnew->handle = handle;
213
+ fnew->pf = alloc_percpu(struct tc_basic_pcnt);
214
+ if (!fnew->pf) {
215
+ err = -ENOMEM;
216
+ goto errout;
217
+ }
211218
212219 err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr,
213220 extack);
....@@ -231,12 +238,14 @@
231238
232239 return 0;
233240 errout:
241
+ free_percpu(fnew->pf);
234242 tcf_exts_destroy(&fnew->exts);
235243 kfree(fnew);
236244 return err;
237245 }
238246
239
-static void basic_walk(struct tcf_proto *tp, struct tcf_walker *arg)
247
+static void basic_walk(struct tcf_proto *tp, struct tcf_walker *arg,
248
+ bool rtnl_held)
240249 {
241250 struct basic_head *head = rtnl_dereference(tp->root);
242251 struct basic_filter *f;
....@@ -268,17 +277,19 @@
268277 }
269278
270279 static int basic_dump(struct net *net, struct tcf_proto *tp, void *fh,
271
- struct sk_buff *skb, struct tcmsg *t)
280
+ struct sk_buff *skb, struct tcmsg *t, bool rtnl_held)
272281 {
282
+ struct tc_basic_pcnt gpf = {};
273283 struct basic_filter *f = fh;
274284 struct nlattr *nest;
285
+ int cpu;
275286
276287 if (f == NULL)
277288 return skb->len;
278289
279290 t->tcm_handle = f->handle;
280291
281
- nest = nla_nest_start(skb, TCA_OPTIONS);
292
+ nest = nla_nest_start_noflag(skb, TCA_OPTIONS);
282293 if (nest == NULL)
283294 goto nla_put_failure;
284295
....@@ -286,6 +297,18 @@
286297 nla_put_u32(skb, TCA_BASIC_CLASSID, f->res.classid))
287298 goto nla_put_failure;
288299
300
+ for_each_possible_cpu(cpu) {
301
+ struct tc_basic_pcnt *pf = per_cpu_ptr(f->pf, cpu);
302
+
303
+ gpf.rcnt += pf->rcnt;
304
+ gpf.rhit += pf->rhit;
305
+ }
306
+
307
+ if (nla_put_64bit(skb, TCA_BASIC_PCNT,
308
+ sizeof(struct tc_basic_pcnt),
309
+ &gpf, TCA_BASIC_PAD))
310
+ goto nla_put_failure;
311
+
289312 if (tcf_exts_dump(skb, &f->exts) < 0 ||
290313 tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0)
291314 goto nla_put_failure;