summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/sch_generic.h8
-rw-r--r--net/sched/sch_netem.c6
2 files changed, 13 insertions, 1 deletions
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 513aecb66565..2d5acae04344 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -656,6 +656,14 @@ static inline int qdisc_drop(struct sk_buff *skb, struct Qdisc *sch)
return NET_XMIT_DROP;
}
+static inline int qdisc_drop_all(struct sk_buff *skb, struct Qdisc *sch)
+{
+ kfree_skb_list(skb);
+ sch->qstats.drops++;
+
+ return NET_XMIT_DROP;
+}
+
static inline int qdisc_reshape_fail(struct sk_buff *skb, struct Qdisc *sch)
{
sch->qstats.drops++;
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index cbf402451c20..afdd343ad826 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -511,8 +511,12 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
1<<(prandom_u32() % 8);
}
- if (unlikely(skb_queue_len(&sch->q) >= sch->limit))
+ if (unlikely(skb_queue_len(&sch->q) >= sch->limit)) {
+ /* qdisc_reshape_fail() can't handle segmented skb */
+ if (segs)
+ return qdisc_drop_all(skb, sch);
return qdisc_reshape_fail(skb, sch);
+ }
sch->qstats.backlog += qdisc_pkt_len(skb);