How to disable TCP slow start in Linux?
On Linux platforms the SSR setting can be checked and disabled via the following commands:
$> sysctl net.ipv4.tcp_slow_start_after_idle
$> sysctl -w net.ipv4.tcp_slow_start_after_idle=0
Slow start is also used after a connection has been idle, unless this behavior is disabled in
/proc/sys/net/ipv4/tcp_slow_start_after_idle.
Mitigating TCP slow start in web applications
One of the most simple answers is to check that HTTP/1.1 keep alive is enabled, I guess. Server shouldn't send Connection: close
header. This will allow browser to use limited number of TCP connections to request resources. Those connections TCP congestion window will grow allowing further requests to use LTE bandwidth more effectively.
More advanced solutions would be to use HTTP/2 which doesn't have such violent limitations on request pipelining. A lot of data could be easily pipelined in one connection.
TCP Slow Start Term Confusion
Early (very early) implementations didn't use a congestion window. So they started very hard by sending a full receiver-window of data. Thus, aggressive as it may seem, slow-start is actually more conservative.
Unusually slow TCP-connection in Linux
I'm not really sure this is exactly your case, but it looks similar. Seems that it's a known problem.
Reasons
A number of circumstances can lead to such Linux kernel behavior:
- Specificity of kernel connection handling in SYN-cookies context with connections having zero Window Scale (or if WS modified in some other way).
- Zero Window Scale you provoked by
setsockopt()
withSO_RCVBUF
(seetcp_select_initial_window()
) - Extremely small
backlog
Explanation
About "slow" transmission:
The Windows Scaling option is calculated at [SYN - SYN+ACK] stage by both hosts. Roughly speaking Host A says "imply my TCP window size on N during future exchange" (SYN) then Host B says "imply my TCP window size on M during future exchange" (SYN+ACK) - here N and M could be th same. So, in a normal situation, these coefficients are stored and eventually used while data exchange.
But TCP SYN-cookies technique implies forgetfulness about [SYN - SYN+ACK] stage of connection (some stated options including WS will be lost after SYN+ACK). In that case Linux kernel re-calculates WS value when ACK arrives (if the ACK has arrived, then creating a regular connection is needed). But that second recalculation could be a bit different because setsockopt()
does not affect it (for some objective reasons). Here you face with situation, when your server sends zero Window Scale option with SYN+ACK, then forgets about it, then re-spawn connection (when ACK arrives) as it was with some default Window Scale (e.g. 7) and use little window implying that client will multiply it by 128. But client doesn't forget that WS is 0 and treats little window size as real - hence it send a little portions of data - hereby your "slow" connection takes the stage.
About SYN-flood:
When you have such a little backlog an simple 3 SYN-retransmits can provoke SYN-cookies (i.e. will fill in your backlog queue). BTW do you see retransmissions in tcpdump?
From ip-sysctl.txt:
Note, that syncookies is fallback facility.
It MUST NOT be used to help highly loaded servers to stand
against legal connection rate. If you see SYN flood warnings
in your logs, but investigation shows that they occur
because of overload with legal connections, you should tune
another parameters until this warning disappear.
See: tcp_max_syn_backlog, tcp_synack_retries, tcp_abort_on_overflow.
syncookies seriously violate TCP protocol, do not allow
to use TCP extensions, can result in serious degradation
of some services (f.e. SMTP relaying), visible not by you,
but your clients and relays, contacting you. While you see
SYN flood warnings in logs not being really flooded, your server
is seriously misconfigured.
So if there are no SYN-flood attacks in your LAN - your server is seriously misconfigured. SYN-cookies should do its job only when SYN-flood attack is present.
Solution
Concluding, there can be some activities to eliminate the problem:
- If there is a real SYN-flood in your network - SYN-cookies partially
solve this information security issue. With a real attack, there’s
no time to think about slow connections. This is an emergency. - If nope, i.e. some SYN-retransmissions provoked SYN-cookies:
- thoughtfully increase backlog to eliminate such conditions;
- don't do
setsockopt()
withSO_RCVBUF
on listening socket. It doesn't make much sense. Without doingsetsockopt()
you can reduce the probability of different WS calculations by kernel in mentioned scenario. Btw you can setSO_RCVBUF
on accepted socket if needed.
Repro
I reproduced your problem with simple client and server with hping3
under approximate conditions. So you can stuff server's backlog queue with:
hping3 -c 3 -S -p 12345 --fast 10.0.0.99
then initiate connection from client - the connection will be opened in the so-called "SYN-cookies context" at least on 4.4 kernel. You can also check it on 3.10 kernel increasing -c
from 3
to X
up to successful reproduction.
Why is the initial phase in TCP congestion control called slow start?
Slow start was introduced in 1988*. It was called "slow start" because it was slower than the prior approach which was simply blasting packets out without considering the congestion.
Congestion Avoidance and Control by Van Jacobson and Michael J. Karels
Related Topics
While Using Printf How to Escape Special Characters in Shell Script
How to Check If Linux Console Screensaver Has Blanked Screen
Systemd/Udev Dependency Failure When Auto Mounting Separate Partition During Startup
Terminal "Png" Missing When Using Gnuplot
How to Add a Ssh Key to Remote Server
Base Address at Which The Linux Kernel Is Loaded
How to Install Docker 1.9+ in Centos 6.5
How to Speed Up a Video by Dropping Frames
What Are Best Parameters to Run Imagemagick to Convert Low Quality PDF to Images (For Ocr)
What's The Meaning of 'C' in Result of Command "Ls -L /Dev/Tty'
Command-Line Fulltext Indexing
Drop/Rewrite/Generate Keyboard Events Under Linux
Linux Bash Script Get User Input and Store in a Array
Sed Only The Last Match Pattern
How to Log Messages from an ASP.NET Core Application to a Specific File on Linux