net_sched: factorize qdisc stats handling
authorEric Dumazet <eric.dumazet@gmail.com>
Sun, 9 Jan 2011 08:30:54 +0000 (08:30 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 11 Jan 2011 00:07:54 +0000 (16:07 -0800)
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 0af57ebae76204b1ce40c1d392cfc055a7e15d8d..e9eee99d8b1f4668aef09526341d0e032a6f120b 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 3295b94884abd8a2bfa2802ddb4a9617ec658d0a..a3ef808b5e36d5e656c7cce53ab412cbcf388d6c 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 67dc7ce9b63ad0796d038058ceeeaf7672ac2361..83ddfc07e45da91831a9c765c8af3896bf9ee079 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 8daef9632255349f135867672941caa8181c6b54..c2a7c20e81c184ceea4cabb66659c22798c9fa8f 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 0c311be9282798ea6b27d1109f482bfdb20c7dac..d765067e99dbd1485135b406b69abf512d8cbd26 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 186eb837e600da750dd3347f96f033478d131b76..178a4bd7b7cbfd28accd393ef6b9700bc6f6d3f4 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 a0593c9640db1def9adbd1ce1483973dfb300c4c..445bef716f770f5fa625243d999d11228edbf5b2 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 7ebf7439b478d24b4246527c7313fb8cb774496b..e2f08b1e2e5897084e84fd378d7505d2310f7cae 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 97e84f3ee77563fb14aa7b8e0faf2db476a81501..7287cff7af3e045047020143045fbb9213cd9957 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 66cbf4eb8855452477ec0f459d69cd6db2559ce7..836f5fee9e5898c400eb651fa099b485d6f2f124 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 282540778aa8d5907aab2976071a081f18daa29a..943d733409d08316e7bbf81749047c066b63d9bb 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 eb763159086501aa2887c2c80680e37fbf0aa4fc..c80d1c210c5d621454acf3388a63440c3fbfe740 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 aa8b5313f8cf4d1a4a11e7077f9445fed11dd424..de55e642eafc2924bd2b6220aaac1d38e879954e 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 1d295d62bb5ca4cfdf8a3a9c4dc24b36731232ed..60f4bdd4408e25888b4575bd9ab7b75441cab8c6 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 069c62b7bb3691ac8b4008202c4d3d9aee006d0a..2e45791d4f6cf7970d590fde138981254b359403 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 01b519d6c52d3e2bf5f5baf5852594793ba6e7f5..984c1b0c68369dd24b4837fd681126abc229ce92 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 f10e34a6844516db924303b29ade38f9f7e8f49d..bce1665239b8ff7e55901b216fb705bd6b31229e 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 32690deab5d07cfed26eb7d1fda6656d7d1b8fe0..21f13da24763977eaea671c19a58357018f72899 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 e5593c083a7883f99e548e182e90d8a2ae84bb65..1c4bce86347977ec93b1fa5a0fdcceaf34cfe257 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 b1c95bce33ce6f2f8a360e93ab234f8db1ab42c9..966158d49dd105ce882ece6a6ccd6f072f5676ca 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 a67ba3c5a0cce46225d56146d71233a9c4d550b5..a6009c5a2c97dbe446b162923fb997db00f00ee6 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 d54ac94066c2025b9e7ea515b9f8337422eab326..239ec53a634dace6d29a3294c2a98e4c401539b8 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 641a30d646356867b808ac86d7bac59901fe2729..77565e721811f5cc5789a24987be3b0c04a6b371 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 106479a7c94a494665f6783578e61182e82453d5..af9360d1f6eb3b4c839bcfa2f623955c12a232a8 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;
        }