Linux + Traffic Shaping ======================= Shanker Balan http://shankerbalan.com/ Changelog: Wed Apr 30 13:57:00 IST 2003 - Initial commit! The below has not actually been tested, its just something that I had to think but never got the oppurtunity to actually implement it. Maybe it works, maybe it does not. 128kbps Link (kpbs = kilo bits per second) | | +------------> 64kbps Internet | | | | | +------------> 56kbps HTTP (90%) | | | | | +------------> 8 kbps FTP (10%) | ------- | 64kbps | ------- | +------------> 64kbps Intranet | | +------------> 8 kbps POP/IMAP (10%) | | +------------> 16 kbps Citrix/Database (25%) | | +------------> 40kbps HTTP (65%) ------- 64kbps ------- POLICY: 1. 64 kbps for Internet out of availble 128kbps 2. 64 kbps for Intranet out of available 128kbps burstable to 128kbps 3. Intranet apps to be given priority over Internet from 8AM IST thru 10PM IST in the following order: (lower numbers have higher prio) - Citrix/Database Prio 1 - POP/IMAP Prio 2 - Intranet HTTP Prio 3 - Inernet HTTP Prio 4 - Rest (FTP) Prio 5 I propose to use the "Hierarchical Token Bucket" or HTB filter for achieving the above objectives for the following reasons: 1. HTB ensures that the amount of service provided to each class is at least the minimum of the amount it requests and the amount assigned to it. 2. When a class requests less than the amount assigned, the remaining (excess) bandwidth is distributed to other classes which request service. The queuing schedular to be uses if "Stochastic Fairness Queueing" or SFQ for the following reasons: 1. Traffic is divided into a pretty large number of FIFO queues, one for each session 2. Traffic is then sent in a round robin fashion, giving each session the chance to send data in turn. 3. This leads to very fair behaviour and disallows any single conversation from drowning out the rest. The rules: tc qdisc add dev eth0 root handle 1: htb default 50 tc class add dev eth0 parent 1: classid 1:1 htb rate 128kbps ceil 128kbps burst 2k # allocate 64kbps out of 128kbps by creating a child class under the parent HTB # and then create subclassed under the child class for the following services # Intranet services: # # Class Min Max Priority # ------------------------------------ # http 56 64 4 # rest 8 64 5 # # http/rest class will borrow from the parent class up to a max of 64kbps only. # If both queues are active, the 1:20 queue will be restricted to 8kbps. tc class add dev eth0 parent 1:1 classid 1:2 htb rate 64kbps ceil 64kbps burst 2k tc class add dev eth0 parent 1:2 classid 1:10 htb rate 56kbps ceil 64kbps burst 2k prio 4 tc class add dev eth0 parent 1:2 classid 1:20 htb rate 8kbps ceil 64kbps burst 2k prio 5 # Now create child classes under the parent for dividing the whole 128k for Intranet usage # # Class Min Max Priority # ------------------------------------- # Citrix/Db 16 128 1 # IMAP/POP 8 128 2 # HTTP 40 128 3 # # Directly borrow from the parent class of 128kbps for IMAP/POP, Citrix/DB and # HTTP for Intranet usage. Citrix/DB and HTTP will borrow up to the rate # permitted by the parent (128Kbps) In case of congestion, queue "1:40" will be # pushed first, followed by "1:30" and then by "1:50". tc class add dev eth0 parent 1:1 classid 1:30 htb rate 8kbps ceil 16kbps burst 2k prio 2 tc class add dev eth0 parent 1:1 classid 1:40 htb rate 16kbps ceil 128kbps burst 2k prio 1 tc class add dev eth0 parent 1:1 classid 1:50 htb rate 40kbps ceil 128kbps burst 2k prio 3 # Assign fairness queing to all the classes. # SFQ ensures that each flow (or TCP/UDP session) is given the chance to send # data in an round robin fashion. 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 tc qdisc add dev eth0 parent 1:40 handle 40: sfq perturb 10 tc qdisc add dev eth0 parent 1:50 handle 50: sfq perturb 10 # attach classifiers - fwmark 1 thru 5 tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 1 fw flowid 1:10 # http tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 2 fw flowid 1:11 # rest tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 3 fw flowid 1:20 # imap/pop tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 4 fw flowid 1:21 # citrix/db tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 5 fw flowid 1:22 # http # And finally mark packets iptables -t mangle -A POSTROUTING -i eth0 -p tcp -d !${LAN} --dport 80 -j MARK --set-mark 1 iptables -t mangle -A POSTROUTING -i eth0 -p tcp -d ${LAN} --dport 80 -j MARK --set-mark 5 iptables -t mangle -A POSTROUTING -i eth0 -p tcp -d ${LAN} --dport 143 -j MARK --set-mark 3 iptables -t mangle -A POSTROUTING -i eth0 -p tcp -d ${LAN} --dport 110 -j MARK --set-mark 3 iptables -t mangle -A POSTROUTING -i eth0 -p tcp -d ${LAN} --dport citrix -j MARK --set-mark 4 iptables -t mangle -A POSTROUTING -i eth0 -p tcp -d ${LAN} --dport db -j MARK --set-mark 4 iptables -t mangle -A POSTROUTING -i eth0 -j MARK --set-mark 2