Lorsqu'ils étudient les hausses soudaines de latence sur des liaisons réseau à haut débit, les ingénieurs analysent généralement les routeurs intermédiaires, la gigue des canaux sans fil ou les files d'attente des équipements d'accès. Pourtant, sous Linux, une part substantielle des temps de transit excessifs provient directement de la mémoire tampon locale du système d'exploitation, bien avant que les trames n'atteignent les cartes réseau ou les interfaces virtuelles. Ce phénomène, qualifié de bufferbloat côté hôte, provoquait historiquement une dégradation sévère des flux interactifs dès que des téléchargements massifs saturaient le lien.
Afin de supprimer ces engorgements de plusieurs mégaoctets dans les pilotes matériels tout en préservant le débit maximal de la ligne, le développeur réseau du noyau Linux Eric Dumazet a conçu le mécanisme TCP Small Queues (TSQ). En instaurant un plafond dynamique d'octets par socket entre la couche de transport et la discipline de file (qdisc), TSQ a profondément transformé l'ordonnancement de la pile réseau. Comprendre TSQ est indispensable pour les architectes de tunnels chiffrés et d'infrastructures VPN modernes.
Les origines du Bufferbloat local avant TSQ
Avant la version 3.6 du noyau Linux, la pile TCP transmettait les paquets vers la couche inférieure aussi rapidement que la fenêtre de congestion (snd_cwnd) l'autorisait. Dès qu'un socket disposait d'espace dans son tampon d'émission, la couche transport assemblait les charges utiles dans des structures sk_buff et les confiait directement au gestionnaire de trafic.
Lors de transferts volumineux, cette architecture accumulait des centaines ou des milliers de paquets non transmis dans les anneaux de descripteurs des pilotes. Un seul flux TCP pouvait facilement retenir entre 2 Mo et 8 Mo de données dans les mémoires logicielles en attendant leur émission physique sur le câble ou la liaison radio.
Cette accumulation excessive entraînait trois conséquences néfastes :
- Allongement artificiel du RTT : Le séjour prolongé des paquets dans la file d'attente locale faussait les mesures de temps d'aller-retour, ralentissant l'adaptation des algorithmes de congestion.
- Blocage de ligne en cas de perte : Lorsqu'une perte de paquet survenait sur le réseau, les mégaoctets de données en souffrance dans la file du pilote devaient d'abord être évacués avant que le paquet réémis ne puisse être injecté.
- Pénalisation du trafic interactif : Les flux de commande SSH, les requêtes DNS et les trames audio VoIP partageant la machine se retrouvaient bloqués derrière les volumineuses vagues de paquets des gros fichiers.
Si les mécanismes d'Active Queue Management (AQM) tels que CoDel ou FQ-CoDel interviennent efficacement au niveau des cartes réseau, ils perdent leur efficacité si la couche supérieure déverse d'immenses salves ininterrompues. Une régulation fine s'imposait dès la frontière du transport.
Le principe d'autorégulation par socket de TCP Small Queues
TCP Small Queues établit une boucle de rétroaction directe entre la confirmation de transmission matérielle et la génération de données par les sockets. Plutôt que de considérer les files réseau comme un réservoir sans fin, TSQ mesure avec précision le volume d'octets en cours d'acheminement pour chaque connexion.
Le suivi de la variable sk_wmem_alloc
Chaque structure sk_buff allouée incrémente le compteur de mémoire d'écriture sk->sk_wmem_alloc du socket émetteur. Cette valeur intègre la charge utile, les en-têtes et les métadonnées mémoire. Lorsque l'interface matérielle ou virtuelle termine l'émission d'une trame, l'interruption pilote libère la mémoire (kfree_skb), décrémentant immédiatement sk_wmem_alloc.
Avant d'effectuer une segmentation ou d'injecter de nouvelles données, la pile TCP vérifie si la mémoire en attente dépasse le seuil dynamique de TSQ :
static bool tcp_small_queue_check(struct sock *sk, const struct sk_buff *skb, unsigned int factor)
{
unsigned int limit = max(2 * skb->truesize, sk->sk_pacing_shift);
limit = min_t(unsigned int, limit, sysctl_tcp_limit_output_bytes);
if (atomic_read(&sk->sk_wmem_alloc) > limit) {
set_bit(TSQ_THROTTLED, &tcp_sk(sk)->tsq_flags);
return true; /* Suspension temporaire de l'envoi */
}
return false;
}
Si le seuil est franchi, le noyau active l'indicateur TSQ_THROTTLED sur le socket et interrompt l'envoi vers la couche inférieure. Le socket cède son tour de traitement, protégeant les files d'attente du pilote contre toute saturation.
Réactivation du socket par interruption matérielle
Dès que le pilote réseau libère la mémoire de trame via skb_destroy(), le noyau vérifie si le socket associé porte le marqueur TSQ_THROTTLED. Dans l'affirmative, une tâche système légère (tsq_tasklet) planifie l'exécution de tcp_tsq_handler().
Cette fonction efface l'indicateur d'attente et relance tcp_write_xmit() pour libérer le train de paquets suivant. Comme cette commutation s'opère en quelques fractions de milliseconde, le débit maximal est préservé tout en maintenant une réserve locale extrêmement réduite.
Synergie avec le cadencement (Pacing) et l'ordonnanceur Sch_FQ
TSQ offre son plein potentiel lorsqu'il fonctionne de concert avec le cadencement régulier des paquets (packet pacing) et la file d'attente équitable (sch_fq). Le cadencement lisse les rafales sur la durée estimée du RTT au lieu de libérer une fenêtre entière à chaque accusé de réception ACK.
Le noyau Linux adapte automatiquement la limite TSQ au rythme d'émission calculé :
- Sur une liaison à 1 Gbps, une milliseconde de trafic équivaut à environ 125 Ko de données en file.
- Sur une liaison à 100 Mbps, ce plafond se réduit spontanément à environ 12,5 Ko.
Grâce à cette modulation, TSQ s'aligne en temps réel sur la capacité du chemin réseau. Avec sch_fq, chaque socket dispose de sa propre file d'attente virtuelle, ce qui évite toute interférence de latence entre sessions parallèles.
Enjeux majeurs pour les réseaux VPN et interfaces TUN
Le bufferbloat local constitue une menace accrue dans les architectures de réseaux privés virtuels. Dans les protocoles de tunnelisation comme WireGuard ou OpenVPN, le trafic chiffré sortant traverse une interface réseau virtuelle (tun0 ou wg0) avant de parvenir à la carte Ethernet ou Wi-Fi.
Le piège du double tamponnement
Sans régulation TSQ, les flux empruntant un tunnel subissent un double engorgement :
- Rétention sur l'interface virtuelle : Le flux TCP interne submerge la file du périphérique
tunavec des paquets en attente de chiffrement. - Rétention sur la carte physique : Le socket UDP externe inonde l'anneau d'émission matériel avec les datagrammes encapsulés.
Cette superposition fait bondir la latence de bout en bout de 20 ms à plus de 350 ms lors d'échanges intenses. Une perte sur la liaison externe paralyse alors la transmission interne.
Les gains d'optimisation dans RiceGuard
Au sein de l'architecture RiceGuard, le traitement des paquets s'intègre harmonieusement avec la comptabilité mémoire du noyau Linux. En calquant la taille des unités MTU virtuelles sur les segments matériels et en appliquant les règles de limitation TSQ, les descripteurs virtuels ne retiennent jamais de surplus de paquets.
Associé au moteur de routage Core L3 VPN et au transfert sans copie en mémoire (zero-copy), TSQ permet aux trames de communication vocale et aux flux interactifs de devancer les volumineux téléchargements en quelques microsecondes, garantissant une stabilité remarquable.
Vérification et configuration sous Linux
Les administrateurs système peuvent auditer et affiner les paramètres de TSQ via les commandes réseau usuelles.
Consulter et modifier la limite TSQ
Le volume maximal d'octets qu'un socket peut cumuler dans les files aval se configure via sysctl :
# Afficher la limite TSQ globale actuelle (valeur par défaut usuelle : 262144 octets / 256 Ko)
sysctl net.ipv4.tcp_limit_output_bytes
# Ajuster le seuil à 128 Ko pour les passerelles VPN nécessitant une latence minimale
sudo sysctl -w "net.ipv4.tcp_limit_output_bytes = 131072"
Surveiller l'activité TSQ avec Socket Statistics
La commande ss permet de constater directement la régulation TSQ sur les connexions actives :
# Analyser les métriques TCP détaillées sur le port 443
ss -tin '( dport = :443 or sport = :443 )'
Les indicateurs clés à observer :
wmem_alloc: Mémoire d'émission mobilisée en attente d'évacuation par la carte réseau.tsq: Présent dès que la connexion subit une temporisation TSQ.pacing_rate: Vitesse de cadencement déterminée par l'algorithme de contrôle de congestion.bytes_acked: Volume cumulé de données confirmées sans incident.
Lorsque la valeur de wmem_alloc demeure contenue sous la barre des 150 Ko lors de saturations de bande passante, TSQ neutralise parfaitement l'engorgement local.
Conclusion
TCP Small Queues s'impose comme une pièce maîtresse de l'ingénierie réseau sous Linux. En régulant les volumes d'octets dès la couche transport, TSQ a définitivement résolu l'ancien problème du bufferbloat sur les hôtes émetteurs.
Dans les infrastructures VPN, TSQ métamorphose les cartes virtuelles en canaux de transmission fluides et protégés contre les congestions locales. En symbiose avec les ordonnanceurs équitables, cette technologie offre une cohabitation sereine entre transferts massifs et applications temps réel hautement exigeantes.



