diff --git a/README.md b/README.md index 270eb9918..09448932d 100644 --- a/README.md +++ b/README.md @@ -187,6 +187,7 @@ option and which are reproduced below: -g, --graphite=[IP46:]PORT TCP address of graphite statistics server -w, --graphite-interval=INT Graphite data statistics send interval --graphite-prefix=STRING Graphite prefix for every line + --max-sessions=INT Limit the number of maximum concurrent sessions Most of these options are indeed optional, with two exceptions. It's mandatory to specify at least one local IP address through `--interface`, and at least one of the `--listen-...` options must be given. diff --git a/daemon/call.h b/daemon/call.h index e6ea9df55..184f56f42 100644 --- a/daemon/call.h +++ b/daemon/call.h @@ -223,6 +223,7 @@ struct stats { struct totalstats { time_t started; atomic64 total_timeout_sess; + atomic64 total_rejected_sess; atomic64 total_silent_timeout_sess; atomic64 total_regular_term_sess; atomic64 total_forced_term_sess; @@ -427,6 +428,7 @@ struct callmaster_config { GQueue *interfaces; /* struct interface_address */ int port_min; int port_max; + int max_sessions; unsigned int timeout; unsigned int silent_timeout; unsigned int delete_delay; diff --git a/daemon/call_interfaces.c b/daemon/call_interfaces.c index ef361ccef..21bc35684 100644 --- a/daemon/call_interfaces.c +++ b/daemon/call_interfaces.c @@ -738,6 +738,20 @@ out: const char *call_offer_ng(bencode_item_t *input, struct callmaster *m, bencode_item_t *output, const char* addr, const struct sockaddr_in6 *sin) { + static char *errstr[64]; memset(errstr,0,64); + + if (m->conf.max_sessions>0) { + rwlock_lock_r(&m->hashlock); + if (g_hash_table_size(m->callhash) >= m->conf.max_sessions) { + rwlock_unlock_r(&m->hashlock); + atomic64_inc(&m->totalstats.total_rejected_sess); + atomic64_inc(&m->totalstats_interval.total_rejected_sess); + ilog(LOG_ERROR, "Parallel session limit reached (%i)",m->conf.max_sessions); + snprintf(errstr, 64, "Parallel session limit reached (%i)",m->conf.max_sessions); + return errstr; + } + rwlock_unlock_r(&m->hashlock); + } return call_offer_answer_ng(input, m, output, OP_OFFER, addr, sin); } diff --git a/daemon/cli.c b/daemon/cli.c index be4d46ea0..55813c286 100644 --- a/daemon/cli.c +++ b/daemon/cli.c @@ -42,6 +42,8 @@ static void cli_incoming_list_totals(char* buffer, int len, struct callmaster* m ADJUSTLEN(printlen,outbufend,replybuffer); printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total managed sessions :"UINT64F"\n", num_sessions); ADJUSTLEN(printlen,outbufend,replybuffer); + printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total rejected sessions :"UINT64F"\n", atomic64_get(&m->totalstats.total_rejected_sess)); + ADJUSTLEN(printlen,outbufend,replybuffer); printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total timed-out sessions via TIMEOUT :"UINT64F"\n",atomic64_get(&m->totalstats.total_timeout_sess)); ADJUSTLEN(printlen,outbufend,replybuffer); printlen = snprintf(replybuffer,(outbufend-replybuffer), " Total timed-out sessions via SILENT_TIMEOUT :"UINT64F"\n",atomic64_get(&m->totalstats.total_silent_timeout_sess)); diff --git a/daemon/graphite.c b/daemon/graphite.c index 82e8adcff..1b505f95f 100644 --- a/daemon/graphite.c +++ b/daemon/graphite.c @@ -110,6 +110,7 @@ int send_graphite_data() { /* atomically copy values to stack and reset to zero */ atomic64_local_copy_zero_struct(&ts, &cm->totalstats_interval, total_timeout_sess); + atomic64_local_copy_zero_struct(&ts, &cm->totalstats_interval, total_rejected_sess); atomic64_local_copy_zero_struct(&ts, &cm->totalstats_interval, total_silent_timeout_sess); atomic64_local_copy_zero_struct(&ts, &cm->totalstats_interval, total_regular_term_sess); atomic64_local_copy_zero_struct(&ts, &cm->totalstats_interval, total_forced_term_sess); @@ -145,6 +146,8 @@ int send_graphite_data() { rc = sprintf(ptr,"%s.totals.silent_timeout_sess "UINT64F" %llu\n",hostname, atomic64_get_na(&ts.total_silent_timeout_sess),(unsigned long long)g_now.tv_sec); ptr += rc; if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } rc = sprintf(ptr,"%s.totals.timeout_sess "UINT64F" %llu\n",hostname, atomic64_get_na(&ts.total_timeout_sess),(unsigned long long)g_now.tv_sec); ptr += rc; + if (graphite_prefix!=NULL) { rc = sprintf(ptr,"%s.",graphite_prefix); ptr += rc; } + rc = sprintf(ptr,"%s.totals.reject_sess "UINT64F" %llu\n",hostname, atomic64_get_na(&ts.total_rejected_sess),(unsigned long long)g_now.tv_sec); ptr += rc; rc = write(graphite_sock, data_to_send, ptr - data_to_send); if (rc<0) { diff --git a/daemon/main.c b/daemon/main.c index 93c3d5e75..ca2961118 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -101,6 +101,7 @@ static int timeout; static int silent_timeout; static int port_min = 30000; static int port_max = 40000; +static int max_sessions = 0; static u_int32_t redis_ip; static u_int16_t redis_port; static int redis_db = -1; @@ -295,6 +296,7 @@ static void options(int *argc, char ***argv) { { "delete-delay", 'd', 0, G_OPTION_ARG_INT, &delete_delay, "Delay for deleting a session from memory.", "INT" }, { "sip-source", 0, 0, G_OPTION_ARG_NONE, &sip_source, "Use SIP source address by default", NULL }, { "dtls-passive", 0, 0, G_OPTION_ARG_NONE, &dtls_passive_def,"Always prefer DTLS passive role", NULL }, + { "max-sessions", 0, 0, G_OPTION_ARG_INT, &max_sessions, "Limit of maximum number of sessions", NULL }, { NULL, } }; @@ -569,6 +571,7 @@ no_kernel: mc.interfaces = &interfaces; mc.port_min = port_min; mc.port_max = port_max; + mc.max_sessions = max_sessions; mc.timeout = timeout; mc.silent_timeout = silent_timeout; mc.delete_delay = delete_delay; diff --git a/debian/ngcp-rtpengine-daemon.default b/debian/ngcp-rtpengine-daemon.default index d06a56e74..afa883027 100644 --- a/debian/ngcp-rtpengine-daemon.default +++ b/debian/ngcp-rtpengine-daemon.default @@ -27,3 +27,4 @@ TABLE=0 # GRAPHITE=9006 # GRAPHITE_INTERVAL=60 # GRAPHITE_PREFIX=myownprefix +# MAX_SESSIONS=5000 diff --git a/debian/ngcp-rtpengine-daemon.init b/debian/ngcp-rtpengine-daemon.init index f3001db7f..7be49ea14 100755 --- a/debian/ngcp-rtpengine-daemon.init +++ b/debian/ngcp-rtpengine-daemon.init @@ -76,6 +76,8 @@ OPTIONS="$OPTIONS --table=$TABLE" [ -z "$GRAPHITE" ] || OPTIONS="$OPTIONS --graphite=$GRAPHITE" [ -z "$GRAPHITE_INTERVAL" ] || OPTIONS="$OPTIONS --graphite-interval=$GRAPHITE_INTERVAL" [ -z "$GRAPHITE_PREFIX" ] || OPTIONS="$OPTIONS --graphite-prefix=$GRAPHITE_PREFIX" +[ -z "$MAX_SESSIONS" ] || OPTIONS="$OPTIONS --max-sessions=$MAX_SESSIONS" + if test "$FORK" = "no" ; then OPTIONS="$OPTIONS --foreground" fi diff --git a/el/rtpengine.init b/el/rtpengine.init index 3cf2930ad..cf3ff51c1 100644 --- a/el/rtpengine.init +++ b/el/rtpengine.init @@ -167,6 +167,11 @@ build_opts() { then OPTS+=" --log-facility-rtcp=$LOG_FACILITY_RTCP" fi + + if [[ -n "$MAX_SESSIONS" ]] + then + OPTS+=" --max-sessions=$MAX_SESSIONS" + fi } start() {