aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorstephen hemminger <stephen@networkplumber.org>2013-10-06 18:16:49 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-11 17:30:38 -0400
commitff704050f2fc0f3382b5a70bba56a51a3feca79d (patch)
treed4ba003c5b40b929ab08a50d720a9df2e69be58a /net
parent638a52b801e40ed276ceb69b73579ad99365361a (diff)
netem: free skb's in tree on reset
Netem can leak memory because packets get stored in red-black tree and it is not cleared on reset. Reported by: Сергеев Сергей <adron@yapic.net> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/sched/sch_netem.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 6b75b6733e8e..b87e83d07478 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -358,6 +358,21 @@ static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sche
358 return PSCHED_NS2TICKS(ticks); 358 return PSCHED_NS2TICKS(ticks);
359} 359}
360 360
361static void tfifo_reset(struct Qdisc *sch)
362{
363 struct netem_sched_data *q = qdisc_priv(sch);
364 struct rb_node *p;
365
366 while ((p = rb_first(&q->t_root))) {
367 struct sk_buff *skb = netem_rb_to_skb(p);
368
369 rb_erase(p, &q->t_root);
370 skb->next = NULL;
371 skb->prev = NULL;
372 kfree_skb(skb);
373 }
374}
375
361static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) 376static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
362{ 377{
363 struct netem_sched_data *q = qdisc_priv(sch); 378 struct netem_sched_data *q = qdisc_priv(sch);
@@ -610,6 +625,7 @@ static void netem_reset(struct Qdisc *sch)
610 struct netem_sched_data *q = qdisc_priv(sch); 625 struct netem_sched_data *q = qdisc_priv(sch);
611 626
612 qdisc_reset_queue(sch); 627 qdisc_reset_queue(sch);
628 tfifo_reset(sch);
613 if (q->qdisc) 629 if (q->qdisc)
614 qdisc_reset(q->qdisc); 630 qdisc_reset(q->qdisc);
615 qdisc_watchdog_cancel(&q->watchdog); 631 qdisc_watchdog_cancel(&q->watchdog);