Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

Can anyone provide the tc command to limit upload bandwidth per user in Debian Lenny?

I found that to mark packets per user with iptables I can use the following command

iptables -t mangle -A OUTPUT -p tcp -m owner --uid-owner testuser -j MARK --set-mark 500

but I have no idea how to use tc

update

by running following commands, i managed to limit testuser upload bandwidth to 10Mbit

iptables -t mangle -N HTB_OUT
iptables -t mangle -I POSTROUTING -j HTB_OUT
iptables -t mangle -A HTB_OUT -j MARK --set-mark 30
iptables -t mangle -A HTB_OUT -m owner --uid-owner testuser -j MARK --set-mark 10

tc qdisc replace dev eth0 root handle 1: htb default 30
tc class replace dev eth0 parent 1: classid 1:1 htb rate 10Mbit burst 5k
tc class replace dev eth0 parent 1:1 classid 1:10 htb rate 10Mbit ceil 10Mbit
tc qdisc replace dev eth0 parent 1:10 handle 10: sfq perturb 10
tc filter add dev eth0 parent 1:0 prio 0 protocol ip handle 10 fw flowid 1:10

now the problem is, i do not want to limit testuser's FTP bandwidth but by running above commands FTP speed also limited to 10Mbit.

Regards

share|improve this question
1  
A similar question was asked here before The answer suggested to look up the LARTC. There is no specific example, but the full NAT example might be helpful. –  Dmitri Chubarov Dec 9 '12 at 15:49
    
Thanks i found a solution for limit upload bandwidth per user with TC and iptables commands. but now the problem is, it limit the user's FTP speed too :( –  Gihan Lasita Dec 9 '12 at 16:13
    
Of course it does. –  Michael Hampton Dec 9 '12 at 16:39
    
may be is there way to use two rules and set different speed for FTP port 21 only? –  Gihan Lasita Dec 9 '12 at 16:46
2  
sure, use two iptables rules, and match them on different port numbers. –  Sirex Dec 9 '12 at 23:21

2 Answers 2

Couple of obvious problems I see with your htb config.

First, you don't have a 1:30 handle, and you should, given the default 30. Perhaps you meant default 1? This would attach all traffic to classid 1:1 unless the rule attached traffic to a different class.

Second, you need to set your rate in the htb 1:1 highest level class to something reasonable and less than your line rate. For example, if your line rate is 100Mbit, rate should be maybe 90% that: 90Mbit. Some people recommend more conservative settings like 75% line rate; I play a dangerous game at 90% and it works OK for me -- reduce if you notice dropped packets or improper bandwidth allocation. The latter is indicative of upstream buffering.

Third, your rate-limited class should be configured with a rate set to the guaranteed bandwidth you're willing to allocate the class and the ceil set to the maximum level you'll allow the user. For example, let's say you want to give testuser 400kbit of guaranteed bandwidth, but if the line is otherwise idle, let it grow to line rate. Set rate 400kbit and ceil to whatever you put as rate for 1:1. If you don't set ceil, it defaults to rate.

Fourth, to accomplish your goal of exempting ftp traffic, you'll need to use connmark instead of just mark. Otherwise your related data connection won't get properly exempted from the --set-mark 10. Connmark will properly pick up related connections.

I suggest the following (untested!) rules off the top of my head:

# flush rules out of postrouting so you're not constantly inserting during testing.
iptables -t mangle -F POSTROUTING
iptables -t mangle -X HTB_OUT

# The use of RETURN here is to fall out of our user chain and hit 
# -j CONNMARK --save-mark in the POSTROUTING chain.
iptables -t mangle -N HTB_OUT
iptables -t mangle -A HTB_OUT -j MARK --set-mark 30
iptables -t mangle -A HTB_OUT -p tcp --dport 21 -j MARK --set-mark 30
iptables -t mangle -A HTB_OUT -m mark ! --mark 0 -j RETURN
iptables -t mangle -A HTB_OUT -m owner --uid-owner testuser -j MARK --set-mark 10
iptables -t mangle -A HTB_OUT -m mark ! --mark 0 -j RETURN

iptables -t mangle -A POSTROUTING -j CONNMARK --restore-mark
iptables -t mangle -A POSTROUTING -m mark ! --mark 0 -j ACCEPT
iptables -t mangle -A POSTROUTING -j HTB_OUT
iptables -t mangle -A POSTROUTING -j CONNMARK --save-mark

Then for tc, something like the following:

# set a script variable that will represent our line-rate minus some change
CAPRATE=90Mbit
CAP_SUB_400=89Mbit

# clear our qdisc settings for eth0 so we're starting from a clean slate.
tc qdisc del dev eth0 root

tc qdisc add dev eth0 root handle 1: htb default 20
tc class add dev eth0 parent 1: classid 1:1 htb rate ${CAPRATE} burst 5k
# this is our capped class:
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 400kbit ceil ${CAPRATE}
# this is our default, catch-all class:
tc class add dev eth0 parent 1:1 classid 1:20 htb rate ${CAP_SUB_400} ceil ${CAPRATE}
tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10

tc filter add dev eth0 parent 1:0 prio 0 protocol ip handle 10 fw flowid 1:10

Things to remember: The sum of all rates for the immediate children of any parent should not exceed the parent rate ever. I cheated a little here and rounded 1:20's rate down to 89Mbit instead of 89600kbit. You can under-commit, but you should never over-commit.

iptables rules are evaluated in order. If your policy allows it, the most common matches should appear first; granted most of this is obviated by the POSTROUTING rules before entering the HTB_OUT chain, but it's a good rule of thumb.

So what's SFQ for... it's like stirring the pot. SFQ tries to give every connection (endpoint pair, actually) a fair share of the bandwidth, then every perturb seconds it mixes things up again, in case too many connections ended up in the same internal bucket (which is possible because of how hashing is done on src/dst/portpair). For more info, check lartc or the tc-sfq manpage.

share|improve this answer
    
Dratted dates. No idea how I got on this question to necro it, but since I already wrote an answer, heck with it. –  Andrew Domaszek May 19 at 22:46
iptables -A OUTPUT -m conntrack --connbytes from:to --connbytes-mode packets/bytes/avgpkt -m owner --uid-owner owner -J DROP

Other possibilities -m connlimit -m hashlimit

share|improve this answer
    
can you please explain what the above command do? i have no idea –  Gihan Lasita Dec 10 '12 at 10:08

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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