diff options
| -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); |
