Getting tc(8) to work for me with Linux with SIP/IAX

In Thoughts on VoIP and achieving good call quality I was still trying to figure out how to configure the outbound prioritsation of traffic on my Linux box to favour VoIP using tc(8). Finally I’ve had time to try and figure it out and as far as I can see it helps a bit.

Just a reminder of the problem.

My linux box runs Asterisk, but is also a web and mail server, runs NFS etc, etc, …. That means that sometimes it’s busy sending traffic which is not VoIP traffic. As a result during a voice call even though the bandwidth in my LAN is sufficient for all of this, some of the voice traffic may get delayed, affecting audio quality. It’s also worth noting that Asterisk accepts calls from my voip phone and then resends the call to the final destination which may be an internal PSTN gateway or an external VoIP provider. This double call issue means that any VoIP delays may get accentuated.

From the previous article I successfully checked that the voip traffic generated by Asterisk and my voip phones uses the dscp values EF for RTP voice traffic and CS3 for call signalling. Unfortunately my Siemens C470IP uses AF31, so this needs to be taken into account too.

I came across a few different posts about setting up tc(8) but none of them seemed to fit my situation. Some people configure it on a linux router and manage the bandwidth that way, others try to do the prioritisation based on ip port filtering. With RTP this does not work very well and besides it seems that if you want to implement QoS it’s best to try to do it consistently 1 way.

So I modified a script I found which almost seemed to do what I needed, and basically did the following:

  • Convert the 3 DSCP values into decimal
  • Multiply them by 4 as there are 2 bits to the right within the ToS byte
  • Convert that number to hex

That gave me the following values

Next, to match this properly in the tos byte we need to match the first 6 bits, as the last 2 are used for ECN.

See this link which shows the relation between DSCP and ToS bits.

Hence for tc(8) I need to use a byte mask of 0xfc.

The remaining script which I use is shown below and basically assigns all traffic to a low priority queue and then matches these 3 DSCP values, putting them in queue 0 (highest priority).


#!/bin/sh
#
# Taken from: http://www.howtoforge.com/voip_qos_traffic_shaping_iproute2_asterisk
# and adapted to filter by DSCP values EF, CS3 and AF31 (due to a Siemens
# voip phone not using the right dscp value).
#
[ -n "$DEBUG" ] && set -x
myname=$(basename $0)

start () {
# wrong? but set all traffic to lowest queue
tc qdisc add dev $interface root handle 1: prio priomap 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2

# Adjust each queue so they themselves have some queuing discipline:
# This gives the first queue a supposed capacity of 3000 packets. In
# reality, the size will be 128 packets as it is hard coded in the tc
# program as being the maximum size possible.

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

# Simon’s thoughts:
# decimal binary 4x hex bitmask
# CS3 24 011 000 96 0x60 0xfc
# EF 46 101 110 184 0xB8 0xfc
# AF31 26 011 010 104 0x68 0xfc

tc filter add dev $interface protocol ip parent 1: prio 1 u32 match ip tos 0x60 0xfc flowid 1:1
tc filter add dev $interface protocol ip parent 1: prio 1 u32 match ip tos 0xb8 0xfc flowid 1:1
tc filter add dev $interface protocol ip parent 1: prio 1 u32 match ip tos 0x68 0xfc flowid 1:1
}

# To see some statistics
status () {
tc -s qdisc ls dev $interface
}

# To remove your queues and return to the normal state
stop () {
tc qdisc del dev $interface root
}

interface=eth0

case $1 in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
*)
echo “Usage: $myname {start|stop|restart|status}”
esac

This seems to now configure the interface giving VoIP (IAX and SIP traffic in my case high priority of everything else.

Work to do is to figure out how to recongise peer to peer traffic for when I download ISO images and drop those into a lower queue than the other ssh, smtp, http traffic that the server is doing. That however is not a concern for the voice traffic.

Published by

Simon J Mudd

Born in England, I now live in Spain, but spent a few years living in the Netherlands. I previously worked in banking (financial markets) both in IT and as a broker, but IT has always had a stronger influence. Now working at booking.com as a Senior Database Administrator. Other interests include photography, and travel. Simon is married, with two children and lives in Madrid.

One thought on “Getting tc(8) to work for me with Linux with SIP/IAX”

  1. Thanks for this informative post, I’ve been trying to find something similar to setup prioritization on my own VoIP calls.

Leave a Reply