SIP协议简介与SIPp流量测试工具
Posted F5Networks
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SIP协议简介与SIPp流量测试工具相关的知识,希望对你有一定的参考价值。
胡旭昌
Enterprise Network Engineer,F5 Networks
2015年加入F5技术支持服务团队,具有八年以上的网络系统部署实施维护经验。F5 Certified Technology Specialists – LTM & DNS
近年来,随着基于IP网络的语音通信的发展以及普及,作为一种被广泛采用的协议,Session Initiation Protocol(会话发起协议,以下简称SIP协议)开始受到大量的使用。本期话题就简要介绍一下该协议。
在各种语音通信流量中,通常可以按照用途分为信令以及媒体流量两部分。信令虽然不携带真正的媒体内容,但其用来控制媒体流的开始、暂停、恢复以及结束,同时也可以用来控制媒体流的走向。SIP协议同样如此,其本身并不携带真正的多媒体信息,但是却起着控制媒体流的作用。
SIP协议作为一个Internet Engineering Task Force(互联网工程任务组,简称IETF)标准在RFC 3261中予以定义。并非如一些二进制的协议那般复杂,SIP协议看上去更像是HTTP协议的一种变体。如下是一个简单的SIP请求头部:
INVITE sip:bob@example.com SIP/2.0
Via: SIP/2.0/UDP alice.example.com:5060;branch=z9hG4Mm776asdhds
Max-Forwards: 70
To: Bob <sip:bob@example.com>
From: Alice <sip:alice@example.com>;tag=3920388734
Call-ID: a84b4c76e66710@alice.example.com
CSeq: 1 INVITE
Contact: <sip:alice@alice.example.com>
Content-Type: application/sdp
Content-Length: 142
▲可左右滑动查看全部内容
一个SIP请求,与HTTP请求类似,也包括一个请求行,如上例中的
INVITEsip:bob@example.com SIP/2.0,方法是INVITE,URL是sip:bob@example.com,协议版本是SIP/2.0。INVITE方法是最常用的创建会话的方法,相应地,结束一个会话通常使用BYE方法。
在请求行之后是各个SIP头部,其格式与HTTP请求类似,都包括了一个name以及相应的value。
以下是一个SIP响应的头部:
SIP/2.0 200 OK
Via: SIP/2.0/UDP alice.example.com:5060;branch= z9hG4Mm776asdhds
To: Bob <sip:bob@example.com>;tag=a6c85cf
From: Alice <sip:alice@example.com>;tag=3920388734
Call-ID: a84b4c76e66710@alice.example.com
CSeq: 1 INVITE
Contact: <sip:bob@example.com>
Content-Type: application/sdp
Content-Length: 131
▲可左右滑动查看全部内容
大家可能注意到一点,上例中的From头与To头在请求与响应中是相同的,尽管在响应中To头多加了一个tag。在SIP规范RFC 3261中指出,From头标记的是请求发起者的逻辑识别符。因此在一个SIP transaction(请求/响应)中,From头和To头应当一致。响应中的To头按照规范,应当添加1个tag来标记此次对话。
Call-ID头,顾名思义,用于标记识别一个SIP dialog(对话)。Call-ID的值是全局唯一的。通信双方(UA)需要在同一个对话中保持相同的Call-ID。
CSeq头可以标记出不同的transaction(交易)。该头部通常包含1个十进制的数字以及一个SIP的方法,如1 INVITE等。一个交易通常包含1个请求和若干个相应的响应,这些请求和响应包含相同的CSeq头。
当1个对话中包含多个交易,同一个Call-ID可与多个CSeq来标识一个特定的交易。
Via头在SIP协议中也非常重要。Via头在1个SIP请求中由发送方予以添加。在每经过一个SIP代理服务器之后,代理服务器也可以插入自己的Via头,该Via头部位于所有的Via头的最上方,并将其转发往下一跳,直至到达最终的SIP消息接收方。在回复时,SIP请求接收方根据收到请求的第一个Via头来发送响应。大家可能注意到,很多的SIP消息是通过UDP协议来传输的,而UDP协议虽然也存在四元组的说法,但是与DNS协议不同,SIP的请求与响应可以通过不同的UDP流完成。如下举例中,相应的响应应当首先发送到charles.example.com:5060:
Via: SIP/2.0/UDP charles.example.com:5060;branch=z0ID4bK9b49v2ef1.1;received=192.168.2.3
Via: SIP/2.0/UDP bob.example.com:5060;branch= z0ID4bK9b49v2xd112983.1;received=192.168.2.2
Via: SIP/2.0/UDP alice.example.com:5060;branch= z0ID4bK9b49v2ef1ashds8;received=192.168.2.1
▲可左右滑动查看全部内容:
Contact头标记了随后SIP请求应当发送到的URI,即出现在SIP Request-URI中。
SIPp工具
SIPp作为一个常用的 SIP流量压力测试工具,经常被用来测试某套SIP系统的性能。该工具可以从http://sipp.sourceforge.net/下载源代码,并通过gcc或者其它C语言编译器编译以及安装。
- SIPp基本示例
首先,我们在服务器上启动SIP服务:
# sipp -sn uas -i 10.0.197.3
当SIPp启动后我们看到如下界面:
随着SIP流量从客户端发送过来,这里的数值会实时显示接收到的SIP请求数量和发送的响应数量。
在客户端,以下命令可以发起SIP请求到服务器并且观察实时统计数据。
# sipp -i 10.0.197.1 10.0.197.3
下图显示了已经收到了20个INVITE请求以及BYE请求,并且都完成按照脚本执行的回复响应:
通常,在运行任意脚本之前,我们都可以尝试发送一个对话来验证是否能够正常执行脚本并且数据是否如预期设计的那样。在上例中,我们可以尝试如下命令来验证流量:
# sipp -i 10.0.197.1 10.0.197.3 -m 1
同时我们可以抓包来验证:
# tcpdump -ni eth0 -s 0 -w /var/tmp/sipSimple.pcap
如下是用最简单的tshark命令查看抓取的数据包:
$ tshark -r sipSimple.pcap
1 0.000000 10.0.197.1 → 10.0.197.3 SIP/SDP 556 Request: INVITE sip:service@10.0.197.3:5060 |
2 0.000456 10.0.197.3 → 10.0.197.1 SIP 352 Status: 180 Ringing |
3 0.001691 10.0.197.3 → 10.0.197.1 SIP/SDP 513 Status: 200 OK |
4 0.002252 10.0.197.1 → 10.0.197.3 SIP 403 Request: ACK sip:service@10.0.197.3:5060 |
5 0.006694 10.0.197.1 → 10.0.197.3 SIP 403 Request: BYE sip:service@10.0.197.3:5060 |
6 0.006864 10.0.197.3 → 10.0.197.1 SIP 344 Status: 200 OK |
▲可左右滑动查看全部内容
- 模拟多客户端
在客户端我们可以创建一个XML文件,在这个示例中,这个文件将命名为client.xml。同时,injection文件将被命名为infFile.txt。
以下是client.xml文件的内容:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<scenario name="client">
<send retrans="500">
<![CDATA[
INVITE sip:[field0]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [field2]:5060;branch=[branch]
From: <sip:[field1]@[field2]:5060>;tag=[call_number]
To: <sip:[field0]@[remote_ip]:[remote_port]>
Call-ID: [call_id]
CSeq: 1 INVITE
Contact: <sip:[field1]@[field2]:5060>
Content-Type: application/sdp
Max-Forwards: 70
Content-Length: [len]
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [field2]
s=SIP Call
c=IN IP[media_ip_type] [field2]
t=0 0
m=audio [auto_media_port] RTP/AVP 0
a=rtpmap:0 PCMU/8000
a=rtpmap:4 G723/8000
a=rtpmap:18 G729/8000
a=rtpmap:97 telephone-event/8000
a=sendrecv
]]>
</send>
<recv response="100"></recv>
<recv response="183"></recv>
<recv response="200"></recv>
<send>
<![CDATA[
ACK sip:[field0]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [field2]:5060;branch=[branch]
From: <sip:[field1]@[field2]:5060>;tag=[call_number]
To: <sip:[field0]@[remote_ip]:[remote_port]>[peer_tag_param]
Call-ID: [call_id]
CSeq: 1 ACK
Contact: <sip:[field1]@[field2]:5060>
Max-Forwards: 70
Content-Length: 0
]]>
</send>
<recv request="INFO">
<action>
<ereg regexp=".*" search_in="hdr" header="From:" check_it="true" assign_to="1" />
<ereg regexp=".*" search_in="hdr" header="To:" check_it="true" assign_to="2" />
</action>
</recv>
<send>
<![CDATA[
SIP/2.0 200 OK
[last_Via:]
From:[$1]
To:[$2]
[last_Call-ID:]
[last_CSeq:]
Contact: <sip:[field1]@[field2]:5060>
Content-Length: 0
]]>
</send>
<send retrans="500">
<![CDATA[
BYE sip:[field0]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [field2]:5060;branch=[branch]
From:[$2]
To:[$1]
[last_Call-ID:]
CSeq: 2 BYE
Contact: <sip:[field1]@[field2]:5060>
Max-Forwards: 70
Content-Length: 0
]]>
</send>
<recv response="200"></recv>
</scenario>
▲可滑动查看全部内容:
左右滑动(任意黑色背景)、上下(代码右侧黑白交接处)
SEQUENTIAL
100000;190000;10.0.197.6
100001;190001;10.0.197.7
100002;190002;10.0.197.8
100003;190003;10.0.197.9
100004;190004;10.0.197.10
100005;190005;10.0.197.11
100006;190006;10.0.197.12
100007;190007;10.0.197.13
100008;190008;10.0.197.14
100009;190009;10.0.197.15
100010;190010;10.0.197.16
100011;190011;10.0.197.17
100012;190012;10.0.197.18
100013;190013;10.0.197.19
100014;190014;10.0.197.20
100015;190015;10.0.197.21
100016;190016;10.0.197.22
100017;190017;10.0.197.23
100018;190018;10.0.197.24
100019;190019;10.0.197.25
100020;190020;10.0.197.26
100021;190021;10.0.197.27
100022;190022;10.0.197.28
100023;190023;10.0.197.29
100024;190024;10.0.197.30
100025;190025;10.0.197.31
100026;190026;10.0.197.32
100027;190027;10.0.197.33
100028;190028;10.0.197.34
100029;190029;10.0.197.35
100030;190030;10.0.197.36
100031;190031;10.0.197.37
100032;190032;10.0.197.38
100033;190033;10.0.197.39
100034;190034;10.0.197.40
100035;190035;10.0.197.41
100036;190036;10.0.197.42
100037;190037;10.0.197.43
100038;190038;10.0.197.44
100039;190039;10.0.197.45
100040;190040;10.0.197.46
100041;190041;10.0.197.47
100042;190042;10.0.197.48
100043;190043;10.0.197.49
100044;190044;10.0.197.50
100045;190045;10.0.197.51
100046;190046;10.0.197.52
100047;190047;10.0.197.53
100048;190048;10.0.197.54
100049;190049;10.0.197.55
100050;190050;10.0.197.56
100051;190051;10.0.197.57
100052;190052;10.0.197.58
100053;190053;10.0.197.59
100054;190054;10.0.197.60
100055;190055;10.0.197.61
100056;190056;10.0.197.62
100057;190057;10.0.197.63
100058;190058;10.0.197.64
100059;190059;10.0.197.65
100060;190060;10.0.197.66
100061;190061;10.0.197.67
100062;190062;10.0.197.68
100063;190063;10.0.197.69
100064;190064;10.0.197.70
100065;190065;10.0.197.71
100066;190066;10.0.197.72
100067;190067;10.0.197.73
100068;190068;10.0.197.74
100069;190069;10.0.197.75
100070;190070;10.0.197.76
100071;190071;10.0.197.77
100072;190072;10.0.197.78
100073;190073;10.0.197.79
100074;190074;10.0.197.80
100075;190075;10.0.197.81
100076;190076;10.0.197.82
100077;190077;10.0.197.83
100078;190078;10.0.197.84
100079;190079;10.0.197.85
100080;190080;10.0.197.86
100081;190081;10.0.197.87
100082;190082;10.0.197.88
100083;190083;10.0.197.89
100084;190084;10.0.197.90
100085;190085;10.0.197.91
100086;190086;10.0.197.92
100087;190087;10.0.197.93
100088;190088;10.0.197.94
100089;190089;10.0.197.95
100090;190090;10.0.197.96
100091;190091;10.0.197.97
100092;190092;10.0.197.98
100093;190093;10.0.197.99
100094;190094;10.0.197.100
100095;190095;10.0.197.101
100096;190096;10.0.197.102
100097;190097;10.0.197.103
100098;190098;10.0.197.104
100099;190099;10.0.197.105
100100;190100;10.0.197.106
▲可上下滑动查看全部内容:(按住代码右侧黑白交接处)
在服务器内,为了配合客户端这一侧的呼叫流程,也相应地创建了一个server.xml,如下:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<scenario name="Basic UAS responder">
<recv request="INVITE">
<action>
<ereg regexp=".*" search_in="hdr" header="From:" check_it="true" assign_to="1" />
<ereg regexp=".*" search_in="hdr" header="To:" check_it="true" assign_to="2" />
<ereg regexp="sip:.*@" search_in="hdr" header="To:" check_it="true" assign_to="5" />
<ereg regexp="sip.*:[0-9]+" search_in="hdr" header="Contact:" check_it="true" assign_to="6" />
</action>
</recv>
<send><![CDATA[
SIP/2.0 100 Trying
[last_Via:]
[last_From:]
[last_To:]
[last_Call-ID:]
[last_CSeq:]
Content-Length: 0
]]>
</send>
<send><![CDATA[
SIP/2.0 183 Session Progress
[last_Via:]
[last_From:]
[last_To:];tag=[call_number]
[last_Call-ID:]
[last_CSeq:]
Contact: <[$5][local_ip]:[local_port];transport=[transport]>
Content-Length: [len]
Content-Type: application/sdp
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [auto_media_port] RTP/AVP 8 97
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=ptime:20
a=fmtp:97 0-15
]]>
</send>
<pause milliseconds="15000"/>
<send retrans="500">
<![CDATA[
SIP/2.0 200 OK
[last_Via:]
[last_From:]
[last_To:];tag=[call_number]
[last_Call-ID:]
[last_CSeq:]
Contact: <[$5][local_ip]:[local_port];transport=[transport]>
Content-Length: [len]
Content-Type: application/sdp
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [auto_media_port] RTP/AVP 8 97
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=ptime:20
a=fmtp:97 0-15
]]>
</send>
<recv request="ACK"></recv>
<send retrans="500">
<![CDATA[
INFO [$6] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From:[$2];tag=[call_number]
To:[$1]
[last_Call-ID:]
CSeq: 1 INFO
Max-Forwards: 70
Contact: <[$5][local_ip]:[local_port];transport=[transport]>
Content-Length: [len]
Content-Type: application/example
Event-Type=0
Event-Content=content
OP-Type=type
cause=200;text="completed"
]]>
</send>
<recv response="200"></recv>
<recv request="BYE"></recv>
<send>
<![CDATA[
SIP/2.0 200 OK
[last_Via:]
[last_From:]
[last_To:]
[last_Call-ID:]
[last_CSeq:]
Contact: <[$5][local_ip]:[local_port];transport=[transport]>
Content-Length: 0
]]>
</send>
</scenario>
▲可滑动查看全部内容:
左右滑动(任意黑色背景)、上下(代码右侧黑白交接处)
在服务器上运行如下命令启动SIPp实例:
# sipp -t un -sf server.xml -i 10.0.197.3
以上命令中,-sf参数可以指定一个场景文件以实现特定的call flow。
# sipp -t ui -ip_field 2 -p 5060 -sf client.xml -inf infFile.txt 10.0.197.3 -m 100
以下是运行结果截图:
- 媒体流播放
如果在SIPp的测试过程中,我们需要发送媒体流,那么借助SIPp的脚本,我们可以在特定位置插入媒体流指令,并且指定所需的媒体流文件。SIPp安装源文件提供了若干媒体流的抓包范例,如g711a.pcap。可以使用该文件或者其它指定格式的文件来执行媒体流的模拟播放。
如下server_media.xml脚本会在INVITE请求的200响应之后插入一段媒体流并循环播放一次,并在INFO请求收到响应后再次播放一遍。
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<scenario name="Basic UAS responder">
<recv request="INVITE">
<action>
<ereg regexp=".*" search_in="hdr" header="From:" check_it="true" assign_to="1" />
<ereg regexp=".*" search_in="hdr" header="To:" check_it="true" assign_to="2" />
<ereg regexp="sip:.*@" search_in="hdr" header="To:" check_it="true" assign_to="5" />
<ereg regexp="sip.*:[0-9]+" search_in="hdr" header="Contact:" check_it="true" assign_to="6" />
</action>
</recv>
<send><![CDATA[
SIP/2.0 100 Trying
[last_Via:]
[last_From:]
[last_To:]
[last_Call-ID:]
[last_CSeq:]
Content-Length: 0
]]>
</send>
<send><![CDATA[
SIP/2.0 183 Session Progress
[last_Via:]
[last_From:]
[last_To:];tag=[call_number]
[last_Call-ID:]
[last_CSeq:]
Contact: <[$5][local_ip]:[local_port];transport=[transport]>
Content-Length: [len]
Content-Type: application/sdp
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [auto_media_port] RTP/AVP 8 97
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=ptime:20
a=fmtp:97 0-15
]]>
</send>
<pause milliseconds="15000"/>
<send retrans="500">
<![CDATA[
SIP/2.0 200 OK
[last_Via:]
[last_From:]
[last_To:];tag=[call_number]
[last_Call-ID:]
[last_CSeq:]
Contact: <[$5][local_ip]:[local_port];transport=[transport]>
Content-Length: [len]
Content-Type: application/sdp
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=-
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [auto_media_port] RTP/AVP 8 97
a=rtpmap:8 PCMA/8000
a=rtpmap:97 telephone-event/8000
a=ptime:20
a=fmtp:97 0-15
]]>
</send>
<recv request="ACK"></recv>
<label id="2"/>
<nop>
<action>
<exec play_pcap_audio="g711a.pcap"/>
</action>
</nop>
<pause milliseconds="400"next="2"/>
<send retrans="500">
<![CDATA[
INFO [$6] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From:[$2];tag=[call_number]
To:[$1]
[last_Call-ID:]
CSeq: 1 INFO
Max-Forwards: 70
Contact: <[$5][local_ip]:[local_port];transport=[transport]>
Content-Length: [len]
Content-Type: application/example
Event-Type=0
Event-Content=content
OP-Type=type
cause=200;text="completed"
]]>
</send>
<recv response="200"></recv>
<nop>
<action>
<exec play_pcap_audio="g711a.pcap"/>
</action>
</nop>
<recv request="BYE"></recv>
<send>
<![CDATA[
SIP/2.0 200 OK
[last_Via:]
[last_From:]
[last_To:]
[last_Call-ID:]
[last_CSeq:]
Contact: <[$5][local_ip]:[local_port];transport=[transport]>
Content-Length: 0
]]>
</send>
</scenario>
▲可滑动查看全部内容:
左右滑动(任意黑色背景)、上下(代码右侧黑白交接处)
相应的客户端场景脚本如下:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<scenario name="client">
<send retrans="500">
<![CDATA[
INVITE sip:[field0]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: <sip:[field1]@[local_ip]:[local_port]>;tag=[call_number]
To: <sip:[field0]@[remote_ip]:[remote_port]>
Call-ID: [call_id]
CSeq: 1 INVITE
Contact: <sip:[field1]@[local_ip]:[local_port]>
Content-Type: application/sdp
Max-Forwards: 70
Content-Length: [len]
v=0
o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
s=SIP Call
c=IN IP[media_ip_type] [media_ip]
t=0 0
m=audio [auto_media_port] RTP/AVP 0
a=rtpmap:0 PCMU/8000
a=rtpmap:4 G723/8000
a=rtpmap:18 G729/8000
a=rtpmap:97 telephone-event/8000
a=sendrecv
]]>
</send>
<recv response="100"></recv>
<recv response="183"></recv>
<recv response="200"></recv>
<send>
<![CDATA[
ACK sip:[field0]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From: <sip:[field1]@[local_ip]:[local_port]>;tag=[call_number]
To: <sip:[field0]@[remote_ip]:[remote_port]>[peer_tag_param]
Call-ID: [call_id]
CSeq: 1 ACK
Contact: <sip:[field1]@[local_ip]:[local_port]>
Max-Forwards: 70
Content-Length: 0
]]>
</send>
<recv request="INFO">
<action>
<ereg regexp=".*" search_in="hdr" header="From:" check_it="true" assign_to="1" />
<ereg regexp=".*" search_in="hdr" header="To:" check_it="true" assign_to="2" />
</action>
</recv>
<send>
<![CDATA[
SIP/2.0 200 OK
[last_Via:]
From:[$1]
To:[$2]
[last_Call-ID:]
[last_CSeq:]
Contact: <sip:[field1]@[local_ip]:[local_port]>
Content-Length: 0
]]>
</send>
<send retrans="500">
<![CDATA[
BYE sip:[field0]@[remote_ip]:[remote_port] SIP/2.0
Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
From:[$2]
To:[$1]
[last_Call-ID:]
CSeq: 2 BYE
Contact: <sip:[field1]@[local_ip]:[local_port]>
Max-Forwards: 70
Content-Length: 0
]]>
</send>
<recv response="200"></recv>
</scenario>
▲可滑动查看全部内容:
左右滑动(任意黑色背景)、上下(代码右侧黑白交接处)
在服务器上启动实例如下:
# sipp -t un -sf server_media.xml -i 10.0.197.3 -mi 10.0.198.1 -mp 5000
在SIPp模拟客户端上使用如下命令启动SIPp脚本产生SIP流量:
# sipp -t un -i 10.0.197.1 -sf client_media.xml -inf infFile.txt 10.0.197.3 -m 100
以下是运行报告截图:
SIPp工具的功能非常强大,可以根据不同的场景来定制所需的脚本。本期为大家展示了SIPp几个基本的场景配置,希望能够为大家搭建SIP相关模拟环境提供一些参考。
一点通回顾
●
●
●
●
关于F5售后服务
●
●
●
如果你喜欢本文
戳戳这里吧
以上是关于SIP协议简介与SIPp流量测试工具的主要内容,如果未能解决你的问题,请参考以下文章