Wiki Exemple de script pour de la QoS

Licence CC By‑SA.
Étiquettes : aucune
0
2
mar.
2011

Script mettant en œuvre de la QoS. Le flux réseau obtient par défaut la priorité la plus basse. Ensuite on élève la priorité (4 disponibles en tout) de certains flux en fonction du port ou de l’adresse IP. Vous pouvez adapter simplement le script en modifiant les 4 variables définie au début : DEV l’interface réseau, IFB l’interface créée par la commande modprobe ifb (ne devrait pas changer), DOWNLINK le débit descendant, et UPLINK l’ascendant, en kilo-octets par secondes : attention à prendre moins que la bande passante réellement disponible, environ 90 % devrait être un bon compromis. Vous pouvez aussi commenter les lignes qui sont en-dessous des echo, qui commencent par tc filter, pour désactiver un filtre.

Une introduction au sujet est disponible.

#!/bin/sh

DEV=eth0
IFB=ifb0
DOWNLINK=750
UPLINK=75

if [ $# -ne 1 ]; then
    echo "Usage: network-priority.sh (start|stop)"
    exit 1
fi

case "$1" in
start)
echo "Upload"
    tc qdisc add dev $DEV root handle 1:0 htb default 1
    # limiter la bande-passante
    tc class add dev $DEV parent 1:0 classid 1:1 htb \
        rate ${UPLINK}kbps
    tc qdisc add dev $DEV parent 1:1 handle 2:0 prio \
        bands 4 priomap 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
echo "  Default (lowest) priority"
    tc qdisc add dev $DEV parent 2:4 handle 14:0 prio
    tc qdisc add dev $DEV parent 14:1 sfq perturb 10
    tc qdisc add dev $DEV parent 14:2 sfq perturb 10
    tc qdisc add dev $DEV parent 14:3 sfq perturb 10
echo "  Highest priority"
    # pour différencier session interactive ou non
    tc qdisc add dev $DEV parent 2:1 handle 10:0 prio
    # répartir équitablement
    tc qdisc add dev $DEV parent 10:1 handle 11:0 sfq \
        perturb 10
    tc qdisc add dev $DEV parent 10:2 handle 12:0 sfq \
        perturb 10
    tc qdisc add dev $DEV parent 10:3 handle 13:0 sfq \
        perturb 10
echo "    SSH (server)"
    tc filter add dev $DEV parent 2:0 protocol ip prio 1 \
        u32 match ip sport 22 0xffff flowid 2:1
    tc filter add dev $DEV parent 2:0 protocol ipv6 prio 2 \
        u32 match ip6 sport 22 0xffff flowid 2:1
echo "  High priority"
    tc qdisc add dev $DEV parent 2:2 handle 20:0 sfq \
        perturb 10
echo "    *box (192.168.0.254)"
    tc filter add dev $DEV parent 2:0 protocol ip prio 3 \
        u32 match ip dst 192.168.0.254 flowid 2:2
echo "    MPD (server)"
    tc filter add dev $DEV parent 2:0 protocol ip prio 4 \
        u32 match ip sport 8000 0xffff flowid 2:2
echo "  Normal priority"
    tc qdisc add dev $DEV parent 2:3 handle 30:0 sfq \
        perturb 10
echo "    HTTP (client)"
    tc filter add dev $DEV parent 2:0 protocol ip prio 5 \
        u32 match ip dport 80 0xffff flowid 2:3
    tc filter add dev $DEV parent 2:0 protocol ipv6 prio 6 \
        u32 match ip6 dport 80 0xffff flowid 2:3
echo "    HTTPS (client)"
    tc filter add dev $DEV parent 2:0 protocol ip prio 7 \
        u32 match ip dport 443 0xffff flowid 2:3
    tc filter add dev $DEV parent 2:0 protocol ipv6 prio 8 \
        u32 match ip6 dport 443 0xffff flowid 2:3
echo "    FTP (client)"
    tc filter add dev $DEV parent 2:0 protocol ip prio 9 \
        u32 match ip dport 21 0xffff flowid 2:3
    tc filter add dev $DEV parent 2:0 protocol ipv6 prio 10 \
        u32 match ip6 dport 21 0xffff flowid 2:3

echo "Download"
    modprobe ifb
    ip link set dev $IFB up
    tc qdisc add dev $DEV ingress
    tc filter add dev $DEV parent ffff: protocol ipv6 \
        u32 match ip6 dst ::/128 action mirred egress redirect dev $IFB
    tc filter add dev $DEV parent ffff: protocol ip \
        u32 match ip dst 0/0 action mirred egress redirect dev $IFB
    tc qdisc add dev $IFB root handle 1:0 htb default 1
    tc class add dev $IFB parent 1:0 classid 1:1 htb \
        rate ${DOWNLINK}kbps
    tc qdisc add dev $IFB parent 1:1 handle 2:0 prio \
        bands 4 priomap 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3
echo "  Default (lowest) priority"
    tc qdisc add dev $IFB parent 2:4 handle 14:0 prio
    tc qdisc add dev $IFB parent 14:1 sfq perturb 10
    tc qdisc add dev $IFB parent 14:2 sfq perturb 10
    tc qdisc add dev $IFB parent 14:3 sfq perturb 10
echo "  Highest priority"
    # différencier session intéractive (automatique)
    tc qdisc add dev $IFB parent 2:1 handle 10:0 prio
    # répartir équitablement
    tc qdisc add dev $IFB parent 10:1 handle 11:0 sfq \
        perturb 10
    tc qdisc add dev $IFB parent 10:2 handle 12:0 sfq \
        perturb 10
    tc qdisc add dev $IFB parent 10:3 handle 13:0 sfq \
        perturb 10
echo "    SSH (server)"
    tc filter add dev $IFB parent 2:0 protocol ip prio 1 \
        u32 match ip dport 22 0xffff flowid 2:1
    tc filter add dev $IFB parent 2:0 protocol ipv6 prio 2 \
        u32 match ip6 dport 22 0xffff flowid 2:1
echo "  High priority"
    tc qdisc add dev $IFB parent 2:2 handle 20:0 sfq \
        perturb 10
echo "    *box (192.168.0.254)"
    tc filter add dev $IFB parent 2:0 protocol ip prio 3 \
        u32 match ip src 192.168.0.254 flowid 2:2
echo "    MPD (server)"
    tc filter add dev $IFB parent 2:0 protocol ip prio 4 \
        u32 match ip dport 8000 0xffff flowid 2:2
echo "  Normal priority"
    tc qdisc add dev $IFB parent 2:3 handle 30:0 sfq \
        perturb 10
echo "    HTTP (client)"
    tc filter add dev $IFB parent 2:0 protocol ip prio 5 \
        u32 match ip sport 80 0xffff flowid 2:3
    tc filter add dev $IFB parent 2:0 protocol ipv6 prio 6 \
        u32 match ip6 sport 80 0xffff flowid 2:3
echo "    HTTPS (client)"
    tc filter add dev $IFB parent 2:0 protocol ip prio 7 \
        u32 match ip sport 443 0xffff flowid 2:3
    tc filter add dev $IFB parent 2:0 protocol ipv6 prio 8 \
        u32 match ip6 sport 443 0xffff flowid 2:3
echo "    FTP (client)"
    tc filter add dev $IFB parent 2:0 protocol ip prio 9 \
        u32 match ip sport 21 0xffff flowid 2:3
    tc filter add dev $IFB parent 2:0 protocol ipv6 prio 10 \
        u32 match ip6 sport 21 0xffff flowid 2:3
    ;;
stop)
    tc qdisc del dev $DEV root
    tc qdisc del dev $DEV ingress
    tc qdisc del dev $IFB root
    rmmod ifb
    ;;
*)
    echo "Usage: network-priority.sh (start|stop)"
    exit 1
    ;;
esac

exit 0
  • # Une erreur, mais pas de recherche de cause...

    Posté par  (site web personnel) . Évalué à 1 (+0/-0).

    bonjour,

    Merci pour ce script. Utilisé tel que (juste adaptation des 4 premiers paramètres), j'ai une petite erreur:

    Upload
      Default (lowest) priority
      Highest priority
        SSH (server)
      High priority
        *box (192.168.0.1)
        MPD (server)
      Normal priority
        HTTP (client)
        HTTPS (client)
        FTP (client)
    Download
    Illegal "match"
    What is "action"?
    Usage: ... u32 [ match SELECTOR ... ] [ link HTID ] [ classid CLASSID ]
                   [ police POLICE_SPEC ] [ offset OFFSET_SPEC ]
                   [ ht HTID ] [ hashkey HASHKEY_SPEC ]
                   [ sample SAMPLE ]
    or         u32 divisor DIVISOR
    
    Where: SELECTOR := SAMPLE SAMPLE ...
           SAMPLE := { ip | ip6 | udp | tcp | icmp | u{32|16|8} } SAMPLE_ARGS
           FILTERID := X:Y:Z
      Default (lowest) priority
      Highest priority
        SSH (server)
      High priority
        *box (192.168.0.1)
        MPD (server)
      Normal priority
        HTTP (client)
        HTTPS (client)
        FTP (client)
    
    • [^] # Re: Une erreur, mais pas de recherche de cause...

      Posté par  (site web personnel) . Évalué à 1 (+0/-0).

      Pendant que j'en suis au commentaires,

      juste pour valider ma compréhension: si je veut faire une classe encore moins prioritaire pour l'upload, il suffit que je rajoute quelques lignes comme cela:

      echo "    P2P (client)"
          tc filter add dev $DEV parent 2:0 protocol ip prio 11 \
          u32 match ip dport 6890 0xffff flowid 2:3
          tc filter add dev $DEV parent 2:0 protocol ipv6 prio 12 \
          u32 match ip6 dport 6890 0xffff flowid 2:3
      

      est-ce que je peut définir une plage de port au lieu d'un port précis? dport 6890-6899 est-il correct?

      merci encore.

      • [^] # Re: Une erreur, mais pas de recherche de cause...

        Posté par  . Évalué à 2 (+0/-0).

        Étonnant, je viens de vérifier que je n’avais pas mis de coquille et ici ça marche. Peux-tu vérifier que ce ne soit pas juste la ligne concernant IPv6 qui pose problème (si tu n’as pas IPv6). Il suffit de commenter :

        tc filter add dev $DEV parent ffff: protocol ipv6 \
                u32 match ip6 dst ::/128 action mirred egress redirect dev $IFB
        À priori tu as bien le module ifb0 de chargé. Le noyau est pas trop vieux ? La série 2.6.3* devrait être ok. Du coup le script marchera pour l’upload, par contre pour le download ça ne doit pas marcher.

        Pour la plage de port, c’est très compliqué… le match fonctionne avec un masque, qui est le 0xffff écrit après le numéro de port : on vérifie alors la correspondance exacte. Pour définir une plage de port il suffit « d’éteindre » les bons bits du masque. L’inconvénient est que le choix de la plage de port n’est pas totalement libre, ceci pour des raisons de performance.

        Attention ! Quand tu écris un filter avec un flowid 2:3 tu enverras vers la priorité que j’ai appelée « normal », qui n’est pas la plus basse. En l’état actuel du script ton client P2P utilisera la plus basse priorité car c’est celle par défaut (sauf si ta plage de port passe par 8000 qui est celui de MPD).

        Donc du coup je ne sais pas trop ce que tu veux : élever la priorité de client P2P, ou lui donner la plus basse priorité ? Dans le premier cas c’est faisable mais il faut jeter un œil au lartc pour voir précisément comment fonctionne le masque. Dans le second cas, il n’y a rien à faire.

        • [^] # Re: Une erreur, mais pas de recherche de cause...

          Posté par  (site web personnel) . Évalué à 1 (+0/-0).

          Concernant le noyau, il n'est pas vieux: 2.6.32-27

          Pour la plage de port, comme elle n'est pas très grande (10 ports), je peux peut être faire les dix lignes dont j'ai besoin...

          Pour le P2P, mon but était de le diminuer, mais en fait je ne me servais pas de la priorité normale, j'ai donc monté le serveur http en priorité normal. Le résultat est le même.

          Pour le message d'erreur, ce n'est pas l'IPV6, car si je commente la ligne, aucun changement. Le fait que le download ne soit pas maitrisé m'importe peu sur une ligne ADSL. C'est de toute façon tellement supérieur à mon upload que mon serveur n'est pas trop chargé de ce point de vue...

          Mais c'est sur que c'est frustrant de ne pas comprendre la source de l'erreur. Si je peux t'aider à debugger en te donnant plus d'info, n'hésite pas. Mes capacités s'arretent là. Mais je pense que ton outil est une très bonne initiative pour tous ceux qui s'autohebergent.

          • [^] # Re: Une erreur, mais pas de recherche de cause...

            Posté par  (site web personnel) . Évalué à 1 (+0/-0).

            Par contre, et je ne sais pas si c'est structurellement possible dans ton script.

            Si tu veux supprimer les limitations pour les mouvements sur le reseau local? comment fais tu? Car pour le moment ta machine se limite sur le reseau local également. Ca pose un vrai problème pour un serveur de fichier...

            Je suppose que c'est la raison pour laquelle dans la doc TC, ils partaient au départ de 2 parents?, alors que tous tes services passent par la même classe racine.

            J'essaye de comprendre, mais comme je ne comprend pas tous ce qu'il y a dans le code...

            • [^] # Re: Une erreur, mais pas de recherche de cause...

              Posté par  . Évalué à 2 (+0/-0).

              Effectivement, je n’avais pas pensé au réseau local en faisant le script.

              Ton idée de partir de deux parents est bonne. C’est possible de l’ajouter au script : avec une classe fille supplémentaire au htb.

              Concrètement au lieu d’avoir :

              tc class add dev $DEV parent 1:0 classid 1:1 htb \
                      rate ${UPLINK}kbps
              On aura, à vu d’œil :
              tc class add dev $DEV parent 1:0 classid 1:1 htb \
                      rate ${UPLINK}kbps
              tc class add dev $DEV parent 1:0 classid 1:2 htb \
                      rate ${LOCAL}kbps
              tc filter add dev $DEV parent 1:0 protocol ip prio 99 \
                      u32 match ip dst IP/PLAGE flowid  1:2
              Idem en débit descendant (dst devient src cependant). L’IP/PLAGE est la notation usuelle, pour les adresses privées : 192.168.0.0/16.

              Ça ne sera pas l’idéal, mais ça fonctionnera. Pour mieux faire il faudrait aller voir du côté du paramètre ceil de htb. Genre écrire rate 1kbps ceil ${LOCAL}kbps, peut-être ?

Envoyer un commentaire

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.