gsm_data_shared: introduce 'struct gsm_abis_mo'

... as a common wrapper around nm_attr and nm_state
diff --git a/openbsc/include/openbsc/gsm_data_shared.h b/openbsc/include/openbsc/gsm_data_shared.h
index 5c7b40b..3a6f95f 100644
--- a/openbsc/include/openbsc/gsm_data_shared.h
+++ b/openbsc/include/openbsc/gsm_data_shared.h
@@ -83,6 +83,12 @@
 	uint8_t availability;
 };
 
+struct gsm_abis_mo {
+	const char *name;
+	struct gsm_nm_state nm_state;
+	struct tlv_parsed *nm_attr;
+};
+
 #define MAX_A5_KEY_LEN	(128/8)
 #define A38_XOR_MIN_KEY_LEN	12
 #define A38_XOR_MAX_KEY_LEN	16
@@ -104,7 +110,6 @@
 	LCHAN_S_INACTIVE,	/* channel is set inactive */
 };
 
-
 struct gsm_lchan {
 	/* The TS that we're part of */
 	struct gsm_bts_trx_ts *ts;
@@ -187,7 +192,7 @@
 	enum gsm_phys_chan_config pchan;
 
 	unsigned int flags;
-	struct gsm_nm_state nm_state;
+	struct gsm_abis_mo mo;
 	struct tlv_parsed nm_attr;
 	uint8_t nm_chan_comb;
 
@@ -227,10 +232,10 @@
 	/* Some BTS (specifically Ericsson RBS) have a per-TRX OML Link */
 	struct e1inp_sign_link *oml_link;
 
-	struct gsm_nm_state nm_state;
+	struct gsm_abis_mo mo;
 	struct tlv_parsed nm_attr;
 	struct {
-		struct gsm_nm_state nm_state;
+		struct gsm_abis_mo mo;
 	} bb_transc;
 
 	uint16_t arfcn;
@@ -240,10 +245,10 @@
 	union {
 		struct {
 			struct {
-				struct gsm_nm_state nm_state;
+				struct gsm_abis_mo mo;
 			} bbsig;
 			struct {
-				struct gsm_nm_state nm_state;
+				struct gsm_abis_mo mo;
 			} pa;
 		} bs11;
 		struct {
@@ -316,7 +321,7 @@
 };
 
 struct gsm_envabtse {
-	struct gsm_nm_state nm_state;
+	struct gsm_abis_mo mo;
 };
 
 struct gsm_bts_gprs_nsvc {
@@ -329,7 +334,7 @@
 	uint16_t remote_port;	/* on the SGSN */
 	uint32_t remote_ip;	/* on the SGSN */
 
-	struct gsm_nm_state nm_state;
+	struct gsm_abis_mo mo;
 };
 
 enum neigh_list_manual_mode {
@@ -369,8 +374,8 @@
 
 	/* Abis network management O&M handle */
 	struct abis_nm_h *nmh;
-	struct gsm_nm_state nm_state;
-	struct tlv_parsed nm_attr;
+
+	struct gsm_abis_mo mo;
 
 	/* number of this BTS on given E1 link */
 	uint8_t bts_nr;
@@ -382,7 +387,7 @@
 	struct gsm_bts_trx *c0;
 
 	struct {
-		struct gsm_nm_state nm_state;
+		struct gsm_abis_mo mo;
 	} site_mgr;
 
 	/* bitmask of all SI that are present/valid in si_buf */
@@ -399,27 +404,27 @@
 		} ip_access;
 		struct {
 			struct {
-				struct gsm_nm_state nm_state;
+				struct gsm_abis_mo mo;
 			} cclk;
 			struct {
-				struct gsm_nm_state nm_state;
+				struct gsm_abis_mo mo;
 			} rack;
 			struct gsm_envabtse envabtse[4];
 		} bs11;
 		struct {
 			struct {
-				struct gsm_nm_state nm_state;
+				struct gsm_abis_mo mo;
 				struct llist_head conn_groups;
 			} is;
 			struct {
-				struct gsm_nm_state nm_state;
+				struct gsm_abis_mo mo;
 				struct llist_head conn_groups;
 			} con;
 			struct {
-				struct gsm_nm_state nm_state;
+				struct gsm_abis_mo mo;
 			} dp;
 			struct {
-				struct gsm_nm_state nm_state;
+				struct gsm_abis_mo mo;
 			} tf;
 		} rbs2000;
 		struct {
@@ -431,12 +436,12 @@
 	struct {
 		enum bts_gprs_mode mode;
 		struct {
-			struct gsm_nm_state nm_state;
+			struct gsm_abis_mo mo;
 			uint16_t nsei;
 			uint8_t timer[7];
 		} nse;
 		struct {
-			struct gsm_nm_state nm_state;
+			struct gsm_abis_mo mo;
 			uint16_t bvci;
 			uint8_t timer[11];
 		} cell;
diff --git a/openbsc/src/libbsc/abis_nm.c b/openbsc/src/libbsc/abis_nm.c
index f2220a7..0c3fff5 100644
--- a/openbsc/src/libbsc/abis_nm.c
+++ b/openbsc/src/libbsc/abis_nm.c
@@ -150,17 +150,17 @@
 	);
 }
 
-/* obtain the gsm_nm_state data structure for a given object instance */
-static struct gsm_nm_state *
-objclass2nmstate(struct gsm_bts *bts, uint8_t obj_class,
-		 struct abis_om_obj_inst *obj_inst)
+/* obtain the MO structure for a given object instance */
+static struct gsm_abis_mo *
+objclass2mo(struct gsm_bts *bts, uint8_t obj_class,
+	    struct abis_om_obj_inst *obj_inst)
 {
 	struct gsm_bts_trx *trx;
-	struct gsm_nm_state *nm_state = NULL;
+	struct gsm_abis_mo *mo = NULL;
 
 	switch (obj_class) {
 	case NM_OC_BTS:
-		nm_state = &bts->nm_state;
+		mo = &bts->mo;
 		break;
 	case NM_OC_RADIO_CARRIER:
 		if (obj_inst->trx_nr >= bts->num_trx) {
@@ -168,7 +168,7 @@
 			return NULL;
 		}
 		trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
-		nm_state = &trx->nm_state;
+		mo = &trx->mo;
 		break;
 	case NM_OC_BASEB_TRANSC:
 		if (obj_inst->trx_nr >= bts->num_trx) {
@@ -176,7 +176,7 @@
 			return NULL;
 		}
 		trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
-		nm_state = &trx->bb_transc.nm_state;
+		mo = &trx->bb_transc.mo;
 		break;
 	case NM_OC_CHANNEL:
 		if (obj_inst->trx_nr >= bts->num_trx) {
@@ -186,52 +186,66 @@
 		trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
 		if (obj_inst->ts_nr >= TRX_NR_TS)
 			return NULL;
-		nm_state = &trx->ts[obj_inst->ts_nr].nm_state;
+		mo = &trx->ts[obj_inst->ts_nr].mo;
 		break;
 	case NM_OC_SITE_MANAGER:
-		nm_state = &bts->site_mgr.nm_state;
+		mo = &bts->site_mgr.mo;
 		break;
 	case NM_OC_BS11:
 		switch (obj_inst->bts_nr) {
 		case BS11_OBJ_CCLK:
-			nm_state = &bts->bs11.cclk.nm_state;
+			mo = &bts->bs11.cclk.mo;
 			break;
 		case BS11_OBJ_BBSIG:
 			if (obj_inst->ts_nr > bts->num_trx)
 				return NULL;
 			trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
-			nm_state = &trx->bs11.bbsig.nm_state;
+			mo = &trx->bs11.bbsig.mo;
 			break;
 		case BS11_OBJ_PA:
 			if (obj_inst->ts_nr > bts->num_trx)
 				return NULL;
 			trx = gsm_bts_trx_num(bts, obj_inst->trx_nr);
-			nm_state = &trx->bs11.pa.nm_state;
+			mo = &trx->bs11.pa.mo;
 			break;
 		default:
 			return NULL;
 		}
 	case NM_OC_BS11_RACK:
-		nm_state = &bts->bs11.rack.nm_state;
+		mo = &bts->bs11.rack.mo;
 		break;
 	case NM_OC_BS11_ENVABTSE:
 		if (obj_inst->trx_nr >= ARRAY_SIZE(bts->bs11.envabtse))
 			return NULL;
-		nm_state = &bts->bs11.envabtse[obj_inst->trx_nr].nm_state;
+		mo = &bts->bs11.envabtse[obj_inst->trx_nr].mo;
 		break;
 	case NM_OC_GPRS_NSE:
-		nm_state = &bts->gprs.nse.nm_state;
+		mo = &bts->gprs.nse.mo;
 		break;
 	case NM_OC_GPRS_CELL:
-		nm_state = &bts->gprs.cell.nm_state;
+		mo = &bts->gprs.cell.mo;
 		break;
 	case NM_OC_GPRS_NSVC:
 		if (obj_inst->trx_nr >= ARRAY_SIZE(bts->gprs.nsvc))
 			return NULL;
-		nm_state = &bts->gprs.nsvc[obj_inst->trx_nr].nm_state;
+		mo = &bts->gprs.nsvc[obj_inst->trx_nr].mo;
 		break;
 	}
-	return nm_state;
+	return mo;
+}
+
+/* obtain the gsm_nm_state data structure for a given object instance */
+static struct gsm_nm_state *
+objclass2nmstate(struct gsm_bts *bts, uint8_t obj_class,
+		 struct abis_om_obj_inst *obj_inst)
+{
+	struct gsm_abis_mo *mo;
+
+	mo = objclass2mo(bts, obj_class, obj_inst);
+	if (!mo)
+		return NULL;
+
+	return &mo->nm_state;
 }
 
 /* obtain the in-memory data structure of a given object instance */
@@ -2626,7 +2640,7 @@
 {
 	int new_state = locked ? NM_STATE_LOCKED : NM_STATE_UNLOCKED;
 
-	trx->nm_state.administrative = new_state;
+	trx->mo.nm_state.administrative = new_state;
 	if (!trx->bts || !trx->bts->oml_link)
 		return;
 
diff --git a/openbsc/src/libbsc/abis_om2000.c b/openbsc/src/libbsc/abis_om2000.c
index fd3cf1f..b636e73 100644
--- a/openbsc/src/libbsc/abis_om2000.c
+++ b/openbsc/src/libbsc/abis_om2000.c
@@ -664,7 +664,7 @@
 		trx = gsm_bts_trx_num(bts, mo->assoc_so);
 		if (!trx)
 			return NULL;
-		nm_state = &trx->nm_state;
+		nm_state = &trx->mo.nm_state;
 		break;
 	case OM2K_MO_CLS_TS:
 		trx = gsm_bts_trx_num(bts, mo->assoc_so);
@@ -672,22 +672,22 @@
 			return NULL;
 		if (mo->inst >= ARRAY_SIZE(trx->ts))
 			return NULL;
-		nm_state = &trx->ts[mo->inst].nm_state;
+		nm_state = &trx->ts[mo->inst].mo.nm_state;
 		break;
 	case OM2K_MO_CLS_TF:
-		nm_state = &bts->rbs2000.tf.nm_state;
+		nm_state = &bts->rbs2000.tf.mo.nm_state;
 		break;
 	case OM2K_MO_CLS_IS:
-		nm_state = &bts->rbs2000.is.nm_state;
+		nm_state = &bts->rbs2000.is.mo.nm_state;
 		break;
 	case OM2K_MO_CLS_CON:
-		nm_state = &bts->rbs2000.con.nm_state;
+		nm_state = &bts->rbs2000.con.mo.nm_state;
 		break;
 	case OM2K_MO_CLS_DP:
-		nm_state = &bts->rbs2000.con.nm_state;
+		nm_state = &bts->rbs2000.con.mo.nm_state;
 		break;
 	case OM2K_MO_CLS_CF:
-		nm_state = &bts->nm_state;
+		nm_state = &bts->mo.nm_state;
 		break;
 	case OM2K_MO_CLS_TX:
 		trx = gsm_bts_trx_num(bts, mo->assoc_so);
diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c
index 378f5ea..8654dd7 100644
--- a/openbsc/src/libbsc/bsc_init.c
+++ b/openbsc/src/libbsc/bsc_init.c
@@ -293,14 +293,14 @@
 				lchan_reset(&ts->lchan[lchan_no]);
 			}
 
-			ts->nm_state.operational = 0;
-			ts->nm_state.availability = 0;
+			ts->mo.nm_state.operational = 0;
+			ts->mo.nm_state.availability = 0;
 		}
 
-		trx->nm_state.operational = 0;
-		trx->nm_state.availability = 0;
-		trx->bb_transc.nm_state.operational = 0;
-		trx->bb_transc.nm_state.availability = 0;
+		trx->mo.nm_state.operational = 0;
+		trx->mo.nm_state.availability = 0;
+		trx->bb_transc.mo.nm_state.operational = 0;
+		trx->bb_transc.mo.nm_state.availability = 0;
 
 		abis_nm_clear_queue(trx->bts);
 		break;
diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c
index a72ff21..b667b92 100644
--- a/openbsc/src/libbsc/bsc_vty.c
+++ b/openbsc/src/libbsc/bsc_vty.c
@@ -256,9 +256,9 @@
 	else if (bts->type == GSM_BTS_TYPE_HSL_FEMTO)
 		vty_out(vty, "  Serial Number: %lu%s", bts->hsl.serno, VTY_NEWLINE);
 	vty_out(vty, "  NM State: ");
-	net_dump_nmstate(vty, &bts->nm_state);
+	net_dump_nmstate(vty, &bts->mo.nm_state);
 	vty_out(vty, "  Site Mgr NM State: ");
-	net_dump_nmstate(vty, &bts->site_mgr.nm_state);
+	net_dump_nmstate(vty, &bts->site_mgr.mo.nm_state);
 	vty_out(vty, "  Paging: %u pending requests, %u free slots%s",
 		paging_pending_requests_nr(bts),
 		bts->paging.available_slots, VTY_NEWLINE);
@@ -366,7 +366,7 @@
 		vty_out(vty, "   description %s%s", trx->description,
 			VTY_NEWLINE);
 	vty_out(vty, "   rf_locked %u%s",
-		trx->nm_state.administrative == NM_STATE_LOCKED ? 1 : 0,
+		trx->mo.nm_state.administrative == NM_STATE_LOCKED ? 1 : 0,
 		VTY_NEWLINE);
 	vty_out(vty, "   arfcn %u%s", trx->arfcn, VTY_NEWLINE);
 	vty_out(vty, "   nominal power %u%s", trx->nominal_power, VTY_NEWLINE);
@@ -617,9 +617,9 @@
 		trx->nominal_power, trx->max_power_red,
 		trx->nominal_power - trx->max_power_red, VTY_NEWLINE);
 	vty_out(vty, "  NM State: ");
-	net_dump_nmstate(vty, &trx->nm_state);
+	net_dump_nmstate(vty, &trx->mo.nm_state);
 	vty_out(vty, "  Baseband Transceiver NM State: ");
-	net_dump_nmstate(vty, &trx->bb_transc.nm_state);
+	net_dump_nmstate(vty, &trx->bb_transc.mo.nm_state);
 	if (is_ipaccess_bts(trx->bts)) {
 		vty_out(vty, "  ip.access stream ID: 0x%02x%s",
 			trx->rsl_tei, VTY_NEWLINE);
@@ -693,7 +693,7 @@
 			ts->flags & TS_F_PDCH_MODE ? "PDCH" : "TCH/F");
 	vty_out(vty, "%s", VTY_NEWLINE);
 	vty_out(vty, "  NM State: ");
-	net_dump_nmstate(vty, &ts->nm_state);
+	net_dump_nmstate(vty, &ts->mo.nm_state);
 	if (!is_ipaccess_bts(ts->trx->bts))
 		vty_out(vty, "  E1 Line %u, Timeslot %u, Subslot %u%s",
 			ts->e1_link.e1_nr, ts->e1_link.e1_ts,
diff --git a/openbsc/src/libbsc/bts_ipaccess_nanobts.c b/openbsc/src/libbsc/bts_ipaccess_nanobts.c
index 706712e..e756f2a 100644
--- a/openbsc/src/libbsc/bts_ipaccess_nanobts.c
+++ b/openbsc/src/libbsc/bts_ipaccess_nanobts.c
@@ -402,7 +402,7 @@
 		 * This code is here to make sure that on start
 		 * a TRX remains locked.
 		 */
-		int rc_state = trx->nm_state.administrative;
+		int rc_state = trx->mo.nm_state.administrative;
 		/* Patch ARFCN into radio attribute */
 		nanobts_attr_radio[5] &= 0xf0;
 		nanobts_attr_radio[5] |= trx->arfcn >> 8;
diff --git a/openbsc/src/libbsc/chan_alloc.c b/openbsc/src/libbsc/chan_alloc.c
index cfd3874..c0bdc1b 100644
--- a/openbsc/src/libbsc/chan_alloc.c
+++ b/openbsc/src/libbsc/chan_alloc.c
@@ -38,7 +38,7 @@
 {
 	/* FIXME: How does this behave for BS-11 ? */
 	if (is_ipaccess_bts(ts->trx->bts)) {
-		if (!nm_is_running(&ts->nm_state))
+		if (!nm_is_running(&ts->mo.nm_state))
 			return 0;
 	}
 
@@ -49,8 +49,8 @@
 {
 	/* FIXME: How does this behave for BS-11 ? */
 	if (is_ipaccess_bts(trx->bts)) {
-		if (!nm_is_running(&trx->nm_state) ||
-		    !nm_is_running(&trx->bb_transc.nm_state))
+		if (!nm_is_running(&trx->mo.nm_state) ||
+		    !nm_is_running(&trx->bb_transc.mo.nm_state))
 			return 0;
 	}
 
@@ -465,8 +465,8 @@
 		int i;
 
 		/* skip administratively deactivated tranxsceivers */
-		if (!nm_is_running(&trx->nm_state) ||
-		    !nm_is_running(&trx->bb_transc.nm_state))
+		if (!nm_is_running(&trx->mo.nm_state) ||
+		    !nm_is_running(&trx->bb_transc.mo.nm_state))
 			continue;
 
 		for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
@@ -475,7 +475,7 @@
 			int j;
 
 			/* skip administratively deactivated timeslots */
-			if (!nm_is_running(&ts->nm_state))
+			if (!nm_is_running(&ts->mo.nm_state))
 				continue;
 
 			for (j = 0; j < subslots_per_pchan[ts->pchan]; j++) {
diff --git a/openbsc/src/libcommon/gsm_data.c b/openbsc/src/libcommon/gsm_data.c
index 54e7a63..b1fb4db 100644
--- a/openbsc/src/libcommon/gsm_data.c
+++ b/openbsc/src/libcommon/gsm_data.c
@@ -147,7 +147,7 @@
 
 	trx->bts = bts;
 	trx->nr = bts->num_trx++;
-	trx->nm_state.administrative = NM_STATE_UNLOCKED;
+	trx->mo.nm_state.administrative = NM_STATE_UNLOCKED;
 
 	for (k = 0; k < TRX_NR_TS; k++) {
 		struct gsm_bts_trx_ts *ts = &trx->ts[k];