SIPp
SIPp reference documentation
- Foreword
- Installation
-
Using SIPp
- Main features
- Integrated scenarios
- 3PCC Extended
- Controlling SIPp
- Running SIPp in background
- Create your own XML scenarios
- Screens
- Transport modes
- Handling media with SIPp
- Exit codes
- Statistics
- Error handling
- Online help (-h)
- Performance testing with SIPp
- Useful tools aside SIPp
- Getting support
- Contributing to SIPp
Foreword
SIPp is a performance testing tool for the SIP protocol. It includes a few basic SipStone user agent scenarios (UAC and UAS) and establishes and releases multiple calls with the INVITE and BYE methods. It can also reads XML scenario files describing any performance testing configuration. It features the dynamic display of statistics about running tests (call rate, round trip delay, and message statistics), periodic CSV statistics dumps, TCP and UDP over multiple sockets or multiplexed with retransmission management, regular expressions and variables in scenario files, and dynamically adjustable call rates.
SIPp can be used to test many real SIP equipements like SIP proxies, B2BUAs, SIP media servers, SIP/x gateways, SIP PBX, ... It is also very useful to emulate thousands of user agents calling your SIP system.
Want to see it?
Here is a screenshot

And here is a video (Windows Media Player 9 codec or above required) of SIPp in action:
Installation
Getting SIPp
SIPp is released under the GNU GPL license. All the terms of the license apply. It is provided to the SIP community by Hewlett-Packard engineers in hope it can be useful.
We receive some support from our company to work on this tool freely, but HP does not provide any support nor warranty concerning SIPp.
Stable release
Like many other "open source" projects, there are two versions of SIPp: a stable and unstable release. Stable release: before being labelled as "stable", a SIPp release is thoroughly tested. So you can be confident that all mentioned features will work :)
Unstable release
Unstable release: all new features and bug fixes are checked in SIPp's SVN repository as soon as they are available. Every night, an automatic extraction is done and the source code of this release is made available.
Available platforms
SIPp is available on almost all UNIX platforms: HPUX, Tru64, Linux (RedHat, Debian, FreeBSD), Solaris/SunOS.
A Windows port has been contributed. You can now compile SIPp under Cygwin. A binary package with a Windows installer is also available. Check the download page to download it and run SIPp under Windows.
Installing SIPp
- On Linux, SIPp is provided in the form of source code. You will need to compile SIPp to actually use it.
- Pre-requisites to compile SIPp are (see Compilation tips):
- C++ Compiler
- curses or ncurses library
- For authentication and TLS support: OpenSSL >= 0.9.8
- For pcap play support: libpcap and libnet
- For distributed pauses: Gnu Scientific Libraries
- You have four options to compile SIPp:
-
Without TLS (Transport Layer Security) and authentication support:
This is the recommended setup if you don't need to handle SIP authentication
and/or TLS. In this case, there are no depencies to install before
building SIPp. It is straight forward:
# gunzip sipp-xxx.tar.gz # tar -xvf sipp-xxx.tar # cd sipp # make
-
With TLS and authentication support, you must have
installed OpenSSL library (>=0.9.8)
(which may come with your system). Building SIPp consist only in adding
the "ossl" option to the make command:
# gunzip sipp-xxx.tar.gz # tar -xvf sipp-xxx.tar # cd sipp # make ossl
-
With PCAP play and without authentication support:
# gunzip sipp-xxx.tar.gz # tar -xvf sipp-xxx.tar # cd sipp # make pcapplay
-
With PCAP play and authentication support:
# gunzip sipp-xxx.tar.gz # tar -xvf sipp-xxx.tar # cd sipp # make pcapplay_ossl
-
Without TLS (Transport Layer Security) and authentication support:
This is the recommended setup if you don't need to handle SIP authentication
and/or TLS. In this case, there are no depencies to install before
building SIPp. It is straight forward:
- On Windows, SIPp is provided both with the source and the pre-compiled executable. Just execute the installer to have SIPp installed.
- To compile SIPp on Windows with pcap (media support), you must:
- Copy the WinPcap developer package to "C:\cygwin\lib\WpdPack"
- Remove or rename "pthread.h" in "C:\cygwin\lib\WpdPack\Include", as it interfers with pthread.h from cygwin
- Compile using either "make pcapplay_cygwin" or "pcapplay_ossl_cygwin"
Increasing File Descriptors Limit
If your system does not supports enough file descriptors, you may experience problems when using the TCP/TLS mode with many simultaneous calls.
You have two ways to overcome this limit: either use the -max_socket command line option or change the limits of your system.
Depending on the operating system you use, different procedures allow you to increase the maximum number of file descriptors:
-
On Linux 2.4 kernels the default number of file descriptors can be increased by modifying the /etc/security/limits.conf and the /etc/pam.d/login file.
Open the /etc/security/limits.conf file and add the following lines:
soft nofile 1024 hard nofile 65535
Open the /etc/pam.d/login and add the following line
session required /lib/security/pam_limits.so
The system file descriptor limit is set in the /proc/sys/fs/file-max file. The following command will increase the file descriptor limit:
echo 65535> /proc/sys/fs/file-max
To increase the number of file descriptors to its maximum limit (65535) set in the /etc/security/limits.conf file, type:
ulimit -n unlimited
Logout then login again to make the changes effective.
-
On HP-UX systems the default number of file descriptors can be increased by modifying the system configuration with the sam utility. In the Kernel Configuration menu, select Configurable parameters, and change the following attributes:
maxfiles : 4096 maxfiles_lim : 4096 nfiles : 4096 ninode : 4096 max_thread_proc : 4096 nkthread : 4096
Using SIPp
Main features
SIPp allows to generate one or many SIP calls to one remote system. The tool is started from the command line. In this example, two SIPp are started in front of each other to demonstrate SIPp capabilities.
Run sipp with embedded server (uas) scenario:
# ./sipp -sn uas
On the same host, run sipp with embedded client (uac) scenario
# ./sipp -sn uac 127.0.0.1
Integrated scenarios
Integrated scenarios? Yes, there are scenarios that are embedded in SIPp executable. While you can create your own custom SIP scenarios (see how to create your own XML scenarios), a few basic (yet useful) scenarios are available in SIPp executable.
UAC
Scenario file: uac.xml (original XML file)
SIPp UAC Remote
|(1) INVITE |
|------------------>|
|(2) 100 (optional) |
|<------------------|
|(3) 180 (optional) |
|<------------------|
|(4) 200 |
|<------------------|
|(5) ACK |
|------------------>|
| |
|(6) PAUSE |
| |
|(7) BYE |
|------------------>|
|(8) 200 |
|<------------------|
UAC with media
Scenario file: uac_pcap.xml (original XML file)
SIPp UAC Remote
|(1) INVITE |
|------------------>|
|(2) 100 (optional) |
|<------------------|
|(3) 180 (optional) |
|<------------------|
|(4) 200 |
|<------------------|
|(5) ACK |
|------------------>|
| |
|(6) RTP send (8s) |
|==================>|
| |
|(7) RFC2833 DIGIT 1|
|==================>|
| |
|(8) BYE |
|------------------>|
|(9) 200 |
|<------------------|
UAS
Scenario file: uas.xml (original XML file)
Remote SIPp UAS
|(1) INVITE |
|------------------>|
|(2) 180 |
|<------------------|
|(3) 200 |
|<------------------|
|(4) ACK |
|------------------>|
| |
|(5) PAUSE |
| |
|(6) BYE |
|------------------>|
|(7) 200 |
|<------------------|
regexp
Scenario file: regexp.xml (original XML file)
This scenario, which behaves as an UAC is explained in greater details in this section.
SIPp regexp Remote
|(1) INVITE |
|------------------>|
|(2) 100 (optional) |
|<------------------|
|(3) 180 (optional) |
|<------------------|
|(4) 200 |
|<------------------|
|(5) ACK |
|------------------>|
| |
|(6) PAUSE |
| |
|(7) BYE |
|------------------>|
|(8) 200 |
|<------------------|
branch
Scenario files: branchc.xml (original XML file) and branchs.xml (original XML file)
Those scenarios, which work against each other (branchc for client side and branchs for server side) are explained in greater details in this section.
REGISTER ---------->
200 <----------
200 <----------
INVITE ---------->
100 <----------
180 <----------
403 <----------
200 <----------
ACK ---------->
[ 5000 ms]
BYE ---------->
200 <----------
UAC Out-of-call Messages
Scenario file: ooc_default.xml (original XML file)
When a SIPp UAC receives an out-of-call request, it instantiates an out-of-call scenario. By default this scenario simply replies with a 200 OK response. This scenario can be overridden by passing the -oocsf or -oocsn command line options.
SIPp UAC Remote
|(1) .* |
|<------------------|
|(2) 200 |
|------------------>|
3PCC
3PCC stands for 3rd Party Call Control. 3PCC is described in RFC 3725. While this feature was first developped to allow 3PCC like scenarios, it can also be used for every case where you would need one SIPp to talk to several remotes.
In order to keep SIPp simple (remember, it's a test tool!), one SIPp instance can only talk to one remote. Which is an issue in 3PCC call flows, like call flow I (SIPp beeing a controller):
A Controller B
|(1) INVITE no SDP | |
|<------------------| |
|(2) 200 offer1 | |
|------------------>| |
| |(3) INVITE offer1 |
| |------------------>|
| |(4) 200 OK answer1 |
| |<------------------|
| |(5) ACK |
| |------------------>|
|(6) ACK answer1 | |
|<------------------| |
|(7) RTP | |
|.......................................|
Scenario file: 3pcc-A.xml (original XML file)
Scenario file: 3pcc-B.xml (original XML file)
Scenario file: 3pcc-C-A.xml (original XML file)
Scenario file: 3pcc-C-B.xml (original XML file)
The 3PCC feature in SIPp allows to have two SIPp instances launched and synchronised together. If we take the example of call flow I, one SIPp instance will take care of the dialog with remote A (this instance is called 3PCC-C-A for 3PCC-Controller-A-Side) and another SIPp instance will take care of the dialog with remote B (this instance is called 3PCC-C-B for 3PCC-Controller-B-Side).
The 3PCC call flow I will, in reality, look like this (Controller has been divided in two SIPp instances):
A Controller A Controller B B
|(1) INVITE no SDP | | |
|<------------------| | |
|(2) 200 offer1 | | |
|------------------>| | |
| sendCmd (offer1) | |
| |----------------->| |
| | recvCmd |
| | |(3) INVITE offer1 |
| | |------------------>|
| | |(4) 200 OK answer1 |
| | |<------------------|
| | sendCmd |
| | (answer1) | |
| |<-----------------| |
| recvCmd |(5) ACK |
| | |------------------>|
|(6) ACK answer1 | | |
|<------------------| | |
|(7) RTP | | |
|..........................................................|
As you can see, we need to pass information between both sides of the controller. SDP "offer1" is provided by A in message (2) and needs to be sent to B side in message (3). This mechanism is implemented in the scenarios through the <sendCmd> command. This:
<sendCmd>
<![CDATA[
Call-ID: [call_id]
[$1]
]]>
</sendCmd>
Will send a "command" to the twin SIPp instance. Note that including the Call-ID is mandatory in order to correlate the commands to actual calls. In the same manner, this:
<recvCmd>
<action
<ereg regexp="Content-Type:.*"
search_in="msg"
assign_to="2"/>
</action>
</recvCmd>
Will receive a "command" from the twin SIPp instance. Using the regular expression mechanism, the content is retrieved and stored in a call variable ($2 in this case), ready to be reinjected
<send>
<![CDATA[
ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port]
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]
To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
Call-ID: [call_id]
CSeq: 1 ACK
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 70
Subject: Performance Test
[$2]
]]>
</send>
In other words, sendCmd and recvCmd can be seen as synchronization points between two SIPp instances, with the ability to pass parameters between each other.
Another scenario that has been reported to be do-able with the 3PCC feature is the following:
- A calls B. B answers. B and A converse
- B calls C. C answers. C and B converse
- B "REFER"s A to C and asks to replace A-B call with B-C call.
- A accepts. A and C talk. B drops out of the calls.
3PCC Extended
An extension of the 3pcc mode is implemented in sipp. This feature allows n twin sipp instances to communicate each other, each one of them being connected to a remote host.
The sipp instance which initiates the call is launched in "master" mode. The others are launched in "slave" mode. Twin sipp instances have names, given in the command line (for example, s1, s2...sn for the slaves and m for the master) Correspondances between instances names and their addresses must be stored in a file (provided by -slave_cfg command line argument), in the following format:
s1;127.0.0.1:8080 s2;127.0.0.1:7080 m;127.0.0.1:6080
Each twin sipp instance must access a different copy of this file.
sendCmd and recvCmd have additional attributes:
<sendCmd dest="s1">
<![CDATA[
Call-ID: [call_id]
From: m
[$1]
]]>
</sendCmd>
Will send a command to the "s1" peer instance, which can be either master or slave, depending on the command line argument, which must be consistent with the scenario: a slave instance cannot have a sendCmd action before having any recvCmd. Note that the message must contain a "From" field, filled with the name of the sender.
<recvCmd src="m">
<action
<ereg regexp="Content-Type:.*"
search_in="msg"
assign_to="2"/>
</action>
</recvCmd>
Indicates that the twin command is expected to be received from the "m" peer instance.
Note that the master must be the launched at last.
There is no integrated scenarios for the 3pcc extended mode, but you can easily adapt those from 3pcc.
Example: the following drawing illustrate the entire procedure. The arrows that are
shown between SIPp master and slaves depict only the synchronization commands exchanged between
the different SIPp instances. The SIP message exchange takes place as usual.
Controlling SIPp
SIPp can be controlled interactively through the keyboard or via a UDP socket. SIPp supports both 'hot' keys that can be entered at any time and also a simple command mode. The hot keys are:
| Key | Action |
|---|---|
| + | Increase the call rate by 1 * rate_scale |
| * | Increase the call rate by 10 * rate_scale |
| - | Decrease the call rate by 1 * rate_scale |
| / | Decrease the call rate by 10 * rate_scale |
| c | Enter command mode |
| q | Quit SIPp (after all calls complete, enter a second time to quit immediately) |
| Q | Quit SIPp immediately |
| s | Dump screens to the log file (if -trace_screen is passed) |
| p | Pause traffic |
| 1 | Display the scenario screen |
| 2 | Display the statistics screen |
| 3 | Display the repartition screen |
| 4 | Display the variable screen |
| 5 | Display the TDM screen |
| 6-9 | Display the second tdrough fifth repartition screen. |
In command mode, you can type a single line command that instructs SIPp to take some action. Command mode is more versatile than the hot keys, but takes more time to input some common actions. The following commands are available:
List of Interactive Commands
| Command | Description | Example |
|---|---|---|
| dump tasks | Prints a list of active tasks (most tasks are calls) to the error log. | dump tasks |
| set rate X | Sets the call rate. | set rate 10 |
| set rate-scale X | Sets the rate scale, which adjusts the speed of '+', '-', '*', and '/'. | set rate-scale 10 |
| set users X | Sets the number of users (only valid when -users is specified). | set rate 10 |
| set limit X | Sets the open call limit (equivalent to -l option) | set limit 100 |
| set hide <true|false> | Should the hide XML attribute be respected? | set hide false |
| set index <true|false> | Display message indexes in the scenario screen. | set index true |
| set display <main|ooc> | Changes the scenario that is displayed to either the main or the out-of-call scenario. | set display main
set display ooc |
| trace <log> <on|off> | Turns | trace error on |
Traffic control
SIPp generates SIP traffic according to the scenario specified. You can control the number of calls (scenario) that are started per second. If you pass the -users option, then you need to control the number of instantiated users. You can control the rate through:
- Interactive hot keys (described in the previous section)
- Interactive Commands
- Startup Parameters
There are two commands that control rates: set rate X sets the current call rate to X. Additionally, set rate-scale X sets the rate_scale parameter to X. This enables you to use the '+', '-', '*', and '/' keys to set the rate more quickly. For example, if you do set rate-scale 100, then each time you press '+', the call rate is increased by 100 calls and each time you press '*', the call rate is increased by 1000 calls. Similarly, for a user based benchmark you can run set users X.
At starting time, you can control the rate by specifying parameters on the command line:
- "-r" to specify the call rate in number of calls per seconds
- "-rp" to specify the "rate period"
in milliseconds for the call rate (default is 1000ms/1sec).
This allows you to have n calls every m milliseconds (by using -r n -rp m).
./sipp -sn uac -r 7 -rp 2000 127.0.0.1
You can also pause the traffic by pressing the 'p' key. SIPp will stop placing new calls and wait until all current calls go to their end. You can resume the traffic by pressing 'p' again.
To quit SIPp, press the 'q' key. SIPp will stop placing new calls and wait until all current calls go to their end. SIPp will then exit.
You can also force SIPp to quit immediatly by pressing the 'Q' key. Current calls will be terminated by sending a BYE or CANCEL message (depending if the calls have been established or not). The same behaviour is obtained by pressing 'q' twice.
Remote control
SIPp can be "remote-controlled" through a UDP socket. This allows for example
- To automate a series of actions, like increasing the call rate smoothly, wait for 10 seconds, increase more, wait for 1 minute and loop
- Have a feedback loop so that an application under test can remote control SIPp to lower the load, pause the traffic, ...
Each SIPp instance is listening to a UDP socket. It starts to listen to port 8888 and each following SIPp instance (up to 60) will listen to base_port + 1 (8889, 8890, ...).
It is then possible to control SIPp like this:
echo p >/dev/udp/x.y.z.t/8888 -> put SIPp in pause state (p key) echo q >/dev/udp/x.y.z.t/8888 -> quit SIPp (q key)
You could also have a small shell script to automate a serie of action. For example, this script will increase the call rate by 10 more new calls/s every 5 seconds, wait at this call rate for one minute and exit SIPp:
#!/bin/sh echo "*" >/dev/udp/127.0.0.1/8889 sleep 5 echo "*" >/dev/udp/127.0.0.1/8889 sleep 5 echo "*" >/dev/udp/127.0.0.1/8889 sleep 5 echo "*" >/dev/udp/127.0.0.1/8889 sleep 60 echo "q" >/dev/udp/127.0.0.1/8889
To send a command to SIPp, preface it with 'c'. For example: echo "cset rate 100" >/dev/udp/127.0.0.1/8888 sets the call rate to 100.
Running SIPp in background
SIPp can be launched in background mode (-bg command line option).
By doing so, SIPp will be detached from the current terminal and run in the background. The PID of the SIPp process is provided. If you didn't specify a number of calls to execute with the -m option, SIPp will run forever.
There is a mechanism implemented to stop SIPp smoothly. The command kill -SIGUSR1 [SIPp_PID] will instruct SIPp to stop placing any new calls and finish all ongoing calls before exiting.
When using the background mode, the main sipp instance stops and a child process will continue the job. Therefore, the log files names will contain another PID than the actual sipp instance PID.
Create your own XML scenarios
Of course embedded scenarios will not be enough. So it's time to create your own scenarios. A SIPp scenario is written in XML (a DTD that may help you write SIPp scenarios does exist and has been tested with jEdit - this is described in a later section). A scenario will always start with:
<?xml version="1.0" encoding="ISO-8859-1" ?> <scenario name="Basic Sipstone UAC">
And end with:
</scenario>
Easy, huh? Ok, now let's see what can be put inside. You are not obliged to read the whole table now! Just go in the next section for an example.
List of commands with their attributes
| Command | Attribute(s) | Description | Example |
|---|---|---|---|
| <send> | retrans | Used for UDP transport only: it specifies the T1 timer value, as described in SIP RFC 3261, section 17.1.1.2. | <send retrans="500">: will initiate T1 timer to 500 milliseconds (RFC3261 default). |
| start_rtd | Starts one of the 5 "Response Time Duration" timer. (see statistics section). | <send start_rtd="2">: the timer number 2 will start when the message is sent. | |
| rtd | Stops one of the 5 "Response Time Duration" timer. | <send rtd="2">: the timer number 2 will stop when the message is sent. | |
| repeat_rtd | Used with a rtd attribute, it allows the corresponding "Response Time Duration" timer to be counted more than once per call (useful for loop call flows). | <send rtd="1" repeat_rtd="true">: the timer number 1 value will be printed but the timer won't stop. | |
| crlf | Displays an empty line after the arrow for the message in main SIPp screen. | <send crlf="true"> | |
| lost | Emulate packet lost. The value is specified as a percentage. | <send lost="10">: 10% of the message sent are actually not sent :). | |
| next | You can put a "next" in a send to go to another part of the script when you are done with sending the message. See conditional branching section for more info. | Example to jump to label "12" after sending an ACK: <send next="12">
<![CDATA[
ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
Via: ...
From: ...
To: ...
Call-ID: ...
Cseq: ...
Contact: ...
Max-Forwards: ...
Subject: ...
Content-Length: 0
]]>
</send>
|
|
| test | You can put a "test" next to a "next" attribute to indicate that you only want to branch to the label specified with "next" if the variable specified in "test" is set (through regexp for example). See conditional branching section for more info. | Example to jump to label "6" after sending an ACK only if
variable 4 is set: <send next="6" test="4">
<![CDATA[
ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
Via: ...
From: ...
To: ...
Call-ID: ...
Cseq: ...
Contact: ...
Max-Forwards: ...
Subject: ...
Content-Length: 0
]]>
</send>
|
|
| counter | Increments the counter given as parameter when the message is sent. A total of 5 counter can be used. The counter are saved in the statistic file. | <send counter="1">: Increments counter #1 when the message is sent. | |
| start_txn | Records the branch ID of this sent message so that responses can be properly matched (without this element the transaction matching is done based on the CSeq method, which is imprecise). | <send start_txn="invite">: Stores the branch ID of this message in the transaction named "invite". | |
| <recv> | response | Indicates what SIP message code is expected. | <recv response="200">: SIPp will expect a SIP message with code "200". |
| request | Indicates what SIP message request is expected. | <recv request="ACK">: SIPp will expect an "ACK" SIP message. | |
| optional | Indicates if the message to receive is optional. In case of an optional
message and if the message is actually received, it is not seen as a unexpected message.
When an unexpected message is received, Sipp looks if this message matches an optional message defined in the previous step of the scenario. If optional is set to "global", Sipp will look every previous steps of the scenario. | <recv response="100" optional="true">: The 100 SIP message can be received without being considered as "unexpected". | |
| crlf | Displays an empty line after the arrow for the message in main SIPp screen. | <recv crlf="true"> | |
| rrs | Record Route Set. if this attribute is set to "true", then the "Record-Route:" header of the message received is stored and can be recalled using the [routes] keyword. | <recv response="100" rrs="true">. | |
| auth | Authentication. if this attribute is set to "true", then the "Proxy-Authenticate:" header of the message received is stored and is used to build the [authentication] keyword. | <recv response="407" auth="true">. | |
| start_rtd | Starts one of the 5 "Response Time Duration" timer. (see statistics section). | <recv start_rtd="4">: the timer number 4 will start when the message is received. | |
| rtd | Stops one of the 5 "Response Time Duration" timer. | <recv rtd="4">: the timer number 4 will stop when the message is received. | |
| repeat_rtd | Used with a rtd attribute, it allows the corresponding "Response Time Duration" timer to be counted more than once per call (useful for loop call flows). | <recv rtd="1" repeat_rtd="true">: the timer number 1 value will be printed but the timer won't stop. | |
| lost | Emulate packet lost. The value is specified as a percentage. | <recv lost="10">: 10% of the message received are thrown away. | |
| timeout | Specify a timeout while waiting for a message. If the message is not received, the call is aborted, unless an ontimeout label is defined. | <recv timeout="100000"> | |
| ontimeout | Specify a label to jump to if the timeout popped before the message to be received. | Example to jump to label "5" when not receiving a 100 message after 100 seconds:<recv response="100" timeout="100000" ontimeout="5"> </recv> |
|
| action | Specify an action when receiving the message. See Actions section for possible actions. | Example of a "regular expression" action:<recv response="200">
<action>
<ereg regexp="([0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]*"
search_in="msg"
check_it="true"
assign_to="1,2"/>
</action>
</recv>
|
|
| next | You can put a "next" in an optional receive to go to another part of the script if you receive that message. See conditional branching section for more info. | Example to jump to label "5" when receiving a 403 message: <recv response="100"
optional="true">
</recv>
<recv response="180" optional="true">
</recv>
<recv response="403" optional="true" next="5">
</recv>
<recv response="200">
</recv>
|
|
| test | You can put a "test" in an optional receive to go to another part of the script if you receive that message only if the variable specified by "test" is set. See conditional branching section for more info. | Example to jump to label "5" when receiving a 403 message only if
variable 3 is set: <recv response="100"
optional="true">
</recv>
<recv response="180" optional="true">
</recv>
<recv response="403" optional="true" next="5" test="3">
</recv>
<recv response="200">
</recv>
|
|
| chance | In combination with "test", probability to actually branch to another part of the scenario. Chance can have a value between 0 (never) and 1 (always). See conditional branching section for more info. |
<recv response="403" optional="true" next="5" test="3" chance="0.90"> </recv>90% chance to go to label "5" if variable "3" is set. |
|
| counter | Increments the counter given as parameter when the message is received. A total of 5 counter can be used. The counter are saved in the statistic file. | <recv counter="1">: Increments counter #1 when the message is received. | |
| regexp_match | Boolean. Indicates if 'request' ('response' is not available) is given as a regular expression. If so, the recv command will match against the regular expression. This allows to catch several cases in the same receive command. | Example of a recv command that matches MESSAGE or PUBLISH or SUBSCRIBE requests:<recv request="MESSAGE|PUBLISH|SUBSCRIBE" crlf="true" regexp_match="true"> </recv> |
|
| response_txn | Indicates that this is a response to a transaction that was previously started. To match, the branch ID of the first via header must match the stored transaction ID. | <recv response="200" response_txn="invite" />: Matches only responses to the message sent with start_txn="invite" attribute. | |
| <pause> | milliseconds | Specify the pause delay, in milliseconds. When this delay is not set, the value of the -d command line parameter is used. | <pause milliseconds="5000"/>: pause the scenario for 5 seconds. |
| variable | Indicates which call variable to use to determine the length of the pause. | <pause variable="1" /> pauses for the number of milliseconds specified by call variable 1. | |
| distribution | Indicates which statistical distribution to use to determine the length of the pause. Without GSL, you may use uniform or fixed. With GSL, normal, exponential, gamma, lambda, lognormal, negbin, (negative binomial), pareto, and weibull are available. Depending on the distribution you select, you must also supply distribution specific parameters. |
The following examples show the various types of distributed pauses:
|
|
| crlf | Displays an empty line after the arrow for the message in main SIPp screen. | <pause crlf="true"> | |
| next | You can put a "next" in a pause to go to another part of the script when you are done with the pause. See conditional branching section for more info. | Example to jump to label "7" after pausing 4 seconds:<pause milliseconds="4000" next="7"/> |
|
| sanity_check | By default, statistically distributed pauses are sanity checked to ensure that their 99th percentile values are less than INT_MAX. Setting sanity_check to false disables this behavior. | <pause distribution="lognormal" mean="10" stdev="10" sanity_check="false"/> disables sanity checking of the lognormal distribution. | |
| <nop> | action | The nop command doesn't do anything at SIP level. It is only there to specify an action to execute. See Actions section for possible actions. | Execute the play_pcap_audio/video action:<nop>
<action>
<exec play_pcap_audio="pcap/g711a.pcap"/>
</action>
</nop>
|
| start_rtd | Starts one of the 5 "Response Time Duration" timer. (see statistics section). | <nop start_rtd="1">: the timer number 1 starts when nop is executed. | |
| rtd | Stops one of the 5 "Response Time Duration" timer. | <nop rtd="1">: the timer number 1 will stops when nop is executed. | |
| <sendCmd> | <![CDATA[]]> | Content to be sent to the twin 3PCC SIPp instance. The Call-ID must be included in the CDATA. In 3pcc extended mode, the From must be included to. |
<sendCmd>
<![CDATA[
Call-ID: [call_id]
[$1]
]]>
</sendCmd>
|
| dest | 3pcc extended mode only: the twin sipp instance which the command will be sent to | <sendCmd dest="s1">: the command will be sent to the "s1" twin instance | |
| <recvCmd> | action | Specify an action when receiving the command. See Actions section for possible actions. | Example of a "regular expression" to retrieve what has been send by a sendCmd command:<recvCmd>
<action
<ereg regexp="Content-Type:.*"
search_in="msg"
assign_to="2"/>
</action>
</recvCmd>
|
| src | 3pcc extended mode only: indicate the twin sipp instance which the command is expected to be received from | <recvCmd src = "s1">: the command will be expected to be received from the "s1" twin instance | |
| <label> | id | A label is used when you want to branch to specific parts in your scenarios. The "id" attribute is an integer where the maximum value is 19. See conditional branching section for more info. | Example: set label number 13:<label id="13"/> |
| <Response Time Repartition> | value | Specify the intervals, in milliseconds, used to distribute the values of response times. | <ResponseTimeRepartition value="10, 20, 30"/>: response time values are distributed between 0 and 10ms, 10 and 20ms, 20 and 30ms, 30 and beyond. |
| <Call Length Repartition> | value | Specify the intervals, in milliseconds, used to distribute the values of the call length measures. | <CallLengthRepartition value="10, 20, 30"/>: call length values are distributed between 0 and 10ms, 10 and 20ms, 20 and 30ms, 30 and beyond. |
There are not so many commands: send, recv, sendCmd, recvCmd, pause, ResponseTimeRepartition and CallLengthRepartition. To make things even clearer, nothing is better than an example...
Structure of client (UAC like) XML scenarios
A client scenario is a scenario that starts with a "send" command. So let's start:
<scenario name="Basic Sipstone UAC">
<send>
<![CDATA[
INVITE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port]
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]
To: sut <sip:[service]@[remote_ip]:[remote_port]>
Call-ID: [call_id]
Cseq: 1 INVITE
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 70
Subject: Performance Test
Content-Type: application/sdp
Content-Length: [len]
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
t=0 0
c=IN IP[media_ip_type] [media_ip]
m=audio [media_port] RTP/AVP 0
a=rtpmap:0 PCMU/8000
]]>
</send>
Inside the "send" command, you have to enclose your SIP message between the "<![CDATA" and the "]]>" tags. Everything between those tags is going to be sent toward the remote system. You may have noticed that there are strange keywords in the SIP message, like [service], [remote_ip], .... Those keywords are used to indicate to SIPp that it has to do something with it.
Here is the list:
Keyword list
| Keyword | Default | Description |
|---|---|---|
| [service] | service | Service field, as passed in the -s service_name |
| [remote_ip] | - | Remote IP address, as passed on the command line. |
| [remote_port] | 5060 | Remote IP port, as passed on the command line. You can add a computed offset [remote_port+3] to this value. |
| [transport] | UDP | Depending on the value of -t parameter, this will take the values "UDP" or "TCP". |
| [local_ip] | Primary host IP address | Will take the value of -i parameter. |
| [local_ip_type] | - | Depending on the address type of -i parameter (IPv4 or IPv6), local_ip_type will have value "4" for IPv4 and "6" for IPv6. |
| [local_port] | Chosen by the system | Will take the value of -p parameter. You can add a computed offset [local_port+3] to this value. |
| [len] | - | Computed length of the SIP body. To be used in "Content-Length" header. You can add a computed offset [len+3] to this value. |
| [call_number] | - | Index. The call_number starts from "1" and is incremented by 1 for each call. |
| [cseq] | - | Generates automatically the CSeq number. The initial value is 1 by default. It can be changed by using the -base_cseq command line option. |
| [call_id] | - | A call_id identifies a call and is generated by SIPp for each new call. In client mode, it is mandatory
to use the value generated by SIPp in the "Call-ID" header. Otherwise, SIPp will not recognise
the answer to the message sent as being part of an existing call. Note: [call_id] can be pre-pended with an arbitrary string using '///'. Example: Call-ID: ABCDEFGHIJ///[call_id] - it will still be recognized by SIPp as part of the same call. |
| [media_ip] | - | Depending on the value of -mi parameter, it is the local IP address for RTP echo. |
| [media_ip_type] | - | Depending on the address type of -mi parameter (IPv4 or IPv6), media_ip_type will have value "4" for IPv4 and "6" for IPv6. Useful to build the SDP independently of the media IP type. |
| [media_port] | - | Depending on the value of -mp parameter, it set the local RTP echo port number. Default is none. RTP/UDP packets received on that port are echoed to their sender. You can add a computed offset [media_port+3] to this value. |
| [auto_media_port] | - | Only for pcap. To make audio and video ports begin from the value of -mp parameter, and change for each call using a periodical system, modulo 10000 (which limits to 10000 concurrent RTP sessions for pcap_play) |
| [last_*] | - | The '[last_*]' keyword is replaced automatically by the specified header if it was present in the last message received (except if it was a retransmission). If the header was not present or if no message has been received, the '[last_*]' keyword is discarded, and all bytes until the end of the line are also discarded. If the specified header was present several times in the message, all occurences are concatenated (CRLF separated) to be used in place of the '[last_*]' keyword. |
| [field0-n file=<filename> line=<number>] | - | Used to inject values from an external CSV file. See "Injecting values from an external CSV during calls" section. The optional file and line parameters allow you to select which of the injection files specified on the command line to use and which line number from that file. |
| [timestamp] | - | The current time using the same format as error log messages. |
| [last_message] | - | The last received message. |
| [$n] | - | Used to inject the value of call variable number n. See "Actions" section |
| [authentication] | - | Used to put the authentication header. This field can have parameters, in the following form: [authentication username=myusername password=mypassword]. If no username is provided, the value from -s command line parameter (service) is used. If no password is provided, the value from -ap command line parameter is used. See "Authentication" section |
| [pid] | - | Provide the process ID (pid) of the main SIPp thread. |
| [routes] | - | If the "rrs" attribute in a recv command is set to "true", then the "Record-Route:" header of the message received is stored and can be recalled using the [routes] keyword |
| [next_url] | - | If the "rrs" attribute in a recv command is set to "true", then the [next_url] contains the contents of the Contact header (i.e within the '<' and '>' of Contact) |
| [branch] | - | Provide a branch value which is a concatenation of magic cookie
(z9hG4bK) + call number + message index in scenario. An offset (like [branch-N]) can be appended if you need to have the same branch value as a previous message. |
| [msg_index] | - | Provide the message number in the scenario. |
| [cseq] | - | Provides the CSeq value of the last request received. This value can be incremented (e.g. [cseq+1] adds 1 to the CSeq value of the last request). |
| [clock_tick] | - | Includes the internal SIPp clock tick value in the message. |
| [tdmmap] | - | Includes the tdm map values used by the call in the message (see -tdmmap option). |
| [fill] | - | Injects filler characters into the message. The length of the fill text is equal to the call variable stored in the variable=N parameter. By default the text is a sequence of X's, but can be controlled with the text="text" parameter. |
| [users] | - | If the -users command line option is specified, then this keyword contains the number of users that are currently instantiated. |
| [userid] | - | If the -users command line option is specified, then this keyword containst he integer identifier of the current user (starting at zero and ending at [users-1]). |
Now that the INVITE message is sent, SIPp can wait for an answer by using the "recv" command.
<recv response="100"> optional="true" </recv> <recv response="180"> optional="true" </recv> <recv response="200"> </recv>
100 and 180 messages are optional, and 200 is mandatory. In a "recv" sequence, there must be one mandatory message.
Now, let's send the ACK:
<send>
<![CDATA[
ACK sip:[service]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port]
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]
To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
Call-ID: [call_id]
Cseq: 1 ACK
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 70
Subject: Performance Test
Content-Length: 0
]]>
</send>
We can also insert a pause. The scenario will wait for 5 seconds at this point.
<pause milliseconds="5000"/>
And finish the call by sending a BYE and expecting the 200 OK:
<send retrans="500">
<![CDATA[
BYE sip:[service]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port]
From: sipp <sip:sipp@[local_ip]:[local_port]>;tag=[call_number]
To: sut <sip:[service]@[remote_ip]:[remote_port]>[peer_tag_param]
Call-ID: [call_id]
Cseq: 2 BYE
Contact: sip:sipp@[local_ip]:[local_port]
Max-Forwards: 70
Subject: Performance Test
Content-Length: 0
]]>
</send>
<recv response="200">
</recv>
And this is the end of the scenario:
</scenario>
Creating your own SIPp scenarios is not a big deal. If you want to see other examples, use the -sd parameter on the command line to display embedded scenarios.
Structure of server (UAS like) XML scenarios
A server scenario is a scenario that starts with a "recv" command. The syntax and the list of available commands is the same as for "client" scenarios.
But you are more likely to use [last_*] keywords in those server side scenarios. For example, a UAS example will look like:
<recv request="INVITE">
</recv>
<send>
<![CDATA[
SIP/2.0 180 Ringing
[last_Via:]
[last_From:]
[last_To:];tag=[call_number]
[last_Call-ID:]
[last_CSeq:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
Content-Length: 0
]]>
</send>
The answering message, 180 Ringing in this case, is built with the content of headers received in the INVITE message.
Actions
In a "recv" or "recvCmd" command, you have the possibility to execute an action. Several actions are available:
- Regular expressions (ereg)
- Log something in aa log file (log)
- Execute an external (system), internal (int_cmd) or pcap_play_audio/pcap_play_video command (exec)
- Manipulate double precision variables using arithmetic
- Assign string values to a variable
- Compare double precision variables
- Jump to a particular scenario index
- Store the current time into variables
- Lookup a key in an indexed injection file
- Verify Authorization credentials
Regular expressions
Using regular expressions in SIPp allows to
- Extract content of a SIP message or a SIP header and store it for future usage (called re-injection)
- Check that a part of a SIP message or of an header is matching an expected expression
Regular expressions used in SIPp are defined per Posix Extended standard (POSIX 1003.2). If you want to learn how to write regular expressions, I will recommend this regexp tutorial.
Here is the syntax of the regexp action:
regexp action syntax
| Keyword | Default | Description |
|---|---|---|
| regexp | None | Contains the regexp to use for matching the received message or header. MANDATORY. |
| search_in | msg | can have 2 values: "msg" (try to match against the entire message) or "hdr" (try to match against a specific SIP header). |
| header | None | Header to try to match against. Only used when the search_in tag is set to hdr. MANDATORY IF search_in is equal to hdr. |
| case_indep | false | To look for a header ignoring case . Only used when the search_in tag is set to hdr. |
| occurence | 1 | To find the nth occurence of a header. Only used when the search_in tag is set to hdr. |
| start_line | false | To look only at start of line. Only used when the search_in tag is set to hdr. |
| check_it | false | if set to true, the call is marked as failed if the regexp doesn't match. |
| assign_to | None | contain the variable id (integer) or a list of
variable id which will be used to store the
result(s) of the matching process between the regexp
and the message. Those variables can be re-used at
a later time either by using '[$n]' in the scenario
to inject the value of the variable in the messages or
by using the content of the variables for conditional
branching. The first variable in the variable list of
assign_to contains the entire regular
expression matching. The following variables contain the
sub-expressions matching. Example: <ereg regexp="o=([[:alnum:]]*) ([[:alnum:]]*) ([[:alnum:]]*)"
search_in="msg"
check_it=i"true"
assign_to="3,4,5,8"/>If the SIP message contains the line o=user1 53655765 2353687637 IN IP4 127.0.0.1variable 3 contains "o=user1 53655765 2353687637", variable 4 contains "user1", variable 5 contains "53655765" and variable 8 contains "2353687637". |
Note that you can have several regular expressions in one action.
The following example is used to:
- First action:
- Extract the first IPv4 address of the received SIP message
- Check that we could actually extract this IP address (otherwise call will be marked as failed)
- Assign the extracted IP address to call variables 1 and 2.
- Second action:
- Extract the Contact: header of the received SIP message
- Assign the extracted Contract: header to variable 6.
<recv response="200" start_rtd="true">
<action>
<ereg regexp="([0-9]{1,3}\.){3}[0-9]{1,3}:[0-9]*" search_in="msg" check_it="true" assign_to="1,2" />
<ereg regexp=".*" search_in="hdr" header="Contact:" check_it="true" assign_to="6" />
</action>
</recv>
Log a message
The "log" action allows you to customize your traces. Messages are printed in the <scenario file name>_<pid>_logs.log file. Any keyword is expanded to reflect the value actually used.
Example:
<recv request="INVITE" crlf="true" rrs="true">
<action>
<ereg regexp=".*" search_in="hdr" header="Some-New-Header:" assign_to="1" />
<log message="From is [last_From]. Custom header is [$1]"/>
</action>
</recv>
You can use the alternative "warning" action to log a message to SIPp's error log. For example:
<warning message="From is [last_From]. Custom header is [$1]"/>
Execute a command
The "exec" action allows you to execute "internal", "external", "play_pcap_audio" or "play_pcap_video" commands.
Internal commands
Internal commands (specified using int_cmd attribute) are stop_call, stop_gracefully (similar to pressing 'q'), stop_now (similar to ctrl+C).
Example that stops the execution of the script on receiving a 603 response:
<recv response="603" optional="true">
<action>
<exec int_cmd="stop_now"/>
</action>
</recv>
External commands
External commands (specified using command attribute) are anything that can be executed on local host with a shell.
Example that execute a system echo for every INVITE received:
<recv request="INVITE">
<action>
<exec command="echo [last_From] is the from header received >> from_list.log"/>
</action>
</recv>
PCAP (media) commands
PCAP play commands (specified using play_pcap_audio / play_pcap_video attributes) allow you to send a pre-recorded RTP stream using the pcap library.
Choose play_pcap_audio to send the pre-recorded RTP stream using the "m=audio" SIP/SDP line port as a base for the replay.
Choose play_pcap_video to send the pre-recorded RTP stream using the "m=video" SIP/SDP line port as a base.
The play_pcap_audio/video command has the following format: play_pcap_audio="[file_to_play]" with:
- file_to_play: the pre-recorded pcap file to play
Example that plays a pre-recorded RTP stream:
<nop>
<action>
<exec play_pcap_audio="pcap/g711a.pcap"/>
</action>
</nop>
Variable Manipulation
You may also perform simple arithmetic (add, subtract, multiply, divide) on floating point values. The "assign_to" attribute contains the first operand, and is also the destination of the resulting value. The second operand is either an immediate value or stored in a variable, represented by the "value" and "variable" attributes, respectively.
SIPp supports call variables that take on double-precision floating values. The actions that modify double variables all write to the variable referenced by the assign_to parameter. These variables can be assigned using one of three actions: assign, sample, or todouble. For assign, the double precision value is stored in the "value" parameter. The sample action assigns values based on statistical distributions, and uses the same parameters as a statistically distributed pauses. Finally, the todouble command converts the variable referenced by the "variable" attribute to a double before assigning it.
For example, to assign the value 1.0 to $1 and sample from the normal distribution into $2:
<nop>
<action>
<assign assign_to="1" value="1" />
<sample assign_to="2" distribution="normal" mean="0" stdev="1"/>
<!-- Stores the first field in the injection file into string variable $3.
You may also use regular expressions to store string variables. -->
<assignstr assign_to="3" value="[field0]" />
<!-- Converts the string value in $3 to a double-precision value stored in $4. -->
<todouble assign_to="4" variable="3" />
</action>
</nop>
Simple arithmetic is also possible using the <add>, <subtract>, <multiply>, and <divide> actions, which add, subtract, multiply, and divide the variable referenced by assign_to by the value in value. For example, the following action modifies variable one as follows:
<nop>
<action>
<assign assign_to="1" value="0" /> <!-- $1 == 0 -->
<add assign_to="1" value="2" /> <!-- $1 == 2 -->
<subtract assign_to="1" value="3" /> <!-- $1 == -1 -->
<multiply assign_to="1" value="4" /> <!-- $1 == -4 -->
<divide assign_to="1" value="5" /> <!-- $1 == -0.8 -->
</action>
Rather than using fixed values, you may also retrieve the second operand from a variable, using the <variable> parameter. For example:
<nop>
<action>
<!-- Multiplies $1 by itself -->
<multiply assign_to="1" variable="1" />
<!-- Divides $1 by $2, Note that $2 must not be zero -->
<multiply assign_to="1" variable="2" />
</action>
</nop>
String Variables
You can create string variables by using the <assignstr> command, which accepts two parameters: assign_to and value. The value may contain any of the same substitutions that a message can contain. For example:
<nop>
<action>
<!-- Assign the value in field0 of the CSV file to a $1. -->
<assignstr assign_to="1" value="[field0]" />
</action>
</nop>
Variable Testing
Variable testing allows you to construct loops and control structures using call variables. THe test action takes four arguments: variable which is the variable that to compare against value, and assign_to which is a boolean call variable that the result of the test is stored in. Compare may be one of the following tests: equal, not_equal, greater_than, less_than, greater_than_equal, or less_than_equal.
Example that sets $2 to true if $1 is less than 10:
<nop>
<action>
<test assign_to="2" variable="1" compare="less_than" value="10" />
</action>
</nop>
Jumping to an Index
You can jump to an arbitrary scenario index using the <jump> action. This can be used to create rudimentary subroutines. The caller can save their index using the [msg_index] substitution, and the callee can jump back to the same place using this action. If there is a special label named "_unexp.main" in the scenario, SIPp will jump to that label whenever an unexpected message is received and store the previous address in the variable named "_unexp.retaddr".
Example that jumps to index 5:
<nop>
<action>
<jump value="5" />
</action>
</nop>
Example that jumps to the index contained in the variable named _unexp.retaddr:
<nop>
<action>
<jump variable="_unexp.retaddr" />
</action>
</nop>
gettimeofday
The gettimeofday action allows you to get the current time in seconds and microseconds since the epoch. For example:
<nop>
<action>
<gettimeofday assign_to="seconds,microseconds" />
</action>
</nop>
lookup
The lookup action is used for indexed injection files (see indexed injection files). The lookup action takes a file and key as input and produces an integer line number as output. For example the following action extracts the username from an authorization header and uses it to find the corresponding line in users.csv.
<recv request="REGISTER">
<action>
<ereg regexp="Digest .*username=\"([^\"]*)\"" search_in="hdr" header="Authorization:" assign_to="junk,username" />
<lookup assign_to="line" file="users.csv" key="[$username]" />
</action>
</nop>
verifyauth
The verifyauth action checks the Authorization header in an incoming message against a provided username and password. The result of the check is stored in a boolean variable. This allows you to simulate a server which requires authorization. Currently only simple MD5 digest authentication is supported. Before using the verifyauth action, you must send a challenge. For example:
<recv request="REGISTER" />
<send><![CDATA[
SIP/2.0 401 Authorization Required
[last_Via:]
[last_From:]
[last_To:];tag=[pid]SIPpTag01[call_number]
[last_Call-ID:]
[last_CSeq:]
Contact: <sip:[local_ip]:[local_port];transport=[transport]>
WWW-Authenticate: Digest realm="test.example.com", nonce="47ebe028cda119c35d4877b383027d28da013815"
Content-Length: [len]
]]>
</send>
After receiving the second request, you can extract the username provided and compare it against a list of user names and passwords provided as an injection file, and take the appropriate action based on the result:
<recv request="REGISTER" />
<action>
<ereg regexp="Digest .*username=\"([^\"]*)\"" search_in="hdr" header="Authorization:" assign_to="junk,username" />
<lookup assign_to="line" file="users.conf" key="[$username]" />
<verifyauth assign_to="authvalid" username="[field0 line=\"[$line]\"]" password="[field3 line=\"[$line]\"]" />
</action>
</recv>
<nop hide="true" test="authvalid" next="goodauth" />
<nop hide="true" next="badauth" />
Injecting values from an external CSV during calls
You can use "-inf file_name" as a command line parameter to input values into the scenarios. The first line of the file should say whether the data is to be read in sequence (SEQUENTIAL), random order (RANDOM), or in a user based manner (USER). Each line corresponds to one call and has one or more ';' delimited data fields and they can be referred as [field0], [field1], ... in the xml scenario file. Example:
SEQUENTIAL #This line will be ignored Sarah;sipphone32 Bob;sipphone12 #This line too Fred;sipphone94
Will be read in sequence (first call will use first line, second call second line). At any place where the keyword "[field0]" appears in the scenario file, it will be replaced by either "Sarah", "Bob" or "Fred" depending on the call. At any place where the keyword "[field1]" appears in the scenario file, it will be replaced by either "sipphone32" or "sipphone12" or "sipphone94" depending on the call. At the end of the file, SIPp will re-start from the beginning. The file is not limited in size.
You can override the default line selection strategy with the optional line argument. For example:
[field0 line=1]
Selects the second line in the file (the first line is line zero. The line parameters support keywords in the argument, so in conjunction with a lookup action it is possible to select values based on a key.
The CSV file can contain comment lines. A comment line is a line that starts with a "#".
As a picture says more than 1000 words, here is one:

Think of the possibilities of this feature. They are huge.
It is possible to use more than one injection file, and is necessary when you want to select different types of data in different ways. For example, when running a user-based benchmark, you may have a caller.csv with "USER" as the first line and a callee.csv with "RANDOM" as the first line. To specify which CSV file is used, add the file= parameter to the keyword. For example:
INVITE sip:[field0 file="callee.csv"] SIP/2.0 From: sipp user <[field0 file="caller.csv"]>;tag=[pid]SIPpTag00[call_number] To: sut user <[field0 file="callee.csv"]> ...
Will select the destination user from callee.csv and the sending user from caller.csv. If no file parameter is specified, then the first input file on the command line is used by default.
PRINTF Injection files
An extension of the standard injection file is a "PRINTF" injection file. Often, an input file will has a repetitive nature such as:
USERS user000;password000 user001;password001 ... user999;password999
SIPp must maintain this structure in memory, which can reduce performance for very large injection files. To eliminate this problem, SIPp can automatically generate such a structured file based on one or more template lines. For example:
USERS,PRINTF=999 user%03d;password%03d
Has the same logical meaning as the original example, yet SIPp only needs to store one entry in memory. Each time a line is used; SIPp will replace %d with the requested line number (starting from zero). Standard printf format decimal specifiers can be used. When more than one template line is available, SIPp cycles through them. This example:
USERS,PRINTF=4 user%03d;password%03d;Foo user%03d;password%03d;Bar
Is equivalent to the following injection file:
USERS user000;password000;Foo user001;password001;Bar user002;password002;Foo user003;password003;Bar
The following parameters are used to control the behavior of printf injection files:
Printf Injection File Parameters
| Parameter | Description | Example |
|---|---|---|
| PRINTF | How many virtual lines exist in this file. | PRINTF=10, creates 10 virtual lines |
| PRINTFMULTIPLE | Multiple the virtual line number by this value before generating the substitutions used. | PRINTF=10,PRINTFMULTIPLE=2 creates 10 virtual lines numbered 0,2,4,...,18. |
| PRINTFOFFSET | Add this value to the virtual line number before generating the substitutions used (applied after PRINTFMULTIPLE). | PRINTF=10,PRINTFOFFSET=100 creates 10 virtual lines numbered 100-109. PRINTF=10,PRINTFMULTIPLE=2,PRINTFOFFSET=10 creates 10 users numbered 10,12,14,...28. |
Indexing Injection files
The -infindex option allows you to generate an index of an injection file. The arguments to -infindex are the injection file to index and the field number that should be indexed. For example if you have an injection file that contains user names and passwords (as the following):
USERS alice,pass_A bob,pass_B carol,pass_C
You may want to extract the password for a given user in the file. To do this efficiently, SIPp must build an index for the first field (0). Thus you would pass the argument -infindex users.csv 0 (assuming the file is named users.csv). SIPp will create an index that contains the logical entries {"alice" => 0, "bob" => 1, "carol" => 2}. To extract a particular password, you can use the lookup action to store the line number into a variable (say $line) and then use the keyword[field1 line="[$line]"].
Conditional branching
Conditional branching in scenarios
It is possible to execute a scenario in a non-linear way. You can jump from one part of the scenario to another for example when a message is received or if a call variable is set.
You define a label (in the xml) as <label id="n"/> Where n is a number between 1 and 19 (we can easily have more if needed). The label commands go anywhere in the main scenario between other commands. To any action command (send, receive, pause, etc.) you add a next="n" parameter, where n matches the id of a label. When it has done the command it continues the scenario from that label. This part is useful with optional receives like 403 messages, because it allows you to go to a different bit of script to reply to it and then rejoin at the BYE (or wherever or not).
Alternatively, if you add a test="m" parameter to the next, it goes to the label only if variable [$m] is set. This allows you to look for some string in a received packet and alter the flow either on that or a later part of the script. The evaluation of a test varies based on the type of call variable. For regular expressions, at least one match must have been found; for boolean variables the value must be true; and for all others a value must have been set (currently this only applies to doubles). For more complicated tests, see the <test> action.
Example:
The following example corresponds to the embedded 'branchc' (client side) scenario.
It has to run against the embedded 'branchs' (server side) scenario.


Randomness in conditional branching
To have SIPp behave somewhat more like a "normal" SIP client being used by a human, it is possible to use "statistical branching". Wherever you can have a conditional branch on a variable being set (test="4"), you can also branch based on a statistical decision using the attribute "chance" (e.g. chance="0.90"). Chance can have a value between 0 (never) and 1 (always). "test" and "chance" can be combined, i.e. only branching when the test succeeds and the chance is good.
With this, you can have a variable reaction in a given scenario (e.g.. answer the call or reject with busy), or run around in a loop (e.g. registrations) and break out of it after some random number of iterations.
SIP authentication
SIPp supports SIP authentication. Two authentication algorithm are supported: Digest/MD5 ("algorithm="MD5"") and Digest/AKA ("algorithm="AKAv1-MD5"", as specified by 3GPP for IMS).
Enabling authentication is simple. When receiving a 401 (Unauthorized) or a 407 (Proxy Authentication Required), you must add auth="true" in the <recv> command to take the challenge into account. Then, the authorization header can be re-injected in the next message by using [authentication] keyword.
Computing the authorization header is done through the usage of the "[authentication]" keyword. Depending on the algorithm ("MD5" or "AKAv1-MD5"), different parameters must be passed next to the authentication keyword:
- Digest/MD5 (example: [authentication username=joe password=schmo])
- username: username: if no username is specified, the username is taken from the '-s' (service) command line parameter
- password: password: if no password is specified, the password is taken from the '-ap' (authentication password) command line parameter
- Digest/AKA: (example: [authentication username=HappyFeet aka_OP=0xCDC202D5123E20F62B6D676AC72CB318 aka_K=0x465B5CE8B199B49FAA5F0A2EE238A6BC aka_AMF=0xB9B9])
- username: username: if no username is specified, the username is taken from the '-s'






