Bi-Directional Quality of Service (QoS)
I had some time to come up with a crazy Bi-Directional QoS script.
The mechanics:
INBOUND TRAFFIC -> eth0 -> NAT -> eth1 (where eth0 is Internet, and eth1 is Network)
OUTBOUND TRAFFIC -> eth1 -> NAT -> eth0
Traffic is classified by the following:
POSTROUTING methods.
INBOUND TRAFFIC -> POSTROUTING MARK -> eth1
OUTBOUND TRAFFIC -> POSTROUTING MARK -> eth0
The main reason why I choose marking traffic from both interfaces was because it was after NAT - I needed to mark certain traffic by its IP address. Marking traffic using PREROUTING and POSTROUTING just didn’t work.
Application:
#Download
$iptables -t mangle -I POSTROUTING -o eth1 -j DL-unconditioned
#Upload
$iptables -t mangle -I POSTROUTING -o eth0 -j UP-unconditioned
Perquisites:
Linux Kernel 2.6.12, iptables v1.3.5, modules: IMQ, layer7, mark, reject, log, multiport, TOS, HFSC, mangle, limit, state, nat_ftp, etc.
The Linux Kernel Archives
Netfilter/IPtables project home page
Application Layer Packet Classifier for Linux
Linux IMQ patch for iptables
You will most likely need to recompile the kernel first. I started off installing FC4 and then recompiling the kernel - if you are using a distribution method always use a distribution that has a kernel lower than your patched one.
First things first make sure you load the required modules i.e.:
shell> modprobe imq
shell> modprobe ipt_IMQ
Under the services section the following are for games (although this section is in development). 1 = enable and 0 = disable.
# UT2004 7777:7787/UDP
ENABLE_UNREAL04="1"
# GuildWars 6112/TCP
ENABLE_GUILDWAR="1"
Network configuration uses the IMQ devices. Where:
ethOUT="imq1" # Upload
ethIN="imq0" # Download
Queue Size sets the transmit queue length of your bandwidth - this is important depending on your available bandwidth. I found for low traffic networks and high interactive activities you may want this value low - whereas a higher value for high traffic and high-throughput. (read the comments in the script for more details)
# "Transmit queue length"
# (default 1000) higher the better for smoothness, lower the better for interactive
# traffic at the cost of packet loss for high-throughput
len0="3000"
len1="3000"
Maximum Transmissible Unit
Changes mtu on the device. Lowering the mtu will result in lower latency but will also cause slightly lower throughput due to IP and tcp protocol overhead. (default 1500, Recommend 1492 for DSL users)
mtu0="1500"
mtu1="1500"
ToS or Type of Services section is still in development…
mind="16" # Minimize-Delay 16 (0x10) hi interactive
maxt="8" # Maximize-Throughput 8 (0x08)
maxr="4" # Maximize-Reliability 4 (0x04)
minc="2" # Minimize-Cost 2 (0x02)
normal="0" # Normal-Service 0 (0x00)
Under program paths, change this information to reflect the correct path.
iptables="/usr/local/sbin/iptables"
ip="/sbin/ip"
tc="/sbin/tc"
modprobe="/sbin/modprobe"
Starting from Line 197 edit these settings to reflect your real bandwidth and set your percentage of your real bandwidth to top speed. You want your $dtotalmax variable lower than your real (actual) bandwidth to allow overflow of the IP header information, etc.
realdownspeed="8000"
dtotalmax=$(echo "scale=9; $realdownspeed * 0.90" | bc)
dtotalmax=`printf "%2.0f" $dtotalmax`
At line 206 to 246 are bandwidth rules for your downstream. Using the HFSC algorithm three variables are needed in order for this setup to function correctly.
- Variable prefix ‘rate#’ is the guarantee rate of your downstream per chain - this rate combined with all the chains must not exceed the available $dtotalmax (which is 80-90% of your actual bandwidth).
- ‘mrate#’ is the max rate of bandwidth this chain is allowed to consume (bandwidth throttling make sure this value is also less than your $dtotalmax variable)
- ‘mdelay#’ is the max delay or slope a packet can withstand a queue. (I don’t understand this variable that much in corrolation to my ’sc’ to ‘ul’ method class.)
The redirect section Line 264 forwards acknowledgement packets to higher chains.
At line 326 to 347 contains information of LEVEL 10 - the highest priority traffic. At line 334 to 344 is what you really need to change…
Line (334-344):
# WARNING: VoIP RULES ARE DIFFERENT THAN UPLOAD RULES
$iptables -t mangle -A $chainname -d 192.168.10.2 -m comment --comment "${mark}:VoIP 1234567890" -j $gotochain
$iptables -t mangle -A $chainname -d 192.168.10.3 -m comment --comment "${mark}:VoIP 0987654321" -j $gotochain
$iptables -t mangle -A $chainname -p icmp -m comment --comment "${mark}:ICMP" -j $gotochain
names="dhcp"
for name in $names
do
$iptables -t mangle -A $chainname -m comment --comment "${mark}:${name}" -m layer7 --l7proto $name -j $gotochain
done
You can mark an entire IP address by this:
$iptables -t mangle -A $chainname -d 192.168.10.2 -m comment --comment "${mark}:VoIP 1234567890" -j $gotochain
Mark mutiple targets by a look like: (where the variable ‘names’ contains a list of options - i.e. names=”dhcp dns rpd” etc.)
names="dhcp"
for name in $names
do
$iptables -t mangle -A $chainname -m comment --comment "${mark}:${name}" -m layer7 --l7proto $name -j $gotochain
done
Once you finish the section for the download speed, start working on your upload speeds starting from Line 499.
Notices:
There are certains things this script lacks.
- Placing squid on the box which houses this script would not work as packets will not be marked correctly INBOUND.
- The same goes true with running a DNS server on the same machine.
- Remember this script is Bi-Directional, if you must use Squid and DNS you may have to suffice with the mechanics of PREROUTING and POSTROUTING where targeting –source-mac and -destination ip addresses on one interface than two.
- The other solution if you have the spare hardware is to create a bridge after the QoS/Firewall system that has Squid and DNS services.
- This script was designed with 2×8 classes where this may not be intended for your needs. If you need less classes simply remove them and adjust the appropriate lines.
You can download this script here. (make sure you read all the comments)
References:
HFSC Scheduling with Linux
About this entry
You’re currently reading “Bi-Directional Quality of Service (QoS),” an entry on Taehoon’s Blog
- Published:
- 03.16.07 / 5am
- Category:
- Networking, Programming, References & Documentation, QoS+VoIP
No comments
Jump to comment form | comments rss [?] | trackback uri [?]