Skip to main content

Voice quality reporting for Cisco VoIP using FreeRadius

This is an, I hope, comprehensive writeup on how to configure a Cisco gateway to send RADIUS Accounting details to a RADIUS server running FreeRadius. Among other things, these RADIUS packets contain <a href="http://www.cisco.com/en/US/docs/ios/voice/cdr/developer/guide/cdrdefs.html#wp1011077">useful information about the quality of the audio</a> as perceived by the calling and called parties of the call.

First we have to configure the Cisco hardware to send the RADIUS packets. I'm using a Cisco AS5350XM configured to send only RADIUS accounting details at the end of the call. Note that although the configuration suggests as much, you're not required to use H.323, SIP will also work just as well.

aaa new-model
aaa group server radius voip-accounting
 server [ip address] auth-port 1812 acct-port 1813
 ip radius source-interface GigabitEthernet0/0
aaa accounting connection h323 stop-only group voip-accounting
radius-server host [ip address] auth-port 1812 acct-port 1813 key 7 [secret]
radius-server vsa send accounting

Note how I'm telling it basically the same thing twice. Apparently this is really necessary, haven't had the time to properly test. This was the easy part.

Setting "aaa new-model" is, as far as I know, required but it will also mess up the way logging in to your Cisco equipment works. Setting this will mean that you will need a username + password combination to log in and the enable password, instead of just a password and the enable password.

Now make sure FreeRADIUS is up and running on a server reachable by the Cisco hardware. Edit /etc/freeradius/radiusd and make sure that the "with_cisco_vsa_hack" is set to yes:

with_cisco_vsa_hack = yes

Edit /etc/freeradius/dictionary so that the Cisco dictionary is NOT specifically loaded

$INCLUDE        /usr/share/freeradius/dictionary

Add the following to the dictionary file to be able to use the values the Cisco equipment is sending you (there's lots more information in the RADIUS packets, this is just what I needed):

ATTRIBUTE       coder-type-rate         118     string  Cisco
ATTRIBUTE       hiwater-playout-delay   119     string  Cisco
ATTRIBUTE       lowater-playout-delay   120     string  Cisco
ATTRIBUTE       round-trip-delay        121     string  Cisco
ATTRIBUTE       late-packets            122     string  Cisco
ATTRIBUTE       lost-packets            123     string  Cisco
ATTRIBUTE       early-packets           124     string  Cisco

I had to make sure the numbers didn't overlap with the existing values already in the Cisco dictionary. This is kinda important, you don't want to end up with the wrong data in the wrong column. Swapping source and destination numbers is totally possible if you're not careful.

Now it's time to insert a record in the database. For some reason my colleague who setup the radius server inserted the query into /etc/freeradius/sql/mysql/dialup.conf (check the comments). There might be better places. If you only want to save the end of call records, make sure you have no other accounting queries active in the queries file:

accounting_stop_query = "INSERT INTO ${acct_table}
(RadAcctId,
 AcctSessionId,
 AcctUniqueId,
 UserName,
 Realm,
 NASIPAddress,
 CiscoNASPort,
 NASPortId,
 NASPortType,
 AcctStartTime,
 AcctStopTime,
 AcctSessionTime,
 AcctAuthentic,
 ConnectInfo_start,
 ConnectInfo_stop,
 AcctInputOctets,
 AcctOutputOctets,
 CalledStationId,
 CallingStationId,
 AcctTerminateCause,
 ServiceType,
 FramedProtocol,
 FramedIPAddress,
 AcctStartDelay,
 AcctStopDelay,
 H323GWId,
 H323CallOrigin,
 H323CallType,
 H323Setuptime,
 H323ConnectTime,
 H323DisconnectTime,
 H323DisconnectCause,
 H323RemoteAddress,
 H323VoiceQuality,
 H323ConfId,
 Timestamp,
 codec,
 hiwater,
 lowater,
 roundtrip,
 plate,
 plost,
 pearly,
 DestinationId )
VALUES (
 '',
 '%{Acct-Session-Id}',
 '%{Acct-Unique-Session-Id}',
 '%{SQL-User-Name}',
 '%{Realm}',
 '%{NAS-IP-Address}',
 '%{Cisco-NAS-Port}',
 '%{NAS-Port-Id}',
 '%{NAS-Port-Type}',
 from_unixtime(unix_timestamp('%S')-%{Acct-Session-Time}),
 '%S',
 '%{Acct-Session-Time}',
 '%{Acct-Authentic}',
 '',
 '%{Connect-Info}',
 '%{Acct-Input-Octets}',
 '%{Acct-Output-Octets}',
 '%{Called-Station-Id}',
 '%{Calling-Station-Id}',
 '%{Acct-Terminate-Cause}',
 '%{Service-Type}',
 '%{Framed-Protocol}',
 '%{Framed-IP-Address}',
 '0',
 '%{Acct-Delay-Time}',
 '%{h323-remote-address}',
 '%{h323-call-origin}',
 '%{h323-call-type}',
 '%{h323-setup-time}',
 '%{h323-connect-time}',
 '%{h323-disconnect-time}',
 '%{h323-disconnect-cause}',
 '%{h323-remote-address}',
 '%{h323-voice-quality}',
 '%{h323-conf-id}' ,
 '%{Timestamp}',
 '%{coder-type-rate}',
 '%{hiwater-playout-delay}',
 '%{lowater-playout-delay}',
 '%{round-trip-delay}',
 '%{late-packets}',
 '%{lost-packets}',
 '%{early-packets}',
 '%{remote-media-address}'
)"

Note that we only added the last few SQL parameters and somehow FreeRADIUS is able to provide the rest. Make sure you have the correct table name and columns configured (double/triplecheck the query and your table).

The column H323VoiceQuality will contain the so called ICPIF impairment factor. A small writeup of what that means is <a href="http://ccie11440.blogspot.com/2007/11/calculated-planning-impairment-factor.html">here</a>.