aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/sch_fq.c
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2013-11-15 11:58:14 -0500
committerDavid S. Miller <davem@davemloft.net>2013-11-15 21:01:52 -0500
commitf52ed89971adbe79b6438c459814034707b8ab91 (patch)
tree87135c0dc32f5abc284e4298fc674ff7f03d0f16 /net/sched/sch_fq.c
parent65c5189a2b57b9aa1d89e4b79da39928257c9505 (diff)
pkt_sched: fq: fix pacing for small frames
For performance reasons, sch_fq tried hard to not setup timers for every sent packet, using a quantum based heuristic : A delay is setup only if the flow exhausted its credit. Problem is that application limited flows can refill their credit for every queued packet, and they can evade pacing. This problem can also be triggered when TCP flows use small MSS values, as TSO auto sizing builds packets that are smaller than the default fq quantum (3028 bytes) This patch adds a 40 ms delay to guard flow credit refill. Fixes: afe4fd062416 ("pkt_sched: fq: Fair Queue packet scheduler") Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Maciej Żenczykowski <maze@google.com> Cc: Willem de Bruijn <willemb@google.com> Cc: Yuchung Cheng <ycheng@google.com> Cc: Neal Cardwell <ncardwell@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sched/sch_fq.c')
-rw-r--r--net/sched/sch_fq.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index 26906ab51c52..95d843961907 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -88,6 +88,7 @@ struct fq_sched_data {
88 struct fq_flow internal; /* for non classified or high prio packets */ 88 struct fq_flow internal; /* for non classified or high prio packets */
89 u32 quantum; 89 u32 quantum;
90 u32 initial_quantum; 90 u32 initial_quantum;
91 u32 flow_refill_delay;
91 u32 flow_max_rate; /* optional max rate per flow */ 92 u32 flow_max_rate; /* optional max rate per flow */
92 u32 flow_plimit; /* max packets per flow */ 93 u32 flow_plimit; /* max packets per flow */
93 struct rb_root *fq_root; 94 struct rb_root *fq_root;
@@ -114,6 +115,7 @@ static struct fq_flow detached, throttled;
114static void fq_flow_set_detached(struct fq_flow *f) 115static void fq_flow_set_detached(struct fq_flow *f)
115{ 116{
116 f->next = &detached; 117 f->next = &detached;
118 f->age = jiffies;
117} 119}
118 120
119static bool fq_flow_is_detached(const struct fq_flow *f) 121static bool fq_flow_is_detached(const struct fq_flow *f)
@@ -366,17 +368,20 @@ static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
366 } 368 }
367 369
368 f->qlen++; 370 f->qlen++;
369 flow_queue_add(f, skb);
370 if (skb_is_retransmit(skb)) 371 if (skb_is_retransmit(skb))
371 q->stat_tcp_retrans++; 372 q->stat_tcp_retrans++;
372 sch->qstats.backlog += qdisc_pkt_len(skb); 373 sch->qstats.backlog += qdisc_pkt_len(skb);
373 if (fq_flow_is_detached(f)) { 374 if (fq_flow_is_detached(f)) {
374 fq_flow_add_tail(&q->new_flows, f); 375 fq_flow_add_tail(&q->new_flows, f);
375 if (q->quantum > f->credit) 376 if (time_after(jiffies, f->age + q->flow_refill_delay))
376 f->credit = q->quantum; 377 f->credit = max_t(u32, f->credit, q->quantum);
377 q->inactive_flows--; 378 q->inactive_flows--;
378 qdisc_unthrottled(sch); 379 qdisc_unthrottled(sch);
379 } 380 }
381
382 /* Note: this overwrites f->age */
383 flow_queue_add(f, skb);
384
380 if (unlikely(f == &q->internal)) { 385 if (unlikely(f == &q->internal)) {
381 q->stat_internal_packets++; 386 q->stat_internal_packets++;
382 qdisc_unthrottled(sch); 387 qdisc_unthrottled(sch);
@@ -454,7 +459,6 @@ begin:
454 fq_flow_add_tail(&q->old_flows, f); 459 fq_flow_add_tail(&q->old_flows, f);
455 } else { 460 } else {
456 fq_flow_set_detached(f); 461 fq_flow_set_detached(f);
457 f->age = jiffies;
458 q->inactive_flows++; 462 q->inactive_flows++;
459 } 463 }
460 goto begin; 464 goto begin;
@@ -608,6 +612,7 @@ static const struct nla_policy fq_policy[TCA_FQ_MAX + 1] = {
608 [TCA_FQ_FLOW_DEFAULT_RATE] = { .type = NLA_U32 }, 612 [TCA_FQ_FLOW_DEFAULT_RATE] = { .type = NLA_U32 },
609 [TCA_FQ_FLOW_MAX_RATE] = { .type = NLA_U32 }, 613 [TCA_FQ_FLOW_MAX_RATE] = { .type = NLA_U32 },
610 [TCA_FQ_BUCKETS_LOG] = { .type = NLA_U32 }, 614 [TCA_FQ_BUCKETS_LOG] = { .type = NLA_U32 },
615 [TCA_FQ_FLOW_REFILL_DELAY] = { .type = NLA_U32 },
611}; 616};
612 617
613static int fq_change(struct Qdisc *sch, struct nlattr *opt) 618static int fq_change(struct Qdisc *sch, struct nlattr *opt)
@@ -664,6 +669,12 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt)
664 err = -EINVAL; 669 err = -EINVAL;
665 } 670 }
666 671
672 if (tb[TCA_FQ_FLOW_REFILL_DELAY]) {
673 u32 usecs_delay = nla_get_u32(tb[TCA_FQ_FLOW_REFILL_DELAY]) ;
674
675 q->flow_refill_delay = usecs_to_jiffies(usecs_delay);
676 }
677
667 if (!err) 678 if (!err)
668 err = fq_resize(q, fq_log); 679 err = fq_resize(q, fq_log);
669 680
@@ -699,6 +710,7 @@ static int fq_init(struct Qdisc *sch, struct nlattr *opt)
699 q->flow_plimit = 100; 710 q->flow_plimit = 100;
700 q->quantum = 2 * psched_mtu(qdisc_dev(sch)); 711 q->quantum = 2 * psched_mtu(qdisc_dev(sch));
701 q->initial_quantum = 10 * psched_mtu(qdisc_dev(sch)); 712 q->initial_quantum = 10 * psched_mtu(qdisc_dev(sch));
713 q->flow_refill_delay = msecs_to_jiffies(40);
702 q->flow_max_rate = ~0U; 714 q->flow_max_rate = ~0U;
703 q->rate_enable = 1; 715 q->rate_enable = 1;
704 q->new_flows.first = NULL; 716 q->new_flows.first = NULL;
@@ -733,6 +745,8 @@ static int fq_dump(struct Qdisc *sch, struct sk_buff *skb)
733 nla_put_u32(skb, TCA_FQ_INITIAL_QUANTUM, q->initial_quantum) || 745 nla_put_u32(skb, TCA_FQ_INITIAL_QUANTUM, q->initial_quantum) ||
734 nla_put_u32(skb, TCA_FQ_RATE_ENABLE, q->rate_enable) || 746 nla_put_u32(skb, TCA_FQ_RATE_ENABLE, q->rate_enable) ||
735 nla_put_u32(skb, TCA_FQ_FLOW_MAX_RATE, q->flow_max_rate) || 747 nla_put_u32(skb, TCA_FQ_FLOW_MAX_RATE, q->flow_max_rate) ||
748 nla_put_u32(skb, TCA_FQ_FLOW_REFILL_DELAY,
749 jiffies_to_usecs(q->flow_refill_delay)) ||
736 nla_put_u32(skb, TCA_FQ_BUCKETS_LOG, q->fq_trees_log)) 750 nla_put_u32(skb, TCA_FQ_BUCKETS_LOG, q->fq_trees_log))
737 goto nla_put_failure; 751 goto nla_put_failure;
738 752