net_sched: update hierarchical backlog too
When the bottom qdisc decides to, for example, drop some packet, it calls qdisc_tree_decrease_qlen() to update the queue length for all its ancestors, we need to update the backlog too to keep the stats on root qdisc accurate. Cc: Jamal Hadi Salim <jhs@mojatatu.com> Acked-by: Jamal Hadi Salim <jhs@mojatatu.com> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
86a7996cc8
commit
2ccccf5fb4
@@ -346,7 +346,7 @@ static int
|
||||
sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
|
||||
{
|
||||
struct sfq_sched_data *q = qdisc_priv(sch);
|
||||
unsigned int hash;
|
||||
unsigned int hash, dropped;
|
||||
sfq_index x, qlen;
|
||||
struct sfq_slot *slot;
|
||||
int uninitialized_var(ret);
|
||||
@@ -461,7 +461,7 @@ enqueue:
|
||||
return NET_XMIT_SUCCESS;
|
||||
|
||||
qlen = slot->qlen;
|
||||
sfq_drop(sch);
|
||||
dropped = sfq_drop(sch);
|
||||
/* Return Congestion Notification only if we dropped a packet
|
||||
* from this flow.
|
||||
*/
|
||||
@@ -469,7 +469,7 @@ enqueue:
|
||||
return NET_XMIT_CN;
|
||||
|
||||
/* As we dropped a packet, better let upper stack know this */
|
||||
qdisc_tree_decrease_qlen(sch, 1);
|
||||
qdisc_tree_reduce_backlog(sch, 1, dropped);
|
||||
return NET_XMIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -537,6 +537,7 @@ static void sfq_rehash(struct Qdisc *sch)
|
||||
struct sfq_slot *slot;
|
||||
struct sk_buff_head list;
|
||||
int dropped = 0;
|
||||
unsigned int drop_len = 0;
|
||||
|
||||
__skb_queue_head_init(&list);
|
||||
|
||||
@@ -565,6 +566,7 @@ static void sfq_rehash(struct Qdisc *sch)
|
||||
if (x >= SFQ_MAX_FLOWS) {
|
||||
drop:
|
||||
qdisc_qstats_backlog_dec(sch, skb);
|
||||
drop_len += qdisc_pkt_len(skb);
|
||||
kfree_skb(skb);
|
||||
dropped++;
|
||||
continue;
|
||||
@@ -594,7 +596,7 @@ drop:
|
||||
}
|
||||
}
|
||||
sch->q.qlen -= dropped;
|
||||
qdisc_tree_decrease_qlen(sch, dropped);
|
||||
qdisc_tree_reduce_backlog(sch, dropped, drop_len);
|
||||
}
|
||||
|
||||
static void sfq_perturbation(unsigned long arg)
|
||||
@@ -618,7 +620,7 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
|
||||
struct sfq_sched_data *q = qdisc_priv(sch);
|
||||
struct tc_sfq_qopt *ctl = nla_data(opt);
|
||||
struct tc_sfq_qopt_v1 *ctl_v1 = NULL;
|
||||
unsigned int qlen;
|
||||
unsigned int qlen, dropped = 0;
|
||||
struct red_parms *p = NULL;
|
||||
|
||||
if (opt->nla_len < nla_attr_size(sizeof(*ctl)))
|
||||
@@ -667,8 +669,8 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
|
||||
|
||||
qlen = sch->q.qlen;
|
||||
while (sch->q.qlen > q->limit)
|
||||
sfq_drop(sch);
|
||||
qdisc_tree_decrease_qlen(sch, qlen - sch->q.qlen);
|
||||
dropped += sfq_drop(sch);
|
||||
qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped);
|
||||
|
||||
del_timer(&q->perturb_timer);
|
||||
if (q->perturb_period) {
|
||||
|
Reference in New Issue
Block a user