diff options
Diffstat (limited to 'net/ipv4/tcp_output.c')
-rw-r--r-- | net/ipv4/tcp_output.c | 55 |
1 files changed, 20 insertions, 35 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 75b68116682a..6094db5e11be 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -428,11 +428,11 @@ static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned | |||
428 | * packet to the list. This won't be called frequently, I hope. | 428 | * packet to the list. This won't be called frequently, I hope. |
429 | * Remember, these are still headerless SKBs at this point. | 429 | * Remember, these are still headerless SKBs at this point. |
430 | */ | 430 | */ |
431 | static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss_now) | 431 | int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss_now) |
432 | { | 432 | { |
433 | struct tcp_sock *tp = tcp_sk(sk); | 433 | struct tcp_sock *tp = tcp_sk(sk); |
434 | struct sk_buff *buff; | 434 | struct sk_buff *buff; |
435 | int nsize; | 435 | int nsize, old_factor; |
436 | u16 flags; | 436 | u16 flags; |
437 | 437 | ||
438 | nsize = skb_headlen(skb) - len; | 438 | nsize = skb_headlen(skb) - len; |
@@ -490,18 +490,29 @@ static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned | |||
490 | tp->left_out -= tcp_skb_pcount(skb); | 490 | tp->left_out -= tcp_skb_pcount(skb); |
491 | } | 491 | } |
492 | 492 | ||
493 | old_factor = tcp_skb_pcount(skb); | ||
494 | |||
493 | /* Fix up tso_factor for both original and new SKB. */ | 495 | /* Fix up tso_factor for both original and new SKB. */ |
494 | tcp_set_skb_tso_segs(sk, skb, mss_now); | 496 | tcp_set_skb_tso_segs(sk, skb, mss_now); |
495 | tcp_set_skb_tso_segs(sk, buff, mss_now); | 497 | tcp_set_skb_tso_segs(sk, buff, mss_now); |
496 | 498 | ||
497 | if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) { | 499 | /* If this packet has been sent out already, we must |
498 | tp->lost_out += tcp_skb_pcount(skb); | 500 | * adjust the various packet counters. |
499 | tp->left_out += tcp_skb_pcount(skb); | 501 | */ |
500 | } | 502 | if (after(tp->snd_nxt, TCP_SKB_CB(buff)->end_seq)) { |
503 | int diff = old_factor - tcp_skb_pcount(skb) - | ||
504 | tcp_skb_pcount(buff); | ||
501 | 505 | ||
502 | if (TCP_SKB_CB(buff)->sacked&TCPCB_LOST) { | 506 | tp->packets_out -= diff; |
503 | tp->lost_out += tcp_skb_pcount(buff); | 507 | if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) { |
504 | tp->left_out += tcp_skb_pcount(buff); | 508 | tp->lost_out -= diff; |
509 | tp->left_out -= diff; | ||
510 | } | ||
511 | if (diff > 0) { | ||
512 | tp->fackets_out -= diff; | ||
513 | if ((int)tp->fackets_out < 0) | ||
514 | tp->fackets_out = 0; | ||
515 | } | ||
505 | } | 516 | } |
506 | 517 | ||
507 | /* Link BUFF into the send queue. */ | 518 | /* Link BUFF into the send queue. */ |
@@ -1350,12 +1361,6 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
1350 | if (before(TCP_SKB_CB(skb)->seq, tp->snd_una)) { | 1361 | if (before(TCP_SKB_CB(skb)->seq, tp->snd_una)) { |
1351 | if (before(TCP_SKB_CB(skb)->end_seq, tp->snd_una)) | 1362 | if (before(TCP_SKB_CB(skb)->end_seq, tp->snd_una)) |
1352 | BUG(); | 1363 | BUG(); |
1353 | |||
1354 | if (sk->sk_route_caps & NETIF_F_TSO) { | ||
1355 | sk->sk_route_caps &= ~NETIF_F_TSO; | ||
1356 | sock_set_flag(sk, SOCK_NO_LARGESEND); | ||
1357 | } | ||
1358 | |||
1359 | if (tcp_trim_head(sk, skb, tp->snd_una - TCP_SKB_CB(skb)->seq)) | 1364 | if (tcp_trim_head(sk, skb, tp->snd_una - TCP_SKB_CB(skb)->seq)) |
1360 | return -ENOMEM; | 1365 | return -ENOMEM; |
1361 | } | 1366 | } |
@@ -1370,22 +1375,8 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
1370 | return -EAGAIN; | 1375 | return -EAGAIN; |
1371 | 1376 | ||
1372 | if (skb->len > cur_mss) { | 1377 | if (skb->len > cur_mss) { |
1373 | int old_factor = tcp_skb_pcount(skb); | ||
1374 | int diff; | ||
1375 | |||
1376 | if (tcp_fragment(sk, skb, cur_mss, cur_mss)) | 1378 | if (tcp_fragment(sk, skb, cur_mss, cur_mss)) |
1377 | return -ENOMEM; /* We'll try again later. */ | 1379 | return -ENOMEM; /* We'll try again later. */ |
1378 | |||
1379 | /* New SKB created, account for it. */ | ||
1380 | diff = old_factor - tcp_skb_pcount(skb) - | ||
1381 | tcp_skb_pcount(skb->next); | ||
1382 | tp->packets_out -= diff; | ||
1383 | |||
1384 | if (diff > 0) { | ||
1385 | tp->fackets_out -= diff; | ||
1386 | if ((int)tp->fackets_out < 0) | ||
1387 | tp->fackets_out = 0; | ||
1388 | } | ||
1389 | } | 1380 | } |
1390 | 1381 | ||
1391 | /* Collapse two adjacent packets if worthwhile and we can. */ | 1382 | /* Collapse two adjacent packets if worthwhile and we can. */ |
@@ -1993,12 +1984,6 @@ int tcp_write_wakeup(struct sock *sk) | |||
1993 | TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH; | 1984 | TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH; |
1994 | if (tcp_fragment(sk, skb, seg_size, mss)) | 1985 | if (tcp_fragment(sk, skb, seg_size, mss)) |
1995 | return -1; | 1986 | return -1; |
1996 | /* SWS override triggered forced fragmentation. | ||
1997 | * Disable TSO, the connection is too sick. */ | ||
1998 | if (sk->sk_route_caps & NETIF_F_TSO) { | ||
1999 | sock_set_flag(sk, SOCK_NO_LARGESEND); | ||
2000 | sk->sk_route_caps &= ~NETIF_F_TSO; | ||
2001 | } | ||
2002 | } else if (!tcp_skb_pcount(skb)) | 1987 | } else if (!tcp_skb_pcount(skb)) |
2003 | tcp_set_skb_tso_segs(sk, skb, mss); | 1988 | tcp_set_skb_tso_segs(sk, skb, mss); |
2004 | 1989 | ||