add a VTY command which shows a specific HNB

Add the 'show hnb NAME' VTY command which displays just
one specific HNB, addressed by its identity string.
This augments the functionality provided by 'show hnb all'.

Change-Id: Iab12aa4ab090b72c472358b84daf6919b30747f6
Related: OS#2774
diff --git a/include/osmocom/iuh/hnbgw.h b/include/osmocom/iuh/hnbgw.h
index db49dc1..4848c2f 100644
--- a/include/osmocom/iuh/hnbgw.h
+++ b/include/osmocom/iuh/hnbgw.h
@@ -151,6 +151,7 @@
 extern void *talloc_asn1_ctx;
 
 struct hnb_context *hnb_context_by_id(struct hnb_gw *gw, uint32_t cid);
+struct hnb_context *hnb_context_by_identity_info(struct hnb_gw *gw, const char *identity_info);
 unsigned hnb_contexts(const struct hnb_gw *gw);
 
 struct ue_context *ue_context_by_id(struct hnb_gw *gw, uint32_t id);
diff --git a/src/hnbgw.c b/src/hnbgw.c
index cd6104b..e40996f 100644
--- a/src/hnbgw.c
+++ b/src/hnbgw.c
@@ -105,6 +105,19 @@
 	return NULL;
 }
 
+struct hnb_context *hnb_context_by_identity_info(struct hnb_gw *gw, const char *identity_info)
+{
+	struct hnb_context *hnb;
+
+	llist_for_each_entry(hnb, &gw->hnb_list, list) {
+		if (strcmp(identity_info, hnb->identity_info) == 0)
+			return hnb;
+	}
+
+	return NULL;
+}
+
+
 unsigned hnb_contexts(const struct hnb_gw *gw)
 {
 	unsigned num_ctx = 0;
diff --git a/src/hnbgw_vty.c b/src/hnbgw_vty.c
index 859cd31..15fdaf8 100644
--- a/src/hnbgw_vty.c
+++ b/src/hnbgw_vty.c
@@ -200,7 +200,7 @@
 	vty_out(vty, "UE IMSI \"%s\" context ID %u%s", ue->imsi, ue->context_id, VTY_NEWLINE);
 }
 
-DEFUN(show_hnb, show_hnb_cmd, "show hnb all", SHOW_STR "Display information about a HNB")
+DEFUN(show_hnb, show_hnb_cmd, "show hnb all", SHOW_STR "Display information about all HNB")
 {
 	struct hnb_context *hnb;
 	unsigned int count = 0;
@@ -220,6 +220,27 @@
 	return CMD_SUCCESS;
 }
 
+DEFUN(show_one_hnb, show_one_hnb_cmd, "show hnb NAME ", SHOW_STR "Display information about a HNB")
+{
+	struct hnb_context *hnb;
+	int found = 0;
+	const char *identity_info = argv[0];
+
+	if (llist_empty(&g_hnb_gw->hnb_list)) {
+		vty_out(vty, "No HNB connected%s", VTY_NEWLINE);
+		return CMD_SUCCESS;
+	}
+
+	hnb = hnb_context_by_identity_info(&g_hnb_gw, identity_info);
+	if (hnb == NULL) {
+		vty_out(vty, "No HNB found with identity '%s'%s", identity_info, VTY_NEWLINE);
+		return CMD_SUCCESS;
+	}
+
+	vty_dump_hnb_info(vty, hnb);
+	return CMD_SUCCESS;
+}
+
 DEFUN(show_ue, show_ue_cmd, "show ue all", SHOW_STR "Display information about a UE")
 {
 	struct ue_context *ue;
@@ -377,6 +398,7 @@
 
 	install_element_ve(&show_cnlink_cmd);
 	install_element_ve(&show_hnb_cmd);
+	install_element_ve(&show_one_hnb_cmd);
 	install_element_ve(&show_ue_cmd);
 	install_element_ve(&show_talloc_cmd);
 }