首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >聊聊 SIPp uas.xml 及相关配置实践

聊聊 SIPp uas.xml 及相关配置实践

作者头像
杜金房
发布2026-06-15 16:58:59
发布2026-06-15 16:58:59
540
举报

SIPp 是一款常用的 SIP 协议性能测试工具,uas.xml 是其内置的用户代理服务器(UAS)场景配置文件。本文将从基础使用、代理适配修改、主动发送 BYE 消息配置三个维度,详细讲解 uas.xml 的相关操作。

获取 uas.xml 并编写启动脚本

首先,通过 SIPp 内置命令可直接导出默认 uas.xml 配置文件,执行以下命令即可:

代码语言:javascript
复制
sipp -sd uas > uas.xml

为了便捷启动 UAS 服务,我们可以编写一个启动脚本uas.sh,将启动参数固化其中。脚本内容如下,需根据实际环境修改 LOCAL_IP(本地 IP 地址)和 LOCAL_PORT(本地端口,默认 SIP 端口为 5060):

代码语言:javascript
复制
#!/bin/bash

# 配置本地IP和端口(需根据实际环境调整)
LOCAL_IP=192.168.1.100
LOCAL_PORT=5060

# 启动SIPp UAS服务,指定配置文件、本地IP和端口
sipp -sf uas.xml -i $LOCAL_IP -p $LOCAL_PORT

脚本核心参数说明:

  • -sf:指定 SIPp 运行的场景配置文件(此处为 uas.xml);
  • -i:绑定本地 IP 地址,用于接收 SIP 消息;
  • -p:绑定本地端口,用于监听 SIP 消息。

脚本编写完成后,需赋予执行权限并启动,命令如下:

代码语言:javascript
复制
# 赋予脚本执行权限
chmod +x uas.sh
# 启动 UAS
./uas.sh

启动成功后,FreeSWITCH 可直接呼叫 SIPp 监听的 IP 和端口,进行基础的 SIP 呼叫压力测试。

进阶:修改 uas.xml 以便适配 Kamailio 代理呼叫

若需通过 Kamailio(SIP 代理程序)实现 FreeSWITCH 与 SIPp 的呼叫交互,需对默认 uas.xml 进行三处关键修改,确保 SIP 消息能正确通过代理传递。

修改编码格式(支持中文注释)

默认 uas.xml 第一行编码为`ISO-8859-1`,不支持中文注释。将其修改为 `UTF-8` 编码,方便后续添加中文说明:

原内容:

代码语言:javascript
复制
<?xml version="1.0" encoding="ISO-8859-1" ?>

修改后:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8" ?>

接收 INVITE 消息时启用路由集保存

SIP 代理场景下,需保存路由集(Route Sets)以确保后续响应消息能正确回传给代理。找到接收 INVITE 消息的配置段,添加 rrs="true" 参数(rrs 即 Record Route Sets):

原内容:

代码语言:javascript
复制
  <recv request="INVITE" crlf="true">
  </recv>

修改后:

代码语言:javascript
复制
  <recv request="INVITE" crlf="true" rrs="true">
  </recv>

说明:启用 rrs="true" 后,SIPp 会保存接收消息中的路由信息,用于后续发送响应/请求时使用,适配有状态 SIP 代理场景。

响应消息中添加 Record-Route 头域

Record-Route 头域用于记录呼叫路径,确保后续消息(如 BYE)能沿原路径回传。需在 180 Ringing 和 200 OK 两个响应消息中添加 `[last_Record-Route:]` 占位符(自动复用接收消息中的 Record-Route 信息)。

  • 修改 180 Ringing 响应:

原内容:

代码语言:javascript
复制
 <send>
    <![CDATA[
      SIP/2.0 180 Ringing
      [last_Via:]
      [last_From:]
      [last_To:];tag=[pid]SIPpTag01[call_number]
      [last_Call-ID:]
      [last_CSeq:]
      Contact: <sip:[local_ip]:[local_port];transport=[transport]>
      Content-Length: 0
    ]]>
  </send>

修改后(添加 [last_Record-Route:]):

代码语言:javascript
复制
<send>
    <![CDATA[
      SIP/2.0 180 Ringing
      [last_Via:]
      [last_From:]
      [last_To:];tag=[pid]SIPpTag01[call_number]
      [last_Call-ID:]
      [last_CSeq:]
      [last_Record-Route:]
      Contact: <sip:[local_ip]:[local_port];transport=[transport]>
      Content-Length: 0
    ]]>
  </send>
  • 修改 200 OK 响应(INVITE 最终响应):

原内容:

代码语言:javascript
复制
  <send retrans="500">
    <![CDATA[
      SIP/2.0 200 OK
      [last_Via:]
      [last_From:]
      [last_To:];tag=[pid]SIPpTag01[call_number]
      [last_Call-ID:]
      [last_CSeq:]
      Contact: <sip:[local_ip]:[local_port];transport=[transport]>
      Content-Type: application/sdp
      Content-Length: [len]
      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 [media_port] RTP/AVP 0
      a=rtpmap:0 PCMU/8000
      a=ptime:20
    ]]>
  </send>

修改后(添加 [last_Record-Route:]):

代码语言:javascript
复制
 <send retrans="500">
    <![CDATA[
      SIP/2.0 200 OK
      [last_Via:]
      [last_From:]
      [last_To:];tag=[pid]SIPpTag01[call_number]
      [last_Call-ID:]
      [last_CSeq:]
      [last_Record-Route:]
      Contact: <sip:[local_ip]:[local_port];transport=[transport]>
      Content-Type: application/sdp
      Content-Length: [len]
      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 [media_port] RTP/AVP 0
      a=rtpmap:0 PCMU/8000
      a=ptime:20
    ]]>
  </send>

适配代理的 uas.xml 完整内容

整合上述修改后,完整的 uas.xml 如下:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<!-- This program is free software; you can redistribute it and/or      -->
<!-- modify it under the terms of the GNU General Public License as     -->
<!-- published by the Free Software Foundation; either version 2 of the -->
<!-- License, or (at your option) any later version.                    -->
<!--                                                                    -->
<!-- This program is distributed in the hope that it will be useful,    -->
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of     -->
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      -->
<!-- GNU General Public License for more details.                       -->
<!--                                                                    -->
<!-- You should have received a copy of the GNU General Public License  -->
<!-- along with this program; if not, write to the                      -->
<!-- Free Software Foundation, Inc.,                                    -->
<!-- 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA             -->
<!--                                                                    -->
<!--                 Sipp default 'uas' scenario.                       -->
<!--                                                                    -->
<scenario name="Basic UAS responder">
  <!-- By adding rrs="true" (Record Route Sets), the route sets         -->
  <!-- are saved and used for following messages sent. Useful to test   -->
  <!-- against stateful SIP proxies/B2BUAs.                             -->
  <!-- Adding ignoresdp="true" here would ignore the SDP data: that     -->
  <!-- can be useful if you want to reject reINVITEs and keep the       -->
  <!-- media stream flowing.                                            -->
  <recv request="INVITE" crlf="true" rrs="true">
  </recv>
  <!-- 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 occurrences are concatenated (CRLF separated)       -->
  <!-- to be used in place of the '[last_*]' keyword.                   -->
  <send>
    <![CDATA[
      SIP/2.0 180 Ringing
      [last_Via:]
      [last_From:]
      [last_To:];tag=[pid]SIPpTag01[call_number]
      [last_Call-ID:]
      [last_CSeq:]
      [last_Record-Route:]
      Contact: <sip:[local_ip]:[local_port];transport=[transport]>
      Content-Length: 0
    ]]>
  </send>
  <send retrans="500">
    <![CDATA[
      SIP/2.0 200 OK
      [last_Via:]
      [last_Record-Route:]
      [last_From:]
      [last_To:];tag=[pid]SIPpTag01[call_number]
      [last_Call-ID:]
      [last_CSeq:]
      [last_Record-Route:]
      Contact: <sip:[local_ip]:[local_port];transport=[transport]>
      Content-Type: application/sdp
      Content-Length: [len]
      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 [media_port] RTP/AVP 0
      a=rtpmap:0 PCMU/8000
    ]]>
  </send>
  <recv request="ACK"
        optional="true"
        rtd="true"
        crlf="true">
  </recv>
  <recv request="BYE">
  </recv>
  <send>
    <![CDATA[
      SIP/2.0 200 OK
      [last_Via:]
      [last_From:]
      [last_To:]
      [last_Call-ID:]
      [last_CSeq:]
      Contact: <sip:[local_ip]:[local_port];transport=[transport]>
      Content-Length: 0
    ]]>
  </send>
  <!-- Keep the call open for a while in case the 200 is lost to be     -->
  <!-- able to retransmit it if we receive the BYE again.               -->
  <timewait milliseconds="4000"/>
  <!-- definition of the response time repartition table (unit is ms)   -->
  <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
  <!-- definition of the call length repartition table (unit is ms)     -->
  <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
</scenario>

uas_send_bye.xml 实现 SIPp 主动发送 BYE

默认 uas.xml 中,SIPp 作为 UAS 被动接收主叫发送的 BYE 消息。若需让 SIPp 主动发起挂断(即主动发送 BYE 消息),可创建uas_send_bye.xml 配置文件,核心逻辑是:接收 ACK 消息后,提取呼叫信息,主动构造并发送 BYE 消息。

核心修改说明

相较于适配代理的 uas.xml,uas_send_bye.xml 主要增加/修改了以下部分:

  • 接收 ACK 消息时,通过 `ereg` 正则提取 To 头域(含 tag)和 From 头域信息,分别赋值给 `us` 和 `them` 变量;
  • 添加 `<pause/>` 标签(默认暂停1秒,可通过 `milliseconds` 属性指定时长),模拟通话过程;
  • 新增发送 BYE 消息的配置,通过 `start_txn="bye"` 标记 BYE 事务,使用提取的 `
  • 新增接收 BYE 响应(200 OK)的配置,通过 `response_txn="bye"` 关联 BYE 事务。

uas_send_bye.xml 完整内容:

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<!-- This program is free software; you can redistribute it and/or      -->
<!-- modify it under the terms of the GNU General Public License as     -->
<!-- published by the Free Software Foundation; either version 2 of the -->
<!-- License, or (at your option) any later version.                    -->
<!--                                                                    -->
<!-- This program is distributed in the hope that it will be useful,    -->
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of     -->
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      -->
<!-- GNU General Public License for more details.                       -->
<!--                                                                    -->
<!-- You should have received a copy of the GNU General Public License  -->
<!-- along with this program; if not, write to the                      -->
<!-- Free Software Foundation, Inc.,                                    -->
<!-- 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA             -->
<!--                                                                    -->
<!--                 Sipp default 'uas' scenario.                       -->
<!--                                                                    -->
<scenario name="Basic UAS responder">
  <!-- By adding rrs="true" (Record Route Sets), the route sets         -->
  <!-- are saved and used for following messages sent. Useful to test   -->
  <!-- against stateful SIP proxies/B2BUAs.                             -->
  <!-- Adding ignoresdp="true" here would ignore the SDP data: that     -->
  <!-- can be useful if you want to reject reINVITEs and keep the       -->
  <!-- media stream flowing.                                            -->
  <recv request="INVITE" crlf="true" rrs="true">
  </recv>
  <!-- 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 occurrences are concatenated (CRLF separated)       -->
  <!-- to be used in place of the '[last_*]' keyword.                   -->
  <send>
    <![CDATA[
      SIP/2.0 180 Ringing
      [last_Via:]
      [last_From:]
      [last_To:];tag=[pid]SIPpTag01[call_number]
      [last_Call-ID:]
      [last_CSeq:]
      [last_Record-Route:]
      Contact: <sip:[local_ip]:[local_port];transport=[transport]>
      Content-Length: 0
    ]]>
  </send>
  <send retrans="500">
    <![CDATA[
      SIP/2.0 200 OK
      [last_Via:]
      [last_Record-Route:]
      [last_From:]
      [last_To:];tag=[pid]SIPpTag01[call_number]
      [last_Call-ID:]
      [last_CSeq:]
      [last_Record-Route:]
      Contact: <sip:[local_ip]:[local_port];transport=[transport]>
      Content-Type: application/sdp
      Content-Length: [len]
      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 [media_port] RTP/AVP 0
      a=rtpmap:0 PCMU/8000
    ]]>
  </send>
  <recv request="ACK" rrs="true">
    <action>
      <ereg regexp=": *(.*)" search_in="hdr" header="To" assign_to="_,us"/><!-- with tag -->
      <ereg regexp=": *(.*)" search_in="hdr" header="From" assign_to="_,them"/>
    </action>
  </recv>
  <Reference variables="_"/>
  <pause/>
  <send start_txn="bye" retrans="500">
    <![CDATA[
      BYE [next_url] SIP/2.0
      Via: SIP/2.0/[transport] [local_ip]:[local_port];branch=[branch]
      [routes]
      From: [$us]
      To: [$them]
      [last_Call-ID:]
      CSeq: [cseq] BYE
      Contact: sip:[service]@[local_ip]:[local_port]
      Content-Length: 0
    ]]>
  </send>
  <recv response="200" response_txn="bye"/>
  <!-- definition of the response time repartition table (unit is ms)   -->
  <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
  <!-- definition of the call length repartition table (unit is ms)     -->
  <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
</scenario>

关键说明:

  • 变量使用:SIPp 中的 `[last_*]`占位符、`$变量名` 等均为内置语法,需严格遵循格式要求,否则会导致配置文件解析失败;
  • 代理适配:核心是确保路由信息正确传递,`rrs="true"` 和 `[last_Record-Route:]` 两个配置缺一不可;
  • 主动 BYE 逻辑:From 标签和 To 标签互换是关键,若未互换,会导致对方无法正确识别 BYE 消息归属的呼叫;

编写(或者修改) 自己的 XML scenarios 有一个很大的好处就是可以熟悉 SIP 规范。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-05-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FreeSWITCH中文社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档