Monday, March 19, 2012

How to set the concurrent calls limit on SIP trunk in Asterisk?

Have you ever wanted to setup the concurrent calls limit on SIP trunk in Asterisk System? Ok, then you are in the right place to find your answers.


Scenario:

Suppose Server2 is from third party and we don't have a control over it. So, it can send any amount of calls to Server1. Our job is to limit the number of concurrent calls from Server2 to Server1. Thus, we will be working on Server1 to achieve our goal.


Method1:

If you are using Asterisk system, you might have already known that SIP Peer is also know as SIP trunk.
There is an easy way to set it up in SIP trunk/peer configuration using call-limit parameter.  (Warning!! This parameter is deprecated and Asterisk strongly discourages to use it)

#vi sip.conf
   context=mydefaultContext

   [SIPTrunkFORserver2]
   type=peer
   fromdomain=server1_IP_add
   host=server2_IP_add
   outboundproxy=server2_IP_add
   call-limit=100    
;Here I am limiting to 100 max concurrent calls thru' this trunk 
   context=FromServer2Trunk   
;Call from this trunk lands to [FromServer2Trunk] context

Pros: It's easy to implement
Cons: It's deprecated parameter, so it may not be available in future versions of Asterisk. (Luckily it is available in 1.8). I found that it requires Asterisk Restart when you want to remove call-limit parameter.


Method2 (preferred):

Looking at cons of using call-limit, I decided not to use it even though I found it to be really easy implementation. Similar goal can be achieved via the use of GROUP() and GROUP-COUNT() functions available in Asterisk Dialplan. You don't have to make any adjustments on SIP Trunk configuration for call limit (which  is good thing).

GROUP() function defines the trunk group
GROUP_COUNT() function returns the number of concurrent calls on the given trunk group


#vi sip.conf
#SIP configuration on Server1
   context=mydefaultContext

   [SIPTrunkFORserver2]
   type=peer
   fromdomain=server1_IP_add
   host=server2_IP_add
   outboundproxy=server2_IP_add
   call-limit=100    
   context=FromServer2Trunk   
;Call from this trunk lands to [FromServer2Trunk] context
 We are directing the call from server2 to [FromServer2Trunk] context in our dialplan.

#vi extensions.conf
#Asterisk dialplan on Server1

   [FromServer2Trunk]
   exten => _X.,1,Verbose(1,***** Server2  dialing ${EXTEN} *******)
        same => n,Set(GROUP()=server2Trunkgroup)
        same => n,Verbose(1,**** Number of concurrent calls are ${GROUP_COUNT(server2Trunkgroup)})
        same => n,GotoIf($[${GROUP_COUNT(server2Trunkgroup)} > 100]?999)
        same => n,Dial(SIP/telco/${EXTEN})

        same => 999,Verbose(1,***Number of concurrent calls are ${GROUP_COUNT(server2Trunkgroup)}  over limit)
        same => n,Set(DIALSTATUS=CHANUNAVAIL)

Since we are directing only the calls from Server2 to [FromServer2Trunk] context in our dialplan in Server1, we can safely use GROUP() function to define the name of the trunk group associated with the incoming calls from Server2. I named it as server2Trunkgroup

Now we can use GROUP_COUNT(server2Trunkgroup) to count the number of concurrent-calls flowing in to Server1 from Server2. We can use GotoIf statement to compare the concurrent calls with threshold value (say 100 in my case). If number of concurrent calls are less than threshold value, accept the call, otherwise drop the call with channel status: CHANUNAVAIL. 

You can implement more sophisticated logic to achieve your goal. 
I hope this helped you. Good Luck!

Thursday, March 15, 2012

Asterisk Stress testing using SIPp : Asterisk Dimensioning and Benchmarking


Tool:
SIPp is performance testing tool for SIP based protocol. It's open source and quite easy to start with.
Detailed documentation from SIPp: http://sipp.sourceforge.net/doc1.1/reference.htm

SIPp Installation on SuSE Linux:
(This installation process should work with other linux flavors too)

Option1: Install SIPp standard using available SIPp RPM package

Option2 (Preferred): Install SIPp from source
  • Go to http://sipp.sourceforge.net/index.html
  • Go to Download & then to Stable
  • Browse SIPP folder
  • Browse the latest SIPP version; You will see various installation files.
  • Download sip.svn.tar.gz (source) file: preferably download at /opt/SIPp folder
  • Unzip it  #tar xvzf sipp.svn.tar.gz : Say it is unzipped in sipp.svn folder
Note: Before installing it, check the dependencies. You can try to install without checking the dependencies. It’s all up to you
    • C++ compiler
    • Curses or ncurses library (for graphics in text mode)
    • OpenSSL , OpenSSL-devel  : For authentication and TLS support
    • Libpcap, libpcap-devel (don’t confuse it with libcap-devel), libnet : For pcap play support
(you might have to install libnet-devel, if you run across an error while installing SIPp)
  • Go to sip.svn folder where you extracted the tar file.  
           Run #make pcapplay_ossl    (This will install sipp; and also enable PCAP play and authentication for SIPp. sipp executable is located in the same location where you ran make command.)

Application: 
Test Scenario:
SIPp will make  test calls to Asterisk. Asterisk will answer the call and play an audio file/MOH back to the SIPp

Step1:Asterisk server configuration to allow calls from SIPp
    • Write an appropriate dialplan to handle calls from SIPp. Dialplan for Asterisk resides at /etc/asterisk/extensions.conf
Let’s configure extension 44444 in our dialplan to play 30 seconds audio file and extension 55555 to play music on hold.

[for_everyone]
exten => 44444,1,Answer
      same => n,Verbose(1,### PERFORMING SIPP TEST #######)
       same => n,SetMusicOnHold(default)
       same => n,WaitMusicOnHold(30)
       same => n,Hangup

exten => 55555,1,Answer
      same => n,Verbose(1,### PERFORMING SIPP TEST #######)
      same => n,Background(en/audiofile-20-sec)
      same => n,Hangup

    • In sip.conf define the host of SIPp as a peer OR you can simply define default context for any unknown peers/users. In my case it is [for_everyone]

    • Increase the number of file descriptors (FDs) ie. “Max number of open files” using ulimit command to allow asterisk to handle more than 200 concurrent calls
#ulimit –n     
(default value is 1024)
#ulimit –n 20000
#ulimit –n
   20000
(Warning! This is a temporary way to increase the number of FDs and it is local to individual session. ulimit command only affects the current shell environment.)


To increase FDs permanently, go to /etc/security/limits.conf
root             soft   nofile          20000
root             hard   nofile          25000

Reboot your system and check the limits
#ulimit –n    It returns SOFT limit 
#ulimit –n –H   It return HARD limit 

    • You also have to use ‘ulimit –n <number of FDs>’ in asterisk startup script
#vi /etc/init.d/asterisk
                -------
                ---------
                                                ulimit –n 20000
                                                /usr/sbin/asterisk


It is always a good idea to check if your asterisk process is really using the ulimit specified by you or not. You can check that by looking into the process itself.  Check the field ‘Max Open Files’.
                #cat /proc/`pidof asterisk`/limits
Note:  `pidof asterisk` returns PID(Process ID) of asterisk

      Step2: Stress Test using SIPp
  • Go to the installation folder: In my case /opt/SIPp/sipp.svn
  • Run an appropriate command that meets your test requirement

    • SIPp command line help
#./sipp –h |less
                Handy switches of SIPp command line:
                -sn                                          : Scenario e.g uac, uas
                -sf                                           : Open customized scenario; usually XML file
                -d                                            : Duration of each call (in milliseconds)
                -s                                            : Extension to dial
                -l                                             : Call limit (Maximum concurrent calls)
                -r                                             : Calling rate (calls/sec)
                -trace_err                               : Enable error tracing
                -error_file  filename             : Dump error in specified file


    • Run SIPp as a UAC to make a stress test on SIP/Asterisk server with IP 192.168.1.10.  Set calling rate of 10 calls/sec with call limit 100. Also enable error trace and log the error
#./sipp -sn uac -d 20000 -s 44444 asteriskserverIPaddres -l 100 -r 10  -trace_err -error_file sipperror

Note: If you perform packet capture on SIP/Asterisk server, you will not see RTP traffic. It’s because Asterisk doesn’t send one way RTP traffic. Asterisk RTP stack requires bidirectional traffic to send traffic back. (Some people say that there is a patch for Asterisk to support asynchronous RTP. But I didn’t bother to look for it as SIPp supports RTP echo and PCAP play. You can use either one for establishing two ways RTP. I am going to use PCAP play)




    • Run SIPp as a UAC to make a stress test on SIP/Asterisk server with IP 192.168.1.10.  Set calling rate of 10 calls/sec with call limit 100. Also enable error trace and log the error. Please make sure that RTP traffic is flowing.
For RTP traffic, I am going to use uac_pcap.xml scenario file provided in SIPp documentation.
I have downloaded the xml file at /opt/SIPp/SIPpscenario

#./sipp -sf  /opt/SIPp/SIPpscenario uac_pcap.xml -d 20000 -s 44444 asteriskserverIPaddress -l 100 -r 10  -trace_err -error_file sipperror


Good luck!