#!/sbin/runscript # ########################################################################################################### # Traffic Control startup script # # Copyright (c) 2009 iilluzion # # Distributed under GPL-2 ########################################################################################################### PROGRAM=qos CONFIG=/etc/conf.d/qos DEBUG=0 #1 opts="compile" depend() { need net } checkconfig() { if [ ! -e $CONFIG ] ; then eerror "You need to create $CONFIG first." return 1 fi } usage() { echo "usage: $PROGRAM [status|compile|start|stop|restart]" echo " status: View statistics" echo " compile: Generate traffic control commands" echo " start: Start traffic control" echo " stop: Stop traffic control" echo " restart: Restart traffic control" } configure() { source $CONFIG $1 } reset() { for DEV in $DEVICES; do tc qdisc show dev $DEV | grep -v "pfifo_fast" | egrep -q "$QDISCS" && $ECHO tc qdisc del dev $DEV root tc qdisc show dev $DEV | grep -v "pfifo_fast" | grep -q ingress && $ECHO tc qdisc del dev $DEV ingress done } set_leaf_qdisc() { DEV=$1 PARENT_CLASSID=$2 PARENT_CLASSID=${PARENT_CLASSID:-1} if [ ! "$QDISC_CMD" = "prio" ]; then $ECHO tc qdisc add dev $DEV parent $PARENT_CLASSID:40 handle 40 $INTERACTIVE_LEAF_QDISC fi $ECHO tc qdisc add dev $DEV parent $PARENT_CLASSID:50 handle 50 $PRIVILEGED_LEAF_QDISC $ECHO tc qdisc add dev $DEV parent $PARENT_CLASSID:60 handle 60 $BESTEFFORT_LEAF_QDISC if [ $DIRECTION = "DOWN" ]; then $ECHO tc qdisc add dev $DEV parent $PARENT_CLASSID:70 handle 70 $LAN_LEAF_QDISC fi $ECHO } set_filters() { CLASS_TYPES="INTERACTIVE PRIVILEGED BESTEFFORT" if [ $DIRECTION = "DOWN" ]; then CLASS_TYPES=$CLASS_TYPES" LAN" fi PRIVILEGED_FILTER_FLOWID=50 BESTEFFORT_FILTER_FLOWID=60 LAN_FILTER_FLOWID=70 for DEV in $DEVICES; do for CLASS_TYPE in $CLASS_TYPES; do if [ "$QDISC_CMD" = "prio" -a "$CLASS_TYPE" = "INTERACTIVE" ]; then PARENT_CLASSID=1 INTERACTIVE_FILTER_FLOWID=1 else PARENT_CLASSID=$1 PARENT_CLASSID=${PARENT_CLASSID:-1} INTERACTIVE_FILTER_FLOWID=40 fi for FILTER_NUM in `seq 1 100`; do eval FILTER="\$$CLASS_TYPE"_FILTER_$FILTER_NUM [ -z "$FILTER" ] && break eval FILTER_FLOWID="\$$CLASS_TYPE"_FILTER_FLOWID $ECHO tc filter add dev $DEV parent $PARENT_CLASSID:0 $FILTER flowid $PARENT_CLASSID:$FILTER_FLOWID done done $ECHO done } set_htb() { for DEV in $DEVICES; do $ECHO tc qdisc add dev $DEV root handle 1 htb default 60 $ECHO tc class add dev $DEV parent 1: classid 1:2 htb rate $LAN_RATE $ECHO tc class add dev $DEV parent 1:2 classid 1:30 htb rate $WAN_SUB_RATE $ECHO tc class add dev $DEV parent 1:30 classid 1:40 htb rate $INTERACTIVE_RATE prio 1 $ECHO tc class add dev $DEV parent 1:30 classid 1:50 htb rate $PRIVILEGED_RATE ceil $WAN_SUB_RATE prio 3 $ECHO tc class add dev $DEV parent 1:30 classid 1:60 htb rate $BESTEFFORT_RATE ceil $WAN_SUB_RATE prio 6 if [ $DIRECTION = "DOWN" ]; then $ECHO tc class add dev $DEV parent 1:2 classid 1:70 htb rate $OUT_OF_WAN_RATE prio 7 fi set_leaf_qdisc $DEV $ECHO done set_filters } set_hfsc() { for DEV in $DEVICES; do $ECHO tc qdisc add dev $DEV root handle 1 hfsc default 60 $ECHO tc class add dev $DEV parent 1: classid 1:2 hfsc sc rate $LAN_RATE ul rate $LAN_RATE $ECHO tc class add dev $DEV parent 1:2 classid 1:30 hfsc sc rate $WAN_SUB_RATE ul rate $WAN_SUB_RATE $ECHO tc class add dev $DEV parent 1:30 classid 1:40 hfsc sc umax $INTERACTIVE_HFSC_UMAX dmax $INTERACTIVE_HFSC_DMAX rate $INTERACTIVE_RATE ul rate $INTERACTIVE_RATE $ECHO tc class add dev $DEV parent 1:30 classid 1:50 hfsc sc umax $PRIVILEGED_HFSC_UMAX dmax $PRIVILEGED_HFSC_DMAX rate $PRIVILEGED_RATE ul rate $WAN_SUB_RATE $ECHO tc class add dev $DEV parent 1:30 classid 1:60 hfsc sc rate $BESTEFFORT_RATE ul rate $WAN_SUB_RATE if [ $DIRECTION = "DOWN" ]; then $ECHO tc class add dev $DEV parent 1:2 classid 1:70 hfsc sc rate $OUT_OF_WAN_RATE ul rate $OUT_OF_WAN_RATE fi set_leaf_qdisc $DEV $ECHO done set_filters } set_prio() { PARENT_CLASSID=10 for DEV in $DEVICES; do $ECHO tc qdisc add dev $DEV root handle 1 prio bands 2 priomap 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 # by default unclassified traffic goes to flowid 1:2 $ECHO tc qdisc add dev $DEV parent 1:1 handle 40: tbf rate $INTERACTIVE_RATE burst $INTERACTIVE_PRIO_BURST latency $INTERACTIVE_PRIO_LATENCY $ECHO tc qdisc add dev $DEV parent 1:2 handle $PARENT_CLASSID: htb default 60 $ECHO tc class add dev $DEV parent $PARENT_CLASSID: classid $PARENT_CLASSID:30 htb rate $WAN_SUB_RATE $ECHO tc class add dev $DEV parent $PARENT_CLASSID:30 classid $PARENT_CLASSID:50 htb rate $PRIVILEGED_RATE ceil $WAN_SUB_RATE prio 3 $ECHO tc class add dev $DEV parent $PARENT_CLASSID:30 classid $PARENT_CLASSID:60 htb rate $BESTEFFORT_RATE ceil $WAN_SUB_RATE prio 6 if [ $DIRECTION = "DOWN" ]; then $ECHO tc class add dev $DEV parent 10:1 classid $PARENT_CLASSID:70 htb rate $OUT_OF_WAN_RATE prio 7 fi set_leaf_qdisc $DEV $PARENT_CLASSID $ECHO done set_filters $PARENT_CLASSID } set_police() { CLASS_TYPES="INTERACTIVE PRIVILEGED" INTERACTIVE_POLICE_FLOWID=1 PRIVILEGED_POLICE_FLOWID=2 for DEV in $DEVICES; do $ECHO tc qdisc add dev $DEV handle ffff: ingress for CLASS_TYPE in $CLASS_TYPES; do for FILTER_NUM in `seq 1 100`; do eval FILTER="\$$CLASS_TYPE"_FILTER_$FILTER_NUM [ -z "$FILTER" ] && break eval FILTER_FLOWID="\$$CLASS_TYPE"_POLICE_FLOWID eval FILTER_RATE="\$$CLASS_TYPE"_RATE eval FILTER_BURST="\$$CLASS_TYPE"_POLICE_BURST $ECHO tc filter add dev $DEV parent ffff: $FILTER police rate $FILTER_RATE burst $FILTER_BURST continue flowid $FILTER_FLOWID: done done $ECHO tc filter add dev $DEV parent ffff: protocol ip prio 999 u32 match ip src 0.0.0.0/0 police rate $BESTEFFORT_RATE burst $BESTEFFORT_POLICE_BURST drop flowid :3 $ECHO done } get_stats() { for DEV in $WAN_DEVICES $LAN_DEVICES; do echo $DEV Statistics echo echo " Classes:" echo "--------------------------" $ECHO tc -s class show dev $DEV echo echo " Leaf Queuing Disciplines:" echo "--------------------------" $ECHO tc -s qdisc show dev $DEV echo echo " EGRESS Filters:" echo "--------------------------" $ECHO tc -s filter show dev $DEV $ECHO tc -s filter show dev $DEV parent 10: # if PRIO qdisc is applied echo echo " INGRESS Policing Filters:" echo "--------------------------" $ECHO tc -s filter show dev $DEV parent ffff: echo echo done } compile() { DEBUG=1 start } start() { checkconfig || return 1 if [ $DEBUG -gt 0 ]; then ECHO="echo" else ebegin "Starting QoS" fi for LINK_DIRECTION in UP DOWN; do configure $LINK_DIRECTION reset eval QDISC_CMD="\$$LINK_DIRECTION"LINK_QDISC if [ ! "$QDISC_CMD" = "none" ]; then set_$QDISC_CMD fi eval INGRESS_CMD="\$$LINK_DIRECTION"LINK_INGRESS if [ ! "$INGRESS_CMD" = "none" ]; then set_$INGRESS_CMD fi done if [ $DEBUG -eq 0 ]; then eend $? fi } stop() { checkconfig || return 1 if [ $DEBUG -gt 0 ]; then ECHO="echo" else ebegin "Stopping QoS" fi configure ALL reset if [ $DEBUG -eq 0 ]; then eend $? fi } restart() { stop start } status() { get_stats }