From 2ffd35b0ebbb5a48a1d8f38b6f2e3e8c1d95dd4c Mon Sep 17 00:00:00 2001
From: Pau Espin Pedrol <pespin@sysmocom.de>
Date: Tue, 6 Nov 2018 17:56:23 +0100
Subject: [PATCH] WIP

Change-Id: Ida416a969a3309868d6f4e50f34b34f224c32dd6
---
 include/osmocom/bsc/abis_nm.h  |  6 ++--
 src/ipaccess/ipaccess-config.c | 58 +++++++++++++++++++++++-----------
 src/osmo-bsc/abis_nm.c         | 31 ++++++++++++++++--
 3 files changed, 71 insertions(+), 24 deletions(-)

diff --git a/include/osmocom/bsc/abis_nm.h b/include/osmocom/bsc/abis_nm.h
index ef9e4f5fc..0b3e3f2cf 100644
--- a/include/osmocom/bsc/abis_nm.h
+++ b/include/osmocom/bsc/abis_nm.h
@@ -1,4 +1,4 @@
-/* GSM Network Management messages on the A-bis interface 
+/* GSM Network Management messages on the A-bis interface
  * 3GPP TS 12.21 version 8.0.0 Release 1999 / ETSI TS 100 623 V8.0.0 */
 
 /* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
@@ -145,10 +145,12 @@ int abis_nm_ipaccess_msg(struct gsm_bts *bts, uint8_t msg_type,
 int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, uint8_t *attr,
 				int attr_len);
 int abis_nm_ipaccess_restart(struct gsm_bts_trx *trx);
+int abis_nm_ipaccess_get_nvattr(struct gsm_bts_trx *trx, uint8_t *attr,
+				int attr_len);
 int abis_nm_ipaccess_set_attr(struct gsm_bts *bts, uint8_t obj_class,
 				uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr,
 				uint8_t *attr, uint8_t attr_len);
-int abis_nm_ipaccess_rsl_connect(struct gsm_bts_trx *trx, 
+int abis_nm_ipaccess_rsl_connect(struct gsm_bts_trx *trx,
 				 uint32_t ip, uint16_t port, uint8_t stream);
 void abis_nm_ipaccess_cgi(uint8_t *buf, struct gsm_bts *bts);
 int ipac_parse_bcch_info(struct ipac_bcch_info *binf, uint8_t *buf);
diff --git a/src/ipaccess/ipaccess-config.c b/src/ipaccess/ipaccess-config.c
index 0fb5ad929..b969b57c5 100644
--- a/src/ipaccess/ipaccess-config.c
+++ b/src/ipaccess/ipaccess-config.c
@@ -59,7 +59,8 @@ struct gsm_network *bsc_gsmnet;
 
 static int net_listen_testnr;
 static int restart;
-static char *prim_oml_ip;
+static bool get_prim_oml_ip;
+static char *set_prim_oml_ip;
 static char *bts_ip_addr, *bts_ip_mask, *bts_ip_gw;
 static char *unit_id;
 static uint16_t nv_flags;
@@ -493,37 +494,43 @@ static int ipa_nvflag_set(uint16_t *flags, uint16_t *mask, const char *name, int
 
 static void bootstrap_om(struct gsm_bts_trx *trx)
 {
-	struct msgb *nmsg = msgb_alloc(1024, "nested msgb");
-	int need_to_set_attr = 0;
+	struct msgb *nmsg_get = msgb_alloc(1024, "nested get msgb");
+	struct msgb *nmsg_set = msgb_alloc(1024, "nested set msgb");
+	int need_to_get_attr = 0, need_to_set_attr = 0;
 	int len;
 
 	printf("OML link established using TRX %d\n", trx->nr);
 
+	if (get_prim_oml_ip) {
+		printf("getting primary OML link IP\n");
+		msgb_put_u8(nmsg_get, NM_ATT_IPACC_PRIM_OML_CFG);
+		need_to_get_attr = 1;
+	}
 	if (unit_id) {
 		len = strlen(unit_id);
-		if (len > nmsg->data_len-10)
+		if (len > nmsg_set->data_len-10)
 			goto out_err;
 		printf("setting Unit ID to '%s'\n", unit_id);
-		nv_put_unit_id(nmsg, unit_id);
+		nv_put_unit_id(nmsg_set, unit_id);
 		need_to_set_attr = 1;
 	}
-	if (prim_oml_ip) {
+	if (set_prim_oml_ip) {
 		struct in_addr ia;
 
-		if (!inet_aton(prim_oml_ip, &ia)) {
+		if (!inet_aton(set_prim_oml_ip, &ia)) {
 			fprintf(stderr, "invalid IP address: %s\n",
-				prim_oml_ip);
+				set_prim_oml_ip);
 			goto out_err;
 		}
 
 		printf("setting primary OML link IP to '%s'\n", inet_ntoa(ia));
-		nv_put_prim_oml(nmsg, ntohl(ia.s_addr), 0);
+		nv_put_prim_oml(nmsg_set, ntohl(ia.s_addr), 0);
 		need_to_set_attr = 1;
 	}
 	if (nv_mask) {
 		printf("setting NV Flags/Mask to 0x%04x/0x%04x\n",
 			nv_flags, nv_mask);
-		nv_put_flags(nmsg, nv_flags, nv_mask);
+		nv_put_flags(nmsg_set, nv_flags, nv_mask);
 		need_to_set_attr = 1;
 	}
 	if (bts_ip_addr && bts_ip_mask) {
@@ -542,7 +549,7 @@ static void bootstrap_om(struct gsm_bts_trx *trx)
 		}
 
 		printf("setting static IP Address/Mask\n");
-		nv_put_ip_if_cfg(nmsg, ntohl(ia_addr.s_addr), ntohl(ia_mask.s_addr));
+		nv_put_ip_if_cfg(nmsg_set, ntohl(ia_addr.s_addr), ntohl(ia_mask.s_addr));
 		need_to_set_attr = 1;
 	}
 	if (bts_ip_gw) {
@@ -556,22 +563,30 @@ static void bootstrap_om(struct gsm_bts_trx *trx)
 
 		printf("setting static IP Gateway\n");
 		/* we only set the default gateway with zero addr/mask */
-		nv_put_gw_cfg(nmsg, 0, 0, ntohl(ia_gw.s_addr));
+		nv_put_gw_cfg(nmsg_set, 0, 0, ntohl(ia_gw.s_addr));
 		need_to_set_attr = 1;
 	}
 
+	if (need_to_get_attr) {
+		printf("abis_nm_get_attr (%d): %s\n", nmsg_get->len, osmo_hexdump(msgb_data(nmsg_get), msgb_length(nmsg_get)));
+		abis_nm_get_attr(trx->bts, NM_OC_BASEB_TRANSC, 0, trx->nr, 0xff, nmsg_get->head, nmsg_get->len);
+		oml_state = 1;
+	}
+
 	if (need_to_set_attr) {
-		abis_nm_ipaccess_set_nvattr(trx, nmsg->head, nmsg->len);
+		printf("abis_nm_ipaccess_set_nvattr\n");
+		abis_nm_ipaccess_set_nvattr(trx, nmsg_set->head, nmsg_set->len);
 		oml_state = 1;
 	}
 
-	if (restart && !prim_oml_ip && !software) {
+	if (restart && !set_prim_oml_ip && !software) {
 		printf("restarting BTS\n");
 		abis_nm_ipaccess_restart(trx);
 	}
 
 out_err:
-	msgb_free(nmsg);
+	msgb_free(nmsg_get);
+	msgb_free(nmsg_set);
 }
 
 static int nm_state_event(int evt, uint8_t obj_class, void *obj,
@@ -833,6 +848,7 @@ static void print_help(void)
 	printf("Commands for writing to the BTS:\n");
 	printf("  -u --unit-id UNIT_ID\t\tSet the Unit ID of the BTS\n");
 	printf("  -o --oml-ip IP\t\tSet primary OML IP (IP of your BSC)\n");
+	printf("  -O --get-oml-ip IP\t\tGet primary OML IP (IP of your BSC)\n");
 	printf("  -i --ip-address IP/MASK\tSet static IP address + netmask of BTS\n");
 	printf("  -g --ip-gateway IP\t\tSet static IP gateway of BTS\n");
 	printf("  -r --restart\t\t\tRestart the BTS (after other operations)\n");
@@ -911,6 +927,7 @@ int main(int argc, char **argv)
 		char *slash;
 		static struct option long_options[] = {
 			{ "unit-id", 1, 0, 'u' },
+			{ "get-oml-ip", 0, 0, 'O' },
 			{ "oml-ip", 1, 0, 'o' },
 			{ "ip-address", 1, 0, 'i' },
 			{ "ip-gateway", 1, 0, 'g' },
@@ -931,7 +948,7 @@ int main(int argc, char **argv)
 			{ 0, 0, 0, 0 },
 		};
 
-		c = getopt_long(argc, argv, "u:o:i:g:rn:S:U:l:L:hs:d:f:wcpH", long_options,
+		c = getopt_long(argc, argv, "u:Oo:i:g:rn:S:U:l:L:hs:d:f:wcpH", long_options,
 				&option_index);
 
 		if (c == -1)
@@ -943,8 +960,11 @@ int main(int argc, char **argv)
 				exit(2);
 			unit_id = optarg;
 			break;
+		case 'O':
+			get_prim_oml_ip = true;
+			break;
 		case 'o':
-			prim_oml_ip = optarg;
+			set_prim_oml_ip = optarg;
 			break;
 		case 'i':
 			slash = strchr(optarg, '/');
@@ -1044,7 +1064,7 @@ int main(int argc, char **argv)
 	gsm_bts_trx_alloc(bts);
 	gsm_bts_trx_alloc(bts);
 	bts->oml_tei = stream_id;
-	
+
 	osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL);
 	osmo_signal_register_handler(SS_IPAC_NWL, nwl_sig_cb, NULL);
 
@@ -1060,7 +1080,7 @@ int main(int argc, char **argv)
 		perror("Error connecting to the BTS");
 		exit(1);
 	}
-	
+
 	bts->oml_link->ts->sign.delay = 10;
 	bts->c0->rsl_link->ts->sign.delay = 10;
 	while (1) {
diff --git a/src/osmo-bsc/abis_nm.c b/src/osmo-bsc/abis_nm.c
index f75470d40..a147eb866 100644
--- a/src/osmo-bsc/abis_nm.c
+++ b/src/osmo-bsc/abis_nm.c
@@ -544,6 +544,20 @@ static int abis_nm_rx_get_attr_resp(struct msgb *mb, const struct gsm_bts_trx *t
 	DEBUGPFOH(DNM, foh, "Get Attributes Response for BTS%u\n", bts->nr);
 
 	abis_nm_tlv_parse(&tp, bts, foh->data, oh->length-sizeof(*foh));
+	if (TLVP_PRES_LEN(&tp, NM_ATT_IPACC_PRIM_OML_CFG_LIST, 1)) {
+		data = TLVP_VAL(&tp, NM_ATT_IPACC_PRIM_OML_CFG_LIST);
+		//uint16_t cfg_list_len = osmo_load16be(data+1);
+		OSMO_ASSERT(NM_ATT_IPACC_PRIM_OML_CFG == *data);
+		uint32_t ip = osmo_load32be(data+1);
+		uint16_t port = osmo_load16be(data+5);
+		struct in_addr ia = {0};
+		ia.s_addr = htonl(ip);
+		LOGP(DNM, LOGL_NOTICE, "%s Get Attributes Response: OML IP is %s:%u\n", gsm_trx_name(trx), inet_ntoa(ia), port);
+	} else {
+		LOGPFOH(DNM, LOGL_ERROR, foh, "BTS%u: Get Attr Response without List of Required Attributes?!\n",
+			bts->nr);
+	}
+
 	if (!TLVP_PRES_LEN(&tp, NM_ATT_GET_ARI, 1)) {
 		LOGPFOH(DNM, LOGL_ERROR, foh, "BTS%u: Get Attr Response without Response Info?!\n",
 			bts->nr);
@@ -1649,10 +1663,12 @@ int abis_nm_get_attr(struct gsm_bts *bts, uint8_t obj_class, uint8_t bts_nr, uin
 	if (bts->type != GSM_BTS_TYPE_OSMOBTS) {
 		LOGPC(DNM, LOGL_NOTICE, "Getting attributes from BTS%d type %s is not supported.\n",
 		      bts->nr, btstype2str(bts->type));
-		return -EINVAL;
+	      fprintf(stderr, "Getting attributes from BTS%d type %s is not supported.\n",
+		    bts->nr, btstype2str(bts->type));
+		//return -EINVAL;
 	}
 
-	DEBUGP(DNM, "Get Attr (bts=%d)\n", bts->nr);
+	 fprintf(stderr, "Get Attr (bts=%d)\n", bts->nr);
 
 	msg = nm_msgb_alloc();
 	oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
@@ -2779,7 +2795,7 @@ int abis_nm_ipaccess_msg(struct gsm_bts *bts, uint8_t msg_type,
 }
 
 /* set some attributes in NVRAM */
-int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, uint8_t *attr,
+	int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, uint8_t *attr,
 				int attr_len)
 {
 	return abis_nm_ipaccess_msg(trx->bts, NM_MT_IPACC_SET_NVATTR,
@@ -2787,6 +2803,15 @@ int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, uint8_t *attr,
 				    attr_len);
 }
 
+/* get some attributes from NVRAM */
+int abis_nm_ipaccess_get_nvattr(struct gsm_bts_trx *trx, uint8_t *attr,
+				int attr_len)
+{
+	return abis_nm_ipaccess_msg(trx->bts, NM_MT_IPACC_GET_NVATTR,
+				    NM_OC_BASEB_TRANSC, 0, trx->nr, 0xff, attr,
+				    attr_len);
+}
+
 static void rsl_connect_timeout(void *data)
 {
 	struct gsm_bts_trx *trx = data;
-- 
2.19.1

