Penguin
Diff: LinuxQualityOfService
EditPageHistoryDiffInfoLikePages

Differences between current version and revision by previous author of LinuxQualityOfService.

Other diffs: Previous Major Revision, Previous Revision, or view the Annotated Edit History

Newer page: version 12 Last edited on Thursday, October 16, 2008 12:46:09 pm by DanielLawson
Older page: version 10 Last edited on Thursday, September 22, 2005 9:48:33 am by MichaelBordignon Revert
@@ -7,9 +7,9 @@
 I live in a flat where we pay 3rds of the cost of the internet bill, so between three people, they each should have an even crack at the bandwidth. 
  
 I devised two queuing structures that should give a decent balance between users, one for egress on the internal interface and one for egress on the external interface. 
  
-  
+<pre>  
 Egress on internal interface (eth0). 
  
  Root Class 
  Qdisc 1: PRIO 
@@ -117,9 +117,9 @@
  | | For TCP and other non-interactive | | 
  | | applications. | | 
  | -------------------------------------- | 
  ------------------------------------------ 
-  
+</pre>  
  
 Linux QoS is based around a heirachical structure of queueing disciples (qdiscs), classes and filters. 
  
 There are two major types of qdiscs, those that are classful, or contain classes, and those that are classless, or leaf qdiscs. 
@@ -140,37 +140,44 @@
 With this in mind, let us first create the QoS rules on the ppp0 interface. 
  
 First, lets delete everything and start on a clean slate. 
  
+<pre>  
  root@sleepy:~# tc qdisc del dev ppp0 root 
  root@sleepy:~# tc qdisc show dev ppp0 
+</pre>  
  
 Ok, now we need to add the qdisc to the device root class, we're using CBQ 
  
+<pre>  
  root@sleepy:~# tc qdisc add dev ppp0 root handle 10: cbq bandwidth 6Mbit rate 127kbit avpkt 1000 
  root@sleepy:~# tc qdisc show dev ppp0 
  qdisc cbq 10: rate 127Kbit (bounded,isolated) prio no-transmit 
  root@sleepy:~# tc class show dev ppp0 
  class cbq 10: root rate 127Kbit (bounded,isolated) prio no-transmit 
+</pre>  
  
 Notice how this has created a root class, we could refer to it as 10:0 if we desired. 
 Lets create the first of our High priority queues. 
  
+<pre>  
  root@sleepy:~# tc class add dev ppp0 parent 10: classid 10:1 cbq bandwidth 6Mbit rate 127kbit weight 20kbit prio 8 allot 1514 cell 8 maxburst 20 avpkt 200 bounded 
  root@sleepy:~# tc class show dev ppp0 
  class cbq 10: root rate 127Kbit (bounded,isolated) prio no-transmit 
  class cbq 10:1 parent 10: rate 127Kbit (bounded) prio no-transmit 
+</pre>  
  
 And apply the SFQ to traffic in that queue! 
  
+<pre>  
  root@sleepy:~# tc qdisc show dev ppp0 
  qdisc sfq 101: quantum 1500b 
  qdisc cbq 10: rate 127Kbit (bounded,isolated) prio no-transmit 
-  
+</pre>  
  
 This is what the QoS looks like now. 
  
-  
+<pre>  
  Root Class 
  Qdisc 10: CBQ 127kbit 
  ------------------------------------------ 
  | Class 10:1(CBQ Class, 127kbit) | 
@@ -180,12 +187,12 @@
  | | For interactive applications | | 
  | | and ICMP etc. | | 
  | -------------------------------------- | 
  ------------------------------------------ 
-  
+</pre>  
  
 Lets have a look at whats happening with traffic so far: 
-  
+<pre>  
  root@sleepy:~# tc -d -s qdisc show dev ppp0 
  qdisc sfq 101: quantum 1500b limit 128p flows 128/1024 
  Sent 0 bytes 0 pkts (dropped 0, overlimits 0) 
  
@@ -202,11 +209,11 @@
  class cbq 10:1 parent 10: leaf 101: rate 128Kbit cell 8b (bounded) prio no-transmit/8 weight 20Kbit allot 1514b 
  level 0 ewma 5 avpkt 200b maxidle 10812us 
  Sent 0 bytes 0 pkts (dropped 0, overlimits 0) 
  borrowed 0 overactions 0 avgidle 283475 undertime 0 
+</pre>  
  
-  
- Well as we can see, things appear to be working, at least to a certian point. 
+Well as we can see, things appear to be working, at least to a certain point. 
  
 All traffic is being queued by the root class, and not being passed to the SFQ qdisc inside class 10:1. 
  
 Now we need to use the third major building block of Linux QoS, the filter. 
@@ -216,14 +223,16 @@
 Linux iptables comes with a feature called fwmark, which allows packets to be tagged as they traverse firewall rules. This can be useful for tagging packets for QoS based on PROTO/IP/PORT information. The iptables MARK target, can be applied to the PREROUTING or POSTROUTING chains on any interface. Because however, I use IP MASQUERADING on my ppp0 interface, the internal IP of the source host sending data to the internet via ADSL has been lost in the ppp0 POSTROUTING chain. 
  
 Therefore, we will use the PREROUTING chain on the eth0 interface to mark the packets. 
  
+<pre>  
  root@sleepy:~# iptables -t mangle -I PREROUTING -j MARK --set-mark 100 -s 10.1.13.3/32 -i eth0 
  root@sleepy:~# iptables -L -n -t mangle -x -v 
  Chain PREROUTING (policy ACCEPT 367 packets, 125801 bytes) 
  pkts bytes target prot opt in out source destination 
  32 2000 MARK all -- eth0 * 10.1.13.3 0.0.0.0/0 MARK set 0x64 
  
+</pre>  
 We are now marking packets with 100, or hex 0x64. 
  
 All that remains to get packets matching the SFQ, is to add the filter with tc: 
  
@@ -232,8 +241,9 @@
 And the results... 
  
 Before: 
  
+<pre>  
  root@sleepy:~# tc -s -d qdisc show dev ppp0 
  qdisc sfq 101: quantum 1500b limit 128p flows 128/1024 
  Sent 0 bytes 0 pkts (dropped 0, overlimits 0) 
  
@@ -250,16 +260,18 @@
  class cbq 10:1 parent 10: leaf 101: rate 128Kbit cell 8b (bounded) prio no-transmit/8 weight 20Kbit allot 1514b 
  level 0 ewma 5 avpkt 200b maxidle 10812us 
  Sent 0 bytes 0 pkts (dropped 0, overlimits 0) 
  borrowed 0 overactions 0 avgidle 283475 undertime 0 
-  
+</pre>  
 Adding Filter: 
+<pre>  
  root@sleepy:~# tc filter add dev ppp0 protocol ip parent 10: prio 1 handle 100 fw flowid 10:1 
  root@sleepy:~# tc filter show dev ppp0 
  filter parent 10: protocol ip pref 1 fw 
  filter parent 10: protocol ip pref 1 fw handle 0x64 classid 10:1 
-  
+</pre>  
 After: 
+<pre>  
  root@sleepy:~# tc -s -d qdisc show dev ppp0 
  qdisc sfq 101: quantum 1500b limit 128p flows 128/1024 
  Sent 548 bytes 9 pkts (dropped 0, overlimits 0) 
  
@@ -276,15 +288,17 @@
  class cbq 10:1 parent 10: leaf 101: rate 128Kbit cell 8b (bounded) prio no-transmit/8 weight 20Kbit allot 1514b 
  level 0 ewma 5 avpkt 200b maxidle 10812us 
  Sent 244 bytes 4 pkts (dropped 0, overlimits 0) 
  borrowed 0 overactions 0 avgidle 283475 undertime 0 
+</pre>  
  
 Alright, now we're getting some traffic in the SFQ now! 
  
 Adding the rest of the queues is relatively straight forward, providing you use a sane numbering scheme for your qdisc/class handles. 
  
 Here is the script to setup the QoS structure for ADSL as above, we're adding 5 user queues, for expansions sake, if they're not used, they don't affect anyone else. 
  
+<pre>  
  # Clear the slate 
  tc qdisc del dev ppp0 root 
  
  # Add a classful qdisc (cbq) to the root class 
@@ -333,15 +347,16 @@
  tc filter add dev ppp0 protocol ip parent 10: prio 1 handle 107 fw flowid 10:7 
  tc filter add dev ppp0 protocol ip parent 10: prio 1 handle 108 fw flowid 10:8 
  tc filter add dev ppp0 protocol ip parent 10: prio 1 handle 109 fw flowid 10:9 
  tc filter add dev ppp0 protocol ip parent 10: prio 1 handle 110 fw flowid 10:10 
-  
+</pre>  
  
 Now, all that is needed is to use iptables to MARK packets for the appropriate queues. 
 Remember MARK does not immediately RETURN the packet. I get around this by marking every packet first, then having the sorting rules match on that mark, so once a packet is marked, it won't be marked again in that table. 
  
 Heres what my PREROUTING chain looks like. 
  
+<pre>  
  Chain PREROUTING (policy ACCEPT 294 packets, 114705 bytes) 
  pkts bytes target prot opt in out source destination 
  716 207616 MARK all -- eth0 * 0.0.0.0/0 0.0.0.0/0 MARK set 0x80 
  18 1080 MARK icmp -- etho * 10.1.13.3 0.0.0.0/0 MARK match 0x80 MARK set 0x65 
@@ -352,11 +367,12 @@
  52 6074 MARK udp -- eth0 * 0.0.0.0/0 0.0.0.0/0 MARK match 0x80 MARK set 0x69 
  159 7296 MARK all -- eth0 * 10.1.13.3 0.0.0.0/0 MARK match 0x80 MARK set 0x6a 
  435 189427 MARK all -- eth0 * 10.1.13.7 0.0.0.0/0 MARK match 0x80 MARK set 0x6b 
  42 2999 MARK all -- eth0 * 0.0.0.0/0 0.0.0.0/0 MARK match 0x80 MARK set 0x6e 
-  
+</pre>  
 Cross-Referencing with the tc filters, we see .. 
  
+<pre>  
  root@sleepy:~# tc filter show dev ppp0 
  filter parent 10: protocol ip pref 1 fw 
  filter parent 10: protocol ip pref 1 fw handle 0x65 classid 10:1 
  filter parent 10: protocol ip pref 1 fw handle 0x66 classid 10:2 
@@ -367,11 +383,14 @@
  filter parent 10: protocol ip pref 1 fw handle 0x6b classid 10:7 
  filter parent 10: protocol ip pref 1 fw handle 0x6c classid 10:8 
  filter parent 10: protocol ip pref 1 fw handle 0x6d classid 10:9 
  filter parent 10: protocol ip pref 1 fw handle 0x6e classid 10:10 
+  
+</pre>  
  
 For example, a udp packet arriving on eth0 with source address 10.1.13.3 will be market with 0x65, and sent to class 10:1, which has a SFQ qdisc on the child class of CBQ, while a TCP packet from 10.1.13.7 will be marked with 0x6b and sent to class 10:7 which has a token bucken qdisc on a child class of a CBQ. 
  
+<pre>  
  root@sleepy:~# tc -s -d class show dev ppp0 
  .... 
  class cbq 10:1 parent 10: leaf 101: rate 127Kbit cell 8b (bounded) prio no-transmit/8 weight 20Kbit allot 1514b 
  level 0 ewma 5 avpkt 200b maxidle 10898us 
@@ -391,9 +410,9 @@
  ... 
  qdisc sfq 101: quantum 1500b limit 128p flows 128/1024 
  Sent 23370 bytes 383 pkts (dropped 0, overlimits 0) 
  ... 
-  
+</pre>  
  
 What remains to do is setup the egress on the internal interface, eth0, and FWMARK packets coming in on the external interface, so we can remark them into the queues. 
  
 If you're still confused, this looks like a rather well commented QoS script: