laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-hnbgw/+/36082?usp=email )
Change subject: New per-hnb rate_ctr and stat_item groups; track uptime ......................................................................
New per-hnb rate_ctr and stat_item groups; track uptime
Let's add a per-hnb rate_ctr and stat_item group. Only one initial counter (number of Iuh establishments) and one initial stat_item (uptime/downtime) is implemented.
Related: SYS#6773 Change-Id: I26d7c3657cdaf7c6ba5aa10a0677381ab099f8dd --- M include/osmocom/hnbgw/hnbgw.h M src/osmo-hnbgw/hnbgw.c M src/osmo-hnbgw/hnbgw_hnbap.c 3 files changed, 120 insertions(+), 2 deletions(-)
Approvals: pespin: Looks good to me, but someone else must approve laforge: Looks good to me, approved Jenkins Builder: Verified osmith: Looks good to me, but someone else must approve
diff --git a/include/osmocom/hnbgw/hnbgw.h b/include/osmocom/hnbgw/hnbgw.h index 864d7ee..b3a6aae 100644 --- a/include/osmocom/hnbgw/hnbgw.h +++ b/include/osmocom/hnbgw/hnbgw.h @@ -18,6 +18,8 @@ #include <osmocom/mgcp_client/mgcp_client.h> #include <osmocom/mgcp_client/mgcp_client_pool.h>
+#define STORE_UPTIME_INTERVAL 10 /* seconds */ + enum { DMAIN, DHNBAP, @@ -70,6 +72,14 @@
#define IUH_MSGB_SIZE 2048
+enum hnb_rate_ctr { + HNB_CTR_IUH_ESTABLISHED, +}; + +enum hnb_stat { + HNB_STAT_UPTIME_SECONDS, +}; + struct umts_cell_id { uint16_t mcc; /*!< Mobile Country Code (0-999) */ uint16_t mnc; /*!< Mobile Network Code (0-999) */ @@ -253,10 +263,16 @@ /* linked list of hnbgw_context_map */ struct llist_head map_list;
- /*! pointer to the associated hnb persistent state */ + /*! pointer to the associated hnb persistent state. Always present after HNB-Register */ struct hnb_persistent *persistent; };
+#define HNBP_CTR(hnbp, x) rate_ctr_group_get_ctr((hnbp)->ctrs, x) +#define HNBP_CTR_INC(hnbp, x) rate_ctr_inc(HNBP_CTR(hnbp, x)) + +#define HNBP_STAT(hbp, x) osmo_stat_item_group_get_item((hnbp)->statg, x) +#define HNBP_STAT_SET(hnbp, x, val) osmo_stat_item_set(HNBP_STAT(hnbp, x), val) + /* persistent data for one HNB. This continues to exist even as conn / hnb_context is deleted on disconnect */ struct hnb_persistent { /*! Entry in HNBGW-global list of hnb_persistent */ @@ -268,6 +284,12 @@ struct umts_cell_id id; /*! stringified version of the cell identiy above (for printing/naming) */ const char *id_str; + + /*! copied from HNB-Identity-Info IE */ + time_t updowntime; + + struct rate_ctr_group *ctrs; + struct osmo_stat_item_group *statg; };
struct ue_context { @@ -313,6 +335,7 @@ struct llist_head hnb_list; /* list of struct hnb_persistent */ struct llist_head hnb_persistent_list; + struct osmo_timer_list store_uptime_timer; /* list of struct ue_context */ struct llist_head ue_list; /* next availble UE Context ID */ diff --git a/src/osmo-hnbgw/hnbgw.c b/src/osmo-hnbgw/hnbgw.c index 3709274..927d824 100644 --- a/src/osmo-hnbgw/hnbgw.c +++ b/src/osmo-hnbgw/hnbgw.c @@ -22,6 +22,10 @@ #include <netinet/in.h> #include <netinet/sctp.h>
+#include <osmocom/core/stats.h> +#include <osmocom/core/rate_ctr.h> +#include <osmocom/core/stat_item.h> + #include <osmocom/vty/vty.h>
#include <osmocom/gsm/gsm23236.h> @@ -270,9 +274,14 @@ void hnb_context_release(struct hnb_context *ctx) { struct hnbgw_context_map *map; + struct timespec tp; + int rc;
LOGHNB(ctx, DMAIN, LOGL_INFO, "Releasing HNB context\n");
+ rc = osmo_clock_gettime(CLOCK_MONOTONIC, &tp); + ctx->persistent->updowntime = (rc < 0) ? 0 : tp.tv_sec; + /* remove from the list of HNB contexts */ llist_del(&ctx->list);
@@ -305,6 +314,31 @@ * HNB Persistent Data ***********************************************************************/
+const struct rate_ctr_desc hnb_ctr_description[] = { + [HNB_CTR_IUH_ESTABLISHED] = { + "iuh:established", "Number of times Iuh link was established" }, +}; + +const struct rate_ctr_group_desc hnb_ctrg_desc = { + "hnb", + "hNodeB", + OSMO_STATS_CLASS_GLOBAL, + ARRAY_SIZE(hnb_ctr_description), + hnb_ctr_description, +}; + +const struct osmo_stat_item_desc hnb_stat_desc[] = { + [HNB_STAT_UPTIME_SECONDS] = { "uptime:seconds", "Seconds of uptime", "s", 60, 0 }, +}; + +const struct osmo_stat_item_group_desc hnb_statg_desc = { + .group_name_prefix = "hnb", + .group_description = "hNodeB", + .class_id = OSMO_STATS_CLASS_GLOBAL, + .num_items = ARRAY_SIZE(hnb_stat_desc), + .item_desc = hnb_stat_desc, +}; + struct hnb_persistent *hnb_persistent_alloc(const struct umts_cell_id *id) { struct hnb_persistent *hnbp = talloc_zero(g_hnbgw, struct hnb_persistent); @@ -313,10 +347,24 @@
hnbp->id = *id; hnbp->id_str = talloc_strdup(hnbp, umts_cell_id_name(id)); + hnbp->ctrs = rate_ctr_group_alloc(hnbp, &hnb_ctrg_desc, 0); + if (!hnbp->ctrs) + goto out_free; + rate_ctr_group_set_name(hnbp->ctrs, hnbp->id_str); + hnbp->statg = osmo_stat_item_group_alloc(hnbp, &hnb_statg_desc, 0); + if (!hnbp->statg) + goto out_free_ctrs; + osmo_stat_item_group_set_name(hnbp->statg, hnbp->id_str);
llist_add(&hnbp->list, &g_hnbgw->hnb_persistent_list);
return hnbp; + +out_free_ctrs: + rate_ctr_group_free(hnbp->ctrs); +out_free: + talloc_free(hnbp); + return NULL; }
struct hnb_persistent *hnb_persistent_find_by_id(const struct umts_cell_id *id) @@ -338,6 +386,32 @@ talloc_free(hnbp); }
+/* return the amount of time the HNB is up (hnbp->ctx != NULL) or down (hnbp->ctx == NULL) */ +static unsigned long long hnbp_get_updowntime(const struct hnb_persistent *hnbp) +{ + struct timespec tp; + + if (!hnbp->updowntime) + return 0; + + if (osmo_clock_gettime(CLOCK_MONOTONIC, &tp) != 0) + return 0; + + return difftime(tp.tv_sec, hnbp->updowntime); +} + +/* timer call-back: Update the HNB_STAT_UPTIME_SECONDS stat item of each hnb_persistent */ +static void hnbgw_store_hnb_uptime(void *data) +{ + struct hnb_persistent *hnbp; + + llist_for_each_entry(hnbp, &g_hnbgw->hnb_persistent_list, list) { + HNBP_STAT_SET(hnbp, HNB_STAT_UPTIME_SECONDS, hnbp->ctx != NULL ? hnbp_get_updowntime(hnbp) : 0); + } + + osmo_timer_schedule(&g_hnbgw->store_uptime_timer, STORE_UPTIME_INTERVAL, 0); +} + /*********************************************************************** * SCTP Socket / stream handling ***********************************************************************/ @@ -584,7 +658,7 @@
#define HNBGW_COPYRIGHT \ "OsmoHNBGW - Osmocom Home Node B Gateway implementation\r\n" \ - "Copyright (C) 2016-2023 by sysmocom s.f.m.c. GmbH info@sysmocom.de\r\n" \ + "Copyright (C) 2016-2024 by sysmocom s.f.m.c. GmbH info@sysmocom.de\r\n" \ "Contributions by Daniel Willmann, Harald Welte, Neels Hofmeyr\r\n" \ "License AGPLv3+: GNU AGPL version 3 or later http://gnu.org/licenses/agpl-3.0.html\r\n" \ "This is free software: you are free to change and redistribute it.\r\n" \ @@ -696,4 +770,7 @@ .ctrs = rate_ctr_group_alloc(g_hnbgw, &iups_ctrg_desc, 0), }; INIT_LLIST_HEAD(&g_hnbgw->sccp.cnpool_iups.cnlinks); + + osmo_timer_setup(&g_hnbgw->store_uptime_timer, hnbgw_store_hnb_uptime, g_hnbgw); + osmo_timer_schedule(&g_hnbgw->store_uptime_timer, STORE_UPTIME_INTERVAL, 0); } diff --git a/src/osmo-hnbgw/hnbgw_hnbap.c b/src/osmo-hnbgw/hnbgw_hnbap.c index 0648ebc..b2ff911 100644 --- a/src/osmo-hnbgw/hnbgw_hnbap.c +++ b/src/osmo-hnbgw/hnbgw_hnbap.c @@ -412,6 +412,7 @@ struct osmo_fd *ofd = osmo_stream_srv_get_ofd(ctx->conn); char identity_str[256]; const char *cell_id_str; + struct timespec tp;
rc = hnbap_decode_hnbregisterrequesties(&ies, in); if (rc < 0) { @@ -443,6 +444,9 @@ ctx->persistent = hnbp; hnbp->ctx = ctx;
+ HNBP_CTR_INC(hnbp, HNB_CTR_IUH_ESTABLISHED); + rc = osmo_clock_gettime(CLOCK_MONOTONIC, &tp); + hnbp->updowntime = (rc < 0) ? 0 : tp.tv_sec;
llist_for_each_entry_safe(hnb, tmp, &g_hnbgw->hnb_list, list) { if (hnb->hnb_registered && ctx != hnb && memcmp(&ctx->id, &hnb->id, sizeof(ctx->id)) == 0) {