diff options
-rw-r--r-- | net/ipv4/tcp_output.c | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 8327e5e86d15..0a4cd24b6578 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -887,6 +887,7 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) | |||
887 | { | 887 | { |
888 | struct tcp_sock *tp = tcp_sk(sk); | 888 | struct tcp_sock *tp = tcp_sk(sk); |
889 | struct sk_buff *skb; | 889 | struct sk_buff *skb; |
890 | unsigned int tso_segs, cwnd_quota; | ||
890 | int sent_pkts; | 891 | int sent_pkts; |
891 | 892 | ||
892 | /* If we are closed, the bytes will have to remain here. | 893 | /* If we are closed, the bytes will have to remain here. |
@@ -896,19 +897,31 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) | |||
896 | if (unlikely(sk->sk_state == TCP_CLOSE)) | 897 | if (unlikely(sk->sk_state == TCP_CLOSE)) |
897 | return 0; | 898 | return 0; |
898 | 899 | ||
900 | skb = sk->sk_send_head; | ||
901 | if (unlikely(!skb)) | ||
902 | return 0; | ||
903 | |||
904 | tso_segs = tcp_init_tso_segs(sk, skb); | ||
905 | cwnd_quota = tcp_cwnd_test(tp, skb); | ||
899 | sent_pkts = 0; | 906 | sent_pkts = 0; |
900 | while ((skb = sk->sk_send_head) && | 907 | |
901 | tcp_snd_test(sk, skb, mss_now, | 908 | while (cwnd_quota >= tso_segs) { |
902 | tcp_skb_is_last(sk, skb) ? nonagle : | 909 | if (unlikely(!tcp_nagle_test(tp, skb, mss_now, |
903 | TCP_NAGLE_PUSH)) { | 910 | (tcp_skb_is_last(sk, skb) ? |
904 | if (skb->len > mss_now) { | 911 | nonagle : TCP_NAGLE_PUSH)))) |
905 | if (tcp_fragment(sk, skb, mss_now)) | 912 | break; |
913 | |||
914 | if (unlikely(!tcp_snd_wnd_test(tp, skb, mss_now))) | ||
915 | break; | ||
916 | |||
917 | if (unlikely(skb->len > mss_now)) { | ||
918 | if (unlikely(tcp_fragment(sk, skb, mss_now))) | ||
906 | break; | 919 | break; |
907 | } | 920 | } |
908 | 921 | ||
909 | TCP_SKB_CB(skb)->when = tcp_time_stamp; | 922 | TCP_SKB_CB(skb)->when = tcp_time_stamp; |
910 | tcp_tso_set_push(skb); | 923 | tcp_tso_set_push(skb); |
911 | if (tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC))) | 924 | if (unlikely(tcp_transmit_skb(sk, skb_clone(skb, GFP_ATOMIC)))) |
912 | break; | 925 | break; |
913 | 926 | ||
914 | /* Advance the send_head. This one is sent out. | 927 | /* Advance the send_head. This one is sent out. |
@@ -917,10 +930,19 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle) | |||
917 | update_send_head(sk, tp, skb); | 930 | update_send_head(sk, tp, skb); |
918 | 931 | ||
919 | tcp_minshall_update(tp, mss_now, skb); | 932 | tcp_minshall_update(tp, mss_now, skb); |
920 | sent_pkts = 1; | 933 | sent_pkts++; |
934 | |||
935 | /* Do not optimize this to use tso_segs. If we chopped up | ||
936 | * the packet above, tso_segs will no longer be valid. | ||
937 | */ | ||
938 | cwnd_quota -= tcp_skb_pcount(skb); | ||
939 | skb = sk->sk_send_head; | ||
940 | if (!skb) | ||
941 | break; | ||
942 | tso_segs = tcp_init_tso_segs(sk, skb); | ||
921 | } | 943 | } |
922 | 944 | ||
923 | if (sent_pkts) { | 945 | if (likely(sent_pkts)) { |
924 | tcp_cwnd_validate(sk, tp); | 946 | tcp_cwnd_validate(sk, tp); |
925 | return 0; | 947 | return 0; |
926 | } | 948 | } |