mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-mgw.git
				synced 2025-10-31 12:03:50 +00:00 
			
		
		
		
	OM2000: Track the Operational Info and MO state
This commit is contained in:
		| @@ -595,11 +595,19 @@ struct gsm_bts { | |||||||
| 		} bs11; | 		} bs11; | ||||||
| 		struct { | 		struct { | ||||||
| 			struct { | 			struct { | ||||||
|  | 				struct gsm_nm_state nm_state; | ||||||
| 				struct llist_head conn_groups; | 				struct llist_head conn_groups; | ||||||
| 			} is; | 			} is; | ||||||
| 			struct { | 			struct { | ||||||
|  | 				struct gsm_nm_state nm_state; | ||||||
| 				struct llist_head conn_groups; | 				struct llist_head conn_groups; | ||||||
| 			} con; | 			} con; | ||||||
|  | 			struct { | ||||||
|  | 				struct gsm_nm_state nm_state; | ||||||
|  | 			} dp; | ||||||
|  | 			struct { | ||||||
|  | 				struct gsm_nm_state nm_state; | ||||||
|  | 			} tf; | ||||||
| 		} rbs2000; | 		} rbs2000; | ||||||
| 		struct { | 		struct { | ||||||
| 			unsigned long serno; | 			unsigned long serno; | ||||||
|   | |||||||
| @@ -172,12 +172,18 @@ struct ipacc_ack_signal_data { | |||||||
| 	u_int8_t msg_type;	 | 	u_int8_t msg_type;	 | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | struct abis_om2k_mo; | ||||||
|  |  | ||||||
| struct nm_statechg_signal_data { | struct nm_statechg_signal_data { | ||||||
| 	u_int8_t obj_class; | 	u_int8_t obj_class; | ||||||
| 	void *obj; | 	void *obj; | ||||||
| 	struct gsm_nm_state *old_state; | 	struct gsm_nm_state *old_state; | ||||||
| 	struct gsm_nm_state *new_state; | 	struct gsm_nm_state *new_state; | ||||||
|  |  | ||||||
|  | 	/* This pointer is vaold for TS 12.21 MO */ | ||||||
| 	struct abis_om_obj_inst *obj_inst; | 	struct abis_om_obj_inst *obj_inst; | ||||||
|  | 	/* This pointer is vaold for RBS2000 MO */ | ||||||
|  | 	struct abis_om2k_mo *om2k_mo; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| struct nm_nack_signal_data { | struct nm_nack_signal_data { | ||||||
|   | |||||||
| @@ -685,6 +685,8 @@ static int update_admstate(struct gsm_bts *bts, u_int8_t obj_class, | |||||||
| 	struct gsm_nm_state *nm_state, new_state; | 	struct gsm_nm_state *nm_state, new_state; | ||||||
| 	struct nm_statechg_signal_data nsd; | 	struct nm_statechg_signal_data nsd; | ||||||
|  |  | ||||||
|  | 	memset(&nsd, 0, sizeof(nsd)); | ||||||
|  |  | ||||||
| 	nsd.obj = objclass2obj(bts, obj_class, obj_inst); | 	nsd.obj = objclass2obj(bts, obj_class, obj_inst); | ||||||
| 	if (!nsd.obj) | 	if (!nsd.obj) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
|   | |||||||
| @@ -652,6 +652,149 @@ static char *om2k_mo_name(const struct abis_om2k_mo *mo) | |||||||
| 	return mo_buf; | 	return mo_buf; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* resolve the gsm_nm_state data structure for a given MO */ | ||||||
|  | static struct gsm_nm_state * | ||||||
|  | mo2nm_state(struct gsm_bts *bts, const struct abis_om2k_mo *mo) | ||||||
|  | { | ||||||
|  | 	struct gsm_bts_trx *trx; | ||||||
|  | 	struct gsm_nm_state *nm_state = NULL; | ||||||
|  |  | ||||||
|  | 	switch (mo->class) { | ||||||
|  | 	case OM2K_MO_CLS_TRXC: | ||||||
|  | 		trx = gsm_bts_trx_num(bts, mo->assoc_so); | ||||||
|  | 		if (!trx) | ||||||
|  | 			return NULL; | ||||||
|  | 		nm_state = &trx->nm_state; | ||||||
|  | 		break; | ||||||
|  | 	case OM2K_MO_CLS_TS: | ||||||
|  | 		trx = gsm_bts_trx_num(bts, mo->assoc_so); | ||||||
|  | 		if (!trx) | ||||||
|  | 			return NULL; | ||||||
|  | 		if (mo->inst >= ARRAY_SIZE(trx->ts)) | ||||||
|  | 			return NULL; | ||||||
|  | 		nm_state = &trx->ts[mo->inst].nm_state; | ||||||
|  | 		break; | ||||||
|  | 	case OM2K_MO_CLS_TF: | ||||||
|  | 		nm_state = &bts->rbs2000.tf.nm_state; | ||||||
|  | 		break; | ||||||
|  | 	case OM2K_MO_CLS_IS: | ||||||
|  | 		nm_state = &bts->rbs2000.is.nm_state; | ||||||
|  | 		break; | ||||||
|  | 	case OM2K_MO_CLS_CON: | ||||||
|  | 		nm_state = &bts->rbs2000.con.nm_state; | ||||||
|  | 		break; | ||||||
|  | 	case OM2K_MO_CLS_DP: | ||||||
|  | 		nm_state = &bts->rbs2000.con.nm_state; | ||||||
|  | 		break; | ||||||
|  | 	case OM2K_MO_CLS_CF: | ||||||
|  | 		nm_state = &bts->nm_state; | ||||||
|  | 		break; | ||||||
|  | 	case OM2K_MO_CLS_TX: | ||||||
|  | 		trx = gsm_bts_trx_num(bts, mo->assoc_so); | ||||||
|  | 		if (!trx) | ||||||
|  | 			return NULL; | ||||||
|  | 		break; | ||||||
|  | 	case OM2K_MO_CLS_RX: | ||||||
|  | 		trx = gsm_bts_trx_num(bts, mo->assoc_so); | ||||||
|  | 		if (!trx) | ||||||
|  | 			return NULL; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nm_state; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void *mo2obj(struct gsm_bts *bts, struct abis_om2k_mo *mo) | ||||||
|  | { | ||||||
|  | 	struct gsm_bts_trx *trx; | ||||||
|  |  | ||||||
|  | 	switch (mo->class) { | ||||||
|  | 	case OM2K_MO_CLS_TX: | ||||||
|  | 	case OM2K_MO_CLS_RX: | ||||||
|  | 	case OM2K_MO_CLS_TRXC: | ||||||
|  | 		return gsm_bts_trx_num(bts, mo->assoc_so); | ||||||
|  | 	case OM2K_MO_CLS_TS: | ||||||
|  | 		trx = gsm_bts_trx_num(bts, mo->assoc_so); | ||||||
|  | 		if (!trx) | ||||||
|  | 			return NULL; | ||||||
|  | 		if (mo->inst >= ARRAY_SIZE(trx->ts)) | ||||||
|  | 			return NULL; | ||||||
|  | 		return &trx->ts[mo->inst]; | ||||||
|  | 	case OM2K_MO_CLS_TF: | ||||||
|  | 	case OM2K_MO_CLS_IS: | ||||||
|  | 	case OM2K_MO_CLS_CON: | ||||||
|  | 	case OM2K_MO_CLS_DP: | ||||||
|  | 	case OM2K_MO_CLS_CF: | ||||||
|  | 		return bts; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void update_mo_state(struct gsm_bts *bts, struct abis_om2k_mo *mo, | ||||||
|  | 			    uint8_t mo_state) | ||||||
|  | { | ||||||
|  | 	struct gsm_nm_state *nm_state = mo2nm_state(bts, mo); | ||||||
|  | 	struct gsm_nm_state new_state; | ||||||
|  | 	struct nm_statechg_signal_data nsd; | ||||||
|  |  | ||||||
|  | 	if (!nm_state) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	new_state = *nm_state; | ||||||
|  | 	/* NOTICE: 12.21 Availability state values != OM2000 */ | ||||||
|  | 	new_state.availability = mo_state; | ||||||
|  |  | ||||||
|  | 	memset(&nsd, 0, sizeof(nsd)); | ||||||
|  |  | ||||||
|  | 	nsd.obj = mo2obj(bts, mo); | ||||||
|  | 	nsd.old_state = nm_state; | ||||||
|  | 	nsd.new_state = &new_state; | ||||||
|  | 	nsd.om2k_mo = mo; | ||||||
|  |  | ||||||
|  | 	dispatch_signal(SS_NM, S_NM_STATECHG_ADM, &nsd); | ||||||
|  |  | ||||||
|  | 	nm_state->availability = new_state.availability; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void update_op_state(struct gsm_bts *bts, const struct abis_om2k_mo *mo, | ||||||
|  | 			    uint8_t op_state) | ||||||
|  | { | ||||||
|  | 	struct gsm_nm_state *nm_state = mo2nm_state(bts, mo); | ||||||
|  | 	struct gsm_nm_state new_state; | ||||||
|  |  | ||||||
|  | 	if (!nm_state) | ||||||
|  | 		return; | ||||||
|  |  | ||||||
|  | 	new_state = *nm_state; | ||||||
|  | 	switch (op_state) { | ||||||
|  | 	case 1: | ||||||
|  | 		new_state.operational = NM_OPSTATE_ENABLED; | ||||||
|  | 		break; | ||||||
|  | 	case 0: | ||||||
|  | 		new_state.operational = NM_OPSTATE_DISABLED; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		new_state.operational = NM_OPSTATE_NULL; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	nm_state->operational = new_state.operational; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void signal_op_state(struct gsm_bts *bts, struct abis_om2k_mo *mo) | ||||||
|  | { | ||||||
|  | 	struct gsm_nm_state *nm_state = mo2nm_state(bts, mo); | ||||||
|  | 	struct nm_statechg_signal_data nsd; | ||||||
|  |  | ||||||
|  | 	nsd.obj = mo2obj(bts, mo); | ||||||
|  | 	nsd.old_state = nm_state; | ||||||
|  | 	nsd.new_state = nm_state; | ||||||
|  | 	nsd.om2k_mo = mo; | ||||||
|  |  | ||||||
|  | 	dispatch_signal(SS_NM, S_NM_STATECHG_OPER, &nsd); | ||||||
|  | } | ||||||
|  |  | ||||||
| static int abis_om2k_sendmsg(struct gsm_bts *bts, struct msgb *msg) | static int abis_om2k_sendmsg(struct gsm_bts *bts, struct msgb *msg) | ||||||
| { | { | ||||||
| 	struct abis_om2k_hdr *o2h; | 	struct abis_om2k_hdr *o2h; | ||||||
| @@ -805,6 +948,9 @@ int abis_om2k_tx_op_info(struct gsm_bts *bts, const struct abis_om2k_mo *mo, | |||||||
| 	DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(mo), | 	DEBUGP(DNM, "Tx MO=%s %s\n", om2k_mo_name(mo), | ||||||
| 		get_value_string(om2k_msgcode_vals, OM2K_MSGT_OP_INFO)); | 		get_value_string(om2k_msgcode_vals, OM2K_MSGT_OP_INFO)); | ||||||
|  |  | ||||||
|  | 	/* we update the state here... and send the signal at ACK */ | ||||||
|  | 	update_op_state(bts, mo, operational); | ||||||
|  |  | ||||||
| 	return abis_om2k_sendmsg(bts, msg); | 	return abis_om2k_sendmsg(bts, msg); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1160,7 +1306,11 @@ static int om2k_rx_op_info_ack(struct msgb *msg) | |||||||
| { | { | ||||||
| 	struct abis_om2k_hdr *o2h = msgb_l2(msg); | 	struct abis_om2k_hdr *o2h = msgb_l2(msg); | ||||||
|  |  | ||||||
| 	/* FIXME: update Operational state in our structures */ | 	/* This Acknowledgement does not contain the actual operational state, | ||||||
|  | 	 * so we signal whatever state we saved when we sent the Op Info | ||||||
|  | 	 * request */ | ||||||
|  |  | ||||||
|  | 	signal_op_state(msg->trx->bts, &o2h->mo); | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| @@ -1269,6 +1419,8 @@ static int process_mo_state(struct gsm_bts *bts, struct msgb *msg) | |||||||
| 		get_value_string(om2k_msgcode_vals, msg_type), | 		get_value_string(om2k_msgcode_vals, msg_type), | ||||||
| 		get_value_string(om2k_mostate_vals, mo_state)); | 		get_value_string(om2k_mostate_vals, mo_state)); | ||||||
|  |  | ||||||
|  | 	update_mo_state(bts, &o2h->mo, mo_state); | ||||||
|  |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user