Sophie

Sophie

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

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>Réalisation</title><link href="style.css" rel="stylesheet" type="text/css" /><meta content="DocBook XSL Stylesheets V1.73.1" name="generator" /><link rel="start" href="index.html" title="Guide pratique de la gestion de bande passante d'une ligne ADSL" /><link rel="up" href="index.html" title="Guide pratique de la gestion de bande passante d'une ligne ADSL" /><link rel="prev" href="ar01s03.html" title="Fonctionnement" /><link rel="next" href="ar01s05.html" title="Test" /></head><body><div class="navheader"><table summary="Navigation header" width="100%"><tr><th align="center" colspan="3">Réalisation</th></tr><tr><td align="left" width="20%"><a accesskey="p" href="ar01s03.html">Précédent</a> </td><th align="center" width="60%"> </th><td align="right" width="20%"> <a accesskey="n" href="ar01s05.html">Suivant</a></td></tr></table><hr /></div><div class="sect1" lang="fr"><div class="titlepage"><div><div><h2 class="title"><a id="implementation" />Réalisation</h2></div></div></div><p>
      Après toutes ces explications, il est temps de passer à la mise en
      oeuvre sous Linux.
    </p><div class="sect2" lang="fr"><div class="titlepage"><div><div><h3 class="title"><a id="N1019D" />Avertissements</h3></div></div></div><p>
        Brider le rythme d'émission des données vers le modem ADSL n'est pas
        aussi simple qu'il y parait. La plupart des modems DSL établit
        juste un pont Ethernet entre le routeur Linux et la passerelle du
        côté du FAI. La couche de liaison de données s'appuie le plus
        souvent sur ATM qui envoie les données au moyen de cellules de 53
        octets. Cinq octets sont consommés pour l'en-tête ATM laissant ainsi
        48 octets de données utiles. La transmission d'un simple octet de
        données isolé ne peut donc pas demander moins de 53 octets au niveau
        du lien ATM. Dans le cas d'un acquittement TCP typique qui comprend
        0 octet de données, 20 octets d'en-tête TCP, autant d'en-tête IP
        et 18 de préambule Ethernet, les données utiles (40 octets) sont
        inférieures au minimum de 48 octets requis par une trame Ethernet.
        Afin d'envoyer les 64 (48+16) octets via ATM, deux cellules ATM sont
        nécessaires, d'où une consommation de 106 octets de bande passante au
        niveau du lien ADSL. Chaque paquet TCP d'acquittement gaspille donc
        42 octets de bande passante. Ceci ne serait pas gênant si Linux prenait
        en compte l'encapsulation due au modem ADSL. Il ne peut malheureusement
        pas le faire et se cantonne aux en-têtes TCP et IP ainsi qu'aux 14
        octets d'adresse MAC (les quatre octets de CRC gérés au niveau matériel sont
        ignorés). Linux ne prend pas en compte la taille minimale de trame
        Ethernet ni la taille de cellule ATM.
      </p><p>
        Tout ceci pour convaincre qu'il faut limiter le trafic sortant à une
        valeur sensiblement inférieure à la véritable capacité de la ligne
        (jusqu'à ce qu'on dispose d'un ordonnanceur de paquets capable de
        prendre en compte les différentes encapsulations employées). Vous
        pouvez penser avoir trouvé un bon réglage mais constater des sauts de
        latence au delà de trois secondes lors d'un téléchargements important. Ceci
        viendra probablement d'une mauvaise évaluation de la bande passante
        consommée par les petits paquets d'acquittement.
      </p><p>
        Je travaille depuis quelques mois sur une solution à ce problème et
        j'ai presque terminé quelque chose qui sera publié afin que chacun
        puisse le tester. Ma solution repose sur une file en espace
        utilisateur à la place de la QoS de Linux pour limiter le rythme de
        transfert des paquets. Il s'agit d'une variante d'HTB en espace
        utilisateur. Pour l'instant cette solution a été capable de réguler
        le trafic sortant lors de téléchargements massifs (plusieurs flux)
        et de transferts point-à-point en volume (gnutella, sic) avec une
        telle efficacité que la latence dépasse au plus de 400 ms la
        latence nominale de 15 ms inhérente à mon lien ADSL. Pour davantage
        d'informations, abonnez-vous à la liste de diffusion ou surveillez
        les mises à jour de ce document.
      </p></div><div class="sect2" lang="fr"><div class="titlepage"><div><div><h3 class="title"><a id="N101A6" />Script: mon_limiteur</h3></div></div></div><p>
        Ci-suit le source d'un script que j'emploie pour gérer la bande
        passante de mon routeur Linux. Il s'appuie sur les concepts expliqués
        dans ce guide. Le trafic sortant est ventilé entre une des sept files
        disponibles en fonction de son type. Le trafic entrant est placé
        dans une file parmi deux, le trafic TCP étant jeté en premier en cas
        de surcharge de la ligne. Les valeurs conviennent à mon installation
        mais les résultats peuvent être différents ailleurs.
      </p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td valign="top" align="center" rowspan="2" width="25"><img alt="[Note]" src="images/note.png" /></td><th align="left">Note</th></tr><tr><td valign="top" align="left"><p>
        Ce script s'inspire du WonderShaper ADSL disponible sur le site du
        <a class="ulink" href="http://www.lartc.org" target="_top">LARTC</a>.
      </p></td></tr></table></div><pre class="programlisting">#!/bin/bash
#
# mon_limiteur - Limiteur et classificateur de trafic pour modem Cable ou ADSL. 
#		 Inspiré de WonderShaper (www.lartc.org)
#
# Écrit par Dan Singletary (7/8/02)
#
# Remarque - ce script suppose que le noyau a été patché avec les files
#	     HTB et IMQ disponibles ici (les noyaux à venir ne demanderont
#	     pas forcément l'application d'un correctif):
#       http://luxik.cdi.cz/~devik/qos/htb/
#       http://luxik.cdi.cz/~patrick/imq/
#
# Options de configuration pour mon_limiteur:
#  DEV    - correspond au périphérique ethX connecté au modem
#  RATEUP - à positionner à une valeur inférieure à la bande
#	    passante montante de la ligne.
#	    Pour ma ligne ADSL en 1500/128, RATEUP=90 convient au rythme
#	    montant de 128kbps. A vous d'ajuster.
#  RATEDN - à positionner en dessous de la bande passante descendante de
#	    la ligne.
#
#
#  Principe d'utilisation d'imq pour limiter le trafic entrant:
#
#    Il est impossible de limiter directement le rythme auquel les
#  données vous sont envoyées depuis l'Internet. Afin de limiter le
#  trafic entrant, on s'appuie sur les mécanismes anti-congestion de
#  TCP. Ceci signifie que SEUL LE TRAFIC TCP PEUT SE LIMITER. Le
#  trafic hors TCP est placé dans une queue prioritaire car le jeter
#  ne conduit vraisemblablement qu'à une retransmission ultérieure
#  qui accroît la bande passante consommée.
#  On limite le trafic TCP en jetant les paquets lorsqu'ils débordent
#  de la file HTB qui les limitera à un certain rythme (RATEDN)
#  légèrement inférieur à la capacité réelle de la ligne. Jeter ces
#  paquets revient à en singer la perte par la file d'émission du
#  côté du FAI. Ceci a l'avantage d'éviter la congestion de la file
#  d'émission chez le FAI puisque TCP ralentira avant qu'elle ne
#  se remplisse. L'usage d'une stratégie de mise en attente basée sur
#  la classification des paquets par priorité permet de ne PAS jeter
#  certains types de paquets (ssh, telnet, etc). Les paquets ne sont
#  retirés des files d'attente de faible priorité qu'une fois que
#  chaque classe a atteint un seuil minimum (1/7 de la bande passante
#  dans ce script).
#
#  Résumé:
#   * La perte d'un paquet TCP diminue le rythme de réception de la
#     connexion associée via les mécanismes de contrôle de congestion.
#   * Jeter des paquets TCP n'apporte rien. S'ils sont importants, ils
#     seront retransmis.
#   * Limiter le rythme des connexions TCP entrantes en dessous de la
#     capacité de la ligne DEVRAIT éviter la mise en attente des paquets
#     du côté du FAI (DSLAM, concentrateur de cables, etc). L'expérience
#     indique que ces files contiennent 4 secondes de trafic à 1500kbps,
#     soit 6Mb de données. A ce niveau, l'absence de mise en attente
#     diminue la latence.
#
#  Avertissements:
#   * Est-ce que la limitation de bande passante diminue l'efficacité de
#     transferts TCP massifs ?
#     - Apparemment non. L'augmentation de priorité des paquets
#       d'acquittement maximise le débit en évitant de perdre de la bande
#       passante à retransmettre des paquets déjà reçus.
#   

# NOTE: La configuration ci-dessous fonctionne avec ma connexion ADSL
# 1.5M/128K via Pacific Bell Internet (SBC Global Services)

DEV=eth0
RATEUP=90
RATEDN=700  # Nettement inférieur à la capacité de la ligne de 1500.
	    # On n'a donc pas à limiter le trafic entrant jusqu'à ce
	    # qu'une meilleure réalisation telle que la modification
	    # de fenêtre TCP soit disponible.

# 
# Fin des options de configuration
#

if [ "$1" = "status" ]
then
        echo "[qdisc]"
        tc -s qdisc show dev $DEV
        tc -s qdisc show dev imq0
        echo "[class]"
        tc -s class show dev $DEV
        tc -s class show dev imq0
        echo "[filter]"
        tc -s filter show dev $DEV
        tc -s filter show dev imq0
        echo "[iptables]"
        iptables -t mangle -L MONLIMITEUR-OUT -v -x 2&gt; /dev/null
        iptables -t mangle -L MONLIMITEUR-IN -v -x 2&gt; /dev/null
        exit
fi

# Remise à zéro
tc qdisc del dev $DEV root    2&gt; /dev/null &gt; /dev/null
tc qdisc del dev imq0 root 2&gt; /dev/null &gt; /dev/null
iptables -t mangle -D POSTROUTING -o $DEV -j MONLIMITEUR-OUT 2&gt; /dev/null &gt; /dev/null
iptables -t mangle -F MONLIMITEUR-OUT 2&gt; /dev/null &gt; /dev/null
iptables -t mangle -X MONLIMITEUR-OUT 2&gt; /dev/null &gt; /dev/null
iptables -t mangle -D PREROUTING -i $DEV -j MONLIMITEUR-IN 2&gt; /dev/null &gt; /dev/null
iptables -t mangle -F MONLIMITEUR-IN 2&gt; /dev/null &gt; /dev/null
iptables -t mangle -X MONLIMITEUR-IN 2&gt; /dev/null &gt; /dev/null
ip link set imq0 down 2&gt; /dev/null &gt; /dev/null
rmmod imq 2&gt; /dev/null &gt; /dev/null

if [ "$1" = "stop" ] 
then 
        echo "Limitation de débit désactivée sur $DEV."
        exit
fi

###########################################################
#
# Limitation de trafic sortant (limite supérieure à RATEUP)

# positionnement de la taille de la file d'émission pour obtenir
# une latence d'environ 2 secondes pour les paquets de la file
# de faible priorité.
ip link set dev $DEV qlen 30

# modification de MTU du périphérique sortant.
# - Diminuer la MTU abaisse la latence mais dégrade le débit en raison de
#   la surcharge IP et TCP.
ip link set dev $DEV mtu 1000

# ajout de la stratégie HTB
tc qdisc add dev $DEV root handle 1: htb default 26

# ajout de la classe de limitation principale
tc class add dev $DEV parent 1: classid 1:1 htb rate ${RATEUP}kbit

# ajout des classes filles:
# - chaque classe dispose AU MOINS de son quota de bande passante. Aucune
#   classe n'est donc étouffée par les autres. Chaque classe peut également
#   consommer toute la bande passante si aucune autre classe ne l'emploie.
tc class add dev $DEV parent 1:1 classid 1:20 htb rate $[$RATEUP/7]kbit ceil ${RATEUP}kbit prio 0
tc class add dev $DEV parent 1:1 classid 1:21 htb rate $[$RATEUP/7]kbit ceil ${RATEUP}kbit prio 1
tc class add dev $DEV parent 1:1 classid 1:22 htb rate $[$RATEUP/7]kbit ceil ${RATEUP}kbit prio 2
tc class add dev $DEV parent 1:1 classid 1:23 htb rate $[$RATEUP/7]kbit ceil ${RATEUP}kbit prio 3
tc class add dev $DEV parent 1:1 classid 1:24 htb rate $[$RATEUP/7]kbit ceil ${RATEUP}kbit prio 4
tc class add dev $DEV parent 1:1 classid 1:25 htb rate $[$RATEUP/7]kbit ceil ${RATEUP}kbit prio 5
tc class add dev $DEV parent 1:1 classid 1:26 htb rate $[$RATEUP/7]kbit ceil ${RATEUP}kbit prio 6

# ajout de la stratégie aux classes filles
# - SFQ offre un traitement sensiblement équitable de chaque classe.
tc qdisc add dev $DEV parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev $DEV parent 1:21 handle 21: sfq perturb 10
tc qdisc add dev $DEV parent 1:22 handle 22: sfq perturb 10
tc qdisc add dev $DEV parent 1:23 handle 23: sfq perturb 10
tc qdisc add dev $DEV parent 1:24 handle 24: sfq perturb 10
tc qdisc add dev $DEV parent 1:25 handle 25: sfq perturb 10
tc qdisc add dev $DEV parent 1:26 handle 26: sfq perturb 10

# répartition du trafic en classe via fwmark
# - le trafic est réparti en classes de priorité suivant l'indicateur
#   fwmark des paquets (ceux-ci sont positionnés avec iptables un peu plus
#   loin). La classe de priorité par défaut a été mise à 1:26 de telle sorte
#   que les paquets qui ne sont pas marqués se retrouvent dans la classe de
#   priorité la plus faible.
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:20
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:21
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 22 fw flowid 1:22
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 23 fw flowid 1:23
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 24 fw flowid 1:24
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 25 fw flowid 1:25
tc filter add dev $DEV parent 1:0 prio 0 protocol ip handle 26 fw flowid 1:26

# ajout de MONLIMITEUR-OUT à la table de modification des paquets d'iptables
# - ceci déclare la table employée pour filtrer et classer les paquets
iptables -t mangle -N MONLIMITEUR-OUT
iptables -t mangle -I POSTROUTING -o $DEV -j MONLIMITEUR-OUT

# ajout de fwmark pour classer les différents types de trafic
# - fwmark est positionné de 20 à 26 suivant la classe. 20 correspond à la
#   priorité la plus forte.
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --sport 0:1024 -j MARK --set-mark 23 # Trafic sur les ports bas
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --dport 0:1024 -j MARK --set-mark 23 # "" 
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --dport 20 -j MARK --set-mark 26     # Port ftp-data, faible priorité
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --dport 5190 -j MARK --set-mark 23   # Messagerie Immédiate AOL
iptables -t mangle -A MONLIMITEUR-OUT -p icmp -j MARK --set-mark 20               # ICMP (ping) - forte priorité (impressionnez vos amis)
iptables -t mangle -A MONLIMITEUR-OUT -p udp -j MARK --set-mark 21                # DNS (petits paquets)
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --dport ssh -j MARK --set-mark 22    # shell sécurisé
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --sport ssh -j MARK --set-mark 22    # shell sécurisé
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --dport telnet -j MARK --set-mark 22 # telnet (hum...)
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --sport telnet -j MARK --set-mark 22 # telnet (hum...)
iptables -t mangle -A MONLIMITEUR-OUT -p ipv6-crypt -j MARK --set-mark 24         # IPSec - la surcharge n'est pas connue...
iptables -t mangle -A MONLIMITEUR-OUT -p tcp --sport http -j MARK --set-mark 25   # Serveur WWW local
iptables -t mangle -A MONLIMITEUR-OUT -p tcp -m length --length :64 -j MARK --set-mark 21 # Petits paquets (des ACK probablement)
iptables -t mangle -A MONLIMITEUR-OUT -m mark --mark 0 -j MARK --set-mark 26      # Répétition - on marque les paquets restants à 26 (faible priorité)

# Fin de la limitation sortante
#
####################################################

echo "Limitation de trafic sortant activé sur $DEV.  Débit: ${RATEUP}kbit/sec."

# Décommenter la ligne suivante pour n'avoir que la limitation de trafic montant.
# exit

####################################################
#
# Limitation du trafic entrant (débit maximal de RATEDN)

# on force le chargement du module imq

modprobe imq numdevs=1

ip link set imq0 up

# ajout de la stratégie de mise en file d'attente
# - par défaut une classe 1:21 à faible priorité

tc qdisc add dev imq0 handle 1: root htb default 21

# ajout de la classe de limitation principale
tc class add dev imq0 parent 1: classid 1:1 htb rate ${RATEDN}kbit

# ajout des classes filles
# - trafic TCP en 21, le reste en 20
#
tc class add dev imq0 parent 1:1 classid 1:20 htb rate $[$RATEDN/2]kbit ceil ${RATEDN}kbit prio 0
tc class add dev imq0 parent 1:1 classid 1:21 htb rate $[$RATEDN/2]kbit ceil ${RATEDN}kbit prio 1

# ajout de la stratégie de limitation aux classes filles
# - voir les remarques ci-dessus sur SFQ.
tc qdisc add dev imq0 parent 1:20 handle 20: sfq perturb 10
tc qdisc add dev imq0 parent 1:21 handle 21: red limit 1000000 min 5000 max 100000 avpkt 1000 burst 50

# répartition du trafic en classe via fwmark
# - le trafic est réparti en classes de priorité suivant l'indicateur
#   fwmark des paquets (ceux-ci sont positionnés avec iptables un peu plus
#   loin). La classe de priorité par défaut à été mise à 1:26 de telle sorte
#   que les paquets qui ne sont pas marqués se retrouvent dans la classe de
#   priorité la plus faible.
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 20 fw flowid 1:20
tc filter add dev imq0 parent 1:0 prio 0 protocol ip handle 21 fw flowid 1:21

# ajout de MONLIMITEUR-IN à la table de modification des paquets d'iptables
iptables -t mangle -N MONLIMITEUR-IN
iptables -t mangle -I PREROUTING -i $DEV -j MONLIMITEUR-IN

# ajout de fwmark pour classer les différents types de trafic
# - fwmark est positionné de 20 à 21 suivant la classe. 20 correspond à la
#   priorité la plus forte.
iptables -t mangle -A MONLIMITEUR-IN -p ! tcp -j MARK --set-mark 20              # Forte priorité pour les paquets non TCP
iptables -t mangle -A MONLIMITEUR-IN -p tcp -m length --length :64 -j MARK --set-mark 20 # Les petits paquets TCP sont probablement des ACK
iptables -t mangle -A MONLIMITEUR-IN -p tcp --dport ssh -j MARK --set-mark 20    # shell sécurisé
iptables -t mangle -A MONLIMITEUR-IN -p tcp --sport ssh -j MARK --set-mark 20    # shell sécurisé
iptables -t mangle -A MONLIMITEUR-IN -p tcp --dport telnet -j MARK --set-mark 20 # telnet (hum...)
iptables -t mangle -A MONLIMITEUR-IN -p tcp --sport telnet -j MARK --set-mark 20 # telnet (hum...)
iptables -t mangle -A MONLIMITEUR-IN -m mark --mark 0 -j MARK --set-mark 21              # Répétition - les paquets sans marque sont positionnés à 21 (faible priorité)

# on envoie les paquets précédents à l'interface imq0.
iptables -t mangle -A MONLIMITEUR-IN -j IMQ

# Fin de la limitation de trafic entrant.
#
####################################################

echo "Limitation de trafic entrant activée sur $DEV.  Débit: ${RATEDN}kbit/sec."</pre></div></div><div class="navfooter"><hr /><table summary="Navigation footer" width="100%"><tr><td align="left" width="40%"><a accesskey="p" href="ar01s03.html">Précédent</a> </td><td align="center" width="20%"> </td><td align="right" width="40%"> <a accesskey="n" href="ar01s05.html">Suivant</a></td></tr><tr><td valign="top" align="left" width="40%">Fonctionnement </td><td align="center" width="20%"><a accesskey="h" href="index.html">Sommaire</a></td><td valign="top" align="right" width="40%"> Test</td></tr></table></div></body></html>