laforge has uploaded this change for review. ( 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 asd 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, 124 insertions(+), 3 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-hnbgw refs/changes/82/36082/1
diff --git a/include/osmocom/hnbgw/hnbgw.h b/include/osmocom/hnbgw/hnbgw.h index 59bb96b..aa2ff47 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 */ uint16_t mnc; /*!< Mobile Network Code */ @@ -234,17 +244,30 @@ /* 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 */ struct llist_head list;
+ /*! back-pointer to hnb_context. Can be NULL if no context at this point */ + struct hnb_context *ctx; + /*! copied from HNB-Identity-Info IE */ char identity_info[256]; + time_t updowntime; + + struct rate_ctr_group *ctrs; + struct osmo_stat_item_group *statg; };
struct ue_context { @@ -290,6 +313,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 8a7626f..91c2930 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> @@ -239,9 +243,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);
@@ -263,6 +272,9 @@ map->hnb_ctx = NULL; }
+ /* remove back reference from hnb_persistent to context */ + ctx->persistent->ctx = NULL; + talloc_free(ctx); }
@@ -270,16 +282,54 @@ * 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 char *identity) { struct hnb_persistent *hnbp = talloc_zero(g_hnbgw, struct hnb_persistent); if (!hnbp) return NULL;
- llist_add(&g_hnbgw->hnb_persistent_list, &hnbp->list); OSMO_STRLCPY_ARRAY(hnbp->identity_info, identity); + hnbp->ctrs = rate_ctr_group_alloc(hnbp, &hnb_ctrg_desc, 0); + if (!hnbp->ctrs) + goto out_free; + hnbp->statg = osmo_stat_item_group_alloc(hnbp, &hnb_statg_desc, 0); + if (!hnbp->statg) + goto out_free_ctrs; + + llist_add(&g_hnbgw->hnb_persistent_list, &hnbp->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_identity(const char *identity) @@ -301,6 +351,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 ***********************************************************************/ @@ -547,7 +623,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" \ @@ -658,4 +734,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 f8c6bd6..21e3946 100644 --- a/src/osmo-hnbgw/hnbgw_hnbap.c +++ b/src/osmo-hnbgw/hnbgw_hnbap.c @@ -411,6 +411,7 @@ struct osmo_plmn_id plmn; struct osmo_fd *ofd = osmo_stream_srv_get_ofd(ctx->conn); char identity_str[256]; + struct timespec tp;
rc = hnbap_decode_hnbregisterrequesties(&ies, in); if (rc < 0) { @@ -429,6 +430,9 @@ return hnbgw_tx_hnb_register_rej(ctx); } ctx->persistent = hnbp; + HNBP_CTR_INC(hnbp, HNB_CTR_IUH_ESTABLISHED); + rc = osmo_clock_gettime(CLOCK_MONOTONIC, &tp); + hnbp->updowntime = (rc < 0) ? 0 : tp.tv_sec;
/* copy all identity parameters from the message to ctx */ OSMO_STRLCPY_ARRAY(ctx->identity_info, identity_str);