-
-
Save guangmuzhu/cfbf176fe9d1ec933521f883d26d2f6d to your computer and use it in GitHub Desktop.
Traffic control script for incoming and outgoing packages using TC (on a specific ip address)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
VERSION="1.0.7" | |
# Interface connect to out lan | |
INTERFACE="eth0" | |
# Interface virtual for incomming traffic | |
VIRTUAL="ifb0" | |
# Try to skip reset | |
CHANGE=0 | |
# set the direction (1 = outgoing only, 2 = incoming only 3 = both) | |
DIRECTION=3 | |
# Speed | |
SPEED_DOWNLOAD="10mbit" | |
SPEED_UPLOAD="10mbit" | |
# Queue length (in packet) | |
LIMIT=100 | |
# Loss in percent (0 = no loss) | |
LOSS="0%" | |
# Delay in milliseconds (0 = no delay) | |
DELAY="40ms" | |
function show_usage { | |
echo | |
echo "Bandwidth Control using TC" | |
echo "Version: $VERSION | Author: ole1986, cambda" | |
echo | |
echo "Usage: $1 [-h|--help] [-I|--if=] [-c|--change] [-r|--remove] [-i|--incoming] [-o|--outgoing] [-L|--limit=] [-d|--delay=] [-l|--loss=] [-U|--uspeed=] [-D|--dspeed=] <IP>" | |
echo | |
echo "Arguments:" | |
echo " -h|--help : show usage" | |
echo " -I|--if=<if> : the interface to connect" | |
echo " -c|--change : not removes all traffic control being set automatically" | |
echo " -r|--remove : removes all traffic control being set" | |
echo " -i|--incoming : limit the bandwidth only for incoming packetes" | |
echo " -o|--outgoing : limit the bandwidth only for outgoing packetes" | |
echo " -L|--limit=100 : define the queue length (default: 100)" | |
echo " -d|--delay=40ms : define the latency (default: 40ms)" | |
echo " -l|--loss=0% : define the loss (default: 0%)" | |
echo " -U|--uspeed=<speed>: define the upload speed (default: 10mbit)" | |
echo " -D|--dspeed=<speed>: define the download speed (default: 10mbit)" | |
echo " <IP> : the ip address to limit the traffic for" | |
echo | |
echo "Changelog:" | |
echo "v1.0.7 - add help as argument" | |
echo "v1.0.6 - add change mode as argument" | |
echo "v1.0.5 - add queue length as argument" | |
echo "v1.0.4 - add loss as argument adn modify default values" | |
echo "v1.0.3 - add interface as argument" | |
echo "v1.0.2 - make use of the 'tc change' instead of removing" | |
echo "v1.0.1 - add uspeed and dspeed to setup limit as argument" | |
echo "v1.0.0 - initial version" | |
} | |
function remove_tc { | |
echo "Unlimit traffic on $INTERFACE (in/out)" | |
# clean up outgoing | |
[[ $(tc qdisc | grep '^qdisc htb 1:') ]] && tc qdisc del root dev $INTERFACE | |
# clean up incoming | |
if [[ $(tc qdisc | grep '^qdisc htb 2:') ]]; then | |
tc qdisc del dev $INTERFACE handle ffff: ingress | |
tc qdisc del root dev $VIRTUAL | |
# Unload the virtual network module | |
ip link set dev $VIRTUAL down | |
modprobe -r ifb | |
fi | |
} | |
function tc_outgoing { | |
echo "Limit outgoing traffic" | |
# update outgoing speed (if already exists) | |
echo "- upload speed $SPEED_UPLOAD" | |
if [[ $CHANGE -ne 0 || $(tc class show dev $INTERFACE | grep '^class htb 1:1') ]]; then | |
TCC="tc class change" | |
else | |
# Add classes per ip | |
tc qdisc add dev $INTERFACE root handle 1: htb direct_qlen 2 | |
TCC="tc class add" | |
fi | |
$TCC dev $INTERFACE parent 1: classid 1:1 htb rate $SPEED_UPLOAD quantum 1600 | |
# update netem | |
echo "- queue length $LIMIT" | |
echo "- latency $DELAY" | |
echo "- loss $LOSS" | |
if [[ $CHANGE -ne 0 || $(tc qdisc | grep '^qdisc netem 10:') ]]; then | |
TCN="tc qdisc change" | |
else | |
TCN="tc qdisc add" | |
fi | |
$TCN dev $INTERFACE parent 1:1 handle 10: netem limit $LIMIT delay $DELAY loss $LOSS | |
# Match ip and put it into the respective class | |
echo "- filter on IP $ADDRESS" | |
if [[ $CHANGE -ne 0 || $(tc filter show dev $INTERFACE | grep '^filter parent 1: protocol ip pref 1') ]]; then | |
TCF="tc filter change" | |
else | |
TCF="tc filter add" | |
fi | |
$TCF dev $INTERFACE protocol ip parent 1: handle 800::801 prio 1 u32 match ip dst $ADDRESS flowid 1:1 | |
} | |
function tc_incoming { | |
# setup virtual interface to redirect incoming traffic | |
if [ $CHANGE -eq 0 ]; then | |
modprobe ifb numifbs=1 | |
ip link set dev $VIRTUAL up | |
fi | |
echo "Limit incoming traffic" | |
# update incoming speed (if already exists) | |
echo "- download speed $SPEED_DOWNLOAD" | |
if [[ $CHANGE -ne 0 || $(tc class show dev $VIRTUAL | grep '^class htb 2:1') ]]; then | |
TCC="tc class change" | |
else | |
tc qdisc add dev $INTERFACE handle ffff: ingress | |
# Redirecto ingress eth0 to egress ifb0 | |
tc filter add dev $INTERFACE parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev $VIRTUAL | |
# Add classes per ip | |
tc qdisc add dev $VIRTUAL root handle 2: htb direct_qlen 2 | |
TCC="tc class add" | |
fi | |
$TCC dev $VIRTUAL parent 2: classid 2:1 htb rate $SPEED_DOWNLOAD quantum 1600 | |
# update netem | |
echo "- queue length $LIMIT" | |
echo "- latency $DELAY" | |
echo "- loss $LOSS" | |
if [[ $CHANGE -ne 0 || $(tc qdisc | grep '^qdisc netem 20:') ]]; then | |
TCN="tc qdisc change" | |
else | |
TCN="tc qdisc add" | |
fi | |
$TCN dev $VIRTUAL parent 2:1 handle 20: netem limit $LIMIT delay $DELAY loss $LOSS | |
# Match ip and put it into the respective class | |
echo "- filter on IP $ADDRESS" | |
if [[ $CHANGE -ne 0 || $(tc filter show dev $VIRTUAL | grep '^filter parent 1: protocol ip pref 1') ]]; then | |
TCF="tc filter change" | |
else | |
TCF="tc filter add" | |
fi | |
$TCF dev $VIRTUAL protocol ip parent 2: handle 800::802 prio 1 u32 match ip src $ADDRESS flowid 2:1 | |
} | |
if [ $# -eq 0 ]; then | |
show_usage $0 | |
exit 0 | |
fi | |
for i in "$@" | |
do | |
case $i in | |
-h|--help) | |
show_usage $0 | |
exit 0 | |
;; | |
-c|--change) | |
CHANGE=1 | |
shift | |
;; | |
-r|--remove) | |
DIRECTION=0 | |
shift | |
;; | |
-o|--outgoing) | |
DIRECTION=1 | |
shift | |
;; | |
-i|--incoming) | |
DIRECTION=2 | |
shift | |
;; | |
-I=*|--if=*) | |
INTERFACE=${i#*=} | |
shift | |
;; | |
-L=*|--limit=*) | |
LIMIT=${i#*=} | |
shift | |
;; | |
-l=*|--loss=*) | |
LOSS=${i#*=} | |
shift | |
;; | |
-d=*|--delay=*) | |
DELAY=${i#*=} | |
shift | |
;; | |
-U=*|--uspeed=*) | |
SPEED_UPLOAD="${i#*=}" | |
shift | |
;; | |
-D=*|--dspeed=*) | |
SPEED_DOWNLOAD="${i#*=}" | |
shift | |
;; | |
esac | |
done | |
[ $CHANGE -eq 0 ] && remove_tc | |
[ -n $1 ] && ADDRESS=$1 | |
[ $DIRECTION -eq 0 ] && exit 0 | |
if [ -z $ADDRESS ]; then | |
echo | |
echo "No IP address defined" | |
exit 0 | |
fi | |
[ $DIRECTION -eq 1 ] && tc_outgoing | |
[ $DIRECTION -eq 2 ] && tc_incoming | |
if [ $DIRECTION -eq 3 ]; then | |
tc_outgoing | |
tc_incoming | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment