L'infâme concept qui plombe inlassablement vos transferts s'appelle la surcharge protocolaire[1]. Cet effet est particulièrement bien démontré dans le cadre du WiFi qui nous intéresse ici sur la page qu'y consacre l'UNINETT, le réseau de recherche norvégien et que je me propose ici de détailler quelque peu.

Surcharge protocolaire. Ce vilain terme désigne toute la bande passante que vient grapiller la gestion des différentes protocoles que vous utilisez. De manière générale, les protocoles de communication que nous utilisons sur les réseaux informatiques marchent grossièrement de la même manière. Premièrement, ces protocoles nécessitent la fourniture d'informations supplémentaires pour assurer leur fonctionnement. Ceci prend couramment la forme d'entêtes, à savoir des segments de données additionnelles qui vont servir au bon traitement des informations véhiculées. On pensera par exemple aux adresses IP qui permettent de trouver le bon chemin dans le réseau, ou encore aux ports TCP ou UDP qui permettent d'envoyer l'information à la bonne application. Ces entêtes viennent s'ajouter aux données proprement dites. Pour acheminer nos données, nous avons donc besoin d'émettre des informations supplémentaires qui vont inmanquablement consommer de la bande passante. Ensuite, une communication complète de bout en bout va mettre en œuvre plusieurs protocoles différents, ce qui se traduit par une série d'encapsulations, les différents protocoles s'embarquant les uns dans les autres comme des poupées russes. Ainsi, TCP est encapsulé dans IP, lui même encaspulé dans la série de protocoles qui composent 802.11, etc. Chacun de ces protocoles va présenter sa propre entête et l'ajouter de la surcharge des précédents. Plus vous empilez de protocoles, plus vous surchargez votre communication et plus vous perdez de bande passante pour transmettre les données qui vous intéressent vraiment.

Mais la surcharge protocolaire ne se résume pas seulement aux entêtes. Il se trouve que certains protocoles impliquent des échanges. Par exemple, l'envoi d'un message peut entraîner l'émission d'une réponse ou d'un acquittement en retour, lesquels n'ont pas forcément de signification au sens des données utiles. Nous devons donc également les prendre en compte, puisqu'ils monopolisent de la bande passante. Enfin, si on peut exprimer la surcharge protocolaire comme les informations supplémentaires que nous devons envoyer, nous pouvons également, et plus efficacement, l'exprimer comme le temps que nous perdons dans la gestion du protocole, à opposer au temps dont on dispose pour nos données utiles. Cette dernière approche permet de prendre en compte un dernier aspect de la surcharge protocolaire qu'est la gestion temporelle des échanges. Certains protocoles imposent en effet l'introduction de temps d'attente qui consomment eux aussi de la bande passante en ce qu'ils nous empêchent de communiquer. La vision temporelle nous permet également de considérer des échanges à des vitesses différentes sur le même médium, ce qui peut se révèler utile dans notre cas.

Voilà pour le survol de la théorie. Appliquons la à un cas pratique très simple et courant : ethernet. Ce protocole de communication physique[2] définit un format de trame. D'un point de vue physique[3], une trame commence par un marqueur physique composé de deux éléments, un préambule et un marqueur de début de trame. Ensuite vient la trame proprement dite avec son entête et ses données[4], puis finalement une somme de contrôle dite FCS[5]. Si on assemble le tout, on obtient la suite suivante :

  • un préambule de 7 octets ;
  • un marqueur de début de trame d'un octet ;
  • un entête ethernet de 14 octets ;
  • des données d'une taille maximale de 1500 octets ;
  • une somme de contrôle de 4 octets.

Nous voyons donc que nous devons y ajouter 26 octets du fait d'ethernet seul. Ce qui veut dire que de ce point de vue, on perd entre 2% et 40% de la bande passante disponible, selon qu'on envoie une trame de taille maximale (1526 octets) ou de taille minimale (72 octets). Et je ne compte pas les 12 octets incompressibles qui séparent chacunes des trames...

Nous devons à présent considérer le fait que les données ethernet sont en fait un paquet IP dont l'entête est longue de 20 octets et dont la charge est un segment TCP qui possède lui-même un entête de 20 octets[6]. Sur les 1500 octets que nous alloue ethernet, ce sont en fait 1460 octets qui nous restent. On perd donc 66 octets pour les différents protocoles. À ceci, nous devrions ajouter le fait que toute donnée TCP doit être acquittée. Dans le pire des cas, chaque segment de données ferait l'objet d'un acquittement spécifique, soit l'émission d'un TCP ACK dans une trame de taille minimale, les données ethernet se limitent à un entête IP, un entête TCP et du bourrage. Soit pour 1460 octets utiles, 138 octets protocolaires et 9% de surcharge. Quant à la gestion temporelle, elle ne nous impacte pas, puisque dans les implémentations courantes d'ethernet, nous obtenons des liens switchés full-duplex qui nous permettent de balancer nos trames dès qu'on voit le medium libre, sans se poser la moindre question, puisque sans concurrence. La contrainte temporelle est donc pratiquement négligeable, ce qui nous facilite énormément la vie.

Penchons-nous maintenant sur l'empilement protocolaire de 802.11. Le format d'une trame de données 802.11 est le suivant :

  • un entête 802.11 proprement dit de 30 octets ;
  • un entête LLC[7] de 3 octets ;
  • un entête SNAP[8] de 5 octets ;
  • les données dont la taille maximale est usuellement fixée à 1500 octets pour faciliter le bridging avec les réseaux filaires ;
  • un FCS de 4 octets.

On constate d'emblée une nette augmentation de l'empilement protocolaire. La surcharge passe dans le pire des cas à 42 octets auxquels nous devons ajouter comme précédemment nos 40 octets d'IP et TCP, soit 82 octets en tout. Près de 5% donc, et même 10% si on considère l'acquittement TCP. Mais lorsqu'on fait des benchmarks, on s'aperçoit qu'on perd nettement plus que cela. Car les choses ne s'arrêtent pas là. Non seulement le protocole prévoit l'échange d'autres messages lors de l'envoi d'une trame, mais il prévoit également le positionnement de temps d'attente incompressibles. Ceci complique considérablement la situation par rapport à ethernet. Si dans les deux cas on fonctionne par partage du médium (CSMA), la gestion des collisions est diffère complètement. En filaire, on balance et on regarde si on détecte des collisions (CSMA/CD), alors qu'en sans-fil, on fait tout ce qu'on peut pour les éviter (CSMA/CA). Une partie de cet effort se traduit par l'ajout de trames particulières dites de contrôle qui vont accompagner les trames de données. D'abord, toute trame de données doit être acquittée au niveau 802.11 par une trame spécifique dite ACK. Ensuite, l'émission d'une trame de données doit parfois être précédée d'une sorte de négociation sur la disponibilité du réseau entre le gestionnaire du réseau (le point d'accès typiquement) et l'émetteur. Ce dernier se signale par une trame dite RTS[9] qui doit être acquittée par un CTS[10]. Les ACK et CTS sont longs de 14 octets et le RTS de 20 octets. Si on considère notre envoi de données TCP avec son acquittement, on doit ajouter l'émission de deux ACK 802.11, et éventuellement de deux RTS et deux CTS. Soit jusqu'à 1720 octets au total, ou un overhead de 260 octets représentant une surcharge de 15%, chiffre qui commence à devenir considérable. Et vous croyez que c'est fini ? Que nenni !

Ces trames de contrôle ne constituent que la première part de l'effort. La seconde se traduit par l'introduction de temps d'attente incompressibles dans le but d'assurer la bonne utilisation du médium. On distingue deux type de temps d'attente :

  • le DIFS[11] qui dure 50µs et précède tout envoi de données ;
  • le SIFS[12] qui dure 10µs et suit toute émission de trame.

Reprenons notre émission TCP acquittée. Nos allons avoir un DIFS suivi d'une trame RTS, puis un SIFS, un CTS, un autre SIFS, la trame de données, un nouveau SIFS, et enfin le ACK. Et rebelotte pour l'acquittement TCP. Nous allons donc introduire 160µs de silence dans l'échange et autant de temps de parole perdu pour envoyer des données utiles. Si on considère un réseau à 11Mbps, chaque microseconde de silence représente 1,375 octet de perdu. On perd donc ici l'équivalent de 220 octets de données. Et s'il n'y avait que cela... Chaque trame émise, quel que soit son type, est précédée d'un élément protocolaire dit PLCP[13] comprenant deux entêtes :

  • un préambule PLCP de 9 ou 18 octets[14] ;
  • un entête PLCP de 6 octets ;

J'aurais pû les mentionner plus haut me direz-vous. Oui, sauf que... Le protocole PLCP a ceci de particulier qu'il est toujours transmis à faible vitesse. Dans le cas d'un préambule long, tout est envoyé à 1Mbps. Dans le cas d'un préambule court, le prémabule est envoyé à 1Mbps et l'entête à 2Mbps. Ils ont donc un temps d'émission sensiblement plus long que les autres entêtes et consomment plus de bande passante.

Comme je commence à fatiguer au niveau de la calculatrice[15], le calcul du pire cas imaginable est laissé en exercice aux lecteurs pugnaces. Et comme UNINETT a déjà fait des calculs à ma place, je peux reprendre leurs résultats. Ils ont choisi d'exclure les RTC/CTS et parviennent dans ce cas aux chiffres éloquents de plus de 50% de surcharge dans le cas d'un préambule long et 40% pour un préambule court. Ce qui veut dire en substance que dans le meilleur des cas, vous disposerez de 60% de la bande passante théorique. Sur un réseau 802.11g à 54Mbps, vous aurez donc 32Mbps utiles pour vos données TCP. Considérant que le surcharge augmente quand la taille des trames diminue et que les trames qui circulent sur le réseau ne sont pas toutes de taille maximale, la surcharge moyenne sera supérieure à 40%.

Je concluerai sur un cas particulier que j'ai vu testé dans un simili-benchmark dont j'ai "oublié" l'origine. Lorsque deux stations WiFi communiquent à travers le même point d'accès, ce dernier fait office de relai, répétant toutes les trames de données. Ce qui veut dire que dans ce cas très précis, vous divisez encore par deux la bande passante dont vous disposez, soit la moitié des 60% précédemment évoqués. Forcément, quand j'ai lu qu'ils obtenaient des pointes à 38Mbps sur du 802.11g classique [16] dans cette configuration précise, je n'ai pu m'empêcher de sourire...

Notes

[1] Overhead en anglais.

[2] Au sens de la pile simplifiée à quatre couches.

[3] Niveau 1 OSI

[4] Niveau 2 OSI.

[5] Frame Check Sequence.

[6] Les tailles d'entêtes IP et TCP sont les tailles minimum ; elles peuvent être plus grandes en cas d'utilisation d'options.

[7] Logical Link Control

[8] SubNetwork Access Protocol

[9] Ready To Send

[10] Clear To Send

[11] Distributed Coordination Function InterFrame Space

[12] Short InterFrame Space

[13] Physical Layer Convergence Protocol

[14] Short preamble vs. long preamble

[15] J'espère que des erreurs ne se sont pas glissées au milieu de l'article...

[16] Pas du 108Mbps...