OpenWrt Forum Archive

Topic: Traffic shaping (upload rate)

The content of this topic has been archived on 27 Apr 2018. There are no obvious gaps in this topic, but there may still be some posts missing at the end.

Hi

I'm having a hard time figuring out how to do some traffic shaping in openwrt. What I'm trying to do is to limit download/upload rate based on client IP.

I have also tried this sample from wiki and it's not working (not limiting upload rate) http://wiki.openwrt.org/doc/howto/packe … r.example2
I have also tried this sample from jow and it's not working (not limiting upload rate) https://forum.openwrt.org/viewtopic.php?id=23285

My approach is below. The download part is working but the upload part is killing me. What am I missing?
I tried to type everything by hand (not using script) and it didn't give me any errors. Also based on packets number and traffic I'd say that packets do get market, but for some reason they a) don't jump to device or b) filter doesn't see the mark.

This is my INCOMING chain in MANGLE table
http://shrani.si/f/40/eh/3ZAQmFmT/inc.png

This is my OUTGOING chain in MANGLE table
http://shrani.si/f/1h/Q8/26g7zbiX/out.png

The code I am using

insmod cls_fw >/dev/null 2>&1
insmod cls_u32 >/dev/null 2>&1
insmod sch_htb >/dev/null 2>&1
insmod sch_sfq >/dev/null 2>&1
insmod sch_ingress >/dev/null 2>&1
insmod act_police >/dev/null 2>&1

DOWN_IMQ=0
DOWN_IMQ_NAME="imq0"
DOWN_RATE=1000
DOWN_BURST2=3080
DOWN_BURST=1540 # DOWN_RATE * 1000 / 8 / 100 or at least MTU
DOWN_MTU=1540

UP_IMQ=1
UP_IMQ_NAME="imq1"
UP_RATE=250
UP_BURST2=3080
UP_BURST=1540 # DOWN_RATE * 1000 / 8 / 100 or at least MTU
UP_MTU=1540

INCOMING_CHAIN=INC
OUTGOING_CHAIN=OUT

ip link set $DOWN_IMQ_NAME up
tc qdisc add dev "$DOWN_IMQ_NAME" root handle 1: htb r2q 10
tc class add dev "$DOWN_IMQ_NAME" parent 1: classid 1:1 htb rate 20000kbit
tc class add dev "$DOWN_IMQ_NAME" parent 1:1 classid 1:10 htb rate ${DOWN_RATE}kbit ceil ${DOWN_RATE}kbit burst $DOWN_BURST2 cburst $DOWN_BURST mtu $DOWN_MTU
tc class add dev "$DOWN_IMQ_NAME" parent 1:1 classid 1:20 htb rate 500kbit ceil 500kbit burst $DOWN_BURST2 cburst $DOWN_BURST mtu $DOWN_MTU
tc filter add dev "$DOWN_IMQ_NAME" parent 1: protocol ip handle 80 fw flowid 1:10
tc filter add dev "$DOWN_IMQ_NAME" parent 1: protocol ip handle 81 fw flowid 1:20


ip link set $UP_IMQ_NAME up
tc qdisc add dev "$UP_IMQ_NAME" root handle 1: htb r2q 10
tc class add dev "$UP_IMQ_NAME" parent 1: classid 1:1 htb rate 500kbit
tc class add dev "$UP_IMQ_NAME" parent 1:1 classid 1:10 htb rate ${UP_RATE}kbit ceil ${UP_RATE}kbit burst $UP_BURST2 cburst $UP_BURST mtu $UP_MTU
tc class add dev "$UP_IMQ_NAME" parent 1:1 classid 1:20 htb rate 500kbit ceil 500kbit burst $UP_BURST2 cburst $UP_BURST mtu $UP_MTU
tc filter add dev "$UP_IMQ_NAME" parent 1: protocol ip handle 82 fw flowid 1:10
tc filter add dev "$UP_IMQ_NAME" parent 1: protocol ip handle 83 fw flowid 1:20

iptables -t mangle -I $INCOMING_CHAIN -j IMQ --todev $DOWN_IMQ
iptables -t mangle -I $INCOMING_CHAIN -d 192.168.1.186 -j MARK --set-mark 81
iptables -t mangle -I $OUTGOING_CHAIN -j IMQ --todev $UP_IMQ
iptables -t mangle -I $OUTGOING_CHAIN -s 192.168.1.186 -j MARK --set-mark 82

if I change the "outgoing" to the code below, it works.

ip link set $UP_IMQ_NAME up
tc qdisc add dev "$UP_IMQ_NAME" root handle 1: htb default 1 r2q 10
tc class add dev "$UP_IMQ_NAME" parent 1: classid 1:1 htb rate ${UP_RATE}kbit ceil ${UP_RATE}kbit burst $UP_BURST2 cburst $UP_BURST mtu $UP_MTU prio 1

iptables -t mangle -I $OUTGOING_CHAIN -s 192.168.1.186 -j IMQ --todev $UP_IMQ

(Last edited by mitja.gti on 27 May 2012, 23:10)

Never mind the question. I guess I'm working too much again smile

The problem with the example above is that first I set mark 0x52 (if IP match) and then I set 0x400. When the packet enters dev 1 it only has mark 0x400 and none of the filters set in TC match.

Solutions are two (well 1 for me).
1) I could use xmark to concat marks. For example if the IP match add 0x100 to 0x400 (don't let the IPs fool you in the above example. In this case they match but that's not the case every time) so you'll get 0x500. Then write two filters in tc. One for 0x400 and one for 0x500.

The following mnemonics are available for --set-xmark:

--and-mark bits
Binary AND the ctmark with bits. (Mnemonic for --set-xmark 0/invbits, where invbits is the binary negation of bits.)
--or-mark bits
Binary OR the ctmark with bits. (Mnemonic for --set-xmark bits/bits.)
--xor-mark bits
Binary XOR the ctmark with bits. (Mnemonic for --set-xmark bits/0.)
--set-mark value[/mask]
Set the connection mark. If a mask is specified then only those bits set in the mask are modified.
--save-mark [--mask mask]
Copy the nfmark to the ctmark. If a mask is specified, only those bits are copied.
--restore-mark [--mask mask]
Copy the ctmark to the nfmark. If a mask is specified, only those bits are copied. This is only valid in the mangle table.

2) This is more useful for me since my example is a bit more complicated as it might look at first sight. The thing is that I don't want to add yet another x rules in another table (which does filtering based on mark 0x400). I decided to do filtering in tc based on the source ip.
For example:
# this will match packets with 0x400
tc filter add dev "$UP_IMQ_NAME" parent 1: protocol ip prio 2 handle 0x400 fw flowid 1:10
# this will match packets that come from source with the ip 192.168.1.186
tc filter add dev "$UP_IMQ_NAME" parent 1: protocol ip prio 1 u32 match ip src 192.168.1.186/32 flowid 1:20

I did a quick test and it's working.
I hope I didn't do yet another silly mistake and someone will find this useful smile

The discussion might have continued from here.