# TC prioritising... not working as I intended.

## dj_farid

I have done some traffic shaping on my router. The router does NAT for my workstation on the LAN.

I have rTorrent and a FTP running on the router. I want torrent traffic to have the lowest priority of all traffic. I would like to have torrent using pretty much the whole upload bandwidth when there is no trafic on the FTP. If someone however uses the FTP, he/she should have all the bandwidth he/she wants.

I have one script that clears all the iptable tables and takes care of NAT and all my firewall rules, running before this script:

```
# Clear

tc qdisc del dev eth0 root    # Clear any previous stuff

# Shaping

## Setup

tc qdisc add dev eth0 root handle 1: htb default 10

tc class add dev eth0 parent 1: classid 1:1 htb rate 904kbit

tc class add dev eth0 parent 1:1 classid 1:10 htb rate 904kbit prio 1

tc class add dev eth0 parent 1:1 classid 1:20 htb rate  300kbit prio 2

tc class add dev eth0 parent 1:1 classid 1:30 htb rate  700kbit prio 3

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 qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10

##Restrict linuxdcpp upload

iptables -t mangle -A OUTPUT -m layer7 --l7proto directconnect -j MARK --set-mark 2

tc filter add dev eth0 protocol ip parent 1:0 handle 2 fw flowid 1:20

##Restrict BitTorrent upload

iptables -t mangle -A OUTPUT -m layer7 --l7proto bittorrent -j MARK --set-mark 3

tc filter add dev eth0 protocol ip parent 1:0 handle 3 fw flowid 1:30

```

```

# tc class show dev eth0

class htb 1:1 root rate 904000bit ceil 904000bit burst 2Kb cburst 2Kb 

class htb 1:10 parent 1:1 leaf 10: prio 1 rate 904000bit ceil 904000bit burst 2Kb cburst 2Kb 

class htb 1:20 parent 1:1 leaf 20: prio 2 rate 300000bit ceil 300000bit burst 1749b cburst 1749b 

class htb 1:30 parent 1:1 leaf 30: prio 3 rate 700000bit ceil 700000bit burst 1949b cburst 1949b 

# tc -s class show dev eth0

class htb 1:1 root rate 904000bit ceil 904000bit burst 2Kb cburst 2Kb 

 Sent 5711206750 bytes 10335972 pkt (dropped 0, overlimits 0 requeues 0) 

 rate 465048bit 113pps backlog 0b 0p requeues 0 

 lended: 0 borrowed: 0 giants: 0

 tokens: -23461 ctokens: -23461

class htb 1:10 parent 1:1 leaf 10: prio 1 rate 904000bit ceil 904000bit burst 2Kb cburst 2Kb 

 Sent 5083833983 bytes 9190026 pkt (dropped 180, overlimits 0 requeues 0) 

 rate 464872bit 113pps backlog 0b 0p requeues 0 

 lended: 9190026 borrowed: 0 giants: 0

 tokens: -23461 ctokens: -23461

class htb 1:20 parent 1:1 leaf 20: prio 2 rate 300000bit ceil 300000bit burst 1749b cburst 1749b 

 Sent 8429 bytes 97 pkt (dropped 0, overlimits 0 requeues 0) 

 rate 0bit 0pps backlog 0b 0p requeues 0 

 lended: 97 borrowed: 0 giants: 0

 tokens: 48385 ctokens: 48385

class htb 1:30 parent 1:1 leaf 30: prio 3 rate 700000bit ceil 700000bit burst 1949b cburst 1949b 

 Sent 627380685 bytes 1145849 pkt (dropped 0, overlimits 0 requeues 0) 

 rate 152bit 0pps backlog 0b 0p requeues 0 

 lended: 1145849 borrowed: 0 giants: 0

 tokens: 22999 ctokens: 22999

```

The 1:30 class which is the torrent traffic seems to be caught according to the statistics.

The priority does not seem to work though. The download speed from my FTP is affected if I am seeding a torrent. I have been monitoring the upload speed from my FTP and at the same time restricting the upload speed of rTorrent. If my script should have worked the way I intended, the FTP speed should not have changed, but it did. The bandwidth seems to be divided pretty much 50/50 between both applications.

Any ideas on what I am doing wrong or could be improved?Last edited by dj_farid on Sun Oct 29, 2006 10:15 pm; edited 2 times in total

----------

## dj_farid

No one here that sees a problem with my script? or with my thoughts?

----------

## swanson

I don't have my own firewall and traffic shaping script to hand for comparision as I'm at work and my ADSL is knackered, but one subtle error is that the sum of the rates of the child classes should add up to the rate of the parent class. For example you could have;

```
tc class add dev eth0 parent 1: classid 1:1 htb rate 904kbps

tc class add dev eth0 parent 1:1 classid 1:10 htb rate 600kbps ceil 904kbps

tc class add dev eth0 parent 1:1 classid 1:20 htb rate 200kbps ceil 904kbps

tc class add dev eth0 parent 1:1 classid 1:30 htb rate 104kbps ceil 700kbps
```

So in other words;

```
1:1 == 1:10 + 1:20 + 1:30

904 == 600 + 200 + 104
```

The ceiling is basically just the maximum of unused bandwidth to allow a class. It defaults to the defined rate if unspecified.

----------

## dj_farid

Thanks Swanson!

I had misunderstood that parta about the ceiling. I thought that the ceiling was automatically the same as the root class (1:1 in my case).

Anyway, I think that I am one step closer now.

I still don't relly get it exactly the way I want it. Seems as if rTorrent uses a lot more of my download than it reports in the gui. I will have to do some more reading on the subject...

Does it matter in what order I mark my packets and do the priority with tc?

As it is now, I have one script doing NAT and some firewalling with iptables, then a second script doing marking packets and doing tc.

----------

## swanson

It'll probably just be that rTorrent is only showing the exact amount of file data it's sending but isn't considering the headers in the TCP packets and other TCP traffic such as ACKs sent to confirm you received packets  successfully from the other host.

For marking of packets the order probably doesn't matter though I really not sure what you're actually asking. An example might be useful.

----------

## dj_farid

There is still something weird with my shaping.

If someone is downloading from glftpd while rTorrent is sending, the speed gets unstable and too low from glftpd.

The traffic generated from glftpd should go into the default que which has highest prio, while torrent traffic has the lowest prio.

But for some reason rTorrent takes 70% of the bandwidth.

This is the first script that takes care of NAT and opens some ports:

```
#!/bin/bash

IPTABLES='/sbin/iptables'

# Set interface values

EXTIF='eth0'

INTIF1='eth1'

# enable ip forwarding in the kernel

/bin/echo 1 > /proc/sys/net/ipv4/ip_forward

echo "Clearing any existing rules and setting default policy.."

# flush rules and delete chains

$IPTABLES -F    #flush

$IPTABLES -X    #delete chain

$IPTABLES -t nat -F #delete prerouting chain

#linuxdcpp routing

$IPTABLES -A FORWARD -p tcp -m state --state NEW -m tcp --dport 31176 -j ACCEPT

$IPTABLES -A FORWARD -p udp -m state --state NEW -m udp --dport 31176 -j ACCEPT

# enable masquerading to allow LAN internet access

$IPTABLES -t nat -A POSTROUTING -o $EXTIF -j MASQUERADE

# forward LAN traffic from $INTIF1 to Internet interface $EXTIF

#$IPTABLES -A FORWARD -i $INTIF1 -o $EXTIF -m state --state NEW,ESTABLISHED -j ACCEPT

# Allowing access to the GLFTPD server

$IPTABLES -A INPUT --protocol tcp --dport 1006 -j ACCEPT

# Passive ports for glftpd

$IPTABLES -A INPUT --protocol tcp --dport 653:845 -j ACCEPT

$IPTABLES -A INPUT --protocol tcp --dport 224:285 -j ACCEPT

$IPTABLES -A INPUT --protocol tcp --dport 1010:1023 -j ACCEPT

$IPTABLES -A OUTPUT --protocol tcp --dport 653:845 -j ACCEPT

$IPTABLES -A OUTPUT --protocol tcp --dport 224:285 -j ACCEPT

$IPTABLES -A OUTPUT --protocol tcp --dport 1010:1023 -j ACCEPT

# Allow access to our ssh server from the WAN

iptables -A INPUT -p TCP --dport 2222 -i $EXTIF -j ACCEPT

# Allow access to BitTorrent on gen2

iptables -A INPUT -p TCP --dport 31111:31115 -i $EXTIF -j ACCEPT

iptables -A INPUT -p UDP --dport 31111:31115 -i $EXTIF -j ACCEPT

# Allow active connects with DC++

$IPTABLES -t nat -A PREROUTING -i $EXTIF -p tcp --dport 31176 -j DNAT --to-destination 192.168.0.115

$IPTABLES -t nat -A PREROUTING -i $EXTIF -p udp --dport 31176 -j DNAT --to-destination 192.168.0.115

# BitTorrent on local workstation

$IPTABLES -t nat -A PREROUTING -i $EXTIF -p tcp --dport 53001:53010 -j DNAT --to-destination 192.168.0.115

$IPTABLES -t nat -A PREROUTING -i $EXTIF -p tcp --dport 53001:53010 -j DNAT --to-destination 192.168.0.115

# New shit ->

# Create chain for bad tcp packets

$IPTABLES -N bad_tcp_packets

# bad_tcp_packets chain

$IPTABLES -A bad_tcp_packets -p tcp --tcp-flags SYN,ACK SYN,ACK \

-m state --state NEW -j REJECT --reject-with tcp-reset 

$IPTABLES -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j LOG \

--log-prefix "New not syn:"

$IPTABLES -A bad_tcp_packets -p tcp ! --syn -m state --state NEW -j DROP

# /New shit

# Block out all other Internet access on $EXTIF

$IPTABLES -A INPUT -i $EXTIF -m state --state NEW,INVALID -j DROP

$IPTABLES -A FORWARD -i $EXTIF -m state --state NEW,INVALID -j DROP 

# ./shape.sh

exit 0

```

This is the second that should take care of prioritizing:

```

#!/bin/bash

TC='/sbin/tc'

echo "Doing some traffic shaping"

# Clear

tc qdisc del dev eth0 root    # Clear any previous stuff

# Shaping

## Setup

CEIL=900

tc qdisc add dev eth0 root handle 1: htb default 10

tc class add dev eth0 parent 1: classid 1:1 htb rate ${CEIL}kbit burst 20k cburst 30k

tc class add dev eth0 parent 1:1 classid 1:10 htb rate 804kbit ceil ${CEIL}kbit burst 20k cburst 30k prio 1

tc class add dev eth0 parent 1:1 classid 1:20 htb rate 50kbit ceil ${CEIL}kbit prio 2

tc class add dev eth0 parent 1:1 classid 1:30 htb rate 50kbit ceil 700kbit prio 3

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 qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10

##Restrict linuxdcpp upload

iptables -t mangle -A OUTPUT -m layer7 --l7proto directconnect -j MARK --set-mark 2

iptables -t mangle -A FORWARD -m layer7 --l7proto directconnect -j MARK --set-mark 2

tc filter add dev eth0 protocol ip parent 1:0 handle 2 fw flowid 1:20

##Restrict BitTorrent upload

iptables -t mangle -A OUTPUT -m layer7 --l7proto bittorrent -j MARK --set-mark 3

#iptables -t mangle -A FORWARD -m layer7 --l7proto bittorrent -j MARK --set-mark 3

tc filter add dev eth0 protocol ip parent 1:0 handle 3 fw flowid 1:30

```

This problem is starting to irritate me. I think that I am staring me blind on my own script and not seeing the small and probably obvious problem here.

----------

## dj_farid

I commented out the last lines in the shaping script, everything that has to do with layer7 protocol.

Now the uploads from me are normal.

It seems that these lines are bugging out my connection:

```
##Restrict linuxdcpp upload

#iptables -t mangle -A OUTPUT -m layer7 --l7proto directconnect -j MARK --set-mark 2

#iptables -t mangle -A FORWARD -m layer7 --l7proto directconnect -j MARK --set-mark 2

#tc filter add dev eth0 protocol ip parent 1:0 handle 2 fw flowid 1:20

##Restrict BitTorrent upload

#iptables -t mangle -A OUTPUT -m layer7 --l7proto bittorrent -j MARK --set-mark 3

#tc filter add dev eth0 protocol ip parent 1:0 handle 3 fw flowid 1:30

```

I am using the 2.6.17.13 kernel. I noticed that there were some changes in l7 with that kernel. Could it be that this is some kind of bug, or am I just doing something wrong?

EDIT:

After uncommenting those lines and re-unning the two scripts, I still had the same problem. So I did a reboot and the problem went away.

I then noticed that the scripts do not wipe the mangle table. I guess that that is why I had to do a reboot before the changes were in effect.

I am now sure that the problem has to do with the l7-filter or iptables marking packets in some way.

EDIT2:

Upgraded iptables to the latest unstable (iptables-1.3.6-r1). This solved the weird problem. There has been a lot of work done in this version regarding l7-filter.

----------

## dj_farid

Still doesn't work. The BitTorrent traffic takes over all my upload, still.

If I connect to a FTP and send something, it sends with around 50/50 with torrent traffic. It should however send with the full capacity, that I have set as ceiling. Torrent traffic should almost halt.

```
# tc -s -d qdisc show dev eth0

qdisc htb 1: r2q 10 default 10 direct_packets_stat 0 ver 3.17

 Sent 17091326102 bytes 29314174 pkt (dropped 3544, overlimits 29504331 requeues 0)

 rate 0bit 0pps backlog 0b 29p requeues 0

qdisc sfq 10: parent 1:10 limit 128p quantum 1514b flows 128/1024 perturb 10sec

 Sent 14672976637 bytes 21481477 pkt (dropped 3010, overlimits 0 requeues 0)

 rate 0bit 0pps backlog 4245b 4p requeues 0

qdisc sfq 20: parent 1:20 limit 128p quantum 1514b flows 128/1024 perturb 10sec

 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)

 rate 0bit 0pps backlog 0b 0p requeues 0

qdisc sfq 30: parent 1:30 limit 128p quantum 1514b flows 128/1024 perturb 10sec

 Sent 2418349267 bytes 7832694 pkt (dropped 534, overlimits 0 requeues 0)

 rate 0bit 0pps backlog 17464b 25p requeues 0

```

There should be more dropped packages in 1:30...

What is wrong here?

EDIT:

Now I know...

L7 does not check all the packages as I thought. It needs to work together with CONNTRACK (Connection tracking).

My working script:

```
#!/bin/bash

TC='/sbin/tc'

echo "Doing some traffic shaping"

# Clear

tc qdisc del dev eth0 root    # Clear any previous stuff

# Shaping

CEIL=904

tc qdisc add dev eth0 root handle 1: htb default 10

tc class add dev eth0 parent 1: classid 1:1 htb rate ${CEIL}kbit

tc class add dev eth0 parent 1:1 classid 1:10 htb rate 820kbit ceil ${CEIL}kbit prio 1

tc class add dev eth0 parent 1:1 classid 1:20 htb rate 80kbit ceil 900kbit quantum 1514 prio 2

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

##Restrict BitTorrent upload

iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark

iptables -t mangle -A OUTPUT -m mark ! --mark 0 -j ACCEPT

iptables -t mangle -A OUTPUT -m layer7 --l7proto bittorrent -j MARK --set-mark 2

#iptables -t mangle -A OUTPUT -m ipp2p --bit -j MARK --set-mark 2

iptables -t mangle -A OUTPUT -j CONNMARK --save-mark

tc filter add dev eth0 protocol ip parent 1:0 handle 2 fw flowid 1:20
```

I would like to use ipp2p instead of l7 for this since it is faster, but the version in portage does not work with the latest kernels...

----------

## rimsky

iptables -t mangle -A OUTPUT -m layer7 --l7proto bittorrent -j MARK --set-mark 2 

iptables v1.4.10: Couldn't load match `layer7':/lib/xtables/libipt_layer7.so: cannot open shared object file: No such file or directory

xtables 1.31

----------

