laforge submitted this change.
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(-)
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) {
To view, visit change 36082. To unsubscribe, or for help writing mail filters, visit settings.