Huge CPU load under large amount of TCP connections
Under a large amount of TCP connections, one CPU core will always go up to 100%. After that happens, the whole VM would start lagging and there will be an evident packet loss.
Is there a way to solve it, make TCP connections use less CPU, or even rate limit it?
NOTE: Rate-Limiting via iptables will not work. Tried the following:
iptables -A INPUT -i eth0 -m state --state NEW -p tcp -m limit --limit 30/minute --dport 25565 -j ACCEPT
iptables -A INPUT -i eth0 -m state --state NEW -p tcp --dport 25565 -j DROP
Note that even dropping the port with iptables -A INPUT -p tcp --dport 25565 -j DROP
will not work.
Under htop, I can't see what process is taking the CPU, so my suppose it's something with Kernel. Some hosting providers like OVH have this solved, but under many others, it happens. What are my options?
Best Regards
I do not think your issue is in the kernel, nor do I think your compute bottleneck is related to your network stuff, depending on your hardware.
I did the following experiment:
Server computer 1: use hping3 to generate SYN packets at a rate of 28,870 per second (derived by experiment, and thought to be close enough to what you are doing) to port 25565 on server computer 2. Command used:
$ sudo /usr/sbin/hping3 -p 25565 --syn --interval u20 s19
Where "s19" is server computer 2, and "u20" has overheads and actually results is 28,870 packets per second instead of 50,000.
Server computer 2: has the one iptables DROP rule. Turbostat was also run to observe power and CPU loads. These commands were run:
doug@s19:~/tmp$ sudo iptables -xvnL ; sleep 10 ; sudo iptables -xvnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
2293479 91739160 DROP tcp -- br0 * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:25565
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
2582175 103287000 DROP tcp -- br0 * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:25565
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
So 2582175 - 2293479 = 288,696 packets in 10 seconds or 28,870/second. Note: I do have less bytes per packet than you, at 40, whereas you seem to have 60.
$ sudo turbostat --Summary --quiet --show Busy%,Bzy_MHz,IRQ,PkgWatt,PkgTmp,RAMWatt,GFXWatt,CorWatt --interval 6
Busy% Bzy_MHz IRQ PkgTmp PkgWatt CorWatt GFXWatt RAMWatt
0.61 4800 196262 38 17.91 17.25 0.00 0.89
0.61 4800 196844 38 17.95 17.29 0.00 0.89
0.60 4800 197409 39 18.01 17.35 0.00 0.89
Negligible CPU utilization, but about 16 more watts used than idle (idle = 1.5 watts).
Desktop computer 1: A qemu/kvm virtual 20.04 machine running as a guest on server computer 2.
The server computer 1 hping3 command becomes:
$ sudo /usr/sbin/hping3 -p 25565 --syn --interval u20 192.168.111.19
And the results are:
doug@desk-ff:~$ sudo iptables -xvnL ; sleep 100 ; sudo iptables -xvnL
Chain INPUT (policy ACCEPT 117 packets, 9384 bytes)
pkts bytes target prot opt in out source destination
2086906 83476240 DROP tcp -- enp1s0 * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:25565
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 73 packets, 9116 bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 144 packets, 12151 bytes)
pkts bytes target prot opt in out source destination
4970267 198810680 DROP tcp -- enp1s0 * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:25565
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 77 packets, 9996 bytes)
pkts bytes target prot opt in out source destination
So, 4970267 - 2086906 = 288,361 packets in 100 seconds or 28,834/second.
and on the host computer:
$ sudo turbostat --Summary --quiet --show Busy%,Bzy_MHz,IRQ,PkgWatt,PkgTmp,RAMWatt,GFXWatt,CorWatt --interval 6
Busy% Bzy_MHz IRQ PkgTmp PkgWatt CorWatt GFXWatt RAMWatt
9.61 4800 207685 58 31.19 30.53 0.00 0.89
9.64 4800 211088 58 31.14 30.48 0.00 0.89
9.44 4800 202499 59 30.72 30.07 0.00 0.89
I have 12 CPUs, so the utilization is greater than 100% of 1 CPU. Or via top:
top - 11:58:16 up 10 days, 18:57, 2 users, load average: 1.00, 0.99, 0.81
Tasks: 239 total, 1 running, 238 sleeping, 0 stopped, 0 zombie
%Cpu0 : 0.3 us, 0.0 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu2 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu3 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu4 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu5 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu6 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu7 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu8 : 0.0 us, 0.0 sy, 0.0 ni, 98.3 id, 0.0 wa, 0.0 hi, 1.7 si, 0.0 st
%Cpu9 : 0.0 us, 3.1 sy, 0.0 ni, 95.6 id, 0.0 wa, 0.0 hi, 1.4 si, 0.0 st
%Cpu10 : 8.3 us, 90.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 1.3 si, 0.0 st
%Cpu11 : 0.0 us, 0.0 sy, 0.0 ni, 98.3 id, 0.0 wa, 0.0 hi, 1.7 si, 0.0 st
So, yes that you are doing this in a VM seems to consume a lot more CPU resources. One option is don't do this in a VM. Or, assign more VCPUs to the VM. I was able to get to 118,283 packets per second ("u1" hping3 interval option), with only a couple of percent increase in overall CPU utilization on the host.
EDIT: Host processor utilization verses packets per second to the VM is rather interesting with a step function type response between 5000 and 6000 pps (recall that 8.33% is 100% of 1 CPU for this 12 CPU host):