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>