9.2. Gestionnaires de mise en file d'attente simples, sans classes

Comme nous l'avons déjà dit, la gestion de mise en file d'attente permet de modifier la façon dont les données sont envoyées. Les gestionnaires de mise en file d'attente sans classes sont ceux qui, en gros, acceptent les données et qui ne font que les réordonner, les retarder ou les jeter.

Ils peuvent être utilisés pour mettre en forme le trafic d'une interface sans aucune subdivision. Il est primordial que vous compreniez cet aspect de la mise en file d'attente avant de continuer sur les gestionnaires de mise en files d'attente basés sur des classes contenant d'autres gestionnaires de mise en file d'attente.

Le gestionnaire le plus largement utilisé est de loin pfifo_fast, qui est celui par défaut. Ceci explique aussi pourquoi ces fonctionnalités avancées sont si robustes. Elles ne sont rien de plus « qu'une autre file d'attente ».

Chacune de ces files d'attente a ses forces et ses faiblesses. Toutes n'ont peut-être pas été bien testées.

9.2.1. pfifo_fast

Cette file d'attente, comme son nom l'indique : premier entré, premier sorti (First In First Out), signifie que les paquets ne subissent pas de traitements spéciaux. En fait, ce n'est pas tout à fait vrai. Cette file d'attente a trois « bandes ». A l'intérieur de chacune de ces bandes, des règles FIFO s'appliquent. Cependant, tant qu'il y a un paquet en attente dans la bande 0, la bande 1 ne sera pas traitée. Il en va de même pour la bande 1 et la bande 2.

Le noyau prend en compte la valeur du champ Type de Service des paquets et prend soin d'insérer dans la bande 0 les paquets ayant le bit « délai minimum » activé.

Ne pas confondre ce gestionnaire de mise en file d'attente sans classes avec celui basé sur des classes PRIO ! Bien qu'ils aient des comportements similaires, pfifo_fast ne possède pas de classes et vous ne pourrez pas y ajouter de nouveaux gestionnaires avec la commande tc.

9.2.1.1. Paramètres & usage

Vous ne pouvez pas configurer le gestionnaire pfifo_fast, dans la mesure où c'est celui par défaut. Voici sa configuration par défaut :

priomap

Détermine comment les priorités des paquets sont reliées aux bandes, telles que définies par le noyau. La relation est établie en se basant sur l'octet TOS du paquet, qui ressemble à ceci :

 
   0     1     2     3     4     5     6     7
+-----+-----+-----+-----+-----+-----+-----+-----+
|                 |                       |     |
|   PRECEDENCE    |          TOS          | MBZ |
|                 |                       |     |
+-----+-----+-----+-----+-----+-----+-----+-----+

Les quatre bits TOS (le champ TOS) sont définis comme suit :

 
Binaire Décimal   Signification
-----------------------------------------
1000    8         Minimise le Délai (Minimize delay) (md)
0100    4         Maximalise le Débit (Maximize throughput) (mt)
0010    2         Maximalise la Fiabilité (Maximize reliability) (mr)
0001    1         Minimalise le Coût Monétaire (Minimize monetary cost) (mmc)
0000    0         Service Normal

Comme il y a 1 bit sur la droite de ces quatre bits, la valeur réelle du champ TOS est le double de la valeur des bits TOS. tcpdump -v -v fournit la valeur de tout le champ TOS, et non pas seulement la valeur des quatre bits. C'est la valeur que l'on peut voir dans la première colonne du tableau suivant :

 
TOS     Bits  Signification                     Priorité Linux    Bande
------------------------------------------------------------------------
0x0     0     Service Normal                    0 Best Effort     1
0x2     1     Minimise le Coût Monétaire (mmc)  1 Filler          2
0x4     2     Maximalise la Fiabilité (mr)      0 Best Effort     1
0x6     3     mmc+mr                            0 Best Effort     1
0x8     4     Maximalise le Débit (mt)          2 Masse           2
0xa     5     mmc+mt                            2 Masse           2
0xc     6     mr+mt                             2 Masse           2
0xe     7     mmc+mr+mt                         2 Masse           2
0x10    8     Minimise le Délai (md)            6 Interactive     0
0x12    9     mmc+md                            6 Interactive     0
0x14    10    mr+md                             6 Interactive     0
0x16    11    mmc+mr+md                         6 Interactive     0
0x18    12    mt+md                             4 Int. Masse      1
0x1a    13    mmc+mt+md                         4 Int. Masse      1
0x1c    14    mr+mt+md                          4 Int. Masse      1
0x1e    15    mmc+mr+mt+md                      4 Int. Masse      1

[NdT : par flux de masse (bulk flow), il faut entendre « gros flot de données transmises en continu » comme un transfert FTP. A l'opposé, un flux interactif (interactive flow), correspond à celui généré par des requêtes SSH].

Beaucoup de nombres. La seconde colonne contient la valeur correspondante des quatre bits TOS, suivi de leur signification. Par exemple, 15 représente un paquet voulant un coût monétaire minimal, une fiabilité maximum, un débit maximum ET un délai minimum. J'appellerai ceci un « paquet Hollandais ».

La quatrième colonne liste la manière dont le noyau Linux interprète les bits TOS, en indiquant à quelle priorité ils sont reliés.

La dernière colonne montre la carte des priorités par défaut. Sur la ligne de commande, la carte des priorités ressemble à ceci :

1, 2, 2, 2, 1, 2, 0, 0 , 1, 1, 1, 1, 1, 1, 1, 1

Ceci signifie , par exemple, que la priorité 4 sera reliée à la bande numéro 1. La carte des priorités vous permet également de lister des priorités plus grandes (> 7) qui ne correspondent pas à une relation avec le champ TOS, mais qui sont configurées par d'autres moyens.

Le tableau suivant provenant de la RFC 1349 (à lire pour plus de détails) indique comment les applications devraient configurer leurs bits TOS pour fonctionner correctement :

TELNET                    1000           (minimise le délai)
FTP
        Contrôle          1000           (minimise le délai)
        Données           0100           (maximalise le débit)

TFTP                      1000           (minimise le délai)

SMTP 
        phase de commande 1000           (minimise le délai)
        phase DATA        0100           (maximalise le débit)

Domain Name Service
        requête UDP       1000           (minimise le délai)
        requête TCP       0000
        Transfert de Zone 0100           (maximalise le débit)

NNTP                      0001           (minimise le coût monétaire)

ICMP
        Erreurs           0000
        Requêtes          0000 (presque)
        Réponses         <même chose que requête> (presque)
txqueuelen

La longueur de cette file d'attente est fournie par la configuration de l'interface, que vous pouvez voir et configurer avec ifconfig et ip. Pour configurer la longueur de la file d'attente à 10, exécuter : ifconfig eth0 txqueuelen 10

Vous ne pouvez pas configurer ce paramètre avec tc !

9.2.2. Filtre à seau de jetons (Token Bucket Filter)

Le Token Bucket Filter (TBF) est un gestionnaire de mise en file d'attente simple. Il ne fait que laisser passer les paquets entrants avec un débit n'excédant pas une limite fixée administrativement. L'envoi de courtes rafales de données avec un débit dépassant cette limite est cependant possible.

TBF est très précis, et peu gourmand du point de vue réseau et processeur. Considérez-le en premier si vous voulez simplement ralentir une interface !

L'implémentation TBF consiste en un tampon (seau), constamment rempli par des éléments virtuels d'information appelés jetons, avec un débit spécifique (débit de jeton). Le paramètre le plus important du tampon est sa taille, qui correspond au nombre de jetons qu'il peut stocker.

Chaque jeton entrant laisse sortir un paquet de données de la file d'attente de données et ce jeton est alors supprimé du seau. L'association de cet algorithme avec les deux flux de jetons et de données, nous conduit à trois scénarios possibles :

  • Les données arrivent dans TBF avec un débit EGAL au débit des jetons entrants. Dans ce cas, chaque paquet entrant a son jeton correspondant et passe la file d'attente sans délai.

  • Les données arrivent dans TBF avec un débit PLUS PETIT que le débit des jetons. Seule une partie des jetons est supprimée au moment où les paquets de données sortent de la file d'attente, de sorte que les jetons s'accumulent jusqu'à atteindre la taille du tampon. Les jetons libres peuvent être utilisés pour envoyer des données avec un débit supérieur au débit des jetons standard, si de courtes rafales de données arrivent.

  • Les données arrivent dans TBF avec un débit PLUS GRAND que le débit des jetons. Ceci signifie que le seau sera bientôt dépourvu de jetons, ce qui provoque l'arrêt de TBF pendant un moment. Ceci s'appelle « une situation de dépassement de limite » (overlimit situation). Si les paquets continuent à arriver, ils commenceront à être éliminés.

Le dernier scénario est très important, car il autorise la mise en forme administrative de la bande passante disponible pour les données traversant le filtre.

L'accumulation de jetons autorise l'émission de courtes rafales de données sans perte en situation de dépassement de limite, mais toute surcharge prolongée causera systématiquement le retard des paquets, puis leur rejet.

Notez que, dans l'implémentation réelle, les jetons correspondent à des octets, et non des paquets.

9.2.2.1. Paramètres & usage

Même si vous n'aurez probablement pas besoin de les changer, TBF a des paramètres. D'abord, ceux toujours disponibles sont :

limit or latency

Limit est le nombre d'octets qui peuvent être mis en file d'attente en attendant la disponibilité de jetons. Vous pouvez également indiquer ceci d'une autre manière en configurant le paramètre latency, qui spécifie le temps maximal pendant lequel un paquet peut rester dans TBF. Ce dernier paramètre prend en compte la taille du seau, le débit, et s'il est configuré, le débit de crête (peakrate).

burst/buffer/maxburst

Taille du seau, en octets. C'est la quantité maximale, en octets, de jetons dont on disposera simultanément. En général, plus les débits de mise en forme sont importants, plus le tampon doit être grand. Pour 10 Mbit/s sur plateforme Intel, vous avez besoin d'un tampon d'au moins 10 kilo-octets si vous voulez atteindre la limitation configurée !

Si votre tampon est trop petit, les paquets pourront être rejetés car il arrive plus de jetons par top d'horloge que ne peut en contenir le tampon.

mpu

Un paquet de taille nulle n'utilise pas une bande passante nulle. Pour ethernet, la taille minimale d'un paquet est de 64 octets. L'Unité Minimale de Paquet (Minimun Packet Unit) détermine le nombre minimal de jetons à utiliser pour un paquet.

rate

Le paramètre de la vitesse. Voir les remarques au-dessus à propos des limites !

Si le seau contient des jetons et qu'il est autorisé à se vider, alors il le fait par défaut avec une vitesse infinie. Si ceci vous semble inacceptable, utilisez les paramètres suivants :

peakrate

Si des jetons sont disponibles et que des paquets arrivent, ils sont immédiatement envoyés par défaut ; et pour ainsi dire à « la vitesse de la lumière ». Cela peut ne pas vous convenir, spécialement si vous avez un grand seau.

Le débit de crête (peak rate) peut être utilisé pour spécifier la vitesse à laquelle le seau est autorisé à se vider. Si tout se passe comme écrit dans les livres, ceci est réalisé en libérant un paquet, puis en attendant suffisamment longtemps, pour libérer le paquet suivant. Le temps d'attente est calculé de manière à obtenir un débit égal au débit de crête.

Cependant, étant donné que la résolution du minuteur (timer) d'UNIX est de 10 ms et que les paquets ont une taille moyenne de 10 000 bits, nous sommes limités à un débit de crête de 1mbit/s !

mtu/minburst

Le débit de crête de 1Mb/s ne sert pas à grand chose si votre débit habituel est supérieur à cette valeur. Un débit de crête plus élevé peut être atteint en émettant davantage de paquets par top du minuteur, ce qui a pour effet de créer un second seau.

Ce second bucket ne prend par défaut qu'un seul paquet, et n'est donc en aucun cas un seau.

Pour calculer le débit de crête maximum, multipliez le mtu que vous avez configuré par 100 (ou plus exactement par HZ, qui est égal à 100 sur Intel et à 1024 sur Alpha).

9.2.2.2. Configuration simple

Voici une configuration simple, mais très utile :

# tc qdisc add dev ppp0 root tbf rate 220kbit latency 50ms burst 1540

Pourquoi est-ce utile ? Si vous avez un périphérique réseau avec une grande file d'attente, comme un modem DSL ou un modem câble, et que le dialogue se fasse à travers une interface rapide, comme une interface ethernet, vous observerez que télécharger vers l'amont (uploading) dégrade complètement l'interactivité.

[NdT : uploading désigne une opération qui consiste à transférer des données ou des programmes stockés dans un ordinateur local vers un ordinateur distant à travers un réseau. La traduction officielle pour ce terme est « téléchargement vers l'amont ». On parle alors de voie montante. Le downloading désigne l'opération inverse (transfert d'un hôte distant vers l'ordinateur local) et est traduit par « téléchargement » ou « téléchargement vers l'aval ». On parle alors de la voie descendante.]

Le téléchargement vers l'amont va en effet remplir la file d'attente du modem. Celle-ci est probablement ENORME car cela aide vraiment à obtenir de bon débit de téléchargement vers l'amont. Cependant, ceci n'est pas forcément ce que voulez. Vous ne voulez pas forcément avoir une file d'attente importante de manière à garder l'interactivité et pouvoir encore faire des choses pendant que vous envoyez des données.

La ligne de commande au-dessus ralentit l'envoi de données à un débit qui ne conduit pas à une mise en file d'attente dans le modem. La file d'attente réside dans le noyau Linux, où nous pouvons lui imposer une taille limite.

Modifier la valeur 220kbit avec votre vitesse de lien REELLE moins un petit pourcentage. Si vous avez un modem vraiment rapide, augmenter un peu le paramètre burst.

9.2.3. Mise en file d'attente stochastiquement équitable (Stochastic Fairness Queueing)

Stochastic Fairness Queueing (SFQ) est une implémentation simple de la famille des algorithmes de mise en file d'attente équitable. Cette implémentation est moins précise que les autres, mais elle nécessite aussi moins de calculs tout en étant presque parfaitement équitable.

Le mot clé dans SFQ est conversation (ou flux), qui correspond principalement à une session TCP ou un flux UDP. Le trafic est alors divisé en un grand nombre de jolies files d'attente FIFO : une par conversation. Le trafic est alors envoyé dans un tourniquet, donnant une chance à chaque session d'envoyer leurs données tour à tour.

Ceci conduit à un comportement très équitable et empêche qu'une seule conversation étouffe les autres. SFQ est appelé « Stochastic » car il n'alloue pas vraiment une file d'attente par session, mais a un algorithme qui divise le trafic à travers un nombre limité de files d'attente en utilisant un algorithme de hachage.

A cause de ce hachage, plusieurs sessions peuvent finir dans le même seau, ce qui peut réduire de moitié les chances d'une session d'envoyer un paquet et donc réduire de moitié la vitesse effective disponible. Pour empêcher que cette situation ne devienne importante, SFQ change très souvent son algorithme de hachage pour que deux sessions entrantes en collision ne le fassent que pendant un nombre réduit de secondes.

Il est important de noter que SFQ n'est seulement utile que dans le cas où votre interface de sortie est vraiment saturée ! Si ce n'est pas le cas, il n'y aura pas de files d'attente sur votre machine Linux et donc, pas d'effets. Plus tard, nous décrirons comment combiner SFQ avec d'autres gestionnaires de mise en files d'attente pour obtenir le meilleur des deux mondes.

Configurer spécialement SFQ sur l'interface ethernet qui est en relation avec votre modem câble ou votre routeur DSL est vain sans d'autres mises en forme du trafic !

9.2.3.1. Paramètres & usage

SFQ est presque configuré de base :

perturb

Reconfigure le hachage une fois toutes les pertub secondes. S'il n'est pas indiqué, le hachage se sera jamais reconfiguré. Ce n'est pas recommandé. 10 secondes est probablement une bonne valeur.

quantum

Nombre d'octets qu'un flux est autorisé à retirer de la file d'attente avant que la prochaine file d'attente ne prenne son tour. Par défaut, égal à la taille maximum d'un paquet (MTU). Ne le configurez pas en dessous du MTU !

9.2.3.2. Configuration simple

Si vous avez un périphérique qui a une vitesse identique à celle du lien et un débit réel disponible, comme un modem téléphonique, cette configuration aidera à promouvoir l'équité :

# tc qdisc add dev ppp0 root sfq perturb 10
# tc -s -d qdisc ls
qdisc sfq 800c: dev ppp0 quantum 1514b limit 128p flows 128/1024 perturb 10sec 
 Sent 4812 bytes 62 pkts (dropped 0, overlimits 0) 

Le nombre 800c est un descripteur (handle) automatiquement assigné et limit signifie que 128 paquets peuvent attendre dans la file d'attente. Il y a 1024 « seaux de hachage » disponibles pour la comptabilité, 128 pouvant être actifs à la fois (pas plus de paquets ne conviennent dans la file d'attente). Le hachage est reconfiguré toutes les 10 secondes.