Commit a5d28090 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

codel: fix maxpacket/mtu confusion

Under presence of TSO/GSO/GRO packets, codel at low rates can be quite
useless. In following example, not a single packet was ever dropped,
while average delay in codel queue is ~100 ms !

qdisc codel 0: parent 1:12 limit 16000p target 5.0ms interval 100.0ms
 Sent 134376498 bytes 88797 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 13626b 3p requeues 0
  count 0 lastcount 0 ldelay 96.9ms drop_next 0us
  maxpacket 9084 ecn_mark 0 drop_overlimit 0

This comes from a confusion of what should be the minimal backlog. It is
pretty clear it is not 64KB or whatever max GSO packet ever reached the
qdisc.

codel intent was to use MTU of the device.

After the fix, we finally drop some packets, and rtt/cwnd of my single
TCP flow are meeting our expectations.

qdisc codel 0: parent 1:12 limit 16000p target 5.0ms interval 100.0ms
 Sent 102798497 bytes 67912 pkt (dropped 1365, overlimits 0 requeues 0)
 backlog 6056b 3p requeues 0
  count 1 lastcount 1 ldelay 36.3ms drop_next 0us
  maxpacket 10598 ecn_mark 0 drop_overlimit 0
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Cc: Kathleen Nichols <nichols@pollere.com>
Cc: Dave Taht <dave.taht@gmail.com>
Cc: Van Jacobson <vanj@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 6c3c1eb3
...@@ -120,11 +120,13 @@ static inline u32 codel_time_to_us(codel_time_t val) ...@@ -120,11 +120,13 @@ static inline u32 codel_time_to_us(codel_time_t val)
* struct codel_params - contains codel parameters * struct codel_params - contains codel parameters
* @target: target queue size (in time units) * @target: target queue size (in time units)
* @interval: width of moving time window * @interval: width of moving time window
* @mtu: device mtu, or minimal queue backlog in bytes.
* @ecn: is Explicit Congestion Notification enabled * @ecn: is Explicit Congestion Notification enabled
*/ */
struct codel_params { struct codel_params {
codel_time_t target; codel_time_t target;
codel_time_t interval; codel_time_t interval;
u32 mtu;
bool ecn; bool ecn;
}; };
...@@ -166,10 +168,12 @@ struct codel_stats { ...@@ -166,10 +168,12 @@ struct codel_stats {
u32 ecn_mark; u32 ecn_mark;
}; };
static void codel_params_init(struct codel_params *params) static void codel_params_init(struct codel_params *params,
const struct Qdisc *sch)
{ {
params->interval = MS2TIME(100); params->interval = MS2TIME(100);
params->target = MS2TIME(5); params->target = MS2TIME(5);
params->mtu = psched_mtu(qdisc_dev(sch));
params->ecn = false; params->ecn = false;
} }
...@@ -180,7 +184,7 @@ static void codel_vars_init(struct codel_vars *vars) ...@@ -180,7 +184,7 @@ static void codel_vars_init(struct codel_vars *vars)
static void codel_stats_init(struct codel_stats *stats) static void codel_stats_init(struct codel_stats *stats)
{ {
stats->maxpacket = 256; stats->maxpacket = 0;
} }
/* /*
...@@ -234,7 +238,7 @@ static bool codel_should_drop(const struct sk_buff *skb, ...@@ -234,7 +238,7 @@ static bool codel_should_drop(const struct sk_buff *skb,
stats->maxpacket = qdisc_pkt_len(skb); stats->maxpacket = qdisc_pkt_len(skb);
if (codel_time_before(vars->ldelay, params->target) || if (codel_time_before(vars->ldelay, params->target) ||
sch->qstats.backlog <= stats->maxpacket) { sch->qstats.backlog <= params->mtu) {
/* went below - stay below for at least interval */ /* went below - stay below for at least interval */
vars->first_above_time = 0; vars->first_above_time = 0;
return false; return false;
......
...@@ -164,7 +164,7 @@ static int codel_init(struct Qdisc *sch, struct nlattr *opt) ...@@ -164,7 +164,7 @@ static int codel_init(struct Qdisc *sch, struct nlattr *opt)
sch->limit = DEFAULT_CODEL_LIMIT; sch->limit = DEFAULT_CODEL_LIMIT;
codel_params_init(&q->params); codel_params_init(&q->params, sch);
codel_vars_init(&q->vars); codel_vars_init(&q->vars);
codel_stats_init(&q->stats); codel_stats_init(&q->stats);
......
...@@ -391,7 +391,7 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt) ...@@ -391,7 +391,7 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt)
q->perturbation = prandom_u32(); q->perturbation = prandom_u32();
INIT_LIST_HEAD(&q->new_flows); INIT_LIST_HEAD(&q->new_flows);
INIT_LIST_HEAD(&q->old_flows); INIT_LIST_HEAD(&q->old_flows);
codel_params_init(&q->cparams); codel_params_init(&q->cparams, sch);
codel_stats_init(&q->cstats); codel_stats_init(&q->cstats);
q->cparams.ecn = true; q->cparams.ecn = true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment