act_gate.c (b64ee4856c106fc743880c1a33074c7bcebf6eb6) act_gate.c (4b61d3e8d3daebbde7ec02d593f84248fdf8bec2)
1// SPDX-License-Identifier: GPL-2.0-or-later
2/* Copyright 2020 NXP */
3
4#include <linux/module.h>
5#include <linux/types.h>
6#include <linux/kernel.h>
7#include <linux/string.h>
8#include <linux/errno.h>

--- 18 unchanged lines hidden (view full) ---

27 return mono;
28 default:
29 return ktime_mono_to_any(mono, gact->tk_offset);
30 }
31
32 return KTIME_MAX;
33}
34
1// SPDX-License-Identifier: GPL-2.0-or-later
2/* Copyright 2020 NXP */
3
4#include <linux/module.h>
5#include <linux/types.h>
6#include <linux/kernel.h>
7#include <linux/string.h>
8#include <linux/errno.h>

--- 18 unchanged lines hidden (view full) ---

27 return mono;
28 default:
29 return ktime_mono_to_any(mono, gact->tk_offset);
30 }
31
32 return KTIME_MAX;
33}
34
35static void gate_get_start_time(struct tcf_gate *gact, ktime_t *start)
35static int gate_get_start_time(struct tcf_gate *gact, ktime_t *start)
36{
37 struct tcf_gate_params *param = &gact->param;
38 ktime_t now, base, cycle;
39 u64 n;
40
41 base = ns_to_ktime(param->tcfg_basetime);
42 now = gate_get_time(gact);
43
44 if (ktime_after(base, now)) {
45 *start = base;
36{
37 struct tcf_gate_params *param = &gact->param;
38 ktime_t now, base, cycle;
39 u64 n;
40
41 base = ns_to_ktime(param->tcfg_basetime);
42 now = gate_get_time(gact);
43
44 if (ktime_after(base, now)) {
45 *start = base;
46 return;
46 return 0;
47 }
48
49 cycle = param->tcfg_cycletime;
50
47 }
48
49 cycle = param->tcfg_cycletime;
50
51 /* cycle time should not be zero */
52 if (!cycle)
53 return -EFAULT;
54
51 n = div64_u64(ktime_sub_ns(now, base), cycle);
52 *start = ktime_add_ns(base, (n + 1) * cycle);
55 n = div64_u64(ktime_sub_ns(now, base), cycle);
56 *start = ktime_add_ns(base, (n + 1) * cycle);
57 return 0;
53}
54
55static void gate_start_timer(struct tcf_gate *gact, ktime_t start)
56{
57 ktime_t expires;
58
59 expires = hrtimer_get_expires(&gact->hitimer);
60 if (expires == 0)

--- 206 unchanged lines hidden (view full) ---

267 return i;
268
269release_list:
270 release_entry_list(&sched->entries);
271
272 return err;
273}
274
58}
59
60static void gate_start_timer(struct tcf_gate *gact, ktime_t start)
61{
62 ktime_t expires;
63
64 expires = hrtimer_get_expires(&gact->hitimer);
65 if (expires == 0)

--- 206 unchanged lines hidden (view full) ---

272 return i;
273
274release_list:
275 release_entry_list(&sched->entries);
276
277 return err;
278}
279
275static void gate_setup_timer(struct tcf_gate *gact, u64 basetime,
276 enum tk_offsets tko, s32 clockid,
277 bool do_init)
278{
279 if (!do_init) {
280 if (basetime == gact->param.tcfg_basetime &&
281 tko == gact->tk_offset &&
282 clockid == gact->param.tcfg_clockid)
283 return;
284
285 spin_unlock_bh(&gact->tcf_lock);
286 hrtimer_cancel(&gact->hitimer);
287 spin_lock_bh(&gact->tcf_lock);
288 }
289 gact->param.tcfg_basetime = basetime;
290 gact->param.tcfg_clockid = clockid;
291 gact->tk_offset = tko;
292 hrtimer_init(&gact->hitimer, clockid, HRTIMER_MODE_ABS_SOFT);
293 gact->hitimer.function = gate_timer_func;
294}
295
296static int tcf_gate_init(struct net *net, struct nlattr *nla,
297 struct nlattr *est, struct tc_action **a,
298 int ovr, int bind, bool rtnl_held,
299 struct tcf_proto *tp, u32 flags,
300 struct netlink_ext_ack *extack)
301{
302 struct tc_action_net *tn = net_generic(net, gate_net_id);
303 enum tk_offsets tk_offset = TK_OFFS_TAI;
304 struct nlattr *tb[TCA_GATE_MAX + 1];
305 struct tcf_chain *goto_ch = NULL;
280static int tcf_gate_init(struct net *net, struct nlattr *nla,
281 struct nlattr *est, struct tc_action **a,
282 int ovr, int bind, bool rtnl_held,
283 struct tcf_proto *tp, u32 flags,
284 struct netlink_ext_ack *extack)
285{
286 struct tc_action_net *tn = net_generic(net, gate_net_id);
287 enum tk_offsets tk_offset = TK_OFFS_TAI;
288 struct nlattr *tb[TCA_GATE_MAX + 1];
289 struct tcf_chain *goto_ch = NULL;
306 u64 cycletime = 0, basetime = 0;
307 struct tcf_gate_params *p;
308 s32 clockid = CLOCK_TAI;
309 struct tcf_gate *gact;
310 struct tc_gate *parm;
311 int ret = 0, err;
290 struct tcf_gate_params *p;
291 s32 clockid = CLOCK_TAI;
292 struct tcf_gate *gact;
293 struct tc_gate *parm;
294 int ret = 0, err;
295 u64 basetime = 0;
312 u32 gflags = 0;
313 s32 prio = -1;
314 ktime_t start;
315 u32 index;
316
317 if (!nla)
318 return -EINVAL;
319
320 err = nla_parse_nested(tb, TCA_GATE_MAX, nla, gate_policy, extack);
321 if (err < 0)
322 return err;
323
324 if (!tb[TCA_GATE_PARMS])
325 return -EINVAL;
326
296 u32 gflags = 0;
297 s32 prio = -1;
298 ktime_t start;
299 u32 index;
300
301 if (!nla)
302 return -EINVAL;
303
304 err = nla_parse_nested(tb, TCA_GATE_MAX, nla, gate_policy, extack);
305 if (err < 0)
306 return err;
307
308 if (!tb[TCA_GATE_PARMS])
309 return -EINVAL;
310
327 if (tb[TCA_GATE_CLOCKID]) {
328 clockid = nla_get_s32(tb[TCA_GATE_CLOCKID]);
329 switch (clockid) {
330 case CLOCK_REALTIME:
331 tk_offset = TK_OFFS_REAL;
332 break;
333 case CLOCK_MONOTONIC:
334 tk_offset = TK_OFFS_MAX;
335 break;
336 case CLOCK_BOOTTIME:
337 tk_offset = TK_OFFS_BOOT;
338 break;
339 case CLOCK_TAI:
340 tk_offset = TK_OFFS_TAI;
341 break;
342 default:
343 NL_SET_ERR_MSG(extack, "Invalid 'clockid'");
344 return -EINVAL;
345 }
346 }
347
348 parm = nla_data(tb[TCA_GATE_PARMS]);
349 index = parm->index;
350
351 err = tcf_idr_check_alloc(tn, &index, a, bind);
352 if (err < 0)
353 return err;
354
355 if (err && bind)

--- 7 unchanged lines hidden (view full) ---

363 return ret;
364 }
365
366 ret = ACT_P_CREATED;
367 } else if (!ovr) {
368 tcf_idr_release(*a, bind);
369 return -EEXIST;
370 }
311 parm = nla_data(tb[TCA_GATE_PARMS]);
312 index = parm->index;
313
314 err = tcf_idr_check_alloc(tn, &index, a, bind);
315 if (err < 0)
316 return err;
317
318 if (err && bind)

--- 7 unchanged lines hidden (view full) ---

326 return ret;
327 }
328
329 ret = ACT_P_CREATED;
330 } else if (!ovr) {
331 tcf_idr_release(*a, bind);
332 return -EEXIST;
333 }
334 if (ret == ACT_P_CREATED) {
335 to_gate(*a)->param.tcfg_clockid = -1;
336 INIT_LIST_HEAD(&(to_gate(*a)->param.entries));
337 }
371
372 if (tb[TCA_GATE_PRIORITY])
373 prio = nla_get_s32(tb[TCA_GATE_PRIORITY]);
374
375 if (tb[TCA_GATE_BASE_TIME])
376 basetime = nla_get_u64(tb[TCA_GATE_BASE_TIME]);
377
378 if (tb[TCA_GATE_FLAGS])
379 gflags = nla_get_u32(tb[TCA_GATE_FLAGS]);
380
338
339 if (tb[TCA_GATE_PRIORITY])
340 prio = nla_get_s32(tb[TCA_GATE_PRIORITY]);
341
342 if (tb[TCA_GATE_BASE_TIME])
343 basetime = nla_get_u64(tb[TCA_GATE_BASE_TIME]);
344
345 if (tb[TCA_GATE_FLAGS])
346 gflags = nla_get_u32(tb[TCA_GATE_FLAGS]);
347
381 gact = to_gate(*a);
382 if (ret == ACT_P_CREATED)
383 INIT_LIST_HEAD(&gact->param.entries);
348 if (tb[TCA_GATE_CLOCKID]) {
349 clockid = nla_get_s32(tb[TCA_GATE_CLOCKID]);
350 switch (clockid) {
351 case CLOCK_REALTIME:
352 tk_offset = TK_OFFS_REAL;
353 break;
354 case CLOCK_MONOTONIC:
355 tk_offset = TK_OFFS_MAX;
356 break;
357 case CLOCK_BOOTTIME:
358 tk_offset = TK_OFFS_BOOT;
359 break;
360 case CLOCK_TAI:
361 tk_offset = TK_OFFS_TAI;
362 break;
363 default:
364 NL_SET_ERR_MSG(extack, "Invalid 'clockid'");
365 goto release_idr;
366 }
367 }
384
385 err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
386 if (err < 0)
387 goto release_idr;
388
368
369 err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
370 if (err < 0)
371 goto release_idr;
372
373 gact = to_gate(*a);
374
389 spin_lock_bh(&gact->tcf_lock);
390 p = &gact->param;
391
375 spin_lock_bh(&gact->tcf_lock);
376 p = &gact->param;
377
392 if (tb[TCA_GATE_CYCLE_TIME])
393 cycletime = nla_get_u64(tb[TCA_GATE_CYCLE_TIME]);
378 if (tb[TCA_GATE_CYCLE_TIME]) {
379 p->tcfg_cycletime = nla_get_u64(tb[TCA_GATE_CYCLE_TIME]);
380 if (!p->tcfg_cycletime_ext)
381 goto chain_put;
382 }
394
395 if (tb[TCA_GATE_ENTRY_LIST]) {
396 err = parse_gate_list(tb[TCA_GATE_ENTRY_LIST], p, extack);
397 if (err < 0)
398 goto chain_put;
399 }
400
383
384 if (tb[TCA_GATE_ENTRY_LIST]) {
385 err = parse_gate_list(tb[TCA_GATE_ENTRY_LIST], p, extack);
386 if (err < 0)
387 goto chain_put;
388 }
389
401 if (!cycletime) {
390 if (!p->tcfg_cycletime) {
402 struct tcfg_gate_entry *entry;
403 ktime_t cycle = 0;
404
405 list_for_each_entry(entry, &p->entries, list)
406 cycle = ktime_add_ns(cycle, entry->interval);
391 struct tcfg_gate_entry *entry;
392 ktime_t cycle = 0;
393
394 list_for_each_entry(entry, &p->entries, list)
395 cycle = ktime_add_ns(cycle, entry->interval);
407 cycletime = cycle;
408 if (!cycletime) {
409 err = -EINVAL;
410 goto chain_put;
411 }
396 p->tcfg_cycletime = cycle;
412 }
397 }
413 p->tcfg_cycletime = cycletime;
414
415 if (tb[TCA_GATE_CYCLE_TIME_EXT])
416 p->tcfg_cycletime_ext =
417 nla_get_u64(tb[TCA_GATE_CYCLE_TIME_EXT]);
418
398
399 if (tb[TCA_GATE_CYCLE_TIME_EXT])
400 p->tcfg_cycletime_ext =
401 nla_get_u64(tb[TCA_GATE_CYCLE_TIME_EXT]);
402
419 gate_setup_timer(gact, basetime, tk_offset, clockid,
420 ret == ACT_P_CREATED);
421 p->tcfg_priority = prio;
403 p->tcfg_priority = prio;
404 p->tcfg_basetime = basetime;
405 p->tcfg_clockid = clockid;
422 p->tcfg_flags = gflags;
406 p->tcfg_flags = gflags;
423 gate_get_start_time(gact, &start);
424
407
408 gact->tk_offset = tk_offset;
409 hrtimer_init(&gact->hitimer, clockid, HRTIMER_MODE_ABS_SOFT);
410 gact->hitimer.function = gate_timer_func;
411
412 err = gate_get_start_time(gact, &start);
413 if (err < 0) {
414 NL_SET_ERR_MSG(extack,
415 "Internal error: failed get start time");
416 release_entry_list(&p->entries);
417 goto chain_put;
418 }
419
425 gact->current_close_time = start;
426 gact->current_gate_status = GATE_ACT_GATE_OPEN | GATE_ACT_PENDING;
427
428 gact->next_entry = list_first_entry(&p->entries,
429 struct tcfg_gate_entry, list);
430
431 goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
432

--- 10 unchanged lines hidden (view full) ---

443 return ret;
444
445chain_put:
446 spin_unlock_bh(&gact->tcf_lock);
447
448 if (goto_ch)
449 tcf_chain_put_by_act(goto_ch);
450release_idr:
420 gact->current_close_time = start;
421 gact->current_gate_status = GATE_ACT_GATE_OPEN | GATE_ACT_PENDING;
422
423 gact->next_entry = list_first_entry(&p->entries,
424 struct tcfg_gate_entry, list);
425
426 goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch);
427

--- 10 unchanged lines hidden (view full) ---

438 return ret;
439
440chain_put:
441 spin_unlock_bh(&gact->tcf_lock);
442
443 if (goto_ch)
444 tcf_chain_put_by_act(goto_ch);
445release_idr:
451 /* action is not inserted in any list: it's safe to init hitimer
452 * without taking tcf_lock.
453 */
454 if (ret == ACT_P_CREATED)
455 gate_setup_timer(gact, gact->param.tcfg_basetime,
456 gact->tk_offset, gact->param.tcfg_clockid,
457 true);
458 tcf_idr_release(*a, bind);
459 return err;
460}
461
462static void tcf_gate_cleanup(struct tc_action *a)
463{
464 struct tcf_gate *gact = to_gate(a);
465 struct tcf_gate_params *p;
466
467 p = &gact->param;
446 tcf_idr_release(*a, bind);
447 return err;
448}
449
450static void tcf_gate_cleanup(struct tc_action *a)
451{
452 struct tcf_gate *gact = to_gate(a);
453 struct tcf_gate_params *p;
454
455 p = &gact->param;
468 hrtimer_cancel(&gact->hitimer);
456 if (p->tcfg_clockid != -1)
457 hrtimer_cancel(&gact->hitimer);
458
469 release_entry_list(&p->entries);
470}
471
472static int dumping_entry(struct sk_buff *skb,
473 struct tcfg_gate_entry *entry)
474{
475 struct nlattr *item;
476

--- 96 unchanged lines hidden (view full) ---

573 const struct tc_action_ops *ops,
574 struct netlink_ext_ack *extack)
575{
576 struct tc_action_net *tn = net_generic(net, gate_net_id);
577
578 return tcf_generic_walker(tn, skb, cb, type, ops, extack);
579}
580
459 release_entry_list(&p->entries);
460}
461
462static int dumping_entry(struct sk_buff *skb,
463 struct tcfg_gate_entry *entry)
464{
465 struct nlattr *item;
466

--- 96 unchanged lines hidden (view full) ---

563 const struct tc_action_ops *ops,
564 struct netlink_ext_ack *extack)
565{
566 struct tc_action_net *tn = net_generic(net, gate_net_id);
567
568 return tcf_generic_walker(tn, skb, cb, type, ops, extack);
569}
570
581static void tcf_gate_stats_update(struct tc_action *a, u64 bytes, u32 packets,
582 u64 lastuse, bool hw)
571static void tcf_gate_stats_update(struct tc_action *a, u64 bytes, u64 packets,
572 u64 drops, u64 lastuse, bool hw)
583{
584 struct tcf_gate *gact = to_gate(a);
585 struct tcf_t *tm = &gact->tcf_tm;
586
573{
574 struct tcf_gate *gact = to_gate(a);
575 struct tcf_t *tm = &gact->tcf_tm;
576
587 tcf_action_update_stats(a, bytes, packets, false, hw);
577 tcf_action_update_stats(a, bytes, packets, drops, hw);
588 tm->lastuse = max_t(u64, tm->lastuse, lastuse);
589}
590
591static int tcf_gate_search(struct net *net, struct tc_action **a, u32 index)
592{
593 struct tc_action_net *tn = net_generic(net, gate_net_id);
594
595 return tcf_idr_search(tn, a, index);

--- 54 unchanged lines hidden ---
578 tm->lastuse = max_t(u64, tm->lastuse, lastuse);
579}
580
581static int tcf_gate_search(struct net *net, struct tc_action **a, u32 index)
582{
583 struct tc_action_net *tn = net_generic(net, gate_net_id);
584
585 return tcf_idr_search(tn, a, index);

--- 54 unchanged lines hidden ---