Limiting bandwidth on internal interface on Linux gateway

I am responsible for a Linux-based (it runs Debian) branch office router that takes a single high-speed Internet connection (eth2) and turns it into about 20 internal networks, each with a seperate subnet (192.168.1.0/24 to 192.168.20.0/24) and a seperate VLAN (eth0.101 to eth0.120). I am trying to restrict bandwidth on one of the internal subnets that is consistently chewing up more bandwidth than it should. What is the best way to do this?

My first try at this was with wondershaper, which I heard about on SuperUser here. Unfortunately, this is useful for exactly the opposite situation that I have... it's useful on the client side, not on the Internet side.

My second attempt was using the script found at http://www.topwebhosts.org/tools/traffic-control.php, which I modified so the active part is:

tc qdisc add dev eth0.113 root handle 13: htb default 100
tc class add dev eth0.113 parent 13: classid 13:1 htb rate 3mbps
tc class add dev eth0.113 parent 13: classid 13:2 htb rate 3mbps
tc filter add dev eth0.113 protocol ip parent 13:0 prio 1 u32 match ip dst 192.168.13.0/24 flowid 13:1
tc filter add dev eth0.113 protocol ip parent 13:0 prio 1 u32 match ip src 192.168.13.0/24 flowid 13:2

What I want this to do is restrict the bandwidth on VLAN 113 (subnet 192.168.13.0/24) to 3mbit up and 3mbit down. Unfortunately, it seems to have no effect at all! I'm very inexperienced with the tc command, so any help getting this working would be appreciated.


Quote from the developers to someone trying to do the same thing: Doing traffic control on vlan's may not work as expected because the vlan pseudo-device does not have any transmit queue.

Since you've already written your rules to rate limit by subnet, it's a matter of getting Linux to rate control it.

I would suggest working around it by putting the VLAN in a bridge (though for consistency's sake you might want to create a bridge for every VLAN):

brctl addbr br113
btctl addif br113 eth0.113

You can then apply your tc rules to br113 instead of eth0.113.

(Configuring /etc/network/interfaces is left as an exercise for the reader, if this works...)

Or it might be simpler to apply the traffic control rules to your WAN interface eth2; the end result should be about the same.


You need a ifb interface for mirror the inress flow of eth0 to egress side of ifb0.

Try this:

# Interface virtual for incomming traffic
tin1="ifb0"
# Interface connect to out lan
int1="eth0"
# Clean interface
tc qdisc del dev $int1 handle ffff: ingress
tc qdisc del root dev $tin1
tc qdisc add dev $int1 handle ffff: ingress
# Redirecto ingress eth0 to egress ifb0
tc filter add dev $int1 parent ffff: protocol ip u32 match u32 0 0 action mirred egress redirect dev $tin1
# Add classes per ip
tc qdisc add dev $tin1 root handle 2: htb default 20
tc class add dev $tin1 parent 2: classid 2:1 htb rate 20480kbit
tc class add dev $tin1 parent 2:1 classid 2:5 htb rate 80kbit ceil 20480kbit
tc filter add dev $tin1 protocol ip parent 2: prio 1 u32 match ip src 192.168.1.5/32 flowid 2:15

but before, load this module in the kernel for do it:

modprobe ifb numifbs=1
ip link set dev $tin1 up