Réseau Linux : pertes de paquets « parfois seulement » — le vrai flux de débogage

Cet article vous a aidé ?

La perte de paquets intermittente est le pire type d’incident : elle esquive les graphiques, se cache pendant les conférences d’incident et n’apparaît que lorsque votre PDG rejoint la visioconférence générale. L’équipe applicative dit « réseau ». L’équipe réseau dit « serveurs ». Quelqu’un propose de redémarrer « juste pour nettoyer ».

Voici le workflow de production qui met fin à la discussion : vous prouvez les paquets sont perdus, en utilisant des compteurs Linux et des captures spécifiques, puis vous corrigez le goulot qui est réellement responsable de la perte. Pas de vibes. Des preuves.

Un modèle mental impitoyable : où les paquets sont perdus

« Perte de paquets » est un symptôme, pas un emplacement. Un paquet peut être perdu à de nombreux endroits, et Linux vous donne des compteurs pour la plupart d’entre eux. L’astuce consiste à savoir quels compteurs sont adjacents au domaine de perte que vous investiguez.

Pensez en domaines de perte, pas en outils

Quand les gens sont bloqués, ils choisissent généralement un outil (ping, traceroute, tcpdump) et continuent à l’utiliser plus intensément. Les outils sont utiles. Mais le bon flux est : identifier le domaine, puis choisir l’ensemble minimal d’outils pour le prouver.

Domaines de perte courants dans un système de production Linux :

  • Pertes à distance : le paquet quitte correctement votre hôte, mais meurt ailleurs (switch, routeur, pare-feu, file d’entrée d’un hôte distant, CPU distant, politique distante).
  • Problèmes au niveau du lien : câblage, optiques, flaps, FEC, erreurs PCS. C’est « physique », mais cela apparaît dans les compteurs MAC/PHY et parfois dans les logs du pilote.
  • Perte sur le chemin de réception du NIC : débordement du ring buffer, pénurie de descripteurs, bugs du pilote, ou interactions d’offload.
  • Perte dans les backlogs du noyau : backlog NAPI/softirq (la classique histoire softnet_stat), starvation CPU, routage des interruptions.
  • Netfilter/conntrack : pression sur la table d’état, états invalides, timeouts agressifs, ou règles qui DROPPENT sous charge.
  • qdisc/contrôle de trafic : shaping/policing, comportement de fq_codel, ou un qdisc bien intentionné qui droppe silencieusement.
  • Perte au niveau socket : application qui ne lit pas, buffer de réception trop petit, file d’accept pleine, problèmes de SYN backlog.
  • Virtualisation/overlay : files veth, drops sur le bridge, overhead VXLAN/Geneve, discordance MTU d’encapsulation.
  • « Perte réseau » due au stockage : ce n’est pas une blague. Si l’application bloque sur le disque, elle cesse de lire les sockets et vous verrez des retransmissions et timeouts.

L’objectif n’est pas de collecter chaque métrique existante. L’objectif est de corréler un symptôme observé (retransmissions, trous, latence de queue, timeouts) avec un compteur spécifique qui augmente à un endroit précis.

Deux types de « parfois seulement »

La perte intermittente tend à suivre l’un des deux schémas :

  • Perte en rafale (microbursts) : tout va bien jusqu’à ce que cela ne le soit plus, et alors une petite file déborde. Les graphiques semblent propres parce que les moyennes masquent les pics.
  • Pertes conditionnelles : seul un certain trafic est affecté (certain MTU, DSCP, flux hashés vers un membre LACP défectueux, une IRQ épinglée sur un CPU occupé, un bucket conntrack sous attaque).

Si vous ne distinguez pas ces deux cas, vous dépannerez la mauvaise chose pendant des jours. Les pertes en rafale exigent du travail sur les files/capacités. Les pertes conditionnelles nécessitent une inspection du hashing, du MTU, des politiques et des flux par flux.

Une citation à garder sur un post-it : « L’espoir n’est pas une stratégie. » — idée paraphrasée attribuée à de nombreux leaders en opérations.

Blague #1 : La perte de paquets, c’est comme un enfant avec un marqueur. Si vous ne l’attrapez pas sur le fait, tout ce que vous obtenez, c’est un mur plein de « hein, c’est bizarre ».

Playbook de diagnostic rapide (premier/deuxième/troisième)

C’est l’ordre de triage qui vous amène rapidement au goulot, même lorsque le problème est intermittent et que vos tableaux de bord mentent par lissage.

Premier : prouver si la perte est locale ou distante

  1. Vérifier les retransmissions TCP et les compteurs de perte du noyau sur l’hôte affecté. Si les retransmissions augmentent mais que les drops RX/TX locaux n’augmentent pas, suspectez l’amont, un distant ou un middlebox.
  2. Capturer des paquets des deux côtés d’une frontière d’interface. Par exemple : capturer sur eth0 et sur bond0, ou sur eth0 et dans l’espace de noms. Si le paquet apparaît d’un côté et pas de l’autre, vous avez trouvé la frontière de perte.
  3. Comparer les compteurs d’erreur NIC/PHY. CRC, FCS, erreurs de symbole et flaps de lien ne sont pas des « problèmes applicatifs ».

Deuxième : vérifier les trois files qui débordent le plus souvent

  1. Ring RX du NIC / drops du pilote : ethtool -S montre souvent « missed », « no_buffer », « rx_missed_errors », etc.
  2. Backlog du noyau : les drops dans /proc/net/softnet_stat sont la preuve irréfutable d’une starvation CPU/softirq.
  3. qdisc : tc -s qdisc montre les drops à la queue egress ; le policing apparaît aussi comme des drops.

Troisième : isoler les motifs conditionnels

  1. MTU/fragmentation : vérifier les blackholes PMTUD, l’overhead d’overlay, et le filtrage ICMP.
  2. Hashing/LACP : un membre a-t-il des erreurs ? Un chemin présente-t-il un routage asymétrique ou du policing ?
  3. conntrack : table pleine ou churn ; les drops apparaissent « seulement au pic ».
  4. IRQ/affinité CPU : un cœur occupé qui gère tout le RX provoque des pertes intermittentes sous charge.

Si vous effectuez ces étapes dans cet ordre, vous arrêtez de deviner. Vous arrêtez aussi de « réparer » des choses qui n’étaient pas cassées.

Faits intéressants et contexte historique

  • L’Ethernet a toujours perdu des trames sous congestion ; l’ancien Ethernet partagé reposait sur la détection de collision. Les réseaux commutés modernes ont déplacé la douleur dans les buffers et files.
  • Linux NAPI a été introduit pour réduire les tempêtes d’interruptions en passant en mode sondage sous charge ; c’est pourquoi le temps CPU softirq est si important sur des NICs occupés.
  • Bufferbloat est devenu un terme courant à la fin des années 2000 ; de grands buffers réduisent les pertes mais peuvent détruire la latence. Ce compromis existe toujours dans votre NIC et votre switch.
  • Le contrôle de congestion TCP suppose que la perte signifie congestion. Quand la perte est causée par de mauvaises optiques ou une queue cassée, TCP réduit son débit et votre appli « ralentit mystérieusement ».
  • Les offloads GRO/LRO ont été créés pour réduire la charge CPU en coalesçant les paquets, mais ils compliquent les captures et l’analyse temporelle.
  • fq_codel et les qdiscs associés sont devenus populaires parce qu’ils combattent la latence sous charge en gérant les files mieux que FIFO.
  • Conntrack existe parce que les pare-feu stateful et NAT avaient besoin de suivi ; à grande échelle, conntrack devient une ressource noyau partagée qui peut échouer comme une base de données.
  • RSS/RPS/XPS (Receive/Transmit packet steering) représentent des décennies de travail accumulé pour alimenter uniformément les CPU multicœurs ; une mauvaise configuration provoque encore « un cœur qui surchauffe et des paquets qui tombent ».
  • Les jumbo frames ne sont pas nouvelles, mais les overlays ont rendu les erreurs MTU plus probables : l’overhead VXLAN/Geneve transforme « marche en labo » en « drops seulement pour de gros payloads ».

Tâches pratiques : commandes, sorties, décisions

Ci-dessous des tâches réelles à exécuter pendant un incident. Chacune inclut : la commande, ce que signifie la sortie, et la décision à prendre. Exécutez-les sur les deux extrémités quand vous le pouvez. Si vous ne les exécutez que sur un seul hôte, vous apprendrez quand même beaucoup, mais pas assez pour gagner des débats.

Tâche 1 : Confirmer que le symptôme est réel (et quel protocole le montre)

cr0x@server:~$ ping -c 20 -i 0.2 -s 56 10.10.5.20
PING 10.10.5.20 (10.10.5.20) 56(84) bytes of data.
64 bytes from 10.10.5.20: icmp_seq=1 ttl=62 time=0.611 ms
64 bytes from 10.10.5.20: icmp_seq=2 ttl=62 time=0.623 ms
Request timeout for icmp_seq 7
64 bytes from 10.10.5.20: icmp_seq=8 ttl=62 time=0.640 ms

--- 10.10.5.20 ping statistics ---
20 packets transmitted, 19 received, 5% packet loss, time 3805ms
rtt min/avg/max/mdev = 0.611/0.655/0.812/0.052 ms

Sens : Une perte ICMP existe, mais ICMP peut être priorisé à la baisse ou limité par des équipements. Ne concluez pas « le réseau est cassé » à partir de ping seul.

Décision : Vérifiez immédiatement les signaux au niveau TCP (retransmissions) pour les charges réelles. Si seules les ICMP sont affectées, suspectez du policing/limitation de débit.

Tâche 2 : Vérifier les retransmissions TCP et les resets sur l’hôte

cr0x@server:~$ netstat -s | egrep -i 'retran|reset|timeout' | head
    1823 segments retransmitted
    17 bad segments received
    42 resets received for embryonic SYN_RECV sockets
    9 connections reset due to unexpected data

Sens : Les retransmissions indiquent une perte quelque part sur le chemin (ou un réordonnancement suffisamment sévère pour ressembler à une perte). Les resets SYN_RECV suggèrent une pression sur le backlog ou des problèmes de gestion des SYN.

Décision : Si les retransmissions augmentent pendant la fenêtre d’incident, traitez cela comme une perte réelle de paquets ou un jitter extrême. Passez aux compteurs et captures.

Tâche 3 : Identifier la route et si PMTUD doit fonctionner

cr0x@server:~$ ip route get 10.10.5.20
10.10.5.20 via 10.10.4.1 dev eth0 src 10.10.4.55 uid 0
    cache

Sens : Vous connaissez maintenant l’interface de sortie et le saut suivant. C’est votre ancre pour chaque compteur et capture ultérieurs.

Décision : Exécutez les statistiques au niveau interface sur eth0. Si le routage change pendant le problème (ECMP), vous devrez corréler le comportement par chemin.

Tâche 4 : Vérifier l’état du lien, la vitesse/duplex et les problèmes physiques évidents

cr0x@server:~$ ethtool eth0
Settings for eth0:
	Supported ports: [ FIBRE ]
	Supported link modes:   10000baseSR/Full
	Speed: 10000Mb/s
	Duplex: Full
	Auto-negotiation: off
	Link detected: yes

Sens : Le lien est monté à la vitesse attendue. Cela n’écarte pas les optiques ou le câble, mais enlève « mismatch duplex » et « c’est en fait 1G » de la liste.

Décision : Si le lien flappe ou négocie à une vitesse inattendue, arrêtez-vous et réparez le physique. Si cela semble stable, passez aux compteurs d’erreur.

Tâche 5 : Lire les compteurs NIC et du pilote pour les drops RX/TX et erreurs

cr0x@server:~$ ethtool -S eth0 | egrep -i 'drop|error|miss|no_buffer|timeout' | head -n 20
     rx_missed_errors: 1249
     rx_no_buffer_count: 1180
     rx_errors: 0
     tx_errors: 0
     tx_timeout_count: 0

Sens : rx_missed_errors / rx_no_buffer_count signifie généralement que le NIC n’a pas pu remettre les paquets au noyau suffisamment vite (exhaustion du ring, starvation CPU, ou problèmes du pilote). C’est une perte locale.

Décision : Si ces compteurs augmentent pendant l’incident, vous regardez une pression sur le chemin de réception. Passez aux softnet stats, à la distribution des IRQ et aux tailles de ring.

Tâche 6 : Vérifier les drops d’interface génériques (moins précis, mais utiles)

cr0x@server:~$ ip -s link show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel 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
    9132299123  9023123  0       431      0       12213
    TX:  bytes  packets  errors  dropped  carrier collsns
    8023312288  8112231  0       0        0       0

Sens : Le champ dropped est un agrégat grossier ; il peut inclure des drops au niveau noyau, pas strictement NIC. Pourtant : s’il augmente avec votre problème, c’est un gros indice.

Décision : Si RX dropped augmente mais que ethtool -S n’affiche pas de missed, suspectez le backlog noyau, netfilter, ou les couches qdisc/virtualisation.

Tâche 7 : Vérifier les drops du backlog noyau avec softnet_stat

cr0x@server:~$ awk '{d+=$2; t+=$1} END{print "total_processed="t, "total_dropped="d}' /proc/net/softnet_stat
total_processed=140338812 total_dropped=92841

Sens : La deuxième colonne correspond aux paquets dropés dans le backlog par CPU. Si ce nombre augmente rapidement pendant l’incident, le noyau droppe avant que le paquet n’atteigne votre socket.

Décision : Regardez la saturation CPU, l’affinité des interruptions, et si votre NIC alimente un seul cœur. Réparer le physique ne servira à rien ; il faut corriger l’ordonnancement CPU/interrupt/queueing.

Tâche 8 : Identifier si les IRQ sont concentrées sur un seul CPU

cr0x@server:~$ grep -E 'eth0|mlx|ixgbe|i40e' /proc/interrupts | head
  86:  9833221        12         4         9   IR-PCI-MSI 524288-edge      eth0-TxRx-0
  87:       31   9123312         8        11   IR-PCI-MSI 524289-edge      eth0-TxRx-1
  88:       25        18   9011123        13   IR-PCI-MSI 524290-edge      eth0-TxRx-2
  89:       22        15        10   8832212   IR-PCI-MSI 524291-edge      eth0-TxRx-3

Sens : Si une ligne IRQ a presque toutes les interruptions sur un seul CPU, vous obtenez des pertes locales sous charge. Une distribution uniforme est l’objectif, mais « uniforme » dépend de la topologie NUMA et de la charge.

Décision : Si la répartition est déséquilibrée, ajustez l’affinité des IRQ (prudemment), activez/vérifiez RSS, et confirmez RPS/XPS quand approprié.

Tâche 9 : Vérifier le temps CPU passé en softirq (traitement réseau)

cr0x@server:~$ mpstat -P ALL 1 3
Linux 6.5.0-18-generic (server) 	02/04/2026 	_x86_64_	(32 CPU)

02:18:11 PM  CPU   %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
02:18:12 PM  all    8.2  0.0  6.1    0.2   0.0  14.9   0.0    0.0    0.0  70.6
02:18:12 PM   7    3.1  0.0  5.9    0.0   0.0  62.2   0.0    0.0    0.0  28.8

Sens : Un cœur avec un %soft extrêmement élevé suggère qu’il est noyé par le traitement des paquets. Cela corrèle fortement avec des drops softnet_stat.

Décision : Rééquilibrez les interruptions, vérifiez le nombre de queues RSS, réduisez le coût par paquet (les offloads peuvent aider), ou distribuez la charge réseau.

Tâche 10 : Inspecter les drops et backlog qdisc à l’egress

cr0x@server:~$ tc -s qdisc show dev eth0
qdisc fq_codel 0: root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn
 Sent 8122331123 bytes 8112231 pkt (dropped 3312, overlimits 0 requeues 12)
 backlog 0b 0p requeues 12
  maxpacket 1514 drop_overlimit 3312 new_flow_count 4012 ecn_mark 0

Sens : Les drops ici sont des drops de la queue egress de l’hôte. Ce n’est pas « le réseau » ; c’est votre serveur qui décide qu’il ne peut plus mettre en file d’attente d’autres paquets.

Décision : Déterminez pourquoi l’hôte est congestionné en egress : shaping/policing, limite qdisc trop petite, ou le NIC n’arrive pas à transmettre assez vite (ou bloqué par le flow control).

Tâche 11 : Détecter une discordance MTU et les blackholes PMTUD

cr0x@server:~$ ping -M do -s 1472 -c 3 10.10.5.20
PING 10.10.5.20 (10.10.5.20) 1472(1500) 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.10.5.20 ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet loss, time 2025ms

Sens : L’interface de cet hôte a une MTU de 1500, et vous essayez d’envoyer un paquet de 1500 octets avec DF activé. L’erreur est locale et attendue.

Décision : Faites le même test avec la plus grande charge utile attendue pour votre overlay ou configuration jumbo. Si un chemin ne peut pas la passer et qu’ICMP est filtré, vous obtenez « perte seulement pour les gros paquets ».

Tâche 12 : Confirmer les offloads et comprendre les bizarreries de capture

cr0x@server:~$ ethtool -k eth0 | egrep -i 'gro|gso|tso|lro|rx-checksumming|tx-checksumming'
rx-checksumming: on
tx-checksumming: on
tcp-segmentation-offload: on
generic-segmentation-offload: on
generic-receive-offload: on
large-receive-offload: off

Sens : Avec GRO/GSO/TSO activés, les captures peuvent afficher des paquets « géants » ou des schémas de segmentation étranges. Cela ne signifie pas que les jumbo frames sont activées ; cela signifie que le noyau optimise.

Décision : Ne désactivez pas les offloads comme premier réflexe. Si vous devez tester, faites-le temporairement et seulement après avoir capturé des compteurs de référence. Désactiver les offloads peut augmenter la charge CPU et créer des pertes.

Tâche 13 : Capturer au bon endroit et au bon moment (et garder petit)

cr0x@server:~$ sudo tcpdump -i eth0 -nn -s 96 -w /tmp/edge.pcap 'host 10.10.5.20 and (tcp or icmp)' -c 20000
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 96 bytes
20000 packets captured
20000 packets received by filter
0 packets dropped by kernel

Sens : « 0 packets dropped by kernel » signifie que votre processus de capture a suivi. Bien. Si tcpdump droppe des paquets, votre capture devient peu fiable pour l’analyse des microbursts.

Décision : Si vous voyez des pertes dans l’appli mais que tcpdump n’affiche pas de trous en egress, vous avez probablement des pertes distantes ou des problèmes de chemin de retour. Capturez aussi sur le récepteur.

Tâche 14 : Utiliser ss pour vérifier la pression sur les sockets (accept queue, rmem/wmem)

cr0x@server:~$ ss -s
Total: 1789 (kernel 0)
TCP:   912 (estab 501, closed 330, orphaned 0, timewait 309/0), ports 0

Transport Total     IP        IPv6
RAW	  0         0         0
UDP	  71        60        11
TCP	  582       421       161
INET	  653       481       172
FRAG	  0         0         0

Sens : Vue de sanity. Pour un diagnostic plus profond, inspectez les écouteurs spécifiques et leurs files d’attente.

cr0x@server:~$ ss -lntp | head
State  Recv-Q Send-Q Local Address:Port  Peer Address:Port Process
LISTEN 512    4096   0.0.0.0:443        0.0.0.0:*     users:(("nginx",pid=1412,fd=8))
LISTEN 128    128    127.0.0.1:9100     0.0.0.0:*     users:(("node_exporter",pid=1201,fd=3))

Sens : Recv-Q sur un écouteur est le backlog des connexions en attente ; s’il est constamment proche de Send-Q (le backlog configuré), vous droppez des SYNs ou votre accept est bloqué.

Décision : Si votre écouteur est saturé, la perte de paquets peut être une conséquence (retries/timeouts) plutôt qu’une perte réseau pure. Corrigez le taux d’acceptation applicatif, ajustez le backlog ou scalez.

Tâche 15 : Vérifier la saturation conntrack (environnements avec firewall/NAT stateful)

cr0x@server:~$ sudo sysctl net.netfilter.nf_conntrack_count net.netfilter.nf_conntrack_max
net.netfilter.nf_conntrack_count = 252118
net.netfilter.nf_conntrack_max = 262144

Sens : Vous êtes proche de la limite. Quand conntrack est plein, de nouvelles connexions peuvent échouer d’une manière qui ressemble à une perte de paquets (SYNs qui disparaissent, retries, clients qui timeout).

Décision : Si vous êtes près du max pendant les incidents, augmentez la limite (et la mémoire), réduisez le churn, ou arrêtez de suivre les flux qui n’ont pas besoin de l’être.

Tâche 16 : Trouver les retransmissions par connexion (arrêtez de blâmer tout le réseau)

cr0x@server:~$ ss -ti dst 10.10.5.20 | head -n 30
ESTAB 0 0 10.10.4.55:48216 10.10.5.20:443
	 cubic wscale:7,7 rto:204 rtt:4.2/0.8 ato:40 mss:1460 pmtu:1500 rcvmss:1460 advmss:1460 cwnd:10 bytes_sent:88212 bytes_acked:88120 bytes_received:112233 segs_out:712 segs_in:690 data_segs_out:502 retrans:7/23 lost:0 sacked:8

Sens : Cette connexion retransmet. Vous pouvez maintenant demander « qu’est-ce qui est spécial pour ce flux ? » plutôt que de débattre de tout le fabric.

Décision : Comparez les flux affectés et non affectés : destination, DSCP, port, MTU, chemin (ECMP), et si le flux emprunte un membre de bond spécifique.

Blague #2 : Désactiver tous les offloads pour « simplifier » est comme enlever les sièges d’une voiture pour améliorer l’aérodynamisme. Techniquement un changement, satisfaisant émotionnellement, opérationnellement suspect.

Trois mini-histoires du monde de l’entreprise

Mini-histoire 1 : L’incident causé par une mauvaise hypothèse

Une équipe plateforme a hérité d’une flotte de gateways Linux faisant du NAT pour plusieurs services internes. Un jour, des équipes ont commencé à signaler une « perte aléatoire de paquets » affectant les flux de login. Parfois seulement. Principalement aux heures de pointe. Le canal d’incident s’est rempli de captures d’écran de ping, comme le veut la tradition.

L’hypothèse erronée : « Si les pings montrent une perte, le fabric réseau doit être en cause. » L’équipe a escaladé vers le groupe réseau, qui a regardé les erreurs d’interface du switch et n’en a trouvé aucune. Ils ont répondu par le classique : « Ça a l’air propre de notre côté. » La tension a monté. Quelqu’un a proposé un reboot progressif des gateways « pour tout nettoyer ».

Un ingénieur plus calme a vérifié netstat -s et a vu les retransmissions augmenter. Puis il a regardé les compteurs conntrack et a trouvé la table proche de la limite. Pas toujours pleine. Juste en flirt avec la limite. Sous pic de churn, de nouveaux flux échouaient. Certains clients réessayaient avec de nouveaux ports source, ajoutant encore du churn. Une boucle de rétroaction, mais uniquement sous certains profils de charge.

La morale est banale : le système avait grandi, le dimensionnement conntrack n’avait pas suivi. Une précédente étude de capacité supposait que « les connexions sont collantes ». Elles ne l’étaient pas. Une mise à jour client mobile a augmenté les connexions courtes. Rien n’était « cassé » dans le fabric ; la gateway refusait de créer des états et noyait les SYNs.

La correction n’était pas héroïque. Ils ont augmenté conntrack max avec une marge mémoire appropriée, arrêté de tracer le trafic qui n’en avait pas besoin, et ajouté un tableau de bord qui trace nf_conntrack_count vs nf_conntrack_max avec alerte sur sustained > 80%.

Leçon : la « perte de paquets » intermittente peut être un problème d’épuisement d’état. Si vous ne vérifiez pas tôt les tables noyau partagées, vous gaspillerez du temps à « déboguer le réseau » alors que le serveur refuse simplement de mémoriser de nouvelles connexions.

Mini-histoire 2 : L’optimisation qui s’est retournée contre eux

Une équipe gérait un service sensible à la latence (adjacent au trading, pas HFT mais assez pour que des ingénieurs argumentent sur des microsecondes). Ils voulaient réduire la charge CPU sur un nœud d’ingestion occupé. Quelqu’un a proposé de désactiver GRO/GSO/TSO pour que le traitement des paquets soit « plus prévisible » et les captures « plus précises ».

Ils ont appliqué le changement pendant une fenêtre calme. L’utilisation CPU est montée, mais restait dans le budget. Une semaine plus tard, le trafic a augmenté. Soudain, le nœud a commencé à montrer des timeouts intermittents et des retransmissions. Les dashboards étaient confus : le débit réseau restait inchangé, mais la latence en queue p99 a bondi et les retries clients ont augmenté.

Le mode de défaillance était classique : en désactivant les offloads, ils ont augmenté le coût CPU par paquet. Sous des taux de paquets plus élevés, un seul cœur traitant les softirq s’est saturé. Les drops dans /proc/net/softnet_stat ont augmenté. Ces drops ressemblaient à une « perte réseau », mais l’hôte abandonnait simplement la charge car il ne suivait pas.

L’équipe a reverté les changements d’offload et a plutôt résolu le vrai problème : distribution des IRQ et dimensionnement des queues RX, plus s’assurer que RSS était correctement configuré et mappé aux CPU appropriés. Les captures restaient exploitables en les plaçant aux bons points et en utilisant des snap lengths appropriés.

Leçon : des « optimisations » qui retirent des fonctions noyau/NIC déplacent souvent le coût vers le CPU et convertissent un débit prévisible en pertes intermittentes. Si vous changez les offloads, vous assumez les effets secondaires — surtout lors de la prochaine montée en charge, pas aujourd’hui.

Mini-histoire 3 : La pratique ennuyeuse qui a sauvé la mise

Une entreprise de taille moyenne avait une habitude peu sexy : elle conservait un runbook pour le triage des incidents réseau listant « enregistrez ces compteurs avant et pendant ». Il listait les commandes exactes — ip -s link, ethtool -S, tc -s qdisc, softnet_stat, et un petit filtre tcpdump — et exigeait de coller les sorties dans le ticket d’incident.

Un jour, des requêtes clients ont commencé à timeout, mais seulement depuis une AZ. Les ingénieurs juraient que c’était un déploiement de code parce que le timing coïncidait. Le runbook les a forcés à collecter des compteurs sur un nœud non affecté et sur un nœud affecté. La comparaison a été décisive : les nœuds affectés montraient une augmentation des erreurs RX « missed » dans ethtool -S, alors que les nœuds non affectés ne l’affichaient pas.

L’équipe réseau a vérifié les compteurs de port du switch pour le rack affecté et a trouvé un motif correspondant d’erreurs physique. Pas assez pour faire flapper le lien. Juste assez pour ruiner des trames et déclencher des retransmissions. La réparation était physique : remplacer des optiques et nettoyer quelques patchs. Résolu sans rollback, et le postmortem avait une timeline basée sur des preuves.

Leçon : la collecte cohérente et ennuyeuse de compteurs fait gagner du temps car elle facilite les comparaisons. Le travail n’est pas d’être brillant ; le travail est d’être correct rapidement.

Erreurs fréquentes : symptôme → cause racine → correction

1) « Ping montre 5% de perte, les utilisateurs se plaignent, donc le réseau droppe des paquets »

Symptôme : perte au ping, mais les applis TCP sont pour la plupart correctes ; RTT ICMP instable.

Cause racine : ICMP est limité ou priorisé à la baisse sur routeurs/pare-feu ; certains équipements le traitent comme un nuisance.

Correction : validez avec les retransmissions TCP (netstat -s, ss -ti) et les métriques applicatives ; utilisez tcpdump ciblé pour le protocole réel.

2) « Pas d’erreurs d’interface, donc ce n’est pas physique »

Symptôme : retransmissions en pic ; ip -s link semble propre.

Cause racine : les problèmes physiques peuvent apparaître dans les compteurs switch, FEC/PCS, ou des compteurs NIC spécifiques au vendor non exposés par les compteurs basiques.

Correction : utilisez ethtool -S et corrélez avec les compteurs de port switch ; vérifiez les flaps de lien dans les logs.

3) « Nous avons augmenté les buffers, donc les drops devraient avoir disparu »

Symptôme : perte réduite, mais la latence tail s’aggrave ; les utilisateurs se plaignent toujours.

Cause racine : bufferbloat : moins de pertes au prix de files gigantesques et d’une latence élevée.

Correction : utilisez des qdiscs sensés (souvent fq_codel), dimensionnez correctement les buffers, et surveillez le p99 de latence en priorité.

4) « Seuls les gros uploads échouent ; les petites requêtes réussissent »

Symptôme : petits paquets OK ; gros transferts bloquent ; retransmissions augmentent.

Cause racine : MTU/blackhole PMTUD, souvent parce que ICMP fragmentation-needed est bloqué, surtout avec des overlays.

Correction : validez le path MTU avec ping -M do ; assurez la bonne MTU de bout en bout ; autorisez les ICMP nécessaires ; ajustez le MTU de l’overlay.

5) « Les drops NIC sont nuls, donc l’hôte ne peut pas dropper »

Symptôme : retransmissions et timeouts ; ethtool -S semble propre.

Cause racine : les drops se produisent dans le backlog noyau (softnet_stat), qdisc (tc -s qdisc), netfilter, ou les files socket.

Correction : vérifiez /proc/net/softnet_stat, les stats tc, et les files ss ; adressez la distribution CPU/IRQ et les limites de queue.

6) « Nous avons désactivé les offloads pour déboguer, et c’est pire »

Symptôme : nouvelles pertes sous charge ; CPU en hausse ; softirq élevé.

Cause racine : supprimer les offloads augmente le coût CPU par paquet et peut déclencher des drops du backlog.

Correction : revenez en arrière sur les changements d’offload ; déboguez avec des captures aux frontières ; corrigez l’échelle des interruptions/queues à la place.

7) « Ça doit être le pare-feu ; on ajoutera des règles plus tard »

Symptôme : échecs de connexion intermittents sous pic.

Cause racine : saturation ou churn conntrack, plus des règles coûteuses provoquant une pression CPU.

Correction : vérifiez l’utilisation de conntrack ; réduisez le trafic tracé ; ajustez les timeouts ; assurez-vous que le traitement du pare-feu est dimensionné et observable.

8) « Le bonding apporte de la redondance, donc ça ne peut pas causer de perte »

Symptôme : perte intermittente seulement pour certains flux ; un membre semble suspect.

Cause racine : déséquilibre LACP, câble/optique défectueux sur un membre, ou hashing qui attache certains flux à un lien dégradé.

Correction : vérifiez les stats par membre ; drenez/retirez temporairement le membre suspect ; ajustez la politique de hashing si nécessaire.

Listes de contrôle / plan étape par étape

Checklist A : Pendant l’incident (15–30 minutes)

  1. Définissez le symptôme en termes de protocole. Est-ce une perte ICMP, des retransmissions TCP, des trous UDP, ou des timeouts applicatifs ?
  2. Déterminez le chemin. Exécutez ip route get pour identifier l’interface de sortie et le saut suivant.
  3. Collectez des compteurs de base maintenant. Exécutez :
    • ip -s link show dev <if>
    • ethtool -S <if>
    • tc -s qdisc show dev <if>
    • awk ... /proc/net/softnet_stat
    • netstat -s ou ss -s
  4. Attendez 60 secondes et collectez à nouveau. Les deltas importent plus que les valeurs absolues.
  5. Capturez le trafic ciblé pendant une courte fenêtre. Snaplen petit, filtre étroit, nombre fixé, écriture sur disque.
  6. Corrélez un symptôme avec un compteur. Si vous ne le pouvez pas, vous ne savez pas encore où se situe la perte.

Checklist B : Si ça sent la pression CPU/softirq

  1. Vérifier les deltas de /proc/net/softnet_stat pendant l’incident.
  2. Vérifier mpstat pour un %soft élevé sur un ou quelques cœurs.
  3. Vérifier /proc/interrupts pour une distribution IRQ déséquilibrée.
  4. Vérifier le nombre de queues RSS et si le pilote expose plusieurs queues.
  5. Ce n’est qu’après cela que vous considérez tailles de ring, offloads et tuning. Évitez les changements sysctl aléatoires.

Checklist C : Si ça sent le MTU / overlay

  1. Confirmer la MTU d’interface : ip link show.
  2. Valider les tailles de payload avec ping -M do sur les deux extrémités.
  3. Vérifier si ICMP est filtré dans votre environnement (les équipes sécurité aiment faire ça « pour la sécurité »).
  4. Confirmer les paramètres MTU des overlays (VXLAN/Geneve) et s’assurer que l’underlay les supporte.
  5. Corriger la MTU de manière cohérente ; ne comptez pas sur la fragmentation en production moderne sauf si vous aimez les surprises.

Checklist D : Si ça sent les tables d’état (conntrack) ou la policy

  1. Vérifier l’utilisation de conntrack via sysctls et observer pendant le pic.
  2. Inspecter les compteurs de firewall (nftables/iptables) si disponibles ; les paquets dropés par des règles ne sont pas « mystérieux ».
  3. Réduire le trafic tracé quand c’est sûr (par ex. : tout le trafic n’a pas besoin d’état).
  4. Dimensionner correctement la table avec marge mémoire et alerting.

FAQ

1) Si ping montre des pertes mais que TCP semble ok, est-ce une « vraie » perte de paquets ?

Ça peut être une perte ICMP réelle, souvent sans impact pour la performance applicative. Beaucoup d’équipements limitent ICMP. Validez avec les retransmissions TCP et les métriques applicatives.

2) Quel est le fichier Linux le plus utile pour « drops sous charge » ?

/proc/net/softnet_stat. Si la colonne des drops monte pendant l’incident, vous avez des drops du backlog noyau. Cela pointe généralement vers une pression CPU/interrupt/taux de paquets.

3) Pourquoi les moyennes mentent-elles autant pour la perte intermittente ?

Parce que les pertes arrivent souvent en microbursts. Une rafale de 200ms peut déborder une file et causer une perte visible, alors que votre débit moyen sur 1 minute semble normal.

4) Dois-je désactiver GRO/TSO/GSO pour rendre tcpdump « précis » ?

Pas comme premier geste. Les offloads réduisent la charge CPU. Les désactiver peut créer des pertes en saturant softirq. Si vous devez tester, faites-le temporairement, capturez avant/après, et surveillez softnet drops et CPU.

5) Comment savoir si les drops ont lieu à l’ingress ou à l’egress ?

Ingress : augmentation des missed/no-buffer RX, drops softnet, ou problèmes de réception socket. Egress : drops vus par tc -s qdisc, problèmes queue TX, ou shaping/policing. Des captures des deux côtés d’une frontière rendent cela évident.

6) Pourquoi une discordance MTU ressemble-t-elle à « parfois seulement » ?

Parce que tous les paquets ne sont pas gros. Les petites requêtes passent ; les grosses réponses ou uploads bloquent. Si PMTUD est cassé (souvent à cause d’ICMP filtré), la connexion peut rester bloquée et retransmettre jusqu’au timeout.

7) Est-ce que conntrack peut vraiment ressembler à une perte de paquets ?

Oui. Quand conntrack est plein ou fortement contendu, de nouveaux flux peuvent échouer. Les clients voient des timeouts et des retries, et il est facile de qualifier cela de « paquets qui disparaissent ».

8) Que faire si tcpdump indique « packets dropped by kernel » pendant la capture ?

Votre capture n’arrive pas à suivre, ce qui est courant sur des liens occupés. Réduisez le filtre, diminuez le snaplen, capturez moins de paquets, ou capturez à un point moins chargé. N’utilisez pas une capture perdue pour prouver des microbursts.

9) Un ip -s link propre signifie-t-il que le NIC est ok ?

Pas forcément. De nombreux compteurs importants se trouvent uniquement dans ethtool -S, et les erreurs physiques peuvent être plus visibles côté switch.

10) Comment éviter les interminables renvois de blame entre équipes ?

Mettez-vous d’accord sur les frontières et les preuves : « paquet vu ici, pas vu là », plus des compteurs qui augmentent. Des captures à deux points battent les opinions à chaque fois.

Conclusion : prochaines étapes qui fonctionnent

La perte de paquets intermittente cesse d’être mystique quand vous arrêtez de la traiter comme une vibe et que vous commencez à la traiter comme un débordement de file ou une défaillance de chemin conditionnelle. Le mouvement gagnant est de localiser la frontière de perte en utilisant les deltas des compteurs et des captures ciblées et petites.

Faites ceci ensuite, dans l’ordre :

  1. Sur un hôte affecté, enregistrez les deltas pour netstat -s, ip -s link, ethtool -S, tc -s qdisc, et /proc/net/softnet_stat sur une fenêtre de 1–5 minutes.
  2. Si les drops sont locaux, décidez quel domaine les possède : ring NIC, backlog softirq, qdisc, conntrack, ou pression socket.
  3. Si les drops ne sont pas locaux, capturez aux deux extrémités (ou des deux côtés d’une frontière) et forcez la conversation à porter sur des preuves.
  4. Écrivez le runbook que vous auriez souhaité avoir aujourd’hui, tant que la douleur est fraîche. Gardez-le court. Exigez des sorties dans les tickets.

Le meilleur flux de débogage est celui que vous pouvez exécuter épuisé, sous pression, avec trois personnes qui se disputent dans vos oreilles. Construisez ce flux, et la perte intermittente deviendra juste un mardi de plus.

← Précédent
Dual Boot cassé ? Restaurer le chargeur de démarrage Windows en toute sécurité
Suivant →
WireGuard Roaming : la solution qui empêche les déconnexions VPN mobiles

Laisser un commentaire