5 points par GN⁺ 2024-07-29 | 1 commentaires | Partager sur WhatsApp
  • L’optimisation des performances réseau sous Linux consiste à analyser, sous l’angle des goulets d’étranglement, le cheminement des paquets qui passent par les ring buffers de la NIC, les IRQ, NAPI, softIRQ, qdisc et les buffers TCP jusqu’au socket applicatif
  • Sur le chemin de réception, la NIC écrit les paquets en RAM via DMA et déclenche une HardIRQ ; le pilote planifie ensuite NAPI afin de vider le ring buffer dans NET_RX_SOFTIRQ, puis de transmettre les paquets aux couches IP/TCP et au buffer de réception du socket
  • ethtool, /proc/net/softnet_stat, ss, netstat et sysctl sont les points de départ pour l’observation et le réglage ; les axes principaux sont la coalescence d’interruptions, l’IRQ affinity, RSS/RPS/RFS/aRFS, netdev_budget, netdev_max_backlog, txqueuelen et les buffers TCP read/write
  • Il n’existe pas de réglage unique valable pour tous les systèmes : augmenter les ring buffers peut réduire les drops mais accroître la latence, tandis que la coalescence d’interruptions peut réduire l’utilisation CPU et les HardIRQ au prix d’une latence supplémentaire
  • Le traitement de paquets haute performance peut être étendu avec des options comme PACKET_MMAP, DPDK, PF_RING ou XDP/AF_XDP, mais le contournement du noyau, le zéro-copie et les fast paths dans le noyau ont chacun des dépendances matérielles, une occupation CPU et des exigences de version du noyau différentes

Chemin de réception Linux : de la NIC au socket

  • Le périphérique réseau déclenche une IRQ pour signaler l’arrivée d’un paquet, et le mapping des IRQ sous Linux est stocké dans /proc/interrupts
  • Le gestionnaire d’IRQ s’exécute avec une priorité très élevée et peut empêcher la génération d’IRQ supplémentaires ; le pilote reporte donc les traitements longs hors du contexte d’IRQ
  • Ce traitement différé utilise les softIRQ ; pour le traitement de réception réseau, un thread noyau ksoftirqd/<cpu-number>, une structure softnet_data et une poll_list sont créés pour chaque CPU
  • net_dev_init enregistre NET_RX_SOFTIRQ dans le système softIRQ, et son gestionnaire est net_rx_action
  • Arrivée des paquets et traitement NAPI

    • La NIC écrit les données reçues du réseau dans un ring buffer en RAM via DMA
    • Certaines NIC sont des NIC multiqueue disposant de plusieurs ring buffers
    • Lorsque la NIC déclenche une HardIRQ, le gestionnaire d’IRQ du pilote s’exécute
    • Le pilote acquitte l’IRQ de la NIC et appelle napi_schedule pour lancer la boucle de polling softIRQ de NAPI
    • napi_schedule ajoute la structure de polling NAPI du pilote à la poll_list du CPU courant et positionne le bit pending de softIRQ
    • Quand ksoftirqd appelle __do_softirq, le gestionnaire net_rx_action de NET_RX_SOFTIRQ, alors en attente, s’exécute
  • GRO et entrée dans la pile de protocoles

    • net_rx_action examine la liste de polling NAPI et vérifie le budget ainsi que le temps écoulé afin d’éviter que la softIRQ ne monopolise le CPU
    • La fonction poll du pilote récolte les paquets depuis le ring buffer en RAM
    • Les paquets sont transmis à napi_gro_receive
    • GRO (Generic Receive Offloading) est une technique d’offloading logicielle qui réassemble de petits paquets en paquets plus grands afin de réduire le nombre de paquets que l’application doit traiter
    • Si GRO ne met pas le paquet en attente, celui-ci remonte vers le haut de la pile de protocoles via netif_receive_skb
  • Branchements selon l’activation de RPS

    • Si RPS est désactivé :
      • netif_receive_skb transmet les données à __netif_receive_core
      • __netif_receive_core transmet les données aux taps et aux gestionnaires des couches de protocoles enregistrés
    • Si RPS est activé :
      • netif_receive_skb transmet les données à enqueue_to_backlog
      • Le paquet entre dans l’input queue propre à chaque CPU
      • La structure NAPI du CPU distant est ajoutée à la poll_list de ce CPU, et une IPI est mise en file pour réveiller le thread softIRQ du CPU distant
      • Le ksoftirqd du CPU distant récolte les paquets depuis l’input queue CPU avec la fonction de polling process_backlog
  • IP, TCP et buffer de réception du socket

    • Le paquet est reçu dans la couche IPv4 par ip_rcv, puis passe par netfilter et des optimisations de routage
    • Les données destinées au système courant sont transmises à une couche de protocole supérieure comme UDP ou TCP
    • Sur le chemin de réception TCP, elles passent par tcp_v4_rcv, la machine à états finis TCP et la recherche du socket, puis entrent dans le buffer de réception
    • La taille du buffer de réception suit les règles de tcp_rmem
    • Lorsque tcp_moderate_rcvbuf est activé, le noyau ajuste automatiquement le buffer de réception
    • tcp_rmem contient les valeurs minimale, par défaut et maximale du buffer de réception des sockets TCP
    • L’utilisation de SO_RCVBUF désactive l’ajustement automatique du buffer de réception pour ce socket
    • net.core.rmem_max est la limite supérieure de la taille du buffer de réception TCP ; une fenêtre plus grande peut permettre d’envoyer davantage de données avant l’envoi d’un ACK, ce qui réduit la latence et augmente le débit

Chemin d’émission Linux : de l’application à la NIC

  • Le chemin d’émission est plus simple que celui de réception, mais implique qdisc, le TCP write buffer, DMA et les IRQ
  • Lorsque l’application envoie un message via un appel comme sendmsg, le chemin d’émission TCP alloue un skb_buff
  • Le paquet entre dans le write buffer du socket, de taille tcp_wmem
    • tcp_wmem contient les valeurs minimale, par défaut et maximale du buffer d’émission des sockets TCP
    • Le noyau ajuste dynamiquement la taille du buffer d’émission TCP entre les valeurs minimale et maximale
    • L’utilisation de SO_SNDBUF désactive l’ajustement automatique du buffer d’émission pour ce socket
    • net.core.wmem_max est la limite supérieure de la taille du buffer d’émission TCP
  • Les en-têtes TCP et IP sont créés ; après LOCAL_OUT, le routage, POST_ROUTING et la fragmentation, la fonction d’émission L2 est appelée via dev_queue_xmit
  • La qdisc de sortie utilise la longueur txqueuelen et l’algorithme default_qdisc
  • Le pilote place les paquets dans le ring buffer TX et exécute NET_TX_SOFTIRQ après le timeout tx-usecs ou après tx-frames
  • La NIC récupère les paquets depuis la RAM via DMA et les transmet, puis déclenche une HardIRQ une fois l’émission terminée
  • Le pilote traite cette IRQ et planifie le système de polling NAPI pour libérer la RAM

Outils d’observation et points de vérification de base

  • /proc/net/softnet_stat

    • Chaque ligne de /proc/net/softnet_stat représente un cœur CPU, en commençant par CPU0
    • Les statistiques de chaque colonne sont fournies en hexadécimal
    • La 1re colonne correspond au nombre de trames reçues par le gestionnaire d’interruptions
    • La 2e colonne correspond au nombre de trames abandonnées en raison d’un dépassement de netdev_max_backlog
    • La 3e colonne correspond au nombre de fois où ksoftirqd a épuisé netdev_budget ou le temps CPU alors qu’il restait du travail à traiter
    • Les autres colonnes peuvent varier selon la version de Linux
  • /proc/net/sockstat et ss

    • Dans /proc/net/sockstat, vérifiez le champ mem
    • Cette valeur est calculée en additionnant le sk_buff->truesize de tous les sockets
    • ss est un outil qui dump les statistiques des sockets ; il peut afficher des informations similaires à netstat ainsi que davantage d’informations TCP et d’état
    • ss -tm sert à vérifier l’utilisation mémoire des sockets TCP
    • rmem_alloc : mémoire allouée aux paquets reçus
    • rcv_buf : mémoire totale pouvant être allouée aux paquets reçus
    • wmem_alloc : mémoire utilisée par les paquets envoyés déjà transmis à la couche 3
    • snd_buf : mémoire totale pouvant être allouée aux paquets à envoyer
    • wmem_queued : mémoire allouée aux paquets à envoyer qui n’ont pas encore été transmis à la couche 3
    • sock_drop : nombre de paquets abandonnés avant leur démultiplexage vers un socket
  • netstat et sysctl

    • netstat est un outil en ligne de commande qui affiche les connexions réseau ouvertes et les statistiques de la pile de protocoles, et récupère ses informations dans le système de fichiers /proc/net/
    • /proc/net/dev : informations sur les périphériques
    • /proc/net/tcp : informations sur les sockets TCP
    • /proc/net/unix : informations sur les sockets de domaine Unix
    • sysctl est une commande permettant de modifier les paramètres système et réseau au lieu d’écrire directement des valeurs dans le système de fichiers /proc
    • sysctl -w variable=value sert aux modifications temporaires ; pour les modifications permanentes, modifiez /etc/sysctl.conf, puis appliquez avec sysctl -p

Tampon circulaire de la NIC et réglage des interruptions

  • Tampon circulaire de la NIC

    • Le tampon circulaire RX est un tampon circulaire FIFO de taille fixe situé en RAM
    • Le ring buffer lui-même ne contient pas les données des paquets, mais des descripteurs pointant vers les skb placés en RAM via DMA
    • Si vous observez des drops ou des overruns, vous pouvez augmenter la taille de la file, mais cela peut avoir pour effet secondaire d’augmenter la latence
    • Dans de nombreux cas, augmenter simplement la taille du tampon de réception permet d’éviter les pertes de paquets et laisse au noyau un peu plus de temps pour vider le tampon
    • La vérification et la modification se font avec ethtool
    • ethtool -g eth3 : vérifier les tailles actuelles des rings RX/TX et leurs valeurs maximales
    • ethtool -G eth3 rx 8192 tx 8192 : augmenter les tampons RX/TX à leur valeur maximale
    • Surveillez avec ethtool -S eth3 et des compteurs comme err, drop, over, miss, timeout, reset, collis
  • Coalescence des interruptions matérielles

    • La NIC peut accumuler des références de paquets dans le ring buffer RX jusqu’à la condition de timeout rx-usecs ou rx-frames, puis déclencher une HardIRQ ; c’est ce qu’on appelle Interrupt coalescence
    • Des interruptions trop rapides obligent souvent le noyau à interrompre la tâche en cours, ce qui dégrade les performances du système
    • Des interruptions trop tardives peuvent empêcher la NIC de vider le trafic assez vite, entraînant des écrasements et des pertes de trafic
    • Le réglage de la coalescence des interruptions peut réduire l’utilisation CPU et les HardIRQ, et augmenter le débit, mais peut se payer en latence
    • Vous pouvez vérifier les paramètres de coalescence avec ethtool -c eth3 et les modifier, par exemple avec ethtool -C eth3 adaptive-rx off rx-usecs 0 rx-frames 0
    • En mode adaptatif, la carte estime dynamiquement les paramètres de coalescing à partir des motifs de trafic et des motifs de réception du noyau

IRQ affinity et répartition de charge entre CPU

  • IRQ affinity

    • Une IRQ possède un attribut smp_affinity qui définit les cœurs CPU autorisés à exécuter l’ISR de cette IRQ
    • Aligner l’affinité des interruptions et l’affinité des threads applicatifs sur certains cœurs CPU peut améliorer les performances de l’application grâce au partage des lignes de cache
    • Par défaut, c’est le démon irqbalance qui la contrôle
    • Avant un réglage manuel, il faut arrêter irqbalance
    • /proc/irq/<IRQ_NUMBER>/smp_affinity contient un bitmask hexadécimal représentant les cœurs CPU
    • Sur un serveur à 4 cœurs, la valeur par défaut f signifie que toutes les CPU peuvent traiter l’IRQ
    • echo 1 > /proc/irq/32/smp_affinity force l’utilisation de CPU0 uniquement
    • Sur les systèmes de plus de 32 cœurs, les groupes de 32 bits sont séparés par des virgules
    • L’IRQ affinity ne peut améliorer les performances que dans des configurations très spécifiques et avec des charges de travail prédéfinies ; elle peut être une arme à double tranchant
  • RSS

    • Avec une NIC rapide, si une seule file et un seul CPU reçoivent les paquets, un cœur peut assumer toute la responsabilité du traitement des données tandis que les autres restent inactifs
    • RSS (Receive-side scaling) est une technologie de NIC qui permet de répartir le trafic sur plusieurs files de réception/transmission
    • La NIC calcule un hash à partir des adresses IP source/destination et des ports TCP/UDP source/destination, affecte les paquets d’un même flow à une seule file, et répartit uniformément les flows entre les files
    • RSS offre les avantages du traitement de réception parallèle dans les environnements multiprocesseurs
    • Selon la documentation du noyau Linux, RSS doit être activé lorsque la latence est importante ou que le traitement des interruptions de réception constitue un goulot d’étranglement ; pour le réseau à faible latence, la configuration optimale consiste à allouer autant de files que de CPU système
  • RPS, RFS, aRFS

    • RPS (Receive Packet Steering) se rapproche d’une implémentation logicielle de RSS
    • Alors que RSS choisit la file et le CPU qui exécuteront le gestionnaire d’interruption matériel, RPS choisit le CPU qui effectuera le traitement protocolaire au-dessus du gestionnaire d’interruption
    • CONFIG_RPS est requis et est activé par défaut en SMP
    • La configuration se fait via le bitmap CPU de /sys/class/net/<dev>/queues/rx-<n>/rps_cpus
    • Si RSS est disponible, cela peut être inutile, mais cela peut être utile lorsque le nombre de CPU est supérieur au nombre de files
    • RFS (Receive Flow Steering) étend RPS jusqu’à la locality applicative
    • RPS répartit les paquets par flow, mais ne tient pas compte du CPU sur lequel l’application en espace utilisateur s’exécute
    • RFS maintient rps_sock_flow_table, une table globale flow-vers-CPU
    • La taille de la table peut être ajustée avec net.core.rps_sock_flow_entries
    • La rps_dev_flow_table par file sert à réduire les problèmes de désordre liés aux paquets restants lorsque le scheduler déplace une application vers un nouveau CPU
    • aRFS (Accelerated RFS) est un mécanisme de répartition de charge avec accélération matérielle pour RFS
    • Comme il envoie les paquets directement vers un CPU proche du thread qui consomme les données, il peut offrir de meilleures performances que RFS
    • Il nécessite ndo_rx_flow_steer côté NIC, le filtrage ntuple et CONFIG_RFS_ACCEL
    • Le mapping entre CPU et files étant dérivé automatiquement de l’IRQ affinity de chaque file de réception, aucune configuration supplémentaire n’est nécessaire

softIRQ, qdisc, réglage des tampons TCP

  • Budget softIRQ

    • Les routines de polling NAPI sont limitées par netdev_budget_usecs, netdev_budget et dev_weight afin d’éviter que les softIRQ ne monopolisent le CPU
    • La valeur par défaut de net.core.netdev_budget est 300, ce qui signifie que le processus softIRQ vide 300 messages depuis la NIC avant de céder le CPU
    • net.core.netdev_budget_usecs correspond au nombre maximal de microsecondes d’un cycle de polling NAPI
    • net.core.dev_weight est le nombre maximal de paquets par CPU que le noyau peut traiter lors d’une interruption NAPI
    • Si des colonnes autres que la 1re augmentent dans /proc/net/softnet_stat, il peut être nécessaire de modifier le budget ; une faible augmentation peut toutefois être normale
  • qdisc ingress et netdev_max_backlog

    • netdev_max_backlog est une file interne du noyau où le trafic reçu par la NIC est stocké avant d’être traité par la pile protocolaire, par exemple IP/TCP
    • Chaque cœur CPU dispose de sa propre backlog queue
    • Si une interface reçoit des paquets plus vite que le noyau ne peut les traiter, la file côté INPUT se remplit jusqu’à netdev_max_backlog, puis les paquets excédentaires sont supprimés
    • La valeur par défaut est 1000, ce qui peut être insuffisant pour plusieurs interfaces à 1 Gbit/s ou une seule interface à 10 Gbit/s
    • La 2e colonne de /proc/net/softnet_stat est un compteur qui augmente en cas de débordement de la backlog queue
    • La valeur se modifie avec sysctl -w net.core.netdev_max_backlog <value>
  • qdisc egress, txqueuelen, default_qdisc

    • txqueuelen définit le nombre de paquets autorisés dans la file de transmission du noyau d’une interface réseau
    • La valeur par défaut peut être 1000 selon le pilote de l’interface
    • Elle se modifie avec ifconfig <interface> txqueuelen value, et les paquets RX/TX dropped se vérifient avec ip -s link
    • default_qdisc est la discipline de file d’attente par défaut à utiliser pour les périphériques réseau
    • À la place de pfifo_fast, on peut définir des alternatives comme sfq, codel ou fq_codel
    • tc -s qdisc ls dev <interface> permet de vérifier des indicateurs comme dropped, overlimits et requeues
  • Tampons TCP read/write et files de connexion

    • tcp_rmem et tcp_wmem définissent respectivement les valeurs minimale, par défaut et maximale des tampons TCP de réception et d’envoi
    • La modification s’effectue ainsi
      • sysctl -w net.ipv4.tcp_rmem="min default max"
      • sysctl -w net.ipv4.tcp_wmem="min default max"
    • /proc/net/sockstat permet de vérifier l’état d’utilisation des tampons
    • L’accept queue et la SYN queue sont influencées par net.core.somaxconn et net.ipv4.tcp_max_syn_backlog
    • net.core.somaxconn est la limite supérieure du paramètre backlog de listen() ; si l’on modifie cette valeur, l’application doit également être ajustée à une valeur compatible
    • net.ipv4.tcp_syncookies active ou désactive les SYN cookies, utiles pour se protéger contre les attaques SYN flood
    • net.ipv4.tcp_congestion_control définit l’algorithme de contrôle de congestion à utiliser pour les nouvelles connexions

NUMA et performances réseau

  • NUMA (Non-uniform memory access) est une architecture mémoire dans laquelle un processeur peut accéder plus rapidement à la mémoire locale qu’à la mémoire non locale
  • Dans le traitement réseau, le CPU doit accéder à la mémoire des ring buffers ; la localité NUMA peut donc influer sur les performances réseau
  • NUMA divise les CPU, la mémoire et les périphériques en plusieurs nœuds, et fonctionne comme plusieurs petits ordinateurs dotés d’une interconnexion rapide et d’un OS commun
  • Sur un système NUMA, l’objectif du réglage consiste à regrouper les interruptions d’un périphérique sur les cœurs CPU du nœud auquel ce périphérique appartient
  • Les systèmes NUMA peuvent toutefois interagir défavorablement avec les applications temps réel et provoquer des latences d’événements inattendues
  • Les nœuds NUMA se consultent via /sys/devices/system/node/node*
  • La localité d’un périphérique se consulte via /sys/class/net/<interface>/device/numa_node
    • -1 signifie que la plateforme matérielle n’est pas réellement NUMA, que le noyau émule NUMA, ou que le périphérique n’a pas de localité NUMA
  • Le noyau Linux prend en charge NUMA depuis la version 2.5, et les distributions basées sur RedHat et Debian fournissent numactl et numad
  • numad surveille la topologie du système et l’utilisation des ressources, et tente de placer les processus ayant une charge mémoire et CPU suffisamment importante dans une localité NUMA efficace

Options pour un traitement des paquets plus rapide

  • AF_PACKET v4 et PACKET_MMAP

    • AF_PACKET v4 est une interface de paquets rapide de Linux, qui élimine les appels système du chemin de données et utilise par défaut le mode copie
    • Avec PACKET_ZEROCOPY, on peut utiliser un véritable mode zero-copy qui mappe les buffers de paquets DMA dans l’espace utilisateur
    • Le chemin classique consistant à lire un fichier puis à envoyer sur une socket nécessite des changements de contexte entre mode utilisateur et mode noyau, ainsi que plusieurs copies de données
    • Le zero-copy améliore les performances en supprimant les copies de données redondantes
    • PACKET_MMAP est une API Linux destinée au sniffing rapide de paquets
    • Elle fournit un ring buffer mappé en mémoire, partagé entre l’espace utilisateur et le noyau
    • Elle réduit les appels système et les copies entre espace utilisateur et noyau pour les paquets envoyés et reçus
  • DPDK

    • DPDK (Data Plane Development Kit) est un ensemble de bibliothèques en espace utilisateur et un framework de pilotes pour le traitement rapide des paquets
    • Son objectif est d’échanger des paquets réseau à vitesse native entre la NIC et l’application utilisateur
    • Il cible les NIC 10 Gb ou 40 Gb, la vitesse étant le critère le plus important
    • Il se concentre sur le forwarding de paquets plutôt que sur la pile réseau
    • Lorsque DPDK contrôle une NIC, tout le trafic contourne le noyau, et cette NIC n’est plus visible depuis le noyau
    • Les ports sont détachés du pilote du noyau Linux et gérés par des pilotes comme vfio_pci, igb_uio ou uio_pci_generic
    • La communication entre l’application et la NIC est ensuite assurée par le PMD DPDK
    • DPDK nécessite la configuration de hugepages afin d’allouer de grands blocs de mémoire
    • Principaux composants :
      • EAL : interface générique qui masque les différences d’environnement
      • librte_ring : API FIFO lockless multi-producteur, multi-consommateur
      • librte_mempool : allocation de pools d’objets mémoire
      • librte_mbuf : création et manipulation de buffers contenant des paquets réseau
      • librte_timer : service de timers pour l’exécution de fonctions asynchrones
      • PMD : pilote dans lequel le CPU sonde en continu la NIC au lieu d’utiliser des interruptions
    • Limites :
      • Forte dépendance au matériel
      • Il faut réserver des cœurs CPU dédiés pour exécuter les PMD, qui utilisent 100 % du CPU
  • PF_RING

    • PF_RING est un module du noyau Linux et un framework en espace utilisateur qui traitent les paquets à haut débit et fournissent une API cohérente aux applications de traitement de paquets
    • PF_RING sonde les paquets sur la NIC via Linux NAPI
    • NAPI copie les paquets depuis la NIC vers le buffer circulaire PF_RING, puis l’application en espace utilisateur lit les paquets depuis le ring
    • Dans cette architecture, deux pollers — l’application et NAPI — consomment des cycles CPU pour le polling
    • Son avantage est de pouvoir répartir simultanément les paquets entrants sur plusieurs rings
    • Grâce à son architecture modulaire, il permet d’utiliser des composants supplémentaires comme le module ZC, le module de cartes FPGA, le module Stack, le module Timeline ou le module Sysdig
    • PF_RING a réduit le coût de la capture de paquets et du forwarding en userland, mais ses performances optimales restent limitées par cette architecture à deux acteurs, où le noyau copie les paquets depuis la NIC vers le ring et où le userland les lit depuis le ring pour les traiter
    • Depuis la version 7.5, PF_RING inclut la prise en charge d’un adaptateur AF_XDP
  • XDP et AF_XDP

    • XDP (eXpress Data Path) est une implémentation eBPF qui intercepte les paquets très tôt dans le chemin de données réseau de Linux
    • XDP traite directement la page du paquet RX dans la fonction RX du pilote de périphérique, avant l’allocation de SKB
    • eBPF est un bytecode personnalisé et sandboxé exécuté dans le noyau
    • Il utilise 11 registres 64 bits et une pile de 512 octets
    • Grâce au backend LLVM, il est possible de compiler vers eBPF depuis C, Lua, Go, P4, Rust, etc.
    • Il fournit un vérificateur in-kernel et un compilateur JIT, et prend en charge des fonctionnalités comme les maps, les tail calls et les helpers
    • Cas d’usage de XDP :
      • Filtrage pre-stack pour l’atténuation des attaques DoS
      • Forwarding et équilibrage de charge
      • Techniques de batching comme GRO
      • Échantillonnage de flux et monitoring
      • Traitement ULP
    • XDP n’est pas un contournement du noyau, mais un fast path au sein de la pile noyau, et ne remplace pas la pile TCP/IP
    • Il ne nécessite pas de matériel dédié, mais implique des prérequis comme une NIC multi-queue, l’offload de checksum TX/RX, RSS ou TSO
    • Avantages de XDP par rapport à DPDK :
      • Possibilité de choisir entre le busy polling et le réseau piloté par interruptions
      • Pas besoin de huge pages
      • Pas d’exigences matérielles spécifiques
      • Un CPU dédié n’est pas indispensable
      • Pas besoin de réinjecter les paquets dans le noyau depuis une application userspace tierce
      • Pas besoin d’un nouveau modèle de sécurité pour l’accès au matériel réseau
      • Pas besoin de code ni de licence tiers
    • AF_XDP est un nouveau type de socket introduit dans Linux 4.18
    • Il permet de construire une architecture similaire à DPDK ou AF_PACKET en exploitant les fonctionnalités du noyau, sans le contourner complètement
    • Un programme XDP peut rediriger des frames vers un buffer mémoire en espace utilisateur via eBPF
    • Le transfert DMA prend en charge le zero-copy en utilisant la mémoire de l’espace utilisateur
    • Il peut atteindre des performances 3 à 20 fois supérieures à AF_PACKET
    • Limites :
      • Projet relativement jeune
      • Une prise en charge complète nécessite Linux kernel 5.4 ou supérieur

1 commentaires

 
GN⁺ 2024-07-29
Commentaires Hacker News
  • Ça m’aurait été vraiment utile si j’avais vu cette ressource ne serait-ce que quelques semaines plus tôt
    J’essayais de mettre en place un chiffrement de lien L2 entre des datacenters, et j’ai demandé des devis pour des appliances matérielles à plusieurs fournisseurs, mais j’ai trouvé les coûts beaucoup trop élevés, alors je l’ai construit moi-même
    Je l’ai configuré sur du matériel générique pour transporter des trames Ethernet sur un réseau overlay WireGuard et atteindre 10 Gbit/s ; après une dizaine de jours de travail, j’ai obtenu une solution environ 70 % moins chère que l’offre la moins chère et environ 95 % moins chère que la plus onéreuse, mais cela a demandé beaucoup de lecture attentive de la documentation et d’expérimentations
    J’aimerais vérifier si ma compréhension correspond bien à ce qui est décrit dans cet article, et même à première vue cela semble prometteur et complet

    • Par curiosité, j’aimerais savoir pour quel usage un tunnel L3 ne suffisait pas
    • Si vous pouvez partager le code, j’aimerais beaucoup le voir. Je suis très curieux de savoir comment vous avez implémenté ça
  • S’il y a autant de paramètres ajustables, ça vaudrait peut-être le coup de créer un logiciel d’auto-tuning
    On pourrait imaginer une approche proche de la descente de gradient : choisir aléatoirement des paramètres d’une whitelist, les augmenter ou diminuer légèrement dans les limites autorisées, mesurer les performances pendant un moment, revenir en arrière si ça se dégrade et continuer à ajuster si ça s’améliore

  • C’est intéressant, mais en tant qu’ingénieur logiciel, j’ai très rarement l’occasion d’exécuter réellement les commandes mentionnées dans l’article
    Les systèmes tournent pour la plupart dans une sorte de conteneur minimal de Linux, je n’ai pas d’accès shell aux systèmes de production, et les environnements de développement ou de QA sont tellement différents de la production en termes de charge qu’ils aident rarement à reproduire les bugs
    Au final, les seules occasions où je peux essayer ce genre de commandes, c’est quand je touche à mes systèmes personnels ; en revanche, ça semble utile si on travaille comme ingénieur plateforme

    • La plupart des fonctionnalités bas niveau ont de toute façon de fortes chances de ne pas fonctionner ou de ne servir à rien. Les implémentations d’interfaces réseau pour conteneurs vous amènent généralement à manipuler des paires veth et à faire toutes sortes de traitements étranges en espace utilisateur
      L’un des aspects de Kubernetes que j’aime le moins, c’est son modèle réseau. Il part du principe qu’il n’y a qu’une seule carte réseau et que les applications sont suffisamment simples pour ne pas avoir besoin de connaître les couches inférieures
      L’ensemble du modèle réseau semble pouvoir bénéficier d’une refonte majeure, dans un esprit plus adapté aux années 2020, pour le simplifier et l’améliorer
    • Si vous disposez d’un environnement de staging aussi proche que possible de la production, il peut être utile selon les cas d’y expérimenter et d’y analyser le comportement, avec un accès à un environnement proche de la prod
  • Il est indiqué que net.core.wmem_max est la limite supérieure de la taille du tampon d’émission TCP, mais il y a aussi net.ipv4.tcp_wmem, donc je me pose deux questions

    1. pourquoi il n’existe pas de valeur équivalente pour IPv6, et 2. en quoi cela diffère de net.core.wmem_max
    • net.core.wmem_max est, comme son nom l’indique, la valeur maximale
      net.ipv4.tcp_wmem est un triplet de trois valeurs — minimum, défaut et maximum — et la valeur maximale définie ici ne peut pas dépasser le net.core.wmem_max mentionné plus haut
      TCP est censé être le même protocole, qu’il soit transporté sur IPv4 ou sur IPv6
      Ex. : https://docs.redhat.com/en/documentation/red_hat_data_grid/7...
  • Ce qui manque un peu ici, c’est le débogage et l’optimisation pour des débits supérieurs à 100 Gbit/s
    À cette échelle, quand on sert du HTTP, le premier goulot d’étranglement est souvent la bande passante mémoire, ce qui rend fréquemment kTLS nécessaire
    Des outils comme AMD μProf sont très utiles pour le débogage, et du profiling continu basé sur eBPF aide aussi à comprendre précisément ce qui se passe dans le noyau et dans l’espace utilisateur

  • Ça a l’air plutôt chouette. Dans ma carrière jusqu’ici, chaque fois que j’avais besoin de performances, je commençais généralement par le kernel bypass