A set of patches merged via the networking pull request for the Linux 6.18 will help servers better cope with distributed denial of service “DDoS” attacks. Thanks to a Google engineer there are some significant optimizations found in the Linux 6.18 kernel code for more efficiently handling of UDP receive performance under stress, such as in DDoS scenarios.
Merged for Linux 6.18 as part of the networking changes is this patch series from Google engineer Eric Dumazet. Dumazet explains there:
“This series is the result of careful analysis of UDP stack, to optimize the receive side, especially when under one or several UDP sockets are receiving a DDOS attack.
I have measured a 47 % increase of throughput when using IPv6 UDP packets with 120 bytes of payload, under DDOS.
16 cpus are receiving traffic targeting a single socket.
Even after adding NUMA aware drop counters, we were suffering from false sharing between packet producers and the consumer.
1) First four patches are shrinking struct ipv6_pinfo size and reorganize fields to get more efficient TX path. They should also benefit TCP, by removing one cache line miss.
2) patches 5 & 6 changes how sk->sk_rmem_alloc is read and updated. They reduce reduce spinlock contention on the busylock.
3) Patches 7 & 8 change the ordering of sk_backlog (including sk_rmem_alloc) sk_receive_queue and sk_drop_counters for better data locality.
4) Patch 9 removes the hashed array of spinlocks in favor of a per-udp-socket one.
5) Final patch adopts skb_attempt_defer_free(), after TCP got good results with it.”
A 47% increase of throughput in this receiving of DDoS scenario!
Eric Dumazet further added in this patch alone being able to process 14.2M more packets per second while under attack on an Intel Xeon Linux server:
“busylock was protecting UDP sockets against packet floods, but unfortunately was not protecting the host itself.
Under stress, many cpus could spin while acquiring the busylock, and NIC had to drop packets. Or packets would be dropped in cpu backlog if RPS/RFS were in place.
This patch replaces the busylock by intermediate lockless queues. (One queue per NUMA node).
This means that fewer number of cpus have to acquire the UDP receive queue lock.
Most of the cpus can either:
– immediately drop the packet.
– or queue it in their NUMA aware lockless queue.Then one of the cpu is chosen to process this lockless queue in a batch.
The batch only contains packets that were cooked on the same NUMA node, thus with very limited latency impact.
Tested:
DDOS targeting a victim UDP socket, on a platform with 6 NUMA nodes (Intel(R) Xeon(R) 6985P-C)
Before:
nstat -n ; sleep 1 ; nstat | grep Udp
Udp6InDatagrams 1004179 0.0
Udp6InErrors 3117 0.0
Udp6RcvbufErrors 3117 0.0After:
nstat -n ; sleep 1 ; nstat | grep Udp
Udp6InDatagrams 1116633 0.0
Udp6InErrors 14197275 0.0
Udp6RcvbufErrors 14197275 0.0We can see this host can now process 14.2 M more packets per second while under attack, and the victim socket can receive 11 % more packets.”
The timing of this work landing for Linux 6.18 is great with this kernel version expected to become this year’s Long Term Support (LTS) kernel version and thus will see a lot of enterprise/server use moving forward.