Linux – Minimal rate and default class problem for HTB

htbiptableslinuxtraffic-shaping

I have some doubts about a HTB structure I'm using.

My aim is to limit the download and upload speed of users in a local network.
Each user of the network has a personal list of domains with a down and up speed for the domain he cannot exceed.

It means user1 can have his acces on slashdot.org restricted to 8KB on download and 3KB for upload, and user2 can have on slashdot.org a restricted access of 4KB down and 1KB up.

For now I setup a iptables/tc couple that works great, but at a very little scale, using 2 or 3 virtual hosts at the same time (Unfortunately, I cannot perform real size test).

Here is my current structure (I'll only show the one on the egress of the LAN, the one for the upload being simply a "copy" of this one)

An HTB qdisc (handle 2:) attached on the interface, the default traffic class is the class FFFF.

The root class 2:1 directly under the HTB qdisc having for rate and ceiling the DOWNLINK capacity.

The default class 2:FFFF as a child of 2:1, with a rate of 1kbsp and a ceil of DOWNLINK capacity.

Then, there is other classes dynamically added when there is a new restriction for an user from a certain domain, a new tc class is added to control the download speed from its domain.

For now, here is what I did:

Create a new tc class with a unique id (taken from a database, not the point here), as a parent the class 2:1, rate value is 1bps, ceil value is set to the limited download speed.

Here are the tc commands:

-------------- BEGIN SCRIPT --------------
DOWNLINK=800

## Setting up the static tc qdisc and class

$tc qdisc add dev $LAN_IFACE root handle 2: htb default 0xFFFF

# Main class so the default class can borrow bandwith from the others
$tc class replace dev $LAN_IFACE parent 0x2: classid 0x2:0x1 htb rate $DOWNLINK ceil $DOWNLINKkbps

# add the default class of class id 2:a under the main class of classid 2:1
$tc class replace dev $LAN_IFACE parent 0x2:0x1 classid 0x2:0xFFFF htb rate 1kbps ceil $DOWNLINKkbps prio 0

# add to the leaf class 2:10 for default traffic a sfq qdisc
$tc qdisc add dev $LAN_IFACE parent 0x2:0xFFFF handle 0xFFFF: sfq perturb 10

## The dynamic part called each time a new restriction for a couple domain/user is added
$tc class replace dev $LAN_IFACE parent 0x2:0x1 classid 0x2:0x$idHex htb rate 1bps ceil $speedDownkbps prio 1

# Add the sfq at the leaf class 2:1$id
$tc qdisc add dev $LAN_IFACE parent 0x2:0x$idHex handle 0x$idHex: sfq perturb 10

# $id is the mark added by iptables for this couple domain/user
$tc filter replace dev $LAN_IFACE parent 0x2:0 protocol ip prio 3 handle 0x$id fw flowid 0x2:0x$idHex
-------------- END SCRIPT --------------

All the normal traffic (without speed restriction) should go to the default class, and that the restricted one should be sent to its corresponding tc class.

The point I doubt seriously about is the use of the minimal 1bps speed rate for the default class and the restricted class. I cannot control the number of restricted classes that will be created, and I don't want to total rate of the restricted class the be over the one of the root class.

Another point, I added the default the prio 0, and the restricted class the prio 1, so in case the default class should borrow (almost always according to its very slow rate), this class will be served before the other restricted domain. But won't those domains will starve if I keep the ceil of the default class as the one of the root class ?

How can I succeed to allow the users to keep a decent interactivity and bandwidth for a non restricted usage, while limiting the speed for several couple domains/user ?

I am also wondering if the default class is here useful, since if I don;t specify a default class for the htb qdisc, the packets not matching the filters will be dequeued at the hardware speed. (but here again with making the restricted class starve ?)

I'm really new to tc and network QoS, so any advice, critics (constructive ones 😉 ) will be welcome.

Vincent.

Best Answer

Since you didn't include the classifiers it's hard to deduct what traffic you exactly mean in each class. For instance, outgoing http or ssh traffic is very important for interactivity, incoming http not so much.

I would guarantee certain bandwidth for each service by saying: I have x kbps for incoming httpd traffic, and it gets divided equally among the users. If you have 10 or 100 users, it's fair." If you have high priority users or low priority users in each of these services you need to have additional classes and classifiers for them.

(Also I hope you know you can only shape outgoing traffic from an interface, NOT the incoming. That means if you want to limit the uplink, you have to work either with the outgoing interface to the internet or use the Intermediate Queuing Device. The lartc.org Guide is a very good resource.)