diff options
-rw-r--r-- | include/linux/tcp.h | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 20 |
2 files changed, 17 insertions, 5 deletions
diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 0e058a2d1c6d..2d36f6db3706 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h | |||
@@ -342,6 +342,8 @@ struct tcp_sock { | |||
342 | 342 | ||
343 | unsigned long last_synq_overflow; | 343 | unsigned long last_synq_overflow; |
344 | 344 | ||
345 | __u32 tso_deferred; | ||
346 | |||
345 | /* Receiver side RTT estimation */ | 347 | /* Receiver side RTT estimation */ |
346 | struct { | 348 | struct { |
347 | __u32 rtt; | 349 | __u32 rtt; |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index f22536e32cb1..ca406157724c 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -1096,10 +1096,14 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ | |||
1096 | u32 send_win, cong_win, limit, in_flight; | 1096 | u32 send_win, cong_win, limit, in_flight; |
1097 | 1097 | ||
1098 | if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) | 1098 | if (TCP_SKB_CB(skb)->flags & TCPCB_FLAG_FIN) |
1099 | return 0; | 1099 | goto send_now; |
1100 | 1100 | ||
1101 | if (icsk->icsk_ca_state != TCP_CA_Open) | 1101 | if (icsk->icsk_ca_state != TCP_CA_Open) |
1102 | return 0; | 1102 | goto send_now; |
1103 | |||
1104 | /* Defer for less than two clock ticks. */ | ||
1105 | if (!tp->tso_deferred && ((jiffies<<1)>>1) - (tp->tso_deferred>>1) > 1) | ||
1106 | goto send_now; | ||
1103 | 1107 | ||
1104 | in_flight = tcp_packets_in_flight(tp); | 1108 | in_flight = tcp_packets_in_flight(tp); |
1105 | 1109 | ||
@@ -1115,7 +1119,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ | |||
1115 | 1119 | ||
1116 | /* If a full-sized TSO skb can be sent, do it. */ | 1120 | /* If a full-sized TSO skb can be sent, do it. */ |
1117 | if (limit >= 65536) | 1121 | if (limit >= 65536) |
1118 | return 0; | 1122 | goto send_now; |
1119 | 1123 | ||
1120 | if (sysctl_tcp_tso_win_divisor) { | 1124 | if (sysctl_tcp_tso_win_divisor) { |
1121 | u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache); | 1125 | u32 chunk = min(tp->snd_wnd, tp->snd_cwnd * tp->mss_cache); |
@@ -1125,7 +1129,7 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ | |||
1125 | */ | 1129 | */ |
1126 | chunk /= sysctl_tcp_tso_win_divisor; | 1130 | chunk /= sysctl_tcp_tso_win_divisor; |
1127 | if (limit >= chunk) | 1131 | if (limit >= chunk) |
1128 | return 0; | 1132 | goto send_now; |
1129 | } else { | 1133 | } else { |
1130 | /* Different approach, try not to defer past a single | 1134 | /* Different approach, try not to defer past a single |
1131 | * ACK. Receiver should ACK every other full sized | 1135 | * ACK. Receiver should ACK every other full sized |
@@ -1133,11 +1137,17 @@ static int tcp_tso_should_defer(struct sock *sk, struct tcp_sock *tp, struct sk_ | |||
1133 | * then send now. | 1137 | * then send now. |
1134 | */ | 1138 | */ |
1135 | if (limit > tcp_max_burst(tp) * tp->mss_cache) | 1139 | if (limit > tcp_max_burst(tp) * tp->mss_cache) |
1136 | return 0; | 1140 | goto send_now; |
1137 | } | 1141 | } |
1138 | 1142 | ||
1139 | /* Ok, it looks like it is advisable to defer. */ | 1143 | /* Ok, it looks like it is advisable to defer. */ |
1144 | tp->tso_deferred = 1 | (jiffies<<1); | ||
1145 | |||
1140 | return 1; | 1146 | return 1; |
1147 | |||
1148 | send_now: | ||
1149 | tp->tso_deferred = 0; | ||
1150 | return 0; | ||
1141 | } | 1151 | } |
1142 | 1152 | ||
1143 | /* Create a new MTU probe if we are ready. | 1153 | /* Create a new MTU probe if we are ready. |