From a164b6715c62d060b311cccc1130979018fd1eba Mon Sep 17 00:00:00 2001 From: Minh-Quang Nguyen Date: Fri, 2 Sep 2016 11:09:30 -0400 Subject: LC15: Implementation of TS 12.21 measurement related messages to measure PCU KPI Change-Id: I352600f964e6c161b9259c62f2e0a0f39f0f60d9 --- src/common/oml.c | 344 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/common/pcu_sock.c | 171 ++++++++++++++++++++++++- 2 files changed, 514 insertions(+), 1 deletion(-) (limited to 'src') 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); -- cgit v1.2.3