]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - net/sched/act_police.c
net: openvswitch: Set OvS recirc_id from tc chain index
[mirror_ubuntu-hirsute-kernel.git] / net / sched / act_police.c
CommitLineData
2874c5fd 1// SPDX-License-Identifier: GPL-2.0-or-later
1da177e4 2/*
0c6965dd 3 * net/sched/act_police.c Input police filter
1da177e4 4 *
1da177e4
LT
5 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
6 * J Hadi Salim (action changes)
7 */
8
1da177e4
LT
9#include <linux/module.h>
10#include <linux/types.h>
11#include <linux/kernel.h>
1da177e4 12#include <linux/string.h>
1da177e4 13#include <linux/errno.h>
1da177e4 14#include <linux/skbuff.h>
1da177e4
LT
15#include <linux/rtnetlink.h>
16#include <linux/init.h>
5a0e3ad6 17#include <linux/slab.h>
1da177e4 18#include <net/act_api.h>
dc5fc579 19#include <net/netlink.h>
d6124d6b 20#include <net/pkt_cls.h>
fa762da9 21#include <net/tc_act/tc_police.h>
1e9b3d53 22
e9ce1cd3 23/* Each policer is serialized by its individual spinlock */
1da177e4 24
c7d03a00 25static unsigned int police_net_id;
a85a970a 26static struct tc_action_ops act_police_ops;
ddf97ccd 27
2ac06347 28static int tcf_police_walker(struct net *net, struct sk_buff *skb,
ddf97ccd 29 struct netlink_callback *cb, int type,
41780105
AA
30 const struct tc_action_ops *ops,
31 struct netlink_ext_ack *extack)
1da177e4 32{
ddf97ccd 33 struct tc_action_net *tn = net_generic(net, police_net_id);
1da177e4 34
b3620145 35 return tcf_generic_walker(tn, skb, cb, type, ops, extack);
1da177e4 36}
1da177e4 37
53b2bf3f
PM
38static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
39 [TCA_POLICE_RATE] = { .len = TC_RTAB_SIZE },
40 [TCA_POLICE_PEAKRATE] = { .len = TC_RTAB_SIZE },
41 [TCA_POLICE_AVRATE] = { .type = NLA_U32 },
42 [TCA_POLICE_RESULT] = { .type = NLA_U32 },
43};
44
2ac06347 45static int tcf_police_init(struct net *net, struct nlattr *nla,
a85a970a 46 struct nlattr *est, struct tc_action **a,
789871bb 47 int ovr, int bind, bool rtnl_held,
85d0966f 48 struct tcf_proto *tp,
589dad6d 49 struct netlink_ext_ack *extack)
1da177e4 50{
fd6d4338 51 int ret = 0, tcfp_result = TC_ACT_OK, err, size;
7ba699c6 52 struct nlattr *tb[TCA_POLICE_MAX + 1];
d6124d6b 53 struct tcf_chain *goto_ch = NULL;
1da177e4 54 struct tc_police *parm;
e9ce1cd3 55 struct tcf_police *police;
1da177e4 56 struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
ddf97ccd 57 struct tc_action_net *tn = net_generic(net, police_net_id);
2d550dba 58 struct tcf_police_params *new;
0852e455 59 bool exists = false;
7be8ef2c 60 u32 index;
1da177e4 61
cee63723 62 if (nla == NULL)
1da177e4
LT
63 return -EINVAL;
64
8cb08174
JB
65 err = nla_parse_nested_deprecated(tb, TCA_POLICE_MAX, nla,
66 police_policy, NULL);
cee63723
PM
67 if (err < 0)
68 return err;
69
7ba699c6 70 if (tb[TCA_POLICE_TBF] == NULL)
1e9b3d53 71 return -EINVAL;
7ba699c6 72 size = nla_len(tb[TCA_POLICE_TBF]);
1e9b3d53 73 if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
1da177e4 74 return -EINVAL;
0852e455 75
7ba699c6 76 parm = nla_data(tb[TCA_POLICE_TBF]);
7be8ef2c
DL
77 index = parm->index;
78 err = tcf_idr_check_alloc(tn, &index, a, bind);
0190c1d4
VB
79 if (err < 0)
80 return err;
81 exists = err;
0852e455
WC
82 if (exists && bind)
83 return 0;
1da177e4 84
0852e455 85 if (!exists) {
7be8ef2c 86 ret = tcf_idr_create(tn, index, NULL, a,
93be42f9 87 &act_police_ops, bind, true);
0190c1d4 88 if (ret) {
7be8ef2c 89 tcf_idr_cleanup(tn, index);
a03e6fe5 90 return ret;
0190c1d4 91 }
a03e6fe5 92 ret = ACT_P_CREATED;
484afd1b 93 spin_lock_init(&(to_police(*a)->tcfp_lock));
4e8ddd7f 94 } else if (!ovr) {
65a206c0 95 tcf_idr_release(*a, bind);
4e8ddd7f 96 return -EEXIST;
1da177e4 97 }
d6124d6b
DC
98 err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
99 if (err < 0)
100 goto release_idr;
1da177e4 101
a85a970a 102 police = to_police(*a);
1da177e4
LT
103 if (parm->rate.rate) {
104 err = -ENOMEM;
e9bc3fa2 105 R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE], NULL);
1da177e4
LT
106 if (R_tab == NULL)
107 goto failure;
c1b56878 108
1da177e4
LT
109 if (parm->peakrate.rate) {
110 P_tab = qdisc_get_rtab(&parm->peakrate,
e9bc3fa2 111 tb[TCA_POLICE_PEAKRATE], NULL);
71bcb09a 112 if (P_tab == NULL)
1da177e4 113 goto failure;
1da177e4
LT
114 }
115 }
71bcb09a 116
71bcb09a 117 if (est) {
93be42f9
DC
118 err = gen_replace_estimator(&police->tcf_bstats,
119 police->common.cpu_bstats,
71bcb09a 120 &police->tcf_rate_est,
edb09eb1
ED
121 &police->tcf_lock,
122 NULL, est);
71bcb09a 123 if (err)
74030603 124 goto failure;
a883bf56
JP
125 } else if (tb[TCA_POLICE_AVRATE] &&
126 (ret == ACT_P_CREATED ||
1c0d32fd 127 !gen_estimator_active(&police->tcf_rate_est))) {
a883bf56 128 err = -EINVAL;
74030603 129 goto failure;
71bcb09a
SH
130 }
131
fd6d4338
DC
132 if (tb[TCA_POLICE_RESULT]) {
133 tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]);
134 if (TC_ACT_EXT_CMP(tcfp_result, TC_ACT_GOTO_CHAIN)) {
135 NL_SET_ERR_MSG(extack,
136 "goto chain not allowed on fallback");
137 err = -EINVAL;
138 goto failure;
139 }
140 }
141
2d550dba
DC
142 new = kzalloc(sizeof(*new), GFP_KERNEL);
143 if (unlikely(!new)) {
144 err = -ENOMEM;
145 goto failure;
146 }
147
71bcb09a 148 /* No failure allowed after this point */
fd6d4338 149 new->tcfp_result = tcfp_result;
2d550dba
DC
150 new->tcfp_mtu = parm->mtu;
151 if (!new->tcfp_mtu) {
152 new->tcfp_mtu = ~0;
c6d14ff1 153 if (R_tab)
2d550dba 154 new->tcfp_mtu = 255 << R_tab->rate.cell_log;
c6d14ff1
JP
155 }
156 if (R_tab) {
2d550dba
DC
157 new->rate_present = true;
158 psched_ratecfg_precompute(&new->rate, &R_tab->rate, 0);
c6d14ff1
JP
159 qdisc_put_rtab(R_tab);
160 } else {
2d550dba 161 new->rate_present = false;
1da177e4 162 }
c6d14ff1 163 if (P_tab) {
2d550dba
DC
164 new->peak_present = true;
165 psched_ratecfg_precompute(&new->peak, &P_tab->rate, 0);
c6d14ff1
JP
166 qdisc_put_rtab(P_tab);
167 } else {
2d550dba 168 new->peak_present = false;
1da177e4
LT
169 }
170
2d550dba 171 new->tcfp_burst = PSCHED_TICKS2NS(parm->burst);
f2cbd485 172 if (new->peak_present)
2d550dba
DC
173 new->tcfp_mtu_ptoks = (s64)psched_l2t_ns(&new->peak,
174 new->tcfp_mtu);
1da177e4 175
7ba699c6 176 if (tb[TCA_POLICE_AVRATE])
2d550dba 177 new->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]);
1da177e4 178
2d550dba 179 spin_lock_bh(&police->tcf_lock);
f2cbd485
DC
180 spin_lock_bh(&police->tcfp_lock);
181 police->tcfp_t_c = ktime_get_ns();
182 police->tcfp_toks = new->tcfp_burst;
183 if (new->peak_present)
184 police->tcfp_ptoks = new->tcfp_mtu_ptoks;
185 spin_unlock_bh(&police->tcfp_lock);
d6124d6b 186 goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
2d550dba
DC
187 rcu_swap_protected(police->params,
188 new,
189 lockdep_is_held(&police->tcf_lock));
e9ce1cd3 190 spin_unlock_bh(&police->tcf_lock);
1da177e4 191
d6124d6b
DC
192 if (goto_ch)
193 tcf_chain_put_by_act(goto_ch);
2d550dba
DC
194 if (new)
195 kfree_rcu(new, rcu);
1da177e4 196
2d550dba
DC
197 if (ret == ACT_P_CREATED)
198 tcf_idr_insert(tn, *a);
1da177e4
LT
199 return ret;
200
201failure:
3b69a4c9
YY
202 qdisc_put_rtab(P_tab);
203 qdisc_put_rtab(R_tab);
d6124d6b
DC
204 if (goto_ch)
205 tcf_chain_put_by_act(goto_ch);
206release_idr:
4e8ddd7f 207 tcf_idr_release(*a, bind);
1da177e4
LT
208 return err;
209}
210
2ac06347 211static int tcf_police_act(struct sk_buff *skb, const struct tc_action *a,
10297b99 212 struct tcf_result *res)
1da177e4 213{
a85a970a 214 struct tcf_police *police = to_police(a);
2d550dba 215 struct tcf_police_params *p;
93be42f9
DC
216 s64 now, toks, ptoks = 0;
217 int ret;
1da177e4 218
3d3ed181 219 tcf_lastuse_update(&police->tcf_tm);
93be42f9 220 bstats_cpu_update(this_cpu_ptr(police->common.cpu_bstats), skb);
1da177e4 221
2d550dba
DC
222 ret = READ_ONCE(police->tcf_action);
223 p = rcu_dereference_bh(police->params);
224
225 if (p->tcfp_ewma_rate) {
1c0d32fd
ED
226 struct gnet_stats_rate_est64 sample;
227
228 if (!gen_estimator_read(&police->tcf_rate_est, &sample) ||
2d550dba 229 sample.bps >= p->tcfp_ewma_rate)
93be42f9 230 goto inc_overlimits;
1da177e4 231 }
1da177e4 232
2d550dba
DC
233 if (qdisc_pkt_len(skb) <= p->tcfp_mtu) {
234 if (!p->rate_present) {
235 ret = p->tcfp_result;
236 goto end;
1da177e4
LT
237 }
238
d2de875c 239 now = ktime_get_ns();
f2cbd485
DC
240 spin_lock_bh(&police->tcfp_lock);
241 toks = min_t(s64, now - police->tcfp_t_c, p->tcfp_burst);
2d550dba 242 if (p->peak_present) {
f2cbd485 243 ptoks = toks + police->tcfp_ptoks;
2d550dba
DC
244 if (ptoks > p->tcfp_mtu_ptoks)
245 ptoks = p->tcfp_mtu_ptoks;
246 ptoks -= (s64)psched_l2t_ns(&p->peak,
247 qdisc_pkt_len(skb));
1da177e4 248 }
f2cbd485 249 toks += police->tcfp_toks;
2d550dba
DC
250 if (toks > p->tcfp_burst)
251 toks = p->tcfp_burst;
252 toks -= (s64)psched_l2t_ns(&p->rate, qdisc_pkt_len(skb));
1da177e4 253 if ((toks|ptoks) >= 0) {
f2cbd485
DC
254 police->tcfp_t_c = now;
255 police->tcfp_toks = toks;
256 police->tcfp_ptoks = ptoks;
257 spin_unlock_bh(&police->tcfp_lock);
2d550dba 258 ret = p->tcfp_result;
93be42f9 259 goto inc_drops;
1da177e4 260 }
f2cbd485 261 spin_unlock_bh(&police->tcfp_lock);
1da177e4 262 }
93be42f9
DC
263
264inc_overlimits:
265 qstats_overlimit_inc(this_cpu_ptr(police->common.cpu_qstats));
266inc_drops:
267 if (ret == TC_ACT_SHOT)
268 qstats_drop_inc(this_cpu_ptr(police->common.cpu_qstats));
2d550dba 269end:
93be42f9 270 return ret;
1da177e4
LT
271}
272
2d550dba
DC
273static void tcf_police_cleanup(struct tc_action *a)
274{
275 struct tcf_police *police = to_police(a);
276 struct tcf_police_params *p;
277
278 p = rcu_dereference_protected(police->params, 1);
279 if (p)
280 kfree_rcu(p, rcu);
281}
282
12f02b6b
PJV
283static void tcf_police_stats_update(struct tc_action *a,
284 u64 bytes, u32 packets,
285 u64 lastuse, bool hw)
286{
287 struct tcf_police *police = to_police(a);
288 struct tcf_t *tm = &police->tcf_tm;
289
290 _bstats_cpu_update(this_cpu_ptr(a->cpu_bstats), bytes, packets);
291 if (hw)
292 _bstats_cpu_update(this_cpu_ptr(a->cpu_bstats_hw),
293 bytes, packets);
294 tm->lastuse = max_t(u64, tm->lastuse, lastuse);
295}
296
2ac06347 297static int tcf_police_dump(struct sk_buff *skb, struct tc_action *a,
5a7a5555 298 int bind, int ref)
1da177e4 299{
27a884dc 300 unsigned char *b = skb_tail_pointer(skb);
a85a970a 301 struct tcf_police *police = to_police(a);
2d550dba 302 struct tcf_police_params *p;
0f04cfd0
JM
303 struct tc_police opt = {
304 .index = police->tcf_index,
036bb443
VB
305 .refcnt = refcount_read(&police->tcf_refcnt) - ref,
306 .bindcnt = atomic_read(&police->tcf_bindcnt) - bind,
0f04cfd0 307 };
3d3ed181 308 struct tcf_t t;
0f04cfd0 309
e329bc42
VB
310 spin_lock_bh(&police->tcf_lock);
311 opt.action = police->tcf_action;
2d550dba
DC
312 p = rcu_dereference_protected(police->params,
313 lockdep_is_held(&police->tcf_lock));
314 opt.mtu = p->tcfp_mtu;
315 opt.burst = PSCHED_NS2TICKS(p->tcfp_burst);
316 if (p->rate_present)
317 psched_ratecfg_getrate(&opt.rate, &p->rate);
318 if (p->peak_present)
319 psched_ratecfg_getrate(&opt.peakrate, &p->peak);
1b34ec43
DM
320 if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt))
321 goto nla_put_failure;
2d550dba
DC
322 if (p->tcfp_result &&
323 nla_put_u32(skb, TCA_POLICE_RESULT, p->tcfp_result))
1b34ec43 324 goto nla_put_failure;
2d550dba
DC
325 if (p->tcfp_ewma_rate &&
326 nla_put_u32(skb, TCA_POLICE_AVRATE, p->tcfp_ewma_rate))
1b34ec43 327 goto nla_put_failure;
3d3ed181
JHS
328
329 t.install = jiffies_to_clock_t(jiffies - police->tcf_tm.install);
330 t.lastuse = jiffies_to_clock_t(jiffies - police->tcf_tm.lastuse);
53eb440f 331 t.firstuse = jiffies_to_clock_t(jiffies - police->tcf_tm.firstuse);
3d3ed181
JHS
332 t.expires = jiffies_to_clock_t(police->tcf_tm.expires);
333 if (nla_put_64bit(skb, TCA_POLICE_TM, sizeof(t), &t, TCA_POLICE_PAD))
334 goto nla_put_failure;
e329bc42 335 spin_unlock_bh(&police->tcf_lock);
3d3ed181 336
1da177e4
LT
337 return skb->len;
338
7ba699c6 339nla_put_failure:
e329bc42 340 spin_unlock_bh(&police->tcf_lock);
dc5fc579 341 nlmsg_trim(skb, b);
1da177e4
LT
342 return -1;
343}
344
f061b48c 345static int tcf_police_search(struct net *net, struct tc_action **a, u32 index)
ddf97ccd
WC
346{
347 struct tc_action_net *tn = net_generic(net, police_net_id);
348
65a206c0 349 return tcf_idr_search(tn, a, index);
ddf97ccd
WC
350}
351
1da177e4
LT
352MODULE_AUTHOR("Alexey Kuznetsov");
353MODULE_DESCRIPTION("Policing actions");
354MODULE_LICENSE("GPL");
355
356static struct tc_action_ops act_police_ops = {
357 .kind = "police",
eddd2cf1 358 .id = TCA_ID_POLICE,
1da177e4 359 .owner = THIS_MODULE,
12f02b6b 360 .stats_update = tcf_police_stats_update,
2ac06347
JHS
361 .act = tcf_police_act,
362 .dump = tcf_police_dump,
363 .init = tcf_police_init,
364 .walk = tcf_police_walker,
ddf97ccd 365 .lookup = tcf_police_search,
2d550dba 366 .cleanup = tcf_police_cleanup,
a85a970a 367 .size = sizeof(struct tcf_police),
ddf97ccd
WC
368};
369
370static __net_init int police_init_net(struct net *net)
371{
372 struct tc_action_net *tn = net_generic(net, police_net_id);
373
981471bd 374 return tc_action_net_init(net, tn, &act_police_ops);
ddf97ccd
WC
375}
376
039af9c6 377static void __net_exit police_exit_net(struct list_head *net_list)
ddf97ccd 378{
039af9c6 379 tc_action_net_exit(net_list, police_net_id);
ddf97ccd
WC
380}
381
382static struct pernet_operations police_net_ops = {
383 .init = police_init_net,
039af9c6 384 .exit_batch = police_exit_net,
ddf97ccd
WC
385 .id = &police_net_id,
386 .size = sizeof(struct tc_action_net),
1da177e4
LT
387};
388
5a7a5555 389static int __init police_init_module(void)
1da177e4 390{
ddf97ccd 391 return tcf_register_action(&act_police_ops, &police_net_ops);
1da177e4
LT
392}
393
5a7a5555 394static void __exit police_cleanup_module(void)
1da177e4 395{
ddf97ccd 396 tcf_unregister_action(&act_police_ops, &police_net_ops);
1da177e4
LT
397}
398
399module_init(police_init_module);
400module_exit(police_cleanup_module);