diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/tcp_output.c | 86 |
1 files changed, 35 insertions, 51 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index e3f8ea1bfa9c..7d076f0db100 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -403,11 +403,9 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb) | |||
403 | sk->sk_send_head = skb; | 403 | sk->sk_send_head = skb; |
404 | } | 404 | } |
405 | 405 | ||
406 | static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb) | 406 | static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned int mss_now) |
407 | { | 407 | { |
408 | struct tcp_sock *tp = tcp_sk(sk); | 408 | if (skb->len <= mss_now || |
409 | |||
410 | if (skb->len <= tp->mss_cache || | ||
411 | !(sk->sk_route_caps & NETIF_F_TSO)) { | 409 | !(sk->sk_route_caps & NETIF_F_TSO)) { |
412 | /* Avoid the costly divide in the normal | 410 | /* Avoid the costly divide in the normal |
413 | * non-TSO case. | 411 | * non-TSO case. |
@@ -417,10 +415,10 @@ static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb) | |||
417 | } else { | 415 | } else { |
418 | unsigned int factor; | 416 | unsigned int factor; |
419 | 417 | ||
420 | factor = skb->len + (tp->mss_cache - 1); | 418 | factor = skb->len + (mss_now - 1); |
421 | factor /= tp->mss_cache; | 419 | factor /= mss_now; |
422 | skb_shinfo(skb)->tso_segs = factor; | 420 | skb_shinfo(skb)->tso_segs = factor; |
423 | skb_shinfo(skb)->tso_size = tp->mss_cache; | 421 | skb_shinfo(skb)->tso_size = mss_now; |
424 | } | 422 | } |
425 | } | 423 | } |
426 | 424 | ||
@@ -429,7 +427,7 @@ static void tcp_set_skb_tso_segs(struct sock *sk, struct sk_buff *skb) | |||
429 | * packet to the list. This won't be called frequently, I hope. | 427 | * packet to the list. This won't be called frequently, I hope. |
430 | * Remember, these are still headerless SKBs at this point. | 428 | * Remember, these are still headerless SKBs at this point. |
431 | */ | 429 | */ |
432 | static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len) | 430 | static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss_now) |
433 | { | 431 | { |
434 | struct tcp_sock *tp = tcp_sk(sk); | 432 | struct tcp_sock *tp = tcp_sk(sk); |
435 | struct sk_buff *buff; | 433 | struct sk_buff *buff; |
@@ -492,8 +490,8 @@ static int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len) | |||
492 | } | 490 | } |
493 | 491 | ||
494 | /* Fix up tso_factor for both original and new SKB. */ | 492 | /* Fix up tso_factor for both original and new SKB. */ |
495 | tcp_set_skb_tso_segs(sk, skb); | 493 | tcp_set_skb_tso_segs(sk, skb, mss_now); |
496 | tcp_set_skb_tso_segs(sk, buff); | 494 | tcp_set_skb_tso_segs(sk, buff, mss_now); |
497 | 495 | ||
498 | if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) { | 496 | if (TCP_SKB_CB(skb)->sacked & TCPCB_LOST) { |
499 | tp->lost_out += tcp_skb_pcount(skb); | 497 | tp->lost_out += tcp_skb_pcount(skb); |
@@ -569,7 +567,7 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) | |||
569 | * factor and mss. | 567 | * factor and mss. |
570 | */ | 568 | */ |
571 | if (tcp_skb_pcount(skb) > 1) | 569 | if (tcp_skb_pcount(skb) > 1) |
572 | tcp_set_skb_tso_segs(sk, skb); | 570 | tcp_set_skb_tso_segs(sk, skb, tcp_current_mss(sk, 1)); |
573 | 571 | ||
574 | return 0; | 572 | return 0; |
575 | } | 573 | } |
@@ -734,12 +732,14 @@ static inline unsigned int tcp_cwnd_test(struct tcp_sock *tp, struct sk_buff *sk | |||
734 | /* This must be invoked the first time we consider transmitting | 732 | /* This must be invoked the first time we consider transmitting |
735 | * SKB onto the wire. | 733 | * SKB onto the wire. |
736 | */ | 734 | */ |
737 | static inline int tcp_init_tso_segs(struct sock *sk, struct sk_buff *skb) | 735 | static inline int tcp_init_tso_segs(struct sock *sk, struct sk_buff *skb, unsigned int mss_now) |
738 | { | 736 | { |
739 | int tso_segs = tcp_skb_pcount(skb); | 737 | int tso_segs = tcp_skb_pcount(skb); |
740 | 738 | ||
741 | if (!tso_segs) { | 739 | if (!tso_segs || |
742 | tcp_set_skb_tso_segs(sk, skb); | 740 | (tso_segs > 1 && |
741 | skb_shinfo(skb)->tso_size != mss_now)) { | ||
742 | tcp_set_skb_tso_segs(sk, skb, mss_now); | ||
743 | tso_segs = tcp_skb_pcount(skb); | 743 | tso_segs = tcp_skb_pcount(skb); |
744 | } | 744 | } |
745 | return tso_segs; | 745 | return tso_segs; |
@@ -817,7 +817,7 @@ static unsigned int tcp_snd_test(struct sock *sk, struct sk_buff *skb, | |||
817 | struct tcp_sock *tp = tcp_sk(sk); | 817 | struct tcp_sock *tp = tcp_sk(sk); |
818 | unsigned int cwnd_quota; | 818 | unsigned int cwnd_quota; |
819 | 819 | ||
820 | tcp_init_tso_segs(sk, skb); | 820 | tcp_init_tso_segs(sk, skb, cur_mss); |
821 | 821 | ||
822 | if (!tcp_nagle_test(tp, skb, cur_mss, nonagle)) | 822 | if (!tcp_nagle_test(tp, skb, cur_mss, nonagle)) |
823 | return 0; | 823 | return 0; |
@@ -854,7 +854,7 @@ int tcp_may_send_now(struct sock *sk, struct tcp_sock *tp) | |||
854 | * know that all the data is in scatter-gather pages, and that the | 854 | * know that all the data is in scatter-gather pages, and that the |
855 | * packet has never been sent out before (and thus is not cloned). | 855 | * packet has never been sent out before (and thus is not cloned). |
856 | */ | 856 | */ |
857 | static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len) | 857 | static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len, unsigned int mss_now) |
858 | { | 858 | { |
859 | struct sk_buff *buff; | 859 | struct sk_buff *buff; |
860 | int nlen = skb->len - len; | 860 | int nlen = skb->len - len; |
@@ -887,8 +887,8 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len) | |||
887 | skb_split(skb, buff, len); | 887 | skb_split(skb, buff, len); |
888 | 888 | ||
889 | /* Fix up tso_factor for both original and new SKB. */ | 889 | /* Fix up tso_factor for both original and new SKB. */ |
890 | tcp_set_skb_tso_segs(sk, skb); | 890 | tcp_set_skb_tso_segs(sk, skb, mss_now); |
891 | tcp_set_skb_tso_segs(sk, buff); | 891 | tcp_set_skb_tso_segs(sk, buff, mss_now); |
892 | 892 | ||
893 | /* Link BUFF into the send queue. */ | 893 | /* Link BUFF into the send queue. */ |
894 | skb_header_release(buff); | 894 | skb_header_release(buff); |
@@ -972,19 +972,18 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) | |||
972 | if (unlikely(sk->sk_state == TCP_CLOSE)) | 972 | if (unlikely(sk->sk_state == TCP_CLOSE)) |
973 | return 0; | 973 | return 0; |
974 | 974 | ||
975 | skb = sk->sk_send_head; | ||
976 | if (unlikely(!skb)) | ||
977 | return 0; | ||
978 | |||
979 | tso_segs = tcp_init_tso_segs(sk, skb); | ||
980 | cwnd_quota = tcp_cwnd_test(tp, skb); | ||
981 | if (unlikely(!cwnd_quota)) | ||
982 | goto out; | ||
983 | |||
984 | sent_pkts = 0; | 975 | sent_pkts = 0; |
985 | while (likely(tcp_snd_wnd_test(tp, skb, mss_now))) { | 976 | while ((skb = sk->sk_send_head)) { |
977 | tso_segs = tcp_init_tso_segs(sk, skb, mss_now); | ||
986 | BUG_ON(!tso_segs); | 978 | BUG_ON(!tso_segs); |
987 | 979 | ||
980 | cwnd_quota = tcp_cwnd_test(tp, skb); | ||
981 | if (!cwnd_quota) | ||
982 | break; | ||
983 | |||
984 | if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now))) | ||
985 | break; | ||
986 | |||
988 | if (tso_segs == 1) { | 987 | if (tso_segs == 1) { |
989 | if (unlikely(!tcp_nagle_test(tp, skb, mss_now, | 988 | if (unlikely(!tcp_nagle_test(tp, skb, mss_now, |
990 | (tcp_skb_is_last(sk, skb) ? | 989 | (tcp_skb_is_last(sk, skb) ? |
@@ -1006,11 +1005,11 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) | |||
1006 | limit = skb->len - trim; | 1005 | limit = skb->len - trim; |
1007 | } | 1006 | } |
1008 | if (skb->len > limit) { | 1007 | if (skb->len > limit) { |
1009 | if (tso_fragment(sk, skb, limit)) | 1008 | if (tso_fragment(sk, skb, limit, mss_now)) |
1010 | break; | 1009 | break; |
1011 | } | 1010 | } |
1012 | } else if (unlikely(skb->len > mss_now)) { | 1011 | } else if (unlikely(skb->len > mss_now)) { |
1013 | if (unlikely(tcp_fragment(sk, skb, mss_now))) | 1012 | if (unlikely(tcp_fragment(sk, skb, mss_now, mss_now))) |
1014 | break; | 1013 | break; |
1015 | } | 1014 | } |
1016 | 1015 | ||
@@ -1026,27 +1025,12 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) | |||
1026 | 1025 | ||
1027 | tcp_minshall_update(tp, mss_now, skb); | 1026 | tcp_minshall_update(tp, mss_now, skb); |
1028 | sent_pkts++; | 1027 | sent_pkts++; |
1029 | |||
1030 | /* Do not optimize this to use tso_segs. If we chopped up | ||
1031 | * the packet above, tso_segs will no longer be valid. | ||
1032 | */ | ||
1033 | cwnd_quota -= tcp_skb_pcount(skb); | ||
1034 | |||
1035 | BUG_ON(cwnd_quota < 0); | ||
1036 | if (!cwnd_quota) | ||
1037 | break; | ||
1038 | |||
1039 | skb = sk->sk_send_head; | ||
1040 | if (!skb) | ||
1041 | break; | ||
1042 | tso_segs = tcp_init_tso_segs(sk, skb); | ||
1043 | } | 1028 | } |
1044 | 1029 | ||
1045 | if (likely(sent_pkts)) { | 1030 | if (likely(sent_pkts)) { |
1046 | tcp_cwnd_validate(sk, tp); | 1031 | tcp_cwnd_validate(sk, tp); |
1047 | return 0; | 1032 | return 0; |
1048 | } | 1033 | } |
1049 | out: | ||
1050 | return !tp->packets_out && sk->sk_send_head; | 1034 | return !tp->packets_out && sk->sk_send_head; |
1051 | } | 1035 | } |
1052 | 1036 | ||
@@ -1076,7 +1060,7 @@ void tcp_push_one(struct sock *sk, unsigned int mss_now) | |||
1076 | 1060 | ||
1077 | BUG_ON(!skb || skb->len < mss_now); | 1061 | BUG_ON(!skb || skb->len < mss_now); |
1078 | 1062 | ||
1079 | tso_segs = tcp_init_tso_segs(sk, skb); | 1063 | tso_segs = tcp_init_tso_segs(sk, skb, mss_now); |
1080 | cwnd_quota = tcp_snd_test(sk, skb, mss_now, TCP_NAGLE_PUSH); | 1064 | cwnd_quota = tcp_snd_test(sk, skb, mss_now, TCP_NAGLE_PUSH); |
1081 | 1065 | ||
1082 | if (likely(cwnd_quota)) { | 1066 | if (likely(cwnd_quota)) { |
@@ -1093,11 +1077,11 @@ void tcp_push_one(struct sock *sk, unsigned int mss_now) | |||
1093 | limit = skb->len - trim; | 1077 | limit = skb->len - trim; |
1094 | } | 1078 | } |
1095 | if (skb->len > limit) { | 1079 | if (skb->len > limit) { |
1096 | if (unlikely(tso_fragment(sk, skb, limit))) | 1080 | if (unlikely(tso_fragment(sk, skb, limit, mss_now))) |
1097 | return; | 1081 | return; |
1098 | } | 1082 | } |
1099 | } else if (unlikely(skb->len > mss_now)) { | 1083 | } else if (unlikely(skb->len > mss_now)) { |
1100 | if (unlikely(tcp_fragment(sk, skb, mss_now))) | 1084 | if (unlikely(tcp_fragment(sk, skb, mss_now, mss_now))) |
1101 | return; | 1085 | return; |
1102 | } | 1086 | } |
1103 | 1087 | ||
@@ -1388,7 +1372,7 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
1388 | int old_factor = tcp_skb_pcount(skb); | 1372 | int old_factor = tcp_skb_pcount(skb); |
1389 | int new_factor; | 1373 | int new_factor; |
1390 | 1374 | ||
1391 | if (tcp_fragment(sk, skb, cur_mss)) | 1375 | if (tcp_fragment(sk, skb, cur_mss, cur_mss)) |
1392 | return -ENOMEM; /* We'll try again later. */ | 1376 | return -ENOMEM; /* We'll try again later. */ |
1393 | 1377 | ||
1394 | /* New SKB created, account for it. */ | 1378 | /* New SKB created, account for it. */ |
@@ -1991,7 +1975,7 @@ int tcp_write_wakeup(struct sock *sk) | |||
1991 | skb->len > mss) { | 1975 | skb->len > mss) { |
1992 | seg_size = min(seg_size, mss); | 1976 | seg_size = min(seg_size, mss); |
1993 | TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH; | 1977 | TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH; |
1994 | if (tcp_fragment(sk, skb, seg_size)) | 1978 | if (tcp_fragment(sk, skb, seg_size, mss)) |
1995 | return -1; | 1979 | return -1; |
1996 | /* SWS override triggered forced fragmentation. | 1980 | /* SWS override triggered forced fragmentation. |
1997 | * Disable TSO, the connection is too sick. */ | 1981 | * Disable TSO, the connection is too sick. */ |
@@ -2000,7 +1984,7 @@ int tcp_write_wakeup(struct sock *sk) | |||
2000 | sk->sk_route_caps &= ~NETIF_F_TSO; | 1984 | sk->sk_route_caps &= ~NETIF_F_TSO; |
2001 | } | 1985 | } |
2002 | } else if (!tcp_skb_pcount(skb)) | 1986 | } else if (!tcp_skb_pcount(skb)) |
2003 | tcp_set_skb_tso_segs(sk, skb); | 1987 | tcp_set_skb_tso_segs(sk, skb, mss); |
2004 | 1988 | ||
2005 | TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH; | 1989 | TCP_SKB_CB(skb)->flags |= TCPCB_FLAG_PSH; |
2006 | TCP_SKB_CB(skb)->when = tcp_time_stamp; | 1990 | TCP_SKB_CB(skb)->when = tcp_time_stamp; |