• [^] # Re: TC ?

    Posté par . En réponse au journal Spécifier une interface réseau à un processus (2). Évalué à 3. Dernière modification le 09 août 2014 à 20:06.

    Voilà, en guise d’exemple un script. À mon niveau c’est plus du bricolage qu’autre chose.

    Quelques petits trucs à savoir :
    — renseigner les 4 variables correctement (ça c’était le obvious) ;
    — le périphérique IFB est un périphérique spécial qui permet de contrôler le flux entrant1, pour la plupart des noyaux (récents) il y a un module éponyme à activer, testez si chez vous c’est le cas avec modprobe ifb pour l’activer et vérifier ainsi qu’il est bien présent et rmmod ifb pour le désactiver à nouveau ;
    DOWNLINK et UPLINK sont les débits entrant et sortant (en kB/s).

    ATTENTION ! il faut impérativement sous-estimer les capacités réelles de la ligne, sinon ça marche pas (pour de sombres histoires de files d’attentes). On perd donc un chouïa en performance, mais on gagne en confort. Par exemple ma connexion doit tourner autour de 120/850 (au doigt mouillé, dans ses mauvais jours) mais je me limite à 105/750.

    Vous pouvez, à tout hasard essayer le script (en root bien sûr 0:) ), sous décharge de toute responsabilité... C’est qu’en règle générale il n’y a pas de solution clef en main. Il faut simplement mettre start, stop ou restart en argument.

    #!/bin/sh
    DEV=eth0
    IFB=ifb0
    DOWNLINK=750
    UPLINK=105
    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 " Normal priority"
     tc qdisc add dev $DEV parent 2:3 handle 30:0 sfq \
     perturb 10
    # " ICMP"
     tc filter add dev $DEV parent 2:0 protocol ip prio 5 \
     u32 match ip dport 1 0xffff flowid 2:3
     tc filter add dev $DEV parent 2:0 protocol ipv6 prio 6 \
     u32 match ip6 dport 1 0xffff flowid 2:3
    #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 " DNS (client)"
     tc filter add dev $DEV parent 2:0 protocol ip prio 7 \
     u32 match ip protocol 17 0xff flowid 2:3
    #echo " HTTPS (client)"
     tc filter add dev $DEV parent 2:0 protocol ip prio 8 \
     u32 match ip dport 443 0xffff flowid 2:3
     tc filter add dev $DEV parent 2:0 protocol ipv6 prio 9 \
     u32 match ip6 dport 443 0xffff flowid 2:3
     modprobe ifb
    #echo "Up the virtual device"
     ip link set dev $IFB up
     tc qdisc add dev $DEV handle ffff: ingress
    #echo "Download"
     tc filter add dev $DEV parent ffff: protocol ipv6 \
     u32 match u32 0 0 action mirred egress redirect dev $IFB
     tc filter add dev $DEV parent ffff: protocol ip \
     u32 match u32 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 " Normal priority"
     tc qdisc add dev $IFB parent 2:3 handle 30:0 sfq \
     perturb 10
    #echo " ICMP"
     tc filter add dev $IFB parent 2:0 protocol ip prio 5 \
     u32 match ip sport 1 0xffff flowid 2:3
     tc filter add dev $IFB parent 2:0 protocol ipv6 prio 6 \
     u32 match ip6 sport 1 0xffff flowid 2:3
    #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 " DNS (client)"
     tc filter add dev $IFB parent 2:0 protocol ip prio 7 \
     u32 match ip protocol 17 0xff flowid 2:3
    #echo " HTTPS (client)"
     tc filter add dev $IFB parent 2:0 protocol ip prio 8 \
     u32 match ip sport 443 0xffff flowid 2:3
     tc filter add dev $IFB parent 2:0 protocol ipv6 prio 9 \
     u32 match ip6 sport 443 0xffff flowid 2:3
    }
    stop() {
     tc qdisc del dev $DEV root
     tc qdisc del dev $DEV ingress
     tc qdisc del dev $IFB root
     ip link set dev $IFB down
     rmmod ifb
    }
    restart() {
     stop
     start
    }
    [[ "1ドル" == "start" ]] && start
    [[ "1ドル" == "stop" ]] && stop
    [[ "1ドル" == "restart" ]] && restart

    Que fait le script ? Que ce soit le flux entrant ou sortant, la politique est la même. Je crée quatre files d’attente (bands 4 priomap), sachant qu’une file est vidée (et donc ses paquets envoyés sur le réseau) si et seulement si les files de priorités plus élevées sont déjà vides. Ensuite y’a quelques menus ajustements que je ne discuterai pas. Le plus important est la directive filter qui permet d’envoyer les paquets en fonction du port (source ou destination sport ou dport, etc.), sur la bonne file d’attente : flowid 2:n, avec n variant de 1 à 4 son numéro par priorité décroissante. Le serveur (local) SSH a la priorité maximale et monopolise la file 1. Ensuite vient la box (c’était pour la télé je crois), puis en priorité "normale" j’y ai foutu l’ICMP, le HTTP(S) et le DNS (lorsque le poste est client), en bref : la navigation. Il peut être utile d’y mettre tout service que vous considérez utiles (le POP/IMAP/SMTP aurait du s’y retrouver, ainsi que la messagerie instantannée, etc.). Tout le reste, donc le P2P, est envoyé par défaut sur la file d’attente de plus basse priorité (pour l’anecdote, j’ai mis un moment pour comprendre qu’il fallait promouvoir l’ICMP ).

    Voilà. Ça a l’air de fonctionner (je l’ai réactivé du coup chez moi, avec un noyau 3.14, mais je n’ai pas refait les tests poussé de l’époque) dans la grande majorité des cas, mais avec certains sites (bon à vrai dire un seul rencontré et j’ose pas aggraver mon cas alors je ne dirai pas lequel), ça torche pendant quelques secondes, puis ça me coupe la connexion, pour je ne sais quelle raison. Il me suffit de couper le script et relancer le téléchargement.

    Pour le lartc, j’ai oublié de préciser que ce sont les chapitres 9 et suivants qui sont utiles pour comprendre tout le bouzin. Y’a aussi dans le cookbook un exemple un peu similaire au mien, mais moins complet \o/.

    1 Ceux qui ont la chance de posséder un routeur peuvent s’en passer : il leur suffit de contrôler le débit sortant de chacune des deux interfaces.