This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
Hoernchen gerrit-no-reply at lists.osmocom.orgHoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-mgw/+/26193 ) Change subject: rework the counters and stats so they work with the threaded mgw ...................................................................... rework the counters and stats so they work with the threaded mgw Main thread has a one-second timer cb that aggregrates and updates the rate counters, as well as the stats, by reading the actual atomic counters that are being updated by the threads. Change-Id: Iaab3fc262649cb5fb886f0297a60286bde1ffeb0 XXY Change-Id: I5e3598f80cb062dbab376663ee51136b4508b78d --- M include/osmocom/mgcp/mgcp_conn.h M include/osmocom/mgcp/mgcp_network.h M include/osmocom/mgcp/mgcp_ratectr.h M include/osmocom/mgcp/mgcp_trunk.h M src/libosmo-mgcp/mgcp_conn.c M src/libosmo-mgcp/mgcp_e1.c M src/libosmo-mgcp/mgcp_endp.c M src/libosmo-mgcp/mgcp_network.c M src/libosmo-mgcp/mgcp_protocol.c M src/libosmo-mgcp/mgcp_ratectr.c M src/libosmo-mgcp/mgcp_stat.c M src/libosmo-mgcp/mgcp_threads.c M src/libosmo-mgcp/mgcp_threads_vty.c M src/libosmo-mgcp/mgcp_vty.c M tests/mgcp/mgcp_test.c 15 files changed, 245 insertions(+), 215 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-mgw refs/changes/93/26193/1 diff --git a/include/osmocom/mgcp/mgcp_conn.h b/include/osmocom/mgcp/mgcp_conn.h index 4f882e9..8ab61d1 100644 --- a/include/osmocom/mgcp/mgcp_conn.h +++ b/include/osmocom/mgcp/mgcp_conn.h @@ -29,6 +29,7 @@ #include <osmocom/core/linuxlist.h> #include <osmocom/core/rate_ctr.h> #include <inttypes.h> +#include <stdatomic.h> #define LOGPCONN(conn, cat, level, fmt, args...) \ LOGPENDP((conn)->endp, cat, level, "CI:%s " fmt, \ @@ -93,7 +94,7 @@ } stats; } osmux; - struct rate_ctr_group *rate_ctr_group; + atomic_uint_least64_t atomic_counters[_MAX_RTP_CTR_NUM]; }; /*! MGCP connection (untyped) */ @@ -131,17 +132,6 @@ void *priv; }; -/* RTP connection related counters */ -enum { - IN_STREAM_ERR_TSTMP_CTR, - OUT_STREAM_ERR_TSTMP_CTR, - RTP_PACKETS_RX_CTR, - RTP_OCTETS_RX_CTR, - RTP_PACKETS_TX_CTR, - RTP_OCTETS_TX_CTR, - RTP_DROPPED_PACKETS_CTR, - RTP_NUM_CONNECTIONS, -}; /* RTP per-connection statistics. Instances of the corresponding rate counter group * exist for the lifetime of an RTP connection. diff --git a/include/osmocom/mgcp/mgcp_network.h b/include/osmocom/mgcp/mgcp_network.h index b9cf5e3..75e6ae6 100644 --- a/include/osmocom/mgcp/mgcp_network.h +++ b/include/osmocom/mgcp/mgcp_network.h @@ -1,6 +1,7 @@ #pragma once #include <inttypes.h> +#include <stdatomic.h> #include <stdbool.h> #include <osmocom/core/socket.h> @@ -23,7 +24,7 @@ uint32_t ssrc; uint16_t last_seq; uint32_t last_timestamp; - struct rate_ctr *err_ts_ctr; + atomic_uint_least64_t err_ts_ctr; int32_t last_tsdelta; uint32_t last_arrival_time; }; diff --git a/include/osmocom/mgcp/mgcp_ratectr.h b/include/osmocom/mgcp/mgcp_ratectr.h index c03c4e1..8c0cb8e 100644 --- a/include/osmocom/mgcp/mgcp_ratectr.h +++ b/include/osmocom/mgcp/mgcp_ratectr.h @@ -1,4 +1,18 @@ #pragma once +#include <stdatomic.h> + +/* RTP connection related counters */ +enum { + IN_STREAM_ERR_TSTMP_CTR, + OUT_STREAM_ERR_TSTMP_CTR, + RTP_PACKETS_RX_CTR, + RTP_OCTETS_RX_CTR, + RTP_PACKETS_TX_CTR, + RTP_OCTETS_TX_CTR, + RTP_DROPPED_PACKETS_CTR, + RTP_NUM_CONNECTIONS, + _MAX_RTP_CTR_NUM +}; /* Global MCGP general rate counters */ enum { @@ -8,6 +22,7 @@ MGCP_GENERAL_RX_MSGS_UNHANDLED, MGCP_GENERAL_RX_FAIL_MSG_PARSE, MGCP_GENERAL_RX_FAIL_NO_ENDPOINT, + _MGCP_GENERAL_NUM_ENUMS, }; /* Trunk-global MCGP CRCX related rate counters */ @@ -28,6 +43,7 @@ MGCP_CRCX_FAIL_BIND_PORT, MGCP_CRCX_FAIL_AVAIL, MGCP_CRCX_FAIL_CLAIM, + _MGCP_CRCX_NUM_ENUMS, }; /* Trunk-global MCGP MDCX related rate counters */ @@ -45,6 +61,7 @@ MGCP_MDCX_FAIL_NO_REMOTE_CONN_DESC, MGCP_MDCX_FAIL_START_RTP, MGCP_MDCX_FAIL_AVAIL, + _MGCP_MDCX_NUM_ENUMS, }; /* Trunk-global MCGP DLCX related rate counters */ @@ -55,13 +72,15 @@ MGCP_DLCX_FAIL_INVALID_CONNID, MGCP_DLCX_FAIL_UNHANDLED_PARAM, MGCP_DLCX_FAIL_AVAIL, + _MGCP_DLCX_NUM_ENUMS, }; /* Trunk-global E1 related counters */ enum { - E1_I460_TRAU_RX_FAIL_CTR, - E1_I460_TRAU_TX_FAIL_CTR, - E1_I460_TRAU_MUX_EMPTY_CTR, + E1_I460_TRAU_RX_FAIL_CTR, + E1_I460_TRAU_TX_FAIL_CTR, + E1_I460_TRAU_MUX_EMPTY_CTR, + _E1_I460_TRAU_NUM_ENUMS, }; /* NOTE: When adding counters, also the dump_ratectr_* routines in vty.c must be updated. */ @@ -69,6 +88,7 @@ struct mgcp_ratectr_global { /* Rate counter group which contains stats for generic MGCP events. */ struct rate_ctr_group *mgcp_general_ctr_group; + atomic_uint_least64_t mgcp_general_ctr_atomic[_MGCP_GENERAL_NUM_ENUMS]; }; struct mgcp_ratectr_trunk { @@ -79,9 +99,18 @@ /* Rate counter group which contains stats for processed DLCX commands. */ struct rate_ctr_group *mgcp_dlcx_ctr_group; /* Rate counter group which aggregates stats of individual RTP connections. */ - struct rate_ctr_group *all_rtp_conn_stats; + struct rate_ctr_group *all_rtp_conn_stats_group; /* Rate counter group which contains stats for E1 events (only valid for E1 trunks) */ - struct rate_ctr_group *e1_stats; + struct rate_ctr_group *e1_stats_group; +}; + +/* as above, but just counters updated by the trunkthreads, then aggregated by the main thread */ +struct mgcp_per_thread_ctr_trunk { + atomic_uint_least64_t mgcp_crcx_ctr_atomic[_MGCP_CRCX_NUM_ENUMS]; + atomic_uint_least64_t mgcp_mdcx_ctr_atomic[_MGCP_MDCX_NUM_ENUMS]; + atomic_uint_least64_t mgcp_dlcx_ctr_atomic[_MGCP_DLCX_NUM_ENUMS]; + atomic_uint_least64_t all_rtp_conn_stats_atomic[_MAX_RTP_CTR_NUM]; + atomic_uint_least64_t e1_stats_atomic[_E1_I460_TRAU_NUM_ENUMS]; }; struct mgcp_config; diff --git a/include/osmocom/mgcp/mgcp_trunk.h b/include/osmocom/mgcp/mgcp_trunk.h index 36032b9..9058b51 100644 --- a/include/osmocom/mgcp/mgcp_trunk.h +++ b/include/osmocom/mgcp/mgcp_trunk.h @@ -27,8 +27,14 @@ struct per_thread_info *thread_info; int num_threads; /* number of threads for this parent trunk, related to thread_info */ bool use_threads; /* enables thread usage, set at cfg parsing time, ALWAYS false for e1/osmux */ - unsigned int number_endpoints_offset; /* offset for proper ep counting, since only the first thread starts at ep0 */ + unsigned int number_endpoints_offset; /* offset for proper ep counting, only first thread starts at ep0 */ struct mgcp_config *cfg; /* global cfg, points at private cfg copy in thread_info for child trunks */ + struct mgcp_per_thread_ctr_trunk thread_ctr; /* counters used by the threads, used by main thread */ + + /* rate counters and stat items to measure the trunks overall performance and health + updated by the main thread by aggregating the per-thread raw counters */ + struct mgcp_ratectr_trunk ratectr; /* NULL for the threads! */ + struct mgcp_stat_trunk stats; /* NULL for the threads! */ /* !!! no thread specific handling below this comment !!! */ @@ -62,10 +68,6 @@ unsigned int number_endpoints; struct mgcp_endpoint **endpoints; - /* rate counters and stat items to measure the trunks overall performance and health */ - struct mgcp_ratectr_trunk ratectr; - struct mgcp_stat_trunk stats; - union { /* Virtual trunk specific */ struct { diff --git a/src/libosmo-mgcp/mgcp_conn.c b/src/libosmo-mgcp/mgcp_conn.c index 1d169f4..19b56bf 100644 --- a/src/libosmo-mgcp/mgcp_conn.c +++ b/src/libosmo-mgcp/mgcp_conn.c @@ -35,15 +35,6 @@ #include <osmocom/core/timer.h> #include <ctype.h> -const static struct rate_ctr_group_desc rate_ctr_group_desc = { - .group_name_prefix = "conn_rtp", - .group_description = "rtp connection statistics", - .class_id = 1, - .num_ctr = ARRAY_SIZE(mgcp_conn_rate_ctr_desc), - .ctr_desc = mgcp_conn_rate_ctr_desc -}; - - /* Allocate a new connection identifier. According to RFC3435, they must * be unique only within the scope of the endpoint. (Caller must provide * memory for id) */ @@ -87,10 +78,6 @@ static int mgcp_rtp_conn_init(struct mgcp_conn_rtp *conn_rtp, struct mgcp_conn *conn) { struct mgcp_rtp_end *end = &conn_rtp->end; - /* FIXME: Each new rate counter group requires an unique index. At the - * moment we generate this index using this counter, but perhaps there - * is a more concious way to assign the indexes. */ - static atomic_uint rate_ctr_index = 0; conn_rtp->type = MGCP_RTP_DEFAULT; conn_rtp->osmux.cid_allocated = false; @@ -111,12 +98,8 @@ end->output_enabled = 0; end->maximum_packet_time = -1; - conn_rtp->rate_ctr_group = rate_ctr_group_alloc(conn, &rate_ctr_group_desc, rate_ctr_index++); - if (!conn_rtp->rate_ctr_group) - return -1; - - conn_rtp->state.in_stream.err_ts_ctr = rate_ctr_group_get_ctr(conn_rtp->rate_ctr_group, IN_STREAM_ERR_TSTMP_CTR); - conn_rtp->state.out_stream.err_ts_ctr = rate_ctr_group_get_ctr(conn_rtp->rate_ctr_group, OUT_STREAM_ERR_TSTMP_CTR); + memset(&conn_rtp->state, 0, sizeof(conn_rtp->state)); + memset(&conn_rtp->atomic_counters, 0, sizeof(conn_rtp->atomic_counters)); /* Make sure codec table is reset */ mgcp_codec_reset_all(conn_rtp); @@ -130,7 +113,6 @@ if (mgcp_conn_rtp_is_osmux(conn_rtp)) conn_osmux_disable(conn_rtp); mgcp_free_rtp_port(&conn_rtp->end); - rate_ctr_group_free(conn_rtp->rate_ctr_group); mgcp_codec_reset_all(conn_rtp); } @@ -258,24 +240,12 @@ static void aggregate_rtp_conn_stats(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn_rtp) { - struct rate_ctr_group *all_stats = endp->trunk->ratectr.all_rtp_conn_stats; - struct rate_ctr_group *conn_stats = conn_rtp->rate_ctr_group; + atomic_uint_least64_t *per_trunk_stats = endp->trunk->thread_ctr.all_rtp_conn_stats_atomic; + atomic_uint_least64_t *per_conn_stats = conn_rtp->atomic_counters; - if (all_stats == NULL || conn_stats == NULL) - return; - - /* Compared to per-connection RTP statistics, aggregated RTP statistics - * contain one additional rate couter item (RTP_NUM_CONNECTIONS). - * All other counters in both counter groups correspond to each other. */ - OSMO_ASSERT(conn_stats->desc->num_ctr + 1 == all_stats->desc->num_ctr); - - /* all other counters are [now] updated in real-time */ - rate_ctr_add(rate_ctr_group_get_ctr(all_stats, IN_STREAM_ERR_TSTMP_CTR), - rate_ctr_group_get_ctr(conn_stats, IN_STREAM_ERR_TSTMP_CTR)->current); - rate_ctr_add(rate_ctr_group_get_ctr(all_stats, OUT_STREAM_ERR_TSTMP_CTR), - rate_ctr_group_get_ctr(conn_stats, OUT_STREAM_ERR_TSTMP_CTR)->current); - - rate_ctr_inc(rate_ctr_group_get_ctr(all_stats, RTP_NUM_CONNECTIONS)); + per_trunk_stats[IN_STREAM_ERR_TSTMP_CTR] += per_conn_stats[IN_STREAM_ERR_TSTMP_CTR]; + per_trunk_stats[OUT_STREAM_ERR_TSTMP_CTR] += per_conn_stats[OUT_STREAM_ERR_TSTMP_CTR]; + per_trunk_stats[RTP_NUM_CONNECTIONS]++; } /*! free a connection by its ID. diff --git a/src/libosmo-mgcp/mgcp_e1.c b/src/libosmo-mgcp/mgcp_e1.c index 807904f..2de0baf 100644 --- a/src/libosmo-mgcp/mgcp_e1.c +++ b/src/libosmo-mgcp/mgcp_e1.c @@ -41,6 +41,7 @@ #include <osmocom/mgcp/mgcp_e1.h> #include <osmocom/mgcp/mgcp_threads.h> #include <osmocom/codec/codec.h> +#include <stdatomic.h> #define DEBUG_BITS_MAX 80 #define DEBUG_BYTES_MAX 40 @@ -192,13 +193,13 @@ static void e1_i460_mux_empty_cb(struct osmo_i460_subchan *schan, void *user_data) { struct mgcp_endpoint *endp = user_data; - struct rate_ctr_group *rate_ctrs = endp->trunk->ratectr.e1_stats; + atomic_uint_least64_t *rate_ctrs = endp->trunk->thread_ctr.e1_stats_atomic; struct msgb *msg = msgb_alloc_c(endp->trunk, E1_TRAU_BITS_MSGB, "E1-I.460-IDLE-TX-TRAU-frame"); uint8_t *ptr; const uint8_t *ptr_ft; enum osmo_trau_frame_type ft; - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, E1_I460_TRAU_MUX_EMPTY_CTR)); + rate_ctrs[E1_I460_TRAU_MUX_EMPTY_CTR]++; /* Choose an appropiate idle frame type */ ft = endp->e1.trau_rtp_st->type; @@ -242,7 +243,7 @@ unsigned int rtp_hdr_len = sizeof(struct rtp_hdr); struct mgcp_endpoint *endp = user_data; struct msgb *msg = msgb_alloc_c(endp->trunk, RTP_BUF_SIZE, "RTP-rx-from-E1"); - struct rate_ctr_group *rate_ctrs = endp->trunk->ratectr.e1_stats; + atomic_uint_least64_t *rate_ctrs = endp->trunk->thread_ctr.e1_stats_atomic; struct mgcp_conn *conn_dst; struct osmo_trau_frame fr; int rc; @@ -305,7 +306,7 @@ msgb_free(msg); return; skip: - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, E1_I460_TRAU_RX_FAIL_CTR)); + rate_ctrs[E1_I460_TRAU_RX_FAIL_CTR]++; msgb_free(msg); return; } @@ -627,7 +628,7 @@ int mgcp_e1_send_rtp(struct mgcp_endpoint *endp, struct mgcp_rtp_codec *codec, struct msgb *msg) { struct msgb *msg_tf = msgb_alloc_c(endp->trunk, E1_TRAU_BITS_MSGB, "E1-I.460-TX-TRAU-frame"); - struct rate_ctr_group *rate_ctrs = endp->trunk->ratectr.e1_stats; + atomic_uint_least64_t *rate_ctrs = endp->trunk->thread_ctr.e1_stats_atomic; unsigned int rtp_hdr_len = sizeof(struct rtp_hdr); struct osmo_trau_frame tf; uint8_t amr_ft; @@ -683,7 +684,7 @@ return 0; skip: - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, E1_I460_TRAU_TX_FAIL_CTR)); + rate_ctrs[E1_I460_TRAU_TX_FAIL_CTR]++; msgb_free(msg_tf); return -1; } diff --git a/src/libosmo-mgcp/mgcp_endp.c b/src/libosmo-mgcp/mgcp_endp.c index 11ef9e0..72d5fdb 100644 --- a/src/libosmo-mgcp/mgcp_endp.c +++ b/src/libosmo-mgcp/mgcp_endp.c @@ -126,8 +126,6 @@ /* We must only decrement the stat item when the endpoint as actually * claimed. An endpoint is claimed when a call-id is set */ if (endp->callid) { - osmo_stat_item_dec(osmo_stat_item_group_get_item(endp->trunk->stats.common, - TRUNK_STAT_ENDPOINTS_USED), 1); endp->trunk->thread_info->eps_free++; } @@ -613,8 +611,6 @@ * connection ids) */ endp->callid = talloc_strdup(endp, callid); OSMO_ASSERT(endp->callid); - osmo_stat_item_inc(osmo_stat_item_group_get_item(endp->trunk->stats.common, - TRUNK_STAT_ENDPOINTS_USED), 1); endp->trunk->thread_info->eps_free--; /* Allocate resources */ diff --git a/src/libosmo-mgcp/mgcp_network.c b/src/libosmo-mgcp/mgcp_network.c index 2d275ec..32ac930 100644 --- a/src/libosmo-mgcp/mgcp_network.c +++ b/src/libosmo-mgcp/mgcp_network.c @@ -21,6 +21,7 @@ * */ +#include <stdatomic.h> #include <string.h> #include <stdlib.h> #include <unistd.h> @@ -62,12 +63,11 @@ static void rtpconn_rate_ctr_add(struct mgcp_conn_rtp *conn_rtp, struct mgcp_endpoint *endp, int id, int inc) { - struct rate_ctr_group *conn_stats = conn_rtp->rate_ctr_group; - struct rate_ctr_group *mgw_stats = endp->trunk->ratectr.all_rtp_conn_stats; + atomic_uint_least64_t *mgw_stats = endp->trunk->thread_ctr.all_rtp_conn_stats_atomic; /* add to both the per-connection and the global stats */ - rate_ctr_add(rate_ctr_group_get_ctr(conn_stats, id), inc); - rate_ctr_add(rate_ctr_group_get_ctr(mgw_stats, id), inc); + conn_rtp->atomic_counters[id] += inc; + mgw_stats[id] += inc; } static void rtpconn_rate_ctr_inc(struct mgcp_conn_rtp *conn_rtp, struct mgcp_endpoint *endp, int id) @@ -192,13 +192,10 @@ } /* Check timestamp and sequence number for plausibility */ -static int check_rtp_timestamp(const struct mgcp_endpoint *endp, - const struct mgcp_rtp_state *state, - const struct mgcp_rtp_stream_state *sstate, - const struct mgcp_rtp_end *rtp_end, - const struct osmo_sockaddr *addr, - uint16_t seq, uint32_t timestamp, - const char *text, int32_t * tsdelta_out) +static int check_rtp_timestamp(const struct mgcp_endpoint *endp, const struct mgcp_rtp_state *state, + struct mgcp_rtp_stream_state *sstate, const struct mgcp_rtp_end *rtp_end, + const struct osmo_sockaddr *addr, uint16_t seq, uint32_t timestamp, const char *text, + int32_t *tsdelta_out) { int32_t tsdelta; int32_t timestamp_error; @@ -210,7 +207,7 @@ if (seq == sstate->last_seq) { if (timestamp != sstate->last_timestamp) { - rate_ctr_inc(sstate->err_ts_ctr); + sstate->err_ts_ctr++; LOGPENDP(endp, DRTP, LOGL_ERROR, "The %s timestamp delta is != 0 but the sequence " "number %d is the same, " @@ -262,7 +259,7 @@ ts_alignment_error(sstate, state->packet_duration, timestamp); if (timestamp_error) { - rate_ctr_inc(sstate->err_ts_ctr); + sstate->err_ts_ctr++; LOGPENDP(endp, DRTP, LOGL_NOTICE, "The %s timestamp has an alignment error of %d " "on SSRC: %u " @@ -1501,8 +1498,8 @@ sizeof(struct sockaddr_in))); /* Increment RX statistics */ - rate_ctr_inc(rate_ctr_group_get_ctr(conn_src->rate_ctr_group, RTP_PACKETS_RX_CTR)); - rate_ctr_add(rate_ctr_group_get_ctr(conn_src->rate_ctr_group, RTP_OCTETS_RX_CTR), msgb_length(msg)); + conn_src->atomic_counters[RTP_PACKETS_RX_CTR]++; + conn_src->atomic_counters[RTP_OCTETS_RX_CTR]++; /* FIXME: count RTP and RTCP separately, also count IuUP payload-less separately */ /* Forward a copy of the RTP data to a debug ip/port */ diff --git a/src/libosmo-mgcp/mgcp_protocol.c b/src/libosmo-mgcp/mgcp_protocol.c index 99f1257..d889238 100644 --- a/src/libosmo-mgcp/mgcp_protocol.c +++ b/src/libosmo-mgcp/mgcp_protocol.c @@ -22,6 +22,7 @@ */ #include <ctype.h> +#include <stdatomic.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -314,18 +315,18 @@ * !! only public for testing !! */ struct msgb *mgcp_handle_message(struct mgcp_config *cfg, struct to_trunkthread_mgcp_msg *w) { - struct rate_ctr_group *rate_ctrs = cfg->ratectr.mgcp_general_ctr_group; + atomic_uint_least64_t *rate_ctrs = cfg->ratectr.mgcp_general_ctr_atomic; int code; ssize_t rc = w->x.msglen; struct mgcp_parse_data *pdata = &w->x.pdata; struct mgcp_request_data *rq = &w->x.rq; /* Count all messages, even incorect ones */ - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_GENERAL_RX_MSGS_TOTAL)); + rate_ctrs[MGCP_GENERAL_RX_MSGS_TOTAL]++; if (rc < sizeof(rq->name) - 1) { LOGP(DLMGCP, LOGL_ERROR, "msg too short: %zd\n", rc); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_GENERAL_RX_FAIL_MSG_PARSE)); + rate_ctrs[MGCP_GENERAL_RX_FAIL_MSG_PARSE]++; return 0; } memcpy(rq->name, (const char *)&w->msg[0], sizeof(rq->name) - 1); @@ -335,7 +336,7 @@ /* attempt to treat it as a response */ if (sscanf((const char *)&w->msg[0], "%3d %*s", &code) == 1) { LOGP(DLMGCP, LOGL_DEBUG, "Response: Code: %d\n", code); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_GENERAL_RX_FAIL_MSG_PARSE)); + rate_ctrs[MGCP_GENERAL_RX_FAIL_MSG_PARSE]++; return 0; } @@ -343,7 +344,7 @@ rc = mgcp_parse_header(pdata, mgcp_strline((char *)&w->msg[4], &pdata->save)); if (rc < 0) { LOGP(DLMGCP, LOGL_ERROR, "%s: failed to parse MCGP message\n", rq->name); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_GENERAL_RX_FAIL_MSG_PARSE)); + rate_ctrs[MGCP_GENERAL_RX_FAIL_MSG_PARSE]++; return create_err_response(cfg, NULL, -rc, rq->name, "000000"); } @@ -418,7 +419,7 @@ { int rc = -500, handled = 0; struct msgb *resp = NULL; - struct rate_ctr_group *rate_ctrs = w->x.rq.trunk->cfg->ratectr.mgcp_general_ctr_group; + atomic_uint_least64_t *rate_ctrs = w->x.rq.trunk->cfg->ratectr.mgcp_general_ctr_atomic; struct mgcp_parse_data *pdata = &w->x.pdata; struct mgcp_request_data *rq = &w->x.rq; @@ -437,7 +438,7 @@ if (rq->wildcarded) { /* we know this is the trunk that handles this wildcarded message */ } else { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_GENERAL_RX_FAIL_NO_ENDPOINT)); + rate_ctrs[MGCP_GENERAL_RX_FAIL_NO_ENDPOINT]++; /* If the endpoint name suggests that the request refers to a specific endpoint, then the * request cannot be handled and we must stop early. */ LOGP(DLMGCP, LOGL_NOTICE, "%s: cannot find endpoint \"%s\", cause=%d -- abort\n", rq->name, @@ -449,7 +450,7 @@ /* Check if we have to retransmit a response from a previous transaction */ if (pdata->trans && rq->endp->last_trans && strcmp(rq->endp->last_trans, pdata->trans) == 0) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_GENERAL_RX_MSGS_RETRANSMITTED)); + rate_ctrs[MGCP_GENERAL_RX_MSGS_RETRANSMITTED]++; return create_retransmission_response(rq->endp); } } @@ -482,9 +483,9 @@ /* Check if the MGCP request was handled and increment rate counters accordingly - but don't count this multiple times */ if (!rq->wildcarded || (rq->wildcarded && !strcmp(rq->name, "CRCX"))) { if (handled) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_GENERAL_RX_MSGS_HANDLED)); + rate_ctrs[MGCP_GENERAL_RX_MSGS_HANDLED]++; } else { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_GENERAL_RX_MSGS_UNHANDLED)); + rate_ctrs[MGCP_GENERAL_RX_MSGS_UNHANDLED]++; LOGP(DLMGCP, LOGL_ERROR, "MSG with type: '%.4s' not handled\n", rq->name); } } @@ -881,7 +882,7 @@ struct mgcp_parse_data *pdata = rq->pdatap; struct mgcp_trunk *trunk = rq->trunk; struct mgcp_endpoint *endp = rq->endp; - struct rate_ctr_group *rate_ctrs = trunk->ratectr.mgcp_crcx_ctr_group; + atomic_uint_least64_t *rate_ctrs = trunk->thread_ctr.mgcp_crcx_ctr_atomic; int error_code = 400; const char *local_options = NULL; const char *callid = NULL; @@ -897,13 +898,13 @@ /* we must have a free ep */ if (!endp) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_AVAIL)); + rate_ctrs[MGCP_CRCX_FAIL_AVAIL]++; LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: no free endpoints available!\n"); return create_err_response(rq->trunk, NULL, 403, "CRCX", pdata->trans); } if (!mgcp_endp_avail(endp)) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_AVAIL)); + rate_ctrs[MGCP_CRCX_FAIL_AVAIL]++; LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: selected endpoint not available!\n"); return create_err_response(rq->trunk, NULL, 501, "CRCX", pdata->trans); @@ -925,7 +926,7 @@ /* It is illegal to send a connection identifier * together with a CRCX, the MGW will assign the * connection identifier by itself on CRCX */ - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_BAD_ACTION)); + rate_ctrs[MGCP_CRCX_FAIL_BAD_ACTION]++; return create_err_response(rq->trunk, NULL, 523, "CRCX", pdata->trans); break; case 'M': @@ -951,7 +952,7 @@ default: LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "CRCX: unhandled option: '%c'/%d\n", *line, *line); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_UNHANDLED_PARAM)); + rate_ctrs[MGCP_CRCX_FAIL_UNHANDLED_PARAM]++; return create_err_response(rq->trunk, NULL, 539, "CRCX", pdata->trans); break; } @@ -962,14 +963,14 @@ if (!callid) { LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: insufficient parameters, missing callid\n"); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_MISSING_CALLID)); + rate_ctrs[MGCP_CRCX_FAIL_MISSING_CALLID]++; return create_err_response(endp, endp, 516, "CRCX", pdata->trans); } if (!mode) { LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: insufficient parameters, missing mode\n"); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_INVALID_MODE)); + rate_ctrs[MGCP_CRCX_FAIL_INVALID_MODE]++; return create_err_response(endp, endp, 517, "CRCX", pdata->trans); } @@ -986,7 +987,7 @@ } else { /* There is no more room for a connection, leave * everything as it is and return with an error */ - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_LIMIT_EXCEEDED)); + rate_ctrs[MGCP_CRCX_FAIL_LIMIT_EXCEEDED]++; return create_err_response(endp, endp, 540, "CRCX", pdata->trans); } } @@ -1004,7 +1005,7 @@ else { /* This is not our call, leave everything as it is and * return with an error. */ - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_UNKNOWN_CALLID)); + rate_ctrs[MGCP_CRCX_FAIL_UNKNOWN_CALLID]++; return create_err_response(endp, endp, 400, "CRCX", pdata->trans); } } @@ -1015,7 +1016,7 @@ * the callid matches up (see above). */ rc = mgcp_endp_claim(endp, callid); if (rc != 0) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_CLAIM)); + rate_ctrs[MGCP_CRCX_FAIL_CLAIM]++; return create_err_response(endp, endp, 502, "CRCX", pdata->trans); } } @@ -1025,7 +1026,7 @@ if (!_conn) { LOGPENDP(endp, DLMGCP, LOGL_ERROR, "CRCX: unable to allocate RTP connection\n"); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_ALLOC_CONN)); + rate_ctrs[MGCP_CRCX_FAIL_ALLOC_CONN]++; goto error2; } @@ -1035,7 +1036,7 @@ if (mgcp_parse_conn_mode(mode, endp, conn->conn) != 0) { error_code = 517; - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_INVALID_MODE)); + rate_ctrs[MGCP_CRCX_FAIL_INVALID_MODE]++; goto error2; } @@ -1045,13 +1046,13 @@ if (osmux_cid >= -1) { /* -1 is wilcard, alloc next avail CID */ conn->osmux.state = OSMUX_STATE_ACTIVATING; if (conn_osmux_allocate_cid(conn, osmux_cid) == -1) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_NO_OSMUX)); + rate_ctrs[MGCP_CRCX_FAIL_NO_OSMUX]++; goto error2; } } else if (endp->trunk->cfg->osmux == OSMUX_USAGE_ONLY) { LOGPCONN(_conn, DLMGCP, LOGL_ERROR, "CRCX: osmux only and no osmux offered\n"); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_NO_OSMUX)); + rate_ctrs[MGCP_CRCX_FAIL_NO_OSMUX]++; goto error2; } @@ -1063,7 +1064,7 @@ LOGPCONN(_conn, DLMGCP, LOGL_ERROR, "CRCX: inavlid local connection options!\n"); error_code = rc; - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_INVALID_CONN_OPTIONS)); + rate_ctrs[MGCP_CRCX_FAIL_INVALID_CONN_OPTIONS]++; goto error2; } } @@ -1073,7 +1074,7 @@ mgcp_codec_summary(conn); if (rc) { error_code = rc; - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_CODEC_NEGOTIATION)); + rate_ctrs[MGCP_CRCX_FAIL_CODEC_NEGOTIATION]++; goto error2; } @@ -1094,7 +1095,7 @@ LOGPCONN(_conn, DLMGCP, LOGL_ERROR, "CRCX: selected connection mode type requires an opposite end!\n"); error_code = 527; - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_NO_REMOTE_CONN_DESC)); + rate_ctrs[MGCP_CRCX_FAIL_NO_REMOTE_CONN_DESC]++; goto error2; } @@ -1102,14 +1103,14 @@ information, then find a free port for it */ mgcp_get_local_addr(conn->end.local_addr, conn); if (allocate_port(endp, conn) != 0) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_BIND_PORT)); + rate_ctrs[MGCP_CRCX_FAIL_BIND_PORT]++; goto error2; } if (setup_rtp_processing(endp, conn) != 0) { LOGPCONN(_conn, DLMGCP, LOGL_ERROR, "CRCX: could not start RTP processing!\n"); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_START_RTP)); + rate_ctrs[MGCP_CRCX_FAIL_START_RTP]++; goto error2; } @@ -1125,7 +1126,7 @@ LOGPCONN(_conn, DLMGCP, LOGL_NOTICE, "CRCX: connection successfully created\n"); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_SUCCESS)); + rate_ctrs[MGCP_CRCX_SUCCESS]++; mgcp_endp_update(endp); /* NOTE: Only in the virtual trunk we allow dynamic endpoint names */ @@ -1144,7 +1145,7 @@ struct mgcp_parse_data *pdata = rq->pdatap; struct mgcp_trunk *trunk = rq->trunk; struct mgcp_endpoint *endp = rq->endp; - struct rate_ctr_group *rate_ctrs = trunk->ratectr.mgcp_mdcx_ctr_group; + atomic_uint_least64_t *rate_ctrs = trunk->thread_ctr.mgcp_mdcx_ctr_atomic; char new_local_addr[INET6_ADDRSTRLEN]; int error_code = 500; int silent = 0; @@ -1163,19 +1164,19 @@ if (rq->wildcarded) { LOGPENDP(endp, DLMGCP, LOGL_ERROR, "MDCX: wildcarded endpoint names not supported.\n"); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_WILDCARD)); + rate_ctrs[MGCP_MDCX_FAIL_WILDCARD]++; return create_err_response(rq->trunk, endp, 507, "MDCX", pdata->trans); } if (!endp || !mgcp_endp_avail(endp)) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_AVAIL)); + rate_ctrs[MGCP_MDCX_FAIL_AVAIL]++; LOGPENDP(endp, DLMGCP, LOGL_ERROR, "MDCX: selected endpoint not available!\n"); return create_err_response(rq->trunk, NULL, 501, "MDCX", pdata->trans); } if (llist_count(&endp->conns) <= 0) { LOGPENDP(endp, DLMGCP, LOGL_ERROR, "MDCX: endpoint is not holding a connection.\n"); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_NO_CONN)); + rate_ctrs[MGCP_MDCX_FAIL_NO_CONN]++; return create_err_response(endp, endp, 400, "MDCX", pdata->trans); } @@ -1186,7 +1187,7 @@ switch (toupper(line[0])) { case 'C': if (mgcp_verify_call_id(endp, line + 3) != 0) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_INVALID_CALLID)); + rate_ctrs[MGCP_MDCX_FAIL_INVALID_CALLID]++; error_code = 516; goto error3; } @@ -1194,7 +1195,7 @@ case 'I': conn_id = (const char *)line + 3; if ((error_code = mgcp_verify_ci(endp, conn_id))) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_INVALID_CONNID)); + rate_ctrs[MGCP_MDCX_FAIL_INVALID_CONNID]++; goto error3; } break; @@ -1225,7 +1226,7 @@ LOGPENDP(endp, DLMGCP, LOGL_NOTICE, "MDCX: Unhandled MGCP option: '%c'/%d\n", line[0], line[0]); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_UNHANDLED_PARAM)); + rate_ctrs[MGCP_MDCX_FAIL_UNHANDLED_PARAM]++; return create_err_response(rq->trunk, NULL, 539, "MDCX", pdata->trans); break; } @@ -1235,13 +1236,13 @@ if (!conn_id) { LOGPENDP(endp, DLMGCP, LOGL_ERROR, "MDCX: insufficient parameters, missing ci (connectionIdentifier)\n"); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_NO_CONNID)); + rate_ctrs[MGCP_MDCX_FAIL_NO_CONNID]++; return create_err_response(endp, endp, 515, "MDCX", pdata->trans); } conn = mgcp_conn_get_rtp(endp, conn_id); if (!conn) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_CONN_NOT_FOUND)); + rate_ctrs[MGCP_MDCX_FAIL_CONN_NOT_FOUND]++; return create_err_response(endp, endp, 400, "MDCX", pdata->trans); } @@ -1249,7 +1250,7 @@ if (mode) { if (mgcp_parse_conn_mode(mode, endp, conn->conn) != 0) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_INVALID_MODE)); + rate_ctrs[MGCP_MDCX_FAIL_INVALID_MODE]++; error_code = 517; goto error3; } @@ -1264,7 +1265,7 @@ LOGPCONN(conn->conn, DLMGCP, LOGL_ERROR, "MDCX: invalid local connection options!\n"); error_code = rc; - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_INVALID_CONN_OPTIONS)); + rate_ctrs[MGCP_MDCX_FAIL_INVALID_CONN_OPTIONS]++; goto error3; } } @@ -1284,7 +1285,7 @@ LOGPCONN(conn->conn, DLMGCP, LOGL_ERROR, "MDCX: selected connection mode type requires an opposite end!\n"); error_code = 527; - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_NO_REMOTE_CONN_DESC)); + rate_ctrs[MGCP_MDCX_FAIL_NO_REMOTE_CONN_DESC]++; goto error3; } @@ -1317,13 +1318,13 @@ osmo_strlcpy(conn->end.local_addr, new_local_addr, sizeof(conn->end.local_addr)); mgcp_free_rtp_port(&conn->end); if (allocate_port(endp, conn) != 0) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_CRCX_FAIL_BIND_PORT)); + rate_ctrs[MGCP_CRCX_FAIL_BIND_PORT]++; goto error3; } } if (setup_rtp_processing(endp, conn) != 0) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_FAIL_START_RTP)); + rate_ctrs[MGCP_MDCX_FAIL_START_RTP]++; goto error3; } @@ -1340,7 +1341,7 @@ trunk->keepalive_interval != MGCP_KEEPALIVE_NEVER) send_dummy(endp, conn); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_MDCX_SUCCESS)); + rate_ctrs[MGCP_MDCX_SUCCESS]++; if (silent) goto out_silent; @@ -1362,7 +1363,7 @@ struct mgcp_parse_data *pdata = rq->pdatap; struct mgcp_trunk *trunk = rq->trunk; struct mgcp_endpoint *endp = rq->endp; - struct rate_ctr_group *rate_ctrs = trunk->ratectr.mgcp_dlcx_ctr_group; + atomic_uint_least64_t *rate_ctrs = trunk->thread_ctr.mgcp_dlcx_ctr_atomic; int error_code = 400; int silent = 0; char *line; @@ -1377,7 +1378,7 @@ LOGPEPTR(endp, trunk, DLMGCP, LOGL_NOTICE, "DLCX: deleting connection(s) ...\n"); if (endp && !mgcp_endp_avail(endp)) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_AVAIL)); + rate_ctrs[MGCP_DLCX_FAIL_AVAIL]++; LOGPENDP(endp, DLMGCP, LOGL_ERROR, "DLCX: selected endpoint not available!\n"); return create_err_response(rq->trunk, NULL, 501, "DLCX", pdata->trans); @@ -1386,7 +1387,7 @@ if (endp && !rq->wildcarded && llist_empty(&endp->conns)) { LOGPENDP(endp, DLMGCP, LOGL_ERROR, "DLCX: endpoint is not holding a connection.\n"); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_NO_CONN)); + rate_ctrs[MGCP_DLCX_FAIL_NO_CONN]++; return create_err_response(endp, endp, 515, "DLCX", pdata->trans); } @@ -1399,7 +1400,7 @@ num_conns += llist_count(&trunk->endpoints[i]->conns); mgcp_endp_release(trunk->endpoints[i]); } - rate_ctr_add(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_SUCCESS), num_conns); + rate_ctrs[MGCP_DLCX_SUCCESS] += num_conns; return create_ok_response(trunk, NULL, 200, "DLCX", pdata->trans); } @@ -1414,13 +1415,13 @@ if (!endp) { LOGPTRUNK(trunk, DLMGCP, LOGL_NOTICE, "cannot handle requests with call-id (C) without endpoint -- abort!"); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM)); + rate_ctrs[MGCP_DLCX_FAIL_UNHANDLED_PARAM]++; return create_err_response(rq->trunk, NULL, 539, "DLCX", pdata->trans); } if (mgcp_verify_call_id(endp, line + 3) != 0) { error_code = 516; - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_INVALID_CALLID)); + rate_ctrs[MGCP_DLCX_FAIL_INVALID_CALLID]++; goto error3; } break; @@ -1430,13 +1431,13 @@ if (!endp) { LOGPTRUNK(trunk, DLMGCP, LOGL_NOTICE, "cannot handle requests with conn-id (I) without endpoint -- abort!"); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM)); + rate_ctrs[MGCP_DLCX_FAIL_UNHANDLED_PARAM]++; return create_err_response(rq->trunk, NULL, 539, "DLCX", pdata->trans); } conn_id = (const char *)line + 3; if ((error_code = mgcp_verify_ci(endp, conn_id))) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_INVALID_CONNID)); + rate_ctrs[MGCP_DLCX_FAIL_INVALID_CONNID]++; goto error3; } break; @@ -1446,7 +1447,7 @@ default: LOGPEPTR(endp, trunk, DLMGCP, LOGL_NOTICE, "DLCX: Unhandled MGCP option: '%c'/%d\n", line[0], line[0]); - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_UNHANDLED_PARAM)); + rate_ctrs[MGCP_DLCX_FAIL_UNHANDLED_PARAM]++; return create_err_response(rq->trunk, NULL, 539, "DLCX", pdata->trans); break; } @@ -1467,7 +1468,7 @@ num_conns); if (num_conns > 0) - rate_ctr_add(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_SUCCESS), num_conns); + rate_ctrs[MGCP_DLCX_SUCCESS] += num_conns; mgcp_endp_release(endp); @@ -1480,7 +1481,7 @@ /* Find the connection */ conn = mgcp_conn_get_rtp(endp, conn_id); if (!conn) { - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_FAIL_INVALID_CONNID)); + rate_ctrs[MGCP_DLCX_FAIL_INVALID_CONNID]++; goto error3; } /* save the statistics of the current connection */ @@ -1500,7 +1501,7 @@ LOGPENDP(endp, DLMGCP, LOGL_DEBUG, "DLCX: endpoint released\n"); } - rate_ctr_inc(rate_ctr_group_get_ctr(rate_ctrs, MGCP_DLCX_SUCCESS)); + rate_ctrs[MGCP_DLCX_SUCCESS]++; if (silent) goto out_silent; return create_ok_resp_with_param(endp, endp, 250, "DLCX", pdata->trans, stats); diff --git a/src/libosmo-mgcp/mgcp_ratectr.c b/src/libosmo-mgcp/mgcp_ratectr.c index 6030ce2..e2b7f59 100644 --- a/src/libosmo-mgcp/mgcp_ratectr.c +++ b/src/libosmo-mgcp/mgcp_ratectr.c @@ -220,24 +220,24 @@ trunk->trunk_nr); rate_ctr_group_set_name(ratectr->mgcp_dlcx_ctr_group, ctr_name); } - if (ratectr->all_rtp_conn_stats == NULL) { - ratectr->all_rtp_conn_stats = rate_ctr_group_alloc(trunk, &all_rtp_conn_rate_ctr_group_desc, - all_rtp_conn_rate_ctr_index++); - if (!ratectr->all_rtp_conn_stats) + if (ratectr->all_rtp_conn_stats_group == NULL) { + ratectr->all_rtp_conn_stats_group = + rate_ctr_group_alloc(trunk, &all_rtp_conn_rate_ctr_group_desc, all_rtp_conn_rate_ctr_index++); + if (!ratectr->all_rtp_conn_stats_group) return -EINVAL; snprintf(ctr_name, sizeof(ctr_name), "%s-%u:rtp_conn", mgcp_trunk_type_strs_str(trunk->trunk_type), trunk->trunk_nr); - rate_ctr_group_set_name(ratectr->all_rtp_conn_stats, ctr_name); + rate_ctr_group_set_name(ratectr->all_rtp_conn_stats_group, ctr_name); } /* E1 specific */ - if (trunk->trunk_type == MGCP_TRUNK_E1 && ratectr->e1_stats == NULL) { - ratectr->e1_stats = rate_ctr_group_alloc(trunk, &e1_rate_ctr_group_desc, mdcx_rate_ctr_index++); - if (!ratectr->e1_stats) + if (trunk->trunk_type == MGCP_TRUNK_E1 && ratectr->e1_stats_group == NULL) { + ratectr->e1_stats_group = rate_ctr_group_alloc(trunk, &e1_rate_ctr_group_desc, mdcx_rate_ctr_index++); + if (!ratectr->e1_stats_group) return -EINVAL; snprintf(ctr_name, sizeof(ctr_name), "%s-%u:e1", mgcp_trunk_type_strs_str(trunk->trunk_type), trunk->trunk_nr); - rate_ctr_group_set_name(ratectr->e1_stats, ctr_name); + rate_ctr_group_set_name(ratectr->e1_stats_group, ctr_name); } return 0; } @@ -261,15 +261,15 @@ rate_ctr_group_free(ratectr->mgcp_dlcx_ctr_group); ratectr->mgcp_dlcx_ctr_group = NULL; } - if (ratectr->all_rtp_conn_stats) { - rate_ctr_group_free(ratectr->all_rtp_conn_stats); - ratectr->all_rtp_conn_stats = NULL; + if (ratectr->all_rtp_conn_stats_group) { + rate_ctr_group_free(ratectr->all_rtp_conn_stats_group); + ratectr->all_rtp_conn_stats_group = NULL; } /* E1 specific */ - if (ratectr->e1_stats) { - rate_ctr_group_free(ratectr->e1_stats); - ratectr->e1_stats = NULL; + if (ratectr->e1_stats_group) { + rate_ctr_group_free(ratectr->e1_stats_group); + ratectr->e1_stats_group = NULL; } } diff --git a/src/libosmo-mgcp/mgcp_stat.c b/src/libosmo-mgcp/mgcp_stat.c index e679882..512d141 100644 --- a/src/libosmo-mgcp/mgcp_stat.c +++ b/src/libosmo-mgcp/mgcp_stat.c @@ -29,6 +29,7 @@ #include <osmocom/mgcp/mgcp_stat.h> #include <osmocom/mgcp/mgcp_endp.h> #include <osmocom/mgcp/mgcp_trunk.h> +#include <stdatomic.h> /* Helper function for mgcp_format_stats_rtp() to calculate packet loss */ #if defined(__has_attribute) @@ -39,7 +40,7 @@ void calc_loss(struct mgcp_conn_rtp *conn, uint32_t *expected, int *loss) { struct mgcp_rtp_state *state = &conn->state; - struct rate_ctr *packets_rx = rate_ctr_group_get_ctr(conn->rate_ctr_group, RTP_PACKETS_RX_CTR); + atomic_uint_least64_t packets_rx = conn->atomic_counters[RTP_PACKETS_RX_CTR]; *expected = state->stats.cycles + state->stats.max_seq; *expected = *expected - state->stats.base_seq + 1; @@ -54,8 +55,8 @@ * Make sure the sign is correct and use the biggest * positive/negative number that fits. */ - *loss = *expected - packets_rx->current; - if (*expected < packets_rx->current) { + *loss = *expected - packets_rx; + if (*expected < packets_rx) { if (*loss > 0) *loss = INT_MIN; } else { @@ -80,19 +81,17 @@ int ploss; int nchars; - struct rate_ctr *packets_rx = rate_ctr_group_get_ctr(conn->rate_ctr_group, RTP_PACKETS_RX_CTR); - struct rate_ctr *octets_rx = rate_ctr_group_get_ctr(conn->rate_ctr_group, RTP_OCTETS_RX_CTR); - struct rate_ctr *packets_tx = rate_ctr_group_get_ctr(conn->rate_ctr_group, RTP_PACKETS_TX_CTR); - struct rate_ctr *octets_tx = rate_ctr_group_get_ctr(conn->rate_ctr_group, RTP_OCTETS_TX_CTR); + atomic_uint_least64_t packets_rx = conn->atomic_counters[RTP_PACKETS_RX_CTR]; + atomic_uint_least64_t octets_rx = conn->atomic_counters[RTP_OCTETS_RX_CTR]; + atomic_uint_least64_t packets_tx = conn->atomic_counters[RTP_PACKETS_TX_CTR]; + atomic_uint_least64_t octets_tx = conn->atomic_counters[RTP_OCTETS_TX_CTR]; calc_loss(conn, &expected, &ploss); jitter = calc_jitter(&conn->state); nchars = snprintf(str, str_len, "\r\nP: PS=%" PRIu64 ", OS=%" PRIu64 ", PR=%" PRIu64 ", OR=%" PRIu64 ", PL=%d, JI=%u", - packets_tx->current, octets_tx->current, - packets_rx->current, octets_rx->current, - ploss, jitter); + packets_tx, octets_tx, packets_rx, octets_rx, ploss, jitter); if (nchars < 0 || nchars >= str_len) goto truncate; @@ -101,10 +100,8 @@ if (conn->conn->endp->trunk->cfg->osmux != OSMUX_USAGE_OFF) { /* Error Counter */ - nchars = snprintf(str, str_len, - "\r\nX-Osmo-CP: EC TI=%" PRIu64 ", TO=%" PRIu64, - conn->state.in_stream.err_ts_ctr->current, - conn->state.out_stream.err_ts_ctr->current); + nchars = snprintf(str, str_len, "\r\nX-Osmo-CP: EC TI=%" PRIu64 ", TO=%" PRIu64, + conn->state.in_stream.err_ts_ctr, conn->state.out_stream.err_ts_ctr); if (nchars < 0 || nchars >= str_len) goto truncate; diff --git a/src/libosmo-mgcp/mgcp_threads.c b/src/libosmo-mgcp/mgcp_threads.c index 6d47f24..afd744a 100644 --- a/src/libosmo-mgcp/mgcp_threads.c +++ b/src/libosmo-mgcp/mgcp_threads.c @@ -20,6 +20,7 @@ */ #include <pthread.h> +#include <stdatomic.h> #include <stdio.h> #include <talloc.h> #include <assert.h> @@ -234,6 +235,7 @@ temp_trunk.number_endpoints_offset = own_trunk_data->number_endpoints_offset; temp_trunk.endpoints = own_trunk_data->endpoints; temp_trunk.stats = own_trunk_data->stats; + temp_trunk.thread_ctr = own_trunk_data->thread_ctr; temp_trunk.num_threads = own_trunk_data->num_threads; if (own_trunk_data->trunk_type == MGCP_TRUNK_VIRTUAL) @@ -413,6 +415,50 @@ //FIXME: shutdown } +#define UPD_RATE_CTR_ATOMIC(ctrname, tid, enumname) \ + for (int i = 0; i < enumname; i++) { \ + atomic_uint_least64_t *c = &trunk->thread_info[tid].this_trunk->thread_ctr.ctrname##_atomic[i]; \ + struct rate_ctr *ctr = &trunk->ratectr.ctrname##_group->ctr[i]; \ + rate_ctr_add(ctr, *c - ctr->current); \ + } + +static struct osmo_timer_list rate_ctr_timer; + +/* updates rate counters by collecting the atomic per-thread counters, also updates ep used stats */ +static void rate_ctr_timer_cb(void *data) +{ + struct mgcp_trunk *trunk; + struct mgcp_config *cfg = data; + + for (int i = 0; i < _MGCP_GENERAL_NUM_ENUMS; i++) { + struct rate_ctr *ctr = &cfg->ratectr.mgcp_general_ctr_group->ctr[i]; + rate_ctr_add(ctr, cfg->ratectr.mgcp_general_ctr_atomic[i] - ctr->current); + } + + atomic_uint_least64_t endpoints_used = 0; + llist_for_each_entry(trunk, &cfg->trunks, entry) { + int thread_num = 0; + /* at least once: 0-thread trunks still need updating! */ + do { + UPD_RATE_CTR_ATOMIC(mgcp_crcx_ctr, thread_num, _MGCP_CRCX_NUM_ENUMS) + UPD_RATE_CTR_ATOMIC(mgcp_mdcx_ctr, thread_num, _MGCP_MDCX_NUM_ENUMS) + UPD_RATE_CTR_ATOMIC(mgcp_dlcx_ctr, thread_num, _MGCP_DLCX_NUM_ENUMS) + UPD_RATE_CTR_ATOMIC(all_rtp_conn_stats, thread_num, _MAX_RTP_CTR_NUM) + if (trunk->trunk_type == MGCP_TRUNK_E1) + UPD_RATE_CTR_ATOMIC(e1_stats, thread_num, _E1_I460_TRAU_NUM_ENUMS) + + endpoints_used += trunk->thread_info[thread_num].this_trunk->number_endpoints - + trunk->thread_info[thread_num].eps_free; + } while (++thread_num < trunk->num_threads); + + /* cheat by using the rate ctr one second callback to also update the ep usage stats */ + osmo_stat_item_set(osmo_stat_item_group_get_item(trunk->stats.common, TRUNK_STAT_ENDPOINTS_USED), + endpoints_used); + } + + osmo_timer_schedule(&rate_ctr_timer, 1, 0); +} + void split_trunks_into_threads(struct mgcp_config *cfg) { struct mgcp_trunk *trunk; @@ -447,4 +493,9 @@ split_per_thead(&trunk->thread_info[i]); } } + + /* wait for the threads to be done with init, so main thread can safely read atomics*/ + usleep(1000 * 100); + osmo_timer_setup(&rate_ctr_timer, rate_ctr_timer_cb, cfg); + osmo_timer_schedule(&rate_ctr_timer, 1, 0); } diff --git a/src/libosmo-mgcp/mgcp_threads_vty.c b/src/libosmo-mgcp/mgcp_threads_vty.c index 3259c8d..0cd6daa 100644 --- a/src/libosmo-mgcp/mgcp_threads_vty.c +++ b/src/libosmo-mgcp/mgcp_threads_vty.c @@ -31,15 +31,15 @@ struct mgcp_rtp_state *state = &conn->state; struct mgcp_rtp_end *end = &conn->end; struct mgcp_rtp_codec *codec = end->codec; - struct rate_ctr *tx_packets, *tx_bytes; - struct rate_ctr *rx_packets, *rx_bytes; - struct rate_ctr *dropped_packets; + atomic_uint_least64_t tx_packets, tx_bytes; + atomic_uint_least64_t rx_packets, rx_bytes; + atomic_uint_least64_t dropped_packets; - tx_packets = conn->rate_ctr_group[RTP_PACKETS_TX_CTR].ctr; - tx_bytes = conn->rate_ctr_group[RTP_OCTETS_TX_CTR].ctr; - rx_packets = conn->rate_ctr_group[RTP_PACKETS_RX_CTR].ctr; - rx_bytes = conn->rate_ctr_group[RTP_OCTETS_RX_CTR].ctr; - dropped_packets = conn->rate_ctr_group[RTP_DROPPED_PACKETS_CTR].ctr; + tx_packets = conn->atomic_counters[RTP_PACKETS_TX_CTR]; + tx_bytes = conn->atomic_counters[RTP_OCTETS_TX_CTR]; + rx_packets = conn->atomic_counters[RTP_PACKETS_RX_CTR]; + rx_bytes = conn->atomic_counters[RTP_OCTETS_RX_CTR]; + dropped_packets = conn->atomic_counters[RTP_DROPPED_PACKETS_CTR]; vty_out(vty, " Packets Sent: %" PRIu64 " (%" PRIu64 " bytes total)%s" @@ -51,12 +51,12 @@ " FPP: %d Packet Duration: %u%s" " FMTP-Extra: %s Audio-Name: %s Sub-Type: %s%s" " Output-Enabled: %d Force-PTIME: %d%s", - tx_packets->current, tx_bytes->current, VTY_NEWLINE, rx_packets->current, rx_bytes->current, - VTY_NEWLINE, state->in_stream.err_ts_ctr->current, state->out_stream.err_ts_ctr->current, VTY_NEWLINE, - dropped_packets->current, VTY_NEWLINE, codec->payload_type, codec->rate, codec->channels, VTY_NEWLINE, - codec->frame_duration_num, codec->frame_duration_den, VTY_NEWLINE, end->frames_per_packet, - end->packet_duration_ms, VTY_NEWLINE, end->fmtp_extra, codec->audio_name, codec->subtype_name, - VTY_NEWLINE, end->output_enabled, end->force_output_ptime, VTY_NEWLINE); + tx_packets, tx_bytes, VTY_NEWLINE, rx_packets, rx_bytes, VTY_NEWLINE, state->in_stream.err_ts_ctr, + state->out_stream.err_ts_ctr, VTY_NEWLINE, dropped_packets, VTY_NEWLINE, codec->payload_type, + codec->rate, codec->channels, VTY_NEWLINE, codec->frame_duration_num, codec->frame_duration_den, + VTY_NEWLINE, end->frames_per_packet, end->packet_duration_ms, VTY_NEWLINE, end->fmtp_extra, + codec->audio_name, codec->subtype_name, VTY_NEWLINE, end->output_enabled, end->force_output_ptime, + VTY_NEWLINE); } void dump_endpoint(struct vty *vty, struct mgcp_endpoint *endp, unsigned int trunk_nr, enum mgcp_trunk_type trunk_type, diff --git a/src/libosmo-mgcp/mgcp_vty.c b/src/libosmo-mgcp/mgcp_vty.c index 62a2bbf..8635fe0 100644 --- a/src/libosmo-mgcp/mgcp_vty.c +++ b/src/libosmo-mgcp/mgcp_vty.c @@ -209,22 +209,15 @@ " %25n: %10c (%S/s %M/m %H/h %D/d) %d", ratectr->mgcp_mdcx_ctr_group); } - if (ratectr->all_rtp_conn_stats) { - vty_out(vty, " %s:%s", - ratectr->all_rtp_conn_stats->desc->group_description, - VTY_NEWLINE); - vty_out_rate_ctr_group_fmt(vty, - " %25n: %10c (%S/s %M/m %H/h %D/d) %d", - ratectr->all_rtp_conn_stats); + if (ratectr->all_rtp_conn_stats_group) { + vty_out(vty, " %s:%s", ratectr->all_rtp_conn_stats_group->desc->group_description, VTY_NEWLINE); + vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", + ratectr->all_rtp_conn_stats_group); } - if (ratectr->e1_stats && trunk->trunk_type == MGCP_TRUNK_E1) { - vty_out(vty, " %s:%s", - ratectr->e1_stats->desc->group_description, - VTY_NEWLINE); - vty_out_rate_ctr_group_fmt(vty, - " %25n: %10c (%S/s %M/m %H/h %D/d) %d", - ratectr->e1_stats); + if (ratectr->e1_stats_group && trunk->trunk_type == MGCP_TRUNK_E1) { + vty_out(vty, " %s:%s", ratectr->e1_stats_group->desc->group_description, VTY_NEWLINE); + vty_out_rate_ctr_group_fmt(vty, " %25n: %10c (%S/s %M/m %H/h %D/d) %d", ratectr->e1_stats_group); } } diff --git a/tests/mgcp/mgcp_test.c b/tests/mgcp/mgcp_test.c index 9deee85..c74a2c4 100644 --- a/tests/mgcp/mgcp_test.c +++ b/tests/mgcp/mgcp_test.c @@ -16,9 +16,8 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#undef _GNU_SOURCE -#define _GNU_SOURCE +#include <stdatomic.h> #include <osmocom/mgcp/mgcp.h> #include <osmocom/mgcp/vty.h> #include <osmocom/mgcp/mgcp_common.h> @@ -39,11 +38,17 @@ #include <osmocom/core/socket.h> #include <string.h> #include <limits.h> -#include <dlfcn.h> + #include <time.h> #include <math.h> #include <ctype.h> +#undef _GNU_SOURCE +#define _GNU_SOURCE +#undef __USE_GNU +#define __USE_GNU +#include <dlfcn.h> + char *strline_r(char *str, char **saveptr); const char *strline_test_data = @@ -1084,21 +1089,19 @@ struct mgcp_conn_rtp *conn = NULL; struct mgcp_conn *_conn = NULL; struct mgcp_rtp_state *state; - struct rate_ctr *packets_rx; _conn = mgcp_conn_alloc(NULL, &endp, MGCP_CONN_TYPE_RTP, "test-connection"); conn = mgcp_conn_get_rtp(&endp, _conn->id); state = &conn->state; - packets_rx = rate_ctr_group_get_ctr(conn->rate_ctr_group, RTP_PACKETS_RX_CTR); state->stats.initialized = 1; state->stats.base_seq = pl_test_dat[i].base_seq; state->stats.max_seq = pl_test_dat[i].max_seq; state->stats.cycles = pl_test_dat[i].cycles; - packets_rx->current = pl_test_dat[i].packets; + conn->atomic_counters[RTP_PACKETS_RX_CTR] = pl_test_dat[i].packets; calc_loss(conn, &expected, &loss); if (loss != pl_test_dat[i].loss @@ -1309,8 +1312,8 @@ uint64_t last_out_ts_err_cnt = 0; struct mgcp_conn_rtp *conn = NULL; struct mgcp_conn *_conn = NULL; - struct rate_ctr test_ctr_in; - struct rate_ctr test_ctr_out; + atomic_uint_least64_t test_ctr_in; + atomic_uint_least64_t test_ctr_out; printf("Testing packet error detection%s%s.\n", patch_ssrc ? ", patch SSRC" : "", @@ -1323,8 +1326,8 @@ memset(&test_ctr_in, 0, sizeof(test_ctr_in)); memset(&test_ctr_out, 0, sizeof(test_ctr_out)); - state.in_stream.err_ts_ctr = &test_ctr_in; - state.out_stream.err_ts_ctr = &test_ctr_out; + state.in_stream.err_ts_ctr = test_ctr_in; + state.out_stream.err_ts_ctr = test_ctr_out; endp.type = &ep_typeset.rtp; @@ -1374,17 +1377,16 @@ printf("Out TS change: %d, dTS: %d, Seq change: %d, " "TS Err change: in +%u, out +%u\n", - state.out_stream.last_timestamp - last_timestamp, - state.out_stream.last_tsdelta, + state.out_stream.last_timestamp - last_timestamp, state.out_stream.last_tsdelta, state.out_stream.last_seq - last_seqno, - (unsigned int) (state.in_stream.err_ts_ctr->current - last_in_ts_err_cnt), - (unsigned int) (state.out_stream.err_ts_ctr->current - last_out_ts_err_cnt)); + (unsigned int)(state.in_stream.err_ts_ctr - last_in_ts_err_cnt), + (unsigned int)(state.out_stream.err_ts_ctr - last_out_ts_err_cnt)); printf("Stats: Jitter = %u, Transit = %d\n", calc_jitter(&state), state.stats.transit); - last_in_ts_err_cnt = state.in_stream.err_ts_ctr->current; - last_out_ts_err_cnt = state.out_stream.err_ts_ctr->current; + last_in_ts_err_cnt = state.in_stream.err_ts_ctr; + last_out_ts_err_cnt = state.out_stream.err_ts_ctr; last_timestamp = state.out_stream.last_timestamp; last_seqno = state.out_stream.last_seq; -- To view, visit https://gerrit.osmocom.org/c/osmo-mgw/+/26193 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-mgw Gerrit-Branch: master Gerrit-Change-Id: I5e3598f80cb062dbab376663ee51136b4508b78d Gerrit-Change-Number: 26193 Gerrit-PatchSet: 1 Gerrit-Owner: Hoernchen <ewild at sysmocom.de> Gerrit-MessageType: newchange -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20211109/4c921d50/attachment.htm>