| From ef640efee8b476c5c600854ce26891d68f6b4d05 Mon Sep 17 00:00:00 2001 |
| From: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> |
| Date: Wed, 15 Sep 2010 10:27:52 -0700 |
| Subject: tcp: Prevent overzealous packetization by SWS logic. |
| |
| |
| From: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> |
| |
| [ Upstream commit 01f83d69844d307be2aa6fea88b0e8fe5cbdb2f4 ] |
| |
| If peer uses tiny MSS (say, 75 bytes) and similarly tiny advertised |
| window, the SWS logic will packetize to half the MSS unnecessarily. |
| |
| This causes problems with some embedded devices. |
| |
| However for large MSS devices we do want to half-MSS packetize |
| otherwise we never get enough packets into the pipe for things |
| like fast retransmit and recovery to work. |
| |
| Be careful also to handle the case where MSS > window, otherwise |
| we'll never send until the probe timer. |
| |
| Reported-by: ツ Leandro Melo de Sales <leandroal@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| --- |
| include/net/tcp.h | 18 ++++++++++++++++-- |
| 1 file changed, 16 insertions(+), 2 deletions(-) |
| |
| --- a/include/net/tcp.h |
| +++ b/include/net/tcp.h |
| @@ -511,8 +511,22 @@ extern unsigned int tcp_current_mss(stru |
| /* Bound MSS / TSO packet size with the half of the window */ |
| static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize) |
| { |
| - if (tp->max_window && pktsize > (tp->max_window >> 1)) |
| - return max(tp->max_window >> 1, 68U - tp->tcp_header_len); |
| + int cutoff; |
| + |
| + /* When peer uses tiny windows, there is no use in packetizing |
| + * to sub-MSS pieces for the sake of SWS or making sure there |
| + * are enough packets in the pipe for fast recovery. |
| + * |
| + * On the other hand, for extremely large MSS devices, handling |
| + * smaller than MSS windows in this way does make sense. |
| + */ |
| + if (tp->max_window >= 512) |
| + cutoff = (tp->max_window >> 1); |
| + else |
| + cutoff = tp->max_window; |
| + |
| + if (cutoff && pktsize > cutoff) |
| + return max_t(int, cutoff, 68U - tp->tcp_header_len); |
| else |
| return pktsize; |
| } |