www.fridu.net

  • Increase font size
  • Default font size
  • Decrease font size

Network Quality of Service

Print

This post describe how to implement network QoS (Quality of Service) on Linux. It first describes concept and then provides a QuickStart with small automation script to generate adequate "tc" and "iptables" commands. QoS is important for who ever want to avoid conflict in between log and high priority stream, typical examples are:

  • avoid to break your VO/IP quality while downloading big files.
  • make sure your interactive SSH activity got priority ever WEB browsing
  • etc ...

 


QoS concept

QoS (Quality of Service) allow you to sort and prioritize network stream. The only reason for using QoS is to handle the weakness of your network bandwidth, and unfortunately most will never have enough bandwidth, QoS requirement will probably stand up for a while. Typical consumer reason for implementing QoS

  • make sure that your VO/IP communication will not
  • provide a better user experience while running interactive ssh session
  • prevent your son peer2peer traffic to completely flood your DSL connection
  • etc ...


While almost everyone understand why QoS can be useful most people miss two very important points.

  • QoS can only apply to outgoing packet. While you may not have though about it, you need to realize that have absolutely no control on your incoming packet. What ever it send from whoever/anywhere with your IP adresse as destination will reach your home. If someone it flooding you with unsolicited packet your connection will be slow what ever you're doing.
  • QoS must apply before your DSL modem/router. If your QoS over estimate your bandwith, it will push too many packet to your DSL modem, moving your IP waiting queue list from your QoS control point to your Modem/router where you have no more QoS.


As soon you understand QoS mechanism you realize that only telecoms operators can implement a full QoS with an attach and point to end point SLA (Service Line Agreement). Nevertheless even a home made limited "outgoing" packet will have a significant impact on your bandwidth and this for following reason:

  • Most of us run ADSL and have a much more limited outgoing traffic than incoming, and ADSL is not ready to disappear anytime soon (see paragraph which ADSL and not SDSL). 
  • Most traffic have some form of handshake, either direct at network layer for TCP based stream  or at the application level for most of UDP based operations. As result by slowing down acknowledgment your directly influence incoming bandwidth stream.

Typical errors

Make sure not to over estimate your bandwidth: In order your QoS to work you need QoS FIFOs to be effectively handle at your packet filtering systems. This mean than any packet leaving your QoS should be sent to Internet without being queuing by a device you do not control (typically your DSL modem/router). As a result when making test you need to reduce your theoretical operator bandwidth the a level that really correspond to what you have (see testing chapter at the end).

Optimize the right packet: if you want to optimize your VO/IP based on SIP protocol do not forget that port 5600 is only use for signalization, when voice uses RTP packets on a different port. If you're having SIP appliance it might be easier to leverage source or destination IP than port number.

Only outgoing packet:  you do not control incoming packet if you're flood by peer2peer traffic they is nothing QoS can do for you. You should also realize that QoS is applied at post-routing level where some NAT may already have transformed your packet. In order to make sure you're taging the right packet push a packet to a dedicated class and check with "tc -s class show dev eth0" that you effectively marked the right traffic with the right tag.

Why ADSL and not SDSL

Most of us would be more than happy to exchange ADSL (Asynchronous Digital Subscriber Line) for SDSL (Synchronous  Digital Subscriber Line). In Europe we typically have for downstream/upstream from 20/2-Mbits/s to 5/1-Mbits/s for 15-30Euro/month depending if we leave in city/country side and have a basic Internet access or a bundle including Internet+VO/IP+TV. This being said moving from a ADSL with 20/2 to an SDSL with 10/10-Mbit/s will cost you best case ten time the price. Few fact first

  • Cheap bandwidth comes from modern hardwares than can extract a weak signal lost on in the middle of high noises for cheap price. This is how we can achieve 20Mbit/s over simple copper wires that in some case were installed just after second world war two.
  • Bandwidth is limited with attenuation and every one must realize that the farther from the operator connection point you are, the worse your signal/noise ratio will be and for a given quality of line the less bandwidth your will get.


This being said some will argue that attenuation is the same for down and up stream and they are perfectly right. Nevertheless the density of connection is much higher at DSLAM (operator end point) and for this reason not only you have to deal with our own noise, but you also inherit a significant level of noise from the others because of lines density.

Bandwidth depends on your signal/noise ratio and because of high density at DSLAM we have more noise at the operator than at your home destination. This is not too much of a problem for downstream, because at operator end point signal level is high and ratio keeps good despite of the high level of noise. Unfortunately this is not true for upstream signal that while having a high level at your home, reach the operator where noise is high with with a low signal, forcing us to reduce the speed to keep signal/noise ratio acceptable. On the other end when down stream signal reach your house, even if signal is weak it is not a huge problem, this because line density is weak providing a very clean noise environment and keeping noise/signal ratio acceptable despite of weak signal.

Conclusion: ADSL is not ready to disapear any time soon Frown

QoS within Linux (QuickStart)

Following explanation is based on Fridu-Xen QoS script that you can download from here

  • Unpack .tgz archive (tar -xzf Fridu-Xen-Scripts.tgz)
  • Install                      (cd Fridu-Xen-Scripts; ./install.sh)
  • Edit QoS rules         (edit /etc/sysconfig/Fridu-qos.config)
      • Start QoS                (Fridu-qos.script start)
Note: while this script is part of Fridu-Xen kit, it is a Fridu Firewall completely independent on Xen. 

Before going further you need to understand following three elements:

  • Traffic Control Class allows you to classify your bandwidth. This is where you split your bandwith in different slides. Each slide having either a fix or a moving part of global bandwith and a level of priority.
  • Traffic Control Filters, this is where you define which packet is going where. For a given packet IP tag, which class will be chosen and which queuing algorithm will be applied.
  • Packet Tagging, this is where you chose to mark an IP packet with a given tag. Usually base on port/address source or destination, but also on any other characteristic (size, proto, ...).

Traffic Control Class

Traffic class are organized like a winter tree with branches but no leafs. You start from root node "1.0" to which you give all your interface bandwidth (ex: 100Mbit/s) and you then split you bandwidth in slide.

Image

Traffic control class has many different options, must of you will probably be more than happy with what Fridu script will generate for you. For classes Fridu script has a unique command syntax is:

QoSclass Interface Bandwidth  NodeName RootNodeName [bounded]

   # class slice bandwith and handle overload/sharing
  # ------------------------------------------------
  QoSclass  $EXT  90${MBIT} 1:0  1:10 1                          ;# Let's say we do not have 100Mbits !!!
  QoSclass  $EXT  10${MBIT} 1:10 1:12 2                         ;# Privat 10Mbits/ (stream RTP)
  QoSclass  $EXT  80${MBIT} 1:10 1:14 3 bounded          ;# Public 80Mbit/s (normal traffic)
  QoSclass  $EXT  40${MBIT} 1:14 1:16 4                         ;# Public Normal 40Mbit/s expendable
  QoSclass  $EXT  40${MBIT} 1:14 1:18 5 bounded          ;# Public Slow traffic 40Mbit/s locked

Tagging Traffic packets

While Fridu script keep this par for the end, it is easier for you to defined it before Traffic Filters. Tag is what will allow you to stamp you network traffic in order later on filters to send it to the right class. Technically tagging is implemented thought iptables mangle module within post-routing table, but when using Fridu script this is completely transparent and user only have to handle 3 commands, each of then will define which packet should be stamp with a given tag number.

  • QoSFWport  tags any traffic on a given interface coming or going to a given port
  • QoSFWtiny   tags any packet smaller than a given size
  • QoSFWstop  tags any remaining packet with a default value.

Syntaxe:

  • QoSFWport Interface  udp|tcp port tag-number
  • QoSFWtiny  Interface  udp|tcp size tag-number
  • QoSFWstop Interface Tag-Number

 
  # IPtables rules are processed in Order
  # --------------------------------------------------

  # Real Time IMS RTP stream VP/IP
  QoSFWport $EXT udp 10000:11000 10                         ;# SIP RTP Traffic
  QoSFWport $EXT udp 4569  10                                     ;# IAX Asterisk Traffic

  # Traffic we want fast
  QoSFWport $EXT udp 44096 11                                    ;# OpenVpn
  QoSFWport $EXT udp 53    12                                       ;# DNS traffic
  QoSFWtiny $EXT tcp 64    12                                         ;# TCP packet less than 64bytes classid=17
  QoSFWport $EXT tcp 22    12                                        ;# SSH traffic

  # Normal Traffic
  QoSFWport $EXT tcp 80    14                                        ;# WEB Traffic

  # Slow Traffic
  QoSFWport $EXT tcp 25    20                                        ;# SMTP is marked 20     (slow)
  QoSFWstop $EXT 15                                                      ;# anything else mark 15 (normal/slow)


Traffic Filters

Last but not least you have to select which tag-number should go to which class. Filter will take as input parameter  packet tag number defined in previous step and as output parameter class's node to which packet should be sent and finally a priority which defined  how packet will be queue. Fridu script command name for filter is:

QoSFilter Interface Parent Destination-Class-Node Packet-Tag-Number Priority

  • Interface ex:eth0, tun0, ...
  • Parent is the parent ID of the queuing policy as defined in QoSqdisc (ex: 1.0)
  • Destination-Class-Node as defined in QoSclass
  • Packet-Tag as defined in QoSFWport
  • Priority priority used o push packet inside destination class.

   # filters check mask and send to appropriate classid
  # --------------------------------------------------
  QoSfilter $EXT 1:0 1:12 10 1                                   ;# data marked 10 private prio=1
  QoSfilter $EXT 1:0 1:12 11 2                                   ;# data marked 11 private prio=2

  QoSfilter $EXT 1:0 1:16 12 3                                   ;# data marked 12 private prio=3
  QoSfilter $EXT 1:0 1:16 13 1                                   ;# data marked 13 public  prio=1
  QoSfilter $EXT 1:0 1:16 14 2                                   ;# data marked 14 public  prio=2
  QoSfilter $EXT 1:0 1:16 15 3                                   ;# data marked 15 public  prio=3

  QoSfilter $EXT 1:0 1:18 20 1                                   ;# data marked 16 SLOW    prio=1
  QoSfilter $EXT 1:0 1:18 21 2                                   ;# data marked 17 BATCH   prio=2

 

Intitial parameters

Traffic shaping can be very complex, you can have many deferent algorithm to choose how packet will be queued, you can defined deferent policy for different slides of your bandwidth. Most of us will keep this as simple as possible and will probably have only one policy with one interface.

  EXT=eth0
  VPN=tun1

  # Define or main interface to DSL router
  # ------------------------------------------------
  QoSclean  $EXT                                                            ;# start cleaning the interface
  QoSqdisc  $EXT 100${MBIT} 1:0                                  ;# set root policy for interface 

 

Tuning/Testing your configuration

 Unfortunately thy is no easy way to test/tune your configuration.

Make sure you know your real bandwidth 

  • ping a reference point (ex: your sip gateway)
  • download a big file to know you down stream bandwidth
  • upload a file to get your upstream.
Note: While to doing the upload/downloadkeep pinging to meusure the disaster.

 In my case a quick test as describe here after show that my numbers are:

  • ping time for 50 byte ~56ms
  • download ~500KB/s
  • upload ~80KB/s 

root@logoden:# Fridu-qos.script stop                  # Stop QoS if any


fulup@logoden:~$ ping -s 50 sip.fridu.net
PING mail.fridu.net (91.121.65.140) 50(78) bytes of data.
58 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=1 ttl=49 time=56.1 ms
58 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=2 ttl=49 time=55.3 ms
58 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=3 ttl=49 time=58.4 ms

fulup@logoden:~$ wget ftp://ftp.free.fr/..-iso/openSUSE-10.3-Beta3-KDE-i386.iso
5% [===>                                                                      ] 41 808 736   577.21K/s    ETA 20:48

 

fulup@logoden:~/Tape$ ftp fridu.net
Connected to fridu.netftp> cd tmp
250 Directory successfully changed.
ftp> put Eriba-Himmer-Caravan_D_2007.pdf
local: Eriba-Himmer-Caravan_D_2007.pdf remote: Eriba-Himmer-Caravan_D_2007.pdf
200 PORT command successful. Consider using PASV.
150 Ok to send data.
226 File receive OK.
2000658 bytes sent in 25.48 secs (86.3 kB/s)

 

If your configuration is not to bad you should see that ping time should not be too much change while downloading a file, on the the other hand when uploading ping should fall down. In my case I got

# Ping before upload
64 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=38 ttl=49 time=62.3 ms
64 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=39 ttl=49 time=62.4 ms
64 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=40 ttl=49 time=61.5 ms
64 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=41 ttl=49 time=62.3 ms
# My concurent transfert start here.
64 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=44 ttl=49 time=156 ms
64 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=46 ttl=49 time=671 ms
64 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=47 ttl=49 time=713 ms
64 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=48 ttl=49 time=225 ms
64 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=50 ttl=49 time=708 ms

At this level they is not way your VO/IP to work correctly any ping time above 100ms degrade quality and anything above 300ms make voice fall down to first world war quality level. Let start QoS and do the same test

root@logoden # Fridu-qos.script start
fulup@logoden:~/Tape$ ping -c 50 sip.fridu.net
# Before ftp upload
64 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=30 ttl=49 time=62.2 ms
64 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=31 ttl=49 time=62.4 ms
64 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=32 ttl=49 time=61.8 ms
64 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=33 ttl=49 time=62.4 ms
# after FTP upload
64 bytes from ns25564.ovh.net (91.121.65.140: icmp_seq=34 ttl=49 time=75.4 ms
64 bytes from ns25564.ovh.net (91.121.65.140: icmp_seq=35 ttl=49 time=68.2 ms
64 bytes from ns25564.ovh.net (91.121.65.140): icmp_seq=36 ttl=49 time=80.8 ms
 
If with QoS on you still see your ping performance drop down then you have over estimated your bandwith and you need to reduce it at your main class node, or yo mess up your QoS config or both Smile In case of doubt you need to check where your traffic is going for this push traffic to dummy classes and use "tc -s class show" command.
 
24 # tc -s class show dev eth0
class cbq 1: root rate 100000Kbit (bounded,isolated) prio no-transmit
 Sent 1849873 bytes 2175 pkt (dropped 0, overlimits 0 requeues 0)
 rate 0bit 0pps backlog 0b 0p requeues 0
  borrowed 0 overactions 0 avgidle 80 undertime 0
class cbq 1:10 parent 1: rate 90000Kbit prio 1
 Sent 1847815 bytes 2126 pkt (dropped 0, overlimits 0 requeues 0)
 rate 0bit 0pps backlog 0b 0p requeues 0
  borrowed 0 overactions 0 avgidle 80 undertime 0
class cbq 1:12 parent 1:10 rate 10000Kbit prio 2
 Sent 20077 bytes 168 pkt (dropped 0, overlimits 0 requeues 0)
 rate 0bit 0pps backlog 0b 0p requeues 0
  borrowed 0 overactions 0 avgidle 80 undertime 0
class cbq 1:14 parent 1:10 rate 80000Kbit (bounded) prio 3
 Sent 1827738 bytes 1958 pkt (dropped 0, overlimits 0 requeues 0)
 rate 0bit 0pps backlog 0b 0p requeues 0
  borrowed 36 overactions 0 avgidle 80 undertime 0
class cbq 1:16 parent 1:14 rate 40000Kbit prio 4
 Sent 1827738 bytes 1958 pkt (dropped 0, overlimits 0 requeues 0)
 rate 0bit 0pps backlog 0b 0p requeues 0
  borrowed 36 overactions 0 avgidle 80 undertime 0
class cbq 1:18 parent 1:14 rate 40000Kbit (bounded) prio 5
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0)
 rate 0bit 0pps backlog 0b 0p requeues 0
  borrowed 0 overactions 0 avgidle 0 undertime 0
25 #
 
 

Bug Improvement

Please let me know Contact-Me  

 

Add your comment

Your name:
Your email:
Subject:
Comment: