diff options
Diffstat (limited to 'net/sched/sch_fq.c')
-rw-r--r-- | net/sched/sch_fq.c | 45 |
1 files changed, 26 insertions, 19 deletions
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index fc6de56a331e..a2fef8b10b96 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c | |||
@@ -420,6 +420,7 @@ static struct sk_buff *fq_dequeue(struct Qdisc *sch) | |||
420 | struct fq_flow_head *head; | 420 | struct fq_flow_head *head; |
421 | struct sk_buff *skb; | 421 | struct sk_buff *skb; |
422 | struct fq_flow *f; | 422 | struct fq_flow *f; |
423 | u32 rate; | ||
423 | 424 | ||
424 | skb = fq_dequeue_head(sch, &q->internal); | 425 | skb = fq_dequeue_head(sch, &q->internal); |
425 | if (skb) | 426 | if (skb) |
@@ -468,28 +469,34 @@ begin: | |||
468 | f->time_next_packet = now; | 469 | f->time_next_packet = now; |
469 | f->credit -= qdisc_pkt_len(skb); | 470 | f->credit -= qdisc_pkt_len(skb); |
470 | 471 | ||
471 | if (f->credit <= 0 && | 472 | if (f->credit > 0 || !q->rate_enable) |
472 | q->rate_enable && | 473 | goto out; |
473 | skb->sk && skb->sk->sk_state != TCP_TIME_WAIT) { | ||
474 | u32 rate = skb->sk->sk_pacing_rate ?: q->flow_default_rate; | ||
475 | 474 | ||
476 | rate = min(rate, q->flow_max_rate); | 475 | if (skb->sk && skb->sk->sk_state != TCP_TIME_WAIT) { |
477 | if (rate) { | 476 | rate = skb->sk->sk_pacing_rate ?: q->flow_default_rate; |
478 | u64 len = (u64)qdisc_pkt_len(skb) * NSEC_PER_SEC; | ||
479 | |||
480 | do_div(len, rate); | ||
481 | /* Since socket rate can change later, | ||
482 | * clamp the delay to 125 ms. | ||
483 | * TODO: maybe segment the too big skb, as in commit | ||
484 | * e43ac79a4bc ("sch_tbf: segment too big GSO packets") | ||
485 | */ | ||
486 | if (unlikely(len > 125 * NSEC_PER_MSEC)) { | ||
487 | len = 125 * NSEC_PER_MSEC; | ||
488 | q->stat_pkts_too_long++; | ||
489 | } | ||
490 | 477 | ||
491 | f->time_next_packet = now + len; | 478 | rate = min(rate, q->flow_max_rate); |
479 | } else { | ||
480 | rate = q->flow_max_rate; | ||
481 | if (rate == ~0U) | ||
482 | goto out; | ||
483 | } | ||
484 | if (rate) { | ||
485 | u32 plen = max(qdisc_pkt_len(skb), q->quantum); | ||
486 | u64 len = (u64)plen * NSEC_PER_SEC; | ||
487 | |||
488 | do_div(len, rate); | ||
489 | /* Since socket rate can change later, | ||
490 | * clamp the delay to 125 ms. | ||
491 | * TODO: maybe segment the too big skb, as in commit | ||
492 | * e43ac79a4bc ("sch_tbf: segment too big GSO packets") | ||
493 | */ | ||
494 | if (unlikely(len > 125 * NSEC_PER_MSEC)) { | ||
495 | len = 125 * NSEC_PER_MSEC; | ||
496 | q->stat_pkts_too_long++; | ||
492 | } | 497 | } |
498 | |||
499 | f->time_next_packet = now + len; | ||
493 | } | 500 | } |
494 | out: | 501 | out: |
495 | qdisc_bstats_update(sch, skb); | 502 | qdisc_bstats_update(sch, skb); |