Skip to content

Instantly share code, notes, and snippets.

@sixtyfive
Last active October 22, 2016 09:01
Show Gist options
  • Save sixtyfive/3bc0c0bc155dfc8961ac583630f74f39 to your computer and use it in GitHub Desktop.
Save sixtyfive/3bc0c0bc155dfc8961ac583630f74f39 to your computer and use it in GitHub Desktop.
Script for handling the Cake scheduler on EdgeOS
# Save as /etc/config/cake
# The interface to be limited
IF=eth0
# Kbps values
DNSPEED=100000
UPSPEED=7500
# Percentages
DNLIMIT=60 # ERLite3 can only manage 60Mbps
UPLIMIT=95
# Custom options
UPOPTS=''
DNOPTS='besteffort'
#!/bin/bash
# Save as /etc/init.d/cake
### BEGIN INIT INFO
# Provides: cake
# Required-Start: $network
# Required-Stop: $network
# Default-Start: 2 3 4 5
# Default-Stop: 1
# Short-Description: Enable CAKE scheduler
### END INIT INFO
PATH=/sbin:/bin:/usr/sbin:/usr/bin
. /lib/lsb/init-functions
TC=/sbin/tc
IP=/sbin/ip
if [ -r /config/cake ]; then
. /config/cake
if [ -z "$DNSPEED" -o -z "$UPSPEED" \
-o -z "$DNLIMIT" -o -z "$UPLIMIT" \
-o -z "$IF" ]; then
echo "Error: /config/cake is not complete!"
exit 5
fi; if [ ! -x $TC -o ! -x $IP ]; then
echo "Error: both $TC and $IP must be present and executable!"
# exit 5
fi
else
echo "Error: /config/cake must exist!"
exit 5
fi
if [ "$#" -gt 1 -a "$2" != "stop" ]; then
UPOPTS="${@:2}"
DNOPTS="$UPOPTS"
echo "Applying custom options '$UPOPTS'."
fi
load() {
modprobe sch_cake
modprobe act_mirred
set_limits
return $?
}
unload() {
# Adapted from pgage's Cake start/stop script (UBNT Forums)
# http://community.ubnt.com/ubnt/attachments/ubnt/EdgeMAX/132960/1/cake_sh.zip
tc filter del dev $IF parent ffff: protocol all \
prio 10 u32 match u32 0 0 flowid 1:1 action mirred \
egress redirect dev ifb4${IF}
tc qdisc del dev ifb4${IF} root
ifconfig ifb4${IF} down
tc qdisc del dev $IF ingress
tc qdisc del dev $IF handle ffff: ingress
ip link delete dev ifb4${IF}
tc qdisc del dev $IF root
modprobe -r act_mirred
modprobe -r sch_cake
return $?
}
set_limits() {
DNLIMIT=$(($DNSPEED/100*$DNLIMIT))
UPLIMIT=$(($UPSPEED/100*$UPLIMIT))
echo -e "\nDownload limit: ${DNLIMIT}kbps\nUpload limit: ${UPLIMIT}kbps"
#
# Cake is always about regulation of outbound, unless...
tc qdisc add dev $IF root cake bandwidth ${UPLIMIT}kbit $UPOPTS
#
# ... an IFB interface is present which regulates inbound (IFB
# = Intermediate Block Interface. Documentation can be found
# at https://www.bufferbloat.net/projects/codel/wiki/Cake/)
ip link add name ifb4${IF} type ifb
tc qdisc add dev ifb4${IF} handle ffff: ingress
tc qdisc add dev ifb4${IF} root cake bandwidth ${DNLIMIT}kbit $DNOPTS
ifconfig ifb4${IF} up
# Why is the filter not applied to the IFB interface too, though?
tc filter add dev $IF parent ffff: protocol all \
prio 10 u32 match u32 0 0 flowid 1:1 action mirred \
egress redirect dev ifb4${IF}
return 0 # FIXME: Be more honest here!
}
usage() {
# Usage notes also taken and adapted from pgage's script
# FIXME: Rework the script so pgage's commandline arguments work properly again!
echo "Usage: $0 <start|stop|reload|status> [cake args]"
echo
echo Note: This script must be run as root or with sudo
echo
echo Turn Cake on:
echo " $0 start [cake args]"
echo
echo Turn Cake off:
echo " $0 stop"
echo
echo Change Cake options:
echo " $0 reload [cake args]"
echo
echo Show status:
echo " $0 status"
echo
echo "[cake args] are optional and provide any additional arguments to Cake"
echo " See https://www.bufferbloat.net/projects/codel/wiki/Cake/"
echo
echo Examples:
echo
echo 'ADSL modem using PPPoE with LLC-Snap connected via Ethernet:'
echo $0 reload pppoe-llcsnap via-ethernet # 360kbit 5mbit
echo
echo 'Symmetric WiFi uplink, enable host fairness (triple isolation) with NAT support:'
echo $0 start triple-isolate nat # 30mbit 30mbit
echo
echo 'UHF to Curiosity rover on Mars:'
echo $0 start interplanetary # 32kbit 32kbit
}
case $1 in
start)
log_daemon_msg "Enabling Cake scheduler" "cake"
load
log_end_msg $?
;;
stop)
log_daemon_msg "Disabling Cake scheduler" "cake"
unload
log_end_msg $?
;;
reload)
log_daemon_msg "Setting new limits for Cake scheduler" "cake"
set_limits
log_end_msg $?
;;
status)
while true; do
echo -e "\033c"
$TC -s qdisc
echo -en "\n(Hit <Ctrl-C> to exit)"
sleep 2
done
;;
*)
usage
echo
exit 2
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment