laforge has uploaded this change for review.
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);
To view, visit change 36082. To unsubscribe, or for help writing mail filters, visit settings.