TT#36303 support bandwidth usage resource limit

Also fixes logic for other resource limits

Change-Id: I263e097da5b5671826e0d92a28fb3a5c6f3ac193
changes/75/21175/2
Richard Fuchs 8 years ago
parent 6da7494a08
commit 14ffd8feb0

@ -219,6 +219,7 @@ option and which are reproduced below:
--max-sessions=INT Limit the number of maximum concurrent sessions
--max-load=FLOAT Reject new sessions if load averages exceeds this value
--max-cpu=FLOAT Reject new sessions if CPU usage (in percent) exceeds this value
--max-bandwidth=INT Reject new sessions if bandwidth usage (in bytes per second) exceeds this value
--homer=IP46:PORT Address of Homer server for RTCP stats
--homer-protocol=udp|tcp Transport protocol for Homer (default udp)
--homer-id=INT 'Capture ID' to use within the HEP protocol
@ -520,9 +521,16 @@ The options are described in more detail below.
* --max-cpu
If the current CPU usage (in percent) exceeds the value given here, reject new sessions until
the load average drops below the threshold. CPU usage is sampled in 0.5 second intervals. Only
the CPU usage drops below the threshold. CPU usage is sampled in 0.5-second intervals. Only
supported on systems providing a Linux-style `/proc/stat`.
* --max-bandwidth
If the current bandwidth usage (in bytes per second) exceeds the value given here,
reject new sessions until
the bandwidth usage drops below the threshold. Bandwidth usage is sampled in 1-second intervals
and is based on received packets, not sent packets.
* --homer
Enables sending the decoded contents of RTCP packets to a Homer SIP capture server. The transport

@ -747,7 +747,7 @@ static enum load_limit_reasons call_offer_session_limit(void) {
rwlock_unlock_r(&rtpe_callhash_lock);
}
if (!ret && rtpe_config.load_limit) {
if (ret == LOAD_LIMIT_NONE && rtpe_config.load_limit) {
int loadavg = g_atomic_int_get(&load_average);
if (loadavg >= rtpe_config.load_limit) {
ilog(LOG_WARN, "Load limit exceeded (%.2f > %.2f)",
@ -756,7 +756,7 @@ static enum load_limit_reasons call_offer_session_limit(void) {
}
}
if (!ret && rtpe_config.cpu_limit) {
if (ret == LOAD_LIMIT_NONE && rtpe_config.cpu_limit) {
int cpu = g_atomic_int_get(&cpu_usage);
if (cpu >= rtpe_config.cpu_limit) {
ilog(LOG_WARN, "CPU usage limit exceeded (%.1f%% > %.1f%%)",
@ -765,6 +765,15 @@ static enum load_limit_reasons call_offer_session_limit(void) {
}
}
if (ret == LOAD_LIMIT_NONE && rtpe_config.bw_limit) {
uint64_t bw = atomic64_get(&rtpe_stats.bytes);
if (bw >= rtpe_config.bw_limit) {
ilog(LOG_WARN, "Bandwidth limit exceeded (%" PRIu64 " > %" PRIu64 ")",
bw, rtpe_config.bw_limit);
ret = LOAD_LIMIT_BW;
}
}
rwlock_unlock_r(&rtpe_config.config_lock);
return ret;

@ -46,6 +46,7 @@ static void cli_incoming_set_maxopenfiles(str *instr, struct streambuf *replybuf
static void cli_incoming_set_maxsessions(str *instr, struct streambuf *replybuffer);
static void cli_incoming_set_maxcpu(str *instr, struct streambuf *replybuffer);
static void cli_incoming_set_maxload(str *instr, struct streambuf *replybuffer);
static void cli_incoming_set_maxbw(str *instr, struct streambuf *replybuffer);
static void cli_incoming_set_timeout(str *instr, struct streambuf *replybuffer);
static void cli_incoming_set_silenttimeout(str *instr, struct streambuf *replybuffer);
static void cli_incoming_set_offertimeout(str *instr, struct streambuf *replybuffer);
@ -65,8 +66,10 @@ static void cli_incoming_list_numsessions(str *instr, struct streambuf *replybuf
static void cli_incoming_list_maxsessions(str *instr, struct streambuf *replybuffer);
static void cli_incoming_list_maxcpu(str *instr, struct streambuf *replybuffer);
static void cli_incoming_list_maxload(str *instr, struct streambuf *replybuffer);
static void cli_incoming_list_maxbw(str *instr, struct streambuf *replybuffer);
static void cli_incoming_list_maxopenfiles(str *instr, struct streambuf *replybuffer);
static void cli_incoming_list_totals(str *instr, struct streambuf *replybuffer);
static void cli_incoming_list_counters(str *instr, struct streambuf *replybuffer);
static void cli_incoming_list_sessions(str *instr, struct streambuf *replybuffer);
static void cli_incoming_list_timeout(str *instr, struct streambuf *replybuffer);
static void cli_incoming_list_silenttimeout(str *instr, struct streambuf *replybuffer);
@ -96,6 +99,7 @@ static const cli_handler_t cli_set_handlers[] = {
{ "maxsessions", cli_incoming_set_maxsessions },
{ "maxcpu", cli_incoming_set_maxcpu },
{ "maxload", cli_incoming_set_maxload },
{ "maxbw", cli_incoming_set_maxbw },
{ "timeout", cli_incoming_set_timeout },
{ "silenttimeout", cli_incoming_set_silenttimeout },
{ "offertimeout", cli_incoming_set_offertimeout },
@ -112,10 +116,12 @@ static const cli_handler_t cli_list_handlers[] = {
{ "numsessions", cli_incoming_list_numsessions },
{ "sessions", cli_incoming_list_sessions },
{ "totals", cli_incoming_list_totals },
{ "counters", cli_incoming_list_counters },
{ "maxopenfiles", cli_incoming_list_maxopenfiles },
{ "maxsessions", cli_incoming_list_maxsessions },
{ "maxcpu", cli_incoming_list_maxcpu },
{ "maxload", cli_incoming_list_maxload },
{ "maxbw", cli_incoming_list_maxbw },
{ "timeout", cli_incoming_list_timeout },
{ "silenttimeout", cli_incoming_list_silenttimeout },
{ "offertimeout", cli_incoming_list_offertimeout },
@ -229,7 +235,8 @@ static void cli_incoming_params_start(str *instr, struct streambuf *replybuffer)
"redis-write = %s:%d/%d\nno-redis-required = %d\nnum-threads = %d\nxmlrpc-format = %d\nlog_format = %d\n"
"redis_allowed_errors = %d\nredis_disable_time = %d\nredis_cmd_timeout = %d\nredis_connect_timeout = %d\n"
"max-cpu = %.1f\n"
"max-load = %.2f\n",
"max-load = %.2f\n"
"max-bandwidth = %" PRIu64 "\n",
initial_rtpe_config.kernel_table, initial_rtpe_config.max_sessions, initial_rtpe_config.timeout,
initial_rtpe_config.silent_timeout, initial_rtpe_config.final_timeout, initial_rtpe_config.offer_timeout,
initial_rtpe_config.delete_delay,
@ -242,7 +249,8 @@ static void cli_incoming_params_start(str *instr, struct streambuf *replybuffer)
initial_rtpe_config.fmt, initial_rtpe_config.log_format, initial_rtpe_config.redis_allowed_errors,
initial_rtpe_config.redis_disable_time, initial_rtpe_config.redis_cmd_timeout, initial_rtpe_config.redis_connect_timeout,
(double) initial_rtpe_config.cpu_limit / 100,
(double) initial_rtpe_config.load_limit / 100);
(double) initial_rtpe_config.load_limit / 100,
initial_rtpe_config.bw_limit);
for(s = initial_rtpe_config.interfaces.head; s ; s = s->next) {
ifa = s->data;
@ -277,7 +285,8 @@ static void cli_incoming_params_current(str *instr, struct streambuf *replybuffe
"redis-write-db = %d\nno-redis-required = %d\nnum-threads = %d\nxmlrpc-format = %d\nlog_format = %d\n"
"redis_allowed_errors = %d\nredis_disable_time = %d\nredis_cmd_timeout = %d\nredis_connect_timeout = %d\n"
"max-cpu = %.1f\n"
"max-load = %.2f\n",
"max-load = %.2f\n"
"max-bw = %" PRIu64 "\n",
rtpe_config.kernel_table, rtpe_config.max_sessions, rtpe_config.timeout, rtpe_config.silent_timeout,
rtpe_config.final_timeout,
rtpe_config.offer_timeout,
@ -288,7 +297,8 @@ static void cli_incoming_params_current(str *instr, struct streambuf *replybuffe
rtpe_config.num_threads, rtpe_config.fmt, rtpe_config.log_format, rtpe_config.redis_allowed_errors,
rtpe_config.redis_disable_time, rtpe_config.redis_cmd_timeout, rtpe_config.redis_connect_timeout,
(double) rtpe_config.cpu_limit / 100,
(double) rtpe_config.load_limit / 100);
(double) rtpe_config.load_limit / 100,
rtpe_config.bw_limit);
for(c = rtpe_config.interfaces.head; c ; c = c->next) {
ifa = c->data;
@ -338,6 +348,7 @@ static void cli_incoming_params_diff(str *instr, struct streambuf *replybuffer)
int_diff_print(initial_rtpe_config.max_sessions, rtpe_config.max_sessions, "max-sessions", replybuffer);
int_diff_print(initial_rtpe_config.cpu_limit, rtpe_config.cpu_limit, "max-cpu", replybuffer);
int_diff_print(initial_rtpe_config.load_limit, rtpe_config.load_limit, "max-load", replybuffer);
int_diff_print(initial_rtpe_config.bw_limit, rtpe_config.bw_limit, "max-bw", replybuffer);
int_diff_print(initial_rtpe_config.timeout, rtpe_config.timeout, "timeout", replybuffer);
int_diff_print(initial_rtpe_config.silent_timeout, rtpe_config.silent_timeout, "silent-timeout", replybuffer);
int_diff_print(initial_rtpe_config.final_timeout, rtpe_config.final_timeout, "final-timeout", replybuffer);
@ -410,6 +421,16 @@ static void cli_incoming_params_diff(str *instr, struct streambuf *replybuffer)
}
static void cli_incoming_list_counters(str *instr, struct streambuf *replybuffer) {
streambuf_printf(replybuffer, "\nCurrent per-second counters:\n\n");
streambuf_printf(replybuffer, " Packets per second :%" PRIu64 "\n",
atomic64_get(&rtpe_stats.packets));
streambuf_printf(replybuffer, " Bytes per second :%" PRIu64 "\n",
atomic64_get(&rtpe_stats.bytes));
streambuf_printf(replybuffer, " Errors per second :%" PRIu64 "\n",
atomic64_get(&rtpe_stats.errors));
}
static void cli_incoming_list_totals(str *instr, struct streambuf *replybuffer) {
struct timeval avg, calls_dur_iv;
u_int64_t num_sessions, min_sess_iv, max_sess_iv;
@ -536,6 +557,14 @@ static void cli_incoming_list_maxload(str *instr, struct streambuf *replybuffer)
return ;
}
static void cli_incoming_list_maxbw(str *instr, struct streambuf *replybuffer) {
/* don't lock anything while reading the value */
streambuf_printf(replybuffer, "Maximum bandwidth configured on rtpengine: %" PRIu64 "\n",
rtpe_config.bw_limit);
return ;
}
static void cli_incoming_list_maxopenfiles(str *instr, struct streambuf *replybuffer) {
struct rlimit rlim;
pid_t pid = getpid();
@ -892,6 +921,33 @@ static void cli_incoming_set_maxload(str *instr, struct streambuf *replybuffer)
return;
}
static void cli_incoming_set_maxbw(str *instr, struct streambuf *replybuffer) {
char *endptr;
if (str_shift(instr, 1)) {
streambuf_printf(replybuffer, "%s\n", "More parameters required.");
return;
}
errno = 0;
uint64_t num = strtoull(instr->s, &endptr, 10);
if ((errno == ERANGE && (num == ULLONG_MAX)) || (errno != 0 && num == 0) ) {
streambuf_printf(replybuffer, "Fail setting maxbw to %s; errno=%d\n", instr->s, errno);
return;
} else if (endptr == instr->s) {
streambuf_printf(replybuffer, "Fail setting maxbw to %s; no digists found\n", instr->s);
return;
} else {
rwlock_lock_w(&rtpe_config.config_lock);
rtpe_config.bw_limit = num * 100;
rwlock_unlock_w(&rtpe_config.config_lock);
streambuf_printf(replybuffer, "Success setting maxbw to %" PRIu64 "\n", num);
}
return;
}
static void cli_incoming_set_gentimeout(str *instr, struct streambuf *replybuffer, int *conf_timeout) {
long timeout_num;
char *endptr;

@ -24,6 +24,7 @@ const char magic_load_limit_strings[__LOAD_LIMIT_MAX][64] = {
[LOAD_LIMIT_MAX_SESSIONS] = "Parallel session limit reached",
[LOAD_LIMIT_CPU] = "CPU usage limit exceeded",
[LOAD_LIMIT_LOAD] = "Load limit exceeded",
[LOAD_LIMIT_BW] = "Bandwidth limit exceeded",
};

@ -40,6 +40,7 @@ enum load_limit_reasons {
LOAD_LIMIT_MAX_SESSIONS = 0,
LOAD_LIMIT_CPU,
LOAD_LIMIT_LOAD,
LOAD_LIMIT_BW,
__LOAD_LIMIT_MAX
};

@ -294,6 +294,7 @@ static void options(int *argc, char ***argv) {
{ "max-sessions", 0, 0, G_OPTION_ARG_INT, &rtpe_config.max_sessions, "Limit of maximum number of sessions", "INT" },
{ "max-load", 0, 0, G_OPTION_ARG_DOUBLE, &max_load, "Reject new sessions if load averages exceeds this value", "FLOAT" },
{ "max-cpu", 0, 0, G_OPTION_ARG_DOUBLE, &max_cpu, "Reject new sessions if CPU usage (in percent) exceeds this value", "FLOAT" },
{ "max-bandwidth",0, 0, G_OPTION_ARG_INT64, &rtpe_config.bw_limit, "Reject new sessions if bandwidth usage (in bytes per second) exceeds this value", "INT" },
{ "homer", 0, 0, G_OPTION_ARG_STRING, &homerp, "Address of Homer server for RTCP stats","IP46|HOSTNAME:PORT"},
{ "homer-protocol",0,0,G_OPTION_ARG_STRING, &homerproto, "Transport protocol for Homer (default udp)", "udp|tcp" },
{ "homer-id", 0, 0, G_OPTION_ARG_STRING, &rtpe_config.homer_id, "'Capture ID' to use within the HEP protocol", "INT" },
@ -465,6 +466,7 @@ void fill_initial_rtpe_cfg(struct rtpengine_config* ini_rtpe_cfg) {
ini_rtpe_cfg->max_sessions = rtpe_config.max_sessions;
ini_rtpe_cfg->cpu_limit = rtpe_config.cpu_limit;
ini_rtpe_cfg->load_limit = rtpe_config.load_limit;
ini_rtpe_cfg->bw_limit = rtpe_config.bw_limit;
ini_rtpe_cfg->timeout = rtpe_config.timeout;
ini_rtpe_cfg->silent_timeout = rtpe_config.silent_timeout;
ini_rtpe_cfg->offer_timeout = rtpe_config.offer_timeout;

@ -70,6 +70,7 @@ struct rtpengine_config {
char *iptables_chain;
int load_limit;
int cpu_limit;
uint64_t bw_limit;
};

@ -139,6 +139,9 @@ void config_load(int *argc, char ***argv, GOptionEntry *app_entries, const char
case G_OPTION_ARG_INT:
CONF_OPTION_GLUE(integer, int);
case G_OPTION_ARG_INT64:
CONF_OPTION_GLUE(uint64, uint64_t);
case G_OPTION_ARG_DOUBLE:
CONF_OPTION_GLUE(double, double);

Loading…
Cancel
Save