hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/net/sched/act_police.c
....@@ -1,10 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * net/sched/act_police.c Input police filter
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: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
106 * J Hadi Salim (action changes)
....@@ -21,35 +17,8 @@
2117 #include <linux/slab.h>
2218 #include <net/act_api.h>
2319 #include <net/netlink.h>
24
-
25
-struct tcf_police {
26
- struct tc_action common;
27
- int tcfp_result;
28
- u32 tcfp_ewma_rate;
29
- s64 tcfp_burst;
30
- u32 tcfp_mtu;
31
- s64 tcfp_toks;
32
- s64 tcfp_ptoks;
33
- s64 tcfp_mtu_ptoks;
34
- s64 tcfp_t_c;
35
- struct psched_ratecfg rate;
36
- bool rate_present;
37
- struct psched_ratecfg peak;
38
- bool peak_present;
39
-};
40
-
41
-#define to_police(pc) ((struct tcf_police *)pc)
42
-
43
-/* old policer structure from before tc actions */
44
-struct tc_police_compat {
45
- u32 index;
46
- int action;
47
- u32 limit;
48
- u32 burst;
49
- u32 mtu;
50
- struct tc_ratespec rate;
51
- struct tc_ratespec peakrate;
52
-};
20
+#include <net/pkt_cls.h>
21
+#include <net/tc_act/tc_police.h>
5322
5423 /* Each policer is serialized by its individual spinlock */
5524
....@@ -71,27 +40,33 @@
7140 [TCA_POLICE_PEAKRATE] = { .len = TC_RTAB_SIZE },
7241 [TCA_POLICE_AVRATE] = { .type = NLA_U32 },
7342 [TCA_POLICE_RESULT] = { .type = NLA_U32 },
43
+ [TCA_POLICE_RATE64] = { .type = NLA_U64 },
44
+ [TCA_POLICE_PEAKRATE64] = { .type = NLA_U64 },
7445 };
7546
7647 static int tcf_police_init(struct net *net, struct nlattr *nla,
7748 struct nlattr *est, struct tc_action **a,
7849 int ovr, int bind, bool rtnl_held,
50
+ struct tcf_proto *tp, u32 flags,
7951 struct netlink_ext_ack *extack)
8052 {
81
- int ret = 0, err;
53
+ int ret = 0, tcfp_result = TC_ACT_OK, err, size;
8254 struct nlattr *tb[TCA_POLICE_MAX + 1];
55
+ struct tcf_chain *goto_ch = NULL;
8356 struct tc_police *parm;
8457 struct tcf_police *police;
8558 struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
8659 struct tc_action_net *tn = net_generic(net, police_net_id);
60
+ struct tcf_police_params *new;
8761 bool exists = false;
8862 u32 index;
89
- int size;
63
+ u64 rate64, prate64;
9064
9165 if (nla == NULL)
9266 return -EINVAL;
9367
94
- err = nla_parse_nested(tb, TCA_POLICE_MAX, nla, police_policy, NULL);
68
+ err = nla_parse_nested_deprecated(tb, TCA_POLICE_MAX, nla,
69
+ police_policy, NULL);
9570 if (err < 0)
9671 return err;
9772
....@@ -112,16 +87,20 @@
11287
11388 if (!exists) {
11489 ret = tcf_idr_create(tn, index, NULL, a,
115
- &act_police_ops, bind, false);
90
+ &act_police_ops, bind, true, flags);
11691 if (ret) {
11792 tcf_idr_cleanup(tn, index);
11893 return ret;
11994 }
12095 ret = ACT_P_CREATED;
96
+ spin_lock_init(&(to_police(*a)->tcfp_lock));
12197 } else if (!ovr) {
12298 tcf_idr_release(*a, bind);
12399 return -EEXIST;
124100 }
101
+ err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
102
+ if (err < 0)
103
+ goto release_idr;
125104
126105 police = to_police(*a);
127106 if (parm->rate.rate) {
....@@ -139,7 +118,8 @@
139118 }
140119
141120 if (est) {
142
- err = gen_replace_estimator(&police->tcf_bstats, NULL,
121
+ err = gen_replace_estimator(&police->tcf_bstats,
122
+ police->common.cpu_bstats,
143123 &police->tcf_rate_est,
144124 &police->tcf_lock,
145125 NULL, est);
....@@ -152,121 +132,182 @@
152132 goto failure;
153133 }
154134
155
- spin_lock_bh(&police->tcf_lock);
135
+ if (tb[TCA_POLICE_RESULT]) {
136
+ tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]);
137
+ if (TC_ACT_EXT_CMP(tcfp_result, TC_ACT_GOTO_CHAIN)) {
138
+ NL_SET_ERR_MSG(extack,
139
+ "goto chain not allowed on fallback");
140
+ err = -EINVAL;
141
+ goto failure;
142
+ }
143
+ }
144
+
145
+ new = kzalloc(sizeof(*new), GFP_KERNEL);
146
+ if (unlikely(!new)) {
147
+ err = -ENOMEM;
148
+ goto failure;
149
+ }
150
+
156151 /* No failure allowed after this point */
157
- police->tcfp_mtu = parm->mtu;
158
- if (police->tcfp_mtu == 0) {
159
- police->tcfp_mtu = ~0;
152
+ new->tcfp_result = tcfp_result;
153
+ new->tcfp_mtu = parm->mtu;
154
+ if (!new->tcfp_mtu) {
155
+ new->tcfp_mtu = ~0;
160156 if (R_tab)
161
- police->tcfp_mtu = 255 << R_tab->rate.cell_log;
157
+ new->tcfp_mtu = 255 << R_tab->rate.cell_log;
162158 }
163159 if (R_tab) {
164
- police->rate_present = true;
165
- psched_ratecfg_precompute(&police->rate, &R_tab->rate, 0);
160
+ new->rate_present = true;
161
+ rate64 = tb[TCA_POLICE_RATE64] ?
162
+ nla_get_u64(tb[TCA_POLICE_RATE64]) : 0;
163
+ psched_ratecfg_precompute(&new->rate, &R_tab->rate, rate64);
166164 qdisc_put_rtab(R_tab);
167165 } else {
168
- police->rate_present = false;
166
+ new->rate_present = false;
169167 }
170168 if (P_tab) {
171
- police->peak_present = true;
172
- psched_ratecfg_precompute(&police->peak, &P_tab->rate, 0);
169
+ new->peak_present = true;
170
+ prate64 = tb[TCA_POLICE_PEAKRATE64] ?
171
+ nla_get_u64(tb[TCA_POLICE_PEAKRATE64]) : 0;
172
+ psched_ratecfg_precompute(&new->peak, &P_tab->rate, prate64);
173173 qdisc_put_rtab(P_tab);
174174 } else {
175
- police->peak_present = false;
175
+ new->peak_present = false;
176176 }
177177
178
- if (tb[TCA_POLICE_RESULT])
179
- police->tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]);
180
- police->tcfp_burst = PSCHED_TICKS2NS(parm->burst);
181
- police->tcfp_toks = police->tcfp_burst;
182
- if (police->peak_present) {
183
- police->tcfp_mtu_ptoks = (s64) psched_l2t_ns(&police->peak,
184
- police->tcfp_mtu);
185
- police->tcfp_ptoks = police->tcfp_mtu_ptoks;
186
- }
187
- police->tcf_action = parm->action;
178
+ new->tcfp_burst = PSCHED_TICKS2NS(parm->burst);
179
+ if (new->peak_present)
180
+ new->tcfp_mtu_ptoks = (s64)psched_l2t_ns(&new->peak,
181
+ new->tcfp_mtu);
188182
189183 if (tb[TCA_POLICE_AVRATE])
190
- police->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]);
184
+ new->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]);
191185
192
- spin_unlock_bh(&police->tcf_lock);
193
- if (ret != ACT_P_CREATED)
194
- return ret;
195
-
186
+ spin_lock_bh(&police->tcf_lock);
187
+ spin_lock_bh(&police->tcfp_lock);
196188 police->tcfp_t_c = ktime_get_ns();
197
- tcf_idr_insert(tn, *a);
189
+ police->tcfp_toks = new->tcfp_burst;
190
+ if (new->peak_present)
191
+ police->tcfp_ptoks = new->tcfp_mtu_ptoks;
192
+ spin_unlock_bh(&police->tcfp_lock);
193
+ goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
194
+ new = rcu_replace_pointer(police->params,
195
+ new,
196
+ lockdep_is_held(&police->tcf_lock));
197
+ spin_unlock_bh(&police->tcf_lock);
198
+
199
+ if (goto_ch)
200
+ tcf_chain_put_by_act(goto_ch);
201
+ if (new)
202
+ kfree_rcu(new, rcu);
198203
199204 return ret;
200205
201206 failure:
202207 qdisc_put_rtab(P_tab);
203208 qdisc_put_rtab(R_tab);
209
+ if (goto_ch)
210
+ tcf_chain_put_by_act(goto_ch);
211
+release_idr:
204212 tcf_idr_release(*a, bind);
205213 return err;
214
+}
215
+
216
+static bool tcf_police_mtu_check(struct sk_buff *skb, u32 limit)
217
+{
218
+ u32 len;
219
+
220
+ if (skb_is_gso(skb))
221
+ return skb_gso_validate_mac_len(skb, limit);
222
+
223
+ len = qdisc_pkt_len(skb);
224
+ if (skb_at_tc_ingress(skb))
225
+ len += skb->mac_len;
226
+
227
+ return len <= limit;
206228 }
207229
208230 static int tcf_police_act(struct sk_buff *skb, const struct tc_action *a,
209231 struct tcf_result *res)
210232 {
211233 struct tcf_police *police = to_police(a);
212
- s64 now;
213
- s64 toks;
214
- s64 ptoks = 0;
234
+ struct tcf_police_params *p;
235
+ s64 now, toks, ptoks = 0;
236
+ int ret;
215237
216
- spin_lock(&police->tcf_lock);
217
-
218
- bstats_update(&police->tcf_bstats, skb);
219238 tcf_lastuse_update(&police->tcf_tm);
239
+ bstats_cpu_update(this_cpu_ptr(police->common.cpu_bstats), skb);
220240
221
- if (police->tcfp_ewma_rate) {
241
+ ret = READ_ONCE(police->tcf_action);
242
+ p = rcu_dereference_bh(police->params);
243
+
244
+ if (p->tcfp_ewma_rate) {
222245 struct gnet_stats_rate_est64 sample;
223246
224247 if (!gen_estimator_read(&police->tcf_rate_est, &sample) ||
225
- sample.bps >= police->tcfp_ewma_rate) {
226
- police->tcf_qstats.overlimits++;
227
- if (police->tcf_action == TC_ACT_SHOT)
228
- police->tcf_qstats.drops++;
229
- spin_unlock(&police->tcf_lock);
230
- return police->tcf_action;
231
- }
248
+ sample.bps >= p->tcfp_ewma_rate)
249
+ goto inc_overlimits;
232250 }
233251
234
- if (qdisc_pkt_len(skb) <= police->tcfp_mtu) {
235
- if (!police->rate_present) {
236
- spin_unlock(&police->tcf_lock);
237
- return police->tcfp_result;
252
+ if (tcf_police_mtu_check(skb, p->tcfp_mtu)) {
253
+ if (!p->rate_present) {
254
+ ret = p->tcfp_result;
255
+ goto end;
238256 }
239257
240258 now = ktime_get_ns();
241
- toks = min_t(s64, now - police->tcfp_t_c,
242
- police->tcfp_burst);
243
- if (police->peak_present) {
259
+ spin_lock_bh(&police->tcfp_lock);
260
+ toks = min_t(s64, now - police->tcfp_t_c, p->tcfp_burst);
261
+ if (p->peak_present) {
244262 ptoks = toks + police->tcfp_ptoks;
245
- if (ptoks > police->tcfp_mtu_ptoks)
246
- ptoks = police->tcfp_mtu_ptoks;
247
- ptoks -= (s64) psched_l2t_ns(&police->peak,
248
- qdisc_pkt_len(skb));
263
+ if (ptoks > p->tcfp_mtu_ptoks)
264
+ ptoks = p->tcfp_mtu_ptoks;
265
+ ptoks -= (s64)psched_l2t_ns(&p->peak,
266
+ qdisc_pkt_len(skb));
249267 }
250268 toks += police->tcfp_toks;
251
- if (toks > police->tcfp_burst)
252
- toks = police->tcfp_burst;
253
- toks -= (s64) psched_l2t_ns(&police->rate, qdisc_pkt_len(skb));
269
+ if (toks > p->tcfp_burst)
270
+ toks = p->tcfp_burst;
271
+ toks -= (s64)psched_l2t_ns(&p->rate, qdisc_pkt_len(skb));
254272 if ((toks|ptoks) >= 0) {
255273 police->tcfp_t_c = now;
256274 police->tcfp_toks = toks;
257275 police->tcfp_ptoks = ptoks;
258
- if (police->tcfp_result == TC_ACT_SHOT)
259
- police->tcf_qstats.drops++;
260
- spin_unlock(&police->tcf_lock);
261
- return police->tcfp_result;
276
+ spin_unlock_bh(&police->tcfp_lock);
277
+ ret = p->tcfp_result;
278
+ goto inc_drops;
262279 }
280
+ spin_unlock_bh(&police->tcfp_lock);
263281 }
264282
265
- police->tcf_qstats.overlimits++;
266
- if (police->tcf_action == TC_ACT_SHOT)
267
- police->tcf_qstats.drops++;
268
- spin_unlock(&police->tcf_lock);
269
- return police->tcf_action;
283
+inc_overlimits:
284
+ qstats_overlimit_inc(this_cpu_ptr(police->common.cpu_qstats));
285
+inc_drops:
286
+ if (ret == TC_ACT_SHOT)
287
+ qstats_drop_inc(this_cpu_ptr(police->common.cpu_qstats));
288
+end:
289
+ return ret;
290
+}
291
+
292
+static void tcf_police_cleanup(struct tc_action *a)
293
+{
294
+ struct tcf_police *police = to_police(a);
295
+ struct tcf_police_params *p;
296
+
297
+ p = rcu_dereference_protected(police->params, 1);
298
+ if (p)
299
+ kfree_rcu(p, rcu);
300
+}
301
+
302
+static void tcf_police_stats_update(struct tc_action *a,
303
+ u64 bytes, u64 packets, u64 drops,
304
+ u64 lastuse, bool hw)
305
+{
306
+ struct tcf_police *police = to_police(a);
307
+ struct tcf_t *tm = &police->tcf_tm;
308
+
309
+ tcf_action_update_stats(a, bytes, packets, drops, hw);
310
+ tm->lastuse = max_t(u64, tm->lastuse, lastuse);
270311 }
271312
272313 static int tcf_police_dump(struct sk_buff *skb, struct tc_action *a,
....@@ -274,6 +315,7 @@
274315 {
275316 unsigned char *b = skb_tail_pointer(skb);
276317 struct tcf_police *police = to_police(a);
318
+ struct tcf_police_params *p;
277319 struct tc_police opt = {
278320 .index = police->tcf_index,
279321 .refcnt = refcount_read(&police->tcf_refcnt) - ref,
....@@ -283,25 +325,36 @@
283325
284326 spin_lock_bh(&police->tcf_lock);
285327 opt.action = police->tcf_action;
286
- opt.mtu = police->tcfp_mtu;
287
- opt.burst = PSCHED_NS2TICKS(police->tcfp_burst);
288
- if (police->rate_present)
289
- psched_ratecfg_getrate(&opt.rate, &police->rate);
290
- if (police->peak_present)
291
- psched_ratecfg_getrate(&opt.peakrate, &police->peak);
328
+ p = rcu_dereference_protected(police->params,
329
+ lockdep_is_held(&police->tcf_lock));
330
+ opt.mtu = p->tcfp_mtu;
331
+ opt.burst = PSCHED_NS2TICKS(p->tcfp_burst);
332
+ if (p->rate_present) {
333
+ psched_ratecfg_getrate(&opt.rate, &p->rate);
334
+ if ((police->params->rate.rate_bytes_ps >= (1ULL << 32)) &&
335
+ nla_put_u64_64bit(skb, TCA_POLICE_RATE64,
336
+ police->params->rate.rate_bytes_ps,
337
+ TCA_POLICE_PAD))
338
+ goto nla_put_failure;
339
+ }
340
+ if (p->peak_present) {
341
+ psched_ratecfg_getrate(&opt.peakrate, &p->peak);
342
+ if ((police->params->peak.rate_bytes_ps >= (1ULL << 32)) &&
343
+ nla_put_u64_64bit(skb, TCA_POLICE_PEAKRATE64,
344
+ police->params->peak.rate_bytes_ps,
345
+ TCA_POLICE_PAD))
346
+ goto nla_put_failure;
347
+ }
292348 if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt))
293349 goto nla_put_failure;
294
- if (police->tcfp_result &&
295
- nla_put_u32(skb, TCA_POLICE_RESULT, police->tcfp_result))
350
+ if (p->tcfp_result &&
351
+ nla_put_u32(skb, TCA_POLICE_RESULT, p->tcfp_result))
296352 goto nla_put_failure;
297
- if (police->tcfp_ewma_rate &&
298
- nla_put_u32(skb, TCA_POLICE_AVRATE, police->tcfp_ewma_rate))
353
+ if (p->tcfp_ewma_rate &&
354
+ nla_put_u32(skb, TCA_POLICE_AVRATE, p->tcfp_ewma_rate))
299355 goto nla_put_failure;
300356
301
- t.install = jiffies_to_clock_t(jiffies - police->tcf_tm.install);
302
- t.lastuse = jiffies_to_clock_t(jiffies - police->tcf_tm.lastuse);
303
- t.firstuse = jiffies_to_clock_t(jiffies - police->tcf_tm.firstuse);
304
- t.expires = jiffies_to_clock_t(police->tcf_tm.expires);
357
+ tcf_tm_dump(&t, &police->tcf_tm);
305358 if (nla_put_64bit(skb, TCA_POLICE_TM, sizeof(t), &t, TCA_POLICE_PAD))
306359 goto nla_put_failure;
307360 spin_unlock_bh(&police->tcf_lock);
....@@ -314,8 +367,7 @@
314367 return -1;
315368 }
316369
317
-static int tcf_police_search(struct net *net, struct tc_action **a, u32 index,
318
- struct netlink_ext_ack *extack)
370
+static int tcf_police_search(struct net *net, struct tc_action **a, u32 index)
319371 {
320372 struct tc_action_net *tn = net_generic(net, police_net_id);
321373
....@@ -328,13 +380,15 @@
328380
329381 static struct tc_action_ops act_police_ops = {
330382 .kind = "police",
331
- .type = TCA_ID_POLICE,
383
+ .id = TCA_ID_POLICE,
332384 .owner = THIS_MODULE,
385
+ .stats_update = tcf_police_stats_update,
333386 .act = tcf_police_act,
334387 .dump = tcf_police_dump,
335388 .init = tcf_police_init,
336389 .walk = tcf_police_walker,
337390 .lookup = tcf_police_search,
391
+ .cleanup = tcf_police_cleanup,
338392 .size = sizeof(struct tcf_police),
339393 };
340394