mirror of
https://gitlab.alpinelinux.org/alpine/aports.git
synced 2025-04-20 01:26:38 +02:00
464 lines
13 KiB
Bash
464 lines
13 KiB
Bash
#!/sbin/openrc-run
|
|
#
|
|
###########################################################################################################
|
|
# Traffic Control startup script
|
|
#
|
|
# Copyright (c) 2009 iilluzion
|
|
#
|
|
# Distributed under GPL-2
|
|
###########################################################################################################
|
|
|
|
PROGRAM=$SVCNAME
|
|
CONFIG=/etc/conf.d/$SVCNAME
|
|
DEBUG=0 #1
|
|
|
|
extra_started_commands="describe"
|
|
extra_stopped_commands="compile"
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
depend()
|
|
{
|
|
need net
|
|
after firewall
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
checkconfig() {
|
|
if [ ! -e $CONFIG ] ; then
|
|
eerror "You need to create $CONFIG first."
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
bits()
|
|
{
|
|
RATE=0
|
|
R_RATE=$1
|
|
|
|
R_NUMBER=`echo "$R_RATE" | sed -e "s/[^0-9]//g"`
|
|
R_UNIT=`echo "$R_RATE" | sed -e "s/[0-9]//g"`
|
|
|
|
if [ "$R_UNIT" == "" ]; then
|
|
R_UNIT="kbit"
|
|
fi
|
|
|
|
if [ "$R_UNIT" == "kbps" ]; then R_RATE=$(($R_NUMBER * 1024 * 8))
|
|
elif [ "$R_UNIT" == "mbps" ]; then R_RATE=$(($R_NUMBER * 1024 * 1024 * 8))
|
|
elif [ "$R_UNIT" == "mbit" ]; then R_RATE=$(($R_NUMBER * 1024 * 1024))
|
|
elif [ "$R_UNIT" == "kbit" ]; then R_RATE=$(($R_NUMBER * 1024))
|
|
elif [ "$R_UNIT" == "bps" ]; then R_RATE=$(($R_NUMBER * 8))
|
|
else
|
|
echo "Unknown unit '$R_UNIT' (mbps, mbit, kbit, kbps, bps)"
|
|
fi
|
|
|
|
echo "$R_RATE"
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
expand_leaf_qdisc()
|
|
{
|
|
case "$1" in
|
|
pfifo) echo "pfifo limit ${PFIFO_LIMIT-20480}";;
|
|
sfq) echo "sfq perturb ${SFQ_PERTURB-10}";;
|
|
red) echo "red min $RED_MIN max $RED_MAX burst $RED_BURST limit $RED_LIMIT probability $RED_PROB avpkt $RED_AVPKT";;
|
|
esac
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
configure()
|
|
{
|
|
if [ ! -z $1 ]; then
|
|
eval WAN_RATE="\$$1"_RATE
|
|
WAN_RATE=`bits $WAN_RATE`
|
|
|
|
# Calculaton of WAN classes rates
|
|
WAN_SUB_RATE=$((WAN_RATE - (RATE_SUB_PERCENT * WAN_RATE / 100)))
|
|
INTERACTIVE_RATE=$((WAN_SUB_RATE / 5))
|
|
if [ $INTERACTIVE_RATE -lt 75000 ]; then
|
|
INTERACTIVE_RATE=75000
|
|
PRIVILEGED_RATE=$(((WAN_SUB_RATE - 75000) / 2))
|
|
BESTEFFORT_RATE=$(((WAN_SUB_RATE - 75000) / 2))
|
|
else
|
|
PRIVILEGED_RATE=$((WAN_SUB_RATE / 2))
|
|
BESTEFFORT_RATE=$((WAN_SUB_RATE / 3))
|
|
fi
|
|
|
|
DEV_RATE=${DEV_RATE:-$EGRESS_RATE}
|
|
DEV_RATE=`bits $DEV_RATE`
|
|
if [ $DEV_RATE -lt $WAN_RATE ]; then
|
|
DEV_RATE=$WAN_RATE
|
|
fi
|
|
OUT_OF_WAN_RATE=$((DEV_RATE - WAN_RATE))
|
|
|
|
# Calculation of Queuing Discipline parameters
|
|
INTERACTIVE_PRIO_LATENCY=50000
|
|
INTERACTIVE_PRIO_BURST=$((INTERACTIVE_RATE / 100 / 8))
|
|
|
|
INTERACTIVE_HFSC_DMAX=50000
|
|
INTERACTIVE_HFSC_UMAX=1500
|
|
|
|
PRIVILEGED_HFSC_DMAX=100000
|
|
PRIVILEGED_HFSC_UMAX=1500
|
|
|
|
# Random Early Detect (RED) parameters calculation:
|
|
# min = maximum delay * rate (dalay ~ 200ms = 0.2sec) [b]
|
|
# max = 3 * min [b]
|
|
# avpkt = 1000 (MTU 1500)
|
|
# limit = 8 * max [b]
|
|
# burst = (min + min + max)/(3 * avpkt) [b]
|
|
# probability = 0.02
|
|
|
|
RED_DELAY=200
|
|
RED_MIN=$((RED_DELAY * BESTEFFORT_RATE / 1000 / 8)) # devided on 8 since rate given in bit/s so we get bytes
|
|
RED_MAX=$((3 * RED_MIN))
|
|
RED_AVPKT=1000
|
|
RED_PROB=0.02
|
|
RED_BURST=$(((RED_MIN + RED_MIN + RED_MAX) / (3 * RED_AVPKT)))
|
|
RED_LIMIT=$((8 * RED_MAX))
|
|
|
|
# Setting leaf Queuing Disciplines parameters
|
|
INTERACTIVE_LEAF_QDISC=pfifo
|
|
INTERACTIVE_LEAF_QDISC=`expand_leaf_qdisc $INTERACTIVE_LEAF_QDISC`
|
|
PRIVILEGED_LEAF_QDISC=pfifo
|
|
PRIVILEGED_LEAF_QDISC=`expand_leaf_qdisc $PRIVILEGED_LEAF_QDISC`
|
|
|
|
# Force using SFQ in case rate is less than 2mbit
|
|
if [ $BESTEFFORT_RATE -lt 2097152 ]; then
|
|
BESTEFFORT_LEAF_QDISC=sfq
|
|
fi
|
|
BESTEFFORT_LEAF_QDISC=`expand_leaf_qdisc $BESTEFFORT_LEAF_QDISC`
|
|
|
|
LAN_LEAF_QDISC=sfq
|
|
LAN_LEAF_QDISC=`expand_leaf_qdisc $LAN_LEAF_QDISC`
|
|
fi
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
reset()
|
|
{
|
|
# Supported Queuing Disciplines
|
|
QDISCS="prio|tbf|htb|hfsc|sfq|red|pfifo"
|
|
|
|
tc qdisc show dev $DEV | grep -v "pfifo_fast" | grep -E -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
|
|
|
|
if [ "$INGRESS_ALG" = "ifb" ] && [ ! -z $IFB_DEV ]; then
|
|
$ECHO ip link set dev $IFB_DEV down
|
|
fi
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
set_leaf_qdisc()
|
|
{
|
|
PARENT_CLASSID=$1
|
|
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 [ $OUT_OF_WAN_RATE -gt 0 ]; 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 [ $OUT_OF_WAN_RATE -gt 0 ]; then
|
|
CLASS_TYPES=$CLASS_TYPES" LAN"
|
|
fi
|
|
|
|
PRIVILEGED_FILTER_FLOWID=50
|
|
BESTEFFORT_FILTER_FLOWID=60
|
|
LAN_FILTER_FLOWID=70
|
|
|
|
{
|
|
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
|
|
if [ ! -z "$FILTER" ]; then
|
|
eval FILTER_FLOWID="\$$CLASS_TYPE"_FILTER_FLOWID
|
|
$ECHO tc filter add dev $DEV parent $PARENT_CLASSID:0 $FILTER flowid $PARENT_CLASSID:$FILTER_FLOWID
|
|
fi
|
|
done
|
|
done
|
|
} | sort -g
|
|
|
|
$ECHO
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
set_htb()
|
|
{
|
|
$ECHO tc qdisc add dev $DEV root handle 1 htb default 60 r2q ${HTB_R2Q-100}
|
|
$ECHO tc class add dev $DEV parent 1: classid 1:2 htb rate $DEV_RATE burst $(($DEV_RATE*5/4))
|
|
$ECHO tc class add dev $DEV parent 1:2 classid 1:30 htb rate $WAN_SUB_RATE burst $(($WAN_SUB_RATE*5/4))
|
|
$ECHO tc class add dev $DEV parent 1:30 classid 1:40 htb rate $INTERACTIVE_RATE ceil $WAN_SUB_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 burst $(($WAN_SUB_RATE*5/4))
|
|
$ECHO tc class add dev $DEV parent 1:30 classid 1:60 htb rate $BESTEFFORT_RATE ceil $WAN_SUB_RATE prio 6 burst $(($WAN_SUB_RATE*5/4))
|
|
|
|
if [ $OUT_OF_WAN_RATE -gt 0 ]; 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
|
|
|
|
$ECHO
|
|
|
|
set_filters
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
set_hfsc()
|
|
{
|
|
$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 $DEV_RATE ul rate $DEV_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 $WAN_SUB_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 [ $OUT_OF_WAN_RATE -gt 0 ]; 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
|
|
|
|
$ECHO
|
|
|
|
set_filters
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
set_prio()
|
|
{
|
|
PARENT_CLASSID=10
|
|
$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 $WAN_SUB_RATE 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 [ $OUT_OF_WAN_RATE -gt 0 ]; 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 $PARENT_CLASSID
|
|
|
|
$ECHO
|
|
|
|
set_filters $PARENT_CLASSID
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
set_ifb()
|
|
{
|
|
$ECHO ip link set dev $IFB_DEV up
|
|
$ECHO tc qdisc add dev $DEV ingress handle ffff:
|
|
$ECHO tc filter add dev $DEV parent ffff: protocol ip prio 10 u32 match u32 0 0 action mirred egress redirect dev $IFB_DEV > /dev/null 2>&1
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
set_police()
|
|
{
|
|
|
|
# Calculation of policing bursts
|
|
# burst = rate / 17 (taken basing on experemental results)
|
|
|
|
POLICE_BURST_SCALE=17
|
|
WAN_POLICE_BURST=$((WAN_RATE / POLICE_BURST_SCALE))
|
|
|
|
WAN_POLICE_FLOWID=1
|
|
|
|
$ECHO tc qdisc add dev $DEV handle ffff: ingress
|
|
$ECHO tc filter add dev $DEV parent ffff: protocol ip prio 999 u32 match ip src 0.0.0.0/0 police rate $WAN_RATE burst $WAN_POLICE_BURST drop flowid :$WAN_POLICE_FLOWID
|
|
|
|
$ECHO
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
set_cpolice()
|
|
{
|
|
|
|
# Calculation of policing bursts
|
|
# burst = rate / 17 (taken basing on experemental results)
|
|
|
|
POLICE_BURST_SCALE=17
|
|
INTERACTIVE_POLICE_BURST=$((INTERACTIVE_RATE / POLICE_BURST_SCALE))
|
|
PRIVILEGED_POLICE_BURST=$((PRIVILEGED_RATE / POLICE_BURST_SCALE))
|
|
BESTEFFORT_POLICE_BURST=$((BESTEFFORT_RATE / POLICE_BURST_SCALE))
|
|
|
|
CLASS_TYPES="INTERACTIVE PRIVILEGED"
|
|
INTERACTIVE_POLICE_FLOWID=1
|
|
PRIVILEGED_POLICE_FLOWID=2
|
|
|
|
$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
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
get_stats()
|
|
{
|
|
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
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
compile()
|
|
{
|
|
DEBUG=1
|
|
|
|
start
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
start()
|
|
{
|
|
checkconfig || return 1
|
|
|
|
if [ $DEBUG -gt 0 ]; then
|
|
ECHO="echo"
|
|
else
|
|
ebegin "Starting QoS at $DEV"
|
|
fi
|
|
|
|
reset
|
|
|
|
for LINK_DIRECTION in EGRESS INGRESS; do
|
|
configure $LINK_DIRECTION
|
|
eval ALG_CMD="\$$LINK_DIRECTION"_ALG
|
|
if [ ! "$ALG_CMD" = "none" ]; then
|
|
set_$ALG_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 at $DEV"
|
|
fi
|
|
|
|
reset
|
|
|
|
if [ $DEBUG -eq 0 ]; then
|
|
eend $?
|
|
fi
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
restart()
|
|
{
|
|
stop
|
|
start
|
|
}
|
|
|
|
###########################################################################################################
|
|
#
|
|
#
|
|
describe()
|
|
{
|
|
checkconfig || return 1
|
|
|
|
get_stats
|
|
}
|