Lines Matching +full:te +full:- +full:source
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
9 * Redistribution and use in source and binary forms, with or without
12 * 1. Redistributions of source code must retain the above copyright
32 * ng_car - An implementation of committed access rate for netgraph
35 * - Sanitize input config values (impose some limits)
36 * - Implement DSCP marking for IPv4
37 * - Decouple functionality into a simple classifier (g/y/r)
65 hook_p hook; /* this (source) hook */
69 int64_t te; /* exceeded/peak token bucket counter */ member
201 priv->node = node; in ng_car_constructor()
207 priv->upper.hook = NULL; in ng_car_constructor()
208 priv->upper.dest = NULL; in ng_car_constructor()
209 priv->upper.tc = priv->upper.conf.cbs = NG_CAR_CBS_MIN; in ng_car_constructor()
210 priv->upper.te = priv->upper.conf.ebs = NG_CAR_EBS_MIN; in ng_car_constructor()
211 priv->upper.conf.cir = NG_CAR_CIR_DFLT; in ng_car_constructor()
212 priv->upper.conf.green_action = NG_CAR_ACTION_FORWARD; in ng_car_constructor()
213 priv->upper.conf.yellow_action = NG_CAR_ACTION_FORWARD; in ng_car_constructor()
214 priv->upper.conf.red_action = NG_CAR_ACTION_DROP; in ng_car_constructor()
215 priv->upper.conf.mode = 0; in ng_car_constructor()
216 getbinuptime(&priv->upper.lastRefill); in ng_car_constructor()
217 priv->upper.q_first = 0; in ng_car_constructor()
218 priv->upper.q_last = 0; in ng_car_constructor()
219 ng_callout_init(&priv->upper.q_callout); in ng_car_constructor()
220 mtx_init(&priv->upper.q_mtx, "ng_car_u", NULL, MTX_DEF); in ng_car_constructor()
222 priv->lower.hook = NULL; in ng_car_constructor()
223 priv->lower.dest = NULL; in ng_car_constructor()
224 priv->lower.tc = priv->lower.conf.cbs = NG_CAR_CBS_MIN; in ng_car_constructor()
225 priv->lower.te = priv->lower.conf.ebs = NG_CAR_EBS_MIN; in ng_car_constructor()
226 priv->lower.conf.cir = NG_CAR_CIR_DFLT; in ng_car_constructor()
227 priv->lower.conf.green_action = NG_CAR_ACTION_FORWARD; in ng_car_constructor()
228 priv->lower.conf.yellow_action = NG_CAR_ACTION_FORWARD; in ng_car_constructor()
229 priv->lower.conf.red_action = NG_CAR_ACTION_DROP; in ng_car_constructor()
230 priv->lower.conf.mode = 0; in ng_car_constructor()
231 priv->lower.lastRefill = priv->upper.lastRefill; in ng_car_constructor()
232 priv->lower.q_first = 0; in ng_car_constructor()
233 priv->lower.q_last = 0; in ng_car_constructor()
234 ng_callout_init(&priv->lower.q_callout); in ng_car_constructor()
235 mtx_init(&priv->lower.q_mtx, "ng_car_l", NULL, MTX_DEF); in ng_car_constructor()
249 priv->lower.hook = hook; in ng_car_newhook()
250 priv->upper.dest = hook; in ng_car_newhook()
251 bzero(&priv->lower.stats, sizeof(priv->lower.stats)); in ng_car_newhook()
252 NG_HOOK_SET_PRIVATE(hook, &priv->lower); in ng_car_newhook()
254 priv->upper.hook = hook; in ng_car_newhook()
255 priv->lower.dest = hook; in ng_car_newhook()
256 bzero(&priv->upper.stats, sizeof(priv->upper.stats)); in ng_car_newhook()
257 NG_HOOK_SET_PRIVATE(hook, &priv->upper); in ng_car_newhook()
277 if (hinfo->q_first != hinfo->q_last) { in ng_car_rcvdata()
296 m_tag_prepend(m, &colp->tag); \ in ng_car_rcvdata()
299 colp->color = col; \ in ng_car_rcvdata()
305 ++hinfo->stats.dropped_pkts; \ in ng_car_rcvdata()
311 if (hinfo->conf.opt & NG_CAR_COUNT_PACKETS) { in ng_car_rcvdata()
314 len = m->m_pkthdr.len; in ng_car_rcvdata()
319 if ((hinfo->conf.opt & NG_CAR_COLOR_AWARE) && (colp != NULL)) in ng_car_rcvdata()
320 col = colp->color; in ng_car_rcvdata()
325 if (hinfo->tc - len >= 0 && col <= QOS_COLOR_GREEN) { in ng_car_rcvdata()
327 ++hinfo->stats.green_pkts; in ng_car_rcvdata()
328 hinfo->tc -= len; in ng_car_rcvdata()
330 hinfo->conf.green_action, in ng_car_rcvdata()
337 if (hinfo->tc - len >= 0 && col <= QOS_COLOR_GREEN) { in ng_car_rcvdata()
339 ++hinfo->stats.green_pkts; in ng_car_rcvdata()
340 hinfo->tc -= len; in ng_car_rcvdata()
342 hinfo->conf.green_action, in ng_car_rcvdata()
346 } else if (hinfo->conf.mode == NG_CAR_SHAPE) { in ng_car_rcvdata()
351 } else if (hinfo->conf.mode == NG_CAR_RED) { in ng_car_rcvdata()
353 if (len - (hinfo->tc - len) > hinfo->conf.ebs || in ng_car_rcvdata()
356 ++hinfo->stats.red_pkts; in ng_car_rcvdata()
357 hinfo->te = 0; in ng_car_rcvdata()
359 hinfo->conf.red_action, in ng_car_rcvdata()
362 /* Use token bucket to simulate RED-like drop in ng_car_rcvdata()
364 } else if (hinfo->te + (len - hinfo->tc) < hinfo->conf.ebs && in ng_car_rcvdata()
367 ++hinfo->stats.yellow_pkts; in ng_car_rcvdata()
368 hinfo->te += len - hinfo->tc; in ng_car_rcvdata()
370 hinfo->tc -= len; in ng_car_rcvdata()
372 hinfo->conf.yellow_action, in ng_car_rcvdata()
376 ++hinfo->stats.red_pkts; in ng_car_rcvdata()
377 hinfo->te = 0; in ng_car_rcvdata()
379 hinfo->conf.red_action, in ng_car_rcvdata()
385 if (hinfo->te - len >= 0 && col <= QOS_COLOR_YELLOW) { in ng_car_rcvdata()
387 ++hinfo->stats.yellow_pkts; in ng_car_rcvdata()
388 hinfo->te -= len; in ng_car_rcvdata()
390 hinfo->conf.yellow_action, in ng_car_rcvdata()
394 ++hinfo->stats.red_pkts; in ng_car_rcvdata()
396 hinfo->conf.red_action, in ng_car_rcvdata()
404 NG_FWD_ITEM_HOOK(error, item, hinfo->dest); in ng_car_rcvdata()
406 ++hinfo->stats.errors; in ng_car_rcvdata()
407 ++hinfo->stats.passed_pkts; in ng_car_rcvdata()
424 switch (msg->header.typecookie) { in ng_car_rcvmsg()
426 switch (msg->header.cmd) { in ng_car_rcvmsg()
438 bstats = (struct ng_car_bulkstats *)resp->data; in ng_car_rcvmsg()
440 bcopy(&priv->upper.stats, &bstats->downstream, in ng_car_rcvmsg()
441 sizeof(bstats->downstream)); in ng_car_rcvmsg()
442 bcopy(&priv->lower.stats, &bstats->upstream, in ng_car_rcvmsg()
443 sizeof(bstats->upstream)); in ng_car_rcvmsg()
445 if (msg->header.cmd == NGM_CAR_GET_STATS) in ng_car_rcvmsg()
448 bzero(&priv->upper.stats, in ng_car_rcvmsg()
449 sizeof(priv->upper.stats)); in ng_car_rcvmsg()
450 bzero(&priv->lower.stats, in ng_car_rcvmsg()
451 sizeof(priv->lower.stats)); in ng_car_rcvmsg()
463 bconf = (struct ng_car_bulkconf *)resp->data; in ng_car_rcvmsg()
465 bcopy(&priv->upper.conf, &bconf->downstream, in ng_car_rcvmsg()
466 sizeof(bconf->downstream)); in ng_car_rcvmsg()
467 bcopy(&priv->lower.conf, &bconf->upstream, in ng_car_rcvmsg()
468 sizeof(bconf->upstream)); in ng_car_rcvmsg()
470 if (bconf->downstream.opt & NG_CAR_COUNT_PACKETS) { in ng_car_rcvmsg()
471 bconf->downstream.cir /= 1024; in ng_car_rcvmsg()
472 bconf->downstream.pir /= 1024; in ng_car_rcvmsg()
473 bconf->downstream.cbs /= 128; in ng_car_rcvmsg()
474 bconf->downstream.ebs /= 128; in ng_car_rcvmsg()
476 if (bconf->upstream.opt & NG_CAR_COUNT_PACKETS) { in ng_car_rcvmsg()
477 bconf->upstream.cir /= 1024; in ng_car_rcvmsg()
478 bconf->upstream.pir /= 1024; in ng_car_rcvmsg()
479 bconf->upstream.cbs /= 128; in ng_car_rcvmsg()
480 bconf->upstream.ebs /= 128; in ng_car_rcvmsg()
487 (struct ng_car_bulkconf *)msg->data; in ng_car_rcvmsg()
490 if (msg->header.arglen != sizeof(*bconf)) { in ng_car_rcvmsg()
495 if (bconf->downstream.opt & NG_CAR_COUNT_PACKETS) { in ng_car_rcvmsg()
496 bconf->downstream.cir *= 1024; in ng_car_rcvmsg()
497 bconf->downstream.pir *= 1024; in ng_car_rcvmsg()
498 bconf->downstream.cbs *= 128; in ng_car_rcvmsg()
499 bconf->downstream.ebs *= 128; in ng_car_rcvmsg()
501 if (bconf->upstream.opt & NG_CAR_COUNT_PACKETS) { in ng_car_rcvmsg()
502 bconf->upstream.cir *= 1024; in ng_car_rcvmsg()
503 bconf->upstream.pir *= 1024; in ng_car_rcvmsg()
504 bconf->upstream.cbs *= 128; in ng_car_rcvmsg()
505 bconf->upstream.ebs *= 128; in ng_car_rcvmsg()
507 if ((bconf->downstream.cir > 1000000000) || in ng_car_rcvmsg()
508 (bconf->downstream.pir > 1000000000) || in ng_car_rcvmsg()
509 (bconf->upstream.cir > 1000000000) || in ng_car_rcvmsg()
510 (bconf->upstream.pir > 1000000000) || in ng_car_rcvmsg()
511 (bconf->downstream.cbs == 0 && in ng_car_rcvmsg()
512 bconf->downstream.ebs == 0) || in ng_car_rcvmsg()
513 (bconf->upstream.cbs == 0 && in ng_car_rcvmsg()
514 bconf->upstream.ebs == 0)) in ng_car_rcvmsg()
519 if ((bconf->upstream.mode == NG_CAR_SHAPE) && in ng_car_rcvmsg()
520 (bconf->upstream.cir == 0)) { in ng_car_rcvmsg()
524 if ((bconf->downstream.mode == NG_CAR_SHAPE) && in ng_car_rcvmsg()
525 (bconf->downstream.cir == 0)) { in ng_car_rcvmsg()
531 bcopy(&bconf->downstream, &priv->upper.conf, in ng_car_rcvmsg()
532 sizeof(priv->upper.conf)); in ng_car_rcvmsg()
533 priv->upper.tc = priv->upper.conf.cbs; in ng_car_rcvmsg()
534 if (priv->upper.conf.mode == NG_CAR_RED || in ng_car_rcvmsg()
535 priv->upper.conf.mode == NG_CAR_SHAPE) { in ng_car_rcvmsg()
536 priv->upper.te = 0; in ng_car_rcvmsg()
538 priv->upper.te = priv->upper.conf.ebs; in ng_car_rcvmsg()
542 bcopy(&bconf->upstream, &priv->lower.conf, in ng_car_rcvmsg()
543 sizeof(priv->lower.conf)); in ng_car_rcvmsg()
544 priv->lower.tc = priv->lower.conf.cbs; in ng_car_rcvmsg()
545 if (priv->lower.conf.mode == NG_CAR_RED || in ng_car_rcvmsg()
546 priv->lower.conf.mode == NG_CAR_SHAPE) { in ng_car_rcvmsg()
547 priv->lower.te = 0; in ng_car_rcvmsg()
549 priv->lower.te = priv->lower.conf.ebs; in ng_car_rcvmsg()
575 ng_uncallout(&priv->upper.q_callout, node); in ng_car_shutdown()
576 ng_uncallout(&priv->lower.q_callout, node); in ng_car_shutdown()
577 mtx_destroy(&priv->upper.q_mtx); in ng_car_shutdown()
578 mtx_destroy(&priv->lower.q_mtx); in ng_car_shutdown()
579 NG_NODE_UNREF(priv->node); in ng_car_shutdown()
598 while (hinfo->q_first != hinfo->q_last) { in ng_car_disconnect()
599 NG_FREE_M(hinfo->q[hinfo->q_first]); in ng_car_disconnect()
600 hinfo->q_first++; in ng_car_disconnect()
601 if (hinfo->q_first >= NG_CAR_QUEUE_SIZE) in ng_car_disconnect()
602 hinfo->q_first = 0; in ng_car_disconnect()
605 if (hinfo->hook == priv->upper.hook) in ng_car_disconnect()
606 priv->lower.dest = NULL; in ng_car_disconnect()
608 priv->upper.dest = NULL; in ng_car_disconnect()
609 hinfo->hook = NULL; in ng_car_disconnect()
632 bintime_sub(&deltat, &h->lastRefill); in ng_car_refillhook()
636 h->lastRefill = newt; in ng_car_refillhook()
648 if (h->conf.mode == NG_CAR_SINGLE_RATE) { in ng_car_refillhook()
651 h->tc += (h->conf.cir * deltat_us) >> 23; in ng_car_refillhook()
652 delta = h->tc - h->conf.cbs; in ng_car_refillhook()
654 h->tc = h->conf.cbs; in ng_car_refillhook()
657 h->te += delta; in ng_car_refillhook()
658 if (h->te > ((int64_t)h->conf.ebs)) in ng_car_refillhook()
659 h->te = h->conf.ebs; in ng_car_refillhook()
662 } else if (h->conf.mode == NG_CAR_DOUBLE_RATE) { in ng_car_refillhook()
664 h->tc += (h->conf.cir * deltat_us) >> 23; in ng_car_refillhook()
665 if (h->tc > ((int64_t)h->conf.cbs)) in ng_car_refillhook()
666 h->tc = h->conf.cbs; in ng_car_refillhook()
669 h->te += (h->conf.pir * deltat_us) >> 23; in ng_car_refillhook()
670 if (h->te > ((int64_t)h->conf.ebs)) in ng_car_refillhook()
671 h->te = h->conf.ebs; in ng_car_refillhook()
675 h->tc += (h->conf.cir * deltat_us) >> 23; in ng_car_refillhook()
676 if (h->tc > ((int64_t)h->conf.cbs)) in ng_car_refillhook()
677 h->tc = h->conf.cbs; in ng_car_refillhook()
681 h->lastRefill = newt; in ng_car_refillhook()
692 delay = (-(hinfo->tc)) * hz * 8 / hinfo->conf.cir + 1; in ng_car_schedule()
694 ng_callout(&hinfo->q_callout, NG_HOOK_NODE(hinfo->hook), hinfo->hook, in ng_car_schedule()
712 while (hinfo->tc >= 0) { in ng_car_q_event()
714 m = hinfo->q[hinfo->q_first]; in ng_car_q_event()
715 NG_SEND_DATA_ONLY(error, hinfo->dest, m); in ng_car_q_event()
717 ++hinfo->stats.errors; in ng_car_q_event()
718 ++hinfo->stats.passed_pkts; in ng_car_q_event()
721 hinfo->q_first++; in ng_car_q_event()
722 if (hinfo->q_first >= NG_CAR_QUEUE_SIZE) in ng_car_q_event()
723 hinfo->q_first = 0; in ng_car_q_event()
726 if (hinfo->q_first == hinfo->q_last) in ng_car_q_event()
730 m = hinfo->q[hinfo->q_first]; in ng_car_q_event()
731 if (hinfo->conf.opt & NG_CAR_COUNT_PACKETS) { in ng_car_q_event()
732 hinfo->tc -= 128; in ng_car_q_event()
734 hinfo->tc -= m->m_pkthdr.len; in ng_car_q_event()
739 if (hinfo->q_first != hinfo->q_last) in ng_car_q_event()
760 if ((hinfo->conf.opt & NG_CAR_COLOR_AWARE) && (colp != NULL)) in ng_car_enqueue()
761 col = colp->color; in ng_car_enqueue()
766 mtx_lock(&hinfo->q_mtx); in ng_car_enqueue()
769 len = hinfo->q_last - hinfo->q_first; in ng_car_enqueue()
774 if ((len >= (NG_CAR_QUEUE_SIZE - 1)) || in ng_car_enqueue()
775 (hinfo->te + len >= NG_CAR_QUEUE_SIZE) || in ng_car_enqueue()
778 ++hinfo->stats.red_pkts; in ng_car_enqueue()
779 ++hinfo->stats.dropped_pkts; in ng_car_enqueue()
782 hinfo->te = 0; in ng_car_enqueue()
785 ++hinfo->stats.yellow_pkts; in ng_car_enqueue()
788 hinfo->q[hinfo->q_last] = m; in ng_car_enqueue()
789 hinfo->q_last++; in ng_car_enqueue()
790 if (hinfo->q_last >= NG_CAR_QUEUE_SIZE) in ng_car_enqueue()
791 hinfo->q_last = 0; in ng_car_enqueue()
795 hinfo->te += len - NG_CAR_QUEUE_MIN_TH; in ng_car_enqueue()
799 if (hinfo->conf.opt & NG_CAR_COUNT_PACKETS) { in ng_car_enqueue()
800 hinfo->tc -= 128; in ng_car_enqueue()
802 hinfo->tc -= m->m_pkthdr.len; in ng_car_enqueue()
811 mtx_unlock(&hinfo->q_mtx); in ng_car_enqueue()