From bfeea6713b4e17fcd5cfb0a5b4c042eaf526ae22 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 27 Dec 2017 22:53:36 +0100 Subject: [PATCH] Expand ctrl interface Add commands to get number of connected HNBs and identity string of connected HNB based on Cell ID. Change-Id: I3a2d6fa3d6d0829ccee4ecc0998d9299c97820e9 --- include/osmocom/iuh/hnbgw.h | 9 +++- src/hnbgw.c | 90 ++++++++++++++++++++++++++++++++++++- 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/include/osmocom/iuh/hnbgw.h b/include/osmocom/iuh/hnbgw.h index 971ede41..094f31f9 100644 --- a/include/osmocom/iuh/hnbgw.h +++ b/include/osmocom/iuh/hnbgw.h @@ -6,7 +6,7 @@ #include #include #include - +#include #define DEBUG #include @@ -18,6 +18,10 @@ enum { DRANAP, }; +enum hnb_ctrl_node { + CTRL_NODE_HNB = _LAST_CTRL_NODE, + _LAST_CTRL_NODE_HNB +}; #define HNBGW_LOCAL_IP_DEFAULT "0.0.0.0" /* TODO: CS and PS now both connect to OsmoSTP, i.e. that's always going to be the same address. Drop the @@ -142,6 +146,9 @@ struct hnb_gw { extern void *talloc_asn1_ctx; +struct hnb_context *hnb_context_by_id(struct hnb_gw *gw, uint32_t cid); +unsigned hnb_contexts(const struct hnb_gw *gw); + struct ue_context *ue_context_by_id(struct hnb_gw *gw, uint32_t id); struct ue_context *ue_context_by_imsi(struct hnb_gw *gw, const char *imsi); struct ue_context *ue_context_by_tmsi(struct hnb_gw *gw, uint32_t tmsi); diff --git a/src/hnbgw.c b/src/hnbgw.c index a66f14aa..cd492bb2 100644 --- a/src/hnbgw.c +++ b/src/hnbgw.c @@ -93,6 +93,30 @@ static struct hnb_gw *hnb_gw_create(void *ctx) return gw; } +struct hnb_context *hnb_context_by_id(struct hnb_gw *gw, uint32_t cid) +{ + struct hnb_context *hnb; + + llist_for_each_entry(hnb, &gw->hnb_list, list) { + if (hnb->id.cid == cid) + return hnb; + } + + return NULL; +} + +unsigned hnb_contexts(const struct hnb_gw *gw) +{ + unsigned num_ctx = 0; + struct hnb_context *hnb; + + llist_for_each_entry(hnb, &gw->hnb_list, list) { + num_ctx++; + } + + return num_ctx; +} + struct ue_context *ue_context_by_id(struct hnb_gw *gw, uint32_t id) { struct ue_context *ue; @@ -423,6 +447,63 @@ static void handle_options(int argc, char **argv) } } +CTRL_CMD_DEFINE_RO(hnb_info, "info"); +static int get_hnb_info(struct ctrl_cmd *cmd, void *data) +{ + struct hnb_context *hnb = data; + + cmd->reply = talloc_strdup(cmd, hnb->identity_info); + + return CTRL_CMD_REPLY; +} + +CTRL_CMD_DEFINE_RO(hnbs, "num-hnb"); +static int get_hnbs(struct ctrl_cmd *cmd, void *data) +{ + cmd->reply = talloc_asprintf(cmd, "%u", hnb_contexts(data)); + + return CTRL_CMD_REPLY; +} + +int hnb_ctrl_cmds_install() +{ + int rc = 0; + + rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_hnbs); + rc |= ctrl_cmd_install(CTRL_NODE_HNB, &cmd_hnb_info); + + return rc; +} + +static int hnb_ctrl_node_lookup(void *data, vector vline, int *node_type, void **node_data, int *i) +{ + const char *token = vector_slot(vline, *i); + struct hnb_context *hnb; + long num; + + switch (*node_type) { + case CTRL_NODE_ROOT: + if (strcmp(token, "hnb") != 0) + return 0; + + (*i)++; + + if (!ctrl_parse_get_num(vline, *i, &num)) + return -ERANGE; + + hnb = hnb_context_by_id(data, num); + if (!hnb) + return -ENODEV; + + *node_data = hnb; + *node_type = CTRL_NODE_HNB; + break; + default: + return 0; + } + + return 1; +} int main(int argc, char **argv) { @@ -480,11 +561,18 @@ int main(int argc, char **argv) exit(1); } - g_hnb_gw->ctrl = ctrl_interface_setup_dynip(NULL, ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_HNBGW, NULL); + g_hnb_gw->ctrl = ctrl_interface_setup_dynip2(g_hnb_gw, ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_HNBGW, + hnb_ctrl_node_lookup, _LAST_CTRL_NODE_HNB); if (!g_hnb_gw->ctrl) { LOGP(DMAIN, LOGL_ERROR, "Failed to create CTRL interface on %s:%u\n", ctrl_vty_get_bind_addr(), OSMO_CTRL_PORT_HNBGW); exit(1); + } else { + rc = hnb_ctrl_cmds_install(); + if (rc) { + LOGP(DMAIN, LOGL_ERROR, "Failed to install CTRL interface commands\n"); + return 2; + } } ranap_set_log_area(DRANAP);