Der ultimative Leitfaden zur Linux-Netzwerk-Performance
(ntk148v.github.io)- Beim Tuning der Linux-Netzwerk-Performance geht es darum, den Weg eines Pakets durch NIC-Ringpuffer, IRQ, NAPI, softIRQ, qdisc und TCP-Puffer bis zum Anwendungssocket anhand möglicher Engpässe zu interpretieren.
- Im Empfangspfad schreibt die NIC Pakete per DMA in den RAM und löst einen HardIRQ aus; der Treiber plant NAPI ein, leert im
NET_RX_SOFTIRQden Ringpuffer und übergibt die Pakete anschließend an die IP/TCP-Schichten und den Socket-Empfangspuffer. ethtool,/proc/net/softnet_stat,ss,netstatundsysctlsind die Ausgangspunkte für Beobachtung und Anpassung; die wichtigsten Stellschrauben sind Interrupt Coalescing, IRQ affinity, RSS/RPS/RFS/aRFS,netdev_budget,netdev_max_backlog,txqueuelensowie TCP-read/write-Puffer.- Es gibt keine einzelne Einstellung, die für alle Systeme passt: Größere Ringpuffer können Drops reduzieren, aber die Latenz erhöhen; Interrupt Coalescing kann CPU-Auslastung und HardIRQs senken, erzeugt dafür jedoch Latenzkosten.
- Hochperformante Paketverarbeitung lässt sich mit Optionen wie
PACKET_MMAP, DPDK,PF_RINGund XDP/AF_XDP erweitern, doch je nach Kernel-Bypass, Zero-Copy oder schnellem Pfad im Kernel unterscheiden sich Hardware-Abhängigkeiten, CPU-Belegung und Anforderungen an die Kernel-Version.
Linux-Empfangspfad: von der NIC bis zum Socket
- Netzwerkgeräte lösen IRQs aus, um das Eintreffen von Paketen zu signalisieren; das IRQ-Mapping unter Linux ist in
/proc/interruptsgespeichert. - IRQ-Handler laufen mit sehr hoher Priorität und können weitere IRQs blockieren; daher verschieben Treiber längere Arbeiten aus dem IRQ-Kontext heraus.
- Für diese verzögerte Verarbeitung werden softIRQs verwendet; bei der Netzwerk-Empfangsverarbeitung werden pro CPU ein Kernel-Thread
ksoftirqd/<cpu-number>,softnet_dataundpoll_listangelegt. net_dev_initregistriertNET_RX_SOFTIRQim softIRQ-System; der zugehörige Handler istnet_rx_action.-
Paketeingang und NAPI-Verarbeitung
- Die NIC schreibt die aus dem Netzwerk empfangenen Daten per DMA in einen Ringpuffer im RAM.
- Manche NICs sind Multiqueue-NICs mit mehreren Ringpuffern.
- Wenn die NIC einen HardIRQ auslöst, wird der IRQ-Handler des Treibers ausgeführt.
- Der Treiber quittiert den IRQ der NIC und ruft
napi_scheduleauf, um die NAPI-softIRQ-Poll-Schleife zu starten. napi_schedulefügt die NAPI-Poll-Struktur des Treibers zurpoll_listder aktuellen CPU hinzu und setzt das softIRQ-pending-Bit.- Wenn
ksoftirqd__do_softirqaufruft, wird der Handlernet_rx_actiondes ausstehendenNET_RX_SOFTIRQausgeführt.
-
GRO und Eintritt in den Protokoll-Stack
net_rx_actionprüft die NAPI-Poll-Liste und kontrolliertbudgetsowie die verstrichene Zeit, damit softIRQ die CPU nicht monopolisiert.- Die
poll-Funktion des Treibers erntet Pakete aus dem Ringpuffer im RAM. - Die Pakete werden an
napi_gro_receiveübergeben. - GRO (Generic Receive Offloading) ist ein softwarebasiertes Offloading-Verfahren, das kleine Pakete wieder zu größeren Paketen zusammensetzt und so die Anzahl der Pakete reduziert, die die Anwendung verarbeiten muss.
- Wenn GRO das Paket nicht zurückhält, wandert es über
netif_receive_skbnach oben in den Protokoll-Stack.
-
Verzweigung je nachdem, ob RPS aktiviert ist
- Wenn RPS deaktiviert ist:
netif_receive_skbübergibt die Daten an__netif_receive_core.__netif_receive_coreleitet die Daten an tap und die registrierten Handler der Protokollschichten weiter.
- Wenn RPS aktiviert ist:
netif_receive_skbübergibt die Daten anenqueue_to_backlog.- Das Paket gelangt in die CPU-spezifische input queue.
- Die NAPI-Struktur der entfernten CPU wird zur
poll_listdieser CPU hinzugefügt, und ein IPI wird in die Warteschlange gestellt, um den softIRQ-Thread der entfernten CPU aufzuwecken. ksoftirqdauf der entfernten CPU erntet mit der Poll-Funktionprocess_backlogPakete aus der CPU input queue.
- Wenn RPS deaktiviert ist:
-
IP, TCP und Socket-Empfangspuffer
- Pakete werden in der IPv4-Schicht mit
ip_rcvempfangen und durchlaufen netfilter sowie Routing-Optimierungen. - Daten, die an das aktuelle System gerichtet sind, werden an höhere Protokollschichten wie UDP oder TCP weitergegeben.
- Im TCP-Empfangspfad gelangen sie über
tcp_v4_rcv, die TCP finite state machine und die Socket-Suche in den Empfangspuffer. - Die Größe des Empfangspuffers folgt den Regeln von
tcp_rmem. - Wenn
tcp_moderate_rcvbufaktiviert ist, passt der Kernel den Empfangspuffer automatisch an. tcp_rmementhält Mindestwert, Standardwert und Höchstwert für den Empfangspuffer eines TCP-Sockets.- Wird
SO_RCVBUFverwendet, wird die automatische Anpassung des Empfangspuffers für diesen Socket deaktiviert. net.core.rmem_maxist die Obergrenze für die Größe des TCP-Empfangspuffers; größere Fenster erlauben es, vor dem Senden eines ACK mehr Daten zu übertragen, was die Latenz verringern und den Durchsatz erhöhen kann.
- Pakete werden in der IPv4-Schicht mit
Linux-Sendepfad: von der Anwendung bis zur NIC
- Der Sendepfad ist einfacher als der Empfangspfad, umfasst aber qdisc, TCP-write buffer, DMA und IRQ.
- Wenn eine Anwendung mit einem Aufruf wie
sendmsgeine Nachricht sendet, weist der TCP-Sendepfad einenskb_buffzu. - Pakete gelangen in den Socket-write buffer mit der Größe von
tcp_wmem.tcp_wmementhält Mindestwert, Standardwert und Höchstwert für den Sendepuffer eines TCP-Sockets.- Der Kernel passt die Größe des TCP-Sendepuffers dynamisch zwischen Mindest- und Höchstwert an.
- Wird
SO_SNDBUFverwendet, wird die automatische Anpassung des Sendepuffers für diesen Socket deaktiviert. net.core.wmem_maxist die Obergrenze für die Größe des TCP-Sendepuffers.
- TCP-Header und IP-Header werden erzeugt; nach
LOCAL_OUT, Routing,POST_ROUTINGund fragmentation wird mitdev_queue_xmitdie L2-Sendefunktion aufgerufen. - Die ausgehende qdisc verwendet die Länge
txqueuelenund den Algorithmusdefault_qdisc. - Der Treiber legt Pakete in den TX-Ringpuffer und führt nach einem
tx-usecs-Timeout oder nachtx-framesNET_TX_SOFTIRQaus. - Die NIC holt die Pakete per DMA aus dem RAM und sendet sie; nach Abschluss der Übertragung löst sie einen HardIRQ aus.
- Der Treiber verarbeitet diesen IRQ und plant das NAPI-Poll-System ein, um RAM freizugeben.
Beobachtungs-Tools und grundlegende Prüfpunkte
-
/proc/net/softnet_stat- Jede Zeile in
/proc/net/softnet_statsteht für einen CPU-Kern, beginnend mit CPU0 - Die Statistiken der einzelnen Spalten werden hexadezimal angegeben
- Die 1. Spalte ist die Anzahl der Frames, die der Interrupt-Handler empfangen hat
- Die 2. Spalte ist die Anzahl der Frames, die wegen Überschreitung von
netdev_max_backlogverworfen wurden - Die 3. Spalte ist die Anzahl der Fälle, in denen noch Arbeit zu erledigen war,
ksoftirqdabernetdev_budgetoder die CPU-Zeit ausgeschöpft hatte - Die übrigen Spalten können je nach Linux-Version variieren
- Jede Zeile in
-
/proc/net/sockstatundss- In
/proc/net/sockstatprüft man das Feldmem - Dieser Wert wird berechnet, indem
sk_buff->truesizeüber alle Sockets aufsummiert wird ssist ein Tool zum Dumpen von Socket-Statistiken und kann ähnliche Informationen wienetstatsowie zusätzliche TCP- und Zustandsinformationen anzeigenss -tmwird genutzt, um die Speichernutzung von TCP-Sockets zu prüfenrmem_alloc: Speicher, der für empfangene Pakete alloziert wurdercv_buf: gesamter Speicher, der für empfangene Pakete alloziert werden kannwmem_alloc: Speicher, der für ausgehende Pakete verwendet wird, die bereits an Layer 3 übergeben wurdensnd_buf: gesamter Speicher, der für ausgehende Pakete alloziert werden kannwmem_queued: Speicher, der für ausgehende Pakete alloziert wurde, die noch nicht an Layer 3 übergeben wurdensock_drop: Anzahl der Pakete, die verworfen wurden, bevor sie auf einen Socket demultiplexed wurden
- In
-
netstatundsysctlnetstatist ein Kommandozeilen-Tool, das offene Netzwerkverbindungen und Statistiken des Protokoll-Stacks ausgibt und seine Informationen aus dem Dateisystem/proc/net/bezieht/proc/net/dev: Geräteinformationen/proc/net/tcp: TCP-Socket-Informationen/proc/net/unix: Informationen zu Unix-Domain-Socketssysctlist ein Befehl zum Ändern von System- und Netzwerkeinstellungen, statt Werte direkt in das/proc-Dateisystem zu schreibensysctl -w variable=valuewird für temporäre Änderungen verwendet; für dauerhafte Änderungen bearbeitet man/etc/sysctl.confund wendet sie anschließend mitsysctl -pan
NIC-Ringpuffer und Interrupt-Tuning
-
NIC-Ringpuffer
- Der RX-Ringpuffer ist ein FIFO-Ringpuffer fester Größe im RAM
- Der Ringpuffer selbst enthält keine Paketdaten, sondern Deskriptoren, die auf per DMA in den RAM geschriebene
skbzeigen - Wenn Drops oder Overruns zu sehen sind, kann man die Queue-Größe erhöhen, als Nebenwirkung kann jedoch die Latenz steigen
- In vielen Fällen reicht es aus, die Größe des Empfangspuffers zu erhöhen, um Paket-Drops zu verhindern; dadurch bekommt der Kernel etwas mehr Zeit, den Puffer zu leeren
- Prüfung und Änderung erfolgen mit
ethtool ethtool -g eth3: aktuelle RX/TX-Ringgrößen und Maximalwerte prüfenethtool -G eth3 rx 8192 tx 8192: RX/TX-Puffer auf den Maximalwert erhöhen- Die Überwachung erfolgt mit
ethtool -S eth3und Countern wieerr,drop,over,miss,timeout,reset,collis
-
Hardware-Interrupt-Coalescing
- Die NIC kann Paket-Referenzen im RX-Ringpuffer sammeln, bis ein
rx-usecs-Timeout oder die Bedingungrx-frameserreicht ist, und dann einen HardIRQ auslösen; dies nennt man Interrupt coalescence - Werden Interrupts zu früh ausgelöst, unterbricht der Kernel laufende Arbeit zu häufig, was die Systemleistung verschlechtert
- Werden Interrupts zu spät ausgelöst, kann die NIC den Traffic möglicherweise nicht schnell genug abarbeiten, wodurch Überschreibungen und Traffic-Verluste entstehen können
- Das Tuning des Interrupt-Coalescing kann CPU-Nutzung und HardIRQs reduzieren und den Durchsatz erhöhen, kann aber Latenzkosten verursachen
- Mit
ethtool -c eth3prüft man die Coalesce-Parameter; sie lassen sich etwa mitethtool -C eth3 adaptive-rx off rx-usecs 0 rx-frames 0ändern - Im Adaptive Mode schätzt die Karte die Coalescing-Einstellungen dynamisch anhand der Traffic-Muster und der Empfangsmuster des Kernels
- Die NIC kann Paket-Referenzen im RX-Ringpuffer sammeln, bis ein
IRQ-Affinity und Lastverteilung zwischen CPUs
-
IRQ-Affinity
- IRQs haben ein Attribut
smp_affinity, das die CPU-Kerne definiert, auf denen der ISR dieses IRQs ausgeführt werden darf - Wenn man Interrupt-Affinity und die Affinity von Anwendungsthreads auf bestimmte CPU-Kerne abstimmt, kann sich die Anwendungsleistung durch gemeinsame Cache-Lines verbessern
- Standardmäßig übernimmt der Daemon
irqbalancedie Steuerung - Vor manuellen Anpassungen muss
irqbalancegestoppt werden - In
/proc/irq/<IRQ_NUMBER>/smp_affinityist eine hexadezimale Bitmaske gespeichert, die die CPU-Kerne repräsentiert - Auf einem Server mit 4 Kernen bedeutet der Standardwert
f, dass der IRQ auf allen CPUs verarbeitet werden kann echo 1 > /proc/irq/32/smp_affinitysorgt dafür, dass nur CPU0 verwendet wird- Auf Systemen mit mehr als 32 Kernen werden 32-Bit-Gruppen durch Kommas getrennt
- IRQ-Affinity kann nur bei sehr spezifischen Konfigurationen und vorab definierten Workloads die Performance verbessern und ein zweischneidiges Schwert sein
- IRQs haben ein Attribut
-
RSS
- Wenn eine schnelle NIC Pakete nur über eine einzelne Queue und eine einzelne CPU empfängt, kann ein Kern die gesamte Datenverarbeitung tragen, während die anderen Kerne im Leerlauf sind
- RSS (Receive-side scaling) ist eine NIC-Technik, bei der die NIC Traffic auf mehrere Sende- und Empfangsqueues verteilt
- Die NIC berechnet einen Hash auf Basis von Source-/Destination-IP sowie TCP/UDP-Source-/Destination-Port, weist Pakete desselben Flows einer einzelnen Queue zu und verteilt Flows gleichmäßig auf die Queues
- RSS bietet in Multiprocessing-Umgebungen Vorteile durch parallele Empfangsverarbeitung
- Laut Linux-Kernel-Dokumentation sollte RSS aktiviert werden, wenn Latenz wichtig ist oder die Verarbeitung von Empfangs-Interrupts zum Bottleneck wird; bei Low-Latency-Networking ist eine Konfiguration optimal, die so viele Queues zuweist, wie das System CPUs hat
-
RPS, RFS, aRFS
- RPS (Receive Packet Steering) ist näherungsweise eine Software-Implementierung von RSS
- Während RSS die Queue und CPU auswählt, auf der der Hardware-Interrupt-Handler läuft, wählt RPS die CPU aus, auf der die Protokollverarbeitung oberhalb des Interrupt-Handlers ausgeführt wird
CONFIG_RPSist erforderlich und ist auf SMP-Systemen standardmäßig aktiviert- Die Konfiguration erfolgt über die CPU-Bitmap in
/sys/class/net/<dev>/queues/rx-<n>/rps_cpus - Wenn RSS vorhanden ist, kann RPS überflüssig sein; wenn es aber mehr CPUs als Queues gibt, kann es nützlich sein
- RFS (Receive Flow Steering) erweitert RPS um Application Locality
- RPS verteilt Pakete Flow-basiert, berücksichtigt aber nicht, auf welcher CPU die Userspace-Anwendung läuft
- RFS verwaltet mit
rps_sock_flow_tableeine globale Flow-to-CPU-Tabelle - Die Tabellengröße lässt sich mit
net.core.rps_sock_flow_entriesanpassen - Die per-Queue geführte
rps_dev_flow_tablewird genutzt, um Probleme mit vertauschter Reihenfolge durch verbleibende Pakete zu reduzieren, wenn der Scheduler eine Anwendung auf eine neue CPU verschiebt - aRFS (Accelerated RFS) ist ein hardwarebeschleunigter Mechanismus zur Lastverteilung für RFS
- Da Pakete direkt an eine CPU nahe dem Thread gesendet werden, der die Daten konsumiert, kann aRFS eine bessere Performance als RFS erzielen
- Erforderlich sind
ndo_rx_flow_steerder NIC,ntuple-Filtering undCONFIG_RFS_ACCEL - Da die Zuordnung von CPUs zu Queues automatisch aus der IRQ-Affinity der jeweiligen Empfangsqueue abgeleitet wird, ist keine zusätzliche Konfiguration nötig
softIRQ, qdisc, TCP-Puffer-Tuning
-
softIRQ-Budget
- NAPI-Polling-Routinen werden durch
netdev_budget_usecs,netdev_budgetunddev_weightbegrenzt, damit softIRQ nicht die CPU monopolisiert - Der Standardwert von
net.core.netdev_budgetist 300; das bedeutet, dass der softIRQ-Prozess 300 Nachrichten von der NIC abarbeitet, bevor er die CPU wieder freigibt net.core.netdev_budget_usecsist die maximale Anzahl an Mikrosekunden eines NAPI-Polling-Cyclesnet.core.dev_weightist die maximale Anzahl von Paketen pro CPU, die der Kernel in einem NAPI-Interrupt verarbeiten kann- Wenn in
/proc/net/softnet_statandere Spalten als die 1. Spalte ansteigen, kann eine Änderung des Budgets nötig sein; geringe Anstiege können normal sein
- NAPI-Polling-Routinen werden durch
-
Ingress-qdisc und
netdev_max_backlognetdev_max_backlogist eine kernelinterne Queue, in der Traffic nach dem Empfang durch die NIC und vor der Verarbeitung durch Protokoll-Stacks wie IP/TCP gespeichert wird- Pro CPU-Kern gibt es jeweils eine Backlog-Queue
- Wenn ein Interface Pakete schneller empfängt, als der Kernel sie verarbeiten kann, füllt sich die INPUT-seitige Queue bis
netdev_max_backlog; darüber hinausgehende Pakete werden verworfen - Der Standardwert ist 1000 und kann für mehrere 1-Gbps-Interfaces oder ein einzelnes 10-Gbps-Interface zu niedrig sein
- Die 2. Spalte in
/proc/net/softnet_statist ein Counter, der bei Backlog-Queue-Overflows ansteigt - Eine Änderung des Werts erfolgt mit
sysctl -w net.core.netdev_max_backlog <value>
-
Egress-qdisc,
txqueuelen,default_qdisctxqueuelenlegt die Anzahl der Pakete fest, die in der Kernel-Transmit-Queue eines Netzwerk-Interface-Geräts erlaubt sind- Der Standardwert kann je nach Interface-Treiber 1000 betragen
- Ändern lässt sich der Wert mit
ifconfig <interface> txqueuelen value; RX/TX dropped prüft man mitip -s link default_qdiscist die standardmäßig für Netzwerkgeräte zu verwendende Queuing Discipline- Statt
pfifo_fastkönnen Alternativen wiesfq,codeloderfq_codelfestgelegt werden - Mit
tc -s qdisc ls dev <interface>prüft man Kennzahlen wie dropped, overlimits und requeues
-
TCP-Read/Write-Buffer und Verbindungs-Queues
tcp_rmemundtcp_wmemdefinieren jeweils Minimum, Standardwert und Maximum der TCP-Empfangs- bzw. TCP-Sendepuffer- Die Änderung erfolgt beispielsweise so
sysctl -w net.ipv4.tcp_rmem="min default max"sysctl -w net.ipv4.tcp_wmem="min default max"
- Mit
/proc/net/sockstatprüft man den Zustand der Puffernutzung - Accept Queue und SYN Queue werden von
net.core.somaxconnundnet.ipv4.tcp_max_syn_backlogbeeinflusst net.core.somaxconnist die Obergrenze für den backlog-Parameter vonlisten(); wenn dieser Wert geändert wird, muss auch die Anwendung auf einen kompatiblen Wert angepasst werdennet.ipv4.tcp_syncookiesschaltet SYN Cookies ein oder aus, die zum Schutz vor SYN-Flood-Angriffen nützlich sindnet.ipv4.tcp_congestion_controllegt den Congestion-Control-Algorithmus fest, der für neue Verbindungen verwendet wird
NUMA und Netzwerk-Performance
- NUMA (Non-uniform memory access) ist eine Speicherarchitektur, bei der ein Prozessor schneller auf lokalen Speicher zugreifen kann als auf nicht lokalen Speicher
- Da die CPU bei der Netzwerkverarbeitung auf Ringpuffer-Speicher zugreifen muss, kann NUMA Locality die Netzwerk-Performance beeinflussen
- NUMA teilt CPU, Speicher und Geräte in mehrere Nodes auf und verhält sich wie mehrere kleine Computer mit schnellem Interconnect und gemeinsamem OS
- In NUMA-Systemen besteht das Tuning-Ziel darin, die Interrupts eines Geräts auf die CPU-Kerne des einzelnen Nodes zu bündeln, zu dem dieses Gerät gehört
- Allerdings können NUMA-Systeme ungünstig mit Echtzeitanwendungen interagieren und unerwartete Event-Latenzen verursachen
- NUMA-Nodes prüft man mit
/sys/devices/system/node/node* - Die Geräte-Locality prüft man mit
/sys/class/net/<interface>/device/numa_node-1bedeutet, dass die Hardwareplattform kein echtes NUMA ist, der Kernel NUMA emuliert oder das Gerät keine NUMA Locality hat
- Der Linux-Kernel unterstützt NUMA seit 2.5; RedHat- und Debian-basierte Distributionen stellen
numactlundnumadbereit numadüberwacht die System-Topologie und Ressourcennutzung und versucht, Prozesse mit ausreichend großem Speicher- und CPU-Bedarf an einer effizienten NUMA Locality zu platzieren
Optionen für schnellere Paketverarbeitung
-
AF_PACKETv4 undPACKET_MMAPAF_PACKET v4ist eine schnelle Paketschnittstelle unter Linux, die System Calls aus dem Datenpfad entfernt und standardmäßig den Copy-Mode verwendet- Mit
PACKET_ZEROCOPYlässt sich ein echter Zero-Copy-Modus nutzen, bei dem DMA-Paketpuffer in den Userspace gemappt werden - Der übliche Pfad aus File-Read und anschließendem Socket-Send erfordert Context Switches zwischen User Mode und Kernel Mode sowie mehrere Datenkopien
- Zero-Copy erhöht die Performance, indem redundante Datenkopien vermieden werden
PACKET_MMAPist eine Linux-API für schnelles Packet Sniffing- Sie stellt einen mmapped Ring Buffer bereit, der von Userspace und Kernel gemeinsam genutzt wird
- Sie reduziert System Calls sowie Kopien zwischen Userspace und Kernel bei gesendeten und empfangenen Paketen
-
DPDK
- DPDK (Data Plane Development Kit) ist ein Framework aus Userspace-Bibliotheken und Treibern für schnelle Paketverarbeitung
- Ziel ist es, Netzwerkpakete zwischen NIC und User-Anwendung mit nativer Geschwindigkeit zu senden und zu empfangen
- Zielhardware sind 10Gb- oder 40Gb-NICs; Geschwindigkeit ist das wichtigste Kriterium
- Der Fokus liegt nicht auf einem Netzwerk-Stack, sondern auf Packet Forwarding
- Wenn DPDK die NIC kontrolliert, umgeht sämtlicher Traffic den Kernel, und die betreffende NIC ist für den Kernel nicht sichtbar
- Ports werden vom Linux-Kernel-Treiber ungebunden und von Treibern wie
vfio_pci,igb_uiooderuio_pci_genericverwaltet - Anschließend übernimmt der DPDK PMD die Kommunikation zwischen Anwendung und NIC
- DPDK erfordert eine Hugepages-Konfiguration, um große Speicher-Chunks zu allozieren
- Hauptkomponenten:
- EAL: generisches Interface, das Unterschiede zwischen Umgebungen verbirgt
librte_ring: lockless Multi-Producer-, Multi-Consumer-FIFO-APIlibrte_mempool: Allokation von Pools für Speicherobjektelibrte_mbuf: Erzeugung und Manipulation von Buffern für Netzwerkpaketelibrte_timer: Timer-Service für die asynchrone Ausführung von Funktionen- PMD: Treiber, bei dem die CPU die NIC kontinuierlich pollt, statt Interrupts zu nutzen
- Einschränkungen:
- Starke Hardwareabhängigkeit
- Für die Ausführung eines PMD muss ein CPU-Core exklusiv zugewiesen werden; er nutzt 100% CPU
-
PF_RINGPF_RINGist ein Linux-Kernelmodul und Userspace-Framework, das Pakete mit hoher Geschwindigkeit verarbeitet und Paketverarbeitungsanwendungen eine konsistente API bietetPF_RINGpollt Pakete von der NIC über Linux NAPI- NAPI kopiert Pakete von der NIC in den
PF_RINGCircular Buffer, und die Userspace-Anwendung liest Pakete aus dem Ring - In dieser Struktur gibt es zwei Poller – die Anwendung und NAPI –, sodass CPU-Zyklen für Polling aufgewendet werden
- Ein Vorteil ist, dass eingehende Pakete gleichzeitig auf mehrere Ringe verteilt werden können
- Durch die modulare Struktur lassen sich zusätzliche Komponenten wie ZC Module, FPGA-based Card Module, Stack Module, Timeline Module und Sysdig Module verwenden
PF_RINGhat die Kosten für Packet Capture und Userland Forwarding reduziert, ist in der Maximalleistung jedoch durch die Zwei-Akteur-Struktur begrenzt, bei der der Kernel von der NIC in den Ring kopiert und Userland aus dem Ring liest und verarbeitetPF_RINGenthält seit Version 7.5 Unterstützung für einenAF_XDP-Adapter
-
XDP und
AF_XDP- XDP (eXpress Data Path) ist eine eBPF-Implementierung, die Pakete sehr früh im Linux-Netzwerkdatenpfad abfängt
- XDP verarbeitet die RX-Packet-Page direkt innerhalb der RX-Funktion des Device-Treibers, noch bevor ein SKB allokiert wird
- eBPF ist benutzerdefinierter, sandboxed Bytecode, der im Kernel ausgeführt wird
- Es verwendet 11 64-Bit-Register und einen 512-Byte-Stack
- Über das LLVM-Backend kann aus C, Lua, Go, P4, Rust und weiteren Sprachen nach eBPF kompiliert werden
- Es bietet einen In-Kernel-Verifier und einen JIT-Compiler und unterstützt Funktionen wie Maps, Tail Calls und Helper
- Einsatzbereiche von XDP:
- Pre-Stack-Filtering zur DoS-Abmilderung
- Forwarding und Load Balancing
- Batching-Verfahren wie GRO
- Flow Sampling und Monitoring
- ULP Processing
- XDP ist kein Kernel Bypass, sondern ein Fast Path innerhalb des Kernel-Stacks, und ersetzt den TCP/IP-Stack nicht
- Es ist keine dedizierte Hardware erforderlich, allerdings gibt es Anforderungen wie Multi-Queue-NIC, TX/RX Checksum Offload, RSS und TSO
- Vorteile von XDP gegenüber DPDK:
- Wahl zwischen Busy Polling und interruptgesteuertem Networking
- Keine Huge Pages erforderlich
- Keine speziellen Hardwareanforderungen
- Dedizierte CPU nicht zwingend erforderlich
- Pakete müssen von 3rd-party Userspace Applications nicht erneut in den Kernel injiziert werden
- Kein neues Security Model für den Zugriff auf Netzwerkhardware erforderlich
- Kein 3rd-party Code/Licensing erforderlich
AF_XDPist ein neuer Socket-Typ, der mit Linux 4.18 eingeführt wurde- Ohne den Kernel vollständig zu umgehen, kann es Kernel-Funktionen nutzen, um eine DPDK oder
AF_PACKETähnliche Struktur aufzubauen - Ein XDP-Programm kann Frames per eBPF in einen Userspace-Memory-Buffer umleiten
- DMA-Transfers unterstützen Zero-Copy über Userspace-Speicher
- Gegenüber
AF_PACKETlässt sich eine Performance-Steigerung um das 3- bis 20-Fache erreichen - Einschränkungen:
- Relativ junges Projekt
- Für vollständige Unterstützung ist Linux-Kernel 5.4 oder neuer erforderlich
1 Kommentare
Hacker-News-Kommentare
Das wäre vor ein paar Wochen wirklich nützliches Material für mich gewesen.
Ich wollte L2-Link-Verschlüsselung zwischen Rechenzentren umsetzen und habe mir Angebote für Hardware-Appliances von mehreren Anbietern eingeholt, fand die Kosten aber viel zu hoch und habe es deshalb selbst gebaut.
Ich habe Ethernet-Frames über ein WireGuard-Overlay-Netzwerk auf Standardhardware transportiert und so 10 Gbit/s erreicht. Nach etwa zehn Tagen Arbeit war die Lösung rund 70 % günstiger als das billigste Angebot und etwa 95 % günstiger als das teuerste, aber dafür waren viel Detaildokumentation und viele Experimente nötig.
Ich würde den Inhalt dieses Artikels gern nutzen, um zu prüfen, ob mein Verständnis korrekt ist; auf den ersten Blick wirkt er vielversprechend und umfassend.
Wenn es so viele einstellbare Werte gibt, wäre es dann nicht sinnvoll, Auto-Tuning-Software zu bauen?
Ein Ansatz ähnlich dem Gradientenabstieg scheint möglich: zufällig Parameter aus einer Whitelist auswählen, sie innerhalb eines zulässigen Bereichs leicht erhöhen oder senken, die Performance eine Weile messen und dann zurückrollen, wenn sie schlechter wird, oder weiter anpassen, wenn sie besser wird.
Interessant, aber als Softwareentwickler habe ich fast nie die Gelegenheit, die im Artikel genannten Befehle tatsächlich auszuführen.
Die Systeme laufen meist in irgendeinem abgespeckten Linux-Container, es gibt keinen Shell-Zugriff auf die Produktionssysteme, und Entwicklungs- oder QA-Umgebungen unterscheiden sich hinsichtlich Last und anderer Aspekte so stark von der Produktion, dass das Reproduzieren von Bugs meistens kaum hilft.
Letztlich hat man nur dann Gelegenheit, die Befehle aus dem Artikel auszuprobieren, wenn man am eigenen System arbeitet; als Platform Engineer wäre das wahrscheinlich nützlicher.
Einer der Punkte, die mir an Kubernetes weniger gefallen, ist das Networking-Modell. Es geht davon aus, dass es nur eine Netzwerkkarte gibt und dass Anwendungen so einfach sind, dass sie kein Wissen über die darunterliegenden Schichten brauchen.
Das gesamte Networking-Modell scheint noch viel Raum für eine grundlegende Modernisierung und Verbesserung im Stil der 2020er zu haben.
Es heißt,
net.core.wmem_maxsei die Obergrenze für die Größe des TCP-Sendepuffers, und es gibt auchnet.ipv4.tcp_wmem, daher frage ich mich zwei Dinge:net.core.wmem_max?net.core.wmem_maxist, wie der Name sagt, der Maximalwert.net.ipv4.tcp_wmemist ein Dreifachwert mit Minimum, Standard und Maximum; der dort angegebene Maximalwert kann den zuvor genanntennet.core.wmem_maxnicht überschreiten.TCP sollte dasselbe Protokoll sein, unabhängig davon, ob es über IPv4 oder IPv6 transportiert wird.
Beispiel: https://docs.redhat.com/en/documentation/red_hat_data_grid/7...
Was hier etwas fehlt, ist Debugging und Tuning für Durchsatz jenseits von 100 Gbit/s.
Wenn man auf diesem Niveau HTTP ausliefert, ist der erste Flaschenhals oft die Speicherbandbreite, weshalb man häufig kTLS braucht.
Tools wie AMD μProf sind fürs Debugging sehr nützlich, und eBPF-basiertes kontinuierliches Profiling hilft ebenfalls dabei zu verstehen, was genau im Kernel und im User Space passiert.
Sieht ziemlich cool aus. In meiner bisherigen Laufbahn habe ich, sobald Performance nötig war, meist direkt mit Kernel-Bypass angefangen.