aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2005-05-03 19:24:57 -0400
committerDavid S. Miller <davem@davemloft.net>2005-05-03 19:24:57 -0400
commitd5d75cd6b10ddad2f375b61092754474ad78aec7 (patch)
tree73b6a0fa4177d8d7bfed465201842a3742a709c0
parent771018e76aaa6474be20a53c20458bcae8b00485 (diff)
[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 4323a74eea30..07977f8f2679 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1289,6 +1289,7 @@ static int __init pktsched_init(void)
1289 1289
1290subsys_initcall(pktsched_init); 1290subsys_initcall(pktsched_init);
1291 1291
1292EXPORT_SYMBOL(qdisc_lookup);
1292EXPORT_SYMBOL(qdisc_get_rtab); 1293EXPORT_SYMBOL(qdisc_get_rtab);
1293EXPORT_SYMBOL(qdisc_put_rtab); 1294EXPORT_SYMBOL(qdisc_put_rtab);
1294EXPORT_SYMBOL(register_qdisc); 1295EXPORT_SYMBOL(register_qdisc);
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 864b8d353ffa..e0c9fbe73b15 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -206,7 +206,6 @@ static int netem_run(struct Qdisc *sch)
206static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) 206static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
207{ 207{
208 struct netem_sched_data *q = qdisc_priv(sch); 208 struct netem_sched_data *q = qdisc_priv(sch);
209 struct sk_buff *skb2;
210 int ret; 209 int ret;
211 210
212 pr_debug("netem_enqueue skb=%p\n", skb); 211 pr_debug("netem_enqueue skb=%p\n", skb);
@@ -220,11 +219,21 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
220 } 219 }
221 220
222 /* Random duplication */ 221 /* Random duplication */
223 if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor) 222 if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) {
224 && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) { 223 struct sk_buff *skb2;
225 pr_debug("netem_enqueue: dup %p\n", skb2); 224
225 skb2 = skb_clone(skb, GFP_ATOMIC);
226 if (skb2 && netem_delay(sch, skb2) == NET_XMIT_SUCCESS) {
227 struct Qdisc *qp;
228
229 /* Since one packet can generate two packets in the
230 * queue, the parent's qlen accounting gets confused,
231 * so fix it.
232 */
233 qp = qdisc_lookup(sch->dev, TC_H_MAJ(sch->parent));
234 if (qp)
235 qp->q.qlen++;
226 236
227 if (netem_delay(sch, skb2)) {
228 sch->q.qlen++; 237 sch->q.qlen++;
229 sch->bstats.bytes += skb2->len; 238 sch->bstats.bytes += skb2->len;
230 sch->bstats.packets++; 239 sch->bstats.packets++;
@@ -253,6 +262,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
253 } else 262 } else
254 sch->qstats.drops++; 263 sch->qstats.drops++;
255 264
265 pr_debug("netem: enqueue ret %d\n", ret);
256 return ret; 266 return ret;
257} 267}
258 268