net_sched: factorize qdisc stats handling
Eric Dumazet [Sun, 9 Jan 2011 08:30:54 +0000 (08:30 +0000)]
HTB takes into account skb is segmented in stats updates.
Generalize this to all schedulers.

They should use qdisc_bstats_update() helper instead of manipulating
bstats.bytes and bstats.packets

Add bstats_update() helper too for classes that use
gnet_stats_basic_packed fields.

Note : Right now, TCQ_F_CAN_BYPASS shortcurt can be taken only if no
stab is setup on qdisc.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

24 files changed:
include/net/sch_generic.h
net/core/dev.c
net/sched/act_csum.c
net/sched/act_ipt.c
net/sched/act_mirred.c
net/sched/act_nat.c
net/sched/act_pedit.c
net/sched/act_police.c
net/sched/act_simple.c
net/sched/act_skbedit.c
net/sched/sch_atm.c
net/sched/sch_cbq.c
net/sched/sch_drr.c
net/sched/sch_dsmark.c
net/sched/sch_hfsc.c
net/sched/sch_htb.c
net/sched/sch_ingress.c
net/sched/sch_multiq.c
net/sched/sch_netem.c
net/sched/sch_prio.c
net/sched/sch_red.c
net/sched/sch_sfq.c
net/sched/sch_tbf.c
net/sched/sch_teql.c

index 0af57eb..e9eee99 100644 (file)
@@ -207,7 +207,7 @@ static inline int qdisc_qlen(struct Qdisc *q)
        return q->q.qlen;
 }
 
-static inline struct qdisc_skb_cb *qdisc_skb_cb(struct sk_buff *skb)
+static inline struct qdisc_skb_cb *qdisc_skb_cb(const struct sk_buff *skb)
 {
        return (struct qdisc_skb_cb *)skb->cb;
 }
@@ -394,7 +394,7 @@ static inline bool qdisc_tx_is_noop(const struct net_device *dev)
        return true;
 }
 
-static inline unsigned int qdisc_pkt_len(struct sk_buff *skb)
+static inline unsigned int qdisc_pkt_len(const struct sk_buff *skb)
 {
        return qdisc_skb_cb(skb)->pkt_len;
 }
@@ -426,10 +426,18 @@ static inline int qdisc_enqueue_root(struct sk_buff *skb, struct Qdisc *sch)
        return qdisc_enqueue(skb, sch) & NET_XMIT_MASK;
 }
 
-static inline void __qdisc_update_bstats(struct Qdisc *sch, unsigned int len)
+
+static inline void bstats_update(struct gnet_stats_basic_packed *bstats,
+                                const struct sk_buff *skb)
+{
+       bstats->bytes += qdisc_pkt_len(skb);
+       bstats->packets += skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1;
+}
+
+static inline void qdisc_bstats_update(struct Qdisc *sch,
+                                      const struct sk_buff *skb)
 {
-       sch->bstats.bytes += len;
-       sch->bstats.packets++;
+       bstats_update(&sch->bstats, skb);
 }
 
 static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch,
@@ -437,7 +445,7 @@ static inline int __qdisc_enqueue_tail(struct sk_buff *skb, struct Qdisc *sch,
 {
        __skb_queue_tail(list, skb);
        sch->qstats.backlog += qdisc_pkt_len(skb);
-       __qdisc_update_bstats(sch, qdisc_pkt_len(skb));
+       qdisc_bstats_update(sch, skb);
 
        return NET_XMIT_SUCCESS;
 }
index 3295b94..a3ef808 100644 (file)
@@ -2297,7 +2297,10 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
                 */
                if (!(dev->priv_flags & IFF_XMIT_DST_RELEASE))
                        skb_dst_force(skb);
-               __qdisc_update_bstats(q, skb->len);
+
+               qdisc_skb_cb(skb)->pkt_len = skb->len;
+               qdisc_bstats_update(q, skb);
+
                if (sch_direct_xmit(skb, q, dev, txq, root_lock)) {
                        if (unlikely(contended)) {
                                spin_unlock(&q->busylock);
index 67dc7ce..83ddfc0 100644 (file)
@@ -508,8 +508,7 @@ static int tcf_csum(struct sk_buff *skb,
 
        spin_lock(&p->tcf_lock);
        p->tcf_tm.lastuse = jiffies;
-       p->tcf_bstats.bytes += qdisc_pkt_len(skb);
-       p->tcf_bstats.packets++;
+       bstats_update(&p->tcf_bstats, skb);
        action = p->tcf_action;
        update_flags = p->update_flags;
        spin_unlock(&p->tcf_lock);
index 8daef96..c2a7c20 100644 (file)
@@ -209,8 +209,7 @@ static int tcf_ipt(struct sk_buff *skb, struct tc_action *a,
        spin_lock(&ipt->tcf_lock);
 
        ipt->tcf_tm.lastuse = jiffies;
-       ipt->tcf_bstats.bytes += qdisc_pkt_len(skb);
-       ipt->tcf_bstats.packets++;
+       bstats_update(&ipt->tcf_bstats, skb);
 
        /* yes, we have to worry about both in and out dev
         worry later - danger - this API seems to have changed
index 0c311be..d765067 100644 (file)
@@ -165,8 +165,7 @@ static int tcf_mirred(struct sk_buff *skb, struct tc_action *a,
 
        spin_lock(&m->tcf_lock);
        m->tcf_tm.lastuse = jiffies;
-       m->tcf_bstats.bytes += qdisc_pkt_len(skb);
-       m->tcf_bstats.packets++;
+       bstats_update(&m->tcf_bstats, skb);
 
        dev = m->tcfm_dev;
        if (!dev) {
index 186eb83..178a4bd 100644 (file)
@@ -125,8 +125,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
        egress = p->flags & TCA_NAT_FLAG_EGRESS;
        action = p->tcf_action;
 
-       p->tcf_bstats.bytes += qdisc_pkt_len(skb);
-       p->tcf_bstats.packets++;
+       bstats_update(&p->tcf_bstats, skb);
 
        spin_unlock(&p->tcf_lock);
 
index a0593c9..445bef7 100644 (file)
@@ -187,8 +187,7 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a,
 bad:
        p->tcf_qstats.overlimits++;
 done:
-       p->tcf_bstats.bytes += qdisc_pkt_len(skb);
-       p->tcf_bstats.packets++;
+       bstats_update(&p->tcf_bstats, skb);
        spin_unlock(&p->tcf_lock);
        return p->tcf_action;
 }
index 7ebf743..e2f08b1 100644 (file)
@@ -298,8 +298,7 @@ static int tcf_act_police(struct sk_buff *skb, struct tc_action *a,
 
        spin_lock(&police->tcf_lock);
 
-       police->tcf_bstats.bytes += qdisc_pkt_len(skb);
-       police->tcf_bstats.packets++;
+       bstats_update(&police->tcf_bstats, skb);
 
        if (police->tcfp_ewma_rate &&
            police->tcf_rate_est.bps >= police->tcfp_ewma_rate) {
index 97e84f3..7287cff 100644 (file)
@@ -42,8 +42,7 @@ static int tcf_simp(struct sk_buff *skb, struct tc_action *a, struct tcf_result
 
        spin_lock(&d->tcf_lock);
        d->tcf_tm.lastuse = jiffies;
-       d->tcf_bstats.bytes += qdisc_pkt_len(skb);
-       d->tcf_bstats.packets++;
+       bstats_update(&d->tcf_bstats, skb);
 
        /* print policy string followed by _ then packet count
         * Example if this was the 3rd packet and the string was "hello"
index 66cbf4e..836f5fe 100644 (file)
@@ -46,8 +46,7 @@ static int tcf_skbedit(struct sk_buff *skb, struct tc_action *a,
 
        spin_lock(&d->tcf_lock);
        d->tcf_tm.lastuse = jiffies;
-       d->tcf_bstats.bytes += qdisc_pkt_len(skb);
-       d->tcf_bstats.packets++;
+       bstats_update(&d->tcf_bstats, skb);
 
        if (d->flags & SKBEDIT_F_PRIORITY)
                skb->priority = d->priority;
index 2825407..943d733 100644 (file)
@@ -422,10 +422,8 @@ drop: __maybe_unused
                }
                return ret;
        }
-       sch->bstats.bytes += qdisc_pkt_len(skb);
-       sch->bstats.packets++;
-       flow->bstats.bytes += qdisc_pkt_len(skb);
-       flow->bstats.packets++;
+       qdisc_bstats_update(sch, skb);
+       bstats_update(&flow->bstats, skb);
        /*
         * Okay, this may seem weird. We pretend we've dropped the packet if
         * it goes via ATM. The reason for this is that the outer qdisc
index eb76315..c80d1c2 100644 (file)
@@ -390,8 +390,7 @@ cbq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        ret = qdisc_enqueue(skb, cl->q);
        if (ret == NET_XMIT_SUCCESS) {
                sch->q.qlen++;
-               sch->bstats.packets++;
-               sch->bstats.bytes += qdisc_pkt_len(skb);
+               qdisc_bstats_update(sch, skb);
                cbq_mark_toplevel(q, cl);
                if (!cl->next_alive)
                        cbq_activate_class(cl);
@@ -650,8 +649,7 @@ static int cbq_reshape_fail(struct sk_buff *skb, struct Qdisc *child)
                ret = qdisc_enqueue(skb, cl->q);
                if (ret == NET_XMIT_SUCCESS) {
                        sch->q.qlen++;
-                       sch->bstats.packets++;
-                       sch->bstats.bytes += qdisc_pkt_len(skb);
+                       qdisc_bstats_update(sch, skb);
                        if (!cl->next_alive)
                                cbq_activate_class(cl);
                        return 0;
index aa8b531..de55e64 100644 (file)
@@ -351,7 +351,6 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 {
        struct drr_sched *q = qdisc_priv(sch);
        struct drr_class *cl;
-       unsigned int len;
        int err;
 
        cl = drr_classify(skb, sch, &err);
@@ -362,7 +361,6 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                return err;
        }
 
-       len = qdisc_pkt_len(skb);
        err = qdisc_enqueue(skb, cl->qdisc);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                if (net_xmit_drop_count(err)) {
@@ -377,10 +375,8 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                cl->deficit = cl->quantum;
        }
 
-       cl->bstats.packets++;
-       cl->bstats.bytes += len;
-       sch->bstats.packets++;
-       sch->bstats.bytes += len;
+       bstats_update(&cl->bstats, skb);
+       qdisc_bstats_update(sch, skb);
 
        sch->q.qlen++;
        return err;
index 1d295d6..60f4bdd 100644 (file)
@@ -260,8 +260,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                return err;
        }
 
-       sch->bstats.bytes += qdisc_pkt_len(skb);
-       sch->bstats.packets++;
+       qdisc_bstats_update(sch, skb);
        sch->q.qlen++;
 
        return NET_XMIT_SUCCESS;
index 069c62b..2e45791 100644 (file)
@@ -1599,10 +1599,8 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        if (cl->qdisc->q.qlen == 1)
                set_active(cl, qdisc_pkt_len(skb));
 
-       cl->bstats.packets++;
-       cl->bstats.bytes += qdisc_pkt_len(skb);
-       sch->bstats.packets++;
-       sch->bstats.bytes += qdisc_pkt_len(skb);
+       bstats_update(&cl->bstats, skb);
+       qdisc_bstats_update(sch, skb);
        sch->q.qlen++;
 
        return NET_XMIT_SUCCESS;
index 01b519d..984c1b0 100644 (file)
@@ -569,15 +569,12 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                }
                return ret;
        } else {
-               cl->bstats.packets +=
-                       skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
-               cl->bstats.bytes += qdisc_pkt_len(skb);
+               bstats_update(&cl->bstats, skb);
                htb_activate(q, cl);
        }
 
        sch->q.qlen++;
-       sch->bstats.packets += skb_is_gso(skb)?skb_shinfo(skb)->gso_segs:1;
-       sch->bstats.bytes += qdisc_pkt_len(skb);
+       qdisc_bstats_update(sch, skb);
        return NET_XMIT_SUCCESS;
 }
 
@@ -648,12 +645,10 @@ static void htb_charge_class(struct htb_sched *q, struct htb_class *cl,
                                htb_add_to_wait_tree(q, cl, diff);
                }
 
-               /* update byte stats except for leaves which are already updated */
-               if (cl->level) {
-                       cl->bstats.bytes += bytes;
-                       cl->bstats.packets += skb_is_gso(skb)?
-                                       skb_shinfo(skb)->gso_segs:1;
-               }
+               /* update basic stats except for leaves which are already updated */
+               if (cl->level)
+                       bstats_update(&cl->bstats, skb);
+
                cl = cl->parent;
        }
 }
index f10e34a..bce1665 100644 (file)
@@ -63,8 +63,7 @@ static int ingress_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 
        result = tc_classify(skb, p->filter_list, &res);
 
-       sch->bstats.packets++;
-       sch->bstats.bytes += qdisc_pkt_len(skb);
+       qdisc_bstats_update(sch, skb);
        switch (result) {
        case TC_ACT_SHOT:
                result = TC_ACT_SHOT;
index 32690de..21f13da 100644 (file)
@@ -83,8 +83,7 @@ multiq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 
        ret = qdisc_enqueue(skb, qdisc);
        if (ret == NET_XMIT_SUCCESS) {
-               sch->bstats.bytes += qdisc_pkt_len(skb);
-               sch->bstats.packets++;
+               qdisc_bstats_update(sch, skb);
                sch->q.qlen++;
                return NET_XMIT_SUCCESS;
        }
index e5593c0..1c4bce8 100644 (file)
@@ -240,8 +240,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 
        if (likely(ret == NET_XMIT_SUCCESS)) {
                sch->q.qlen++;
-               sch->bstats.bytes += qdisc_pkt_len(skb);
-               sch->bstats.packets++;
+               qdisc_bstats_update(sch, skb);
        } else if (net_xmit_drop_count(ret)) {
                sch->qstats.drops++;
        }
@@ -477,8 +476,7 @@ static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
                __skb_queue_after(list, skb, nskb);
 
                sch->qstats.backlog += qdisc_pkt_len(nskb);
-               sch->bstats.bytes += qdisc_pkt_len(nskb);
-               sch->bstats.packets++;
+               qdisc_bstats_update(sch, nskb);
 
                return NET_XMIT_SUCCESS;
        }
index b1c95bc..966158d 100644 (file)
@@ -84,8 +84,7 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 
        ret = qdisc_enqueue(skb, qdisc);
        if (ret == NET_XMIT_SUCCESS) {
-               sch->bstats.bytes += qdisc_pkt_len(skb);
-               sch->bstats.packets++;
+               qdisc_bstats_update(sch, skb);
                sch->q.qlen++;
                return NET_XMIT_SUCCESS;
        }
index a67ba3c..a6009c5 100644 (file)
@@ -94,8 +94,7 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 
        ret = qdisc_enqueue(skb, child);
        if (likely(ret == NET_XMIT_SUCCESS)) {
-               sch->bstats.bytes += qdisc_pkt_len(skb);
-               sch->bstats.packets++;
+               qdisc_bstats_update(sch, skb);
                sch->q.qlen++;
        } else if (net_xmit_drop_count(ret)) {
                q->stats.pdrop++;
index d54ac94..239ec53 100644 (file)
@@ -403,8 +403,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                slot->allot = q->scaled_quantum;
        }
        if (++sch->q.qlen <= q->limit) {
-               sch->bstats.bytes += qdisc_pkt_len(skb);
-               sch->bstats.packets++;
+               qdisc_bstats_update(sch, skb);
                return NET_XMIT_SUCCESS;
        }
 
index 641a30d..77565e7 100644 (file)
@@ -134,8 +134,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch)
        }
 
        sch->q.qlen++;
-       sch->bstats.bytes += qdisc_pkt_len(skb);
-       sch->bstats.packets++;
+       qdisc_bstats_update(sch, skb);
        return NET_XMIT_SUCCESS;
 }
 
index 106479a..af9360d 100644 (file)
@@ -83,8 +83,7 @@ teql_enqueue(struct sk_buff *skb, struct Qdisc* sch)
 
        if (q->q.qlen < dev->tx_queue_len) {
                __skb_queue_tail(&q->q, skb);
-               sch->bstats.bytes += qdisc_pkt_len(skb);
-               sch->bstats.packets++;
+               qdisc_bstats_update(sch, skb);
                return NET_XMIT_SUCCESS;
        }