aboutsummaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/oml.c344
-rw-r--r--src/common/pcu_sock.c171
2 files changed, 514 insertions, 1 deletions
diff --git a/src/common/oml.c b/src/common/oml.c
index 13a47999..29cba5ae 100644
--- a/src/common/oml.c
+++ b/src/common/oml.c
@@ -94,6 +94,9 @@ static struct tlv_definition abis_nm_att_tlvdef_ipa = {
[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 },
},
};
@@ -406,6 +409,81 @@ int oml_tx_nm_fail_evt_rep(struct gsm_abis_mo *mo, uint8_t event_type, uint8_t e
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 */
enum abis_nm_t200_idx {
T200_SDCCH = 0,
@@ -941,6 +1019,226 @@ static int oml_rx_chg_adm_state(struct gsm_bts *bts, struct msgb *msg)
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);
@@ -984,6 +1282,15 @@ static int down_fom(struct gsm_bts *bts, struct msgb *msg)
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",
foh->msg_type);
@@ -1560,6 +1867,43 @@ static int handle_oml_fail_evt_rep_sig(unsigned int subsys, unsigned int signal,
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 78c5fe8c..8aec856d 100644
--- a/src/common/pcu_sock.c
+++ b/src/common/pcu_sock.c
@@ -47,6 +47,7 @@ uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx);
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 @@ int pcu_tx_info_ind(void)
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 @@ int pcu_tx_info_ind(void)
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 @@ int pcu_tx_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len)
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 @@ static int pcu_rx_failure_event_rep(struct gsm_bts *bts, struct gsm_pcu_if_fail_
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 @@ static int pcu_rx(struct gsm_network *net, uint8_t msg_type,
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);