From 6390ae4945c83476d84253f67fe18cb4652dff22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Mon, 24 Nov 2008 21:13:50 -0800 Subject: [PATCH] --- yaml --- r: 122127 b: refs/heads/master c: adb92db857ee2a0a2b925ccfbd560203c3f88aae h: refs/heads/master i: 122125: 7a66991bcf5681507aee304d23f3a69e64800b7e 122123: 08438bc52b8f020ac955ce48ebf863f37edcb230 122119: 923ac4836fb1ba9682144537d6f9ee77ee489145 122111: 5ca8caff03b2d6940d572238608bd91128b6a39a v: v3 --- [refs] | 2 +- trunk/net/ipv4/tcp_input.c | 27 +++++++++++++++++++++++---- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/[refs] b/[refs] index f65392d07333..719acf871108 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: e8bae275d9354104f7ae24a48a90d1a6286e7bd9 +refs/heads/master: adb92db857ee2a0a2b925ccfbd560203c3f88aae diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index 3f26599ddc88..ca46eb9151f8 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -1248,20 +1248,39 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb, { int in_sack, err; unsigned int pkt_len; + unsigned int mss; in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) && !before(end_seq, TCP_SKB_CB(skb)->end_seq); if (tcp_skb_pcount(skb) > 1 && !in_sack && after(TCP_SKB_CB(skb)->end_seq, start_seq)) { - + mss = tcp_skb_mss(skb); in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq); - if (!in_sack) + if (!in_sack) { pkt_len = start_seq - TCP_SKB_CB(skb)->seq; - else + if (pkt_len < mss) + pkt_len = mss; + } else { pkt_len = end_seq - TCP_SKB_CB(skb)->seq; - err = tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->gso_size); + if (pkt_len < mss) + return -EINVAL; + } + + /* Round if necessary so that SACKs cover only full MSSes + * and/or the remaining small portion (if present) + */ + if (pkt_len > mss) { + unsigned int new_len = (pkt_len / mss) * mss; + if (!in_sack && new_len < pkt_len) { + new_len += mss; + if (new_len > skb->len) + return 0; + } + pkt_len = new_len; + } + err = tcp_fragment(sk, skb, pkt_len, mss); if (err < 0) return err; }