mgcp_ratectr: add stats items to monitor trunk usage

We are currently counting events in rate counters, but there is
currently no way to get a sample of the current situation of the trunk
usage. In particular how many endpoints are currently in use.

This is a corrected version of:
Ib7b654168dc3512f55e45cc4755dc1f6f423d023

Change-Id: I6d3a74f6087512130d85002348787bffc672de81
Related: SYS#5201
diff --git a/src/libosmo-mgcp/mgcp_endp.c b/src/libosmo-mgcp/mgcp_endp.c
index 16043d4..4fcddb8 100644
--- a/src/libosmo-mgcp/mgcp_endp.c
+++ b/src/libosmo-mgcp/mgcp_endp.c
@@ -29,6 +29,7 @@
 
 #include <osmocom/abis/e1_input.h>
 #include <osmocom/mgcp/mgcp_e1.h>
+#include <osmocom/core/stat_item.h>
 
 #define E1_RATE_MAX 64
 #define E1_OFFS_MAX 8
@@ -122,6 +123,12 @@
 	 * RSIP is executed), free them all at once. */
 	mgcp_conn_free_all(endp);
 
+	/* 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);
+
 	/* Reset endpoint parameters and states */
 	talloc_free(endp->callid);
 	endp->callid = NULL;
@@ -598,6 +605,8 @@
 	 * 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);
 
 	/* Allocate resources */
 	switch (endp->trunk->trunk_type) {
diff --git a/src/libosmo-mgcp/mgcp_ratectr.c b/src/libosmo-mgcp/mgcp_ratectr.c
index 3c3b5db..d8e0374 100644
--- a/src/libosmo-mgcp/mgcp_ratectr.c
+++ b/src/libosmo-mgcp/mgcp_ratectr.c
@@ -24,8 +24,11 @@
 
 #include <errno.h>
 #include <osmocom/core/stats.h>
+#include <osmocom/core/stat_item.h>
 #include <osmocom/mgcp/mgcp_conn.h>
 #include <osmocom/mgcp/mgcp_trunk.h>
+#include <osmocom/mgcp/mgcp_protocol.h>
+#include <osmocom/mgcp/mgcp_endp.h>
 #include <osmocom/mgcp/mgcp_ratectr.h>
 
 static const struct rate_ctr_desc mgcp_general_ctr_desc[] = {
@@ -247,3 +250,48 @@
 	}
 	return 0;
 }
+
+const struct osmo_stat_item_desc trunk_stat_desc[] = {
+	[TRUNK_STAT_ENDPOINTS_TOTAL] = { "endpoints:total",
+					 "Number of endpoints that exist on the trunk",
+					 "", 60, 0 },
+	[TRUNK_STAT_ENDPOINTS_USED] = { "endpoints:used",
+					"Number of endpoints in use",
+					"", 60, 0 },
+};
+
+const struct osmo_stat_item_group_desc trunk_statg_desc = {
+	.group_name_prefix = "trunk",
+	.group_description = "mgw trunk",
+	.class_id = OSMO_STATS_CLASS_GLOBAL,
+	.num_items = ARRAY_SIZE(trunk_stat_desc),
+	.item_desc = trunk_stat_desc,
+};
+
+static int free_stat_item_group(struct osmo_stat_item_group *stat_item_group)
+{
+	osmo_stat_item_group_free(stat_item_group);
+	return 0;
+}
+
+/*! allocate trunk specific stat items
+ *  (called once on trunk initialization).
+ *  \param[in] trunk for which the stat items are allocated.
+ *  \returns 0 on success, -EINVAL on failure. */
+int mgcp_stat_trunk_alloc(struct mgcp_trunk *trunk)
+{
+	struct mgcp_stat_trunk *stats = &trunk->stats;
+	static unsigned int common_stat_index = 0;
+	char stat_name[256];
+
+	stats->common = osmo_stat_item_group_alloc(trunk, &trunk_statg_desc, common_stat_index);
+	if (!stats->common)
+		return -EINVAL;
+	snprintf(stat_name, sizeof(stat_name), "%s-%u:common", mgcp_trunk_type_strs_str(trunk->trunk_type),
+		 trunk->trunk_nr);
+	osmo_stat_item_group_set_name(stats->common, stat_name);
+	talloc_set_destructor(stats->common, free_stat_item_group);
+	common_stat_index++;
+
+	return 0;
+}
diff --git a/src/libosmo-mgcp/mgcp_trunk.c b/src/libosmo-mgcp/mgcp_trunk.c
index 73de972..a97ad39 100644
--- a/src/libosmo-mgcp/mgcp_trunk.c
+++ b/src/libosmo-mgcp/mgcp_trunk.c
@@ -27,6 +27,7 @@
 #include <osmocom/mgcp/mgcp_trunk.h>
 #include <osmocom/mgcp/mgcp_e1.h>
 #include <osmocom/abis/e1_input.h>
+#include <osmocom/core/stat_item.h>
 
 const struct value_string mgcp_trunk_type_strs[] = {
 	{ MGCP_TRUNK_VIRTUAL,		"virtual" },
@@ -64,6 +65,7 @@
 	llist_add_tail(&trunk->entry, &cfg->trunks);
 
 	mgcp_ratectr_trunk_alloc(trunk);
+	mgcp_stat_trunk_alloc(trunk);
 
 	return trunk;
 }
@@ -127,7 +129,8 @@
 
 	/* make the endpoints we just created available to the MGW code */
 	trunk->number_endpoints = number_endpoints;
-
+	osmo_stat_item_set(osmo_stat_item_group_get_item(trunk->stats.common, TRUNK_STAT_ENDPOINTS_TOTAL),
+			   trunk->number_endpoints);
 	return 0;
 }