Hack 77. Shape Network Traffic to Improve Quality of Service
There's a reason why the Public Switched Telephone Network (PSTN) has been the dominant global voice network for a century: Quality of Service. VoIP is a wonderful technology. It enables all kinds of features and portability options that are not available with traditional telephony technologies. However, unlike traditional telephony, VoIP has some inherent quality issues. By the time you finish reading this hack, you'll know how to tackle the quality problem with the VoIP engineer's best weapon: the Linux kernel's built-in router. On the traditional telephone network, every single call has a dedicated time slot using a technology called time division multiplexing (TDM). With TDM, a circuit is divided into several time slots, each with its own dedicated slice of bandwidth. This is what ensures that your call is the only call in that time slot, and that after all of the time slots are used, the circuit is at top capacity and no further calls will be allowed. With VoIP, your call is converted into thousands of small datagrams (or packets, if you please). These packets are then queued up on a device (your computer, analog telephone adapter [ATA], router, etc.) and thrown out over the wire, with no guarantee that they will even reach their ultimate destination, wherever that might be. You can see how this might cause problems with voice quality, especially when other data traffic on that same link is vying for that link's limited capacity (or "bandwidth," depending on your preferred vernacular). This is especially problematic with consumer access technologies such as cable modem or DSL. In a typical residential or small-office setup, you will have one relatively high-speed link to the Internet, and that link is responsible for carrying email, web surfing, and even the occasional big download of a CD-ROM image or something. Now try to put voice traffic on this link. Humans are very sensitive to delay when listening to speech. If one web site on your computer loads 250 ms slower than another web site, you're not really going to notice. However, if there is a 250ms delay in a conversation, you'll perceive that as a very annoying delay, and it will make ordinary conversation difficult. With all of this traffic on one link, how can I make sure that someone downloading a song from iTunes does not cause the audio on my VoIP call to suffer? It's easy, with a technology referred to as Quality of Service (QoS). QoS is a general term applied to a family of technologies that essentially manipulate the first in, first out (FIFO) queues on devices. Remember that PC from before, or that router or ATA? Normally, all of the IP traffic from that device will be placed into a FIFO queue for delivery to the remote endpoint. With QoS, we can manipulate that queue and pass judgment on packets matching certain attributes that move them to the front of the line, regardless of what time they got in, because they are more important to us. This is what you'll do with your VoIP packets. A router with Linux (i.e., a PC with two Ethernet interfaces and Linux installed) will help us. When you place this router between two networkssuch as the Internet and your LANyou can use it to enforce QoS measures. Thanks to the wonderful folks at http://www.lartc.org/, I was able to create a traffic-shaping script that works very well for prioritizing VoIP traffic. It is called AstShape, and it is included in the AstLinux distribution. However, you can use it in any Linux distribution that includes iproute2. This should be just about any major, modern distribution out there today. The first thing you need to do is visit my web site, http://www.kriscompanies.com/, and click on Downloads Asterisk AstShape. The AstShape script will begin downloading, and should finish very quickly. After you have saved it to your hard disk, copy it onto your router in a place like Once you have AstShape "installed," make it executable by running the following: # chown root:root astshape ; chmod 750 astshape This will ensure that no one other than root can run this script. Open AstShape in your favorite text editor, and take a look around. I will show the first few lines of AstShape and explain their meanings: Set this to the downstream speed of your connection (in kilobits). Use a speed test like the one available at http://toast.net/ to get an accurate idea of your connection's actual speed; for instance, the overhead of PPPoE accounts for an approximate 10%13% drop in speed from what is advertised by many consumer DSL packages. Test and test often! Also, you will want to set this number to about 85% of your actual test speed. (See the sidebar "VoIP QoS" for an explanation.) DOWNLINK=5500
Set this to the upstream speed of your connection. Use the Internet speed test results from before, and again subtract 15% from your results. The best way to determine this number is by testing, testing, testing: UPLINK=550 This is your external network deviceprobably eth0 or etH1. However, if you are using the Sangoma S518 mentioned in the sidebar "VoIP QoS" (or dial-upin which case you must really love torturing yourself), this will probably be ppp0: DEV=eth1 This is a list of ports, separated by spaces to be added to the VoIP class. This class of traffic is given highest possible priority. 4569 is the port for IAX2, Asterisk's native Inter-Asterisk Exchange (IAX) protocol. Do notdo notput 5060 here, ever (more on this later)! VOIPPORTS="4569" This is a list of ports to be given "interactive" priority. This is the next highest level of priority, and by default it includes two common ports used for SIP signaling. Please note that with common SIP devices, signaling (SIP) and audio transmission (RTP) take place in two (or more) separate UDP connections and do not travel on the same port. Many people make the mistake of adding port 5060 to their highest class of service for QoS. This does nothing for audio quality, and merely assures that SIP messaging (call setup, status, etc.) is given highest priority. While SIP is a time-sensitive protocol, RTP audio is much more so! Also, you might be thinking of adding port 22 (SSH) to this list. Don't do it just yet. You'll need to have more tricks up your sleeve for SSH: INTPORTS="5060 5061" This is a list of source ports to be added to the "bulk" class of service. This should include all traffic that tends to be large, sustained downloads/uploads. You might ask why port 22 (SSH) is listed here. As I mentioned before, we have some special instructions for SSH later on. Adding port 22 here essentially covers file transfers using SSH, not SSH shell sessions: NOPRIOPORTsrc="/books/3/439/1/html/2/25 22 80 110 143 943" This is the same as the NOPRIOPORTSRC line, except it refers to destination ports: NOPRIOPORTDST="25 22 80 110 143 943" 6.7.1. The Actual ScriptHere I will go over the actual commands from AstShape and attempt to break them down. If you are not interested in modifying AstShape beyond adjusting the preceding values, you do not need to read this section. If you need to do more tweaking, or are just plain curious, read on! This line installs the root hierarchical token bucket (HTB) queue and points default traffic to the 30 class: tc qdisc add dev $DEV root handle 1: htb default 30 This line defines the queue used for VoIP. As I say in the script, this is the "Crown Prince of Bandwidth." Nothing has higher priority than VoIP in AstShape: tc class add dev $DEV parent 1:1 classid 1:10 htb rate \ ${UPLINK}kbit burst 6k prio 1 The same for the "interactive class": tc class add dev $DEV parent 1:1 classid 1:20 htb rate \ ${UPLINK}kbit burst 6k prio 2 The default class: tc class add dev $DEV parent 1:1 classid 1:30 htb rate \ $[9*$UPLINK/10]kbit burst 6k prio 3 The bulk class: tc class add dev $DEV parent 1:1 classid 1:40 htb rate \ $[8*$UPLINK/10]kbit burst 6k prio 4 Now that we have our queues defined, we need to assign traffic to them. Any IP packets with TOS=0x18 belong in the VoIP class: tc filter add dev $DEV parent 1:0 protocol ip prio \ 10 u32 match ip tos 0x18 0xff flowid 1:10 Any IP packets with TOS=0x10 (minimum delay) belong in the interactive class: tc filter add dev $DEV parent 1:0 protocol ip prio \ 20 u32 match ip tos 0x10 0xff flowid 1:20 By default, most SSH client/server programs will set the IP TOS field to 0x10. How convenient! Add DNS to "interactive," too: tc filter add dev $DEV parent 1:0 protocol ip prio \ 21 u32 match ip sport 53 0xffff flowid 1:20 tc filter add dev $DEV parent 1:0 protocol ip prio \ 22 u32 match ip dport 53 0xffff flowid 1:20 DNS is a very time-sensitive protocol, where delays in name resolution can usually be noticed by a user or application very easily. Also, DNS queries are not very large, so it is to our benefit to add them to a higher class of service. You will see several lines that talk about Transmission Control Protocol (TCP) ACKs. These are TCP acknowledgments, and they won't be covered in this book. Trust AstShape (and me) by leaving this alone. Finally, we assign whatever is left to the earlier default class: tc filter add dev $DEV parent 1: protocol ip prio \ 30 u32 match ip dst 0.0.0.0/0 flowid 1:30 As you can see, AstShape is a very simple yet powerful traffic QoS script. A big thanks goes to the folks at LARTC for providing WonderShaper, which AstShape was based on. For more information on traffic shaping/QoS under Linux, please visit the LARTC web site at http://www.lartc.org/. Kristian Kielhofner |