QoS HTB simple avec TC

QoS HTB appliqué avec TC , sans iptables…

Inspiré des liens suivant:

~~READMORE~~

Etat des lieux pour l'exemple et le script : eth0 est l'interface reseau utilisé.

On va “shaper” le debit à 4Mb/s en divisant en 4 bandes plus ou moins prioritaire… puis on va mettre en place quelques règles pour “ssh” , “www” etc…

Pré-requis:

# modprobe ifb
# ip link set dev ifb0 up

Ce qui créé l'interface ifb0 (en fait, y en a plus) , et ce qui monte (UP) l'interface.

ifb0 , qui n'a pas d'IP, ne sert qu'a redirigé le flux entrant de eth0 afin de lui appliqué , aussi, un QoS (sortant!).

Le script qoshtb_test.sh :

#!/bin/bash

# Source: http://linuxfr.org/wiki/Une-introduction-au-contr%C3%B4le-du-trafic-r%C3%A9seau-avec-Linux
# Autres:
# http://blog.nicolargo.com/2009/03/simuler-un-lien-wan-sous-linux.html
# http://www.harald-hoyer.de/linux/traffic-control

[ -n "$MODE" ] || MODE="$1"

# pre-requis:
# # modprobe ifb 
# # ip link set dev ifb0 up

IFACE=eth0
BACKFACE=ifb0

TC=/sbin/tc

[ -x "${TC}" ] || exit 0

# ---------------------------------------------
# QoS simple In/Out sur eth0
# "ifb0" sert a appliquer le QoS sur la partie "IN" de "eth0" 
# (parce que nativement, ça ne s'applique que sur le "OUT")
# 
# Principe: On defini le debit MAX (montant et descendant) ,
# qu'on divise en 4 bandes passantes.
# Par defaut, le debit MAX est attribué quelque soit la priorité.
# Mais lorsqu'il y a concurrence, alors on reduit la bande passante selon
# la concurrence.
# Ainsi, aucune priorité n'est bloqué, mais simplement plus ou moins ajusté.
# ---------------------------------------------

DOWNLINK=4096           # kbit  : Exemple: 4096kbit =
DOWNLINK_P0=$[DOWNLINK/2]               #+ 2048kbit
DOWNLINK_P1=$[DOWNLINK/4]               #+ 1024kbit
DOWNLINK_P2=$[DOWNLINK/8]               #+  512kbit
DOWNLINK_P3=$[DOWNLINK/8]               #+  512kbit

UPLINK=512              # kbit
UPLINK_P0=$[UPLINK/2]
UPLINK_P1=$[UPLINK/4]
UPLINK_P2=$[UPLINK/8]
UPLINK_P3=$[UPLINK/8]

sfq_set() {
    # (je crois) modifier le gestionnaire de file d'attente...?
    local IFACE=$1

    ${TC} qdisc add dev $IFACE parent 1:10 handle 110: sfq perturb 10
    ${TC} qdisc add dev $IFACE parent 1:11 handle 111: sfq perturb 10
    ${TC} qdisc add dev $IFACE parent 1:12 handle 112: sfq perturb 10
    ${TC} qdisc add dev $IFACE parent 1:13 handle 113: sfq perturb 10
}

start() {
  echo "start..."
  ${TC} qdisc add dev $IFACE ingress
  ${TC} filter add dev $IFACE parent ffff: protocol ip u32 match ip dst 0/0 flowid 1:1 action mirred egress redirect dev $BACKFACE
  # Htb 1/2
  ${TC} qdisc add dev $IFACE root handle 1:0 htb default 13
  ${TC} class add dev $IFACE parent 1:0 classid 1:1 htb rate ${UPLINK}kbit ceil ${UPLINK}kbit
  ${TC} class add dev $IFACE parent 1:1 classid 1:10 htb rate ${UPLINK_P0}kbit ceil ${UPLINK}kbit prio 0
  ${TC} class add dev $IFACE parent 1:1 classid 1:11 htb rate ${UPLINK_P1}kbit ceil ${UPLINK}kbit prio 1
  ${TC} class add dev $IFACE parent 1:1 classid 1:12 htb rate ${UPLINK_P2}kbit ceil ${UPLINK}kbit prio 2
  ${TC} class add dev $IFACE parent 1:1 classid 1:13 htb rate ${UPLINK_P3}kbit ceil ${UPLINK}kbit prio 3

  # 2/2
  ${TC} qdisc add dev $BACKFACE root handle 1:0 htb default 13
  ${TC} class add dev $BACKFACE parent 1:0 classid 1:1 htb rate ${DOWNLINK}kbit ceil ${DOWNLINK}kbit
  ${TC} class add dev $BACKFACE parent 1:1 classid 1:10 htb rate ${DOWNLINK_P0}kbit ceil ${DOWNLINK}kbit prio 0
  ${TC} class add dev $BACKFACE parent 1:1 classid 1:11 htb rate ${DOWNLINK_P1}kbit ceil ${DOWNLINK}kbit prio 1
  ${TC} class add dev $BACKFACE parent 1:1 classid 1:12 htb rate ${DOWNLINK_P2}kbit ceil ${DOWNLINK}kbit prio 2
  ${TC} class add dev $BACKFACE parent 1:1 classid 1:13 htb rate ${DOWNLINK_P3}kbit ceil ${DOWNLINK}kbit prio 3

  sfq_set $IFACE
  sfq_set $BACKFACE

  # TOS Minimum Delay (ssh, NOT scp) in 1:10:
  ${TC} filter add dev $IFACE parent 1:0 protocol ip prio 10 u32 match ip tos 0x10 0xff  flowid 1:10
  ${TC} filter add dev $BACKFACE parent 1:0 protocol ip prio 10 u32 match ip tos 0x10 0xff  flowid 1:10

  # ICMP (ip protocol 1) in the interactive class 1:10 so we 
  # can do measurements & impress our friends:
  ${TC} filter add dev $IFACE parent 1:0 protocol ip prio 10 u32 match ip protocol 1 0xff flowid 1:10
  ${TC} filter add dev $BACKFACE parent 1:0 protocol ip prio 10 u32 match ip protocol 1 0xff flowid 1:10

  # ssh
  ${TC} filter add dev $IFACE parent 1:0 protocol ip u32 match ip dport 22 0xffff flowid 1:10
  ${TC} filter add dev $BACKFACE parent 1:0 protocol ip u32 match ip sport 22 0xffff flowid 1:10

  # www
  ${TC} filter add dev $IFACE parent 1:0 protocol ip u32 match ip dport 80 0xffff flowid 1:11
  ${TC} filter add dev $BACKFACE parent 1:0 protocol ip u32 match ip sport 80 0xffff flowid 1:11
  ${TC} filter add dev $IFACE parent 1:0 protocol ip u32 match ip dport 443 0xffff flowid 1:11
  ${TC} filter add dev $BACKFACE parent 1:0 protocol ip u32 match ip sport 443 0xffff flowid 1:11

  # Le reste va sur par defaut 1:13
}

stop() {
  echo "stop..."
  ${TC} qdisc del dev $BACKFACE root
  ${TC} qdisc del dev $IFACE root
  ${TC} qdisc del dev $IFACE ingress
}

usage() {
  echo `basename $0` '{start|stop|restart|status}'
}

case "$MODE" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        sleep 1
        start
        ;;
    status)
        echo "--- qdisc $IFACE --------------"
        ${TC} -s qdisc show dev $IFACE
        echo "--- class $IFACE --------------"
        ${TC} -s class show dev $IFACE
        echo "--- qdisc $BACKFACE --------------"
        ${TC} -s qdisc show dev $BACKFACE
        echo "--- class $BACKFACE --------------"
        ${TC} -s class show dev $BACKFACE
        ;;
    *)
        usage
        ;;
esac

exit 0
# ---------------
# EOF