diff options
Diffstat (limited to 'net/sched/sch_fq.c')
-rw-r--r-- | net/sched/sch_fq.c | 102 |
1 files changed, 62 insertions, 40 deletions
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index 32ad015ee8ce..a9dfdda9ed1d 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c | |||
@@ -285,7 +285,7 @@ static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q) | |||
285 | 285 | ||
286 | 286 | ||
287 | /* remove one skb from head of flow queue */ | 287 | /* remove one skb from head of flow queue */ |
288 | static struct sk_buff *fq_dequeue_head(struct fq_flow *flow) | 288 | static struct sk_buff *fq_dequeue_head(struct Qdisc *sch, struct fq_flow *flow) |
289 | { | 289 | { |
290 | struct sk_buff *skb = flow->head; | 290 | struct sk_buff *skb = flow->head; |
291 | 291 | ||
@@ -293,6 +293,8 @@ static struct sk_buff *fq_dequeue_head(struct fq_flow *flow) | |||
293 | flow->head = skb->next; | 293 | flow->head = skb->next; |
294 | skb->next = NULL; | 294 | skb->next = NULL; |
295 | flow->qlen--; | 295 | flow->qlen--; |
296 | sch->qstats.backlog -= qdisc_pkt_len(skb); | ||
297 | sch->q.qlen--; | ||
296 | } | 298 | } |
297 | return skb; | 299 | return skb; |
298 | } | 300 | } |
@@ -418,8 +420,9 @@ static struct sk_buff *fq_dequeue(struct Qdisc *sch) | |||
418 | struct fq_flow_head *head; | 420 | struct fq_flow_head *head; |
419 | struct sk_buff *skb; | 421 | struct sk_buff *skb; |
420 | struct fq_flow *f; | 422 | struct fq_flow *f; |
423 | u32 rate; | ||
421 | 424 | ||
422 | skb = fq_dequeue_head(&q->internal); | 425 | skb = fq_dequeue_head(sch, &q->internal); |
423 | if (skb) | 426 | if (skb) |
424 | goto out; | 427 | goto out; |
425 | fq_check_throttled(q, now); | 428 | fq_check_throttled(q, now); |
@@ -449,7 +452,7 @@ begin: | |||
449 | goto begin; | 452 | goto begin; |
450 | } | 453 | } |
451 | 454 | ||
452 | skb = fq_dequeue_head(f); | 455 | skb = fq_dequeue_head(sch, f); |
453 | if (!skb) { | 456 | if (!skb) { |
454 | head->first = f->next; | 457 | head->first = f->next; |
455 | /* force a pass through old_flows to prevent starvation */ | 458 | /* force a pass through old_flows to prevent starvation */ |
@@ -466,43 +469,70 @@ begin: | |||
466 | f->time_next_packet = now; | 469 | f->time_next_packet = now; |
467 | f->credit -= qdisc_pkt_len(skb); | 470 | f->credit -= qdisc_pkt_len(skb); |
468 | 471 | ||
469 | if (f->credit <= 0 && | 472 | if (f->credit > 0 || !q->rate_enable) |
470 | q->rate_enable && | 473 | goto out; |
471 | skb->sk && skb->sk->sk_state != TCP_TIME_WAIT) { | ||
472 | u32 rate = skb->sk->sk_pacing_rate ?: q->flow_default_rate; | ||
473 | 474 | ||
474 | rate = min(rate, q->flow_max_rate); | 475 | rate = q->flow_max_rate; |
475 | if (rate) { | 476 | if (skb->sk && skb->sk->sk_state != TCP_TIME_WAIT) |
476 | u64 len = (u64)qdisc_pkt_len(skb) * NSEC_PER_SEC; | 477 | rate = min(skb->sk->sk_pacing_rate, rate); |
477 | 478 | ||
478 | do_div(len, rate); | 479 | if (rate != ~0U) { |
479 | /* Since socket rate can change later, | 480 | u32 plen = max(qdisc_pkt_len(skb), q->quantum); |
480 | * clamp the delay to 125 ms. | 481 | u64 len = (u64)plen * NSEC_PER_SEC; |
481 | * TODO: maybe segment the too big skb, as in commit | ||
482 | * e43ac79a4bc ("sch_tbf: segment too big GSO packets") | ||
483 | */ | ||
484 | if (unlikely(len > 125 * NSEC_PER_MSEC)) { | ||
485 | len = 125 * NSEC_PER_MSEC; | ||
486 | q->stat_pkts_too_long++; | ||
487 | } | ||
488 | 482 | ||
489 | f->time_next_packet = now + len; | 483 | if (likely(rate)) |
484 | do_div(len, rate); | ||
485 | /* Since socket rate can change later, | ||
486 | * clamp the delay to 125 ms. | ||
487 | * TODO: maybe segment the too big skb, as in commit | ||
488 | * e43ac79a4bc ("sch_tbf: segment too big GSO packets") | ||
489 | */ | ||
490 | if (unlikely(len > 125 * NSEC_PER_MSEC)) { | ||
491 | len = 125 * NSEC_PER_MSEC; | ||
492 | q->stat_pkts_too_long++; | ||
490 | } | 493 | } |
494 | |||
495 | f->time_next_packet = now + len; | ||
491 | } | 496 | } |
492 | out: | 497 | out: |
493 | sch->qstats.backlog -= qdisc_pkt_len(skb); | ||
494 | qdisc_bstats_update(sch, skb); | 498 | qdisc_bstats_update(sch, skb); |
495 | sch->q.qlen--; | ||
496 | qdisc_unthrottled(sch); | 499 | qdisc_unthrottled(sch); |
497 | return skb; | 500 | return skb; |
498 | } | 501 | } |
499 | 502 | ||
500 | static void fq_reset(struct Qdisc *sch) | 503 | static void fq_reset(struct Qdisc *sch) |
501 | { | 504 | { |
505 | struct fq_sched_data *q = qdisc_priv(sch); | ||
506 | struct rb_root *root; | ||
502 | struct sk_buff *skb; | 507 | struct sk_buff *skb; |
508 | struct rb_node *p; | ||
509 | struct fq_flow *f; | ||
510 | unsigned int idx; | ||
503 | 511 | ||
504 | while ((skb = fq_dequeue(sch)) != NULL) | 512 | while ((skb = fq_dequeue_head(sch, &q->internal)) != NULL) |
505 | kfree_skb(skb); | 513 | kfree_skb(skb); |
514 | |||
515 | if (!q->fq_root) | ||
516 | return; | ||
517 | |||
518 | for (idx = 0; idx < (1U << q->fq_trees_log); idx++) { | ||
519 | root = &q->fq_root[idx]; | ||
520 | while ((p = rb_first(root)) != NULL) { | ||
521 | f = container_of(p, struct fq_flow, fq_node); | ||
522 | rb_erase(p, root); | ||
523 | |||
524 | while ((skb = fq_dequeue_head(sch, f)) != NULL) | ||
525 | kfree_skb(skb); | ||
526 | |||
527 | kmem_cache_free(fq_flow_cachep, f); | ||
528 | } | ||
529 | } | ||
530 | q->new_flows.first = NULL; | ||
531 | q->old_flows.first = NULL; | ||
532 | q->delayed = RB_ROOT; | ||
533 | q->flows = 0; | ||
534 | q->inactive_flows = 0; | ||
535 | q->throttled_flows = 0; | ||
506 | } | 536 | } |
507 | 537 | ||
508 | static void fq_rehash(struct fq_sched_data *q, | 538 | static void fq_rehash(struct fq_sched_data *q, |
@@ -622,7 +652,7 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt) | |||
622 | q->quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]); | 652 | q->quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]); |
623 | 653 | ||
624 | if (tb[TCA_FQ_INITIAL_QUANTUM]) | 654 | if (tb[TCA_FQ_INITIAL_QUANTUM]) |
625 | q->quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]); | 655 | q->initial_quantum = nla_get_u32(tb[TCA_FQ_INITIAL_QUANTUM]); |
626 | 656 | ||
627 | if (tb[TCA_FQ_FLOW_DEFAULT_RATE]) | 657 | if (tb[TCA_FQ_FLOW_DEFAULT_RATE]) |
628 | q->flow_default_rate = nla_get_u32(tb[TCA_FQ_FLOW_DEFAULT_RATE]); | 658 | q->flow_default_rate = nla_get_u32(tb[TCA_FQ_FLOW_DEFAULT_RATE]); |
@@ -645,6 +675,8 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt) | |||
645 | while (sch->q.qlen > sch->limit) { | 675 | while (sch->q.qlen > sch->limit) { |
646 | struct sk_buff *skb = fq_dequeue(sch); | 676 | struct sk_buff *skb = fq_dequeue(sch); |
647 | 677 | ||
678 | if (!skb) | ||
679 | break; | ||
648 | kfree_skb(skb); | 680 | kfree_skb(skb); |
649 | drop_count++; | 681 | drop_count++; |
650 | } | 682 | } |
@@ -657,21 +689,9 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt) | |||
657 | static void fq_destroy(struct Qdisc *sch) | 689 | static void fq_destroy(struct Qdisc *sch) |
658 | { | 690 | { |
659 | struct fq_sched_data *q = qdisc_priv(sch); | 691 | struct fq_sched_data *q = qdisc_priv(sch); |
660 | struct rb_root *root; | ||
661 | struct rb_node *p; | ||
662 | unsigned int idx; | ||
663 | 692 | ||
664 | if (q->fq_root) { | 693 | fq_reset(sch); |
665 | for (idx = 0; idx < (1U << q->fq_trees_log); idx++) { | 694 | kfree(q->fq_root); |
666 | root = &q->fq_root[idx]; | ||
667 | while ((p = rb_first(root)) != NULL) { | ||
668 | rb_erase(p, root); | ||
669 | kmem_cache_free(fq_flow_cachep, | ||
670 | container_of(p, struct fq_flow, fq_node)); | ||
671 | } | ||
672 | } | ||
673 | kfree(q->fq_root); | ||
674 | } | ||
675 | qdisc_watchdog_cancel(&q->watchdog); | 695 | qdisc_watchdog_cancel(&q->watchdog); |
676 | } | 696 | } |
677 | 697 | ||
@@ -711,12 +731,14 @@ static int fq_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
711 | if (opts == NULL) | 731 | if (opts == NULL) |
712 | goto nla_put_failure; | 732 | goto nla_put_failure; |
713 | 733 | ||
734 | /* TCA_FQ_FLOW_DEFAULT_RATE is not used anymore, | ||
735 | * do not bother giving its value | ||
736 | */ | ||
714 | if (nla_put_u32(skb, TCA_FQ_PLIMIT, sch->limit) || | 737 | if (nla_put_u32(skb, TCA_FQ_PLIMIT, sch->limit) || |
715 | nla_put_u32(skb, TCA_FQ_FLOW_PLIMIT, q->flow_plimit) || | 738 | nla_put_u32(skb, TCA_FQ_FLOW_PLIMIT, q->flow_plimit) || |
716 | nla_put_u32(skb, TCA_FQ_QUANTUM, q->quantum) || | 739 | nla_put_u32(skb, TCA_FQ_QUANTUM, q->quantum) || |
717 | nla_put_u32(skb, TCA_FQ_INITIAL_QUANTUM, q->initial_quantum) || | 740 | nla_put_u32(skb, TCA_FQ_INITIAL_QUANTUM, q->initial_quantum) || |
718 | nla_put_u32(skb, TCA_FQ_RATE_ENABLE, q->rate_enable) || | 741 | nla_put_u32(skb, TCA_FQ_RATE_ENABLE, q->rate_enable) || |
719 | nla_put_u32(skb, TCA_FQ_FLOW_DEFAULT_RATE, q->flow_default_rate) || | ||
720 | nla_put_u32(skb, TCA_FQ_FLOW_MAX_RATE, q->flow_max_rate) || | 742 | nla_put_u32(skb, TCA_FQ_FLOW_MAX_RATE, q->flow_max_rate) || |
721 | nla_put_u32(skb, TCA_FQ_BUCKETS_LOG, q->fq_trees_log)) | 743 | nla_put_u32(skb, TCA_FQ_BUCKETS_LOG, q->fq_trees_log)) |
722 | goto nla_put_failure; | 744 | goto nla_put_failure; |