[PATCH] osmo-bts[master]: LC15: Implementation of TS 12.21 measurement related message...

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Minh-Quang Nguyen gerrit-no-reply at lists.osmocom.org
Fri Sep 2 18:07:54 UTC 2016


Review at  https://gerrit.osmocom.org/811

LC15: Implementation of TS 12.21 measurement related messages to measure PCU KPI

Change-Id: I352600f964e6c161b9259c62f2e0a0f39f0f60d9
---
M include/osmo-bts/oml.h
M include/osmo-bts/pcu_if.h
M include/osmo-bts/pcuif_proto.h
M src/common/oml.c
M src/common/pcu_sock.c
5 files changed, 594 insertions(+), 5 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/11/811/1

diff --git a/include/osmo-bts/oml.h b/include/osmo-bts/oml.h
index fb49078..2751108 100644
--- a/include/osmo-bts/oml.h
+++ b/include/osmo-bts/oml.h
@@ -1,5 +1,6 @@
 #ifndef _OML_H
 #define _OML_H
+#include <osmo-bts/pcuif_proto.h>
 #include "openbsc/signal.h"
 
 struct gsm_bts;
@@ -28,6 +29,9 @@
 	S_NM_OML_BTS_FAIL_VERIFY_CALIB_ALARM,
 	S_NM_OML_BTS_NO_CALIB_PATH_ALARM,
 	S_NM_OML_BTS_RX_PCU_FAIL_EVT_ALARM,
+	S_NM_OML_BTS_UNKN_START_MEAS_REQ_ALARM,
+	S_NM_OML_BTS_UNKN_STOP_MEAS_REQ_ALARM,
+	S_NM_OML_BTS_UNKN_MEAS_REQ_ALARM,
 };
 
 struct oml_fail_evt_rep_sig_data {
@@ -46,9 +50,27 @@
 	uint16_t alarm_signal;	/* Failure alarm report signal cause */
 };
 
+enum abis_nm_msgtype_ipacc_appended {
+	NM_MT_IPACC_START_MEAS_ACK 		= 0xde,
+	NM_MT_IPACC_MEAS_RES_REQ_NACK		= 0xfc,
+	NM_MT_IPACC_START_MEAS_NACK		= 0xfd,
+	NM_MT_IPACC_STOP_MEAS_ACK 		= 0xdf,
+	NM_MT_IPACC_STOP_MEAS_NACK		= 0xfe,
+};
+
+enum abis_nm_ipacc_meas_type {
+	NM_IPACC_MEAS_TYPE_CCCH 		= 0x45,
+	NM_IPACC_MEAS_TYPE_UL_TBF 		= 0x49,
+	NM_IPACC_MEAS_TYPE_DL_TBF 		= 0x4a,
+	NM_IPACC_MEAS_TYPE_TBF_USE 		= 0x4c,
+	NM_IPACC_MEAS_TYPE_LLC_USE 		= 0x4d,
+	NM_IPACC_MEAS_TYPE_CS_CHG 		= 0x50,
+	NM_IPACC_MEAS_TYPE_UNKN
+};
+
 enum abis_nm_failure_event_causes {
 	/* Critical causes */
-	NM_EVT_CAUSE_CRIT_SW_FATAL 			= 0x3000,
+	NM_EVT_CAUSE_CRIT_SW_FATAL 		= 0x3000,
 	NM_EVT_CAUSE_CRIT_DSP_FATAL 		= 0x3001,
 	NM_EVT_CAUSE_CRIT_PROC_STOP 		= 0x3006,
 	NM_EVT_CAUSE_CRIT_RTP_CREATE_FAIL	= 0x332a,
@@ -56,18 +78,21 @@
 	NM_EVT_CAUSE_CRIT_RTP_NO_SOCK		= 0x332c,
 	NM_EVT_CAUSE_CRIT_BAD_CALIB_PATH	= 0x3401,
 	NM_EVT_CAUSE_CRIT_OPEN_CALIB_FAIL 	= 0x3403,
-	NM_EVT_CAUSE_CRIT_VERIFY_CALIB_FAIL = 0x3404,
+	NM_EVT_CAUSE_CRIT_VERIFY_CALIB_FAIL 	= 0x3404,
 	/* Major causes */
 	NM_EVT_CAUSE_MAJ_UKWN_PCU_MSG		= 0x3002,
 	NM_EVT_CAUSE_MAJ_UKWN_DL_MSG		= 0x3003,
 	NM_EVT_CAUSE_MAJ_UKWN_UL_MSG		= 0x3004,
 	NM_EVT_CAUSE_MAJ_UKWN_MPH_MSG		= 0x3005,
-	NM_EVT_CAUSE_MAJ_RSL_FAIL			= 0x3309,
+	NM_EVT_CAUSE_MAJ_UKWN_MEAS_START_MSG	= 0x3007,
+	NM_EVT_CAUSE_MAJ_UKWN_MEAS_REQ_MSG	= 0x3008,
+	NM_EVT_CAUSE_MAJ_UKWN_MEAS_STOP_MSG	= 0x3009,
+	NM_EVT_CAUSE_MAJ_RSL_FAIL		= 0x3309,
 	NM_EVT_CAUSE_MAJ_DEACT_RF_FAIL 		= 0x330a,
 	/* Minor causes */
 	NM_EVT_CAUSE_MIN_PAG_TAB_FULL		= 0x3402,
 	/* Warning causes */
-	NM_EVT_CAUSE_WARN_SW_WARN			= 0x0001,
+	NM_EVT_CAUSE_WARN_SW_WARN		= 0x0001,
 
 };
 
@@ -114,4 +139,10 @@
 /* Initialize failure report signalling */
 int oml_failure_report_init(void *handler);
 
+/* NM measurement related messages */
+int oml_tx_nm_start_meas_ack_nack(struct gsm_abis_mo *mo, uint8_t meas_id, uint8_t nack_cause);
+int oml_tx_nm_meas_res_req_nack(struct gsm_abis_mo *mo, uint8_t meas_id, uint8_t nack_cause);
+int oml_tx_nm_meas_res_resp(struct gsm_abis_mo *mo, struct gsm_pcu_if_meas_resp meas_resp);
+int oml_tx_nm_stop_meas_ack_nack(struct gsm_abis_mo *mo, uint8_t meas_id, uint8_t nack_cause);
+
 #endif // _OML_H */
diff --git a/include/osmo-bts/pcu_if.h b/include/osmo-bts/pcu_if.h
index a020c05..298c1dc 100644
--- a/include/osmo-bts/pcu_if.h
+++ b/include/osmo-bts/pcu_if.h
@@ -4,6 +4,7 @@
 #define PCU_SOCK_DEFAULT	"/tmp/pcu_bts"
 
 extern int pcu_direct;
+extern int pcu_start_meas_flags;
 
 int pcu_tx_info_ind(void);
 int pcu_tx_rts_req(struct gsm_bts_trx_ts *ts, uint8_t is_ptcch, uint32_t fn,
@@ -22,4 +23,8 @@
 
 bool pcu_connected(void);
 
+int  pcu_tx_nm_start_meas(struct gsm_bts *bts, uint8_t meas_id, uint8_t ack_flag);
+int  pcu_tx_nm_meas_res_req(struct gsm_bts *bts, uint8_t meas_id);
+int  pcu_tx_nm_stop_meas(struct gsm_bts *bts, uint8_t meas_id);
+
 #endif /* _PCU_IF_H */
diff --git a/include/osmo-bts/pcuif_proto.h b/include/osmo-bts/pcuif_proto.h
index b961229..c79084e 100644
--- a/include/osmo-bts/pcuif_proto.h
+++ b/include/osmo-bts/pcuif_proto.h
@@ -1,5 +1,6 @@
 #ifndef _PCUIF_PROTO_H
 #define _PCUIF_PROTO_H
+#include <osmocom/gsm/protocol/gsm_12_21.h>
 
 #define PCU_IF_VERSION		0x07
 
@@ -16,6 +17,15 @@
 
 /*alarms & performance counters */
 #define PCU_IF_MSG_FAILURE_EVT_IND 	0x61 /* PCU failure event report indication*/
+#define PCU_IF_MSG_START_MEAS_REQ 	0x62 /* PCU start measurement request */
+#define PCU_IF_MSG_START_MEAS_ACK 	0x63 /* PCU start measurement ACK */
+#define PCU_IF_MSG_START_MEAS_NACK 	0x64 /* PCU start measurement NACK */
+#define PCU_IF_MSG_MEAS_RES_REQ 	0x65 /* PCU measurement result request*/
+#define PCU_IF_MSG_MEAS_RES_RESP 	0x66 /* PCU measurement result response*/
+#define PCU_IF_MSG_MEAS_RES_NACK 	0x67 /* PCU measurement result NACK*/
+#define PCU_IF_MSG_STOP_MEAS_REQ 	0x68 /* PCU stop measurement request */
+#define PCU_IF_MSG_STOP_MEAS_ACK 	0x69 /* PCU stop measurement ACK */
+#define PCU_IF_MSG_STOP_MEAS_NACK 	0x6a /* PCU stop measurement NACK */
 
 /* sapi */
 #define PCU_IF_SAPI_RACH	0x01	/* channel request on CCCH */
@@ -42,6 +52,14 @@
 #define PCU_IF_FLAG_MCS7	(1 << 26)
 #define PCU_IF_FLAG_MCS8	(1 << 27)
 #define PCU_IF_FLAG_MCS9	(1 << 28)
+
+/* PCU start measurement flags */
+#define PCU_IF_FLAG_START_MEAS_CCCH	(1 << 0)
+#define PCU_IF_FLAG_START_MEAS_UL_TBF	(1 << 1)
+#define PCU_IF_FLAG_START_MEAS_DL_TBF	(1 << 2)
+#define PCU_IF_FLAG_START_MEAS_TBF_USE	(1 << 3)
+#define PCU_IF_FLAG_START_MEAS_LLC_USE	(1 << 4)
+#define PCU_IF_FLAG_START_MEAS_CS_CHG	(1 << 5)
 
 struct gsm_pcu_if_data {
 	uint8_t		sapi;
@@ -147,6 +165,24 @@
 	char		add_text[100];
 }__attribute__ ((packed));
 
+struct gsm_pcu_if_start_meas_req {
+	uint8_t 	meas_id;	/*measurement ID */
+	uint8_t		nack_cause;
+	uint8_t		spare[2];
+}__attribute__ ((packed));
+
+struct gsm_pcu_if_meas_req {
+	uint8_t 	meas_id;	/*measurement ID */
+	uint8_t		spare[2];
+}__attribute__ ((packed));
+
+struct gsm_pcu_if_meas_resp {
+	uint8_t 	meas_id;	/*measurement ID */
+	uint8_t		nack_cause;	/*NACK cause */
+	uint16_t	len;		/*total result length */
+	uint8_t		data[100];	/*PM counter result must be started from here */
+}__attribute__ ((packed));
+
 struct gsm_pcu_if {
 	/* context based information */
 	uint8_t		msg_type;	/* message type */
@@ -164,6 +200,10 @@
 		struct gsm_pcu_if_time_ind	time_ind;
 		struct gsm_pcu_if_pag_req	pag_req;
 		struct gsm_pcu_if_fail_evt_ind	failure_evt_ind;
+		struct gsm_pcu_if_start_meas_req start_meas_req;
+		struct gsm_pcu_if_start_meas_req stop_meas_req;
+		struct gsm_pcu_if_meas_req meas_req;
+		struct gsm_pcu_if_meas_resp meas_resp;
 	} u;
 } __attribute__ ((packed));
 
diff --git a/src/common/oml.c b/src/common/oml.c
index 13a4799..29cba5a 100644
--- a/src/common/oml.c
+++ b/src/common/oml.c
@@ -94,6 +94,9 @@
 		[NM_ATT_IPACC_SEC_POSSIBLE] =	{ TLV_TYPE_TL16V },
 		[NM_ATT_IPACC_IML_SSL_STATE] =	{ TLV_TYPE_TL16V },
 		[NM_ATT_IPACC_REVOC_DATE] =	{ TLV_TYPE_TL16V },
+		/* GSM 12.21 attributes */
+		[NM_ATT_MEAS_TYPE] = { TLV_TYPE_TV },
+		[NM_ATT_MEAS_RES] = { TLV_TYPE_TV },
 	},
 };
 
@@ -404,6 +407,81 @@
 	}
 
 	return oml_mo_send_msg(mo, nmsg, NM_MT_FAILURE_EVENT_REP);
+}
+
+/* TS 12.21 8.10.2 */
+int oml_tx_nm_meas_res_resp(struct gsm_abis_mo *mo, struct gsm_pcu_if_meas_resp meas_resp)
+{
+	struct msgb *nmsg;
+
+	LOGP(DOML, LOGL_INFO, "%s Tx MEASurement RESult RESPonse\n", gsm_abis_mo_name(mo));
+
+	nmsg = oml_msgb_alloc();
+	if (!nmsg)
+		return -ENOMEM;
+
+	msgb_tv_put(nmsg, NM_ATT_MEAS_TYPE, meas_resp.meas_id);
+	msgb_tl16v_put(nmsg, NM_ATT_MEAS_RES, meas_resp.len, meas_resp.data);
+
+	return oml_mo_send_msg(mo, nmsg, NM_MT_MEAS_RES_RESP);
+}
+
+int oml_tx_nm_start_meas_ack_nack(struct gsm_abis_mo *mo, uint8_t meas_id, uint8_t nack_cause)
+{
+	struct msgb *msg;
+	uint8_t msg_type;
+
+	msg = oml_msgb_alloc();
+	if (!msg)
+		return -ENOMEM;
+
+	if (nack_cause) {
+		msg_type =  NM_MT_IPACC_START_MEAS_NACK;
+		msgb_tv_put(msg, NM_ATT_NACK_CAUSES, nack_cause);
+		msgb_tv_put(msg, NM_ATT_MEAS_TYPE, meas_id);
+	} else {
+		msg_type = NM_MT_IPACC_START_MEAS_ACK;
+		msgb_tv_put(msg, NM_ATT_MEAS_TYPE, meas_id);
+	}
+
+	return oml_mo_send_msg(mo, msg, msg_type);
+}
+
+int oml_tx_nm_stop_meas_ack_nack(struct gsm_abis_mo *mo, uint8_t meas_id, uint8_t nack_cause)
+{
+	struct msgb *msg;
+	uint8_t msg_type;
+
+	msg = oml_msgb_alloc();
+	if (!msg)
+		return -ENOMEM;
+
+	if (nack_cause) {
+		msg_type =  NM_MT_IPACC_STOP_MEAS_NACK;
+		msgb_tv_put(msg, NM_ATT_NACK_CAUSES, nack_cause);
+		msgb_tv_put(msg, NM_ATT_MEAS_TYPE, meas_id);
+	} else {
+		msg_type = NM_MT_IPACC_STOP_MEAS_ACK;
+		msgb_tv_put(msg, NM_ATT_MEAS_TYPE, meas_id);
+	}
+
+	return oml_mo_send_msg(mo, msg, msg_type);
+}
+
+int oml_tx_nm_meas_res_req_nack(struct gsm_abis_mo *mo, uint8_t meas_id, uint8_t nack_cause)
+{
+	struct msgb *msg;
+	uint8_t msg_type;
+
+	msg = oml_msgb_alloc();
+	if (!msg)
+		return -ENOMEM;
+
+	msg_type =  NM_MT_IPACC_MEAS_RES_REQ_NACK;
+	msgb_tv_put(msg, NM_ATT_NACK_CAUSES, nack_cause);
+	msgb_tv_put(msg, NM_ATT_MEAS_TYPE, meas_id);
+
+	return oml_mo_send_msg(mo, msg, msg_type);
 }
 
 /* TS 12.21 9.4.53 */
@@ -941,6 +1019,226 @@
 	return bts_model_chg_adm_state(bts, mo, obj, adm_state);
 }
 
+/* GSM 12.21 section 8.10.1 */
+static int  oml_rx_nm_meas_res_req(struct gsm_bts *bts, struct msgb *msg)
+{
+	struct abis_om_fom_hdr *foh = msgb_l3(msg);
+	struct gsm_abis_mo *mo = &bts->gprs.cell.mo;
+	struct tlv_parsed tp;
+	int rc;
+	uint8_t meas_id;
+
+	LOGP(DOML, LOGL_DEBUG, "%s Rx MEAS RES REQ\n", gsm_abis_mo_name(mo));
+
+	rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
+	if (rc < 0) {
+		LOGP(DOML, LOGL_NOTICE, "New value for Attribute not supported\n");
+		return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
+	}
+
+	if (!TLVP_PRESENT(&tp, NM_ATT_MEAS_TYPE)) {
+		LOGP(DOML, LOGL_NOTICE, "%s NM_ATT_MEAS_TYPE not found\n", gsm_abis_mo_name(mo));
+		return oml_fom_ack_nack(msg, NM_NACK_SPEC_IMPL_NOTSUPP);
+	}
+
+	/* Get measurement ID */
+	meas_id = *TLVP_VAL(&tp, NM_ATT_MEAS_TYPE);
+
+	/* Set start measurement ID flags*/
+	switch(meas_id) {
+	case NM_IPACC_MEAS_TYPE_CCCH:
+		pcu_start_meas_flags |= PCU_IF_FLAG_START_MEAS_CCCH;
+		break;
+	case NM_IPACC_MEAS_TYPE_UL_TBF:
+		pcu_start_meas_flags |= PCU_IF_FLAG_START_MEAS_UL_TBF;
+		break;
+	case NM_IPACC_MEAS_TYPE_DL_TBF:
+		pcu_start_meas_flags |= PCU_IF_FLAG_START_MEAS_DL_TBF;
+		break;
+	case NM_IPACC_MEAS_TYPE_TBF_USE:
+		pcu_start_meas_flags |= PCU_IF_FLAG_START_MEAS_TBF_USE;
+		break;
+	case NM_IPACC_MEAS_TYPE_LLC_USE:
+		pcu_start_meas_flags |= PCU_IF_FLAG_START_MEAS_LLC_USE;
+		break;
+	case NM_IPACC_MEAS_TYPE_CS_CHG:
+		pcu_start_meas_flags |= PCU_IF_FLAG_START_MEAS_CS_CHG;
+		break;
+	default:
+		LOGP(DOML, LOGL_NOTICE, "%s Unsupported NM START MEASurement type received 0x%02x\n", gsm_abis_mo_name(mo), meas_id);
+
+		/*send alarm to indicate PCU link is not ready */
+		alarm_sig_data.mo = mo;
+		alarm_sig_data.spare[0] = meas_id;
+		osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_UNKN_MEAS_REQ_ALARM, &alarm_sig_data);
+
+		/*send START MEAS NACK */
+		return oml_tx_nm_start_meas_ack_nack(mo, meas_id, NM_NACK_NOTH_REPORT_EXIST);
+	}
+
+	/* send request to PCU */
+	rc = pcu_tx_nm_meas_res_req(bts, meas_id);
+	if (rc < 0) {
+		LOGP(DOML, LOGL_NOTICE, "%s PCU socket may not be ready for measurement ID (%d)\n", gsm_abis_mo_name(mo), meas_id);
+
+		/*send alarm to indicate PCU link is not ready */
+		alarm_sig_data.mo = mo;
+		alarm_sig_data.spare[0] = meas_id;
+		osmo_signal_dispatch(SS_NM, S_NM_OML_PCU_CONN_NOT_AVAIL_ALARM, &alarm_sig_data);
+
+		/*send MEAS RES REQ NACK */
+		return oml_tx_nm_meas_res_req_nack(mo, meas_id, NM_NACK_NOTH_REPORT_EXIST);
+	}
+
+	return 0;
+}
+
+/* GSM 12.21 section 8.10.3 */
+static int  oml_rx_nm_start_meas(struct gsm_bts *bts, struct msgb *msg)
+{
+	struct abis_om_fom_hdr *foh = msgb_l3(msg);
+	struct gsm_abis_mo *mo = &bts->gprs.cell.mo;
+	struct tlv_parsed tp;
+	int rc;
+	uint8_t meas_id;
+
+	LOGP(DOML, LOGL_DEBUG, "%s Rx START MEAS\n", gsm_abis_mo_name(mo));
+
+	rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
+	if (rc < 0) {
+		LOGP(DOML, LOGL_NOTICE, "New value for Attribute not supported\n");
+		return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
+	}
+
+	if (!TLVP_PRESENT(&tp, NM_ATT_MEAS_TYPE)) {
+		LOGP(DOML, LOGL_NOTICE, "New value for Attribute not supported\n");
+		return oml_fom_ack_nack(msg, NM_NACK_SPEC_IMPL_NOTSUPP);
+	}
+
+	/* Get measurement ID */
+	meas_id = *TLVP_VAL(&tp, NM_ATT_MEAS_TYPE);
+
+	/* Set start measurement ID flags*/
+	switch(meas_id) {
+	case NM_IPACC_MEAS_TYPE_CCCH:
+		pcu_start_meas_flags |= PCU_IF_FLAG_START_MEAS_CCCH;
+		break;
+	case NM_IPACC_MEAS_TYPE_UL_TBF:
+		pcu_start_meas_flags |= PCU_IF_FLAG_START_MEAS_UL_TBF;
+		break;
+	case NM_IPACC_MEAS_TYPE_DL_TBF:
+		pcu_start_meas_flags |= PCU_IF_FLAG_START_MEAS_DL_TBF;
+		break;
+	case NM_IPACC_MEAS_TYPE_TBF_USE:
+		pcu_start_meas_flags |= PCU_IF_FLAG_START_MEAS_TBF_USE;
+		break;
+	case NM_IPACC_MEAS_TYPE_LLC_USE:
+		pcu_start_meas_flags |= PCU_IF_FLAG_START_MEAS_LLC_USE;
+		break;
+	case NM_IPACC_MEAS_TYPE_CS_CHG:
+		pcu_start_meas_flags |= PCU_IF_FLAG_START_MEAS_CS_CHG;
+		break;
+	default:
+		LOGP(DOML, LOGL_NOTICE, "%s Unsupported NM START MEASurement type received 0x%02x\n", gsm_abis_mo_name(mo), meas_id);
+
+		/*send alarm to indicate PCU link is not ready */
+		alarm_sig_data.mo = mo;
+		alarm_sig_data.spare[0] = meas_id;
+		osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_UNKN_START_MEAS_REQ_ALARM, &alarm_sig_data);
+
+		/*send START MEAS NACK */
+		return oml_tx_nm_start_meas_ack_nack(mo, meas_id, NM_NACK_NOTH_REPORT_EXIST);
+	}
+
+	/* send request to PCU */
+	rc = pcu_tx_nm_start_meas(bts, meas_id, 0);
+	if (rc < 0) {
+		LOGP(DOML, LOGL_NOTICE, "%s PCU socket may not be ready\n", gsm_abis_mo_name(mo));
+		/*send alarm to indicate PCU link is not ready */
+		alarm_sig_data.mo = mo;
+		alarm_sig_data.spare[0] = meas_id;
+		osmo_signal_dispatch(SS_NM, S_NM_OML_PCU_CONN_NOT_AVAIL_ALARM, &alarm_sig_data);
+
+		/*send START MEAS NACK */
+		return oml_tx_nm_start_meas_ack_nack(mo, meas_id, NM_NACK_NOTH_REPORT_EXIST);
+	}
+
+	return 0;
+}
+
+static int  oml_rx_nm_stop_meas(struct gsm_bts *bts, struct msgb *msg)
+{
+	struct abis_om_fom_hdr *foh = msgb_l3(msg);
+	struct gsm_abis_mo *mo = &bts->gprs.cell.mo;
+	struct tlv_parsed tp;
+	int rc;
+	uint8_t meas_id;
+
+	LOGP(DOML, LOGL_DEBUG, "%s Rx STOP MEAS\n", gsm_abis_mo_name(mo));
+
+	rc = oml_tlv_parse(&tp, foh->data, msgb_l3len(msg) - sizeof(*foh));
+	if (rc < 0) {
+		LOGP(DOML, LOGL_NOTICE, "New value for Attribute not supported\n");
+		return oml_fom_ack_nack(msg, NM_NACK_INCORR_STRUCT);
+	}
+
+	if (!TLVP_PRESENT(&tp, NM_ATT_MEAS_TYPE)) {
+		LOGP(DOML, LOGL_NOTICE, "New value for Attribute not supported\n");
+		return oml_fom_ack_nack(msg, NM_NACK_SPEC_IMPL_NOTSUPP);
+	}
+
+	/* Get measurement ID */
+	meas_id = *TLVP_VAL(&tp, NM_ATT_MEAS_TYPE);
+
+	/* Validate measurement ID */
+	switch(meas_id) {
+	case NM_IPACC_MEAS_TYPE_CCCH:
+		pcu_start_meas_flags &= ~PCU_IF_FLAG_START_MEAS_CCCH;
+		break;
+	case NM_IPACC_MEAS_TYPE_UL_TBF:
+		pcu_start_meas_flags &= ~PCU_IF_FLAG_START_MEAS_UL_TBF;
+		break;
+	case NM_IPACC_MEAS_TYPE_DL_TBF:
+		pcu_start_meas_flags &= ~PCU_IF_FLAG_START_MEAS_DL_TBF;
+		break;
+	case NM_IPACC_MEAS_TYPE_TBF_USE:
+		pcu_start_meas_flags &= ~PCU_IF_FLAG_START_MEAS_TBF_USE;
+		break;
+	case NM_IPACC_MEAS_TYPE_LLC_USE:
+		pcu_start_meas_flags &= ~PCU_IF_FLAG_START_MEAS_LLC_USE;
+		break;
+	case NM_IPACC_MEAS_TYPE_CS_CHG:
+		pcu_start_meas_flags &= ~PCU_IF_FLAG_START_MEAS_CS_CHG;
+		break;
+	default:
+		LOGP(DOML, LOGL_NOTICE, "%s Unsupported NM STOP MEASurement type received 0x%02x\n", gsm_abis_mo_name(mo), meas_id);
+
+		/*send alarm to indicate PCU link is not ready */
+		alarm_sig_data.mo = mo;
+		alarm_sig_data.spare[0] = meas_id;
+		osmo_signal_dispatch(SS_NM, S_NM_OML_BTS_UNKN_STOP_MEAS_REQ_ALARM, &alarm_sig_data);
+
+		/*send START MEAS NACK */
+		return oml_tx_nm_start_meas_ack_nack(mo, meas_id, NM_NACK_NOTH_REPORT_EXIST);
+	}
+
+	/* send request to PCU */
+	rc = pcu_tx_nm_stop_meas(bts, meas_id);
+	if (rc < 0) {
+		LOGP(DOML, LOGL_NOTICE, "%s PCU socket may not be ready\n", gsm_abis_mo_name(mo));
+
+		/*send alarm to indicate PCU link is not ready */
+		alarm_sig_data.mo = mo;
+		alarm_sig_data.spare[0] = meas_id;
+		osmo_signal_dispatch(SS_NM, S_NM_OML_PCU_CONN_NOT_AVAIL_ALARM, &alarm_sig_data);
+
+		/*send STOP MEAS NACK */
+		return oml_tx_nm_stop_meas_ack_nack(mo, meas_id, NM_NACK_NOTH_REPORT_EXIST);
+	}
+
+	return 0;
+}
+
 static int down_fom(struct gsm_bts *bts, struct msgb *msg)
 {
 	struct abis_om_fom_hdr *foh = msgb_l3(msg);
@@ -983,6 +1281,15 @@
 		break;
 	case NM_MT_IPACC_SET_ATTR:
 		ret = oml_ipa_set_attr(bts, msg);
+		break;
+	case NM_MT_START_MEAS:
+		ret = oml_rx_nm_start_meas(bts, msg);
+		break;
+	case NM_MT_MEAS_RES_REQ:
+		ret = oml_rx_nm_meas_res_req(bts, msg);
+		break;
+	case NM_MT_STOP_MEAS:
+		ret = oml_rx_nm_stop_meas(bts, msg);
 		break;
 	default:
 		LOGP(DOML, LOGL_INFO, "unknown Formatted O&M msg_type 0x%02x\n",
@@ -1560,6 +1867,43 @@
 				sig_data->event_cause,
 				sig_data->add_text);
 		break;
+
+	case S_NM_OML_BTS_UNKN_START_MEAS_REQ_ALARM:
+		snprintf(log_msg, 100, "Unsupported START MEASurement ID (0x%02x)\n", sig_data->spare[0]);
+		sig_data->add_text = (char*)&log_msg;
+
+		rc = oml_tx_nm_fail_evt_rep(sig_data->mo,
+				NM_EVT_COMM_FAIL,
+				NM_SEVER_MAJOR,
+				NM_PCAUSE_T_MANUF,
+				NM_EVT_CAUSE_MAJ_UKWN_MEAS_START_MSG,
+				sig_data->add_text);
+		break;
+
+	case S_NM_OML_BTS_UNKN_STOP_MEAS_REQ_ALARM:
+		snprintf(log_msg, 100, "Unsupported STOP MEASurement ID (0x%02x)\n", sig_data->spare[0]);
+		sig_data->add_text = (char*)&log_msg;
+
+		rc = oml_tx_nm_fail_evt_rep(sig_data->mo,
+				NM_EVT_COMM_FAIL,
+				NM_SEVER_MAJOR,
+				NM_PCAUSE_T_MANUF,
+				NM_EVT_CAUSE_MAJ_UKWN_MEAS_STOP_MSG,
+				sig_data->add_text);
+		break;
+
+	case S_NM_OML_BTS_UNKN_MEAS_REQ_ALARM:
+		snprintf(log_msg, 100, "Unsupported MEASurement REQuest ID (0x%02x)\n", sig_data->spare[0]);
+		sig_data->add_text = (char*)&log_msg;
+
+		rc = oml_tx_nm_fail_evt_rep(sig_data->mo,
+				NM_EVT_COMM_FAIL,
+				NM_SEVER_MAJOR,
+				NM_PCAUSE_T_MANUF,
+				NM_EVT_CAUSE_MAJ_UKWN_MEAS_REQ_MSG,
+				sig_data->add_text);
+		break;
+
 	default:
 		break;
 	}
diff --git a/src/common/pcu_sock.c b/src/common/pcu_sock.c
index 78c5fe8..8aec856 100644
--- a/src/common/pcu_sock.c
+++ b/src/common/pcu_sock.c
@@ -47,6 +47,7 @@
 
 extern struct gsm_network bts_gsmnet;
 int pcu_direct = 0;
+int pcu_start_meas_flags = 0;
 static int avail_lai = 0, avail_nse = 0, avail_cell = 0, avail_nsvc[2] = {0, 0};
 
 static const char *sapi_string[] = {
@@ -132,7 +133,7 @@
 	struct gsm_bts_gprs_nsvc *nsvc;
 	struct gsm_bts_trx *trx;
 	struct gsm_bts_trx_ts *ts;
-	int i, j, rc;
+	int i, j, rc, meas_id;
 	struct gsm_bts_role_bts *btsb;
 
 	LOGP(DPCU, LOGL_INFO, "Sending info\n");
@@ -251,6 +252,43 @@
 	rc = pcu_sock_send(net, msg);
 	if (rc < 0)
 		return rc;
+	/* send pending start measurement messages to PCU */
+	for(i = 0; i < 32; i++) {
+
+		meas_id = pcu_start_meas_flags & (1 << i);
+		if(!meas_id)
+			continue;
+
+		/* decode start measurement flags */
+		switch (meas_id) {
+		case PCU_IF_FLAG_START_MEAS_CCCH:
+			meas_id = NM_IPACC_MEAS_TYPE_CCCH;
+			break;
+		case PCU_IF_FLAG_START_MEAS_UL_TBF:
+			meas_id = NM_IPACC_MEAS_TYPE_UL_TBF;
+			break;
+		case PCU_IF_FLAG_START_MEAS_DL_TBF:
+			meas_id = NM_IPACC_MEAS_TYPE_DL_TBF;
+			break;
+		case PCU_IF_FLAG_START_MEAS_TBF_USE:
+			meas_id = NM_IPACC_MEAS_TYPE_TBF_USE;
+			break;
+		case PCU_IF_FLAG_START_MEAS_LLC_USE:
+			meas_id = NM_IPACC_MEAS_TYPE_LLC_USE;
+			break;
+		case PCU_IF_FLAG_START_MEAS_CS_CHG:
+			meas_id = NM_IPACC_MEAS_TYPE_CS_CHG;
+			break;
+		default:
+			meas_id = NM_IPACC_MEAS_TYPE_UNKN;
+			break;
+		}
+
+		/* send request to PCU */
+		rc = pcu_tx_nm_start_meas(bts, meas_id, 1);
+		if (rc < 0)
+			return rc;
+	}
 
 #ifdef ENABLE_LC15BTS
 	struct oml_alarm_list *ceased_alarm;
@@ -500,6 +538,65 @@
 	return pcu_sock_send(&bts_gsmnet, msg);
 }
 
+int  pcu_tx_nm_start_meas(struct gsm_bts *bts, uint8_t meas_id, uint8_t ack_flag)
+{
+	struct gsm_pcu_if *pcu_prim;
+	struct gsm_pcu_if_start_meas_req *start_meas_req;
+	struct msgb *msg;
+
+	msg = pcu_msgb_alloc(PCU_IF_MSG_START_MEAS_REQ, bts->nr);
+	if (!msg)
+		return -ENOMEM;
+
+	pcu_prim = (struct gsm_pcu_if *) msg->data;
+	start_meas_req = &pcu_prim->u.start_meas_req;
+	start_meas_req->meas_id = meas_id;
+	start_meas_req->spare[0] = ack_flag;
+
+	LOGP(DPCU, LOGL_INFO, "[BTS->PCU] Sent START MEASurement REQuest: 0x%02x\n", start_meas_req->meas_id);
+
+	return pcu_sock_send(&bts_gsmnet, msg);
+}
+
+int  pcu_tx_nm_stop_meas(struct gsm_bts *bts, uint8_t meas_id)
+{
+	struct gsm_pcu_if *pcu_prim;
+	struct gsm_pcu_if_start_meas_req *stop_meas_req;
+	struct msgb *msg;
+
+	msg = pcu_msgb_alloc(PCU_IF_MSG_STOP_MEAS_REQ, bts->nr);
+	if (!msg)
+		return -ENOMEM;
+
+	pcu_prim = (struct gsm_pcu_if *) msg->data;
+	stop_meas_req = &pcu_prim->u.start_meas_req;
+	stop_meas_req->meas_id = meas_id;
+
+	LOGP(DPCU, LOGL_INFO, "[BTS->PCU] Sent STOP MEASurement REQuest: 0x%02x\n", stop_meas_req->meas_id);
+
+	return pcu_sock_send(&bts_gsmnet, msg);
+}
+
+int  pcu_tx_nm_meas_res_req(struct gsm_bts *bts, uint8_t meas_id)
+{
+	struct gsm_pcu_if *pcu_prim;
+	struct gsm_pcu_if_meas_req *meas_req;
+	struct msgb *msg;
+
+	msg = pcu_msgb_alloc(PCU_IF_MSG_MEAS_RES_REQ, bts->nr);
+	if (!msg)
+		return -ENOMEM;
+
+	pcu_prim = (struct gsm_pcu_if *) msg->data;
+	meas_req = &pcu_prim->u.meas_req;
+	meas_req->meas_id = meas_id;
+
+	LOGP(DPCU, LOGL_INFO, "[BTS->PCU ]Sent MEASurement RESult REQuest: 0x%02x\n", meas_req->meas_id);
+
+	return pcu_sock_send(&bts_gsmnet, msg);
+}
+
+
 static int pcu_rx_data_req(struct gsm_bts *bts, uint8_t msg_type,
 	struct gsm_pcu_if_data *data_req)
 {
@@ -624,6 +721,60 @@
 	return alarm_sig_data.rc;
 }
 
+static int pcu_rx_nm_start_meas_ack_nack(struct gsm_bts *bts, struct gsm_pcu_if_start_meas_req *start_meas, uint8_t nack_cause)
+{
+	int rc;
+
+	/* don't send ACK/NACK to MSS if BTS does not request send ACK/NACK */
+	if (start_meas->spare[0])
+		return 0;
+
+	rc = oml_tx_nm_start_meas_ack_nack(&bts->gprs.cell.mo, start_meas->meas_id, nack_cause);
+	if (rc < 0 )
+		return rc;
+
+	return 0;
+}
+
+static int pcu_rx_nm_stop_meas_ack_nack(struct gsm_bts *bts, struct gsm_pcu_if_start_meas_req *stop_meas, uint8_t nack_cause)
+{
+	int rc;
+
+	rc = oml_tx_nm_stop_meas_ack_nack(&bts->gprs.cell.mo, stop_meas->meas_id, nack_cause);
+	if (rc < 0 )
+		return rc;
+
+	return 0;
+}
+
+static int pcu_rx_nm_meas_res_req_nack(struct gsm_bts *bts, struct gsm_pcu_if_meas_resp *meas_resp, uint8_t nack_cause)
+{
+	int rc;
+
+	rc = oml_tx_nm_meas_res_req_nack(&bts->gprs.cell.mo, meas_resp->meas_id, nack_cause);
+	if (rc < 0 )
+		return rc;
+
+	return 0;
+}
+
+static int pcu_rx_nm_meas_res_resp(struct gsm_bts *bts, struct gsm_pcu_if_meas_resp *meas_resp)
+{
+	struct gsm_pcu_if_meas_resp res_resp;
+	int rc;
+
+	res_resp.meas_id = meas_resp->meas_id;
+	res_resp.len = meas_resp->len;
+	memcpy(res_resp.data, meas_resp->data, meas_resp->len);
+
+	rc = oml_tx_nm_meas_res_resp(&bts->gprs.cell.mo, res_resp);
+	if (rc < 0 )
+		return rc;
+
+	return 0;
+}
+
+
 static int pcu_rx(struct gsm_network *net, uint8_t msg_type,
 	struct gsm_pcu_if *pcu_prim)
 {
@@ -644,6 +795,24 @@
 	case PCU_IF_MSG_FAILURE_EVT_IND:
 		rc = pcu_rx_failure_event_rep(bts, &pcu_prim->u.failure_evt_ind);
 		break;
+	case PCU_IF_MSG_START_MEAS_ACK:
+		rc =  pcu_rx_nm_start_meas_ack_nack(bts, &pcu_prim->u.start_meas_req, 0);
+		break;
+	case PCU_IF_MSG_START_MEAS_NACK:
+		rc =  pcu_rx_nm_start_meas_ack_nack(bts, &pcu_prim->u.start_meas_req, pcu_prim->u.start_meas_req.nack_cause);
+		break;
+	case PCU_IF_MSG_MEAS_RES_NACK:
+		rc =  pcu_rx_nm_meas_res_req_nack(bts, &pcu_prim->u.meas_resp, pcu_prim->u.meas_resp.nack_cause);
+		break;
+	case PCU_IF_MSG_MEAS_RES_RESP:
+		rc = pcu_rx_nm_meas_res_resp(bts, &pcu_prim->u.meas_resp);
+		break;
+	case PCU_IF_MSG_STOP_MEAS_ACK:
+		rc =  pcu_rx_nm_stop_meas_ack_nack(bts, &pcu_prim->u.stop_meas_req, 0);
+		break;
+	case PCU_IF_MSG_STOP_MEAS_NACK:
+		rc =  pcu_rx_nm_stop_meas_ack_nack(bts, &pcu_prim->u.stop_meas_req, pcu_prim->u.stop_meas_req.nack_cause);
+		break;
 	default:
 		LOGP(DPCU, LOGL_ERROR, "Received unknwon PCU msg type %d\n",
 			msg_type);

-- 
To view, visit https://gerrit.osmocom.org/811
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I352600f964e6c161b9259c62f2e0a0f39f0f60d9
Gerrit-PatchSet: 1
Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Owner: Minh-Quang Nguyen <minh-quang.nguyen at nutaq.com>



More information about the gerrit-log mailing list