aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2005-05-03 16:24:57 -0700
committerDavid S. Miller <davem@davemloft.net>2005-05-03 16:24:57 -0700
commitd5d75cd6b10ddad2f375b61092754474ad78aec7 (patch)
tree73b6a0fa4177d8d7bfed465201842a3742a709c0
parent771018e76aaa6474be20a53c20458bcae8b00485 (diff)
downloadlinux-d5d75cd6b10ddad2f375b61092754474ad78aec7.tar.gz
[PKT_SCHED]: netetm: adjust parent qlen when duplicating
Fix qlen underrun when doing duplication with netem. If netem is used as leaf discipline, then the parent needs to be tweaked when packets are duplicated. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/sched/sch_api.c1
-rw-r--r--net/sched/sch_netem.c20
2 files changed, 16 insertions, 5 deletions
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 4323a74eea30b..07977f8f2679b 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1289,6 +1289,7 @@ static int __init pktsched_init(void)
subsys_initcall(pktsched_init);
+EXPORT_SYMBOL(qdisc_lookup);
EXPORT_SYMBOL(qdisc_get_rtab);
EXPORT_SYMBOL(qdisc_put_rtab);
EXPORT_SYMBOL(register_qdisc);
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 864b8d353ffae..e0c9fbe73b15c 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -206,7 +206,6 @@ static int netem_run(struct Qdisc *sch)
static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
struct netem_sched_data *q = qdisc_priv(sch);
- struct sk_buff *skb2;
int ret;
pr_debug("netem_enqueue skb=%p\n", skb);
@@ -220,11 +219,21 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
}
/* Random duplication */
- if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)
- && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
- pr_debug("netem_enqueue: dup %p\n", skb2);
+ if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) {
+ struct sk_buff *skb2;
+
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (skb2 && netem_delay(sch, skb2) == NET_XMIT_SUCCESS) {
+ struct Qdisc *qp;
+
+ /* Since one packet can generate two packets in the
+ * queue, the parent's qlen accounting gets confused,
+ * so fix it.
+ */
+ qp = qdisc_lookup(sch->dev, TC_H_MAJ(sch->parent));
+ if (qp)
+ qp->q.qlen++;
- if (netem_delay(sch, skb2)) {
sch->q.qlen++;
sch->bstats.bytes += skb2->len;
sch->bstats.packets++;
@@ -253,6 +262,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
} else
sch->qstats.drops++;
+ pr_debug("netem: enqueue ret %d\n", ret);
return ret;
}