Skip to content

Commit adb92db

Browse files
ij1davem330
authored andcommitted
tcp: Make SACK code to split only at mss boundaries
Sadly enough, this adds possible divide though we try to avoid it by checking one mss as common case. Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent e8bae27 commit adb92db

File tree

1 file changed

+23
-4
lines changed

1 file changed

+23
-4
lines changed

net/ipv4/tcp_input.c

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,20 +1248,39 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
12481248
{
12491249
int in_sack, err;
12501250
unsigned int pkt_len;
1251+
unsigned int mss;
12511252

12521253
in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq) &&
12531254
!before(end_seq, TCP_SKB_CB(skb)->end_seq);
12541255

12551256
if (tcp_skb_pcount(skb) > 1 && !in_sack &&
12561257
after(TCP_SKB_CB(skb)->end_seq, start_seq)) {
1257-
1258+
mss = tcp_skb_mss(skb);
12581259
in_sack = !after(start_seq, TCP_SKB_CB(skb)->seq);
12591260

1260-
if (!in_sack)
1261+
if (!in_sack) {
12611262
pkt_len = start_seq - TCP_SKB_CB(skb)->seq;
1262-
else
1263+
if (pkt_len < mss)
1264+
pkt_len = mss;
1265+
} else {
12631266
pkt_len = end_seq - TCP_SKB_CB(skb)->seq;
1264-
err = tcp_fragment(sk, skb, pkt_len, skb_shinfo(skb)->gso_size);
1267+
if (pkt_len < mss)
1268+
return -EINVAL;
1269+
}
1270+
1271+
/* Round if necessary so that SACKs cover only full MSSes
1272+
* and/or the remaining small portion (if present)
1273+
*/
1274+
if (pkt_len > mss) {
1275+
unsigned int new_len = (pkt_len / mss) * mss;
1276+
if (!in_sack && new_len < pkt_len) {
1277+
new_len += mss;
1278+
if (new_len > skb->len)
1279+
return 0;
1280+
}
1281+
pkt_len = new_len;
1282+
}
1283+
err = tcp_fragment(sk, skb, pkt_len, mss);
12651284
if (err < 0)
12661285
return err;
12671286
}

0 commit comments

Comments
 (0)