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

net_sched: sch_fq: change how @inactive is tracked

Currently, when one fq qdisc has no more packets to send, it can still
have some flows stored in its RR lists (q->new_flows & q->old_flows)

This was a design choice, but what is a bit disturbing is that
the inactive_flows counter does not include the count of empty flows
in RR lists.

As next patch needs to know better if there are active flows,
this change makes inactive_flows exact.

Before the patch, following command on an empty qdisc could have returned:

lpaa17:~# tc -s -d qd sh dev eth1 | grep inactive
  flows 1322 (inactive 1316 throttled 0)
  flows 1330 (inactive 1325 throttled 0)
  flows 1193 (inactive 1190 throttled 0)
  flows 1208 (inactive 1202 throttled 0)

After the patch, we now have:

lpaa17:~# tc -s -d qd sh dev eth1 | grep inactive
  flows 1322 (inactive 1322 throttled 0)
  flows 1330 (inactive 1330 throttled 0)
  flows 1193 (inactive 1193 throttled 0)
  flows 1208 (inactive 1208 throttled 0)
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 54ff8ad6
...@@ -125,7 +125,7 @@ struct fq_sched_data { ...@@ -125,7 +125,7 @@ struct fq_sched_data {
/* Read/Write fields. */ /* Read/Write fields. */
u32 flows; u32 flows;
u32 inactive_flows; u32 inactive_flows; /* Flows with no packet to send. */
u32 throttled_flows; u32 throttled_flows;
u64 stat_throttled; u64 stat_throttled;
...@@ -402,9 +402,12 @@ static void fq_erase_head(struct Qdisc *sch, struct fq_flow *flow, ...@@ -402,9 +402,12 @@ static void fq_erase_head(struct Qdisc *sch, struct fq_flow *flow,
static void fq_dequeue_skb(struct Qdisc *sch, struct fq_flow *flow, static void fq_dequeue_skb(struct Qdisc *sch, struct fq_flow *flow,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct fq_sched_data *q = qdisc_priv(sch);
fq_erase_head(sch, flow, skb); fq_erase_head(sch, flow, skb);
skb_mark_not_on_list(skb); skb_mark_not_on_list(skb);
flow->qlen--; if (--flow->qlen == 0)
q->inactive_flows++;
qdisc_qstats_backlog_dec(sch, skb); qdisc_qstats_backlog_dec(sch, skb);
sch->q.qlen--; sch->q.qlen--;
} }
...@@ -484,13 +487,13 @@ static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch, ...@@ -484,13 +487,13 @@ static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
return qdisc_drop(skb, sch, to_free); return qdisc_drop(skb, sch, to_free);
} }
f->qlen++; if (f->qlen++ == 0)
q->inactive_flows--;
qdisc_qstats_backlog_inc(sch, skb); qdisc_qstats_backlog_inc(sch, skb);
if (fq_flow_is_detached(f)) { if (fq_flow_is_detached(f)) {
fq_flow_add_tail(&q->new_flows, f); fq_flow_add_tail(&q->new_flows, f);
if (time_after(jiffies, f->age + q->flow_refill_delay)) if (time_after(jiffies, f->age + q->flow_refill_delay))
f->credit = max_t(u32, f->credit, q->quantum); f->credit = max_t(u32, f->credit, q->quantum);
q->inactive_flows--;
} }
/* Note: this overwrites f->age */ /* Note: this overwrites f->age */
...@@ -597,7 +600,6 @@ static struct sk_buff *fq_dequeue(struct Qdisc *sch) ...@@ -597,7 +600,6 @@ static struct sk_buff *fq_dequeue(struct Qdisc *sch)
fq_flow_add_tail(&q->old_flows, f); fq_flow_add_tail(&q->old_flows, f);
} else { } else {
fq_flow_set_detached(f); fq_flow_set_detached(f);
q->inactive_flows++;
} }
goto begin; goto begin;
} }
......
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