Configuring a Cisco 7961 for SIP and Asterisk

Just prior to writing this, I think I was about ready to kill someone. Setting up this phone was probably one of the most challenging things I have done in a long time. So this will be my attempt to explain to other’s what I did and I will hopefully save some people some time.

Since we all need to be on the same page, let’s start out with the conventions:

  • Asterisk: Gentoo Linux, 192.168.1.5
  • Workhorse: Gentoo Linux (DHCP, TFTP, NTP), 192.168.1.20
  • Phone: Cisco 7961
  • Anything starting with a $ means you put your value in it. I will name the variable something descriptive for you
  • Remember that all filenames with Cisco are case sensitive
  • If there are some files you need examples of or access to and aren’t listed, please don’t hesitate to contact me.

I am not going to go into a lot of detail with things, just give some overview and some examples and it will hopefully be enough to get you in the right direction. Check throughout the document for some references and read up on those if need be.

DISCLAIMER: I am not an expert. If you break your phone while doing anything I mention here, I am not responsible. This is just what I did to get everything to work.

1. The first order of business was to add the phone’s MAC address to DHCP so I could be sure what was accessing the tftp server. I also needed to know the MAC address to create the proper files in the tftp directory. Ensure that you set the tftp server, ntp server, and SIP server in DHCP.

group voip {
        option domain-name-servers 192.168.1.20, 1.2.3.4;
        option domain-name "inside.mycompany.com";
        option smtp-server 192.168.1.20;
        option ntp-servers 192.168.1.20;
        option time-servers 192.168.1.20;
        option routers 192.168.1.1;
        option sip-server 192.168.1.5;
        default-lease-time 86400; # 1 day
        max-lease-time 86400;
        server-name "192.168.1.20";
        option tftp-server-name "192.168.1.20";

        host myphone {
            hardware ethernet 00:19:E8:F4:B4:D0;
            fixed-address 192.168.1.200;
        }
}

2. When you first plug in the phone, it’s loaded with the Skinny protocol software only (SCCP), nothing for SIP. This is because the phone was designed to work best (and really only) with the Cisco Call Manager. The first thing I had to do was to obtain the files that go in the tftproot on 192.168.1.20. In the upgrade package were the files:

  • apps41.1-1-3-15.sbn
  • cnu41.3-1-3-15.sbn
  • copstart.sh
  • cvm41sip.8-0-3-16.sbn
  • dsp41.1-1-3-15.sbn
  • jar41sip.8-0-3-16.sbn
  • load115.txt
  • load30018.txt
  • load308.txt
  • load309.txt
  • SIP41.8-0-4SR1S.loads
  • term41.default.loads
  • term61.default.loads

3. Once you place these files in the tftp root directory, you are ready for the upgrade. (Note: You need a Cisco smartnet file (or be good with Google) to find these files). Upgrading requires a factory reboot of the phone so it will look for the term61.default.loads file. To perform a factory reset of the phone, hold down the ‘#‘ as the phone powers up. Then dial ‘123456789*0#‘ and then let it work. The next time it reboots, it should then grab the necessary files from the tftp server and upgrade itself. You can watch the tftp logs and the phones LCD to ensure that everything that is supposed to be happening is happening.

4. At this point, the phone should be able to completely boot up and will likely just show you the word Unprovisioned at the bottom of the screen. The next step is to create the files that each phone needs to survive. The first file we are going to create is the SEP$MAC.cnf.xml. In the case of the phone that I am going to use for this demo, the filename is: SEP0019E8F490AD.cnf.xml. I know that the phone is also requesting the file CTLSEP0019E8F490AD.tlv, but you can safely ignore that. The minimalist version of the SEP$MAC.cnf.xml file:

<device>
   <deviceProtocol>SIP</deviceProtocol>
   <sshUserId>cisco</sshUserId>
   <sshPassword>cisco</sshPassword>
   <devicePool>
      <dateTimeSetting>
         <dateTemplate>M/D/Ya</dateTemplate>
         <timeZone>Eastern Standard/Daylight Time</timeZone>
         <ntps>
              <ntp>
                  <name>192.168.1.20</name>
                  <ntpMode>Unicast</ntpMode>
              </ntp>
         </ntps>
      </dateTimeSetting>
      <callManagerGroup>
         <members>
            <member priority="0">
               <callManager>
                  <ports>
                     <ethernetPhonePort>2000</ethernetPhonePort>
                     <sipPort>5060</sipPort>
                     <securedSipPort>5061</securedSipPort>
                  </ports>
                  <processNodeName>192.168.1.5</processNodeName>
               </callManager>
            </member>
         </members>
      </callManagerGroup>
   </devicePool>
   <sipProfile>
      <sipProxies>
         <backupProxy></backupProxy>
         <backupProxyPort></backupProxyPort>
         <emergencyProxy></emergencyProxy>
         <emergencyProxyPort></emergencyProxyPort>
         <outboundProxy></outboundProxy>
         <outboundProxyPort></outboundProxyPort>
         <registerWithProxy>true</registerWithProxy>
      </sipProxies>
      <sipCallFeatures>
         <cnfJoinEnabled>true</cnfJoinEnabled>
         <callForwardURI>x--serviceuri-cfwdall</callForwardURI>
         <callPickupURI>x-cisco-serviceuri-pickup</callPickupURI>
         <callPickupListURI>x-cisco-serviceuri-opickup</callPickupListURI>
         <callPickupGroupURI>x-cisco-serviceuri-gpickup</callPickupGroupURI>
         <meetMeServiceURI>x-cisco-serviceuri-meetme</meetMeServiceURI>
         <abbreviatedDialURI>x-cisco-serviceuri-abbrdial</abbreviatedDialURI>
         <rfc2543Hold>false</rfc2543Hold>
         <callHoldRingback>2</callHoldRingback>
         <localCfwdEnable>true</localCfwdEnable>
         <semiAttendedTransfer>true</semiAttendedTransfer>
         <anonymousCallBlock>2</anonymousCallBlock>
         <callerIdBlocking>2</callerIdBlocking>
         <dndControl>1</dndControl>
         <remoteCcEnable>true</remoteCcEnable>
      </sipCallFeatures>
      <sipStack>
         <sipInviteRetx>6</sipInviteRetx>
         <sipRetx>10</sipRetx>
         <timerInviteExpires>180</timerInviteExpires>
         <timerRegisterExpires>3600</timerRegisterExpires>
         <timerRegisterDelta>5</timerRegisterDelta>
         <timerKeepAliveExpires>120</timerKeepAliveExpires>
         <timerSubscribeExpires>120</timerSubscribeExpires>
         <timerSubscribeDelta>5</timerSubscribeDelta>
         <timerT1>500</timerT1>
         <timerT2>4000</timerT2>
         <maxRedirects>70</maxRedirects>
         <remotePartyID>true</remotePartyID>
         <userInfo>None</userInfo>
      </sipStack>
      <autoAnswerTimer>1</autoAnswerTimer>
      <autoAnswerAltBehavior>false</autoAnswerAltBehavior>
      <autoAnswerOverride>true</autoAnswerOverride>
      <transferOnhookEnabled>false</transferOnhookEnabled>
      <enableVad>false</enableVad>
      <preferredCodec>g711ulaw</preferredCodec>
      <dtmfAvtPayload>101</dtmfAvtPayload>
      <dtmfDbLevel>3</dtmfDbLevel>
      <dtmfOutofBand>avt</dtmfOutofBand>
      <alwaysUsePrimeLine>false</alwaysUsePrimeLine>
      <alwaysUsePrimeLineVoiceMail>false</alwaysUsePrimeLineVoiceMail>
      <kpml>3</kpml>
      <natEnabled>false</natEnabled>
      <natAddress></natAddress>
      <phoneLabel>LinkExperts</phoneLabel>
      <stutterMsgWaiting>1</stutterMsgWaiting>
      <callStats>true</callStats>
      <silentPeriodBetweenCallWaitingBursts>10</silentPeriodBetweenCallWaitingBursts>
      <disableLocalSpeedDialConfig>false</disableLocalSpeedDialConfig>
      <startMediaPort>16384</startMediaPort>
      <stopMediaPort>32766</stopMediaPort>
      <sipLines>
         <line button="1">
            <featureID>9</featureID>
            <featureLabel>100</featureLabel>
            <proxy>192.168.0.205</proxy>
            <port>5060</port>
            <name>100</name>
            <displayName>Eric Lubow</displayName>
            <autoAnswer>
               <autoAnswerEnabled>2</autoAnswerEnabled>
            </autoAnswer>
            <callWaiting>3</callWaiting>
            <authName>100</authName>
            <authPassword></authPassword>
            <sharedLine>false</sharedLine>
            <messageWaitingLampPolicy>1</messageWaitingLampPolicy>
            <messagesNumber>*97</messagesNumber>
            <ringSettingIdle>4</ringSettingIdle>
            <ringSettingActive>5</ringSettingActive>
            <contact>100</contact>
            <forwardCallInfoDisplay>
               <callerName>true</callerName>
               <callerNumber>true</callerNumber>
               <redirectedNumber>false</redirectedNumber>
               <dialedNumber>true</dialedNumber>
            </forwardCallInfoDisplay>
         </line>
      </sipLines>
      <voipControlPort>5060</voipControlPort>
      <dscpForAudio>184</dscpForAudio>
      <ringSettingBusyStationPolicy>0</ringSettingBusyStationPolicy>
      <dialTemplate>dialplan.xml</dialTemplate>
   </sipProfile>
   <commonProfile>
      <phonePassword></phonePassword>
      <backgroundImageAccess>true</backgroundImageAccess>
      <callLogBlfEnabled>1</callLogBlfEnabled>
   </commonProfile>
   <loadInformation>SIP41.8-0-4SR1S</loadInformation>
   <vendorConfig>
      <disableSpeaker>false</disableSpeaker>
      <disableSpeakerAndHeadset>false</disableSpeakerAndHeadset>
      <pcPort>1</pcPort>
      <settingsAccess>1</settingsAccess>
      <garp>0</garp>
      <voiceVlanAccess>0</voiceVlanAccess>
      <videoCapability>0</videoCapability>
      <autoSelectLineEnable>0</autoSelectLineEnable>
      <webAccess>1</webAccess>
      <spanToPCPort>1</spanToPCPort>
      <loggingDisplay>1</loggingDisplay>
      <loadServer></loadServer>
   </vendorConfig>
   <versionStamp>1143565489-a3cbf294-7526-4c29-8791-c4fce4ce4c37</versionStamp>
   <networkLocale>US</networkLocale>
   <networkLocaleInfo>
      <name>US</name>
      <version>5.0(2)</version>
   </networkLocaleInfo>
   <deviceSecurityMode>1</deviceSecurityMode>
   <authenticationURL></authenticationURL>
   <directoryURL></directoryURL>
   <idleURL></idleURL>
   <informationURL></informationURL>
   <messagesURL></messagesURL>
   <proxyServerURL>proxy:3128</proxyServerURL>
   <servicesURL></servicesURL>
   <dscpForSCCPPhoneConfig>96</dscpForSCCPPhoneConfig>
   <dscpForSCCPPhoneServices>0</dscpForSCCPPhoneServices>
   <dscpForCm2Dvce>96</dscpForCm2Dvce>
   <transportLayerProtocol>4</transportLayerProtocol>
   <capfAuthMode>0</capfAuthMode>
   <capfList>
      <capf>
         <phonePort>3804</phonePort>
      </capf>
   </capfList>
   <certHash></certHash>
   <encrConfig>false</encrConfig>
</device>

5. You will also need to create a dialplan so the phone doesn’t try to dial immediately. Below is a minimalist dialplan.xml (which is the filename we used in the above schema).

<DIALTEMPLATE>
  <TEMPLATE MATCH="." TIMEOUT="5" User="Phone" />
  <TEMPLATE MATCH="2500" TIMEOUT="2" User="Phone" />
  <TEMPLATE MATCH=".97" TIMEOUT="2" User="Phone" />
  <TEMPLATE MATCH="5..." TIMEOUT="2" User="Phone" />
  <TEMPLATE MATCH="1.........." TIMEOUT="2" User="Phone" />
</DIALTEMPLATE>

6. Although I am still not entirely sure that you need them, here are 2 other files that I was told need to be referenced:
SIPDefault.cnf:

# Image Version
image_version: "P0S3-08-6-00"

# Proxy Server
proxy1_address: "192.168.1.5"

# Proxy Server Port (default - 5060)
proxy1_port:"5060"

# Emergency Proxy info
proxy_emergency: "192.168.1.5" # IP address here alternatively
proxy_emergency_port: "5060"

# Backup Proxy info
proxy_backup: "192.168.0.205"
proxy_backup_port: "5060"

# Outbound Proxy info
outbound_proxy: ""
outbound_proxy_port: "5060"

# NAT/Firewall Traversal
nat_enable: "false"
nat_address: "192.168.1.5"
voip_control_port: "5061"
start_media_port: "16384"
end_media_port: "32766"
nat_received_processing: "0"

# Proxy Registration (0-disable (default), 1-enable)
proxy_register: "1"

# Phone Registration Expiration [1-3932100 sec] (Default - 3600)
timer_register_expires: "3600"

# Codec for media stream (g711ulaw (default), g711alaw, g729)
preferred_codec: "none"

# TOS bits in media stream [0-5] (Default - 5)
tos_media: "5"

# Enable VAD (0-disable (default), 1-enable)
enable_vad: "0"

# Allow for the bridge on a 3way call to join remaining parties upon hangup
cnf_join_enable: "1" ; 0-Disabled, 1-Enabled (default)

# Allow Transfer to be completed while target phone is still ringing
semi_attended_transfer: "0" ; 0-Disabled, 1-Enabled (default)

# Telnet Level (enable or disable the ability to telnet into this phone
telnet_level: "2" ; 0-Disabled (default), 1-Enabled, 2-Privileged

# Inband DTMF Settings (0-disable, 1-enable (default))
dtmf_inband: "1"

# Out of band DTMF Settings (none-disable, avt-avt enable (default), avt_always - always avt ) dtmf_outofband: "avt" ~np~# DTMF dB Level Settings (1-6dB down, 2-3db down, 3-nominal (default), 4-3db up, 5-6dB up)
dtmf_db_level: "3"

# SIP Timers
timer_t1: "500" ; Default 500 msec
timer_t2: "4000" ; Default 4 sec
sip_retx: "10" ; Default 11
sip_invite_retx: "6" ; Default 7
timer_invite_expires: "180" ; Default 180 sec

# Setting for Message speeddial to UOne box
messages_uri: "*97"

# TFTP Phone Specific Configuration File Directory
tftp_cfg_dir: "./"
# Time Server
sntp_mode: "unicast"
sntp_server: "ntp2.usno.navy.mil" # IP address here alternatively
time_zone: "EST"
dst_offset: "1"
dst_start_month: "April"
dst_start_day: ""
dst_start_day_of_week: "Sun"
dst_start_week_of_month: "1"
dst_start_time: "02"
dst_stop_month: "Oct"
dst_stop_day: ""
dst_stop_day_of_week: "Sunday"
dst_stop_week_of_month: "8"
dst_stop_time: "2"
dst_auto_adjust: "1"

# Do Not Disturb Control (0-off, 1-on, 2-off with no user control, 3-on with no user control)
dnd_control: "0" ; Default 0 (Do Not Disturb feature is off)

# Caller ID Blocking (0-disabled, 1-enabled, 2-disabled no user control, 3-enabled no user control)
callerid_blocking: "0" ; Default 0 (Disable sending all calls as anonymous)

# Anonymous Call Blocking (0-disbaled, 1-enabled, 2-disabled no user control, 3-enabled no user control)
anonymous_call_block: "0" ; Default 0 (Disable blocking of anonymous calls)

# Call Waiting (0-disabled, 1-enabled, 2-disabled with no user control, 3-enabled with no user control)
call_waiting: "1" ; Default 1 (Call Waiting enabled)

# DTMF AVT Payload (Dynamic payload range for AVT tones - 96-127)
dtmf_avt_payload: "101" ; Default 100

# XML file that specifies the dialplan desired
dial_template: "dialplan"

# Network Media Type (auto, full100, full10, half100, half10)
network_media_type: "auto"

#Autocompletion During Dial (0-off, 1-on [default])
autocomplete: "0"

#Time Format (0-12hr, 1-24hr [default])
time_format_24hr: "1"

# URL for external Phone Services
services_url: "" # IP address here alternatively

# URL for external Directory location
directory_url: "" # IP address here alternatively

# URL for branding logo
logo_url: "" # IP address here alternatively

# Remote Party ID
remote_party_id: 1 ; 0-Disabled (default), 1-Enabled

and
XmlDefault.cnf.xml

<Default>
<callManagerGroup>
    <members>
       <member priority="0">
          <callManager>
             <ports>
                <ethernetPhonePort>2000</ethernetPhonePort>
                <mgcpPorts>
                   <listen>2427</listen>
                   <keepAlive>2428</keepAlive>
                </mgcpPorts>
             </ports>
             <processNodeName></processNodeName>
          </callManager>
       </member>
    </members>
 </callManagerGroup>
<loadInformation30018 model="IP Phone 7961">P0S3-08-6-00</loadInformation30018>
<loadInformation308 model="IP Phone 7961G-GE">P0S3-08-6-00</loadInformation308>
<authenticationURL></authenticationURL>
<directoryURL></directoryURL>
<idleURL></idleURL>
<informationURL></informationURL>
<messagesURL></messagesURL>
<servicesURL></servicesURL>
</Default>

This should be all the examples and information that you need to get going with your Cisco 7961(|G|GE) phone. Simplicity at it’s finest, eh Cisco?

UPDATE (3/11/12): Thanks to Ken Alker for letting me know that natEnabled now only accepts true/false and no longer 1/0. I’ve updated it on the page.

Asterisk Echo Cancellation

I was lucky (or unlucky) enough to have to rebuild my company’s Asterisk server to prepare to have a backup. I took a slightly less powerful machine, installed Debian Etch on it and threw Asterisk 1.2.13 on it. The goal was to mimic the Asterisk configuration on its sister machine which was a Gentoo 1.2.10 install (eventually to be upgraded to 1.4.4). The FXO cards in both machines are exactly the same. They are the TDM400P. Everything went smoothly except when I got the computer in place, the echo that came in was unbearable.

This brings me to the topic title. There is a lot of information that one needs to know to be good at this. And like usual, I didn’t have time to get to it all. Therefore I will show a summary of commands and tasks and provide you with a few links that helped me out. Long story short, read the docs so you don’t completely mess everything up.

It should also be noted that the config files that some of these options reside in may differ slightly depending on your configuration.

One of the first things that should be done is to run fxotune. Ensure Asterisk isn’t running when you run this and beware because it took approximately 20mins to run on my P4 2.8GHz w/ 256M RAM. Run it using the following command:

fxotune -i 4

The eventual result came out to be below in my /etc/fxotune.conf. Just be sure that run

fxotune -s

before starting Asterisk so your settings get used.

1=8,0,0,0,0,0,0,0,0
2=6,0,0,0,0,0,0,0,0
3=6,0,0,0,0,0,0,0,0
4=6,0,0,0,0,0,0,0,0

That did a good job, but it just wasn’t where it needed to be yet. The next thing I did should have been the first thing I did. Ensure all the telephone wires are as short as possible (while still being long enough to serve their purpose) and are away from all sources of power. This helped with the slight hum I would hear on some calls (this whole scenario is scary to me and thankfully it will be fixed shortly).

Next I moved on to the echo cancellation internals that Asterisk has. First, in the phone.conf, I changed the variable echocancel to high. Obviously, you should step through the possible values incrementally, but mine was already set on medium, so high was the next logical value.

Most of the work was done here in the zapata.conf file. The first value that I tinkered with here is the echocancel (same name as in the phone.conf file). It was initially set to yes which means that Asterisk automatically defaults to a value of 128 taps. Knowing that this variable has to be a power of 2, I decided to have some fun. I started at 2 and went straight up through 256. As it turned out, 64 ended up being the best. They say it is impossible to hear with the normal ear, but there was enough of a difference that I was able to discern which sounded better. Sometimes I couldn’t hear a difference at all (which is what I assume the docs were referencing), but as soon as I heard the difference between 64 and 128, I left it at 64. The last variable I toyed with was echotraining. echotraining was off initially. I tried calls with it on and off and there was a significant difference in initial call quality when echotraining was on. If these didn’t work, I would have messed with the value of the jitterbuffers. However, it is sufficient at 10 because of the small amount of memory that this machine has.

Eventually, once I have more time (and all sysadmins know this is a rarity), I want to move on to adjusting the rxgain/txgain. More information on this can be found here. I didn’t have a need for it now since I have reached what is believed to be tolerable. But ultimately I don’t want to have to deal with this again and I want to finish the job.

Hope this allows at least one person to have a one stop shop for information on echo cancellation and can save them a long night or headache.

References: