Linux Embedded

Le blog des technologies libres et embarquées

Utiliser tc pour optimiser l'upload

Lorsqu'une machine héberge plusieurs services réseau (Torrent, FTP, ...), on peut constater un manque de réactivité de la connexion (consultation de pages Web lente, ...). Vous pouvez bien évidemment limiter le débit montant (upload) de vos services FTP ou Torrent, mais cette solution n'est pas 100% optimale.

Avant d'introduire la solution retenue, voici quelques explications sur ce qu'il se produit. Les modems traditionnels traitent les paquets avec la même priorité. Seuls les paquets avec un type de service particulier ("Type Of Service" - ToS) bénéficie d'un traitement de faveur et peuvent être envoyés en priorité. Ceci permet notamment à des services comme la VoIP d'envoyer des flux de données en temps réel.

Le but de cet article est de montrer comment un routeur Linux peut être configuré pour contrôler la bande passante en upload d'une connexion xDSL et affecter différentes priorités dépendantes du type de trafic. Cette tâche se fait grâce au "traffic control" (tc) de Linux.

Notons qu'il est aussi possible de contrôler la bande passante descendante (uniquement pour les connexions TCP) mais cette tâche est beaucoup plus compliquée. En effet, vous ne pouvez pas modifier la configuration des routeurs de votre FAI. La solution est donc de supprimer certains paquets reçus dans le but de diminuer la bande passante utilisée par une connexion. Ceci fonctionne puisque TCP est conçu pour adapter automatiquement la vitesse des sessions. Cet article ne traitera pas du contrôle du débit descendant d'une connexion (pour plus d'info, consultez les ressources). Enfin, n'oubliez pas que les FAI implémentent la QoS, c'est pourquoi il est inutile de s'inquiéter à propos de la priorité des connexions VoIP/RTP/...

Vue d'ensemble

Dans cet article, je suppose qu'un routeur Linux est déjà configuré comme ceci :

Note: La configuration IPv6 ne sera pas traitée dans cet article, mais elle devrait être assez similaire.

Pour contrôler l'ordre des paquets envoyés sur Internet, ceux-ci doivent être placés dans une queue et triés au niveau du routeur :

Par défaut, les paquets en attente d'envoi se trouvent dans la queue du modem xDSL, c'est pourquoi cet article commence par expliquer comment configurer le routeur afin que ces paquets attendent dans la queue du routeur. tc est ensuite abordé dans le but de trier les paquets sortant et iptables dans le but de les marquer.

Forcer l'attente des paquets sur le routeur

La première chose à faire est de configurer le routeur Linux pour qu'il contrôle intégralement la bande passante en upload de la connexion Internet. Comme déjà évoqué, il faut que les paquets en attente d'émission soient placés en attente au niveau du routeur et non du modem.

Malheureusement, la seule solution consiste à limiter le débit montant du routeur afin que la queue du modem ne se remplisse pas (en fait, peut-être que certains modems permettent de configurer la taille de la queue d'envoi mais je ne pense même pas que cela aiderait).

Pour réaliser cette première étape, Linux offre un service de contrôle du traffic (tc - Traffic Control). tc permet de définir un arbre de "qdiscs" (queues où les paquets sont empilés) et de "classes". Une classe contient une ou plusieurs qdiscs et permet de définir où et comment les paquets sont enfilés. Dans cet article, deux types de qdiscs sont utilisés :

  • HTB (Hierarchy Token Bucket) : HTB permet de limiter la bande passante
  • SFQ (Stochastic Fairness Queueing) : SFQ permet aux paquets de chaque session d'être envoyés à tour de rôle (chaque session est ainsi traitée de manière égale)

Pour plus d'informations, n'hésitez pas à consulter les man pages de tc, tc-htb et tc-sfq.

Donc, voici les commandes permettant de limiter l'upload de $DEV à $RATEUP :

ip link set dev $DEV qlen $QLEN mtu $MTU

tc qdisc add dev $DEV root handle 1: htb default 1
  tc class add dev $DEV parent 1: classid 1:1 htb rate ${RATEUP}kbit
    tc qdisc add dev $DEV parent 1:1 handle 10: sfq perturb 10

Voici en quelques mots ce que font ces commandes :

  1. affectation de la taille de la queue et de la MTU à des valeurs plus appropriées à une connexion xDSL (par exemple $QLEN=100 and $MTU=modem_value);
  2. remplacement de la queue par défaut par une HTB;
  3. ajout d'une classe à la qdisc HTB pour limiter la bande passante à ${RATEUP}kbit;
  4. ajout d'une qdisc SFQ à cette classe;

Trier les paquets avec tc

Le système de classes HTB permet de définir plusieurs qdiscs avec des priorités différentes. Ainsi, les paquets en attente d'envoi sont triés avant d'être envoyés (la priorité la plus grande est 0) :

tc qdisc add dev $DEV root handle 1: htb default 12
  tc class add dev $DEV parent 1: classid 1:1 htb rate ${RATEUP}kbit

    tc class add dev $DEV parent 1:1 classid 1:10 htb \
      rate ${RATEMIN}kbit ceil ${RATEUP}kbit prio 0
    tc class add dev $DEV parent 1:1 classid 1:11 htb \
      rate ${RATEMIN}kbit ceil ${RATEUP}kbit prio 1
    tc class add dev $DEV parent 1:1 classid 1:12 htb \
      rate ${RATEMIN}kbit ceil ${RATEUP}kbit prio 2
    tc class add dev $DEV parent 1:1 classid 1:13 htb \
      rate ${RATEMIN}kbit ceil ${RATEUP}kbit prio 3

      tc qdisc add dev $DEV parent 1:10 handle 10: sfq perturb 10
      tc qdisc add dev $DEV parent 1:11 handle 11: sfq perturb 10
      tc qdisc add dev $DEV parent 1:12 handle 12: sfq perturb 10
      tc qdisc add dev $DEV parent 1:13 handle 13: sfq perturb 10

tc filter add dev $DEV parent 1: prio 0 protocol ip handle 10 \
  fw flowid 1:10
tc filter add dev $DEV parent 1: prio 0 protocol ip handle 11 \
  fw flowid 1:11
tc filter add dev $DEV parent 1: prio 0 protocol ip handle 12 \
  fw flowid 1:12
tc filter add dev $DEV parent 1: prio 0 protocol ip handle 13 \
  fw flowid 1:13

Ce script crée 4 queues avec des priorités de 0 à 3 et avec un débit minimum de $(RATEUP}. Ce débit minimum permet aux applications de basse priorité de garder un accès à Internet et ainsi de ne pas perdre leur connexion à cause d'un timeout (et ce même si des connexions de plus haute priorité utilise toute la bande passante).

La queue définie avec le classid 1:12 est celle par défaut et est utilisée si aucun filtre ne définit un autre comportement. Dans cet exemple, tc filter permet de trier les paquets en fonction d'un tag affecté par iptables (voir section suivante).

Marquer les paquets avec iptables

Si vous maitrisez déjà iptables, marquer les paquets est très simple. Les règles doivent être ajoutées dans la table MANGLE de la chaine POSTROUTING. Voici un exemple de tri des paquets fonctionnant avec la configuration de tc précédente :

# High priority for ping packets
iptables -t mangle -A POSTROUTING -p icmp -j MARK --set-mark 10

# Default for low port outgoing connections (clients)
iptables -t mangle -A POSTROUTING -p tcp --dport 0:1024 \
  -j MARK --set-mark 11

# Default for low port ingoing connections (servers)
iptables -t mangle -A POSTROUTING -p tcp --sport 0:1024 \
  -j MARK --set-mark 12

# High priority for DNS, SIP and ACK packets
iptables -t mangle -A POSTROUTING -p udp -j MARK --set-mark 10
iptables -t mangle -A POSTROUTING -p tcp -m length --length :64 \
  -j MARK --set-mark 10 # Small packets are generally ACKs
iptables -t mangle -A POSTROUTING -p tcp --dport sip \
  -j MARK --set-mark 10
iptables -t mangle -A POSTROUTING -p tcp --dport sip-tls \
  -j MARK --set-mark 10

# High priority for interactive sessions
iptables -t mangle -A POSTROUTING -p tcp --dport ssh \
  -j MARK --set-mark 11
iptables -t mangle -A POSTROUTING -p tcp --sport ssh \
  -j MARK --set-mark 11

# Low priority for FTP data and torrent outbound traffic
iptables -t mangle -A POSTROUTING -p tcp --sport MINPORT:MAXPORT \
  -j MARK --set-mark 14
iptables -t mangle -A POSTROUTING -p tcp --sport 6881:6999 \
  -j MARK --set-mark 14

La configuration est maintenant terminée mais il vous sera nécessaire de lancer des tests afin de déterminer la meilleure valeur de $RATEUP.

Conclusion

Malgré les services hébergés derrière une connexion (xDSL, etc), il est dorénavant possible de garder un bon ping.

tc offre des fonctionnalités bien plus poussées que celles présentées ici. N'hésitez donc pas à vous documenter via les pages man ou les références données ci-dessous. Vous pouvez aussi télécharger mon script tc-restore qui permet la configuration de tc sur un système Debian.

Références

    • le 07 juin 2011 à 16:19

      C'est amusant comme la version en français donne un éclairage nouveau au sujet :-)

      Bon article :-)

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée.