diff options
-rw-r--r-- | include/net/sch_generic.h | 8 | ||||
-rw-r--r-- | net/sched/sch_netem.c | 6 |
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); |