diff options
author | stephen hemminger <stephen@networkplumber.org> | 2013-10-06 18:16:49 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-11 17:30:38 -0400 |
commit | ff704050f2fc0f3382b5a70bba56a51a3feca79d (patch) | |
tree | d4ba003c5b40b929ab08a50d720a9df2e69be58a /net | |
parent | 638a52b801e40ed276ceb69b73579ad99365361a (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.c | 16 |
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 | ||
361 | static 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 | |||
361 | static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) | 376 | static 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); |