Pages

Monday, 8 October 2018

SIPP Performance Tool






Today, I’m goint to share my SIPP project that I have worked on it during last one month. Before begin this case, checking call performance on our voice network was my first goal. It can be said that being continuous of this project offers our team being awake against fail calls. Let me tell you requirements before start;


> Linux server
> SIPP Tool
> Also, we will use python, bash and  stored procedure

In first, I’ll need to give some informations about SIPP. It can be called SIP performance tool that is a free open sources testing tool. It lets you to generate sip traffic. In addition, you are able to create varied scenarios whatever you want, even there is default scenario in SIPP tool. For more technical infos, please check SIPPofficial website.


In this case, I tryed to explain how we can check sip calls performance and report results. You can fallow below lines to download and install SIPp tool properly;

wget  http://sourceforge.net/projects/sipp/files/sipp/3.3/sipp-3.3.tar.gz/
apt-get or Yum  intsall sipp-XXX-tar.gz
cd Sipp-XX
ls -l
 apt-get install  openssl
apt-get install  libssl-dev
apt-get install  libssl1.0.0
apt-get install  libssl0.9.8
apt-get install  pcaputils
apt-get install  libssl-dev
apt-get install  libncursesw5-dev
apt-get install  libncurses5-dev
apt-get install  libcap-dev
make pcapplay_ossl or make pcap
./sipp XXX.XX.XX.XXX -sf REGISTER_client.xml -inf Register_client.csv -m 1

I think, you will encounter many errors when you try to install it but “google” will help you for all errors. (My installation took one day :) )

You may start with creating your own xml scenario that depends according to the your sip server. Let’s begin to execute ‘vim sample.xml’ on your linux server. Here is my xml file;



<?xml version="1.0" encoding="ISO-8859-1" ?>       >>>> be sure your first two lines must be like these.
<!DOCTYPE scenario SYSTEM "sipp.dtd">
<scenario name="UAC REGISTER + INVITE">

   <send retrans="500">     >>> First, send register packet with using retrans(for UDP, timer:500 ms ).
    <![CDATA[
      REGISTER sip:[remote_ip] SIP/2.0
      Via: SIP/2.0/[transport] [local_ip]:[local_port];rport;branch=[branch]
      From: <sip:[field0]@[field1]>;tag=[call_number]
      To: <sip:[field0]@[field1]>       >>> these fields should be defined in .csv file
      Call-ID: [call_id]
      CSeq: [cseq] REGISTER
      Contact: sip:[field0]@[local_ip]:[local_port]
      Max-Forwards: 100
      Expires: 120
      User-Agent: SIPp/Win32
      Content-Length: 0
    ]]>
  </send>

  <recv response="100" optional="true">    >>> it means that options of response against sent packet.
  </recv>

  <recv response="200">      >>> SIPp will wait until get 200 OK.
  </recv>

  <send retrans="500">        >>> Secondly, send invite packet and be sure for branch parameters like below.
    <![CDATA[
      INVITE sip:[field3]@[remote_ip] SIP/2.0
      Via: SIP/2.0/[transport] [local_ip]:5062;rport;branch=z9hG4bK-[call_number]-01
      From: sipp <sip:[field0]@[field1]>;tag=[call_number]
      To: <sip:[field3]@[field1]>
      Call-ID: [call_id]
      CSeq: [cseq] INVITE
      Contact: sip:[field0]@[local_ip]:[local_port]
      Max-Forwards: 100
      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 8
      a=rtpmap:8 PCMA/8000

    ]]>
  </send>
  <recv response="100" optional="true">
  </recv>
  <recv response="407" auth="true">        >>> it is used to build the ‘authentication’ keyword.
  </recv>
  <send>
    <![CDATA[
      ACK sip:[field3]@[remote_ip] SIP/2.0
      Via: SIP/2.0/[transport] [local_ip]:5062;rport;branch=z9hG4bK-[call_number]-01
      From: <sip:[field0]@[field1]>;tag=[call_number]
      [last_To:]
      Call-ID: [call_id]
      CSeq: [cseq] ACK
      Contact: sip:[field0]@[local_ip]:[local_port]
      Max-Forwards: 100
      Content-Length: 0
    ]]>
  </send>
  <send retrans="500">         >>> send invite again, but now with sip credentials.
    <![CDATA[
      INVITE sip:[field3]@[remote_ip] SIP/2.0
      Via: SIP/2.0/[transport] [local_ip]:5062;rport;branch=z9hG4bK-[call_number]-02
      From: sipp <sip:[field0]@[field1]>;tag=[call_number]
      To: <sip:[field3]@[field1]>
      Call-ID: [call_id]
      CSeq: [cseq] INVITE
      Contact: <sip:[field0]@[local_ip]:5062>
      [field2]                                                                   >>> It contains SIP credentials in .csv file
      Max-Forwards: 100
      Supported: replaces
      Allow-Events: talk,hold,conference,refer,check-sync
      Content-Type: application/sdp
      Allow: INVITE, INFO, PRACK, ACK, BYE, CANCEL, OPTIONS, NOTIFY, REGISTER, SUBSCRIBE, REFER, PUBLISH, UPDATE, MESSAGE
      Content-Length: [len]

      v=0
      o=user1 53655765 2353687637 IN IP[local_ip_type] [local_ip]
      s=SDP data
      c=IN IP[media_ip_type] [media_ip]
      t=0 0
      m=audio [media_port] RTP/AVP 8
      a=rtpmap:8 PCMA/8000
      a=rtpmap:18 G729/8000
      a=fmtp:18 annexb=no
      a=rtpmap:9 G722/8000
      a=fmtp:101 0-15
      a=rtpmap:101 telephone-event/8000
      a=ptime:20
      a=sendrecv

    ]]>
  </send>
  <recv response="100" optional="true">
  </recv>
  <recv response="180" optional="true">
  </recv>
  <recv response="183" optional="true">
  </recv>
  <recv response="480" optional="true">
  </recv>

  <recv response="200" rrs="true">
  </recv>
  <send>
    <![CDATA[
      ACK [next_url] SIP/2.0
      Via: SIP/2.0/[transport] [local_ip]:5062;branch=z9hG4bK-[call_number]-03
      From: <sip:[field0]@[field1]>;tag=[call_number]
      [last_To:]
      [routes]
      Call-ID: [call_id]
      CSeq: [cseq] ACK
      Contact: sip:[field0]@[local_ip]:[local_port]
      Max-Forwards: 100
      Content-Length: 0
    ]]>
  </send>
  <pause milliseconds="5000"/>       >>> Duration after the setup call.
  <send retrans="500">
    <![CDATA[
      BYE [next_url] SIP/2.0
      Via: SIP/2.0/[transport] [local_ip]:5062;branch=z9hG4bK-[call_number]-04
      From: <sip:[field0]@[field1]>;tag=[call_number]
      [last_To:]
      [routes]
      Call-ID: [call_id]
      CSeq: [cseq] BYE
      Contact: sip:sipp@[local_ip]:[local_port]
      Max-Forwards: 100
      Content-Length: 0
    ]]>
  </send>
  <recv response="200" crlf="true">
  </recv>
  <ResponseTimeRepartition value="10, 20, 30, 40, 50, 100, 150, 200"/>
  <CallLengthRepartition value="10, 50, 100, 500, 1000, 5000, 10000"/>
</scenario>


Also, you can see .csv file to fill fields in .xml file below;

SEQUENTIAL
<username>;<remote_server>;[authentication username=xxx password=xxx];<called_number>;

After this configurations, execute this command on your linux server;
./sipp <remote_server> -sf sample.xml -inf sample.csv -m 1 



SIPp can be launched in background mode (-bg command line option). But to run in background, I used "export TERM=vt100" in bash script.
Also, in command line, there are many features to offer more effective sip testing.  You can determine port number, username, transport mode, local ip address, duration etc. More features check this link.


Let’s start to create python code to get CDRs from db server. In this case, we need to a stored procedure that created from db admin, then we can send request to db server with python. In addition, you can send your CDRs any e-mail address by python.

That is my python code to get CDRs:



import pandas as pd
import smtplib
import logging
import time
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import pyodbc
import json
import argparse
import cgi, cgitb

def getCdr(conn, anumber, bnumber): 
    oCursor = conn.cursor()

    sql = """\
    EXEC cdr_list @anumber=?, @bnumber=?
    """
    params = (anumber,bnumber)
    oCursor.execute(sql, params)
     result = "0"

    for row in oCursor:
        result = row[0]

    return (result)

def send_email(text):

    sender = "source@domain_address"
    recipient = "egemenu@domain_address"
    subj = "CDR"

    msg = MIMEMultipart('alternative')
    msg['Subject'] = subj
    msg['From'] = sender
    msg['To'] = recipient
    msg.attach(MIMEText(text, 'plain'))


    try:
        a = msg.as_string()
        s = smtplib.SMTP('1.1.1.1)
        s.sendmail(sender, recipient, a )
        s.quit()

        return True
    except:
        return False

def main():
    #connectin to the db with SQL Authentification

  try:
    conn = pyodbc.connect(driver = '/usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so', server = 1.1.1.1, TDS_Version = '7.0', PORT = "xxxx",
        database = 'db_name', uid = ‘username’, pwd = 'password’)

    true_or_false0 =  getCdr(conn, "anumber", "bnumber")
    true_or_false1 =  getCdr(conn, "anumber", "bnumber")
    true_or_false2 =  getCdr(conn, "anumber", "bnumber")
    true_or_false3 =  getCdr(conn, "anumber", "bnumber")
    true_or_false4 =  getCdr(conn, "anumber", "bnumber")

    results={} 
    results['CDR RESULTS >> 1: Successful, 0: Fail, -1: Not Found'] = [true_or_false,true_or_false2,true_or_false3,true_or_false4,true_or_false6]

    return send_email(json.dumps(results, indent = 4, sort_keys=True).replace('\\r\\n', '\n"'))
    conn.close()

  except Exception as e: print(e) 

if __name__ == "__main__":
   res=main()







Now, we’re done to create main basic bash script;



#!/bin/bash
export TERM=vt100
./sipp remote_server -sf sample.xml -inf sample_1.csv -m 1
sleep 20
./sipp remote_server -sf sample.xml -inf sample_2.csv -m 1
sleep 20
./sipp remote_server -sf sample.xml -inf sample_3.csv -m 1
sleep 20
./sipp remote_server -sf sample.xml -inf sample_4.csv -m 1
sleep 20
./sipp remote_server -sf sample.xml -inf sample_5.csv -m 1
sleep 20
python test_getting_cdr.py



With this script, it’ll make 5 calls and then get CDRs in order to check their results.
If you add this main script your crontab, It can run every day or when you want so you find opportunity to check your network.

The informations appeared in e-mail like this;

{
    "CDR RESULTS   >>   1: Successful, 0: Fail, -1: Not Found": [


        "a_number   >>    b0_number    #    1 ",
        "a_number   >>    b1_number    #    1 ",
        "a_number   >>    b2_number    #    1 ",
        "a_number   >>    b3_number    #    0 ",
        "a_number   >>    b4_number    #    0 "


    ]
}

But pay attention when you edit crontab. If you execute ‘crontab -l’ before edit it, that will be better, because you may run ‘crontab -r’ instead of ‘crontab -e’ by mistake. :)

Please do not hesitate to ask any question about this case via e-mail...


No comments:

Post a Comment