diff --git a/include/osmocom/mgcp/mgcp_conn.h b/include/osmocom/mgcp/mgcp_conn.h index ce864b8cd..14ddfbb9b 100644 --- a/include/osmocom/mgcp/mgcp_conn.h +++ b/include/osmocom/mgcp/mgcp_conn.h @@ -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; diff --git a/include/osmocom/mgcp/mgcp_network.h b/include/osmocom/mgcp/mgcp_network.h index 9c075b0cf..5668711e4 100644 --- a/include/osmocom/mgcp/mgcp_network.h +++ b/include/osmocom/mgcp/mgcp_network.h @@ -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); diff --git a/include/osmocom/mgcp/mgcp_ratectr.h b/include/osmocom/mgcp/mgcp_ratectr.h index c03c4e119..f566625b9 100644 --- a/include/osmocom/mgcp/mgcp_ratectr.h +++ b/include/osmocom/mgcp/mgcp_ratectr.h @@ -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; }; diff --git a/src/libosmo-mgcp/mgcp_network.c b/src/libosmo-mgcp/mgcp_network.c index dfbe4d31c..d49256360 100644 --- a/src/libosmo-mgcp/mgcp_network.c +++ b/src/libosmo-mgcp/mgcp_network.c @@ -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); } diff --git a/src/libosmo-mgcp/mgcp_osmux.c b/src/libosmo-mgcp/mgcp_osmux.c index 4ad3f10a9..5ba48e8d2 100644 --- a/src/libosmo-mgcp/mgcp_osmux.c +++ b/src/libosmo-mgcp/mgcp_osmux.c @@ -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); } diff --git a/src/libosmo-mgcp/mgcp_ratectr.c b/src/libosmo-mgcp/mgcp_ratectr.c index bc6aa3c4a..bf3d9d301 100644 --- a/src/libosmo-mgcp/mgcp_ratectr.c +++ b/src/libosmo-mgcp/mgcp_ratectr.c @@ -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) { diff --git a/src/libosmo-mgcp/mgcp_stat.c b/src/libosmo-mgcp/mgcp_stat.c index d13452677..e63feacde 100644 --- a/src/libosmo-mgcp/mgcp_stat.c +++ b/src/libosmo-mgcp/mgcp_stat.c @@ -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); } } diff --git a/src/libosmo-mgcp/mgcp_vty.c b/src/libosmo-mgcp/mgcp_vty.c index 61838673a..5abbf0e2f 100644 --- a/src/libosmo-mgcp/mgcp_vty.c +++ b/src/libosmo-mgcp/mgcp_vty.c @@ -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",