Penguin
Diff: TrafficShaping
EditPageHistoryDiffInfoLikePages

Differences between version 16 and predecessor to the previous major change of TrafficShaping.

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

Newer page: version 16 Last edited on Friday, April 1, 2005 5:27:53 pm by JohnMcPherson Revert
Older page: version 15 Last edited on Friday, October 29, 2004 5:53:02 pm by JohnMcPherson Revert
@@ -18,16 +18,24 @@
 This is a script I use to throttle one machine down to half our ADSL rate. This machine is used for downloading large files (for example .iso's of the latest LinuxDistribution), but we don't want it impacting the rest of our machines. This example was stolen from the Advanced Router HOWTO, and cleaned up a bit by me. 
  
 You run this script on your gateway rate limiting data to your internal client machine(s). 
  
+<verbatim>  
  #!/bin/sh 
  
  # The device data is going *out* of. You can't stop a machine recieving data (short of firewalling) 
  # But you can limit how fast it *sends* data. 
+ # this is the device that goes to the clients on our LAN  
  DEV=eth0 
  
- # The IP you want to throttle 
+ # The IP you want to throttle. Any IP that matches this destination  
+ # will have its traffic added to our (single) child class.  
+ # If you want to rate-limit all your clients, set it to something like:  
+ # IP=.../  
+ # Note that this script will also ratelimit traffic generated by this  
+ # router to any matching IP addresses!  
  IP=10.10.10.13 
+  
  
  # How fast your internal network is. This is used to estimate the rates more accurately. If this 
  # is wrong then the rate will be out by a little bit or something. 
  LINERATE=100mbit 
@@ -38,9 +46,9 @@
  
  # Where the tc executable is. 
  TC=/sbin/tc 
  
- if [ [ ! -x $TC ]; then 
+ if [ ! -x $TC ]; then 
  echo Cant find $TC, aborting 
  exit 1 
  fi 
  
@@ -83,11 +91,60 @@
  # around this is to change the hash function frequently so that this effect is reduced. However 
  # doing this too often makes your rate limiting less accurate, doing it too rarely means that 
  # data is incorrectly classified as above, so we tell the kernel to change the hash every 10s. 
  $TC qdisc add dev $DEV parent 1:1 sfq perturb 10 
-  
+</verbatim>  
  
 Hopefully this is enough to get people started, please, if you know anything more add it to this page. I found the advanced router howto very oblique in it's information. 
+----  
+Similar script, for the case where your router is also a fileserver (and you don't want to rate-limit that, obviously).  
+  
+My server has <tt>eth1</tt> going to the ISP, and <tt>eth0</tt> going to the lan clients. This doesn't rate-limit upstream connections, but few users on our lan use much upstream bandwidth. This script rate-limits to just below our ADSL bandwidth, so that packets get dropped (and [TCP] adjusts its sending rate) rather than getting queued in [TelecomNZ]'s equipment.  
+  
+<verbatim>  
+/bin/sh  
+  
+DEV=eth0  
+# the IP address of the above device (so it isn't ratelimited)  
+SERVERIP=10.21.1.2  
+# lan clients to rate-limit  
+LIMITIPS=10.21.1.0/24  
+  
+# remove any existing queue discipline: (might say no such file or dir)  
+tc qdisc del dev eth0 root 2> /dev/null  
+  
+# quit this script immediately if any command returns error  
+set -e  
+  
+# create a root queuing discipline for our interface  
+tc qdisc add dev $DEV root handle 1:0 cbq bandwidth 100Mbit avpkt 1000 cell 8  
+  
+# create a class called 1:1  
+tc class add dev $DEV parent 1:0 classid 1:1 cbq bandwidth 100Mbit \  
+ prio 8 allot 1514 cell 8 rate 100Mbit maxburst 20 avpkt 1000  
+  
+# create a sub-class of 1:1 called 1:10 that is rate-limited to 105kbit  
+tc class add dev $DEV parent 1:1 classid 1:10 cbq bandwidth 100Mbit \  
+ rate 105Kbit prio 1 allot 1514 cell 8 maxburst 20 \  
+ avpkt 1000 bounded  
+  
+# create a sub-class called 1:20 that isn't limited, for locally generated traffic  
+tc class add dev $DEV parent 1:1 classid 1:20 cbq allot 1514 avpkt 1000 \  
+ rate 100Mbit bandwidth 100Mbit prio 2  
+  
+# locally generated traffic should go to the appropriate sub-class  
+tc filter add dev $DEV parent 1:0 protocol ip prio 1 u32 \  
+ match ip src $SERVERIP/32 flowid 1:20  
+# not sure if this is really needed... traffic from one interface to another?  
+tc filter add dev $DEV parent 1:0 protocol ip prio 1 u32 \  
+ match ip dst $SERVERIP/32 flowid 1:20  
+  
+# traffic to our lan (that didn't match earlier rules) should go to appropriate sub-class  
+tc filter add dev $DEV parent 1:0 protocol ip prio 2 u32 \  
+ match ip dst $LIMITIPS flowid 1:10  
+  
+</verbatim>  
+  
  
 ---- 
 Some points to remember: 
 !!Outgoing interface 
@@ -102,9 +159,9 @@
  
 Notes: 
 This will not work with masquerading 
 The network connection can still get easily saturated 
-  
+<verbatim>  
  #!/bin/sh 
  # List of IPs to have upload throttled 
  IPS=`seq 114 117 | awk '{print "1.2.3."$1}'` 
  
@@ -128,9 +185,9 @@
  match ip src $IP flowid 1:$LASTTHING 
  
  tc qdisc add dev ppp0 parent 1:$LASTTHING sfq perturb 10 
  done; 
-  
+</verbatim>  
 ---- 
 After a bit of fiddling I've managed to get TrafficShaping working on a per protocol (read port) basis 
  
 as per below 
@@ -142,9 +199,9 @@
 started to go critical because of the latency introduced, so we needed to differentiate between different 
 ports and protocols 
  
 so I ended up with this script 
-  
+<verbatim>  
  #!/bin/sh 
  
  DEV=eth0 
  
@@ -189,9 +246,9 @@
  echo "---- Class parameters Ingress ----------" 
  $TC class ls dev $DEV 
  echo "---- filter parameters Ingress ----------" 
  $TC filter ls dev $DEV 
-  
+</verbatim>  
 ''note that sport and protocols require 2 operands, the port/protocol number and a mask'' 
  
  
 ---- 
@@ -200,9 +257,9 @@
  
 It is possible to perform ingress shaping using a similar process. Your version of tc has to have ingress support compiled in - it appears that some RedHat versions may not have this. 
  
 The following script will limit traffic from source port 80 (ie, the return-path from a web connection) to 100kbit. It applies these rules on ppp0, which is my external interface. 
-  
+<verbatim>  
  #!/bin/sh 
  
  TC=/sbin/tc 
  IPTABLES=/sbin/iptables 
@@ -224,9 +281,9 @@
  $TC qdisc add dev $DEV handle FFFF: ingress 
  # apply the actual filter. 
  $TC filter add dev $DEV parent ffff: protocol ip prio 50 handle 1 fw \ 
  police rate $THROTTLE burst $BURST mtu $MTU drop flowid :1 
-  
+</verbatim>  
  
 If I look at the output of wget, its reasonably good at limiting a port 80 download to 10 - 12k/second, which is about right for what we asked. If i look at my ppp0 usage meter in gkrellm, it seems to be using more bandwidth than it should - spends a lot of time at 16 or 17 K/s incoming. Running iptraf on ppp0, in detailed statistics mode, shows that my incoming rate seems to be about 100kbit/sec, although it tends to be a bit higher than this normally. I also tested, and verified, that traffic not caught by the above script - eg, FTP traffic, still obtained full rate 
  
-In comparison with a by-port filter such as the one prior to the ingress script, I see a high level of fluctuation in the download rate, in all three test cases. Whether this is to do with some misconfiguration on my part I dont know 
+In comparison with a by-port filter such as the one prior to the ingress script, I see a high level of fluctuation in the download rate, in all three test cases. Whether this is to do with some misconfiguration on my part I dont know.