Vous avez migré vers Ubuntu 24.04, la carte réseau semble saine, le CPU s’ennuie, et pourtant l’application tousse : pics de latence bizarres, connexions instables, captures de paquets mensongères, ou réplication de stockage qui subit soudainement un « besoin de bande passante » tout en consommant moins. Quelqu’un dit « désactivez les offloads ». Quelqu’un d’autre dit « ne touchez jamais aux offloads ». Les deux ont partiellement raison, et c’est la forme la plus dangereuse de vérité.
Voici le guide sur le terrain pour prouver quand GRO/LRO/TSO (et leurs voisins) posent problème, comment les désactiver sans empirer la situation, et comment le faire de façon à pouvoir revenir en arrière à 3h du matin sans perdre la dignité.
Ce que font réellement GRO/LRO/TSO (et pourquoi ça casse)
Les offloads NIC sont une bonne affaire : déplacer le travail par paquet du CPU vers la carte réseau augmente le débit et réduit l’utilisation CPU. La facture arrive quand le « paquet » que l’OS croit avoir vu n’est pas ce qui a réellement traversé le câble, ou quand une couche intermédiaire suppose voir des segments de taille normale alors qu’elle reçoit un monstre coalescé.
GRO : Generic Receive Offload
GRO est une fonction logicielle Linux qui fusionne plusieurs paquets entrants en un « super-paquet » plus grand avant de le remonter dans la pile. Ça réduit le traitement par paquet et les interruptions. Super pour le débit. Mauvais quand vous avez besoin d’un timing précis par paquet, lorsque vos outils de capture s’attendent à voir la réalité telle quelle, ou quand un bug dans le pilote/chemin noyau gère mal les frontières de segmentation.
GRO n’est pas une caractéristique du câble. C’est une optimisation locale. Le câble transporte toujours des trames MTU normales. Votre hôte peut afficher moins de paquets plus grands dans les captures et compteurs parce que la pile les a fusionnés.
LRO : Large Receive Offload
LRO est généralement une coalescence côté carte/driver. Elle peut être encore plus agressive que GRO. Elle est aussi plus problématique en présence de routage, tunnels, VLANs, et tout ce qui attend des frontières de paquets strictes. Beaucoup d’environnements la gardent désactivée, notamment en virtualisation ou sur des réseaux à overlays importants.
TSO/GSO : segmentation à la transmission (matériel ou logiciel)
TSO (TCP Segmentation Offload) permet au noyau de remettre une grosse charge TCP à la NIC qui la découpe ensuite en segments de taille MSS et calcule les checksums. GSO (Generic Segmentation Offload) est l’équivalent logiciel pour les protocoles que la NIC ne connaît pas. C’est généralement sûr et bénéfique—jusqu’à ce que ça ne le soit plus : bugs de pilote, défaillances de checksum, interactions étranges avec des tunnels, ou équipements sur le chemin qui se comportent mal sous certains motifs d’explosion/segment.
Offloads de checksum : le perturbateur subtil
Le calcul/validation des checksums Rx/Tx peut être fait par le matériel NIC. Les captures prises sur l’hôte peuvent afficher des « bad checksum » parce que le checksum n’était pas encore rempli au point de capture. Ce n’est pas nécessairement un réseau cassé ; c’est une hypothèse erronée.
Une idée paraphrasée de John Allspaw (opérations/fiabilité) : « Les incidents arrivent quand la réalité diverge de notre modèle mental. » Les offloads sont une machine à fabriquer cette divergence.
Blague n°1 : Les offloads, c’est comme embaucher des stagiaires pour la paperasse—rapide et peu coûteux jusqu’à ce qu’ils « optimisent » votre système de classement en art moderne.
Faits et historique : pourquoi ça revient sans cesse
- Fait 1 : LRO précède GRO et était largement désactivé dans les scénarios de routage/tunneling car il peut fusionner des paquets d’une manière qui casse les hypothèses de forwarding.
- Fait 2 : GRO a été introduit comme alternative plus sûre et consciente de la pile à LRO, mais il change toujours la visibilité des paquets pour des outils comme tcpdump et les consommateurs AF_PACKET.
- Fait 3 : TSO est devenu courant quand 1 Gbit/s est devenu 10/25/40/100+ Gbit/s ; les CPU ne peuvent plus se permettre le surcoût par paquet aux débits modernes.
- Fait 4 : « Bad checksum » dans tcpdump sur l’hôte émetteur est souvent un artefact de capture lié au checksum offload, pas un échec réel sur le câble.
- Fait 5 : Beaucoup de CNIs et stacks d’overlay (VXLAN/Geneve) ont connu des périodes où les combinaisons d’offloads étaient boguées jusqu’à maturation des pilotes et noyaux.
- Fait 6 : RSS (Receive Side Scaling) et RPS/XPS ont été développés parce que le traitement de réception sur un seul cœur est devenu un goulot bien avant la bande passante NIC.
- Fait 7 : La modulation/coalescence d’IRQ peut provoquer des pics de latence sous faible trafic même si elle améliore le débit en charge.
- Fait 8 : La virtualisation ajoute une couche : virtio-net et vhost peuvent faire leur propre batch/coalescence, ce qui augmente les effets d’offload.
- Fait 9 : La précision des captures a toujours été « meilleur effort » une fois que vous ajoutez des offloads ; capter sur un SPAN/TAP ou sur un routeur raconte souvent une histoire différente de la capture sur le point final.
Méthode de diagnostic rapide (premier/deuxième/troisième)
Première étape : décidez si vous déboguez la correction ou la performance
Si vous avez corruption de données, sessions cassées, réinitialisations étranges, ou comportement « n’échoue qu’en charge », traitez-le comme un problème de correction jusqu’à preuve du contraire. L’optimisation de performance peut attendre. Désactiver les offloads est un test de correction valide même si cela coûte du débit.
Deuxième étape : trouvez le point d’étranglement en une passe
- Cherchez retransmissions, drops et resets. Si les retransmissions TCP augmentent alors que l’utilisation du lien est faible, vous avez une perte ou un réordonnancement (réel ou apparent).
- Vérifiez la saturation CPU par softirq. Si ksoftirqd ou un noyau unique est saturé, vous êtes limité par le taux de paquets ou mal dirigé (problème RSS/affinité IRQ).
- Comparez compteurs hôte vs switch. Si l’hôte indique des « drops » mais que le port du switch ne le montre pas, votre problème est probablement dans la pile hôte/driver/offload.
Troisième étape : exécutez deux tests A/B contrôlés
- A/B offloads : basculez GRO/LRO/TSO de façon ciblée, mesurez latence/retransmissions/débit.
- A/B MTU et chemin : testez MTU standard vs jumbo, et hôte-à-hôte direct vs via overlay/VPN.
Votre objectif n’est pas « faire grimper les chiffres ». Votre objectif est : prouver la causalité, puis appliquer la plus petite correction qui supprime le mode de défaillance.
Tâches pratiques : commandes, sorties, décisions (12+)
Ce ne sont pas des commandes jouets. Ce sont celles que vous exécutez quand vous êtes en astreinte et que votre graphe vous ment. Chaque tâche inclut ce qu’il faut regarder et quelle décision prendre.
Tâche 1 : Identifier l’interface réelle et le pilote
cr0x@server:~$ ip -br link
lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
enp5s0f0 UP 3c:fd:fe:aa:bb:cc <BROADCAST,MULTICAST,UP,LOWER_UP>
enp5s0f1 DOWN 3c:fd:fe:aa:bb:cd <BROADCAST,MULTICAST>
Sens : Choisissez l’interface qui transporte le trafic (ici : enp5s0f0). « UP, LOWER_UP » signifie que le lien est actif.
Décision : Ne touchez aux offloads que sur l’interface active. Ne faites pas de changements en rafale sur toutes les NICs sauf si vous aimez jouer aux devinettes.
cr0x@server:~$ sudo ethtool -i enp5s0f0
driver: ixgbe
version: 6.8.0-41-generic
firmware-version: 0x800003e7
bus-info: 0000:05:00.0
supports-statistics: yes
supports-test: yes
supports-eeprom-access: yes
supports-register-dump: yes
supports-priv-flags: no
Sens : Le pilote et le firmware comptent. « Ça marchait sur 22.04 » n’est pas une preuve ; c’est un souvenir.
Décision : Si les problèmes sont apparus après un changement de noyau/firmware, gardez cette hypothèse dans votre liste.
Tâche 2 : Inventaire des paramètres d’offload courants (baseline)
cr0x@server:~$ sudo ethtool -k enp5s0f0
Features for enp5s0f0:
rx-checksumming: on
tx-checksumming: on
scatter-gather: on
tcp-segmentation-offload: on
generic-segmentation-offload: on
generic-receive-offload: on
large-receive-offload: off
rx-vlan-offload: on
tx-vlan-offload: on
Sens : C’est votre point de départ. Notez ce qui est déjà désactivé (LRO l’est souvent).
Décision : Copiez ceci dans vos notes d’incident. Quand vous reviendrez en arrière, revenez aux faits, pas aux impressions.
Tâche 3 : Vérifier si vous voyez des retransmissions (souvent le premier indice « offload a cassé »)
cr0x@server:~$ nstat -az | egrep 'Tcp(RetransSegs|ExtTCPSynRetrans|OutRsts|InErrs)'
TcpRetransSegs 1842 0.0
TcpExtTCPSynRetrans 17 0.0
TcpOutRsts 92 0.0
IpInErrs 0 0.0
Sens : Une augmentation de TcpRetransSegs pendant une charge pointe vers de la perte, du réordonnancement, ou des bizarreries de chemin.
Décision : Si les retransmissions augmentent alors que le CPU et l’utilisation du lien semblent normaux, suspectez les interactions pilote/offload/tunnel avant d’accuser « le réseau ».
Tâche 4 : Prouver si les drops sont sur la NIC, dans la pile, ou ailleurs
cr0x@server:~$ ip -s link show enp5s0f0
2: enp5s0f0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
link/ether 3c:fd:fe:aa:bb:cc brd ff:ff:ff:ff:ff:ff
RX: bytes packets errors dropped missed mcast
9876543210 9123456 0 18421 0 1234
TX: bytes packets errors dropped carrier collsns
8765432109 8234567 0 0 0 0
Sens : Les drops RX ici sont visibles par l’hôte. Ils peuvent être des overruns de ring, un backlog CPU, ou un comportement du driver.
Décision : Si les drops RX augmentent pendant la charge, examinez la taille des anneaux, la distribution des IRQ, et GRO/LRO avant d’ajuster les timeouts applicatifs.
Tâche 5 : Voir si softirq est le véritable goulot
cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.8.0-41-generic (server) 12/30/2025 _x86_64_ (32 CPU)
12:00:01 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
12:00:02 AM all 4.2 0.0 6.1 0.1 0.3 7.8 0.0 0.0 0.0 81.5
12:00:02 AM 7 2.1 0.0 4.9 0.0 0.2 48.7 0.0 0.0 0.0 44.1
Sens : Un CPU avec un %soft très élevé indique que le traitement de réception est concentré sur une file/IRQ.
Décision : Avant de désactiver les offloads « parce que internet », vérifiez le RSS/affinité IRQ. Les offloads ne sont pas votre seul levier.
Tâche 6 : Vérifier la distribution des interruptions et si une file monopolise
cr0x@server:~$ awk '/enp5s0f0/ {print}' /proc/interrupts | head
74: 1283921 2031 1888 1999 2101 1902 1988 2010 PCI-MSI 524288-edge enp5s0f0-TxRx-0
75: 1932 1290033 1890 2011 1998 1887 2002 2017 PCI-MSI 524289-edge enp5s0f0-TxRx-1
Sens : Cela semble relativement équilibré. Si vous voyez un compte d’IRQ qui écrase les autres, le steering RSS ou l’affinité est incorrecte.
Décision : Corrigez le steering (RSS/affinité) avant de désactiver GRO et de potentiellement propulser le taux de paquets contre un mur CPU.
Tâche 7 : Vérifier la taille des anneaux (les drops peuvent être une simple famine de buffers)
cr0x@server:~$ sudo ethtool -g enp5s0f0
Ring parameters for enp5s0f0:
Pre-set maximums:
RX: 4096
RX Mini: 0
RX Jumbo: 0
TX: 4096
Current hardware settings:
RX: 512
RX Mini: 0
RX Jumbo: 0
TX: 512
Sens : Les anneaux actuels sont plus petits que le maximum.
Décision : Si vous avez des drops RX sous charge explosive, augmentez les anneaux avant de blâmer GRO. De plus grands anneaux augmentent légèrement la latence mais peuvent prévenir la perte.
Tâche 8 : Confirmer la vitesse/duplex du lien et détecter un autoneg bizarre
cr0x@server:~$ sudo ethtool enp5s0f0 | egrep 'Speed|Duplex|Auto-negotiation|Link detected'
Speed: 10000Mb/s
Duplex: Full
Auto-negotiation: on
Link detected: yes
Sens : Évident, mais vous seriez surpris de voir combien de « bugs réseau » sont en réalité un fallback à 1G.
Décision : Si la vitesse est incorrecte, arrêtez-vous. Réparez le lien/optique/câble/port du switch avant de chasser les offloads.
Tâche 9 : Utiliser tcpdump correctement quand des offloads sont impliqués
cr0x@server:~$ sudo tcpdump -i enp5s0f0 -nn -s 96 tcp and port 443 -c 5
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on enp5s0f0, link-type EN10MB (Ethernet), snapshot length 96 bytes
12:00:10.123456 IP 10.0.0.10.51532 > 10.0.0.20.443: Flags [S], seq 123456789, win 64240, options [mss 1460,sackOK,TS val 111 ecr 0,nop,wscale 7], length 0
12:00:10.123789 IP 10.0.0.20.443 > 10.0.0.10.51532: Flags [S.], seq 987654321, ack 123456790, win 65160, options [mss 1460,sackOK,TS val 222 ecr 111,nop,wscale 7], length 0
Sens : tcpdump sur le point final reste utile pour l’établissement de connexion et le timing. Mais la segmentation du payload et les checksums peuvent vous induire en erreur.
Décision : Si vous diagnostiquez une perte de paquets ou des problèmes MTU, envisagez de capturer sur un SPAN/TAP du switch ou désactivez GRO temporairement pendant la fenêtre de capture.
Tâche 10 : Vérifier les problèmes de chemin MTU (les offloads peuvent parfois les masquer/déclencher)
cr0x@server:~$ ping -c 3 -M do -s 8972 10.0.0.20
PING 10.0.0.20 (10.0.0.20) 8972(9000) bytes of data.
ping: local error: message too long, mtu=1500
ping: local error: message too long, mtu=1500
ping: local error: message too long, mtu=1500
--- 10.0.0.20 ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2049ms
Sens : Votre interface MTU est 1500, donc le ping jumbo échoue localement. C’est normal si vous attendez 1500.
Décision : Ne mélangez pas les hypothèses jumbo avec les attentes TSO/GSO. Si vous avez besoin de jumbo, configurez-le partout, puis retestez les offloads.
Tâche 11 : Mesurer débit et CPU avec iperf3 (baseline avant changement d’offloads)
cr0x@server:~$ iperf3 -c 10.0.0.20 -P 4 -t 10
Connecting to host 10.0.0.20, port 5201
[SUM] 0.00-10.00 sec 10.9 GBytes 9.35 Gbits/sec 0 sender
[SUM] 0.00-10.00 sec 10.8 GBytes 9.29 Gbits/sec receiver
Sens : Bon baseline. Si les offloads sont défaillants, on voit souvent un effondrement du débit avec retransmissions ou un CPU délirant.
Décision : Enregistrez cela. Tout changement que vous ferez doit l’égaler ou corriger la correction sans régression inacceptable.
Tâche 12 : Désactiver GRO temporairement et voir si les symptômes bougent
cr0x@server:~$ sudo ethtool -K enp5s0f0 gro off
cr0x@server:~$ sudo ethtool -k enp5s0f0 | egrep 'generic-receive-offload|large-receive-offload'
generic-receive-offload: off
large-receive-offload: off
Sens : GRO est maintenant désactivé. LRO reste désactivé.
Décision : Retestez la charge fautive et surveillez retransmissions/latence. Si la correction s’améliore immédiatement, GRO faisait au moins partie du mode de défaillance.
Tâche 13 : Désactiver TSO/GSO (prudent : peut augmenter CPU/taux de paquets)
cr0x@server:~$ sudo ethtool -K enp5s0f0 tso off gso off
cr0x@server:~$ sudo ethtool -k enp5s0f0 | egrep 'tcp-segmentation-offload|generic-segmentation-offload'
tcp-segmentation-offload: off
generic-segmentation-offload: off
Sens : La segmentation à l’émission se fera en plus petits morceaux ou entièrement en logiciel, selon la pile et la NIC.
Décision : Si cela résout des blocages/retransmissions sur certains chemins (surtout tunnels), conservez-le comme un fort signal d’interaction pilote/firmware/overlay. Ensuite, décidez comment cibler le changement.
Tâche 14 : Vérifier les statistiques côté pilote pour signes d’alerte (drops, missed, errors)
cr0x@server:~$ sudo ethtool -S enp5s0f0 | egrep -i 'drop|dropped|miss|error|timeout' | head -n 20
rx_missed_errors: 0
rx_no_buffer_count: 124
rx_errors: 0
tx_timeout_count: 0
Sens : rx_no_buffer_count suggère une famine de buffers de réception ; c’est souvent la taille des anneaux, le CPU, ou le comportement en rafale.
Décision : Augmentez les anneaux, ajustez la modulation d’IRQ, ou réduisez la rafale avant de désactiver définitivement les offloads sur toute la flotte.
Tâche 15 : Regarder qdisc et la mise en file (les pics de latence peuvent être locaux)
cr0x@server:~$ tc -s qdisc show dev enp5s0f0
qdisc mq 0: root
qdisc fq_codel 0: parent :1 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn
Sent 812345678 bytes 8234567 pkt (dropped 0, overlimits 0 requeues 12)
backlog 0b 0p requeues 12
Sens : Les stats du qdisc montrent drops/requeues. Toute la douleur n’est pas forcément sur le câble.
Décision : Si vous voyez des drops locaux de qdisc, désactiver GRO ne vous sauvera pas ; vous avez des problèmes de mise en file/bufferbloat ou de shaping.
Tâche 16 : Valider conntrack ou le chemin pare-feu (souvent blâmé à tort)
cr0x@server:~$ sudo conntrack -S | egrep 'insert_failed|drop|invalid'
insert_failed=0
drop=0
invalid=0
Sens : Conntrack ne fond pas. Bien.
Décision : Si les compteurs conntrack drop/insert_failed augmentent, vous avez un problème de table d’état ; ne le « corrigez » pas en basculant GRO.
Comment désactiver les offloads en toute sécurité (temporaire, persistant, ciblé)
L’approche sécurisée est ennuyeuse : isoler, tester, mesurer, ne persister que ce qui est nécessaire, et documenter le rollback. Désactiver les offloads peut absolument corriger des problèmes réels. Cela peut aussi transformer un problème de débit en incident CPU et alors vous aurez deux incidents pour le prix d’un.
Changements temporaires (runtime uniquement)
Utilisez ethtool -K pour un test A/B immédiat. Cela ne survit pas au reboot. C’est une fonctionnalité quand vous expérimentez.
cr0x@server:~$ sudo ethtool -K enp5s0f0 gro off lro off tso off gso off rx off tx off
Cannot change rx-checksumming
Cannot change tx-checksumming
Sens : Certaines fonctions ne peuvent pas être basculées sur certains pilotes/NICs. C’est normal.
Décision : Ne vous battez pas contre le matériel. Basculez ce que vous pouvez, puis ajustez votre plan de test. Souvent, les bascules GRO/TSO sont les plus impactantes de toute façon.
Changements persistants avec systemd-networkd (la méthode native sensée d’Ubuntu 24.04)
Sur Ubuntu 24.04, beaucoup de serveurs utilisent systemd-networkd même si vous définissez la configuration avec netplan. L’idée : vous voulez que les offloads soient appliqués au moment du link-up, pas par un script manuel que « quelqu’un » a oublié d’installer sur la moitié de la flotte.
Créez un fichier .link pour matcher l’interface par nom ou MAC et appliquer les paramètres d’offload. Exemple de correspondance par nom :
cr0x@server:~$ sudo tee /etc/systemd/network/10-enp5s0f0.link >/dev/null <<'EOF'
[Match]
OriginalName=enp5s0f0
[Link]
GenericReceiveOffload=false
TCPSegmentationOffload=false
GenericSegmentationOffload=false
LargeReceiveOffload=false
EOF
cr0x@server:~$ sudo systemctl restart systemd-networkd
cr0x@server:~$ sudo ethtool -k enp5s0f0 | egrep 'generic-receive-offload|tcp-segmentation-offload|generic-segmentation-offload|large-receive-offload'
tcp-segmentation-offload: off
generic-segmentation-offload: off
generic-receive-offload: off
large-receive-offload: off
Sens : Les offloads sont appliqués après redémarrage/renégociation du lien.
Décision : Si la configuration persistante s’applique proprement et corrige le problème sans coût CPU inacceptable, vous pouvez la déployer progressivement.
Changements persistants avec une unité systemd oneshot (fonctionne partout, moins élégant)
Si vous ne pouvez pas compter sur les liens systemd-networkd (environnements mixtes, nommage NIC personnalisé, ou vous voulez quelque chose de franc), utilisez une unité systemd oneshot qui s’exécute après que le réseau est up.
cr0x@server:~$ sudo tee /etc/systemd/system/ethtool-offloads@.service >/dev/null <<'EOF'
[Unit]
Description=Set NIC offloads for %I
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/ethtool -K %I gro off lro off tso off gso off
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
cr0x@server:~$ sudo systemctl enable --now ethtool-offloads@enp5s0f0.service
Created symlink /etc/systemd/system/multi-user.target.wants/ethtool-offloads@enp5s0f0.service → /etc/systemd/system/ethtool-offloads@.service.
Sens : Les offloads sont définis au démarrage pour cette interface.
Décision : Utilisez ceci quand vous avez besoin d’un comportement prévisible rapidement. Puis remplacez par une config link-level plus propre plus tard.
Limiter la portée : désactiver uniquement ce qui est nécessaire
En pratique :
- Si les captures sont trompeuses ou qu’un consommateur utilisateur-espace de paquets est confus : désactivez GRO (et parfois le checksum offload) temporairement pour le diagnostic.
- Si les tunnels/overlays se comportent mal : essayez d’abord de désactiver TSO/GSO, puis GRO.
- Si vous faites du routage/bridging : gardez LRO désactivé. La plupart des environnements de production ne l’activent jamais.
Vérifiez que vous n’avez pas « réparé » en affamant le CPU
Après avoir désactivé les offloads, relancez votre charge et surveillez :
- %soft CPU (charge softirq)
- RX drops et
rx_no_buffer_count - latence p99 et retransmissions
Blague n°2 : Le moyen le plus rapide de prouver que les offloads « ont résolu » un problème, c’est de créer un nouveau goulot CPU—la nature abhorre le vide, et le réseau Linux aussi.
Trois mini-récits du monde de l’entreprise (anonymisés, plausibles, techniquement exacts)
1) Incident causé par une mauvaise hypothèse : « Bad checksums signifie que le réseau corrompt les paquets »
Une équipe paiements a constaté des échecs TLS intermittents après avoir déplacé un service sur de nouveaux hôtes Ubuntu 24.04. Une capture de paquets depuis l’hôte client montrait une parade d’avertissements « bad checksum ». La conclusion immédiate fut prévisible : l’équipement réseau malmène les paquets. L’équipe réseau a été appelée, une war room ouverte, et tout le monde a commencé à chasser des fantômes.
La première hypothèse fut l’erreur : qu’un avertissement de checksum dans une capture côté hôte prouve une corruption sur le fil. Sur Linux moderne, avec le TX checksum offload activé, tcpdump peut attraper les paquets avant que la NIC ne remplisse le checksum. Le paquet sur le fil est correct ; le paquet dans votre capture est incomplet à ce point précis.
La deuxième erreur fut l’escalade par screenshot. Un ingénieur senior a finalement demandé deux choses : une capture depuis un port SPAN du switch, et la sortie de ethtool -k. La capture SPAN montrait des checksums valides. La capture endpoint paraissait « mauvaise » uniquement quand les offloads étaient activés.
Le vrai problème s’est avéré sans rapport avec les checksums : une table conntrack mal dimensionnée sur un hôte gateway partagé larguait des connexions sous charge en rafale. Les offloads étaient innocents ; l’outil de capture était trompeur.
Ce qui a changé la prise de décision : ils ont mis à jour le runbook d’astreinte pour traiter « bad checksum » comme un artefact diagnostique sauf confirmation hors hôte. Ils ont aussi standardisé une méthode « capture avec offloads désactivés pendant 2 minutes » quand une capture endpoint est requise.
2) Optimisation qui a mal tourné : « Activer tous les offloads pour des performances maximales »
Un groupe plateforme exécutant des workloads conteneurisés avait pour mandat d’améliorer la densité de nœuds. Quelqu’un a remarqué que certains nœuds avaient LRO désactivé et a décidé de « normaliser » la flotte pour le débit. Ils ont poussé un changement pour activer tout ce que la NIC annonçait. Les benchmarks de performance semblaient excellents en test synthétique. La modification est passée en production.
Deux jours plus tard, la file support s’est remplie d’étrangetés : flux gRPC qui se bloquaient, timeouts sporadiques entre pods, et un motif où les échecs étaient plus fréquents sur les nœuds avec beaucoup de trafic est-ouest. Le CPU était correct. Le réseau était correct. Les logs n’aidaient pas. L’incident avait cette odeur spéciale : tout est normal sauf l’expérience client.
Le coupable fut LRO interagissant mal avec le trafic encapsulé et la façon dont certains composants observaient les frontières de paquets. Le système ne « perdait » pas tant des paquets que créait un agrégat étrange qui exposait des bugs en bordure dans le chemin overlay. Désactiver LRO a résolu immédiatement.
La leçon fut simple : les offloads ne sont pas des « flags de performance gratuits ». Ce sont des changements de comportement. Si votre environnement utilise des overlays, midboxes, ou datapaths avancés, traitez les offloads comme des upgrades du noyau : testez-les sur du trafic représentatif, pas seulement avec iperf.
Ils sont revenus à une baseline conservative : LRO off partout, garder TSO/GSO activés sauf preuve du contraire, et autoriser GRO seulement là où il n’interfère pas avec l’observabilité ou les composants de traitement de paquets.
3) Pratique ennuyeuse mais correcte qui a sauvé la situation : « A/B tester sur un seul hôte avec timer de rollback »
Une équipe stockage gérant du trafic de réplication sur des liens 25G a commencé à observer des pics de latence de réplication après une refresh OS. Pas de perte de paquets évidente, mais le retard était réel et corrélé aux périodes d’activité. La première impulsion fut d’ajuster l’application et d’ajouter de la bande passante. Ils ont résisté.
Leur SRE lead a insisté sur une expérience un-hôte : choisir un expéditeur et un récepteur, isoler le chemin, et basculer les offloads dans une matrice contrôlée (GRO seulement, TSO seulement, les deux). Chaque changement avait la commande de rollback pré-écrite, et ils utilisaient un job temporisé pour rétablir les paramètres après 20 minutes sauf annulation explicite. Ennuyeux. Correct.
L’expérience a montré quelque chose d’actionnable : désactiver TSO/GSO supprimait les pics de latence mais augmentait le CPU de façon notable. Désactiver GRO avait un effet minimal. Cela a restreint le coupable aux interactions de segmentation à la transmission, pas à la coalescence de réception.
Avec cette preuve, ils ont mis à jour le firmware NIC sur le modèle affecté et ont retesté. Après la mise à jour firmware, TSO/GSO ont pu rester activés. Ils ont évité une taxe CPU permanente et n’ont pas eu à ré-architecturer la topologie stockage.
La pratique qui a sauvé fut moins une astuce sysctl qu’une discipline : une modification, un hôte, un résultat mesurable, rollback garanti.
Erreurs courantes : symptôme → cause racine → correctif
1) Symbole : tcpdump montre « bad checksum » sur les paquets sortants
Cause racine : TX checksum offload ; tcpdump a capturé avant que le checksum soit calculé.
Correctif : Capturez sur SPAN/TAP, ou désactivez brièvement le TX checksum offload pour la capture (ethtool -K IFACE tx off) et revérifiez.
2) Symbole : pics de latence p99 sous faible trafic, débit correct sous forte charge
Cause racine : modulation/coalescence d’interruptions réglée pour le débit ; le CPU est réveillé moins souvent, ajoutant de la latence.
Correctif : Ajustez la coalescence d’IRQ de la NIC (ethtool -c/-C), et seulement après envisagez des changements GRO.
3) Symbole : réseau pod-à-pod Kubernetes instable après upgrade
Cause racine : interaction offload + overlay/tunnel (TSO/GSO/GRO avec VXLAN/Geneve), parfois spécifique au pilote.
Correctif : Désactivez en A/B TSO/GSO d’abord sur les nœuds affectés ; gardez LRO off. Confirmez avec retransmissions et tests de charge.
4) Symbole : RX drops augmentent sur l’hôte pendant des rafales, le switch affiche des compteurs propres
Cause racine : famine de buffers/anneau de réception sur l’hôte ou backlog softirq ; pas forcément une perte externe.
Correctif : Augmentez la taille des anneaux (ethtool -G), confirmez la distribution IRQ/RSS, puis reconsidérez GRO/TSO si nécessaire.
5) Symbole : après désactivation des offloads, la performance s’effondre et le CPU explose
Cause racine : Vous avez supprimé l’agrégation, augmenté le taux de paquets et le coût par paquet, et atteint les limites CPU/softirq.
Correctif : Réactivez TSO/GSO, gardez LRO off, envisagez de laisser GRO activé. Améliorez le steering (RSS), les tailles d’anneaux et l’affinité IRQ.
6) Symbole : les captures montrent des « paquets » géants plus grands que la MTU
Cause racine : GRO/LRO présentant des skbs coalescés au point de capture ; pas une violation de MTU sur le câble.
Correctif : Désactivez GRO/LRO pour la fenêtre de capture, ou capturez hors-hôte.
7) Symbole : réplication stockage ou iSCSI/NFS se comporte pire avec « plus d’optimisation »
Cause racine : les motifs de rafale et le backpressure changés par les offloads ; bugs du pilote sous segments larges soutenus.
Correctif : Testez en A/B TSO/GSO ; surveillez retransmissions et CPU. Si la désactivation aide, vérifiez firmware/driver et envisagez de cibler les changements d’offload aux VLANs/interfaces de stockage.
Listes de contrôle / plan pas-à-pas
Étapes : prouver que les offloads sont le problème (et pas seulement « différents »)
- Baseline : enregistrez
ethtool -k,ethtool -i,ip -s link,nstat. - Reproduire : exécutez la charge réelle, pas seulement iperf. Capturez p95/p99 latence, retransmissions et compteurs d’erreur.
- Bascule unique : désactivez uniquement GRO. Retestez. Si un changement est visible, continuez ; sinon, restaurez.
- Deuxième bascule : désactivez TSO/GSO. Retestez. Surveillez CPU et softirq.
- Décider la portée : si une seule classe de trafic casse (overlay, VLAN stockage), préférez cibler le changement à ces nœuds ou interfaces.
- Plan de rollback : écrivez les commandes exactes de revert et vérifiez qu’elles fonctionnent.
Checklist de changement (comment ne pas devenir l’incident)
- Faites-le d’abord sur un seul hôte. Puis sur un petit pool canari. Puis étendez.
- Gardez LRO off à moins d’une raison mesurée et d’un chemin L2/L3 simple.
- Ne désactivez pas tout d’un coup. GRO et TSO affectent des côtés différents de la pile.
- Surveillez CPU softirq et RX drops après les changements. S’ils grimpent, vous avez déplacé le goulot.
- Persistiez la config via des fichiers link systemd ou des unités systemd, pas du folklore rc.local.
- Documentez : interface, driver, firmware, version kernel, matrice d’offloads et résultat mesuré.
Checklist de rollback (écrivez-la avant de changer quoi que ce soit)
cr0x@server:~$ sudo ethtool -K enp5s0f0 gro on lro off tso on gso on
Sens : Exemple de rollback vers une baseline conservative : garder LRO off, réactiver GRO/TSO/GSO.
Décision : Si le rollback ne restaure pas le comportement, vous avez appris que les offloads n’étaient pas la cause racine. Arrêtez de changer les offloads et élargissez la recherche.
Optionnel : changement de taille d’anneau (uniquement si les drops pointent là)
cr0x@server:~$ sudo ethtool -G enp5s0f0 rx 2048 tx 2048
cr0x@server:~$ sudo ethtool -g enp5s0f0 | egrep 'Current hardware settings|RX:|TX:' -A4
Current hardware settings:
RX: 2048
RX Mini: 0
RX Jumbo: 0
TX: 2048
Sens : De plus grands anneaux réduisent les drops sous micro-rafales mais peuvent augmenter le buffering/la latence.
Décision : Si votre problème est « drops sous micro-rafales », c’est souvent plus correct que de désactiver GRO.
FAQ
1) Dois-je désactiver GRO/LRO/TSO par défaut sur Ubuntu 24.04 ?
Non. Les offloads par défaut sont généralement corrects pour les workloads mainstream. Désactivez uniquement quand vous pouvez montrer un problème de correction ou une régression de performance mesurable liée aux offloads.
2) Pourquoi désactiver les offloads corrige parfois une perte de paquets qui « n’est pas réelle » ?
Parce que vous changez le timing, l’agrégation et les motifs de segmentation. Si un chemin pilote/firmware a un bug sous certaines tailles de segment ou motifs de rafales, changer les offloads peut éviter le déclencheur.
3) Si LRO est si problématique, pourquoi existe-t-elle ?
Elle a été conçue pour le débit sur des chemins plus simples, souvent dans des environnements plus anciens ou contrôlés. Les réseaux modernes (overlays, virtualisation, routage dans l’hôte) ont rendu ses cas limites plus coûteux que ses gains pour beaucoup d’équipes.
4) « Bad checksum » dans tcpdump est-il toujours bénin ?
Pas toujours, mais c’est souvent un artefact d’offload. Validez en capturant hors-hôte ou en désactivant brièvement le checksum offload. Si le problème se reproduit hors-hôte avec des checksums invalides, alors c’est réel.
5) Quelle est la différence pratique entre TSO et GSO ?
TSO est la segmentation TCP réalisée par le matériel NIC. GSO est un cadre logiciel générique qui permet au noyau de gérer la segmentation de façon similaire pour d’autres protocoles ou quand le matériel ne peut pas.
6) Désactiver TSO/GSO augmentera-t-il la latence ?
Ça peut aller dans les deux sens. Cela augmente souvent le travail CPU et le taux de paquets, ce qui peut accroître l’ordonnancement en file sous charge. Mais cela peut réduire la rafale et éviter certains problèmes pilote/tunnel, améliorant la latence tail dans des scénarios spécifiques.
7) J’ai désactivé GRO et mes captures ont l’air « normales » maintenant. Ai-je réparé la production ?
Vous avez réparé l’observabilité. C’est précieux, mais ce n’est pas la même chose que réparer le comportement produit. Réactivez GRO après la capture sauf si vous avez des preuves que GRO causait des problèmes visibles par les utilisateurs.
8) Puis-je désactiver les offloads seulement pour un VLAN, un bridge ou un tunnel ?
Les offloads se configurent typiquement par interface physique ou virtuelle. Vous pouvez appliquer des paramètres à l’interface qui termine votre trafic (ex. la NIC physique, le bond, ou le veth/bridge dans certains cas), mais la granularité « par VLAN » est limitée et dépend du pilote.
9) Comment savoir si je suis lié CPU après avoir désactivé les offloads ?
Surveillez mpstat pour un %soft élevé, vérifiez /proc/interrupts pour un déséquilibre, et regardez la montée des RX drops ou de rx_no_buffer_count. Si ceux-ci augmentent, vous avez échangé un problème réseau contre un problème de traitement hôte.
10) Est-ce qu’Ubuntu 24.04 change lui-même les offloads par rapport à 22.04 ?
Le changement le plus significatif est le noyau, les pilotes, et la façon dont votre firmware NIC interagit avec eux. Les versions d’Ubuntu peuvent déplacer des valeurs par défaut, mais la plupart des histoires « ça a changé après la mise à jour » sont en réalité des changements de comportement pilote/firmware sous les mêmes flags fonctionnels.
Conclusion : prochaines étapes à déployer
GRO/LRO/TSO ne sont pas des méchants. Ce sont des outils puissants. Si vous les utilisez sans comprendre ce qu’ils modifient, vous finirez par trancher dans votre propre modèle mental et perdre du temps dans une war room.
- Exécutez la méthode de diagnostic rapide et décidez si vous poursuivez la correction ou le débit.
- Faites un baseline avec
ethtool -k,nstat,ip -s linket les statistiques softirq CPU. - Testez en A/B une bascule à la fois : GRO d’abord pour l’observabilité/comportement de réception, TSO/GSO pour les bizarreries de transmission/overlay.
- Persistez le plus petit changement en utilisant un fichier
.linksystemd ou une unité oneshot, et canarisez le déploiement. - Vérifiez que vous n’avez pas créé un goulot CPU et que les retransmissions/drops se sont réellement améliorés.
Si vous ne retenez qu’une règle opiniâtre : gardez LRO off, ne désactivez pas TSO/GSO à la légère, et considérez GRO à la fois comme un réglage de performance et un risque pour l’observabilité. Testez sérieusement.