Skip to content

Instantly share code, notes, and snippets.

@nebgnahz
Last active June 21, 2024 19:45
Show Gist options
  • Save nebgnahz/6e1cfb2354397581fb301ffcb53f4fa6 to your computer and use it in GitHub Desktop.
Save nebgnahz/6e1cfb2354397581fb301ffcb53f4fa6 to your computer and use it in GitHub Desktop.
Traffic Shape using `tc` for Linux
#!/bin/bash
set -e
function usage() {
cat << EOF
USAGE:
./shaper start <interface> <bw as XXX kbit>
./shaper clear <interface>
./shaper show <interface>
EOF
}
## Input arguments are `interface`, `bw`
function shaper_start() {
## Packet -> Filter -> Class -> Qdisc -> Network
## We create in the reverse order
sudo tc qdisc add dev $1 root handle 1: htb
sudo tc class add dev $1 parent 1: classid 1:10 htb \
rate $2
sudo tc filter add dev $1 protocol ip parent 1: prio 1 u32 \
match ip dport 8888 0xffff flowid 1:10
sudo tc filter add dev $1 protocol ip parent 1: prio 1 u32 \
match ip dport 9999 0xffff flowid 1:10
sudo tc filter add dev $1 protocol ip parent 1: prio 1 u32 \
match ip dport 5201 0xffff flowid 1:10
}
function shaper_clear() {
sudo tc qdisc del dev $1 root
}
function shaper_show() {
tc qdisc show dev $1
tc class show dev $1
tc filter show dev $1
}
function main() {
case $1 in
show)
shaper_show $2
;;
start)
shaper_start $2 $3 $4
;;
clear)
shaper_clear $2
;;
*)
usage
esac
}
main $@

wondershaper is a great script except it seems too complicated to understand and use (i.e. modify). This script uses tc with HTB (Hierarchy Token Bucket) where configurations are largely simplified. Checkout the usages by running the program without any argument.

For more information, checkout the guide 9.5.5. Hierarchical Token Bucket from the Linux Advanced Routing & Traffic Control HOWTO

Note: the sample script shapes ip traffic with destination port 8888, 9999 and 5201. You should change it to the service port for your own application. In the example section, we are using speedtest which runs over port 80. Do that or you won't see changes.

Example

wget -O shaper <url>
chmod +x shaper
./shaper start eth0 100kbit
./shaper show eth0
./shaper clear eth0

You can use speedtest-cli

wget -O speedtest https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py
chmod +x speedtest
speedtest

tc convention

Just to prevent confusion, tc uses the following rules for bandwith specification:

mbps = 1024 kbps = 1024 * 1024 bps => byte/s
mbit = 1024 kbit => kilo bit/s.
mb = 1024 kb = 1024 * 1024 b => byte
mbit = 1024 kbit => kilo bit.
Internally, the number is stored in bps and b.

But when tc prints the rate, it uses following :

1Mbit = 1024 Kbit = 1024 * 1024 bps => byte/s
@manickamk
Copy link

Hi

Is possible to allocate bandwidth port wise TCP /UDP
TCP -Port
80= 1Mbit,
21= 2 Mbit
8080= 5Mbit

UDP-PORT

5001=1Mbit
5002=2Mbit
5003=3Mbit
5004=4Mbit
5005=5Mbit

if it is possible could you please guide me thanks
Manickam

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment