====== ksoftirqd process utilizes 100% of a CPU ======
Linux esegue diversi processi per gestire le soft IRQ, uno per ogni CPU presente. Ecco un esempio su una CPU con 4 core:
ps uax | grep ksoftirqd | grep -v grep
root 14 0.0 0.0 0 0 ? S Nov07 0:00 [ksoftirqd/0]
root 21 1.4 0.0 0 0 ? S Nov07 21:43 [ksoftirqd/1]
root 26 0.0 0.0 0 0 ? S Nov07 0:03 [ksoftirqd/2]
root 31 0.0 0.0 0 0 ? S Nov07 0:00 [ksoftirqd/3]
Come si vede uno di questi processi (PID 21) consuma molti cicli di CPU più degli altri (TIME 21:43). Il processo è associato alla **CPU #1** [ksoftirqd/1].
Ispezionando lo pseduofile **/proc/interrupts** si può vedere chi è che genera molte interrupt sulla **CPU1**:
cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
0: 19 0 0 0 IR-IO-APIC 2-edge timer
8: 0 0 0 0 IR-IO-APIC 8-edge rtc0
9: 0 0 0 0 IR-IO-APIC 9-fasteoi acpi
14: 0 0 0 0 IR-IO-APIC 14-fasteoi INTC1057:00
16: 0 590 0 0 IR-IO-APIC 16-fasteoi mmc0, idma64.0, i801_smbus, ttyS0
37: 0 0 0 0 IR-IO-APIC 37-fasteoi idma64.1, pxa2xx-spi.1
120: 0 0 0 0 DMAR-MSI 0-edge dmar0
121: 0 0 0 0 DMAR-MSI 1-edge dmar1
125: 0 4289304 0 0 IR-PCI-MSI 1048576-edge net0
126: 0 0 4456557 0 IR-PCI-MSI 1572864-edge lan0
127: 0 0 0 432003 IR-PCI-MSI 376832-edge ahci[0000:00:17.0]
128: 442 0 0 0 IR-PCI-MSI 327680-edge xhci_hcd
129: 0 42 0 0 IR-PCI-MSI 360448-edge mei_me
130: 0 0 164 0 IR-PCI-MSI 32768-edge i915
131: 0 0 0 0 IR-PCI-MSI 524288-edge rtw88_pci
132: 665 0 0 0 IR-PCI-MSI 514048-edge snd_hda_intel:card0
...
Come si vede l'**IRQ 125** ha //affinità// alla **CPU1**, così come la **IRQ 126** ha //affinità// alla **CPU2**, ecc. Si può verificare comunque che il kernel non impone tale affinità, infatti ispezionando lo pseudofile **/proc/irq/IRQ_NUMBER/smp_affinity** si vede:
cat /proc/irq/125/smp_affinity
f
Dove **f** un valore esadecimale che rappresenta una bitmask dei core CPU; tale IRQ può essere quindi servita da uno qualunque dei core.
Dall'elenco delle interrupt si deduce che probabilmente vi è una situazione critica relativamente all'interfaccia **net0**, abbiamo una conferma constatando il gran numero di pacchetti **dropped**:
ifconfig net0
net0: flags=4163 mtu 1500
inet 192.168.1.254 netmask 255.255.255.0 broadcast 192.168.1.255
inet6 fe80::2e0:4cff:fe60:11e4 prefixlen 64 scopeid 0x20
ether 00:e0:4c:60:11:e4 txqueuelen 1000 (Ethernet)
RX packets 3943557 bytes 3439040842 (3.2 GiB)
RX errors 0 dropped 107001 overruns 0 frame 0
TX packets 2410528 bytes 714236244 (681.1 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
===== softnet_stat =====
Grazie al contenuto di **/proc/net/softnet_stat** è possibile avere statistiche sulla gestione da parte delle softirq dei pacchetti network. Ogni riga si riferisce ad un CPU core, le colonne indicano:
- Total number of processed packets (processed).
- Times ksoftirq ran out of quota (dropped).
- Times net_rx_action was rescheduled.
- Number of times processed all lists before quota.
- Number of times did not process all lists due to quota.
- Number of times net_rx_action was rescheduled for GRO (Generic Receive Offload) cells.
- Number of times GRO cells were processed.
Per vedere la tabella in formato decimale invece che esadecimale si può ricorrere al comando:
awk '{for (i=1; i<=NF; i++) printf strtonum("0x" $i) (i==NF?"\n":" ")}' /proc/net/softnet_stat | column -t
===== netdev_max_backlog =====
Se il numero nella **seconda colonna** cresce costantemente (frame persi a causa di una coda backlog piena), è possibile incrementare la dimensione del buffer. Il valore corrente si vede con:
sysctl net.core.netdev_max_backlog
net.core.netdev_max_backlog = 1000
Quindi si può creare un file **/etc/sysctl.d/10-netdev_max_backlog.conf** con il seguente contenuto
net.core.netdev_max_backlog = 2000
e renderlo esecutivo con:
sysctl -p /etc/sysctl.d/10-netdev_max_backlog.conf
===== netdev_budget =====
Anche la **terza colonna** di **/proc/net/softnet_stat**, se cresce costantemente, può indicare un problema. In questo caso significa che il budget dedicato a gestire il traffico ricevuto è esaurito e la softirq viene rischedulata. Si tratta in pratica del numero di volte che un processo softirqd non è riuscito a processare tutti i pacchetti da una interfaccia durante un ciclo di polling NAPI.
Il budget assegnato è dato dai parametri **netdev_budget** e **netdev_budget_usecs** che sono consultabili con i comandi:
sysctl net.core.netdev_budget
net.core.netdev_budget = 300
sysctl net.core.netdev_budget_usecs
net.core.netdev_budget_usecs = 8000
In questo caso softirqd ha, per ogni ciclo di polling, 8000 microsecondi di tempo massimo per processare fino a 300 messaggi dalla scheda di rete. Possiamo aumentarli creando un file **/etc/sysctl.d/10-netdev_budget.conf** con:
net.core.netdev_budget = 600
net.core.netdev_budget_usecs = 24000
ed eseguendo
sysctl -p /etc/sysctl.d/10-netdev_budget.conf
===== Shorewall (netfilter) logging =====
Purtroppo nel nostro caso **non si sono ottenuti risultati incrementando il budget** per la softirq. L'host in questione è un firewall GNU/Linux con due schede di rete, il problema era associato all'interfaccia di rete esterna, protetta da **regole netfilter** tramite il software **Shorewall**. Il numero di regole complessivamente impostate era assolutamente modesto (157 regole):
iptables -S | wc -l
157
Il problema si manifestava in condizioni di portscan intensi, intorno ai 3 pacchetti/secondo. In questo caso il logging dei pacchetti dropped (tramite syslog venivano scritti su **/var/log/syslog** e su **/var/log/kern.log**) causava una perdita apprezzabile di pacchetti di rete.
Avendo **eliminato il logging dei pacchetti dropped** il problema pare risolto.
===== Web References =====
* **[[https://portal.nutanix.com/page/documents/kbs/details?targetId=kA07V000000LUR3SAO|Linux VM performance: ksofirqd process utilizes 100% of a vCPU ...]]**
* **[[https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/9/html/monitoring_and_managing_system_status_and_performance/tuning-the-network-performance_monitoring-and-managing-system-status-and-performance|Tuning the network performance]]**
* **[[https://jsevy.com/network/Linux_network_stack_walkthrough.html|Linux Network Stack Walkthrough]]**
* **[[https://learn.netdata.cloud/docs/collecting-metrics/linux-systems/network/softnet-statistics|Softnet Statistics]]**