diff --git a/apps/mobile_push/load_test/call_gen.py b/apps/mobile_push/load_test/call_gen.py new file mode 100755 index 00000000..49501802 --- /dev/null +++ b/apps/mobile_push/load_test/call_gen.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python +from xmlrpclib import * +s = ServerProxy('http://127.0.0.1:8092') +print s.setTarget(100, 1, 0, '4', '192.168.5.110', 2, 0, 30, 40) + diff --git a/apps/mobile_push/load_test/mobilepush_loadtest.txt b/apps/mobile_push/load_test/mobilepush_loadtest.txt new file mode 100644 index 00000000..ff0d549e --- /dev/null +++ b/apps/mobile_push/load_test/mobilepush_loadtest.txt @@ -0,0 +1,105 @@ +this is a small set of scripts and config files to do load tests on the +mobile-push application. It uses another SEMS instance to register/deregister +users using db_reg_agent module, and place calls using call_gen application. + +both sems instances are expected to run on 192.168.5.110 - if that IP is +different, it needs to be changed in some (many) places. + +1. create users 400..499 (pwd 400..499) in kamailio with + for ((i=400;i<500;i++)); do kamctl add $i $i; done + + 1.b for Kamailio from packages (default config), + - enable: + #!define WITH_MYSQL + #!define WITH_PRESENCE + undefine WITH_AUTH + + - add to presence loading section: + #!ifdef WITH_PRESENCE + loadmodule "presence.so" + loadmodule "presence_xml.so" + + # reginfo related + loadmodule "presence_reginfo.so" + loadmodule "pua.so" + loadmodule "pua_reginfo.so" + #!endif + + - add to presence config section: + #!ifdef WITH_PRESENCE + # ----- presence params ----- + modparam("presence", "db_url", DBURL) + + # ----- presence_xml params ----- + modparam("presence_xml", "db_url", DBURL) + modparam("presence_xml", "force_active", 1) + + # reginfo related + modparam("pua_reginfo", "default_domain", "192.168.5.110") + modparam("pua_reginfo", "publish_reginfo", 1) + modparam("pua_reginfo", "server_address", "sip:reginfo@192.168.5.110") + + - remove auth check in request_route (easier) + # authentication + # if (!is_method("SUBSCRIBE|NOTIFY")) { + # route(AUTH); + # } + + - add SERVICES route to route calls to sems: + # dispatch requests to foreign domains + route(SIPOUT); + + route(SERVICES); + + ... + + route[SERVICES] { + + if (method=="INVITE") { + if ((uri=~"sip:38") || (uri=~"sip:4")) + { + + # $ru = "sip:" + $rU + "@" + "192.168.5.110:5080"; + append_hf("P-App-Param: audio_id=connecting;caller=+492222222222;callee=+491111111111;domain=sip.sipwise.com\r\n"); + append_hf("P-hint: services\r\n"); + t_relay_to("192.168.5.110:5080"); + exit(); + } + } + } + + +2. create database tables for sems with: + +CREATE TABLE `registrations` ( + `subscriber_id` int(11) NOT NULL, + `registration_status` tinyint(1) NOT NULL DEFAULT '0', + `last_registration` datetime NOT NULL, + `expiry` datetime NOT NULL, + `last_code` smallint(2) NOT NULL, + `last_reason` varchar(256) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, + `contacts` varchar(512) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, + PRIMARY KEY (`subscriber_id`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + +CREATE TABLE `subscribers` ( + `subscriber_id` int(10) NOT NULL AUTO_INCREMENT, + `user` varchar(256) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, + `pass` varchar(256) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, + `realm` varchar(256) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, + `contact` varchar(256) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, + PRIMARY KEY (`subscriber_id`) +) ENGINE=MyISAM AUTO_INCREMENT=20005 DEFAULT CHARSET=latin1; + +3. set mysql pwd in db_reg_agent.conf + +4. start load gen sems instance with the configuration given here. + (git clone git://git.sip-router.org/sems ; cp -R sems_cfg/* sems ; cd sems ; make -C apps/xmlrpc2di ; + make -C apps/examples/call_gen; make -C apps/db_reg_agent; make -C core ; cd core ; + ./sems -f etc/sems.conf -D 3 -E ) + +5. run reg_client.py, which will very quickly register and deregister subscribers + by calling removeRegistration/createRegistration on the load gen sems instance + +6. run call_gen.py to set a target of 100 calls (or run sth like +s.createCalls(1, 1, 0, '4', '192.168.5.110', 2, 0, 30, 40) to create one call for testing first diff --git a/apps/mobile_push/load_test/reg_client.py b/apps/mobile_push/load_test/reg_client.py new file mode 100755 index 00000000..01a4972b --- /dev/null +++ b/apps/mobile_push/load_test/reg_client.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +from xmlrpclib import * +from random import * +import time + +s = ServerProxy('http://127.0.0.1:8092') + +r = set() + +while True: + n = randint(400, 499) + if n in r: + print s.removeRegistration(n) + r.remove(n) + else: + print s.createRegistration(n, str(n), str(n), '192.168.5.110') + r.add(n) + + time.sleep(.1) \ No newline at end of file diff --git a/apps/mobile_push/load_test/sems_cfg/core/etc/callgen.conf b/apps/mobile_push/load_test/sems_cfg/core/etc/callgen.conf new file mode 100644 index 00000000..401615ad --- /dev/null +++ b/apps/mobile_push/load_test/sems_cfg/core/etc/callgen.conf @@ -0,0 +1,3 @@ +play_file=wav/default_en.wav +digits_dir=../apps/examples/call_gen/wav/ +from_host=callgen.example.net \ No newline at end of file diff --git a/apps/mobile_push/load_test/sems_cfg/core/etc/db_reg_agent.conf b/apps/mobile_push/load_test/sems_cfg/core/etc/db_reg_agent.conf new file mode 100644 index 00000000..4f878350 --- /dev/null +++ b/apps/mobile_push/load_test/sems_cfg/core/etc/db_reg_agent.conf @@ -0,0 +1,99 @@ +# Database connection +mysql_user=root +mysql_passwd=mysqlrootpwd + +# mysql_server, default: localhost +# mysql_server=localhost + +#mysql_db, default: sems +# mysql_db=sems + +# table for registration status +# default: registrations +# registrations_table="registrations" + +# query joining subscriber info with registration table +joined_query="select subscribers.subscriber_id as subscriber_id, subscribers.user as user, subscribers.pass as pass, subscribers.realm as realm, registrations.registration_status as registration_status, registrations.expiry as expiry, registrations.last_registration as last_registration from subscribers left join registrations on subscribers.subscriber_id=registrations.subscriber_id;" + +#example with contact: +# joined_query="select subscribers.subscriber_id as subscriber_id, subscribers.user as user, subscribers.pass as pass, subscribers.realm as realm, subscribers.contact as contact, registrations.registration_status as registration_status, registrations.expiry as expiry, registrations.last_registration as last_registration from subscribers left join registrations on subscribers.subscriber_id=registrations.subscriber_id;" + +# outbound_proxy= +# set the outbound proxy to send registrations through +# +#outbound_proxy=sip:10.0.0.2:5070 + +# contact_hostport= - overriding contact host:port +# sets the contact host:port portion that is registered +# default: empty +#contact_hostport=10.0.0.50:5080 + +# db_read_contact=[yes, no] : read individual contact to register from DB? +# note: joined_query must select the contact, too +# default: no +#db_read_contact=yes + +#save_contacts=[yes, no] : save contacts? +# for monitoring and troubleshooting, all contacts returned with a positive reply +# may be saved to DB in the registrations.contacts colums +# default: yes +#save_contacts=yes + +#save_auth_replies=[yes, no] : update status on 401 replies (auth)? +# usually, 401 replies which are resent with auth are not saved. if save_auth_replies=yes, +# last_code and last_reason in DB is updated with the 401 +#save_auth_replies=yes + +# expires: desired expires, i.e. expires value that is requested +# default: 7200 +# expires=300 + +# error_retry_interval +# +# default: 300 + +# reregister_interval: fraction of actual expires after which register is refreshed +# default: reregister_interval=0.5 +#reregister_interval=0.5 + +# minimum_reregister_interval: if set, re-register is scheduled in least loaded time +# in minimum_reregister_interval .. reregister_interval i order to smooth load spikes +# must be smaller than reregister_interval +# default: off +# +# example: +# reregister_interval=0.5 +# minimum_reregister_interval=0.4 +# on a registration expiring in 3600s, the least loaded spot between 1440s and 1800s +# is chosen +# +#minimum_reregister_interval=0.4 + +# enable_ratelimiting=yes : Enable ratelimiting? +# default: no +# if enabled, the amount of initial REGISTER requests is limited (not counting re-trans- +# missions and requests re-sent for authentication) +#enable_ratelimiting=yes + +# ratelimit_rate=300 : rate of initial REGISTER requests to send as maximum +#ratelimit_rate=2 + +# ratelimit_per=1 : per time unit (in seconds, e.g. 300 REGISTER in 1 second) +#ratelimit_per=1 + +#ratelimit_slowstart=[yes|no] : on startup send initially ratelimit_rate or 0 requests +#default: no +#ratelimit_slowstart=yes + +# delete_removed_registrations=yes : delete removed registrations from registrations +# table in DB? (otherwise they will stay with STATUS_REMOVED) +# default: yes +# +#delete_removed_registrations=no + +# delete_failed_deregistrations=yes : delete failed de-registrations from registrations +# table in DB? (otherwise they will stay with STATUS_TO_BE_REMOVED) +# only applicable if delete_removed_registrations=yes +# default: no +# +#delete_failed_deregistrations=no diff --git a/apps/mobile_push/load_test/sems_cfg/core/etc/sems.conf b/apps/mobile_push/load_test/sems_cfg/core/etc/sems.conf new file mode 100644 index 00000000..a28fa2c8 --- /dev/null +++ b/apps/mobile_push/load_test/sems_cfg/core/etc/sems.conf @@ -0,0 +1,544 @@ +# $Id$ +# +# sems.conf.sample +# +# Sip Express Media Server (sems) +# +# sample configuration file +# +# +# whitespaces (spaces and tabs) are ignored +# comments start with a "#" and may be used inline +# +# example: option=value # i like this option +# +# @filename includes mod_config_path/filename +# @/absolute/path/to/file includes file + +############################################################ +# Network configuration + +# optional parameter: media_ip=| +# +# - this informs SEMS about the IP address or interface that +# SEMS uses to send and receive media. +# - If neither 'media_ip' nor 'sip_ip' are set, defaults +# to first non-loopback interface. If 'sip_ip' is set, +# 'media_ip' defaults to 'sip_ip. +# +# Examples: +# media_ip=10.0.0.34 +# media_ip=eth0 + +# optional parameter: sip_ip=| +# +# - this informs SEMS about the SIP IP where its SIP stack is +# bound to or should be bound to. This also sets +# the value used for contact header in outgoing calls and +# registrations. +# - If neither 'media_ip' nor 'sip_ip' are set, defaults +# to first non-loopback interface. If 'media_ip' is set, +# 'sip_ip' defaults to 'media_ip. +# +# Example: +# sip_ip=10.0.0.34 +# sip_ip=en0 +# + +# optional parameter: public_ip= +# +# - when running SEMS behind certain simple NAT configurations, +# you can use this parameter to inform SEMS of its public IP +# address. If this parameter is set, SEMS will write this value +# into SDP bodies. +# If this parameter is not set, the local IP address is used. +# N.B., there is no support for port translation; the local +# RTP port is advertised in SDP in either case. +# +# Example: +# public_ip=75.101.219.48 +# + +# optional parameter: sip_port= +# +# - this informs SEMS about the port where its SIP stack is +# bound to or should be bound to. SEMS needs this information +# to correctly set the contact header in outgoing calls +# and registrations. Should be set to equal the 'port' +# configuration option in ser_sems.cfg. +# +# default: 5060 +# +sip_port=5080 + +# optional parameter: outbound_proxy=uri +# +# - this sets an outbound proxy for calls and registrations initiated +# by SEMS. This does not apply to requests in a dialog that +# is initiated by someone else and incoming to SEMS. +# If this is not set (default setting), then for dialogs +# initiated by SEMS the r-uri is resolved and the request +# is sent there directly. +# This is resolved by the SIP stack with DNS if a name is given. +# Warning: If the value set here can not be resolved, no +# requests will be sent out at all! +# +# default: empty +# +# Example: +# outbound_proxy=sip:proxy.mydomain.net + +# optional parameter: force_outbound_proxy={yes|no} +# +# - forces SEMS to send any request to the outbound proxy in any +# situation, by adding an extra first Route to the outbound_proxy. +# This option will only have an effect if the outbound_proxy +# option has been set, and it will break 3261 compatibility +# in some cases; better use next_hop_ip/next_hop_port. +# +# default: no +# +# Example: +# force_outbound_proxy=yes + +# optional parameter: next_hop_ip +# - if this is set, all outgoing requests will be sent to +# this IP, regardless of R-URI etc. +# +#next_hop_ip=192.168.5.106 + +# optional parameter: next_hop_port +# defaults to 5060 +#next_hop_port=5060 + +# optional parameter:next_hop_for_replies +# - use next_hop for replies, too? +# +#next_hop_for_replies=yes + +# optional parameter: rtp_low_port= +# +# - sets lowest for RTP used port +rtp_low_port=10000 + +# optional parameter: rtp_high_port= +# +# - sets highest for RTP used port +rtp_high_port=60000 + +# Additional IFs (optional): +# additional_interfaces = +# +# additional_interfaces must be set if more than one +# interface is to be used for the same purpose (e.g. +# more than one interface for SIP). Configure additional +# interfaces if networks should be bridged or separate +# networks should be served. +# +# For each additional interface, a set of parameters +# suffixed with the interface name should be listed +# with the 'additional_interfaces' parameter. +# +# Please note that for each additional interface, +# 'sip_ip_[if_name]' is mandatory (but can be the interface +# name, then the first assigned IP is used). The other +# parameters are optional. 'media_ip_[if_name]' +# is derived from 'sip_ip_[if_name]' if not set. +# 'public_ip_[ip_name]' is also based on 'sip_ip_[if_name]' +# if not set explicitly. +# +# Example: +# additional_interfaces=intern,extern +# +# sip_ip_intern=192.168.0.5 +# sip_port_intern=5060 +# media_ip_intern=192.168.10.5 +# rtp_low_port_intern=2000 +# rtp_high_port_intern=5000 +# +# sip_ip_extern=213.192.59.73 +# sip_port_extern=5060 +# media_ip_extern=213.192.59.73 +# rtp_low_port_extern=2000 +# rtp_high_port_extern=5000 +# public_ip_extern=213.192.35.73 +# + +############################################################ +# modules and application configuration +# +# Configuration of plugin (module) loading: +# - if load_plugins is set, only those are loaded. +# - if load_plugins is not set, all modules in the plugin_path +# directory are loaded, except those which are listed +# in exclude_plugins. +# + +# optional parameter: plugin_path= +# +# - sets the path to the plug-ins' binaries +# - may be absolute or relative to CWD +plugin_path=/usr/local/lib/sems/plug-in/ + +# optional parameter: load_plugins= +# +# semicolon-separated list of modules to load. +# If empty, all modules in plugin_path are loaded. +# +# example for announcement with only g711 and ilbc codecs +# load_plugins=wav;ilbc;announcement + +# optional parameter: exclude_plugins= +# +# semicolon-separated list of modules to exclude from loading +# ('blacklist'). If empty, all modules in plugin_path are loaded. +# This has only effect it load_plugins is not set. +# +# o precoded_announce: no precoded sample files present +# o py_sems: conflicts with ivr (in some cases) +# o db_reg_agent: needs DB tables +exclude_plugins=precoded_announce;py_sems;db_reg_agent + +# optional: load_plugins_rtld_global= +# +# load these plugins with RTLD_GLOBAL (by default py_sems, +# dsm, ivr, sbc, diameter_client, registrar_client, uac_auth) + +# optional parameter: application +# +# This controls which application is to be executed if there +# is no explicit application requested from the SIP stack +# (i.e. unixsockctrl and second parameter of t_write_unix). +# +# This can be one of +# $(ruri.user) - user part of ruri is taken as application, +# e.g. sip:announcement@host +# $(ruri.param) - uri parameter "app", e.g. +# sip:joe@host.net;app=announcement +# $(apphdr) - the value of the P-App-Name header is used +# +# $(mapping) - regex=>application mapping is read from +# app_mapping.conf (see app_mapping.conf) +# - application name configured here, e.g. +# application=announcement +# +# examples: +# application = conference +# application = $(mapping) +# application = $(ruri.user) +# application = $(ruri.param) +application = $(apphdr) + +# parameter: plugin_config_path= +# +# - in this path configuration files of the applications +# (e.g. announcement.conf) are searched +plugin_config_path=/usr/local/etc/sems/etc/ + +# optional parameter: exclude_payloads= +# +# semicolon-separated list of payloads to exclude from loading +# ('blacklist'). +# +# For example, to only use low bandwidth codecs: +# exclude_payloads=PCMU;PCMA;G726-40;G726-32;G721;L16 +# or, to use only codecs which are not CPU-intensive: +# exclude_payloads=iLBC;speex; +# only use G711 (exclude everything else): +# exclude_payloads=iLBC;speex;G726-40;G726-32;G721;G726-24;G726-16;GSM;L16 + +############################################################ +# logging and running + +# optional parameter: fork={yes|no} +# +# - specifies if sems should run in daemon mode (background) +# (fork=no is the same as -E) +fork=yes + +# optional parameter: stderr={yes|no} +# +# - debug mode: do not fork and log to stderr +# (stderr=yes is the same as -E) +stderr=no + +# optional parameter: loglevel={0|1|2|3} +# +# - sets log level (error=0, warning=1, info=2, debug=3) +# (same as -D) +loglevel=2 + +# optional parameter: syslog_facility={DAEMON|USER|LOCAL[0-7]} +# +# - sets the log facility that is used for syslog. Using this, +# the log can for example be filtered into a special file +# by the syslog daemon. +# +# Default: DAEMON +# +# Example: +# syslog_facility=LOCAL0 + +# optional parameter: log_sessions=[yes|no] +# +# Default: no +# +# If log_sessions=yes is set, INFO level log messages are generated +# for each session when it is started and stopped. +# +# log_sessions=yes + +# optional parameter: log_events=[yes|no] +# +# Default: no +# +# If log_eventy=yes is set, generic DBG level log messages are +# generated for each event that is posted into an event queue. +# +# log_events=yes + +# optional parameter: max_shutdown_time=