I have a router/gateway under Linux, I want to add some QoS to reserve bandwidth for a specific flow. This can be done with iptables/netfilter and tc, but all examples start from the fact that you know in advance the total bandwidth available.

Problem is, my WAN is a moving 3G connection, with variable performances. On day 1, I can have 5 Mbps, and rainy day 2 is down to 2 Mbps. How can I guarantee that my flow 1 will always have 100Kbps available with low latency?

I thought of a complex solution, with a daily or hourly script to check bandwidth and dynamically create and apply QoS scripts, but it's not a good solution to me.

  • It sounds like you need a script/program that can determine your bandwidth, that is exempt from your traffic shaping and that can adjust your tc settings automatically, perhaps via cron or udev. – Aaron Mar 10 '16 at 19:23

You should be able to reach your goal with hfsc scheduler. You will have the ability to reserve a part of the bandwidth and give low latency guaranty with "real time", the other classes will proportionnally fill the rest of the bandwidth with "linkshare".

It is important here to use real time and not linkshare, because real time, in order to be sure to be able to send a packet at the very last miliseconds, is able to stop the other class to send a packet.

In order to accomplish what you want, you need to set a way to high upperlimit on the root class (10MB maybe), but no ul on leaf ones. Because of the way hfsc linkshare is sharing the bandwidth between all the "ls" class, they will share the available bandwidth, over the m2 value if there is more.

For example, you could use this kind of setup :

# dns, ntp, teamspeak
iptables -t mangle -A POSTROUTING -o eth0 -p udp -m multiport --dports 53,123,9987 -j CLASSIFY --set-class 1:100
# Default tcp
iptables -t mangle -A POSTROUTING -o eth0 -p tcp -j CLASSIFY --set-class 1:200
# Default udp
iptables -t mangle -A POSTROUTING -o eth0 -p udp -j CLASSIFY --set-class 1:300

# ROOT QDISC - default goes on class 100 because it's probably arp gratuitous or whois since all ip traffic is already classified
tc qdisc add dev eth0 root handle 1:0 hfsc default 100

# ROOT CLASS - Interface eth0, noeud parent de la branche : 1:0, id de la branche : 1:10
tc class add dev eth0 parent 1:0 classid 1:10 hfsc ls m2 10000kbit ul m2 10000kbit

tc class add dev eth0 parent 1:10 classid 1:100 hfsc sc m1 400kbit d 10ms m2 100kbit
tc qdisc add dev eth0 parent 1:100 handle 110: fq_codel quantum 300 noecn # fq_codel requires to change the quantum for low bandwitdth

# CLASS 200 - some tcp
tc class add dev eth0 parent 1:10 classid 1:200 hfsc ls m1 80kbit d 10ms m2 80kbit
# QDISC - some tcp
tc qdisc add dev eth0 parent 1:200 handle 210: fq_codel

# CLASS 300 - some udp
tc class add dev eth0 parent 1:10 classid 1:300 hfsc ls m1 20kbit d 10ms m2 20kbit # ratio tcp / udp will then be 4:1
# QDISC - some udp
tc qdisc add dev eth0 parent 1:300 handle 310: fq_codel quantum 300 noecn

Values could need to be changed according to your need, especially in class 100, although I tried to write these numbers to fit to your 3G.

You should read more on man tc-hfsc, this post, and this article to learn more about hfsc and how it works.

| improve this answer | |
  • Very complete answer, looks promising, i'll try it thanks – Benoit PHILIPPON Mar 16 '16 at 14:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.