From: lal.harshita Date: Wed, 10 May 2023 08:59:21 +0000 (+0530) Subject: [Epic-ID: ODUHIGH-463] Rebase to master branch change-id Ifb6eb6444edc7f9b0385ea0f11a... X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=f53bec84caa6355f0e1d1938d75d5842db45022b;p=o-du%2Fl2.git [Epic-ID: ODUHIGH-463] Rebase to master branch change-id Ifb6eb6444edc7f9b0385ea0f11a8baae4e74a297 Change-Id: Ie450380a8955a571943bc1ff016c0a4b34737f6d Signed-off-by: lal.harshita --- diff --git a/src/cm/common_def.c b/src/cm/common_def.c index 11d80b2d7..4b974c3b5 100644 --- a/src/cm/common_def.c +++ b/src/cm/common_def.c @@ -484,7 +484,7 @@ uint32_t convertFreqToArfcn(uint32_t freq) for(indexTable = 0; indexTable < 3; indexTable++) { - if(freq < arfcnFreqTable[indexTable][0]) + if(freq < (arfcnFreqTable[indexTable][0] * 1000)) { arfcn = arfcnFreqTable[indexTable][3] + ((freq - (arfcnFreqTable[indexTable][2] * 1000)) / (arfcnFreqTable[indexTable][1])); return (arfcn); diff --git a/src/cm/common_def.h b/src/cm/common_def.h index 1bdb4a118..c58d28afb 100644 --- a/src/cm/common_def.h +++ b/src/cm/common_def.h @@ -145,6 +145,7 @@ #define ODU_PRINT_MSG SPrntMsg #define ODU_REM_PRE_MSG SRemPreMsg #define ODU_REM_PRE_MSG_MULT SRemPreMsgMult +#define ODU_REM_POST_MSG_MULT SRemPstMsgMult #define ODU_REG_TMR_MT SRegTmrMt #define ODU_SEGMENT_MSG SSegMsg #define ODU_CAT_MSG SCatMsg diff --git a/src/cu_stub/cu_f1ap_msg_hdl.c b/src/cu_stub/cu_f1ap_msg_hdl.c index 601637b33..573c3f024 100644 --- a/src/cu_stub/cu_f1ap_msg_hdl.c +++ b/src/cu_stub/cu_f1ap_msg_hdl.c @@ -2566,9 +2566,9 @@ uint8_t BuildQOSInfo(QosInfo *qosInfo, QoSFlowLevelQoSParameters_t *drbQos, uint return RFAILED; } - if(hoInProgress) + if(hoInProgress == Inter_DU_HO) drbQos->qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI = qosInfo->nonDynFiveQI ; - else + else if(hoInProgress == false || hoInProgress == Xn_Based_Inter_CU_HO) { /*FiveQI*/ if(actionType == ProtocolIE_ID_id_DRBs_ToBeModified_Item) @@ -2607,7 +2607,7 @@ uint8_t BuildQOSInfo(QosInfo *qosInfo, QoSFlowLevelQoSParameters_t *drbQos, uint drbQos->nGRANallocationRetentionPriority.pre_emptionCapability = qosInfo->preemptionCapability; drbQos->nGRANallocationRetentionPriority.pre_emptionVulnerability = qosInfo->preemptionVulnerability; } - else + else if((hoInProgress == false) || (hoInProgress == Xn_Based_Inter_CU_HO)) { drbQos->nGRANallocationRetentionPriority.priorityLevel = PriorityLevel_lowest; drbQos->nGRANallocationRetentionPriority.pre_emptionCapability = Pre_emptionCapability_may_trigger_pre_emption; @@ -2693,6 +2693,12 @@ uint8_t BuildQOSInfo(QosInfo *qosInfo, QoSFlowLevelQoSParameters_t *drbQos, uint uint8_t BuildSNSSAI(DrbInfo *drbInfo, SNSSAI_t *snssai, Snssai *snssaiToCopy, bool hoInProgress) { /*SNSSAI*/ + /* In case of non-HO UE context creation and Xn Based HO, DRB's SNSSAI + * configuration is not known beforehand. In these 2 case, the following + * condition will hit */ + if(!hoInProgress || (hoInProgress == Xn_Based_Inter_CU_HO)) + drbInfo->snssai = snssaiToCopy; + /*ssT*/ snssai->sST.size = sizeof(uint8_t); CU_ALLOC(snssai->sST.buf, snssai->sST.size); @@ -2700,10 +2706,7 @@ uint8_t BuildSNSSAI(DrbInfo *drbInfo, SNSSAI_t *snssai, Snssai *snssaiToCopy, bo { return RFAILED; } - if(!hoInProgress) - memcpy(snssai->sST.buf, &snssaiToCopy->sst, snssai->sST.size); - else - memcpy(snssai->sST.buf, &drbInfo->snssai->sst, snssai->sST.size); + memcpy(snssai->sST.buf, &drbInfo->snssai->sst, snssai->sST.size); /*sD*/ CU_ALLOC(snssai->sD, sizeof(OCTET_STRING_t)); @@ -2717,13 +2720,8 @@ uint8_t BuildSNSSAI(DrbInfo *drbInfo, SNSSAI_t *snssai, Snssai *snssaiToCopy, bo { return RFAILED; } - if(!hoInProgress) - memcpy(snssai->sD->buf, snssaiToCopy->sd, snssai->sD->size); - else - memcpy(snssai->sD->buf, drbInfo->snssai->sd, snssai->sD->size); + memcpy(snssai->sD->buf, drbInfo->snssai->sd, snssai->sD->size); - if(!hoInProgress) - drbInfo->snssai = snssaiToCopy; return ROK; }/*End of BuildSNSSAI*/ @@ -2748,10 +2746,14 @@ uint8_t BuildFlowsMap(DrbInfo *drbInfo, Flows_Mapped_To_DRB_List_t *flowMap , ui uint8_t ret = ROK, idx = 0, flowCnt = 0, flowIdx = 0; FlowsMapped *qosFlow; - if(!hoInProgress) + /* In case of non-HO UE context creation and Xn Based HO, DRB's SNSSAI + * configuration is not known beforehand. In these 2 case, the following + * condition will hit */ + if(!hoInProgress || (hoInProgress == Xn_Based_Inter_CU_HO)) flowCnt = 1; else flowCnt = drbInfo->numFlowMap; + flowMap->list.count = flowCnt; flowMap->list.size = flowCnt * sizeof(Flows_Mapped_To_DRB_Item_t *); CU_ALLOC(flowMap->list.array,flowMap->list.size); @@ -2769,7 +2771,7 @@ uint8_t BuildFlowsMap(DrbInfo *drbInfo, Flows_Mapped_To_DRB_List_t *flowMap , ui return RFAILED; } - if(!hoInProgress) + if(!hoInProgress || (hoInProgress == Xn_Based_Inter_CU_HO)) { flowMap->list.array[idx]->qoSFlowIdentifier = 0; if(actionType == ProtocolIE_ID_id_DRBs_ToBeModified_Item) @@ -2803,7 +2805,7 @@ uint8_t BuildFlowsMap(DrbInfo *drbInfo, Flows_Mapped_To_DRB_List_t *flowMap , ui return RFAILED; } - if((!hoInProgress) && (actionType != ProtocolIE_ID_id_DRBs_ToBeModified_Item)) + if(((!hoInProgress) && (actionType != ProtocolIE_ID_id_DRBs_ToBeModified_Item)) || (hoInProgress == Xn_Based_Inter_CU_HO)) drbInfo->numFlowMap++; } return ROK; @@ -2866,7 +2868,7 @@ uint8_t BuildULTnlInfo(uint8_t duId, TnlInfo *ulUpTnlInfo, ULUPTNLInformation_To return RFAILED; } - if(!hoInProgress) + if((!hoInProgress) || (hoInProgress == Xn_Based_Inter_CU_HO)) { /* NOTE: Below IP address must be changed if running on different IP configuration */ ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->transportLayerAddress.buf[0] = 192; @@ -2899,7 +2901,7 @@ uint8_t BuildULTnlInfo(uint8_t duId, TnlInfo *ulUpTnlInfo, ULUPTNLInformation_To return RFAILED; } - if(!hoInProgress) + if((!hoInProgress) || (hoInProgress == Xn_Based_Inter_CU_HO)) { ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[0] = 0; ulInfo->list.array[idx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[1] = 0; @@ -3000,7 +3002,7 @@ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet choice_extension->value.choice.DRB_Information.dRB_QoS, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, PDU_SESSION_ID_1, FALSE); else BuildQOSInforet = BuildQOSInfo(&ueCb->drbList[idx].qos, &drbSetItem->qoSInformation.choice.\ - choice_extension->value.choice.DRB_Information.dRB_QoS, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, PDU_SESSION_ID_1, TRUE); + choice_extension->value.choice.DRB_Information.dRB_QoS, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, PDU_SESSION_ID_1, ueCb->hoInfo.HOType); if(BuildQOSInforet != ROK) { DU_LOG("\nERROR --> F1AP : Failed to build QOS Info in BuildDRBSetup"); @@ -3014,7 +3016,7 @@ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet choice_extension->value.choice.DRB_Information.sNSSAI, cuCb.snssaiList[snssaiIdx], FALSE); else BuildSNSSAIret = BuildSNSSAI(&ueCb->drbList[idx], &drbSetItem->qoSInformation.choice.\ - choice_extension->value.choice.DRB_Information.sNSSAI, NULLP, TRUE); + choice_extension->value.choice.DRB_Information.sNSSAI, cuCb.snssaiList[snssaiIdx], ueCb->hoInfo.HOType); if(BuildSNSSAIret != ROK) { DU_LOG("\nERROR --> F1AP : Failed to build SNSSAI Info in BuildDRBSetup"); @@ -3027,7 +3029,7 @@ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet value.choice.DRB_Information.flows_Mapped_To_DRB_List, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, FALSE); else BuildFlowsMapret = BuildFlowsMap(&ueCb->drbList[idx], &drbSetItem->qoSInformation.choice.choice_extension->\ - value.choice.DRB_Information.flows_Mapped_To_DRB_List, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, TRUE); + value.choice.DRB_Information.flows_Mapped_To_DRB_List, ProtocolIE_ID_id_DRBs_ToBeSetup_Item, ueCb->hoInfo.HOType); if(BuildFlowsMapret != ROK) { DU_LOG("\nERROR --> F1AP : Failed to build Flow Map Info in BuildDRBSetup"); @@ -3040,7 +3042,7 @@ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet FALSE); else BuildULTnlInforet = BuildULTnlInfo(duId, &ueCb->drbList[idx].ulUpTnlInfo, &drbSetItem->uLUPTNLInformation_ToBeSetup_List,\ - TRUE); + ueCb->hoInfo.HOType); if(BuildULTnlInforet != ROK) { DU_LOG("\nERROR --> F1AP : Failed to build tunnel Info in BuildDRBSetup"); @@ -3048,7 +3050,7 @@ uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet } /*RLCMode*/ - if(ueCb->state != UE_HANDOVER_IN_PROGRESS) + if((ueCb->state != UE_HANDOVER_IN_PROGRESS) || (ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO)) { drbSetItem->rLCMode = RLCMode_rlc_um_bidirectional; ueCb->drbList[ueCb->numDrb].rlcMode = drbSetItem->rLCMode; @@ -9228,6 +9230,7 @@ uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb) uint8_t elementCnt; uint8_t idx, idx1, bufLen, duIdx; uint32_t spCellId; + uint32_t targetDuId; DuDb *targetDuDb = NULLP; F1AP_PDU_t *f1apMsg = NULLP; UEContextSetupRequest_t *ueSetReq = NULLP; @@ -9313,16 +9316,23 @@ uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb) ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_SpCell_ID; ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_reject; ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_NRCGI; + + /* Spec 38.473 Sec 9.2.2.1 : For handover case, this IE shall be considered as target cell. */ if(ueCb->state == UE_HANDOVER_IN_PROGRESS) { - /* Spec 38.473 Sec 9.2.2.1 : For handover case, this IE shall be considered as target cell. */ - SEARCH_DU_DB(duIdx, ueCb->hoInfo.targetId, targetDuDb); + if(ueCb->hoInfo.HOType == Inter_DU_HO) + targetDuId = ueCb->hoInfo.tgtNodeId; + else + targetDuId = duId; + + SEARCH_DU_DB(duIdx, targetDuId, targetDuDb); /* Since we are supporting only one cell per DU, accessing 0th index to * get target cell info */ spCellId = targetDuDb->cellCb[0].nrCellId; } else spCellId = ueCb->cellCb->nrCellId; + Nrcgiret = BuildNrcgi(&ueSetReq->protocolIEs.list.array[idx]->value.choice.NRCGI, spCellId); if(Nrcgiret != ROK) { @@ -9618,7 +9628,7 @@ uint8_t procDrbSetupList(uint32_t duId, CuUeCb *ueCb, DRBs_Setup_List_t *drbSetu * RFAILED - failure * * ****************************************************************/ -uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) +uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg, char *recvBuf, MsgLen recvBufLen) { uint8_t duIdx = 0, idx = 0, ueIdx = 0, rrcMsgType=0; uint8_t duUeF1apId = 0, cuUeF1apId = 0; @@ -9650,11 +9660,24 @@ uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) { /* Creating UE context in target DU */ memset(ueCb, 0, sizeof(CuUeCb)); - ueCb->cellCb = &duDb->cellCb[0]; - ueCb->gnbDuUeF1apId = duUeF1apId; - ueCb->gnbCuUeF1apId = cuUeF1apId; - ueCb->state = UE_HANDOVER_IN_PROGRESS; - ueCb->hoInfo.targetId = duId; + + /* Check if UE is under Inter-CU handover */ + if(duDb->tempUeCtxtInHo && (duDb->tempUeCtxtInHo->gnbCuUeF1apId == cuUeF1apId)) + { + memcpy(ueCb, duDb->tempUeCtxtInHo, sizeof(CuUeCb)); + ueCb->gnbDuUeF1apId = duUeF1apId; + CU_FREE(duDb->tempUeCtxtInHo, sizeof(CuUeCb)); + } + else + { + /* In case of Inter DU Handover */ + ueCb->cellCb = &duDb->cellCb[0]; + ueCb->gnbDuUeF1apId = duUeF1apId; + ueCb->gnbCuUeF1apId = cuUeF1apId; + ueCb->state = UE_HANDOVER_IN_PROGRESS; + ueCb->hoInfo.HOType = Inter_DU_HO; + ueCb->hoInfo.tgtNodeId = duId; + } (duDb->numUe)++; ueCb->cellCb->ueCb[ueCb->cellCb->numUe] = ueCb; @@ -9689,65 +9712,73 @@ uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) } } - /* If the UE is in handover, UE context modification request is to be sent to - * source DU once UE context setup response is received from target DU */ - if(ueCb->state == UE_HANDOVER_IN_PROGRESS) + if(ueCb->state != UE_HANDOVER_IN_PROGRESS) { - DuDb *srcDuDb = NULLP; - CuUeCb *ueCbInSrcDu = NULLP; + ueCb->f1apMsgDb.dlRrcMsgCount++; + rrcMsgType = setDlRRCMsgType(ueCb); - /* Since Source DU Id and DU UE F1AP ID assigned to UE by source DU is not known here, we - * need to find Source DU and UE CB in source DU using CU UE F1AP ID */ - for(duIdx=0; duIdx < cuCb.numDu; duIdx++) + DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC reconfiguration"); + if(BuildAndSendDLRRCMessageTransfer(duId, ueCb, SRB1, rrcMsgType) != ROK) + { + DU_LOG("\nINFO --> F1AP: Failed to build and send DL RRC MSG for RRC reconfiguration"); + return RFAILED; + } + } + else + { + if(ueCb->hoInfo.HOType == Inter_DU_HO) { - /* UE context setup response is received from target DU. Search all - * DUs to find source DU except this target DU Id.*/ - if(cuCb.duInfo[duIdx].duId != duId) + /* If the UE is in Inter-DU handover, UE context modification request is to be sent to + * source DU once UE context setup response is received from target DU */ + + DuDb *srcDuDb = NULLP; + CuUeCb *ueCbInSrcDu = NULLP; + + /* Since Source DU Id and DU UE F1AP ID assigned to UE by source DU is not known here, we + * need to find Source DU and UE CB in source DU using CU UE F1AP ID */ + for(duIdx=0; duIdx < cuCb.numDu; duIdx++) { - for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++) + /* UE context setup response is received from target DU. Search all + * DUs to find source DU except this target DU Id.*/ + if(cuCb.duInfo[duIdx].duId != duId) { - /* Check following: - * 1. CU UE F1AP ID in srcDU->ueCb should be same as cuUeF1apId - * received in UE context setup response since CU UE F1AP ID does not - * change for UE in handover. - * 2. srcDU->UeCb->uestate should be UE_HANDOVER_IN_PROGRESS - */ - if((cuCb.duInfo[duIdx].ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId) && - (cuCb.duInfo[duIdx].ueCb[ueIdx].state == UE_HANDOVER_IN_PROGRESS)) + for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++) { - srcDuDb = &cuCb.duInfo[duIdx]; - ueCbInSrcDu = &cuCb.duInfo[duIdx].ueCb[ueIdx]; + /* Check following: + * 1. CU UE F1AP ID in srcDU->ueCb should be same as cuUeF1apId + * received in UE context setup response since CU UE F1AP ID does not + * change for UE in handover. + * 2. srcDU->UeCb->uestate should be UE_HANDOVER_IN_PROGRESS + */ + if((cuCb.duInfo[duIdx].ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId) && + (cuCb.duInfo[duIdx].ueCb[ueIdx].state == UE_HANDOVER_IN_PROGRESS)) + { + srcDuDb = &cuCb.duInfo[duIdx]; + ueCbInSrcDu = &cuCb.duInfo[duIdx].ueCb[ueIdx]; - /* Store source DU info in the new UE context created in - * tareget DU */ - ueCb->hoInfo.sourceId = srcDuDb->duId; + /* Store source DU info in the new UE context created in + * tareget DU */ + ueCb->hoInfo.srcNodeId = srcDuDb->duId; - /* Copy the received container to UeCb */ - memcpy(&ueCbInSrcDu->f1apMsgDb.duToCuContainer, duToCuRrcContainer, sizeof(OCTET_STRING_t)); + /* Copy the received container to UeCb */ + memcpy(&ueCbInSrcDu->f1apMsgDb.duToCuContainer, duToCuRrcContainer, sizeof(OCTET_STRING_t)); - if(BuildAndSendUeContextModificationReq(srcDuDb->duId, ueCbInSrcDu, STOP_DATA_TX) != ROK) - { - DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextModificationReq()"); - return RFAILED; + if(BuildAndSendUeContextModificationReq(srcDuDb->duId, ueCbInSrcDu, STOP_DATA_TX) != ROK) + { + DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextModificationReq()"); + return RFAILED; + } + break; } - break; } } + if(srcDuDb && ueCbInSrcDu) + break; } - if(srcDuDb && ueCbInSrcDu) - break; } - } - else - { - ueCb->f1apMsgDb.dlRrcMsgCount++; - rrcMsgType = setDlRRCMsgType(ueCb); - - DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC reconfiguration"); - if(BuildAndSendDLRRCMessageTransfer(duId, ueCb, SRB1, rrcMsgType) != ROK) + else if(ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO) { - DU_LOG("\nINFO --> F1AP: Failed to build and send DL RRC MSG for RRC reconfiguration"); - return RFAILED; + BuildAndSendHOReqAck(ueCb, duToCuRrcContainer->buf, duToCuRrcContainer->size); } } @@ -9815,29 +9846,36 @@ uint8_t procUlRrcMsg(uint32_t duId, F1AP_PDU_t *f1apMsg) if(duDb->ueCb[duUeF1apId-1].state == UE_HANDOVER_IN_PROGRESS) { - uint8_t ueIdx = 0; - uint8_t srcDuId = duDb->ueCb[duUeF1apId-1].hoInfo.sourceId; - DuDb *srcDuDb = NULLP; - - /* In target DU DB, mark UE as active and delete HO info */ - duDb->ueCb[duUeF1apId-1].state = UE_ACTIVE; - memset(&duDb->ueCb[duUeF1apId-1].hoInfo, 0, sizeof(HandoverInfo)); - - /* Release UE context in source DU because the UE is now - * attached to target DU */ - SEARCH_DU_DB(duIdx, srcDuId, srcDuDb); - for(ueIdx = 0; ueIdx < srcDuDb->numUe; ueIdx++) + if(duDb->ueCb[duUeF1apId-1].hoInfo.HOType == Inter_DU_HO) { - if(srcDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId) + uint8_t ueIdx = 0; + uint8_t srcDuId = duDb->ueCb[duUeF1apId-1].hoInfo.srcNodeId; + DuDb *srcDuDb = NULLP; + + /* Release UE context in source DU because the UE is now + * attached to target DU */ + SEARCH_DU_DB(duIdx, srcDuId, srcDuDb); + for(ueIdx = 0; ueIdx < srcDuDb->numUe; ueIdx++) { - ret = BuildAndSendUeContextReleaseCommand(srcDuId, srcDuDb->ueCb[ueIdx].gnbCuUeF1apId, srcDuDb->ueCb[ueIdx].gnbDuUeF1apId); - if(ret != ROK) + if(srcDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId) { - DU_LOG("\nINFO --> F1AP: Failed to build and send UE context release command to source DU Id [%d]", srcDuId); + ret = BuildAndSendUeContextReleaseCommand(srcDuId, srcDuDb->ueCb[ueIdx].gnbCuUeF1apId, srcDuDb->ueCb[ueIdx].gnbDuUeF1apId); + if(ret != ROK) + { + DU_LOG("\nINFO --> F1AP: Failed to build and send UE context release command to source DU Id [%d]", srcDuId); + } + break; } - break; } } + else + { + BuildAndSendUeContextRelease(&duDb->ueCb[duUeF1apId-1]); + } + + /* In target DU DB, mark UE as active and delete HO info */ + duDb->ueCb[duUeF1apId-1].state = UE_ACTIVE; + memset(&duDb->ueCb[duUeF1apId-1].hoInfo, 0, sizeof(HandoverInfo)); return ret; } break; @@ -11806,17 +11844,17 @@ uint8_t procDrbSetupModList(uint32_t duId, CuUeCb *ueCb, DRBs_SetupMod_List_t *d if(ueCb->state != UE_HANDOVER_IN_PROGRESS) { - /* extracting teId */ - teId = extractTeId(&drbItemIe->value.choice.DRBs_SetupMod_Item.dLUPTNLInformation_ToBeSetup_List); - if(teId > 0) - { - if(addDrbTunnels(duId, teId)== ROK) - { - DU_LOG("\nDEBUG --> EGTP: Tunnel Added for TeId %d", teId); - } - } - else - return RFAILED; + /* extracting teId */ + teId = extractTeId(&drbItemIe->value.choice.DRBs_SetupMod_Item.dLUPTNLInformation_ToBeSetup_List); + if(teId > 0) + { + if(addDrbTunnels(duId, teId)== ROK) + { + DU_LOG("\nDEBUG --> EGTP: Tunnel Added for TeId %d", teId); + } + } + else + return RFAILED; } } } @@ -11908,6 +11946,10 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg, ch SEARCH_DU_DB(duIdx, duId, duDb); ueCtxtModRsp = &f1apMsg->choice.successfulOutcome->value.choice.UEContextModificationResponse; + + /* In case of Inter-CU Handover request received from peer CU */ + if(duDb->tempUeCtxtInHo) + ueCb = duDb->tempUeCtxtInHo; for(idx=0; idx < ueCtxtModRsp->protocolIEs.list.count; idx++) { @@ -11915,17 +11957,34 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg, ch { case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: { - cuUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_CU_UE_F1AP_ID; + if(ueCb == NULLP) + { + cuUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_CU_UE_F1AP_ID; + } + else + { + /* In case of Inter-CU Handover request received from peer CU */ + cuUeF1apId = ueCb->gnbCuUeF1apId; + } break; } case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: { - duUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_DU_UE_F1AP_ID; - ueCb = &duDb->ueCb[duUeF1apId-1]; - - if((ueCb->state == UE_HANDOVER_IN_PROGRESS) && (ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO)) + if(!ueCb) { - BuildAndSendHOReq(ueCb, HO_REQ, recvBuf, recvBufLen); + duUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_DU_UE_F1AP_ID; + ueCb = &duDb->ueCb[duUeF1apId-1]; + + /* In case UE context modification response is received at source GNB CU from source GNB DU + * for a UE in handover, send HO request to target GNB only if not sent already. + * If HO Req is already sent to target GNB, and an HO Req Ack is received, then + * ueCb->hoInfo.cuUeF1apIdTgt will be non-zero + */ + if((ueCb->state == UE_HANDOVER_IN_PROGRESS) && (ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO) && \ + (ueCb->hoInfo.cuUeF1apIdTgt == 0)) + { + BuildAndSendHOReq(ueCb, recvBuf, recvBufLen); + } } break; } @@ -11965,41 +12024,48 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg, ch * UE context setup request to target DU */ if(ueCb->state == UE_HANDOVER_IN_PROGRESS) { + uint8_t ueIdx = 0; + uint8_t tgtDuId = 0; + DuDb *tgtDuDb = NULLP; + CuUeCb *ueCbInTgtDu = NULLP; + if(ueCb->hoInfo.HOType == Inter_DU_HO) { - uint8_t ueIdx = 0; - DuDb *tgtDuDb = NULLP; - CuUeCb *ueCbInTgtDu = NULLP; + tgtDuId = ueCb->hoInfo.tgtNodeId; + } + else if (ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO) + { + tgtDuId = duId; + } - SEARCH_DU_DB(duIdx, ueCb->hoInfo.targetId, tgtDuDb); - if(tgtDuDb) + SEARCH_DU_DB(duIdx, tgtDuId, tgtDuDb); + if(tgtDuDb) + { + /* Since DU UE F1AP ID assigned by target DU to this UE in handover is + * not known here, using CU UE F1AP ID to search for UE Cb in target DU + * DB */ + for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++) { - /* Since DU UE F1AP ID assigned by target DU to this UE in handover is - * not known here, using CU UE F1AP ID to search for UE Cb in target DU - * DB */ - for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++) + if(tgtDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId) { - if(tgtDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId) - { - ueCbInTgtDu = &tgtDuDb->ueCb[ueIdx]; - break; - } + ueCbInTgtDu = &tgtDuDb->ueCb[ueIdx]; + break; } + } - /* If UE context is not found in Target DU DU, send UE context setup - * request */ - if(ueCbInTgtDu == NULLP) + /* If UE context is not found in Target DU, send UE context setup + * request */ + if(ueCbInTgtDu == NULLP) + { + if((BuildAndSendUeContextSetupReq(tgtDuId, ueCb)) != ROK) { - if((BuildAndSendUeContextSetupReq(ueCb->hoInfo.targetId, ueCb)) != ROK) - { - DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextSetupReq"); - return RFAILED; - } + DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextSetupReq"); + return RFAILED; } } } } - + #ifdef START_DL_UL_DATA startDlData(); #endif @@ -12546,7 +12612,7 @@ uint8_t BuildAndSendPagingMsg(uint64_t gsTmsi, uint8_t duId) /******************************************************************* * - * @brief Handles received F1AP message and sends back response + * @brief Decode received character string into F1AP message * * @details * @@ -12554,61 +12620,86 @@ uint8_t BuildAndSendPagingMsg(uint64_t gsTmsi, uint8_t duId) * * Functionality: * - Decodes received F1AP control message - * - Prepares response message, encodes and sends to SCTP * * @params[in] * @return ROK - success * RFAILED - failure * * ****************************************************************/ -void F1APMsgHdlr(uint32_t *duId, Buffer *mBuf) +uint8_t F1APDecodeMsg(F1AP_PDU_t *f1apMsg, Buffer *mBuf, char **recvBuf, MsgLen *recvBufLen) { int i; - char *recvBuf; MsgLen copyCnt; - MsgLen recvBufLen; - F1AP_PDU_t *f1apMsg = NULLP; asn_dec_rval_t rval; /* Decoder return value */ - F1AP_PDU_t f1apasnmsg ; - - DU_LOG("\nINFO --> F1AP : Received F1AP message buffer"); - ODU_PRINT_MSG(mBuf, 0,0); /* Copy mBuf into char array to decode it */ - ODU_GET_MSG_LEN(mBuf, &recvBufLen); - CU_ALLOC(recvBuf, (Size)recvBufLen); - - if(recvBuf == NULLP) + ODU_GET_MSG_LEN(mBuf, recvBufLen); + CU_ALLOC(*recvBuf, (Size)(*recvBufLen)); + if(*recvBuf == NULLP) { DU_LOG("\nERROR --> F1AP : Memory allocation failed"); - return; + return RFAILED; } - if(ODU_COPY_MSG_TO_FIX_BUF(mBuf, 0, recvBufLen, (Data *)recvBuf, ©Cnt) != ROK) + if(ODU_COPY_MSG_TO_FIX_BUF(mBuf, 0, *recvBufLen, (Data *)*recvBuf, ©Cnt) != ROK) { DU_LOG("\nERROR --> F1AP : Failed while copying %d", copyCnt); - return; + return RFAILED; } - DU_LOG("\nDEBUG --> F1AP : Received flat buffer to be decoded : "); - for(i=0; i< recvBufLen; i++) + DU_LOG("\nDEBUG --> F1AP : Received flat buffer to be decoded : \n"); + for(i=0; i< *recvBufLen; i++) { - DU_LOG("%x",recvBuf[i]); + DU_LOG("%x ",(*recvBuf)[i]); } /* Decoding flat buffer into F1AP messsage */ - f1apMsg = &f1apasnmsg; - memset(f1apMsg, 0, sizeof(F1AP_PDU_t)); - - rval = aper_decode(0, &asn_DEF_F1AP_PDU, (void **)&f1apMsg, recvBuf, recvBufLen, 0, 0); - CU_FREE(recvBuf, (Size)recvBufLen); - + rval = aper_decode(0, &asn_DEF_F1AP_PDU, (void **)&f1apMsg, *recvBuf, *recvBufLen, 0, 0); if(rval.code == RC_FAIL || rval.code == RC_WMORE) { DU_LOG("\nERROR --> F1AP : ASN decode failed"); - return; + return RFAILED; } + + /* Printing the decoded F1AP PDU */ DU_LOG("\n"); xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg); + return ROK; +} + +/******************************************************************* + * + * @brief Handles received F1AP message and sends back response + * + * @details + * + * Function : F1APMsgHdlr + * + * Functionality: + * - Decodes received F1AP control message + * - Prepares response message, encodes and sends to SCTP + * + * @params[in] + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +void F1APMsgHdlr(uint32_t *duId, Buffer *mBuf) +{ + char *recvBuf; + MsgLen recvBufLen; + F1AP_PDU_t *f1apMsg = NULLP; + F1AP_PDU_t f1apasnmsg ; + + DU_LOG("\nINFO --> F1AP : Received F1AP message buffer"); + ODU_PRINT_MSG(mBuf, 0,0); + + f1apMsg = &f1apasnmsg; + memset(f1apMsg, 0, sizeof(F1AP_PDU_t)); + if(F1APDecodeMsg(f1apMsg, mBuf, &recvBuf, &recvBufLen) != ROK) + { + DU_LOG("\nERROR --> F1AP : F1AP PDU decode failed"); + return; + } switch(f1apMsg->present) { @@ -12682,7 +12773,7 @@ void F1APMsgHdlr(uint32_t *duId, Buffer *mBuf) case SuccessfulOutcome__value_PR_UEContextSetupResponse: { DU_LOG("\nINFO --> F1AP : UE ContextSetupResponse received"); - procUeContextSetupResponse(*duId, f1apMsg); + procUeContextSetupResponse(*duId, f1apMsg, recvBuf, recvBufLen); break; } case SuccessfulOutcome__value_PR_UEContextModificationResponse: @@ -12713,6 +12804,7 @@ void F1APMsgHdlr(uint32_t *duId, Buffer *mBuf) } }/* End of switch(f1apMsg->present) */ + CU_FREE(recvBuf, (Size)(recvBufLen)); } /* End of F1APMsgHdlr */ /********************************************************************** diff --git a/src/cu_stub/cu_stub.c b/src/cu_stub/cu_stub.c index b817edfc7..6a9c7ddd5 100644 --- a/src/cu_stub/cu_stub.c +++ b/src/cu_stub/cu_stub.c @@ -286,8 +286,8 @@ void initiateInterDuHandover(uint32_t sourceDuId, uint32_t targetDuId, uint32_t { ueCb->state = UE_HANDOVER_IN_PROGRESS; ueCb->hoInfo.HOType = Inter_DU_HO; - ueCb->hoInfo.sourceId = sourceDuId; - ueCb->hoInfo.targetId = targetDuId; + ueCb->hoInfo.srcNodeId = sourceDuId; + ueCb->hoInfo.tgtNodeId = targetDuId; BuildAndSendUeContextModificationReq(sourceDuId, ueCb, QUERY_CONFIG); } @@ -316,13 +316,13 @@ void initiateInterDuHandover(uint32_t sourceDuId, uint32_t targetDuId, uint32_t * RFAILED - failure * * ****************************************************************/ -void initiateInterCuHandover(uint32_t sourceCuId, uint32_t targetCuId, uint32_t cuUeF1apId) +void initiateInterCuHandover(uint32_t targetCuId, uint32_t cellId, uint32_t cuUeF1apId) { uint8_t duIdx, ueIdx; CuUeCb *ueCb = NULLP; - DU_LOG("\nINFO --> CU_STUB: Inter-CU Handover Started for ueId [%d] from CU ID [%d] to CU ID [%d]", \ - cuUeF1apId, sourceCuId, targetCuId); + DU_LOG("\nINFO --> CU_STUB: Inter-CU Handover Started for ueId [%d] to CU ID [%d]", \ + cuUeF1apId, targetCuId); for(duIdx = 0; duIdx < cuCb.numDu; duIdx++) { @@ -343,8 +343,11 @@ void initiateInterCuHandover(uint32_t sourceCuId, uint32_t targetCuId, uint32_t { ueCb->state = UE_HANDOVER_IN_PROGRESS; ueCb->hoInfo.HOType = Xn_Based_Inter_CU_HO; - ueCb->hoInfo.sourceId = sourceCuId; - ueCb->hoInfo.targetId = targetCuId; + ueCb->hoInfo.srcNodeId = cuCb.cuCfgParams.cuId; + ueCb->hoInfo.tgtNodeId = targetCuId; + ueCb->hoInfo.tgtCellId = cellId; + ueCb->hoInfo.cuUeF1apIdSrc = ueCb->gnbCuUeF1apId; + BuildAndSendUeContextModificationReq(cuCb.duInfo[duIdx].duId, ueCb, QUERY_CONFIG); } else @@ -485,32 +488,32 @@ void *cuConsoleHandler(void *args) else if(ch == 'h') { HandoverType hoType; - uint32_t sourceId, targetId, ueId; + uint32_t srcNodeId, tgtNodeId, targetCellId, ueId; DU_LOG("\n\nChoose the type of handover to initiate : \nEnter 1 for Inter-CU Handover over Xn interface\nEnter 2 for Inter-DU Handover\n"); scanf("%d", &hoType); if(hoType == Xn_Based_Inter_CU_HO) { - DU_LOG("\nEnter Source CU ID for Inter-CU Handover : "); - scanf("%d", &sourceId); DU_LOG("\nEnter Target CU ID for Inter-CU Handover : "); - scanf("%d", &targetId); + scanf("%d", &tgtNodeId); + DU_LOG("\nEnter Target Physical Cell ID for Inter-CU Handover : "); + scanf("%d", &targetCellId); DU_LOG("\nEnter CU UE F1AP ID to be handed over : "); scanf("%d", &ueId); - initiateInterCuHandover(sourceId, targetId, ueId); + initiateInterCuHandover(tgtNodeId, targetCellId, ueId); } else if(hoType == Inter_DU_HO) { DU_LOG("\nEnter Source DU ID for Inter-DU Handover : "); - scanf("%d", &sourceId); + scanf("%d", &srcNodeId); DU_LOG("\nEnter Target DU ID for Inter-DU Handover : "); - scanf("%d", &targetId); + scanf("%d", &tgtNodeId); DU_LOG("\nEnter DU UE F1AP ID to be handed over : "); scanf("%d", &ueId); - initiateInterDuHandover(sourceId, targetId, ueId); + initiateInterDuHandover(srcNodeId, tgtNodeId, ueId); } } /* Start Idle mode paging when 'p' is received from console input */ diff --git a/src/cu_stub/cu_stub.h b/src/cu_stub/cu_stub.h index 08cb36b0f..5b764af85 100644 --- a/src/cu_stub/cu_stub.h +++ b/src/cu_stub/cu_stub.h @@ -116,7 +116,9 @@ typedef enum { XN_SETUP_REQ, XN_SETUP_RSP, - HO_REQ + HO_REQ, + HO_REQ_ACK, + UE_CTXT_REL }XnEventType; typedef enum @@ -153,8 +155,11 @@ typedef struct cuCfgParams typedef struct handoverInfo { HandoverType HOType; - uint32_t sourceId; /* If Inter_DU HO, this is Source DU ID. In case of Inter CU HO, this is Source CU ID */ - uint32_t targetId; /* If Inter_DU HO, this is Taregt DU ID. In case of Inter CU HO, this is Target CU ID */ + uint32_t srcNodeId; /* If Inter_DU HO, this is Source DU ID. In case of Inter CU HO, this is Source CU ID */ + uint32_t tgtNodeId; /* If Inter_DU HO, this is Taregt DU ID. In case of Inter CU HO, this is Target CU ID */ + uint32_t tgtCellId; /* Cell Id in target node to which UE is to be handed over */ + uint8_t cuUeF1apIdSrc; /* Used for Inter-CU HO. CU UE F1AP ID of UE in source CU */ + uint8_t cuUeF1apIdTgt; /* Used for Inter-CU HO. CU UE F1AP ID of UE in target CU */ }HandoverInfo; typedef struct dlAmCfg @@ -352,6 +357,7 @@ typedef struct duDb CuCellCb cellCb[MAX_NUM_CELL]; uint8_t numUe; CuUeCb ueCb[MAX_NUM_CELL * MAX_NUM_UE]; + CuUeCb *tempUeCtxtInHo; }DuDb; typedef struct cuGlobalCb diff --git a/src/cu_stub/cu_xnap_msg_hdl.c b/src/cu_stub/cu_xnap_msg_hdl.c index 26d7329bd..8033c9940 100644 --- a/src/cu_stub/cu_xnap_msg_hdl.c +++ b/src/cu_stub/cu_xnap_msg_hdl.c @@ -21,6 +21,7 @@ #include "cu_stub_sctp.h" #include "cu_stub_egtp.h" #include "OCTET_STRING.h" +#include "F1AP-PDU.h" #include "cu_f1ap_msg_hdl.h" #include "cu_stub.h" @@ -165,16 +166,18 @@ void XNAPProcXnSetupRsp(uint32_t *destId, Buffer *mBuf) * @return void * ******************************************************************/ -void BuildAndSendHOReq(CuUeCb *ueCb, XnEventType event, char *xnMsg, MsgLen xnMsgLen) +void BuildAndSendHOReq(CuUeCb *ueCb, char *xnMsg, MsgLen xnMsgLen) { Buffer *mBuf = NULLP; if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK) { if(ODU_ADD_POST_MSG_MULT((Data *)xnMsg, xnMsgLen, mBuf) == ROK) - { - CMCHKPK(oduUnpackUInt8, event, mBuf); - if(sctpSend(XN_INTERFACE, ueCb->hoInfo.targetId, mBuf) != ROK) + { + CMCHKPK(oduUnpackUInt8, ueCb->hoInfo.cuUeF1apIdSrc, mBuf); + CMCHKPK(oduUnpackUInt32, ueCb->hoInfo.tgtCellId, mBuf); + CMCHKPK(oduUnpackUInt8, HO_REQ, mBuf); + if(sctpSend(XN_INTERFACE, ueCb->hoInfo.tgtNodeId, mBuf) != ROK) { DU_LOG("\nERROR --> CU_STUB: Failed to send handover request to peer CU"); ueCb->state = UE_ACTIVE; @@ -184,6 +187,303 @@ void BuildAndSendHOReq(CuUeCb *ueCb, XnEventType event, char *xnMsg, MsgLen xnMs } } +/******************************************************************* + * + * @brief Process received Handover Request + * + * @details + * + * Function : XNAPProcHandoverReq + * + * Functionality: + * 1. Unpack Cell Id from msg and find DU to which it belongs + * 2. Create UE context for UE in handover and store in DU DB + * 3. Decode the F1AP UE context modification msg received in + * XNAP message buffer and extract UE configurations + * 4. Send UE context setup request to DU with these configs + * + * @params[in] Pointer to destination Id + * Pointer to message buffer + * @return void + * + ******************************************************************/ +void XNAPProcHandoverReq(uint32_t destId, Buffer *mBuf) +{ + uint8_t duIdx, cellIdx; + uint8_t cuUeF1apIdSrc; + uint32_t cellId; + DuDb *duDb; + CuCellCb *cellCb; + + DU_LOG("\nINFO --> CU STUB : Received Handover Request"); + + /* Find DU Db and Cell Cb from cellId */ + CMCHKUNPK(oduPackUInt32, &(cellId), mBuf); + for(duIdx = 0; duIdx < cuCb.numDu; duIdx++) + { + duDb = &cuCb.duInfo[duIdx]; + SEARCH_CELL_DB(cellIdx, duDb, cellId, cellCb) + if(cellCb) + break; + } + if(!cellCb) + { + DU_LOG("\nERROR --> CU_STUB: Failed to find Cell Id [%d] received in HO Request", cellId); + return; + } + + /* Fetch CU UE F1AP ID of UE in handover assigned by source CU */ + CMCHKUNPK(oduPackUInt8, &(cuUeF1apIdSrc), mBuf); + + /* Filling temporary UE context which will be used to create actual UE context at + * CU later */ + CU_ALLOC(duDb->tempUeCtxtInHo, sizeof(CuUeCb)); + if(!duDb->tempUeCtxtInHo) + { + DU_LOG("\nERROR --> XNAP : Failed to allocate memory to temporary UE context for UE in handover"); + return; + } + memset(duDb->tempUeCtxtInHo, 0, sizeof(CuUeCb)); + duDb->tempUeCtxtInHo->cellCb = cellCb; + duDb->tempUeCtxtInHo->gnbCuUeF1apId = ++cuCb.gnbCuUeF1apIdGenerator; + duDb->tempUeCtxtInHo->state = UE_HANDOVER_IN_PROGRESS; + duDb->tempUeCtxtInHo->hoInfo.HOType = Xn_Based_Inter_CU_HO; + duDb->tempUeCtxtInHo->hoInfo.srcNodeId = destId; + duDb->tempUeCtxtInHo->hoInfo.tgtNodeId = cuCb.cuCfgParams.cuId; + duDb->tempUeCtxtInHo->hoInfo.tgtCellId = cellId; + duDb->tempUeCtxtInHo->hoInfo.cuUeF1apIdSrc = cuUeF1apIdSrc; + duDb->tempUeCtxtInHo->hoInfo.cuUeF1apIdTgt = duDb->tempUeCtxtInHo->gnbCuUeF1apId; + + /* Decode UE context modification response msg received in Xn Msg */ + char *recvBuf; + MsgLen recvBufLen, copyLen; + F1AP_PDU_t *f1apMsg = NULLP; + F1AP_PDU_t f1apasnmsg ; + + f1apMsg = &f1apasnmsg; + memset(f1apMsg, 0, sizeof(F1AP_PDU_t)); + if(F1APDecodeMsg(f1apMsg, mBuf, &recvBuf, &recvBufLen) != ROK) + { + DU_LOG("\nERROR --> F1AP : F1AP PDU decode failed"); + return; + } + CU_FREE(recvBuf, recvBufLen); + procUeContextModificationResponse(duDb->duId, f1apMsg, NULL, 0); +} + +/******************************************************************* + * + * @brief Build And send dummy Handover request ack to Peer CU + * + * @details + * + * Function : BuildAndSendHOReqAck + * + * Functionality: + * Build And send dummy Handover request ack to Peer CU + * + * @params[in] Pointer to UE Cb + * Message to be sent + * Message Length + * @return void + * + ******************************************************************/ +void BuildAndSendHOReqAck(CuUeCb *ueCb, char *xnMsg, MsgLen xnMsgLen) +{ + Buffer *mBuf = NULLP; + + if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK) + { + if(ODU_ADD_POST_MSG_MULT((Data *)xnMsg, xnMsgLen, mBuf) == ROK) + { + CMCHKPK(oduUnpackUInt8, ueCb->gnbCuUeF1apId, mBuf); + CMCHKPK(oduUnpackUInt8, ueCb->hoInfo.cuUeF1apIdSrc, mBuf); + CMCHKPK(oduUnpackUInt8, HO_REQ_ACK, mBuf); + if(sctpSend(XN_INTERFACE, ueCb->hoInfo.srcNodeId, mBuf) != ROK) + { + DU_LOG("\nERROR --> CU_STUB: Failed to send handover request ack to peer CU"); + } + } + } +} + +/******************************************************************* + * + * @brief Process received Handover Request Ack + * + * @details + * + * Function : XNAPProcHandoverReqAck + * + * Functionality: + * 1. Unpack CU UE F1AP ID (by SCU) and fetch UE CB and + * the corresponding DU DB (SDU) + * 2. Unpack CU UE F1AP ID (by TCU) and fill in UEcb->hoInfo + * 3. Decode DU to CU RRC Container received in XNAP message + * buffer and extract UE configurations. + * 4. Send UE Context modification response to SDU conatining + * RRC Reconfig Message and command to stop transmission + * to UE in handover. + * + * @params[in] Destination Id + * Pointer to message buffer + * @return void + * + ******************************************************************/ +void XNAPProcHandoverReqAck(uint32_t destId, Buffer *mBuf) +{ + uint8_t duIdx, duId, ueIdx; + uint8_t cuUeF1apIdSrc; + uint8_t cuUeF1apIdTgt; + DuDb *duDb; + CuUeCb *ueCb; + + DU_LOG("\nINFO --> CU STUB : Received Handover Request Acknowledgement"); + + /* Fetch UE CB and DU DB in Source CU for UE under Inter-CU Handover */ + CMCHKUNPK(oduPackUInt8, &(cuUeF1apIdSrc), mBuf); + for(duIdx = 0; duIdx < cuCb.numDu; duIdx++) + { + for(ueIdx = 0; ueIdx < MAX_NUM_CELL * MAX_NUM_UE; ueIdx++) + { + if(cuCb.duInfo[duIdx].ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apIdSrc) + { + duDb = &cuCb.duInfo[duIdx]; + ueCb = &cuCb.duInfo[duIdx].ueCb[ueIdx]; + break; + } + } + if(duDb && ueCb) + break; + } + if(!duDb || !ueCb) + { + DU_LOG("\nERROR --> CU STUB : UE CB not found for CU UE F1AP ID [%d]", cuUeF1apIdSrc); + return; + } + + /* Decode CU UE F1AP ID assigned by Target CU to UE in handover and store + * this in hoInfo block for use during future message exchange between the + * two CUs */ + CMCHKUNPK(oduPackUInt8, &(cuUeF1apIdTgt), mBuf); + ueCb->hoInfo.cuUeF1apIdTgt = cuUeF1apIdTgt; + + /* Decode DU to CU RRC Container received in Xn Msg */ + OCTET_STRING_t rrcCont; + MsgLen copyCnt; + + /* Copy mBuf into char array to decode it */ + memset(&rrcCont, 0, sizeof(OCTET_STRING_t)); + ODU_GET_MSG_LEN(mBuf, &rrcCont.size); + CU_ALLOC(rrcCont.buf, rrcCont.size); + if(rrcCont.buf == NULLP) + { + DU_LOG("\nERROR --> XNAP : Memory allocation failed"); + return; + } + if(ODU_COPY_MSG_TO_FIX_BUF(mBuf, 0, rrcCont.size, (Data *)rrcCont.buf, ©Cnt) != ROK) + { + DU_LOG("\nERROR --> F1AP : Failed while copying %d", copyCnt); + return; + } + + /* Extract DU to CU RRC container information and store in UE CB */ + extractDuToCuRrcCont(ueCb, rrcCont); + + CU_FREE(rrcCont.buf, rrcCont.size); + + /* Send UE Context Modification request after filling it using the information received in + * Xn Handover Request Ack */ + if(BuildAndSendUeContextModificationReq(duDb->duId, ueCb, STOP_DATA_TX) != ROK) + { + DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextModificationReq()"); + return; + } +} + +/******************************************************************* + * + * @brief Build And send dummy UE Context Release to Peer CU + * + * @details + * + * Function : BuildAndSendUeContextRelease + * + * Functionality: + * Build And send dummy UE Context Release to Peer CU + * + * @params[in] Pointer to UE Cb + * @return void + * + ******************************************************************/ +void BuildAndSendUeContextRelease(CuUeCb *ueCb) +{ + Buffer *mBuf = NULLP; + + if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK) + { + CMCHKPK(oduUnpackUInt8, ueCb->hoInfo.cuUeF1apIdSrc, mBuf); + CMCHKPK(oduUnpackUInt8, UE_CTXT_REL, mBuf); + if(sctpSend(XN_INTERFACE, ueCb->hoInfo.srcNodeId, mBuf) != ROK) + { + DU_LOG("\nERROR --> CU_STUB: Failed to send UE context release to peer CU"); + } + } + + return; +} + +/******************************************************************* + * @brief Process received UE Context Release + * + * @details + * + * Function : XNAPProcUeContextRel + * + * Functionality: + * 1. Unpack CU UE F1AP ID (by SCU) and fetch UE CB and + * the corresponding DU DB (SDU) + * 2. Send UE Context release command to SDU + * + * @params[in] Destination Id + * Pointer to message buffer + * @return void + * + ******************************************************************/ +void XNAPProcUeContextRel(uint32_t destId, Buffer *mBuf) +{ + uint8_t duIdx, duId, ueIdx; + uint8_t cuUeF1apIdSrc; + DuDb *duDb; + CuUeCb *ueCb; + + DU_LOG("\nINFO --> CU STUB : Received UE Context Release"); + + /* Fetch UE CB and DU DB in Source CU for UE under Inter-CU Handover */ + CMCHKUNPK(oduPackUInt8, &(cuUeF1apIdSrc), mBuf); + for(duIdx = 0; duIdx < cuCb.numDu; duIdx++) + { + for(ueIdx = 0; ueIdx < MAX_NUM_CELL * MAX_NUM_UE; ueIdx++) + { + if(cuCb.duInfo[duIdx].ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apIdSrc) + { + duDb = &cuCb.duInfo[duIdx]; + ueCb = &duDb->ueCb[ueIdx]; + break; + } + } + if(duDb && ueCb) + break; + } + if(!duDb || !ueCb) + { + DU_LOG("\nERROR --> CU STUB : UE CB not found for CU UE F1AP ID [%d]", cuUeF1apIdSrc); + return; + } + + BuildAndSendUeContextReleaseCommand(duDb->duId, ueCb->gnbCuUeF1apId, ueCb->gnbDuUeF1apId); +} + /******************************************************************* * * @brief Handle incoming messages at Xn interface @@ -223,56 +523,18 @@ void XNAPMsgHdlr(uint32_t *destId, Buffer *mBuf) case HO_REQ: { - DU_LOG("\nINFO --> CU STUB : Received Handover Request at XNAP"); - -//Handling of HO Request to be added in next gerrit -#if 0 - char *recvBuf; - MsgLen copyCnt; - MsgLen recvBufLen; - F1AP_PDU_t *f1apMsg = NULLP; - asn_dec_rval_t rval; /* Decoder return value */ - F1AP_PDU_t f1apasnmsg ; - - ODU_PRINT_MSG(mBuf, 0,0); - - /* Copy mBuf into char array to decode it */ - ODU_GET_MSG_LEN(mBuf, &recvBufLen); - CU_ALLOC(recvBuf, (Size)recvBufLen); - - if(recvBuf == NULLP) - { - DU_LOG("\nERROR --> F1AP : Memory allocation failed"); - return; - } - if(ODU_COPY_MSG_TO_FIX_BUF(mBuf, 0, recvBufLen, (Data *)recvBuf, ©Cnt) != ROK) - { - DU_LOG("\nERROR --> F1AP : Failed while copying %d", copyCnt); - return; - } - - DU_LOG("\nDEBUG --> F1AP : Received flat buffer to be decoded : "); - for(i=0; i< recvBufLen; i++) - { - DU_LOG("%x",recvBuf[i]); - } - - /* Decoding flat buffer into F1AP messsage */ - f1apMsg = &f1apasnmsg; - memset(f1apMsg, 0, sizeof(F1AP_PDU_t)); - rval = aper_decode(0, &asn_DEF_F1AP_PDU, (void **)&f1apMsg, recvBuf, recvBufLen, 0, 0); - CU_FREE(recvBuf, (Size)recvBufLen); - - if(rval.code == RC_FAIL || rval.code == RC_WMORE) - { - DU_LOG("\nERROR --> F1AP : ASN decode failed"); - return; - } - DU_LOG("\n"); - xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg); - - procUeContextModificationResponse(0, f1apMsg, recvBuf, recvBufLen); -#endif + XNAPProcHandoverReq(*destId, mBuf); + break; + } + + case HO_REQ_ACK: + { + XNAPProcHandoverReqAck(*destId, mBuf); + break; + } + case UE_CTXT_REL: + { + XNAPProcUeContextRel(*destId, mBuf); break; } default: diff --git a/src/du_app/du_cfg.c b/src/du_app/du_cfg.c index 01b67c5b1..fe4ef425b 100644 --- a/src/du_app/du_cfg.c +++ b/src/du_app/du_cfg.c @@ -43,6 +43,7 @@ #include "PagingCycle.h" #include "PCCH-Config.h" #include "TimeAlignmentTimer.h" +#include "BCCH-DL-SCH-Message.h" #include "RACH-ConfigGeneric.h" #include "PUSCH-TimeDomainResourceAllocation.h" #include "PUCCH-ConfigCommon.h" diff --git a/src/du_app/du_f1ap_msg_hdl.c b/src/du_app/du_f1ap_msg_hdl.c index 22c8286e9..b9a8f3495 100644 --- a/src/du_app/du_f1ap_msg_hdl.c +++ b/src/du_app/du_f1ap_msg_hdl.c @@ -174,12 +174,15 @@ #include "CFRA-SSB-Resource.h" #include "BWP-UplinkCommon.h" #include "ReconfigurationWithSync.h" +#include "BCCH-DL-SCH-Message.h" #include "du_sys_info_hdl.h" #include "DRX-ConfigRrc.h" #include "MeasurementTimingConfigurationRrc.h" #include "MeasurementTimingConfigurationRrc-IEs.h" #include "MeasTimingList.h" #include "MeasTiming.h" +#include "Cells-Status-List.h" +#include "Cells-Status-Item.h" #ifdef O1_ENABLE #include "CmInterface.h" @@ -1046,19 +1049,19 @@ uint8_t BuildServedCellList(GNB_DU_Served_Cells_List_t *duServedCell) for(plmnidx=0; plmnidxlist.array[plmnidx],\ - sizeof(GNB_DU_Served_Cells_ItemIEs_t)); + sizeof(GNB_DU_Served_Cells_ItemIEs_t)); if(duServedCell->list.array[plmnidx] == NULLP) { - return RFAILED; + return RFAILED; } } idx = 0; duServedCell->list.array[idx]->id = ProtocolIE_ID_id_GNB_DU_Served_Cells_Item; duServedCell->list.array[idx]->criticality = Criticality_reject; duServedCell->list.array[idx]->value.present = \ - GNB_DU_Served_Cells_ItemIEs__value_PR_GNB_DU_Served_Cells_Item; + GNB_DU_Served_Cells_ItemIEs__value_PR_GNB_DU_Served_Cells_Item; srvCellItem = \ - &duServedCell->list.array[idx]->value.choice.GNB_DU_Served_Cells_Item; + &duServedCell->list.array[idx]->value.choice.GNB_DU_Served_Cells_Item; /*nRCGI*/ BuildNrcgiret = BuildNrcgi(&srvCellItem->served_Cell_Information.nRCGI); if(BuildNrcgiret != ROK) @@ -1067,7 +1070,7 @@ uint8_t BuildServedCellList(GNB_DU_Served_Cells_List_t *duServedCell) } /*nRPCI*/ srvCellItem->served_Cell_Information.nRPCI = \ - duCfgParam.srvdCellLst[0].duCellInfo.cellInfo.nrPci; + duCfgParam.srvdCellLst[0].duCellInfo.cellInfo.nrPci; /* fiveGS_TAC */ BuildFiveGSTacret = BuildFiveGSTac(&srvCellItem->served_Cell_Information); @@ -1096,7 +1099,7 @@ uint8_t BuildServedCellList(GNB_DU_Served_Cells_List_t *duServedCell) /* GNB DU System Information */ DU_ALLOC(srvCellItem->gNB_DU_System_Information, - sizeof(GNB_DU_System_Information_t)); + sizeof(GNB_DU_System_Information_t)); if(!srvCellItem->gNB_DU_System_Information) { return RFAILED; @@ -1104,20 +1107,20 @@ uint8_t BuildServedCellList(GNB_DU_Served_Cells_List_t *duServedCell) /* MIB */ srvCellItem->gNB_DU_System_Information->mIB_message.size = duCfgParam.srvdCellLst[0].duSysInfo.mibLen; DU_ALLOC(srvCellItem->gNB_DU_System_Information->mIB_message.buf, - srvCellItem->gNB_DU_System_Information->mIB_message.size); + srvCellItem->gNB_DU_System_Information->mIB_message.size); if(!srvCellItem->gNB_DU_System_Information->mIB_message.buf) { return RFAILED; } memcpy(srvCellItem->gNB_DU_System_Information->mIB_message.buf, duCfgParam.srvdCellLst[0].duSysInfo.mibMsg, \ - srvCellItem->gNB_DU_System_Information->mIB_message.size); + srvCellItem->gNB_DU_System_Information->mIB_message.size); /* SIB1 */ srvCellItem->gNB_DU_System_Information->sIB1_message.size =\ - duCfgParam.srvdCellLst[0].duSysInfo.sib1Len; + duCfgParam.srvdCellLst[0].duSysInfo.sib1Len; DU_ALLOC(srvCellItem->gNB_DU_System_Information->sIB1_message.buf, - srvCellItem->gNB_DU_System_Information->sIB1_message.size); + srvCellItem->gNB_DU_System_Information->sIB1_message.size); if(!srvCellItem->gNB_DU_System_Information->sIB1_message.buf) { return RFAILED; @@ -1125,7 +1128,7 @@ uint8_t BuildServedCellList(GNB_DU_Served_Cells_List_t *duServedCell) for(int x=0; xgNB_DU_System_Information->sIB1_message.size; x++) { srvCellItem->gNB_DU_System_Information->sIB1_message.buf[x]=\ - duCfgParam.srvdCellLst[0].duSysInfo.sib1Msg[x]; + duCfgParam.srvdCellLst[0].duSysInfo.sib1Msg[x]; } return ROK; } @@ -1631,7 +1634,7 @@ uint8_t BuildAndSendF1SetupReq() elementCnt = 5; f1SetupReq->protocolIEs.list.count = elementCnt; - f1SetupReq->protocolIEs.list.size = elementCnt * sizeof(F1SetupRequestIEs_t ); + f1SetupReq->protocolIEs.list.size = elementCnt * sizeof(F1SetupRequestIEs_t *); /* Initialize the F1Setup members */ DU_ALLOC(f1SetupReq->protocolIEs.list.array,f1SetupReq->protocolIEs.list.size); @@ -1882,7 +1885,7 @@ void freeCellsToModifyItem(Served_Cells_To_Modify_Item_t *modifyItem) } } DU_FREE(modifyItem->served_Cell_Information.measurementTimingConfiguration.buf,\ - modifyItem->served_Cell_Information.measurementTimingConfiguration.size); + modifyItem->served_Cell_Information.measurementTimingConfiguration.size); } /******************************************************************* @@ -1903,12 +1906,13 @@ void freeCellsToModifyItem(Served_Cells_To_Modify_Item_t *modifyItem) * ****************************************************************/ void FreeDUConfigUpdate(F1AP_PDU_t *f1apDuCfg) { - uint8_t ieIdx=0, cellModifyIdx=0, cellDeleteIdx=0; + uint8_t idx=0,ieIdx=0, cellModifyIdx=0, cellDeleteIdx=0; GNBDUConfigurationUpdate_t *duCfgUpdate = NULLP; Served_Cells_To_Modify_List_t *cellsToModify=NULLP; Served_Cells_To_Delete_List_t *cellsToDelete=NULLP; Served_Cells_To_Delete_Item_t *deleteItem = NULLP; Served_Cells_To_Delete_ItemIEs_t *deleteItemIe = NULLP; + Cells_Status_ItemIEs_t *cellStatusItemIE; if(f1apDuCfg != NULLP) { @@ -1976,6 +1980,18 @@ void FreeDUConfigUpdate(F1AP_PDU_t *f1apDuCfg) duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.GNB_DU_ID.size); break; } + case ProtocolIE_ID_id_Cells_Status_List: + { + for(idx = 0; idx < duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.Cells_Status_List.list.count; idx++) + { + cellStatusItemIE = (Cells_Status_ItemIEs_t *)duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.Cells_Status_List.list.array[idx]; + DU_FREE(cellStatusItemIE->value.choice.Cells_Status_Item.nRCGI.nRCellIdentity.buf, cellStatusItemIE->value.choice.Cells_Status_Item.nRCGI.nRCellIdentity.size); + DU_FREE(cellStatusItemIE->value.choice.Cells_Status_Item.nRCGI.pLMN_Identity.buf, cellStatusItemIE->value.choice.Cells_Status_Item.nRCGI.pLMN_Identity.size); + DU_FREE(duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.Cells_Status_List.list.array[idx],sizeof(Cells_Status_ItemIEs_t)); + } + DU_FREE(duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.Cells_Status_List.list.array,\ + duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.Cells_Status_List.list.size); + } } DU_FREE(duCfgUpdate->protocolIEs.list.array[ieIdx],\ sizeof(GNBDUConfigurationUpdateIEs_t)); @@ -2468,6 +2484,7 @@ uint8_t fillCellToDeleteItem(struct Served_Cells_To_Delete_ItemIEs *deleteItemIe fillBitString(&deleteItem->oldNRCGI.nRCellIdentity, ODU_VALUE_FOUR, ODU_VALUE_FIVE, duCfgParam.sib1Params.cellIdentity); return ROK; } + /******************************************************************* * * @brief Builds ServCellToDeleteList @@ -2519,6 +2536,56 @@ uint8_t buildServCellToDeleteList(Served_Cells_To_Delete_List_t *cellsToDelete) return ROK; } +/******************************************************************* + * + * @brief Builds CellsStatusList + * + * @details + * + * Function : buildCellsStatusList + * + * Functionality: Builds the Cell Status List + * + * @params[in] Pointer to Cells_Status_List_t * + * + * @return ROK - success + * RFAILED - failure + * + *****************************************************************/ +uint8_t buildCellsStatusList(Cells_Status_List_t *cellStatusList) +{ + uint8_t elementCnt = 0, idx = 0, ret = ROK; + Cells_Status_ItemIEs_t *cellStatusItemIE; + + elementCnt = 1; + cellStatusList->list.count = elementCnt; + cellStatusList->list.size = elementCnt * sizeof(Cells_Status_ItemIEs_t *); + DU_ALLOC(cellStatusList->list.array, cellStatusList->list.size); + + for(idx = 0; idx < elementCnt; idx++) + { + DU_ALLOC(cellStatusList->list.array[idx], sizeof(Cells_Status_ItemIEs_t)); + if(!cellStatusList->list.array[idx]) + { + DU_LOG("ERROR --> F1AP: buildCellsStatusList() memory allocation failure"); + return RFAILED; + } + } + idx = 0; + cellStatusItemIE = (Cells_Status_ItemIEs_t *)cellStatusList->list.array[idx]; + cellStatusItemIE->id = ProtocolIE_ID_id_Cells_Status_Item; + cellStatusItemIE->criticality = Criticality_reject; + cellStatusItemIE->value.present = Cells_Status_ItemIEs__value_PR_Cells_Status_Item; + ret = BuildNrcgi(&cellStatusItemIE->value.choice.Cells_Status_Item.nRCGI); + if(ret == RFAILED) + { + DU_LOG("ERROR --> F1AP: buildCellsStatusList() NRCGI failed"); + return RFAILED; + } + cellStatusItemIE->value.choice.Cells_Status_Item.service_status.service_state = Service_State_in_service; + return ROK; +} + /******************************************************************* * * @brief Builds and sends the DUConfigUpdate @@ -2574,7 +2641,7 @@ uint8_t BuildAndSendDUConfigUpdate(ServCellAction servCellAction) InitiatingMessage__value_PR_GNBDUConfigurationUpdate; duCfgUpdate = &f1apDuCfg->choice.initiatingMessage->value.\ choice.GNBDUConfigurationUpdate; - elementCnt = 3; + elementCnt = 4; duCfgUpdate->protocolIEs.list.count = elementCnt; duCfgUpdate->protocolIEs.list.size = \ elementCnt * sizeof(GNBDUConfigurationUpdateIEs_t*); @@ -2641,7 +2708,21 @@ uint8_t BuildAndSendDUConfigUpdate(ServCellAction servCellAction) } } - // NOTE :GNB DU SYS INFO:MIB AND SIB1 INFORMATION TO BE BUILT AND FILLED HERE + // TODO :GNB DU SYS INFO:MIB AND SIB1 INFORMATION TO BE BUILT AND FILLED HERE + + /*Cell Status List*/ + ieIdx++; + duCfgUpdate->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_Cells_Status_List; + duCfgUpdate->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject; + duCfgUpdate->protocolIEs.list.array[ieIdx]->value.present = \ + GNBDUConfigurationUpdateIEs__value_PR_Cells_Status_List; + ret = buildCellsStatusList(&duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.Cells_Status_List); + if(ret == RFAILED) + { + DU_LOG("ERROR --> DU APP : BuildAndSendDUConfigUpdate(): Cell Status List building failed"); + break; + } + /*GNB DU ID */ ieIdx++; duCfgUpdate->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_gNB_DU_ID; diff --git a/src/du_app/du_sys_info_hdl.c b/src/du_app/du_sys_info_hdl.c index 0a830ea5e..64bde2675 100644 --- a/src/du_app/du_sys_info_hdl.c +++ b/src/du_app/du_sys_info_hdl.c @@ -54,11 +54,11 @@ #include "TDD-UL-DL-ConfigCommon.h" #include "ServingCellConfigCommonSIB.h" #include "MCC.h" -#include "BCCH-DL-SCH-Message.h" #include "SIB1.h" #include "odu_common_codec.h" -#include "du_sys_info_hdl.h" +#include "BCCH-DL-SCH-Message.h" #include "du_f1ap_conversions.h" +#include "du_sys_info_hdl.h" void FreeSib1Msg(SIB1_t *sib1Msg); uint8_t FreqInfoUlret = RFAILED; @@ -3278,10 +3278,18 @@ void FreeBcchDlSchMsg(BCCH_DL_SCH_Message_t bcchMsg) FreeSib1Msg(bcchMsg.message.choice.c1->choice.systemInformationBlockType1); break; } + case BCCH_DL_SCH_MessageType__c1_PR_systemInformation: + break; + case BCCH_DL_SCH_MessageType__c1_PR_NOTHING: + break; } DU_FREE(bcchMsg.message.choice.c1, sizeof(struct BCCH_DL_SCH_MessageType__c1)); break; } + case BCCH_DL_SCH_MessageType_PR_messageClassExtension: + break; + case BCCH_DL_SCH_MessageType_PR_NOTHING: + break; } } diff --git a/src/du_app/du_sys_info_hdl.h b/src/du_app/du_sys_info_hdl.h index 2aab5fc0c..b175765d5 100644 --- a/src/du_app/du_sys_info_hdl.h +++ b/src/du_app/du_sys_info_hdl.h @@ -37,6 +37,7 @@ uint8_t BuildBwpUlCommon(BWP_UplinkCommon_t *bwp); uint8_t BuildTddUlDlCfgComm(TDD_UL_DL_ConfigCommon_t *tddCfg); void FreeBwpDlCommon(BWP_DownlinkCommon_t *bwp); void FreeBwpUlCommon(BWP_UplinkCommon_t *bwp); +void FreeBcchDlSchMsg(BCCH_DL_SCH_Message_t bcchMsg); char encBuf[ENC_BUF_MAX_LEN]; DuCfgParams duCfgParam;