The quality of  VoIP phone calls for sure depends on many factors. The main questions that we should understand are: how good is your termination provider and the carrier they are using for the prefix you’ve dialed? What codec is used? Do you have enough bandwidth for real time stream? In most cases even if all is good in chain the voice quality is bad and many people reject using this technology because of the bad voice quality. Imagine a msall office with 20-30 people who actively using an Internet connection all the day. Someone doing browsing, someone watching youtube and some of them are running P2P software on the background with huge amount of sessions opened and traffic generated. In this busy traffic conditions if you try to make a call using VoIP phone you will have bad feeling about VoIP if you don’t have QoS priority set to make SIP call and it’s RTP stream allocated with some guaranteed, always available bandwidth chunk or just put all SIP and associated UDP traffic into the priority with will be higher then all other traffic.


So we are talking about  VoIP phone calls quality, regardless of how busy your Internet connection is and what other activities you have running in your LAN.

A quick note regarding my VoIP system: As Internet connection I am using FFTP with 100 Mbit/s cooper, but real speed with L2TP is about 10 Mbit/s at the moment. The Ethernet goes to Linksys WRT54GL flashed with dd-wrt firmware. I have my own Asterisk box in DMZ and I can configure it to do whatever I want. As CPE I have Nokia E71 phone with Nimbuzz installed – this is good option BTW for mobile VoIP, so I can walk around my house with my cell phone (it has Wi-Fi) and be always registered with my home Asterisk setup.

Setup overview

I assume you already have in place your Linux firewall. VoIP packets transverse your firewall and your NAT is already set and working. We won’t even touch your firewall with this setup. All you need to do is to create the right qdisc, classes and filters to prioritize your VoIP packets. Iproute2′s tc command is here for that.

Let’s consider a network with the following chain:

Internet <——> Cable modem <——-> Linux Firewall <—–> Intranet <—–> VoIP phone

Since I’m using Asterisk with SIP the port of interest is 5060, if you’re running with IAX please change the port to 4569 in below commands:

Quick notes:

IP packets have an area where you can preset QoS (quality of Service).  While your ISP will probably ignore them, you can make use of them in your local network for some traffic shaping. The 4 QoS bits are:

0×02: Minimize Monetary Cost

0×04: Maximize Reliability

0×08: Maximize Throughput

0×10: Minimize Delay

Officially, you are allowed to turn on at most one of those bits. Your firewall can then look at the packets as they come and determine which ones to forward first, usually Minimize Delay.

Unofficially, you can turn on any of those bits at once. So you could have a packet with both Minimize Delay and Maximize Throughput. With this in mind, let’s look at some of the features of Iproute2.

Iproute2 And tc

By default, packets are sent FIFO (First In-First Out). With tc, you can alter that dramatically. Let’s use a very simple queuing system: let’s have 3 “pipes” (or queues) and assign them a priority. That is, as long as there is something in queue 1, we don’t empty (or dequeue) queue 2, and as long as there is something in queue 2, we don’t dequeue queue 3.

This is done with the following command (note: eth1 is the external interface):

tc qdisc add dev eth1 root handle 1: prio priomap 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 0

The 16 values for priomap are important.  It basically says that most packets end up in the 3rd queue (since we start at zero, it’s called “2″), except the packets with QoS Minimize-Delay, which are put in the 2nd queue, except the packets with every QoS bits on, which are put in the 1st queue. (the prio queuing discipline sets 3 queues by default)

The 16 values are in order for the following QoS:

1: 0×00: no QoS is set -> to 3rd queue (2)
2: 0×02: Mimimize Monetary Cost (MMC) (2)
3: 0×04:  Maximize Reliability (MR) (2)
4: 0×06: MMC + MR (2)
5: 0×08: Maximize Throughput (MT) (2)
6: 0x0a: MT + MMC (2)
7: 0x0c: MT + MR (2)
8: 0x0e: MT + MR + MMC (2)
9: 0×10: Minimize Delay (MD) (1)
10: 0×12: MD + MMC (1)
11: 0×14: MD + MR (1)
12: 0×16: MD + MMC + MR (1)
13: 0×18: MD + MT (1)
14: 0x1a: MD + MT + MMC (1)
15: 0x1c: MD  + MT + MR (1)
16: 0x1e: MD + MT + MR + MMC (0)

That was a first step. Next, we will need to adjust each queue so they have some queuing discipline:

tc qdisc add dev eth1 parent 1:1 handle 10: sfq limit 3000
tc qdisc add dev eth1 parent 1:2 handle 20: sfq
tc qdisc add dev eth1 parent 1:3 handle 30: sfq

This gives the first queue a supposed capacity of 3000 packets, but the real size will be 128 packets as it is hard coded in the tc program as being the maximum size possible. At this point, most of the packets will go through the 3rd queue, except those with Minimize-Delay QoS bit set.

If you adjust your sip.conf (or iax.conf if you are using IAX) on your Asterisk box to say the following, some packets may end up in the first queue:

tos=0x1e

However, since this isn’t a guarantee, we will force them to queue 1 using another trick in tc filters. Once again I want to point your attention that SIP uses port 5060 and  IAX uses port 4569. Thus we need to force any packet from/to this port to go through the first queue:

tc filter add dev eth1 protocol ip parent 1: prio 1 u32 match ip dport 5060 0xffff flowid 1:1
tc filter add dev eth1 protocol ip parent 1: prio 1 u32 match ip sport 5060 0xffff flowid 1:1
tc filter add dev eth1 protocol ip parent 1: prio 1 u32 match ip tos 0×10 0xff flowid 1:2

Actually the last line is not required, but I’d prefer to leave it there. So from this point you’ve done. All your VoIP packets are dequeued first and foremost. Even during a heavy download or upload, you won’t lose interactivity for your telephone calls.

To see some statistics, run the following command:

tc -s qdisc ls dev eth1

To undo our adjustments and get back to the default state

tc qdisc del dev eth1 root [it will remove queues]

Hope it helps :-)

One Response to QoS and VoIP – how to set priority for VoIP calls with TC

  1. [...] are welcome to see another articles for setting up QoS for ip telephony traffic on Linux as well as interesting dilemma with QoS in IP-based [...]

Leave a Reply