summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstephen hemminger <stephen@networkplumber.org>2013-10-06 15:16:49 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-11-04 04:35:15 -0800
commit49cf14bacf02f6d9047dc0bf642e3fa2a2e99206 (patch)
tree3586432336b74fa9fdedcbb2279c446ae193e6a3
parent598b990bb1f1f6026dc35e7d6ca69e4cf30e52f4 (diff)
netem: free skb's in tree on reset
[ Upstream commit ff704050f2fc0f3382b5a70bba56a51a3feca79d ] 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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-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 7dc79940f240..3626010e8f0b 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
return PSCHED_NS2TICKS(ticks);
}
+static void tfifo_reset(struct Qdisc *sch)
+{
+ struct netem_sched_data *q = qdisc_priv(sch);
+ struct rb_node *p;
+
+ while ((p = rb_first(&q->t_root))) {
+ struct sk_buff *skb = netem_rb_to_skb(p);
+
+ rb_erase(p, &q->t_root);
+ skb->next = NULL;
+ skb->prev = NULL;
+ kfree_skb(skb);
+ }
+}
+
static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
{
struct netem_sched_data *q = qdisc_priv(sch);
@@ -613,6 +628,7 @@ static void netem_reset(struct Qdisc *sch)
struct netem_sched_data *q = qdisc_priv(sch);
qdisc_reset_queue(sch);
+ tfifo_reset(sch);
if (q->qdisc)
qdisc_reset(q->qdisc);
qdisc_watchdog_cancel(&q->watchdog);