How to Adjust the TCP Window Size Limit on Linux is one of the most popular post on the NetBeez blog. Since we definitely hit a nerve with this topic, I wanted to enhance it by adding a step-by-step video to it as well. Below you’ll find the original blog post and a new “how-to” video. Enjoy!
What affects iPerf throughput?
The maximum bandwidth that iPerf can push between a source and a destination depends on many factors. To name a few:
- Interface: if you are using a Raspberry Pi that has a 10/100 interface, then the upper limit is 100 Mbps.
- CPU capabilities: pushing several Gbps of traffic needs quite a bit of CPU performance.
- Latency: the greater the latency between source and destination, the larger the TCP window size needs to be.
The interface and the CPU put hard limits on the maximum bandwidth you can achieve. You can’t bypass them unless you get new hardware.
However, given your link’s latency, you can adjust the TCP window size in order to achieve the desired bandwidth. But it can be tricky…
How to calculate maximum achievable TCP throughput
The maximum achievable throughput is equal to:
[TCP Window Size in bits] / [Latency in seconds] = [Throughput in bits per second]
The default window size that iPerf uses varies by machine type and operating system. If it’s 64 KBytes, with a modest latency of 10 ms, the maximum bandwidth you can get is 52.43 Mbits/sec. For 500 ms the maximum is 524 Kbits/sec.
The obvious option would be to increase the window size to a larger value and get up to, let’s say, 500 Mbps. For a 50 ms latency, the window size needs to be 3.1 Mbytes.
Indeed, iPerf gives you the option to set the window size, but if you try to set it to 3.1 or 8.0 Mbytes you may get the following warning from iPerf:
“TCP window size: 250 KByte (WARNING: requested 8.00 MByte)”
Oops… Why didn’t iPerf follow your command and used only a 250 Kbyte window?
The devil is in the details!
In this case, the devil is the operating system that has a hard limit on the TCP window size that an application can use. It looks like in this case the limit is 250 Kbytes. These limits exist for good reasons. Larger TCP windows take more system memory and if you have multiple applications running, using large windows they may bog down the system. Or the system may deny TCP connections if it is running out of memory.
In your case, if you have full control of the system and you know what you are doing, you may want to increase the OS limits. As an example, to increase those limits to 8 MBytes, run the following commands as root on a Debian Linux machine:
echo 'net.core.wmem_max=4194304' >> /etc/sysctl.conf
echo 'net.core.rmem_max=12582912' >> /etc/sysctl.conf
echo 'net.ipv4.tcp_rmem = 4096 87380 4194304' >> /etc/sysctl.conf
echo 'net.ipv4.tcp_wmem = 4096 87380 4194304' >> /etc/sysctl.conf
Now if you request iPerf to use a 4 Mbyte TCP window size, you will see that your request will get fulfilled like it’s supposed to!