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>
This commit is contained in:
Родитель
e8bae275d9
Коммит
adb92db857
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче