This is a note to let you know that I've just added the patch titled sch_tbf: handle too small burst to the 3.12-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: sch_tbf-handle-too-small-burst.patch and it can be found in the queue-3.12 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From foo@baz Thu Dec 5 16:16:39 PST 2013 From: Eric Dumazet <edumazet@xxxxxxxxxx> Date: Sat, 23 Nov 2013 12:59:20 -0800 Subject: sch_tbf: handle too small burst From: Eric Dumazet <edumazet@xxxxxxxxxx> [ Upstream commit 4d0820cf6a55d72350cb2d24a4504f62fbde95d9 ] If a too small burst is inadvertently set on TBF, we might trigger a bug in tbf_segment(), as 'skb' instead of 'segs' was used in a qdisc_reshape_fail() call. tc qdisc add dev eth0 root handle 1: tbf latency 50ms burst 1KB rate 50mbit Fix the bug, and add a warning, as such configuration is not going to work anyway for non GSO packets. (For some reason, one has to use a burst >= 1520 to get a working configuration, even with old kernels. This is a probable iproute2/tc bug) Based on a report and initial patch from Yang Yingliang Fixes: e43ac79a4bc6 ("sch_tbf: segment too big GSO packets") Signed-off-by: Eric Dumazet <edumazet@xxxxxxxxxx> Reported-by: Yang Yingliang <yangyingliang@xxxxxxxxxx> Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- net/sched/sch_tbf.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c @@ -21,6 +21,7 @@ #include <net/netlink.h> #include <net/sch_generic.h> #include <net/pkt_sched.h> +#include <net/tcp.h> /* Simple Token Bucket Filter. @@ -117,6 +118,22 @@ struct tbf_sched_data { }; +/* + * Return length of individual segments of a gso packet, + * including all headers (MAC, IP, TCP/UDP) + */ +static unsigned int skb_gso_seglen(const struct sk_buff *skb) +{ + unsigned int hdr_len = skb_transport_header(skb) - skb_mac_header(skb); + const struct skb_shared_info *shinfo = skb_shinfo(skb); + + if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) + hdr_len += tcp_hdrlen(skb); + else + hdr_len += sizeof(struct udphdr); + return hdr_len + shinfo->gso_size; +} + /* GSO packet is too big, segment it so that tbf can transmit * each segment in time */ @@ -136,12 +153,8 @@ static int tbf_segment(struct sk_buff *s while (segs) { nskb = segs->next; segs->next = NULL; - if (likely(segs->len <= q->max_size)) { - qdisc_skb_cb(segs)->pkt_len = segs->len; - ret = qdisc_enqueue(segs, q->qdisc); - } else { - ret = qdisc_reshape_fail(skb, sch); - } + qdisc_skb_cb(segs)->pkt_len = segs->len; + ret = qdisc_enqueue(segs, q->qdisc); if (ret != NET_XMIT_SUCCESS) { if (net_xmit_drop_count(ret)) sch->qstats.drops++; @@ -163,7 +176,7 @@ static int tbf_enqueue(struct sk_buff *s int ret; if (qdisc_pkt_len(skb) > q->max_size) { - if (skb_is_gso(skb)) + if (skb_is_gso(skb) && skb_gso_seglen(skb) <= q->max_size) return tbf_segment(skb, sch); return qdisc_reshape_fail(skb, sch); } @@ -316,6 +329,11 @@ static int tbf_change(struct Qdisc *sch, if (max_size < 0) goto done; + if (max_size < psched_mtu(qdisc_dev(sch))) + pr_warn_ratelimited("sch_tbf: burst %u is lower than device %s mtu (%u) !\n", + max_size, qdisc_dev(sch)->name, + psched_mtu(qdisc_dev(sch))); + if (q->qdisc != &noop_qdisc) { err = fifo_set_limit(q->qdisc, qopt->limit); if (err) Patches currently in stable-queue which might be from edumazet@xxxxxxxxxx are queue-3.12/net-8139cp-fix-a-bug_on-triggered-by-wrong-bytes_compl.patch queue-3.12/sch_tbf-handle-too-small-burst.patch queue-3.12/gro-only-verify-tcp-checksums-for-candidates.patch queue-3.12/net-tcp-fix-panic-in-tcp_fastopen_cache_set.patch queue-3.12/tcp-tsq-restore-minimal-amount-of-queueing.patch queue-3.12/pkt_sched-fq-fix-pacing-for-small-frames.patch queue-3.12/ipv6-fix-possible-seqlock-deadlock-in-ip6_finish_output2.patch queue-3.12/tcp-don-t-update-snd_nxt-when-a-socket-is-switched-from-repair-mode.patch queue-3.12/inet-fix-possible-seqlock-deadlocks.patch queue-3.12/net-x86-bpf-don-t-forget-to-free-sk_filter-v2.patch queue-3.12/sit-fix-use-after-free-of-fb_tunnel_dev.patch queue-3.12/net-clamp-msg_namelen-instead-of-returning-an-error.patch queue-3.12/af_packet-block-bh-in-prb_shutdown_retire_blk_timer.patch queue-3.12/pkt_sched-fq-change-classification-of-control.patch queue-3.12/pkt_sched-fq-warn-users-using-defrate.patch queue-3.12/gro-clean-up-tcpx_gro_receive-checksum-verification.patch queue-3.12/ipv4-fix-possible-seqlock-deadlock.patch queue-3.12/gso-handle-new-frag_list-of-frags-gro-packets.patch -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html