* Hook's token buckets refillment. */
| 581 | * Hook's token buckets refillment. |
| 582 | */ |
| 583 | static void |
| 584 | ng_car_refillhook(struct hookinfo *h) |
| 585 | { |
| 586 | struct bintime newt, deltat; |
| 587 | unsigned int deltat_us; |
| 588 | |
| 589 | /* Get current time. */ |
| 590 | getbinuptime(&newt); |
| 591 | |
| 592 | /* Get time delta since last refill. */ |
| 593 | deltat = newt; |
| 594 | bintime_sub(&deltat, &h->lastRefill); |
| 595 | |
| 596 | /* Time must go forward. */ |
| 597 | if (deltat.sec < 0) { |
| 598 | h->lastRefill = newt; |
| 599 | return; |
| 600 | } |
| 601 | |
| 602 | /* But not too far forward. */ |
| 603 | if (deltat.sec >= 1000) { |
| 604 | deltat_us = (1000 << 20); |
| 605 | } else { |
| 606 | /* convert bintime to the 1/(2^20) of sec */ |
| 607 | deltat_us = (deltat.sec << 20) + (deltat.frac >> 44); |
| 608 | } |
| 609 | |
| 610 | if (h->conf.mode == NG_CAR_SINGLE_RATE) { |
| 611 | int64_t delta; |
| 612 | /* Refill committed token bucket. */ |
| 613 | h->tc += (h->conf.cir * deltat_us) >> 23; |
| 614 | delta = h->tc - h->conf.cbs; |
| 615 | if (delta > 0) { |
| 616 | h->tc = h->conf.cbs; |
| 617 | |
| 618 | /* Refill exceeded token bucket. */ |
| 619 | h->te += delta; |
| 620 | if (h->te > ((int64_t)h->conf.ebs)) |
| 621 | h->te = h->conf.ebs; |
| 622 | } |
| 623 | |
| 624 | } else if (h->conf.mode == NG_CAR_DOUBLE_RATE) { |
| 625 | /* Refill committed token bucket. */ |
| 626 | h->tc += (h->conf.cir * deltat_us) >> 23; |
| 627 | if (h->tc > ((int64_t)h->conf.cbs)) |
| 628 | h->tc = h->conf.cbs; |
| 629 | |
| 630 | /* Refill peak token bucket. */ |
| 631 | h->te += (h->conf.pir * deltat_us) >> 23; |
| 632 | if (h->te > ((int64_t)h->conf.ebs)) |
| 633 | h->te = h->conf.ebs; |
| 634 | |
| 635 | } else { /* RED or SHAPE mode. */ |
| 636 | /* Refill committed token bucket. */ |
| 637 | h->tc += (h->conf.cir * deltat_us) >> 23; |
| 638 | if (h->tc > ((int64_t)h->conf.cbs)) |
| 639 | h->tc = h->conf.cbs; |
| 640 | } |
no test coverage detected