Sophie

Sophie

distrib > * > 2010.0 > * > by-pkgid > a412ceb851151854794ced2a242192bb > files > 3804

howto-html-fr-20080722-1mdv2010.0.noarch.rpm

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Gestionnaires de file d'attente basés sur les classes</title><link href="style.css" rel="stylesheet" type="text/css" /><meta content="DocBook XSL Stylesheets V1.73.2" name="generator" /><link rel="start" href="index.html" title="HOWTO du routage avancé et du contrôle de trafic sous Linux" /><link rel="up" href="ch09.html" title="Chapitre 9. Gestionnaires de mise en file d'attente pour l'administration de la bande passante" /><link rel="prev" href="ch09s04.html" title="terminologie" /><link rel="next" href="ch09s06.html" title="Classifier des paquets avec des filtres" /></head><body><div class="navheader"><table summary="Navigation header" width="100%"><tr><th align="center" colspan="3">Gestionnaires de file d'attente basés sur les classes</th></tr><tr><td align="left" width="20%"><a accesskey="p" href="ch09s04.html">Précédent</a> </td><th align="center" width="60%">Chapitre 9. Gestionnaires de mise en file d'attente pour l'administration de la 
  bande passante</th><td align="right" width="20%"> <a accesskey="n" href="ch09s06.html">Suivant</a></td></tr></table><hr /></div><div class="sect1" lang="fr"><div class="titlepage"><div><div><h2 class="title"><a id="lartc.qdisc.classful" />Gestionnaires de file d'attente basés sur les classes</h2></div></div></div><p>Les gestionnaires de mise en file d'attente basés sur des classes sont
très utiles si vous avez différentes sortes de trafic qui doivent être traités
différemment. L'un d'entre eux est appelé <acronym class="acronym">CBQ</acronym>, pour 
<em class="wordasword">Class Based Queueing</em>.
Il est si souvent mentionné que les personnes identifient les gestionnaires
de mise en file d'attente basés sur des classes uniquement à CBQ, 
ce qui n'est pas le cas.
</p><p><acronym class="acronym">CBQ</acronym> est le mécanisme le plus ancien,
ainsi que le plus compliqué.
Il n'aura pas forcément les effets que vous recherchez. Ceci surprendra
peut-être ceux qui sont sous l'emprise de « <span class="quote">l'effet Sendmail</span> », qui
nous enseigne qu'une technologie complexe, non documentée est forcément
meilleure que toute autre.
</p><p>Nous évoquerons bientôt, plus à propos, CBQ et ses alternatives.
</p><div class="sect2" lang="fr"><div class="titlepage"><div><div><h3 class="title"><a id="N10DB1" />Flux à l'intérieur des gestionnaires basés sur des classes &amp; 
  à l'intérieur des classes</h3></div></div></div><p>Quand le trafic entre dans un gestionnaire de mise en file d'attente 
basé sur des classes, il doit être envoyé vers l'une de ses classes ;
il doit être « <span class="quote">classifié</span> ».
Pour déterminer que faire d'un paquet, les éléments appelés
« <span class="quote">filtres</span> » sont consultés.
Il est important de savoir que les filtres sont appelés de
l'intérieur d'un gestionnaire, et pas autrement !
</p><p>Les filtres attachés à ce gestionnaire renvoient alors une décision que
le gestionnaire utilise pour mettre en file d'attente le paquet vers l'une des
classes. Chaque sous-classe peut essayer d'autres filtres pour voir si de
nouvelles instructions s'appliquent.
Si ce n'est pas le cas, la classe met le paquet en file d'attente dans le
gestionnaire de mise en file d'attente qu'elle contient.
</p><p>En plus de contenir d'autres gestionnaires, la plupart des gestionnaires
de mise en file d'attente basés sur des classes réalisent également de la mise
en forme. 
Ceci est utile pour réaliser à la fois l'ordonnancement 
(avec <acronym class="acronym">SFQ</acronym>, par exemple) et le contrôle de débit.
Vous avez besoin de ceci dans les cas où vous avez une interface à haut débit
(ethernet, par exemple) connectée à un périphérique plus lent (un modem câble).
</p><p>Si vous n'utilisez que <acronym class="acronym">SFQ</acronym>, rien ne devait se passer,
dans la mesure où les paquets entrent et sortent du routeur sans
délai : l'interface de sortie est de loin beaucoup plus rapide que
la vitesse réelle de votre liaison ; il n'y a alors pas de files d'attente à
réordonnancer.
</p></div><div class="sect2" lang="fr"><div class="titlepage"><div><div><h3 class="title"><a id="N10DC8" />La famille des gestionnaires de mise en file d'attente : racines,
descripteurs, descendances et parents</h3></div></div></div><p>Chaque interface à « <span class="quote">un gestionnaire de mise en file d'attente
racine</span> » de sortie (<em class="wordasword">egress root qdisc</em>).
Par défaut, le gestionnaire de mise en file d'attente sans classes mentionné 
plus tôt <code class="literal">pfifo_fast</code>.
Chaque gestionnaire et classe est repéré par un descripteur 
(<em class="wordasword">handle</em>), qui pourra être utilisé par les prochaines
déclarations de configuration pour se référer à ce gestionnaire.
En plus du gestionnaire de sortie, une interface peut également avoir un 
gestionnaire d'entrée (<em class="wordasword">ingress</em>), qui réglemente le 
trafic entrant.
</p><p>Ces descripteurs sont constitués de deux parties : un nombre majeur et 
un nombre mineur : &lt;major&gt;:&lt;minor&gt;. 
Il est habituel de nommer le gestionnaire racine 
<code class="literal">1:</code>, ce qui est équivalent à <code class="literal">1:0</code>.
Le nombre mineur d'un gestionnaire de mise en file d'attente est toujours 0.
</p><p>Les classes doivent avoir le même nombre majeur que leur parent. Le
nombre majeur doit être unique à l'intérieur d'une configuration egress ou
ingress. Le nombre mineur doit être unique à l'intérieur d'un gestionnaire
de mise en file d'attente et de ses classes.
</p><div class="sect3" lang="fr"><div class="titlepage"><div><div><h4 class="title"><a id="N10DE9" />Comment les filtres sont utilisés pour classifier le trafic</h4></div></div></div><p>Pour récapituler, une hiérarchie typique pourrait ressembler à ceci :
</p><pre class="screen">                     1:   Gestionnaire de mise en file d'attente racine
                      |
                     1:1    classe enfant
                   /  |  \
                  /   |   \
                 /    |    \
                 /    |    \
              1:10  1:11  1:12   classes enfants
               |      |     | 
               |     11:    |    classe terminale
               |            | 
               10:         12:   Gestionnaire de mise en file d'attente
              /   \       /   \
           10:1  10:2   12:1  12:2   classes terminales
</pre><p>Mais ne laissez pas cet arbre vous abuser ! 
Vous ne devriez <span class="emphasis"><em>pas</em></span> imaginer le noyau être au sommet de 
l'arbre et le réseau en dessous, ce qui n'est justement pas le cas.
Les paquets sont mis et retirés de la file d'attente à la racine du
gestionnaire, qui est le seul élément avec lequel le noyau dialogue.
</p><p>Un paquet pourrait être classifié à travers une chaîne suivante :
<pre class="literallayout">
1: -&gt; 1:1 -&gt; 12: -&gt; 12:2
</pre>
</p><p>Le paquet réside maintenant dans la file d'attente du gestionnaire attaché à la
classe 12:2. Dans cet exemple, un filtre a été attaché à chaque noeud de
l'arbre, chacun choisissant la prochaine branche à prendre. Cela est 
réalisable. Cependant, ceci est également possible :
<pre class="literallayout">
1: -&gt; 12:2
</pre>
</p><p>Dans ce cas, un filtre attaché à la racine a décidé d'envoyer le paquet
directement à <code class="literal">12:2</code>.
</p></div><div class="sect3" lang="fr"><div class="titlepage"><div><div><h4 class="title"><a id="N10E0B" />Comment les paquets sont retirés de la file d'attente et envoyés 
  vers le matériel</h4></div></div></div><p>Quand le noyau décide qu'il doit extraire des paquets pour les envoyer 
vers l'interface, le gestionnaire racine <code class="literal">1:</code> reçoit une
requête <code class="literal">dequeue</code>, qui est transmise à 
<code class="literal">1:1</code> et qui, à son tour, est passée à 
<code class="literal">10:</code>, <code class="literal">11:</code> et 
<code class="literal">12:</code>, chacune interrogeant leurs descendances qui 
essaient de retirer les paquets de leur file d'attente.
Dans ce cas, le noyau doit parcourir l'ensemble de l'arbre, car seul 
<code class="literal">12:2</code> contient un paquet.
</p><p>En résumé, les classes « <span class="quote">emboîtées</span> » parlent 
<span class="emphasis"><em>uniquement</em></span> à leur gestionnaire de mise en file d'attente
parent ; jamais à une interface.
Seul la file d'attente du gestionnaire racine est vidée par le noyau !
</p><p>Ceci a pour résultat que les classes ne retirent jamais les paquets 
d'une file d'attente plus vite que ce que leur parent autorise.
Et c'est exactement ce que nous voulons : de cette manière, nous pouvons
avoir <acronym class="acronym">SFQ</acronym> dans une classe interne qui ne fait pas de mise en 
forme, mais seulement de l'ordonnancement, et avoir un gestionnaire de mise en
file d'attente extérieur qui met en forme le trafic.
</p></div></div><div class="sect2" lang="fr"><div class="titlepage"><div><div><h3 class="title"><a id="N10E39" />Le gestionnaire de mise en file d'attente PRIO</h3></div></div></div><p>Le gestionnaire de mise en file d'attente ne met pas vraiment en forme 
le trafic ; il ne fait que le subdiviser en se basant sur la manière dont
vous avez configuré vos filtres.
Vous pouvez considérer les gestionnaires <acronym class="acronym">PRIO</acronym> comme une sorte 
de super <code class="literal">pfifo_fast</code> dopé, où chaque bande est une 
classe séparée au lieu d'une simple FIFO.
</p><p>Quand un paquet est mis en file d'attente dans le gestionnaire PRIO, une
classe est choisie en fonction des filtres que vous avez donnés.
Par défaut, trois classes sont créées.
Ces classes contiennent par défaut de purs gestionnaires de mise en file 
d'attente FIFO sans structure interne, mais vous pouvez les remplacer par 
n'importe quels gestionnaires disponibles.
</p><p>Chaque fois qu'un paquet doit être retiré d'une file d'attente,
la classe <code class="literal">:1</code> est d'abord testée.
Les classes plus élevées ne sont utilisées que si aucune des bandes plus 
faibles n'a pas fourni de paquets. 
</p><p>Cette file d'attente est très utile dans le cas où vous voulez donner la
priorité à certains trafics en utilisant toute la puissance des filtres 
<span class="command"><strong>tc</strong></span> et en ne se limitant pas seulement aux options du 
champ TOS. 
Vous pouvez également ajouter un autre gestionnaire de mise en file d'attente 
aux trois classes prédéfinies, tandis que <code class="literal">pfifo_fast</code> est limité aux 
simples gestionnaires FIFO.
</p><p>Puisqu'il ne met pas vraiment en forme, on applique le même avertissement
que pour <acronym class="acronym">SFQ</acronym>.
Utilisez <acronym class="acronym">PRIO</acronym> seulement si votre lien physique est vraiment
saturé ou intégrez-le à l'intérieur d'un gestionnaire de mise en file
d'attente basé sur des classes qui réalisent la mise en forme.
Ce dernier cas est valable pour pratiquement tous les modems-câbles et les 
périphériques DSL.
</p><p>En termes formels, le gestionnaire de mise en file d'attente 
<acronym class="acronym">PRIO</acronym> est un ordonnanceur 
<em class="wordasword">Work-Conserving</em>.
</p><div class="sect3" lang="fr"><div class="titlepage"><div><div><h4 class="title"><a id="N10E67" />Paramètres PRIO &amp; usage</h4></div></div></div><p>Les paramètres suivants sont reconnus par 
<span class="command"><strong>tc</strong></span> :

<div class="variablelist"><dl><dt><span class="term"><code class="option">bands</code></span></dt><dd><p>Nombre de bandes à créer. Chaque bande est en fait une classe.
    Si vous changez ce nombre, vous devez également changer :
    </p></dd><dt><span class="term"><code class="option">priomap</code></span></dt><dd><p>Si vous ne fournissez pas de filtres <span class="command"><strong>tc</strong></span> pour
    classifier le trafic, le gestionnaire <acronym class="acronym">PRIO</acronym> regarde la
    priorité <code class="option">TC_PRIO</code> pour décider comment mettre en
    file d'attente le trafic.
    </p><p>Ceci fonctionne comme le gestionnaire de mise en file d'attente
    <code class="literal">pfifo_fast</code> mentionné plus tôt.
    Voir la section correspondante pour plus de détails.
    </p></dd></dl></div>
Les bandes sont des classes et sont appelées par défaut majeur:1 à majeur:3.
Donc, si votre gestionnaire de mise en file d'attente est appelé 
<code class="literal">12:</code>, <span class="command"><strong>tc</strong></span> filtre le trafic vers
<code class="literal">12:1</code> pour lui accorder une plus grande priorité.
</p><p>Par itération, la bande 0 correspond au nombre mineur 1, la bande 1 au
nombre mineur 2, etc ...
</p></div><div class="sect3" lang="fr"><div class="titlepage"><div><div><h4 class="title"><a id="N10E9E" />Configuration simple</h4></div></div></div><p>Nous allons créer cet arbre :
</p><pre class="screen">     racine 1: prio
          1:   Gestionnaire racine
         / | \ 
       /   |   \
       /   |   \
     1:1  1:2  1:3    classes
      |    |    |
     10:  20:  30:    gestionnaire gestionnaire
     sfq  tbf  sfq
bande 0    1    2
</pre><p>Le trafic de masse ira vers <code class="literal">30:</code> tandis que le
trafic interactif ira vers <code class="literal">20:</code> ou 
<code class="literal">10:</code>.
</p><p>Les lignes de commande :
</p><pre class="screen"># tc qdisc add dev eth0 root handle 1: prio 
## Ceci crée *instantanément* les classes 1:1, 1:2, 1:3
  
# tc qdisc add dev eth0 parent 1:1 handle 10: sfq
# tc qdisc add dev eth0 parent 1:2 handle 20: tbf rate 20kbit buffer 1600 limit 3000
# tc qdisc add dev eth0 parent 1:3 handle 30: sfq                                
</pre><p>Regardons maintenant ce que nous avons créé :

<pre class="screen"># tc -s qdisc ls dev eth0 
qdisc sfq 30: quantum 1514b 
 Sent 0 bytes 0 pkts (dropped 0, overlimits 0) 

 qdisc tbf 20: rate 20Kbit burst 1599b lat 667.6ms 
 Sent 0 bytes 0 pkts (dropped 0, overlimits 0) 

 qdisc sfq 10: quantum 1514b 
 Sent 132 bytes 2 pkts (dropped 0, overlimits 0) 

 qdisc prio 1: bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
 Sent 174 bytes 3 pkts (dropped 0, overlimits 0) 
</pre>

Comme vous pouvez le voir, la bande 0 a déjà reçu du trafic, et un paquet a été
envoyé pendant l'exécution de cette commande !
</p><p>Nous allons maintenant générer du trafic de masse avec un outil qui
configure correctement les options TOS, et regarder de nouveau :

<pre class="screen"># scp tc ahu@10.0.0.11:./
ahu@10.0.0.11's password: 
tc                   100% |*****************************|   353 KB    00:00    
# tc -s qdisc ls dev eth0
qdisc sfq 30: quantum 1514b 
 Sent 384228 bytes 274 pkts (dropped 0, overlimits 0) 

 qdisc tbf 20: rate 20Kbit burst 1599b lat 667.6ms 
 Sent 2640 bytes 20 pkts (dropped 0, overlimits 0) 

 qdisc sfq 10: quantum 1514b 
 Sent 2230 bytes 31 pkts (dropped 0, overlimits 0) 

 qdisc prio 1: bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
 Sent 389140 bytes 326 pkts (dropped 0, overlimits 0) 
</pre>

Comme vous pouvez le voir, tout le trafic a été envoyé comme prévu vers 
le descripteur <code class="literal">30:</code>, qui est la bande de plus faible
priorité.
Maintenant, pour vérifier que le trafic interactif va vers les bandes de plus
grande priorité, nous générons du trafic interactif :
</p><pre class="screen"># tc -s qdisc ls dev eth0
qdisc sfq 30: quantum 1514b 
 Sent 384228 bytes 274 pkts (dropped 0, overlimits 0) 

 qdisc tbf 20: rate 20Kbit burst 1599b lat 667.6ms 
 Sent 2640 bytes 20 pkts (dropped 0, overlimits 0) 

 qdisc sfq 10: quantum 1514b 
 Sent 14926 bytes 193 pkts (dropped 0, overlimits 0) 

 qdisc prio 1: bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1
 Sent 401836 bytes 488 pkts (dropped 0, overlimits 0) 
</pre><p>Ca a marché. Tout le trafic supplémentaire a été vers 
<code class="literal">10:</code>, qui est notre gestionnaire de plus grande
priorité.
Aucun trafic n'a été envoyé vers les priorités les plus faibles, qui
avaient reçu au préalable tout le trafic venant de notre
<span class="command"><strong>scp</strong></span>.
</p></div></div><div class="sect2" lang="fr"><div class="titlepage"><div><div><h3 class="title"><a id="N10EDB" />Le célèbre gestionnaire de mise en file d'attente CBQ</h3></div></div></div><p>Comme dit avant, <acronym class="acronym">CBQ</acronym> est le gestionnaire de mise en 
file d'attente disponible le plus complexe, celui qui a eu le plus de 
publicité, qui est le moins compris et qui est probablement le plus farceur
lors de sa mise au point.
Ce n'est pas parce que les auteurs sont mauvais ou incompétents, loin de là,
mais l'algorithme <acronym class="acronym">CBQ</acronym> n'est pas remarquablement précis et il
ne correspond pas vraiment à la façon dont Linux fonctionne.
</p><p>En plus d'être basé sur des classes, <acronym class="acronym">CBQ</acronym> sert également
à la mise en forme de trafic et c'est sur cet aspect qu'il ne fonctionne pas 
très bien.
Il travaille comme ceci : si vous essayez de mettre en forme une 
connexion de 10mbit/s à 1mbits/s, le lien doit être inactif 90% du 
temps.
Si ce n'est pas le cas, nous devons limiter le taux de sorte qu'il 
<span class="emphasis"><em>soit</em></span> inactif 90% du temps.
</p><p>Ceci est assez dur à mesurer et c'est pour cette raison que <acronym class="acronym">CBQ</acronym>
déduit le temps d'inactivité du nombre de microsecondes qui s'écoulent entre
les requêtes de la couche matérielle pour avoir plus de données.
Cette combinaison peut être utilisée pour évaluer si le lien est chargé ou 
non.
</p><p>Ceci est plutôt léger et l'on arrive pas toujours à des résultats
convenables. Par exemple, qu'en est-il de la vitesse de liaison réelle d'une
interface qui n'est pas capable de transmettre pleinement les données à 
100mbit/s, peut-être à cause d'un mauvais pilote de périphérique ?
Une carte réseau PCMCIA ne pourra jamais atteindre 100mbit/s à cause de la 
conception du bus.
De nouveau, comment calculons-nous le temps d'inactivité ?
</p><p>Cela devient même pire quand on considère un périphérique réseau
"pas-vraiment-réel" comme <em class="wordasword">PPP Over Ethernet</em> ou
<em class="wordasword">PPTP over TCP/IP</em>.
La largeur de bande effective est dans ce cas probablement déterminée par
l'efficacité des tubes vers l'espace utilisateur, qui est énorme.
</p><p>Les personnes qui ont effectué des mesures ont découvert que 
<acronym class="acronym">CBQ</acronym> n'est pas toujours très exact, et parfois même, très 
éloigné de la configuration.
</p><p>Cependant, il marche bien dans de nombreuses circonstances.
Avec la documentation fournie ici, vous devriez être capable de le configurer
pour qu'il fonctionne bien dans la plupart des cas.
</p><div class="sect3" lang="fr"><div class="titlepage"><div><div><h4 class="title"><a id="N10F04" />Mise en forme CBQ en détail </h4></div></div></div><p>Comme dit précédemment, <acronym class="acronym">CBQ</acronym> fonctionne en s'assurant 
que le lien est inactif juste assez longtemps pour abaisser la bande passante
réelle au débit configuré.
Pour réaliser cela, il calcule le temps qui devrait s'écouler entre des 
paquets de taille moyennne.
</p><p>En cours de fonctionnement, le temps d'inactivité effectif 
(<em class="wordasword">the effective idletime</em>) est mesuré en utilisant 
l'algorithme <acronym class="acronym">EWMA</acronym> (<em class="wordasword">Exponential Weighted Moving 
Average</em>), qui considère que les paquets récents sont 
exponentiellement plus nombreux que ceux passés.
La charge moyenne UNIX (<em class="wordasword">UNIX loadaverage</em>) est
calculée de la même manière.
</p><p>Le temps d'inactivité calculé est soustrait à celui mesuré par 
<acronym class="acronym">EWMA</acronym> et le nombre résultant est appelé 
<code class="option">avgidle</code>.
Un lien parfaitement chargé a un <code class="option">avgidle</code> nul : un
paquet arrive à chaque intervalle calculé.
</p><p>Une liaison surchargée a un <code class="option">avgidle</code> négatif et 
s'il devient trop négatif, <acronym class="acronym">CBQ</acronym> s'arrête un moment et se place
alors en dépassement de limite (<em class="wordasword">overlimit</em>).
</p><p>Inversement, un lien inutilisé peut accumuler un 
<code class="option">avgidle</code> énorme, qui autoriserait alors des bandes 
passantes infinies après quelques heures d'inactivité.
Pour éviter cela, <code class="option">avgidle</code> est borné à 
<code class="option">maxidle</code>.
</p><p>En situation de dépassement de limite, <acronym class="acronym">CBQ</acronym> peut en 
théorie bloquer le débit pour une durée équivalente au temps qui doit 
s'écouler entre deux paquets moyens, puis laisser passer un paquet et bloquer
de nouveau le débit.
Regardez cependant le paramètre <code class="option">minburst</code> ci-dessous.
</p><p>Voici les paramètres que vous pouvez spécifier pour configurer la mise
en forme :
</p><div class="variablelist"><dl><dt><span class="term"><code class="option">avpkt</code></span></dt><dd><p>Taille moyenne d'un paquet mesurée en octets.
    Nécessaire pour calculer <code class="option">maxidle</code>,
    qui dérive de <code class="option">maxburst</code>, qui est spécifié en paquets.
    </p></dd><dt><span class="term"><code class="option">bandwidth</code></span></dt><dd><p>La bande passante physique de votre périphérique nécessaire pour les
    calculs du temps de non utilisation (<em class="wordasword">idle time</em>).
    </p></dd><dt><span class="term"><code class="option">cell</code></span></dt><dd><p>La durée de transmission d'un paquet n'augmente pas nécessairement 
    de manière linéaire en fonction de sa taille.
    Par exemple, un paquet de 800 octets peut être transmis en exactement 
    autant de temps qu'un paquet de 806 octets.
    Ceci détermine la granularité.
    Cette valeur est généralement positionnée à <code class="literal">8</code>, et 
    doit être une puissance de deux.
    </p></dd><dt><span class="term"><code class="option">maxburst</code></span></dt><dd><p>Ce nombre de paquets est utilisé pour calculer 
    <code class="option">maxidle</code> de telle sorte que quand
    <code class="option">avgidle</code> est égal à <code class="option">maxidle</code>,
    le nombre de paquets moyens peut être envoyé en rafale avant que 
    <code class="option">avgidle</code> ne retombe à 0.
    Augmentez-le pour être plus tolérant vis à vis des rafales de données.
    Vous ne pouvez pas configurer <code class="option">maxidle</code> directement,
    mais seulement via ce paramètre.
    </p></dd><dt><span class="term"><code class="option">minburst</code></span></dt><dd><p>Comme nous l'avons déjà indiqué, <acronym class="acronym">CBQ</acronym> doit bloquer 
    le débit dans le cas d'un dépassement de limite.
    La solution idéale est de le faire pendant exactement le temps 
    d'inutilisation calculé, puis de laisser passer un paquet.
    Cependant, les noyaux UNIX ont généralement du mal à prévoir des 
    événements plus courts que 10 ms, il vaut donc mieux limiter le débit 
    pendant une période plus longue, puis envoyer 
    <code class="option">minburst</code> paquets d'un seul coup et dormir pendant une
    durée de <code class="option">minburst</code>.
    </p><p>Le temps d'attente est appelé <em class="wordasword">offtime</em>.
    De plus grandes valeurs de <code class="option">minburst</code> mènent à une 
    mise en forme plus précise dans le long terme, mais provoquent de plus 
    grandes rafales de données pendant des périodes de quelques millisecondes.
    </p></dd><dt><span class="term"><code class="option">minidle</code></span></dt><dd><p>Si <code class="option">avgidle</code> est inférieur à 0, nous sommes en
    dépassement de limite et nous devons attendre jusqu'à ce que 
    <code class="option">avgidle</code> devienne suffisamment important pour 
    envoyer un paquet.
    Pour éviter qu'une brusque rafale de données n'empêche le lien de 
    fonctionner pendant une durée prolongée, <code class="option">avgidle</code> 
    est remis à <code class="option">minidle</code> s'il atteint une valeur trop 
    basse.
    </p><p>La valeur <code class="option">minidle</code> est spécifiée en 
    microsecondes négatives : 10 signifie alors que 
    <code class="option">avgidle</code> est borné à -10µs.
    </p></dd><dt><span class="term"><code class="option">mpu</code></span></dt><dd><p>Taille minumum d'un paquet. Nécessaire car même un paquet de taille 
    nulle est encapsulé par 64 octets sur ethernet et il faut donc un certain
    temps pour le transmettre. <acronym class="acronym">CBQ</acronym> doit connaître ce 
    paramètre pour calculer précisément le temps d'inutilisation.
    </p></dd><dt><span class="term"><code class="option">rate</code></span></dt><dd><p>Débit du trafic sortant du gestionnaire. 
    Ceci est le « <span class="quote">paramètre de vitesse</span> » !
    </p></dd></dl></div><p>En interne, <acronym class="acronym">CBQ</acronym> est finement optimisé.
Par exemple, les classes qui sont connues pour ne pas avoir de données 
présentes dans leur file d'attente ne sont pas interrogées.
Les classes en situation de dépassement de limite sont pénalisées par la
diminution de leur priorité effective.
Tout ceci est très habile et compliqué.
</p></div><div class="sect3" lang="fr"><div class="titlepage"><div><div><h4 class="title"><a id="N10FCA" />Le comportement <em class="wordasword">CBQ classful</em></h4></div></div></div><p>En plus de la mise en forme, en utilisant les approximations 
<code class="option">idletime</code> mentionnées ci-dessus, <acronym class="acronym">CBQ</acronym>
peut également agir comme une file d'attente PRIO dans le sens où les classes
peuvent avoir différentes priorités.
Les priorités de plus faible valeur seront examinées avant celles de
valeurs plus élevées.
</p><p>Chaque fois qu'un paquet est demandé par la couche matérielle pour être
envoyé sur le réseau, un processus 
<em class="wordasword">weighted round robin</em> (<acronym class="acronym">WRR</acronym>) démarre
en commençant par les classes de plus faibles numéros.
</p><p>Celles-ci sont regroupées et interrogées si elles ont des données
disponibles. Après qu'une classe ait été autorisée à retirer de la file
d'attente un nombre d'octets, la classe de priorité suivante est consultée.
</p><p>Les paramètres suivants contrôlent le processus 
<acronym class="acronym">WRR</acronym> :
</p><div class="variablelist"><dl><dt><span class="term"><code class="option">allot</code></span></dt><dd><p>Quand le <acronym class="acronym">CBQ</acronym> racine reçoit une demande d'envoi de
    paquets sur une interface, il va essayer tous les gestionnaires internes
    (dans les classes) tour à tour suivant l'ordre du paramètre
    <code class="option">priority</code>.
    A chaque passage, une classe ne peut envoyer qu'une quantité limitée de 
    données.
    Le paramètre <code class="option">allot</code> est l'unité de base de cette
    quantité.
    Voir le paramètre <code class="option">weight</code> pour plus d'informations.
    </p></dd><dt><span class="term"><code class="option">prio</code></span></dt><dd><p><acronym class="acronym">CBQ</acronym> peut également agir comme un périphérique 
    <acronym class="acronym">PRIO</acronym>.
    Les classes internes avec les priorités les plus élevées sont consultées en 
    premier et, aussi longtemps qu'elles ont du trafic, les autres classes ne 
    sont pas examinées.
    </p></dd><dt><span class="term"><code class="option">weight</code></span></dt><dd><p>Le paramètre <code class="option">weight</code> assiste le processus
    <em class="wordasword">Weighted Round Robin</em>.
    Chaque classe a tour à tour la possibilité d'envoyer ses données.
    Si vous avez des classes avec des bandes passantes significativement plus
    importantes, il est logique de les autoriser à envoyer plus de 
    données à chaque tour que les autres.
    </p><p>Vous pouvez utiliser des nombres arbitraires dans la mesure où
    <acronym class="acronym">CBQ</acronym> additionne tous les paramètres 
    <code class="option">weight</code> présents sous une classe et les normalise.
    La règle empirique qui consiste à prendre <code class="literal">rate/10</code>
    semble fonctionner correctement.
    Le paramètre <code class="option">weight</code> normalisé est multiplié par le
    paramètre <code class="option">allot</code> pour déterminer la quantité de 
    données à envoyer à chaque tour.
    </p></dd></dl></div><p>Notez, s'il vous plaît, que toutes les classes à l'intérieur d'une
hiérarchie <acronym class="acronym">CBQ</acronym> doivent avoir le même nombre majeur !
</p></div><div class="sect3" lang="fr"><div class="titlepage"><div><div><h4 class="title"><a id="N1102A" />Paramètres CBQ qui déterminent le partage &amp; 
  le prêt du lien</h4></div></div></div><p>En plus de purement limiter certains trafics, il est également possible
de spécifier quelles classes peuvent emprunter de la bande passante aux
autres classes ou, réciproquement, prêter sa bande passante.
</p><div class="variablelist"><dl><dt><span class="term"><code class="option">isolated</code>/
  <code class="option">sharing</code></span></dt><dd><p>Une classe qui est configurée avec <code class="option">isolated</code>
    ne prêtera pas sa bande passante à ses classes soeurs.
    Utilisez ceci si vous avez sur votre lien deux agences concurrentes ou qui
    ne s'apprécient pas et qui ne veulent pas se prêter gratuitement de la 
    bande passante.</p><p>Le programme de contrôle <span class="command"><strong>tc</strong></span> connait également
    <code class="option">sharing</code>, qui agit à l'inverse du paramètre
    <code class="option">isolated</code>.
    </p></dd><dt><span class="term"><code class="option">bounded</code>/
  <code class="option">borrow</code></span></dt><dd><p>Une classe peut aussi être bornée (<code class="option">bounded</code>),
    ce qui signifie qu'elle n'essaiera pas d'emprunter de la bande passante à
    ses classes enfants.
    <span class="command"><strong>tc</strong></span> connait également <code class="option">borrow</code>, qui
    agit à l'inverse de <code class="option">bounded</code>.
    </p></dd></dl></div><p>Une situation typique pourrait être le cas où vous avez deux agences
présentes sur votre lien qui sont à la fois <code class="option">isolated</code> et
<code class="option">bounded</code>.
Ceci signifie qu'elles sont strictement limitées à leur débit et qu'elles ne 
prêteront pas aux autres leur bande passante.
</p><p>A l'intérieur de ces classes d'agence, il pourrait y avoir d'autres 
classes qui sont autorisées à échanger leur bande passante.
</p></div><div class="sect3" lang="fr"><div class="titlepage"><div><div><h4 class="title"><a id="N1106A" />Configuration simple</h4></div></div></div><pre class="screen">
               1:           gestionnaire de mise en file d'attente racine
               |
              1:1           classe enfant
             /   \
            /     \
          1:3     1:4       classes terminales
           |       |
          30:     40:       gestionnares de mise en file d'attente
         (sfq)   (sfq)
</pre><p>Cette configuration limite le trafic d'un serveur web à 5 mbit et 
le trafic SMTP à 3 mbit. 
Il est souhaitable qu'ils n'occupent pas plus de 6 mbit à eux deux.
Nous avons une carte réseau à 100 mbit et les classes peuvent s'emprunter 
mutuellement de la bande passante.

<pre class="screen"># tc qdisc add dev eth0 root handle 1:0 cbq bandwidth 100Mbit         \ 
  avpkt 1000 cell 8
# tc class add dev eth0 parent 1:0 classid 1:1 cbq bandwidth 100Mbit  \
  rate 6Mbit weight 0.6Mbit prio 8 allot 1514 cell 8 maxburst 20      \
  avpkt 1000 bounded
</pre>

Cette partie installe la racine et la classe <code class="literal">1:1</code>
habituelle.
La classe <code class="literal">1:1</code> est bornée, la bande passante totale ne
pourra donc pas excéder 6 mbit.
</p><p>Comme dit avant, <acronym class="acronym">CBQ</acronym> a besoin de 
<span class="emphasis"><em>NOMBREUX</em></span> paramètres.
Tous ces paramètres sont cependant expliqués au-dessus.
La configuration <acronym class="acronym">HTB</acronym> correspondante est beaucoup plus simple.
</p><pre class="screen"># tc class add dev eth0 parent 1:1 classid 1:3 cbq bandwidth 100Mbit  \
  rate 5Mbit weight 0.5Mbit prio 5 allot 1514 cell 8 maxburst 20      \
  avpkt 1000
# tc class add dev eth0 parent 1:1 classid 1:4 cbq bandwidth 100Mbit  \
  rate 3Mbit weight 0.3Mbit prio 5 allot 1514 cell 8 maxburst 20      \
  avpkt 1000
</pre><p>Ce sont nos deux classes. Notez comment nous avons configuré la valeur 
du paramètre <code class="option">weight</code> en fonction du paramètre 
<code class="option">rate</code>.
La bande passante de l'ensemble des deux classes ne pourra jamais dépasser
6 mbit.
En fait, les identifieurs de classe (<code class="option">classid</code>) doivent
avoir le même numéro majeur que le gestionnaire de mise en file d'attente parent !
</p><pre class="screen"># tc qdisc add dev eth0 parent 1:3 handle 30: sfq
# tc qdisc add dev eth0 parent 1:4 handle 40: sfq
</pre><p>Les deux classes ont par défaut un gestionnaire de mise en file
d'attente <acronym class="acronym">FIFO</acronym>.
Nous les remplaçons par une file d'attente <acronym class="acronym">SFQ</acronym> de telle
sorte que chaque flux de données soit traité de manière égale.

<pre class="screen"># tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip \
  sport 80 0xffff flowid 1:3
# tc filter add dev eth0 parent 1:0 protocol ip prio 1 u32 match ip \
  sport 25 0xffff flowid 1:4
</pre>

</p><p>Ces commandes, directement attachées à la racine, envoient le trafic 
vers le bon gestionnaire de mise en file d'attente.
</p><p>Notez que nous utilisons <strong class="userinput"><code>tc class add</code></strong> pour
<span class="emphasis"><em>CREER</em></span> des classes à l'intérieur d'un gestionnaire de mise
en file d'attente, et que nous utilisons <strong class="userinput"><code>tc qdisc add</code></strong>
pour véritablement configurer ces classes.
</p><p>Vous vous demandez peut-être ce qui arrive au trafic qui n'est 
classifié par aucune des deux règles.
Dans ce cas, les données seront traitées à l'intérieur de 
<code class="literal">1:0</code>, et le débit ne sera pas limité.
</p><p>Si le trafic SMTP+web tente de dépasser la limite de 6 mbit/s,
la bande passante sera divisée selon le paramètre <code class="option">weight</code>,
donnant 5/8 du trafic au serveur web et 3/8 au serveur smtp.
</p><p>Avec cette configuration, vous pouvez également dire que le trafic du
serveur web sera au minimum de 5/8 * 6 mbit = 3.75 mbit.
</p></div><div class="sect3" lang="fr"><div class="titlepage"><div><div><h4 class="title"><a id="N110C6" />D'autres paramètres CBQ : 
  <code class="option">split</code> &amp;
  <code class="option">defmap</code></h4></div></div></div><p>Comme précisé avant, un gestionnaire de mise en file d'attente basé sur 
des classes doit appeler des filtres pour déterminer dans quelle classe un
paquet sera mis en file d'attente.
</p><p>En plus d'appeler les filtres, <acronym class="acronym">CBQ</acronym> offre d'autres 
options : <code class="option">defmap</code> &amp; <code class="option">split</code>.
C'est plutôt compliqué à comprendre et, de plus, ce n'est pas vital.
Mais, étant donné que ceci est le seul endroit connu où 
<code class="option">defmap</code> &amp; <code class="option">split</code> sont 
correctement expliqués, je vais faire de mon mieux.
</p><p>Etant donné que nous voulons le plus souvent réaliser le filtrage en ne
considérant que le champ <acronym class="acronym">TOS</acronym>, une syntaxe spéciale est 
fournie.
Chaque fois que <acronym class="acronym">CBQ</acronym> doit trouver où le paquet doit être mis 
en file d'attente, il vérifie si le noeud est un noeud d'aiguillage
(<em class="wordasword">split node</em>).
Si c'est le cas, un de ses sous-gestionnaires a indiqué son souhait de recevoir
tous les paquets configurés avec une certaine priorité.
Celle ci peut être dérivée du champ <acronym class="acronym">TOS</acronym> ou des options des 
sockets positionnées par les applications.
</p><p>Les bits de priorités des paquets subissent un ET logique avec le champ
<code class="option">defmap</code> pour voir si une correspondance existe.
En d'autres termes, c'est un moyen pratique de créer un filtre très rapide,
qui ne sera actif que pour certaines priorités.
Un <code class="option">defmap</code> de <code class="literal">ff</code> (en hexadécimal) vérifiera
tout tandis qu'une valeur de <code class="literal">0</code> ne vérifiera rien.
Une configuration simple aidera peut-être à rendre les choses plus 
claires :
</p><pre class="screen"># tc qdisc add dev eth1 root handle 1: cbq bandwidth 10Mbit allot 1514 \
  cell 8 avpkt 1000 mpu 64
 
# tc class add dev eth1 parent 1:0 classid 1:1 cbq bandwidth 10Mbit    \
  rate 10Mbit allot 1514 cell 8 weight 1Mbit prio 8 maxburst 20        \
  avpkt 1000
</pre><p>Préambule standard de <acronym class="acronym">CBQ</acronym>.
Je n'ai jamais pris l'habitude de la quantité de nombres nécessaires !
</p><p>Le paramètre <code class="option">defmap</code> se réfère aux bits 
TC_PRIO qui sont définis comme suit :
</p><pre class="screen">TC_PRIO..          Num  Correspond à TOS
-------------------------------------------------
BESTEFFORT         0    Maximalise la Fiabilité 
FILLER             1    Minimalise le Coût 
BULK               2    Maximalise le Débit (0x8)  
INTERACTIVE_BULK   4                               
INTERACTIVE        6    Minimise le Délai (0x10)      
CONTROL            7                               
</pre><p>Les nombres TC_PRIO.. correspondent aux bits comptés à partir de
la droite.
Voir la section <code class="literal">pfifo_fast</code> pour plus de détails sur la
façon dont les bits <acronym class="acronym">TOS</acronym> sont convertis en priorités.
</p><p>Maintenant, les classes interactive et de masse :
</p><pre class="screen"># tc class add dev eth1 parent 1:1 classid 1:2 cbq bandwidth 10Mbit     \
  rate 1Mbit allot 1514 cell 8 weight 100Kbit prio 3 maxburst 20        \
  avpkt 1000 split 1:0 defmap c0

# tc class add dev eth1 parent 1:1 classid 1:3 cbq bandwidth 10Mbit     \
  rate 8Mbit allot 1514 cell 8 weight 800Kbit prio 7 maxburst 20        \
  avpkt 1000 split 1:0 defmap 3f
</pre><p>La gestion de mise en file d'attente d'aiguillage 
(<em class="wordasword">split qdisc</em>) est <code class="literal">1:0</code> et c'est
à ce niveau que le choix sera fait.
<code class="literal">C0</code> correspond au nombre binaire 
<code class="literal">11000000</code> et <code class="literal">3F</code> au nombre binaire 
<code class="literal">00111111</code>.
Ces valeurs sont choisies de telle sorte qu'à elles deux, elles vérifient tous
les bits.
La première classe correspond aux bits 6 &amp; 7, ce qui est équivalent aux
trafics « <span class="quote">interactif</span> » et de « <span class="quote">contrôle</span> ».
La seconde classe correspond au reste.
</p><p>Le noeud <code class="literal">1:0</code> possède maintenant la table 
suivante :
</p><pre class="screen">priorité	envoyer à
0		1:3
1		1:3
2		1:3
3		1:3
4		1:3
5		1:3
6		1:2
7		1:2
</pre><p>Pour d'autres amusements, vous pouvez également donner un 
« <span class="quote">masque de changement</span> » qui indique exactement les priorités que vous
souhaitez changer.
N'utilisez ceci qu'avec la commande <strong class="userinput"><code>tc class change</code></strong>.
Par exemple, pour ajouter le trafic <em class="wordasword">best effort</em> à la
classe <code class="literal">1:2</code>, nous devrons exécuter ceci :
</p><pre class="screen"># tc class change dev eth1 classid 1:2 cbq defmap 01/01
</pre><p>La carte des priorités au niveau de <code class="literal">1:0</code> ressemble
maintenant à ceci :
</p><pre class="screen">priorité	envoyer à
0		1:2
1		1:3
2		1:3
3		1:3
4		1:3
5		1:3
6		1:2
7		1:2
</pre><p>
FIXME: <strong class="userinput"><code>tc class change</code></strong> n'a pas été testé, mais
simplement vu dans les sources.
</p></div></div><div class="sect2" lang="fr"><div class="titlepage"><div><div><h3 class="title"><a id="N1116D" />Seau de jetons à contrôle hiérarchique
  (<em class="wordasword">Hierarchical Token Bucket</em>)</h3></div></div></div><p>Martin Devera(&lt;devik&gt;) réalisa à juste titre que 
<acronym class="acronym">CBQ</acronym> est complexe et qu'il ne semble pas optimisé pour de
nombreuses situations classiques.
Son approche hiérarchique est bien adaptée dans le cas de configurations où il
y a une largeur de bande passante fixée à diviser entre différents éléments.
Chacun de ces éléments aura une bande passante garantie, avec la possibilité 
de spécifier la quantité de bande passante qui pourra être empruntée.
</p><p><acronym class="acronym">HTB</acronym> travaille juste comme <acronym class="acronym">CBQ</acronym>, 
mais il n'a pas recourt à des calculs de temps d'inoccupation pour la mise en
forme.
A la place, c'est un <em class="wordasword">Token Bucket Filter</em> basé sur des
classes, d'où son nom.
Il n'a que quelques paramètres, qui sont bien documentés sur ce
<a class="ulink" href="http://luxik.cdi.cz/~devik/qos/htb/" target="_top">site</a>.
</p><p>Au fur et à mesure que votre configuration <acronym class="acronym">HTB</acronym> se 
complexifie, votre configuration s'adapte bien.
Avec <acronym class="acronym">CBQ</acronym>, elle est déjà complexe même dans les cas 
simples !
<acronym class="acronym">HTB3</acronym> (voir <a class="ulink" href="http://luxik.cdi.cz/~devik/qos/htb/" target="_top">sa page principale</a> pour
les détails des versions HTB) fait maintenant parti des sources officielles
du noyau (à partir des versions 2.4.20-pre1 et 2.5.31 et supérieures). Il
est encore cependant possible que vous soyez obligé de récupérer la version
mise à jour de 'tc' pour HTB3. Les programmes de l'espace utilisateur
et la partie HTB du noyau doivent avoir le même numéro majeur. Sans cela,
'tc' ne marchera pas avec HTB.

</p><p>Si vous avez déjà un noyau récent ou si vous êtes sur le point de mettre à jour votre noyau, considérez 
<acronym class="acronym">HTB</acronym> coûte que coûte.
</p><div class="sect3" lang="fr"><div class="titlepage"><div><div><h4 class="title"><a id="N1119A" />Configuration simple</h4></div></div></div><p>Fonctionnellement presque identique à la configuration simple 
<acronym class="acronym">CBQ</acronym> présentée ci-dessus :
</p><pre class="screen"># tc qdisc add dev eth0 root handle 1: htb default 30

# tc class add dev eth0 parent 1: classid 1:1 htb rate 6mbit burst 15k

# tc class add dev eth0 parent 1:1 classid 1:10 htb rate 5mbit burst 15k
# tc class add dev eth0 parent 1:1 classid 1:20 htb rate 3mbit ceil 6mbit burst 15k
# tc class add dev eth0 parent 1:1 classid 1:30 htb rate 1kbit ceil 6mbit burst 15k
</pre><p>L'auteur recommande <acronym class="acronym">SFQ</acronym> sous ces classes :
</p><pre class="screen"># tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
# tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
# tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10
</pre><p>Ajouter les filtres qui dirigent le trafic vers les bonnes 
classes :
</p><pre class="screen"># U32="tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32"
# $U32 match ip dport 80 0xffff flowid 1:10
# $U32 match ip sport 25 0xffff flowid 1:20
</pre><p>Et, c'est tout.
Pas de vilains nombres non expliqués, pas de paramètres non documentés.
</p><p><acronym class="acronym">HTB</acronym> semble vraiment merveilleux.
Si <code class="literal">10:</code> et <code class="literal">20:</code> ont atteint tous 
les deux leur bande passante garantie et qu'il en reste à partager, ils
l'empruntent avec un rapport de 5:3, comme attendu.
</p><p>Le trafic non classifié est acheminé vers <code class="literal">30:</code>, 
qui a une petite bande passante, mais qui peut emprunter tout ce qui est 
laissé libre.
Puisque nous avons choisi <acronym class="acronym">SFQ</acronym> en interne, on hérite 
naturellement de l'équité.
</p></div></div></div><div class="navfooter"><hr /><table summary="Navigation footer" width="100%"><tr><td align="left" width="40%"><a accesskey="p" href="ch09s04.html">Précédent</a> </td><td align="center" width="20%"><a accesskey="u" href="ch09.html">Niveau supérieur</a></td><td align="right" width="40%"> <a accesskey="n" href="ch09s06.html">Suivant</a></td></tr><tr><td valign="top" align="left" width="40%">terminologie </td><td align="center" width="20%"><a accesskey="h" href="index.html">Sommaire</a></td><td valign="top" align="right" width="40%"> Classifier des paquets avec des filtres</td></tr></table></div></body></html>