osmux: Add connection and global rate counters

Change-Id: I200a4aa3908cac0ec729d980a66f3df7f55e4da7
This commit is contained in:
Pau Espin 2022-09-22 17:53:44 +02:00
parent 663ba5c41f
commit 582c2bf7b0
8 changed files with 112 additions and 17 deletions

View File

@ -88,11 +88,8 @@ struct mgcp_conn_rtp {
struct osmux_in_handle *in;
/* handle to unbatch messages, one allocated and owned per conn */
struct osmux_out_handle *out;
/* statistics */
struct {
uint32_t chunks;
uint32_t octets;
} stats;
/* statistics: */
struct rate_ctr_group *ctrg;
} osmux;
struct {
@ -181,6 +178,40 @@ static const struct rate_ctr_desc all_rtp_conn_rate_ctr_desc[] = {
[RTP_NUM_CONNECTIONS] = {"all_rtp:num_closed_conns", "Total number of rtp connections closed."}
};
/* Osmux connection related counters */
enum {
OSMUX_CHUNKS_RX_CTR,
OSMUX_OCTETS_RX_CTR,
OSMUX_DROPPED_AMR_PAYLOADS_CTR,
/* Only available in global stats: */
OSMUX_NUM_CONNECTIONS,
OSMUX_PACKETS_RX_CTR,
OSMUX_PACKETS_TX_CTR,
OSMUX_DROPPED_PACKETS_CTR,
};
/* RTP per-connection statistics. Instances of the corresponding rate counter group
* exist for the lifetime of an RTP connection.
* Must be kept in sync with all_rtp_conn_rate_ctr_desc below */
static const struct rate_ctr_desc mgcp_conn_osmux_rate_ctr_desc[] = {
[OSMUX_CHUNKS_RX_CTR] = {"osmux:chunks_rx", "Inbound Osmux chunks."},
[OSMUX_OCTETS_RX_CTR] = {"osmux:octets_rx", "Inbound Osmux octets."},
[OSMUX_DROPPED_AMR_PAYLOADS_CTR] = {"osmux:dropped_amr_payloads", "Dropped outbound AMR payloads."}
};
/* Aggregated Osmux connection stats. These are updated when an Osmux connection is freed.
* Must be kept in sync with mgcp_conn_osmux_rate_ctr_desc above */
static const struct rate_ctr_desc all_osmux_conn_rate_ctr_desc[] = {
[OSMUX_CHUNKS_RX_CTR] = {"all_osmux:chunks_rx", "Inbound Osmux chunks."},
[OSMUX_OCTETS_RX_CTR] = {"all_osmux:octets_rx", "Inbound Osmux octets."},
[OSMUX_DROPPED_AMR_PAYLOADS_CTR] = {"all_osmux:dropped_amr_payloads", "Dropped outbound AMR payloads."},
/* These last counters below do not exist in per-connection stats, only here: */
[OSMUX_NUM_CONNECTIONS] = {"all_osmux:num_closed_conns", "Total number of osmux connections closed."},
[OSMUX_PACKETS_RX_CTR] = {"all_osmux:packets_rx", "Total inbound UDP/Osmux packets."},
[OSMUX_PACKETS_TX_CTR] = {"all_osmux:packets_tx", "Total outbound UDP/Osmux packets."},
[OSMUX_DROPPED_PACKETS_CTR] = {"all_osmux:dropped_packets", "Dropped outbound UDP/Osmux packets."}
};
/* Was conn configured to handle Osmux? */
static inline bool mgcp_conn_rtp_is_osmux(const struct mgcp_conn_rtp *conn) {
return conn->type == MGCP_OSMUX_BSC || conn->type == MGCP_OSMUX_BSC_NAT;

View File

@ -178,5 +178,7 @@ void mgcp_rtp_annex_count(const struct mgcp_endpoint *endp, struct mgcp_rtp_stat
void rtpconn_rate_ctr_add(struct mgcp_conn_rtp *conn_rtp, struct mgcp_endpoint *endp,
int id, int inc);
void rtpconn_rate_ctr_inc(struct mgcp_conn_rtp *conn_rtp, struct mgcp_endpoint *endp,
int id);
void forward_data_tap(int fd, struct mgcp_rtp_tap *tap, struct msgb *msg);
uint32_t mgcp_get_current_ts(unsigned codec_rate);

View File

@ -80,6 +80,8 @@ struct mgcp_ratectr_trunk {
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;
/* Rate counter group which aggregates stats of individual Osmux connections. */
struct rate_ctr_group *all_osmux_conn_stats;
/* Rate counter group which contains stats for E1 events (only valid for E1 trunks) */
struct rate_ctr_group *e1_stats;
};

View File

@ -70,7 +70,7 @@ void rtpconn_rate_ctr_add(struct mgcp_conn_rtp *conn_rtp, struct mgcp_endpoint *
rate_ctr_add(rate_ctr_group_get_ctr(mgw_stats, id), inc);
}
static void rtpconn_rate_ctr_inc(struct mgcp_conn_rtp *conn_rtp, struct mgcp_endpoint *endp, int id)
void rtpconn_rate_ctr_inc(struct mgcp_conn_rtp *conn_rtp, struct mgcp_endpoint *endp, int id)
{
rtpconn_rate_ctr_add(conn_rtp, endp, id, 1);
}

View File

@ -41,12 +41,22 @@ struct osmux_handle {
int refcnt;
};
static const struct rate_ctr_group_desc rate_ctr_group_osmux_desc = {
.group_name_prefix = "conn_osmux",
.group_description = "Osmux connection statistics",
.class_id = 1,
.num_ctr = ARRAY_SIZE(mgcp_conn_osmux_rate_ctr_desc),
.ctr_desc = mgcp_conn_osmux_rate_ctr_desc
};
/* Deliver OSMUX batch to the remote end */
static void osmux_deliver_cb(struct msgb *batch_msg, void *data)
{
struct osmux_handle *handle = data;
socklen_t dest_len;
int rc;
struct mgcp_trunk *trunk = (struct mgcp_trunk *)osmux_fd.data;
struct rate_ctr_group *all_osmux_stats = trunk->ratectr.all_osmux_conn_stats;
switch (handle->rem_addr.u.sa.sa_family) {
case AF_INET6:
@ -64,6 +74,9 @@ static void osmux_deliver_cb(struct msgb *batch_msg, void *data)
strerror_r(errno, errbuf, sizeof(errbuf));
LOGP(DOSMUX, LOGL_NOTICE, "osmux sendto(%s) failed: %s\n",
osmo_sockaddr_to_str(&handle->rem_addr), errbuf);
rate_ctr_inc(rate_ctr_group_get_ctr(all_osmux_stats, OSMUX_DROPPED_PACKETS_CTR));
} else {
rate_ctr_inc(rate_ctr_group_get_ctr(all_osmux_stats, OSMUX_PACKETS_TX_CTR));
}
msgb_free(batch_msg);
}
@ -190,12 +203,15 @@ int osmux_xfrm_to_osmux(char *buf, int buf_len, struct mgcp_conn_rtp *conn)
int ret;
struct msgb *msg;
if (!conn->end.output_enabled)
if (!conn->end.output_enabled) {
rtpconn_rate_ctr_inc(conn, conn->conn->endp, OSMUX_DROPPED_AMR_PAYLOADS_CTR);
return -1;
}
if (conn->osmux.state != OSMUX_STATE_ENABLED) {
LOGPCONN(conn->conn, DOSMUX, LOGL_INFO, "forwarding RTP to Osmux conn not yet enabled, dropping (cid=%d)\n",
conn->osmux.cid);
rtpconn_rate_ctr_inc(conn, conn->conn->endp, OSMUX_DROPPED_AMR_PAYLOADS_CTR);
return -1;
}
@ -368,14 +384,16 @@ static int osmux_read_fd_cb(struct osmo_fd *ofd, unsigned int what)
struct msgb *msg;
struct osmux_hdr *osmuxh;
struct osmo_sockaddr rem_addr;
struct mgcp_trunk *trunk = ofd->data;
uint32_t rem;
struct mgcp_conn_rtp *conn_src;
struct mgcp_trunk *trunk = ofd->data;
struct rate_ctr_group *all_rtp_stats = trunk->ratectr.all_osmux_conn_stats;
msg = osmux_recv(ofd, &rem_addr);
if (!msg)
return -1;
rate_ctr_inc(rate_ctr_group_get_ctr(all_rtp_stats, OSMUX_PACKETS_RX_CTR));
if (!trunk->cfg->osmux) {
LOGP(DOSMUX, LOGL_ERROR,
"bsc-nat wants to use Osmux but bsc did not request it\n");
@ -388,7 +406,8 @@ static int osmux_read_fd_cb(struct osmo_fd *ofd, unsigned int what)
rem = msg->len;
while((osmuxh = osmux_xfrm_output_pull(msg)) != NULL) {
struct mgcp_endpoint *endp;
struct mgcp_conn_rtp *conn_src;
conn_src = osmux_conn_lookup(trunk, osmuxh->circuit_id,
&rem_addr);
if (!conn_src) {
@ -397,7 +416,7 @@ static int osmux_read_fd_cb(struct osmo_fd *ofd, unsigned int what)
osmuxh->circuit_id);
goto out;
}
endp = conn_src->conn->endp;
mgcp_conn_watchdog_kick(conn_src->conn);
/*conn_dst = mgcp_find_dst_conn(conn_src->conn);
@ -407,10 +426,10 @@ static int osmux_read_fd_cb(struct osmo_fd *ofd, unsigned int what)
osmuxh->circuit_id);
goto out;
}*/
if (endp_osmux_state_check(conn_src->conn->endp, conn_src, false) == 0) {
conn_src->osmux.stats.octets += osmux_chunk_length(msg, rem);
conn_src->osmux.stats.chunks++;
if (endp_osmux_state_check(endp, conn_src, false) == 0) {
rtpconn_rate_ctr_inc(conn_src, endp, OSMUX_CHUNKS_RX_CTR);
rtpconn_rate_ctr_add(conn_src, endp, OSMUX_OCTETS_RX_CTR,
osmux_chunk_length(msg, rem));
osmux_xfrm_output_sched(conn_src->osmux.out, osmuxh);
}
rem = msg->len;
@ -513,6 +532,8 @@ int osmux_enable_conn(struct mgcp_endpoint *endp, struct mgcp_conn_rtp *conn,
osmux_xfrm_output_set_tx_cb(conn->osmux.out,
scheduled_from_osmux_tx_rtp_cb, conn);
conn->osmux.ctrg = rate_ctr_group_alloc(conn->conn, &rate_ctr_group_osmux_desc, conn->ctrg->idx);
conn->osmux.state = OSMUX_STATE_ENABLED;
return 0;
@ -528,6 +549,9 @@ void conn_osmux_disable(struct mgcp_conn_rtp *conn)
LOGPCONN(conn->conn, DOSMUX, LOGL_INFO,
"Releasing connection using Osmux CID %u\n", conn->osmux.cid);
struct rate_ctr_group *all_osmux_stats = conn->conn->endp->trunk->ratectr.all_osmux_conn_stats;
rate_ctr_inc(rate_ctr_group_get_ctr(all_osmux_stats, OSMUX_NUM_CONNECTIONS));
if (conn->osmux.state == OSMUX_STATE_ENABLED) {
/* We are closing, we don't need pending RTP packets to be transmitted */
osmux_xfrm_output_set_tx_cb(conn->osmux.out, NULL, NULL);
@ -536,6 +560,9 @@ void conn_osmux_disable(struct mgcp_conn_rtp *conn)
osmux_xfrm_input_close_circuit(conn->osmux.in, conn->osmux.cid);
conn->osmux.state = OSMUX_STATE_DISABLED;
osmux_handle_put(conn->osmux.in);
rate_ctr_group_free(conn->osmux.ctrg);
conn->osmux.ctrg = NULL;
}
conn_osmux_release_cid(conn);
}

View File

@ -146,6 +146,14 @@ static const struct rate_ctr_group_desc all_rtp_conn_rate_ctr_group_desc = {
.ctr_desc = all_rtp_conn_rate_ctr_desc
};
static const struct rate_ctr_group_desc all_osmux_conn_rate_ctr_group_desc = {
.group_name_prefix = "all_osmux_conn",
.group_description = "aggregated statistics for all osmux connections",
.class_id = 1,
.num_ctr = ARRAY_SIZE(all_osmux_conn_rate_ctr_desc),
.ctr_desc = all_rtp_conn_rate_ctr_desc
};
/*! allocate global rate counters
* (called once at startup).
* \param[in] cfg mgw configuration for which the rate counters are allocated.
@ -191,6 +199,7 @@ int mgcp_ratectr_trunk_alloc(struct mgcp_trunk *trunk)
static atomic_uint mdcx_rate_ctr_index = 0;
static atomic_uint dlcx_rate_ctr_index = 0;
static atomic_uint all_rtp_conn_rate_ctr_index = 0;
static atomic_uint all_osmux_conn_rate_ctr_index = 0;
char ctr_name[256];
if (ratectr->mgcp_crcx_ctr_group == NULL) {
@ -229,6 +238,15 @@ int mgcp_ratectr_trunk_alloc(struct mgcp_trunk *trunk)
trunk->trunk_nr);
rate_ctr_group_set_name(ratectr->all_rtp_conn_stats, ctr_name);
}
if (ratectr->all_osmux_conn_stats == NULL) {
ratectr->all_osmux_conn_stats = rate_ctr_group_alloc(trunk, &all_osmux_conn_rate_ctr_group_desc,
all_osmux_conn_rate_ctr_index++);
if (!ratectr->all_osmux_conn_stats)
return -EINVAL;
snprintf(ctr_name, sizeof(ctr_name), "%s-%u:osmux_conn", mgcp_trunk_type_strs_str(trunk->trunk_type),
trunk->trunk_nr);
rate_ctr_group_set_name(ratectr->all_osmux_conn_stats, ctr_name);
}
/* E1 specific */
if (trunk->trunk_type == MGCP_TRUNK_E1 && ratectr->e1_stats == NULL) {
@ -265,6 +283,10 @@ void mgcp_ratectr_trunk_free(struct mgcp_trunk *trunk)
rate_ctr_group_free(ratectr->all_rtp_conn_stats);
ratectr->all_rtp_conn_stats = NULL;
}
if (ratectr->all_osmux_conn_stats) {
rate_ctr_group_free(ratectr->all_osmux_conn_stats);
ratectr->all_osmux_conn_stats = NULL;
}
/* E1 specific */
if (ratectr->e1_stats) {

View File

@ -112,9 +112,12 @@ static void mgcp_format_stats_rtp(char *str, size_t str_len,
str_len -= nchars;
if (conn->osmux.state == OSMUX_STATE_ENABLED) {
struct rate_ctr *osmux_chunks_rx, *osmux_octets_rx;
osmux_chunks_rx = rate_ctr_group_get_ctr(conn->ctrg, OSMUX_CHUNKS_RX_CTR);
osmux_octets_rx = rate_ctr_group_get_ctr(conn->ctrg, OSMUX_OCTETS_RX_CTR);
snprintf(str, str_len,
"\r\nX-Osmux-ST: CR=%u, BR=%u",
conn->osmux.stats.chunks, conn->osmux.stats.octets);
"\r\nX-Osmux-ST: CR=%" PRIu64 ", BR=%" PRIu64,
osmux_chunks_rx->current, osmux_octets_rx->current);
}
}

View File

@ -289,6 +289,14 @@ static void dump_ratectr_trunk(struct vty *vty, struct mgcp_trunk *trunk)
" %25n: %10c (%S/s %M/m %H/h %D/d) %d",
ratectr->all_rtp_conn_stats);
}
if (ratectr->all_osmux_conn_stats) {
vty_out(vty, " %s:%s",
ratectr->all_osmux_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_osmux_conn_stats);
}
if (ratectr->e1_stats && trunk->trunk_type == MGCP_TRUNK_E1) {
vty_out(vty, " %s:%s",