X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=src%2Fcu_stub%2Fcu_f1ap_msg_hdl.c;h=bbb2fa8ca6d3c9e16796fee25800c48453daf47b;hb=2a743dfffc577ac90819776af7e0d86cb00fca57;hp=2bf96de624ad3794f181277a99e25050a2b47f3a;hpb=84670fed17a640ca68c199055b740c41f04c9f4d;p=o-du%2Fl2.git diff --git a/src/cu_stub/cu_f1ap_msg_hdl.c b/src/cu_stub/cu_f1ap_msg_hdl.c index 2bf96de62..bbb2fa8ca 100644 --- a/src/cu_stub/cu_f1ap_msg_hdl.c +++ b/src/cu_stub/cu_f1ap_msg_hdl.c @@ -127,6 +127,9 @@ #include "MeasConfigRrc.h" #include "AS-Config.h" #include "RRCReconfiguration-v1530-IEs.h" +#include "CNUEPagingIdentity.h" +#include "PagingCell-Item.h" +#include "UL-DCCH-Message.h" #include "cu_stub_sctp.h" #include "cu_stub_egtp.h" @@ -186,31 +189,6 @@ S16 SendF1APMsg(Region region, Pool pool, uint32_t duId) return ROK; } /* SendF1APMsg */ -/******************************************************************* - * - * @brief Builds NRCell ID - * - * @details - * - * Function : BuildNrCellId - * - * Functionality: Building the NR Cell ID - * - * @params[in] BIT_STRING_t *nrcell - * @return ROK - success - * RFAILED - failure - * - * ****************************************************************/ - -S16 BuildNrCellId(BIT_STRING_t *nrcell) -{ - memset(nrcell->buf, 0, nrcell->size); - nrcell->buf[4] = 16; - nrcell->bits_unused = 4; - nrcell->size = 5 * sizeof(uint8_t); - return ROK; -} - /******************************************************************** * * @brief Builds and sends the F1SetupResponse @@ -416,10 +394,11 @@ uint8_t BuildAndSendF1SetupRsp(uint32_t duId, BIT_STRING_t *nrcellId) buildPlmnId(cuCb.cuCfgParams.plmn , cellToActivate->list.array[0]->value.choice.\ Cells_to_be_Activated_List_Item.nRCGI.pLMN_Identity.buf); cellToActivate->list.array[0]->value.choice.Cells_to_be_Activated_List_Item.\ - nRCGI.nRCellIdentity.size = 5; + nRCGI.nRCellIdentity.size = 5*sizeof(uint8_t); CU_ALLOC(cellToActivate->list.array[0]->value.choice.\ Cells_to_be_Activated_List_Item.nRCGI.nRCellIdentity.buf,\ - 5*sizeof(uint8_t)); + cellToActivate->list.array[0]->value.choice.Cells_to_be_Activated_List_Item.\ + nRCGI.nRCellIdentity.size); if(cellToActivate->list.array[0]->value.choice.\ Cells_to_be_Activated_List_Item.nRCGI.nRCellIdentity.buf == NULLP) { @@ -1532,10 +1511,48 @@ uint8_t BuildDLRRCContainer(CuUeCb *ueCb, uint8_t rrcMsgType, RRCContainer_t *rr if(ret == RFAILED) DU_LOG("\nERROR --> F1AP: Failed to fill DL-CCCH Msg at RRC SETUP"); } - else if(rrcMsgType == REGISTRATION_ACCEPT) + else if(rrcMsgType == RRC_SETUP_COMPLETE) + { + DU_LOG("\nINFO --> F1AP : Sending NAS Security mode command"); + char secModeBuf[30]={0x00, 0x02, 0x2e, 0x82, 0xaf, 0xc0, 0x7d, 0x1c, 0x4e, 0xfc, 0x80, 0x0f, 0xc0, + 0x0b, 0xa0, 0x20, 0x40, 0x9e, 0x0e, 0x1e, 0x0e, 0x1c, 0x26, 0xc0, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00}; + bufLen =30; + rrcContainer->size = bufLen; + CU_ALLOC(rrcContainer->buf, rrcContainer->size); + if(rrcContainer->buf != NULLP) + { + memset(rrcContainer->buf, 0, bufLen); + memcpy(rrcContainer->buf, secModeBuf, bufLen); + } + else + { + DU_LOG("\nERROR --> F1AP : Memory allocation failure for RRC Container buffer"); + ret = RFAILED; + } + } + else if(rrcMsgType == NAS_SECURITY_MODE_COMPLETE) + { + DU_LOG("\nINFO --> F1AP : Sending RRC Security mode command"); + char secModeBuf[9]={0x00, 0x03, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}; + bufLen =9; + rrcContainer->size = bufLen; + CU_ALLOC(rrcContainer->buf, rrcContainer->size); + if(rrcContainer->buf != NULLP) + { + memset(rrcContainer->buf, 0, bufLen); + memcpy(rrcContainer->buf, secModeBuf, bufLen); + } + else + { + DU_LOG("\nERROR --> F1AP : Memory allocation failure for RRC Container buffer"); + ret = RFAILED; + } + } + else if(rrcMsgType == RRC_SECURITY_MODE_COMPLETE) { /*Hardcoded RRC Container from reference logs*/ - char buf[14] ={0x00, 0x03, 0x2a, 0x80, 0xaf, 0xc0, 0x08, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00}; + DU_LOG("\nINFO --> F1AP : Sending Registration accept"); + char buf[14] ={0x00, 0x04, 0x2a, 0x80, 0xaf, 0xc0, 0x08, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00}; bufLen =14; rrcContainer->size = bufLen; CU_ALLOC(rrcContainer->buf, rrcContainer->size); @@ -1550,9 +1567,9 @@ uint8_t BuildDLRRCContainer(CuUeCb *ueCb, uint8_t rrcMsgType, RRCContainer_t *rr ret = RFAILED; } } - else if(rrcMsgType == RRC_RECONFIG) + else if(rrcMsgType == UE_CONTEXT_SETUP_RSP) { - DU_LOG("\nDEBUG --> F1AP : Filling DL DCCH RRC Message "); + DU_LOG("\nINFO --> F1AP : Filling DL DCCH RRC Message for RRC Reconfiguration "); ret = fillDlDcchRrcMsg(ueCb, rrcContainer); if(ret == RFAILED) DU_LOG("\nERROR --> F1AP: Failed to fill DL-DCCH Msg for RRC Reconfiguration"); @@ -1766,24 +1783,24 @@ uint8_t setDlRRCMsgType(CuUeCb *ueCb) case RRC_SETUP: rrcMsgType = RRC_SETUP; break; - case REGISTRATION_ACCEPT: - rrcMsgType = REGISTRATION_ACCEPT; + case RRC_SETUP_COMPLETE: + rrcMsgType = RRC_SETUP_COMPLETE; break; - case UE_CONTEXT_SETUP_REQ: - rrcMsgType = UE_CONTEXT_SETUP_REQ; + case NAS_SECURITY_MODE_COMPLETE: + rrcMsgType = NAS_SECURITY_MODE_COMPLETE; break; - case SECURITY_MODE_COMPLETE: - rrcMsgType = SECURITY_MODE_COMPLETE; + case RRC_SECURITY_MODE_COMPLETE: + rrcMsgType = RRC_SECURITY_MODE_COMPLETE; break; - case RRC_RECONFIG: - rrcMsgType = RRC_RECONFIG; + case REGISTRATION_COMPLETE: + rrcMsgType = REGISTRATION_COMPLETE; + break; + case UE_CONTEXT_SETUP_RSP: + rrcMsgType = UE_CONTEXT_SETUP_RSP; break; case RRC_RECONFIG_COMPLETE: rrcMsgType = RRC_RECONFIG_COMPLETE; break; - case UE_CONTEXT_MOD_REQ: - rrcMsgType = UE_CONTEXT_MOD_REQ; - break; default: break; } @@ -1958,6 +1975,9 @@ uint8_t extractDuToCuRrcCont(CuUeCb *ueCb, OCTET_STRING_t rrcCont) CellGroupConfigRrc_t cellGrpCfg, *cellGrpCfgMsg = NULLP; asn_dec_rval_t rval; /* Decoder return value */ + /* Copy the received container to UeCb */ + memcpy(&ueCb->f1apMsgDb.duToCuContainer, &rrcCont, sizeof(OCTET_STRING_t)); + /* Decoding DU to CU RRC container octet string to cell group config */ cellGrpCfgMsg = &cellGrpCfg; memset(cellGrpCfgMsg, 0, sizeof(CellGroupConfigRrc_t)); @@ -2000,9 +2020,10 @@ uint8_t extractDuToCuRrcCont(CuUeCb *ueCb, OCTET_STRING_t rrcCont) uint8_t procInitULRRCMsg(uint32_t duId, F1AP_PDU_t *f1apMsg) { - uint8_t idx,cellIdx=0, duIdx=0, rrcMsgType, gnbDuUeF1apId; + uint8_t idx = 0, duIdx=0, rrcMsgType=0, gnbDuUeF1apId=0; uint8_t ret =ROK; - uint32_t nrCellId, crnti; + uint16_t cellIdx=0, nrCellId = 0; + uint32_t crnti; DuDb *duDb; CuCellCb *cellCb; CuUeCb *ueCb; @@ -2022,8 +2043,7 @@ uint8_t procInitULRRCMsg(uint32_t duId, F1AP_PDU_t *f1apMsg) break; case ProtocolIE_ID_id_NRCGI: - nrCellId = initULRRCMsg->protocolIEs.list.array[idx]->value.choice.NRCGI.nRCellIdentity.buf[4] >> - initULRRCMsg->protocolIEs.list.array[idx]->value.choice.NRCGI.nRCellIdentity.bits_unused; + bitStringToInt(&initULRRCMsg->protocolIEs.list.array[idx]->value.choice.NRCGI.nRCellIdentity, &nrCellId); SEARCH_CELL_DB(cellIdx, duDb, nrCellId, cellCb); if(cellCb == NULLP) return RFAILED; @@ -2115,7 +2135,6 @@ uint8_t BuildNrcgi(NRCGI_t *nrcgi, uint32_t nrCellId) uint8_t ret; uint8_t unused_bits = 4; uint8_t byteSize = 5; - uint8_t val = nrCellId << unused_bits; /* Allocate Buffer Memory */ nrcgi->pLMN_Identity.size = 3 * sizeof(uint8_t); @@ -2136,7 +2155,7 @@ uint8_t BuildNrcgi(NRCGI_t *nrcgi, uint32_t nrCellId) { return RFAILED; } - fillBitString(&nrcgi->nRCellIdentity, unused_bits, byteSize, val); + fillBitString(&nrcgi->nRCellIdentity, unused_bits, byteSize, nrCellId); return ROK; } @@ -2549,7 +2568,7 @@ uint8_t BuildFlowsMap(DrbInfo *drbInfo, Flows_Mapped_To_DRB_List_t *flowMap , ui * RFAILED - failure * * ****************************************************************/ -uint8_t BuildULTnlInfo(TnlInfo *ulUpTnlInfo, ULUPTNLInformation_ToBeSetup_List_t *ulInfo, bool hoInProgress) +uint8_t BuildULTnlInfo(uint8_t duId, TnlInfo *ulUpTnlInfo, ULUPTNLInformation_ToBeSetup_List_t *ulInfo, bool hoInProgress) { uint8_t idx; uint8_t ulCnt; @@ -2661,8 +2680,9 @@ uint8_t BuildULTnlInfo(TnlInfo *ulUpTnlInfo, ULUPTNLInformation_ToBeSetup_List_t * RFAILED - failure * * ****************************************************************/ -uint8_t BuildDRBSetup(CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet) +uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet) { + uint16_t snssaiIdx=0; uint8_t idx = 0, extIeIdx = 0; uint8_t elementCnt = 0, drbCnt = 0; uint8_t BuildQOSInforet = 0,BuildSNSSAIret = 0; @@ -2731,12 +2751,13 @@ uint8_t BuildDRBSetup(CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet) } /*SNSSAI*/ + snssaiIdx = (idx% cuCb.numSnssaiSupported); if(ueCb->state != UE_HANDOVER_IN_PROGRESS) BuildSNSSAIret = BuildSNSSAI(&ueCb->drbList[ueCb->numDrb], &drbSetItem->qoSInformation.choice.\ - choice_extension->value.choice.DRB_Information.sNSSAI, cuCb.snssaiList[0], FALSE); + 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, cuCb.snssaiList[0], TRUE); + choice_extension->value.choice.DRB_Information.sNSSAI, NULLP, TRUE); if(BuildSNSSAIret != ROK) { DU_LOG("\nERROR --> F1AP : Failed to build SNSSAI Info in BuildDRBSetup"); @@ -2758,10 +2779,10 @@ uint8_t BuildDRBSetup(CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet) /*ULUPTNLInformation To Be Setup List*/ if(ueCb->state != UE_HANDOVER_IN_PROGRESS) - BuildULTnlInforet = BuildULTnlInfo(&ueCb->drbList[ueCb->numDrb].ulUpTnlInfo, &drbSetItem->uLUPTNLInformation_ToBeSetup_List,\ + BuildULTnlInforet = BuildULTnlInfo(duId, &ueCb->drbList[ueCb->numDrb].ulUpTnlInfo, &drbSetItem->uLUPTNLInformation_ToBeSetup_List,\ FALSE); else - BuildULTnlInforet = BuildULTnlInfo(&ueCb->drbList[idx].ulUpTnlInfo, &drbSetItem->uLUPTNLInformation_ToBeSetup_List,\ + BuildULTnlInforet = BuildULTnlInfo(duId, &ueCb->drbList[idx].ulUpTnlInfo, &drbSetItem->uLUPTNLInformation_ToBeSetup_List,\ TRUE); if(BuildULTnlInforet != ROK) { @@ -5271,7 +5292,7 @@ uint8_t BuildSchedulingReqConfig(struct SchedulingRequestConfig *schedulingReque * ****************************************************************/ uint8_t BuildMacCellGrpCfg(MAC_CellGroupConfig_t *macCellGrpCfg) { - macCellGrpCfg->drx_Config = NULLP; + macCellGrpCfg->drx_ConfigRrc = NULLP; macCellGrpCfg->schedulingRequestConfig = NULLP; CU_ALLOC(macCellGrpCfg->schedulingRequestConfig, sizeof(struct SchedulingRequestConfig)); if(!macCellGrpCfg->schedulingRequestConfig) @@ -7402,7 +7423,7 @@ void freeMeasIdToAddModList(MeasIdToAddModList_t *measIdList) * @return void * * ****************************************************************/ -uint8_t freeQuantityConfig(QuantityConfig_t *quantityCfg) +void freeQuantityConfig(QuantityConfig_t *quantityCfg) { uint8_t quanCfgIdx; QuantityConfigNR_t *quantityCfgNr; @@ -7555,7 +7576,7 @@ void freeSrbToAddModList(SRB_ToAddModList_t *srbToAddList) * * @details * - * Function : fillRadioBearerConfig + * Function : freeRadioBearerConfig * * Functionality: Free Radio Bearer config * @@ -7651,12 +7672,6 @@ uint8_t fillSrbToAddModList(CuUeCb *ueCb, SRB_ToAddModList_t *srbToAddList, bool return ROK; } - CU_ALLOC(srbToAddList, sizeof(SRB_ToAddModList_t)); - if(!srbToAddList) - { - DU_LOG("\nERROR --> F1AP: Memory allocation failed for SRB to AddMod List in fillRadioBearerConfig"); - return RFAILED; - } srbToAddList->list.count = elementCnt; srbToAddList->list.size = srbToAddList->list.count * sizeof(SRB_ToAddMod_t *); @@ -7750,13 +7765,6 @@ uint8_t fillDrbToAddModList(CuUeCb *ueCb, DRB_ToAddModList_t *drbToAddList, bool return ROK; } - /* DRB To Add/Mod List */ - CU_ALLOC(drbToAddList, sizeof(DRB_ToAddModList_t)); - if(!drbToAddList) - { - DU_LOG("\nERROR --> F1AP: Memory allocation failed for DRB to AddMod List in fillRadioBearerConfig"); - return RFAILED; - } drbToAddList->list.count = elementCnt; drbToAddList->list.size = drbToAddList->list.count * sizeof(DRB_ToAddMod_t *); @@ -7865,13 +7873,28 @@ uint8_t fillDrbToAddModList(CuUeCb *ueCb, DRB_ToAddModList_t *drbToAddList, bool uint8_t fillRadioBearerConfig(CuUeCb *ueCb, RadioBearerConfig_t *radioBearerConfig, bool updateAllRbCfg) { /* SRB To Add/Mod List */ + CU_ALLOC(radioBearerConfig->srb_ToAddModList, sizeof(SRB_ToAddModList_t)); + if(!radioBearerConfig->srb_ToAddModList) + { + DU_LOG("\nERROR --> F1AP: Memory allocation failed for SRB to AddMod List in fillRadioBearerConfig"); + return RFAILED; + } if(fillSrbToAddModList(ueCb, radioBearerConfig->srb_ToAddModList, updateAllRbCfg) != ROK) { + DU_LOG("\nERROR --> F1AP: failed to fill SRB to AddMod List"); return RFAILED; } + /* DRB To Add/Mod List */ + CU_ALLOC(radioBearerConfig->drb_ToAddModList, sizeof(DRB_ToAddModList_t)); + if(!radioBearerConfig->drb_ToAddModList) + { + DU_LOG("\nERROR --> F1AP: Memory allocation failed for DRB to AddMod List in fillRadioBearerConfig"); + return RFAILED; + } if(fillDrbToAddModList(ueCb, radioBearerConfig->drb_ToAddModList, updateAllRbCfg) != ROK) { + DU_LOG("\nERROR --> F1AP: failed to fill DRB to AddMod List "); return RFAILED; } @@ -8441,13 +8464,28 @@ uint8_t fillRrcReconfigNonCriticalExt(CuUeCb *ueCb, RRCReconfiguration_v1530_IEs CU_ALLOC(rrcRecfg->masterCellGroup, sizeof(OCTET_STRING_t)); if(!rrcRecfg->masterCellGroup) { + DU_LOG("\nERROR --> F1AP : Memory allocation failed in fillRrcReconfigNonCriticalExt"); return RFAILED; } + rrcRecfg->masterCellGroup->size = ueCb->f1apMsgDb.duToCuContainer.size; + CU_ALLOC(rrcRecfg->masterCellGroup->buf, rrcRecfg->masterCellGroup->size); + if(!rrcRecfg->masterCellGroup->buf) + { + DU_LOG("\nERROR --> F1AP : Memory allocation failed in fillRrcReconfigNonCriticalExt"); + return RFAILED; + } + memcpy(rrcRecfg->masterCellGroup->buf, ueCb->f1apMsgDb.duToCuContainer.buf, rrcRecfg->masterCellGroup->size); + +#if 0 + /* Use below code if masterCEllGroup is to be filled explicitly at CU rather than copying from DUToCURRCContainer + * received from DU */ if(fillCellGrpCfg(ueCb, rrcRecfg->masterCellGroup, updateAllRbCfg) != ROK) { + DU_LOG("\nERROR --> F1AP : Failed to fill CellGroupCfg in fillRrcReconfigNonCriticalExt"); return RFAILED; } +#endif return ROK; } @@ -8725,7 +8763,7 @@ uint8_t fillCuToDuContainer(CuUeCb *ueCb, CUtoDURRCInformation_t *rrcMsg) { uint8_t elementCnt = 0; uint8_t ret = ROK; - uint8_t idx, idx2, rrcBufLen; + uint8_t idx; /* UE Capabulity RAT Container List */ CU_ALLOC(rrcMsg->uE_CapabilityRAT_ContainerList, sizeof(UE_CapabilityRAT_ContainerList_t)); @@ -8875,7 +8913,7 @@ void FreeCuToDuInfo(CUtoDURRCInformation_t *rrcMsg) * RFAILED - failure * * ****************************************************************/ -uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb, uint16_t rrcContLen, uint8_t *rrcContainer) +uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb) { uint8_t Nrcgiret, SplCellListret, SrbSetupret; uint8_t ret= RFAILED, ret1; @@ -8916,7 +8954,7 @@ uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb, uint16_t rrcC if(ueCb->state == UE_HANDOVER_IN_PROGRESS) elementCnt = 7; else - elementCnt = 12; + elementCnt = 11; ueSetReq->protocolIEs.list.count = elementCnt; ueSetReq->protocolIEs.list.size = elementCnt * sizeof(UEContextSetupRequestIEs_t *); @@ -9034,7 +9072,7 @@ uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb, uint16_t rrcC ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_DRBs_ToBeSetup_List; ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_reject; ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_DRBs_ToBeSetup_List; - ret1 = BuildDRBSetup(ueCb, &ueSetReq->protocolIEs.list.array[idx]->value.choice.DRBs_ToBeSetup_List); + ret1 = BuildDRBSetup(duId, ueCb, &ueSetReq->protocolIEs.list.array[idx]->value.choice.DRBs_ToBeSetup_List); if(ret1 != ROK) { break; @@ -9042,25 +9080,6 @@ uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb, uint16_t rrcC if(ueCb->state != UE_HANDOVER_IN_PROGRESS) { - /* RRC Container for security mode */ - idx++; - ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_RRCContainer; - ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_reject; - ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_RRCContainer; - - char secModeBuf[9]={0x00, 0x02, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}; - bufLen =9; - ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.size = bufLen; - CU_ALLOC(ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.buf, - ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.size); - if(!ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.buf) - { - DU_LOG("\nERROR --> F1AP : Memory allocation for BuildAndSendUeContextSetupReq failed"); - break; - } - memset(ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.buf, 0, bufLen); - memcpy(ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.buf, secModeBuf, bufLen); - /* RRC delivery status request */ idx++; ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_RRCDeliveryStatusRequest; @@ -9181,7 +9200,7 @@ uint8_t extractTeId(DLUPTNLInformation_ToBeSetup_List_t *dlTnlInfo) * RFAILED - failure * * ****************************************************************/ -uint8_t addDrbTunnels(uint8_t teId) +uint8_t addDrbTunnels(uint32_t duId, uint8_t teId) { uint8_t ret = ROK; EgtpTnlEvt tnlEvt; @@ -9194,7 +9213,7 @@ uint8_t addDrbTunnels(uint8_t teId) tnlEvt.action = EGTP_TNL_MGMT_ADD; tnlEvt.lclTeid = teId; tnlEvt.remTeid = teId; - ret = cuEgtpTnlMgmtReq(tnlEvt); + ret = cuEgtpTnlMgmtReq(duId, tnlEvt); if(ret != ROK) { DU_LOG("\nERROR --> EGTP : Tunnel management request failed for teId %x", teId); @@ -9217,9 +9236,9 @@ uint8_t addDrbTunnels(uint8_t teId) * RFAILED - failure * * ****************************************************************/ -uint8_t procDrbSetupList(DRBs_Setup_List_t *drbSetupList) +uint8_t procDrbSetupList(uint32_t duId, CuUeCb *ueCb, DRBs_Setup_List_t *drbSetupList) { - uint8_t arrIdx = 0; + uint8_t arrIdx = 0, drbIdx = 0; uint32_t teId = 0; DRBs_Setup_ItemIEs_t *drbItemIe = NULLP; @@ -9234,10 +9253,21 @@ uint8_t procDrbSetupList(DRBs_Setup_List_t *drbSetupList) teId = extractTeId(&drbItemIe->value.choice.DRBs_Setup_Item.dLUPTNLInformation_ToBeSetup_List); if(teId > 0) { - if(addDrbTunnels(teId)== ROK) - { - DU_LOG("\nDEBUG --> EGTP: Tunnel Added for TeId %d", teId); - } + if(addDrbTunnels(duId, teId)== ROK) + { + DU_LOG("\nDEBUG --> EGTP: Tunnel Added for TeId %d", teId); + } + /* As per Spec 38.473, in UE COntext Response, Tunnel information + * are sent to CU for setting up of Tunnels in DL direction. + * Search for DRB ID in CU databse */ + for(drbIdx = 0; drbIdx < ueCb->numDrb; drbIdx++) + { + if(ueCb->drbList[drbIdx].drbId == drbItemIe->value.choice.DRBs_Setup_Item.dRBID) + { + fillTeIdString(3, teId, ueCb->drbList[drbIdx].dlUpTnlInfo.teId); + break; + } + } } else return RFAILED; @@ -9264,10 +9294,12 @@ uint8_t procDrbSetupList(DRBs_Setup_List_t *drbSetupList) * ****************************************************************/ uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) { - uint8_t duIdx=0, idx, duUeF1apId; - DuDb *duDb; - CuUeCb *ueCb; + uint8_t duIdx = 0, idx = 0, ueIdx = 0, rrcMsgType=0; + uint8_t duUeF1apId = 0, cuUeF1apId = 0; + DuDb *duDb = NULLP; + CuUeCb *ueCb = NULLP; UEContextSetupResponse_t *ueCtxtSetupRsp = NULLP; + OCTET_STRING_t *duToCuRrcContainer; SEARCH_DU_DB(duIdx, duId, duDb); ueCtxtSetupRsp = &f1apMsg->choice.successfulOutcome->value.choice.UEContextSetupResponse; @@ -9276,21 +9308,50 @@ uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) { switch(ueCtxtSetupRsp->protocolIEs.list.array[idx]->id) { + case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + { + cuUeF1apId = ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.GNB_CU_UE_F1AP_ID; + break; + } case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: { duUeF1apId = ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.GNB_DU_UE_F1AP_ID; ueCb = &duDb->ueCb[duUeF1apId-1]; + /* If ue context is not present in du db, then create UE context + * here. This flow is hit in case of UE handover where UE + * context is created before UE performs RACH on target DU */ + if(ueCb->gnbDuUeF1apId == 0) + { + /* 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.targetDuId = duId; + (duDb->numUe)++; + + ueCb->cellCb->ueCb[ueCb->cellCb->numUe] = ueCb; + ueCb->cellCb->numUe++; + } + break; + } + case ProtocolIE_ID_id_C_RNTI: + { + ueCb->crnti = ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.C_RNTI; break; } case ProtocolIE_ID_id_DRBs_Setup_List: { /* Adding Tunnels for successful DRB */ - procDrbSetupList(&ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.DRBs_Setup_List); + procDrbSetupList(duId, ueCb, &ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.DRBs_Setup_List); break; } case ProtocolIE_ID_id_DUtoCURRCInformation: { DU_LOG("\nINFO --> Received Du to Cu RRC Information "); + duToCuRrcContainer = &ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.\ + DUtoCURRCInformation.cellGroupConfig; if((extractDuToCuRrcCont(ueCb, ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.\ DUtoCURRCInformation.cellGroupConfig)) != ROK) { @@ -9301,7 +9362,69 @@ uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) } } } - ueCb->f1apMsgDb.dlRrcMsgCount++; /* keeping DL RRC Msg Count */ + + /* 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) + { + 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++) + { + /* 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) + { + for(ueIdx = 0; ueIdx < MAX_NUM_UE; 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.sourceDuId = srcDuDb->duId; + + /* 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; + } + 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) + { + DU_LOG("\nINFO --> F1AP: Failed to build and send DL RRC MSG for RRC reconfiguration"); + return RFAILED; + } + } + return ROK; } @@ -9323,12 +9446,12 @@ uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) uint8_t procUlRrcMsg(uint32_t duId, F1AP_PDU_t *f1apMsg) { - uint8_t idx, ret, srbId, rrcMsgType, duIdx=0; - uint8_t cuUeF1apId, duUeF1apId; - uint8_t *rrcContainer = NULLP; - uint16_t rrcContLen; - DuDb *duDb; - CuUeCb *ueCb; + uint8_t idx = 0, ret = ROK, srbId = 0, rrcMsgType = 0, duIdx=0; + uint8_t *rrcContainer = NULLP; + uint16_t rrcContLen = 0; + uint32_t cuUeF1apId = 0, duUeF1apId = 0; + DuDb *duDb = NULLP; + CuUeCb *ueCb = NULLP; ULRRCMessageTransfer_t *ulRrcMsg = NULLP; ret = ROK; @@ -9363,6 +9486,34 @@ uint8_t procUlRrcMsg(uint32_t duId, F1AP_PDU_t *f1apMsg) return RFAILED; } memcpy(rrcContainer, ulRrcMsg->protocolIEs.list.array[idx]->value.choice.RRCContainer.buf, rrcContLen); + + if(duDb->ueCb[duUeF1apId-1].state == UE_HANDOVER_IN_PROGRESS) + { + uint8_t ueIdx = 0; + uint8_t srcDuId = duDb->ueCb[duUeF1apId-1].hoInfo.sourceDuId; + 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(srcDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId) + { + 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; + } + } + return ret; + } break; } @@ -9377,37 +9528,30 @@ uint8_t procUlRrcMsg(uint32_t duId, F1AP_PDU_t *f1apMsg) ueCb = &duDb->ueCb[duUeF1apId-1]; ueCb->f1apMsgDb.dlRrcMsgCount++; rrcMsgType = setDlRRCMsgType(ueCb); - if(rrcMsgType == REGISTRATION_ACCEPT) + if(rrcMsgType == RRC_SETUP_COMPLETE) { - DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC Registration Accept"); + DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for NAS Security Mode Command"); ret = BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType); } - if(rrcMsgType == UE_CONTEXT_SETUP_REQ) + if(rrcMsgType == NAS_SECURITY_MODE_COMPLETE) { - DU_LOG("\nINFO --> F1AP: Sending Ue Context Setup Req"); - ret = BuildAndSendUeContextSetupReq(duId, ueCb, rrcContLen, rrcContainer); + DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC Security Mode Command"); + ret = BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType); } - if(rrcMsgType == SECURITY_MODE_COMPLETE) + else if(rrcMsgType == RRC_SECURITY_MODE_COMPLETE) { - /* To trigger the DL RRC Msg for RRC Reconfig */ - ueCb->f1apMsgDb.dlRrcMsgCount++; - rrcMsgType = setDlRRCMsgType(ueCb); - if(rrcMsgType == RRC_RECONFIG) - { - DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC Reconfig"); - BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType); - } + DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC Registration Accept"); + BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType); } - if(rrcMsgType == RRC_RECONFIG_COMPLETE) + else if(rrcMsgType == REGISTRATION_COMPLETE) { - ueCb->state = UE_ACTIVE; - ueCb->f1apMsgDb.dlRrcMsgCount++; - rrcMsgType = setDlRRCMsgType(ueCb); - if(rrcMsgType == UE_CONTEXT_MOD_REQ) - { - DU_LOG("\nINFO --> F1AP: Sending UE Context Modification Request"); - BuildAndSendUeContextModificationReq(duId, ueCb, RRC_RECONFIG_COMPLETE_IND); - } + DU_LOG("\nINFO --> F1AP: Sending Ue Context Setup Request"); + ret = BuildAndSendUeContextSetupReq(duId, ueCb); + } + else if(rrcMsgType == RRC_RECONFIG_COMPLETE) + { + DU_LOG("\nINFO --> F1AP: Sending UE Context Modification Request"); + BuildAndSendUeContextModificationReq(duId, ueCb, RRC_RECONFIG_COMPLETE_IND); } } return ret; @@ -9621,7 +9765,7 @@ void FreeUlTnlInfoforDrb2(ULUPTNLInformation_ToBeSetup_List_t *ulInfo) * RFAILED - failure * * ****************************************************************/ -uint8_t deleteEgtpTunnel(uint8_t *buf) +uint8_t deleteEgtpTunnel(uint32_t duId, uint8_t *buf) { uint32_t teId = 0; EgtpTnlEvt tnlEvt; @@ -9636,7 +9780,7 @@ uint8_t deleteEgtpTunnel(uint8_t *buf) tnlEvt.action = EGTP_TNL_MGMT_DEL; tnlEvt.lclTeid = teId; tnlEvt.remTeid = teId; - if((cuEgtpTnlMgmtReq(tnlEvt)) != ROK) + if((cuEgtpTnlMgmtReq(duId, tnlEvt)) != ROK) { DU_LOG("\nERROR --> EGTP : Failed to delete tunnel Id %d", teId); } @@ -9659,7 +9803,7 @@ uint8_t deleteEgtpTunnel(uint8_t *buf) * RFAILED - failure * * ****************************************************************/ -uint8_t BuildUlTnlInfoforSetupMod(uint8_t ueId, uint8_t drbId, TnlInfo *ulTnlInfo, ULUPTNLInformation_ToBeSetup_List_t *ulInfo, uint8_t actionType) +uint8_t BuildUlTnlInfoforSetupMod(uint32_t duId, uint8_t ueId, uint8_t drbId, TnlInfo *ulTnlInfo, ULUPTNLInformation_ToBeSetup_List_t *ulInfo, uint8_t actionType) { uint8_t arrIdx; uint8_t ulCnt; @@ -9864,7 +10008,7 @@ void FreeDrbItem(DRBs_ToBeSetupMod_Item_t *drbItem) * * ****************************************************************/ -uint8_t FillDrbItemToSetupMod(CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeSetupMod_Item_t *drbItem) +uint8_t FillDrbItemToSetupMod(uint32_t duId, CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeSetupMod_Item_t *drbItem) { uint8_t ret = ROK; @@ -9944,7 +10088,7 @@ uint8_t FillDrbItemToSetupMod(CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeSetupMod_It } /*ULUPTNLInformation To Be Setup List*/ - ret = BuildUlTnlInfoforSetupMod(ueCb->gnbCuUeF1apId, drbItem->dRBID, &ueCb->drbList[ueCb->numDrb].ulUpTnlInfo, \ + ret = BuildUlTnlInfoforSetupMod(duId, ueCb->gnbCuUeF1apId, drbItem->dRBID, &ueCb->drbList[ueCb->numDrb].ulUpTnlInfo, \ &drbItem->uLUPTNLInformation_ToBeSetup_List, ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item); if(ret != ROK) { @@ -9977,13 +10121,13 @@ uint8_t FillDrbItemToSetupMod(CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeSetupMod_It * * ****************************************************************/ -uint8_t FillDrbItemList(CuUeCb *ueCb, uint8_t arrIdx, struct DRBs_ToBeSetupMod_ItemIEs *drbItemIe) +uint8_t FillDrbItemList(uint32_t duId, CuUeCb *ueCb, uint8_t arrIdx, struct DRBs_ToBeSetupMod_ItemIEs *drbItemIe) { drbItemIe->id = ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item; drbItemIe->criticality = Criticality_reject; drbItemIe->value.present = DRBs_ToBeSetupMod_ItemIEs__value_PR_DRBs_ToBeSetupMod_Item; - if(FillDrbItemToSetupMod(ueCb, arrIdx, (&(drbItemIe->value.choice.DRBs_ToBeSetupMod_Item))) != ROK) + if(FillDrbItemToSetupMod(duId, ueCb, arrIdx, (&(drbItemIe->value.choice.DRBs_ToBeSetupMod_Item))) != ROK) { DU_LOG("\nERROR --> F1AP : FillDrbItemToSetupMod failed"); return RFAILED; @@ -10047,7 +10191,7 @@ void FreeDrbToBeSetupModList(DRBs_ToBeSetupMod_List_t *drbSet) * * ****************************************************************/ -uint8_t BuildDrbToBeSetupList(CuUeCb *ueCb, DRBs_ToBeSetupMod_List_t *drbSet) +uint8_t BuildDrbToBeSetupList(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetupMod_List_t *drbSet) { uint8_t ret = ROK; uint8_t arrIdx =0; @@ -10072,7 +10216,7 @@ uint8_t BuildDrbToBeSetupList(CuUeCb *ueCb, DRBs_ToBeSetupMod_List_t *drbSet) return RFAILED; } - ret = FillDrbItemList(ueCb, arrIdx, (DRBs_ToBeSetupMod_ItemIEs_t *)drbSet->list.array[arrIdx]); + ret = FillDrbItemList(duId, ueCb, arrIdx, (DRBs_ToBeSetupMod_ItemIEs_t *)drbSet->list.array[arrIdx]); if(ret != ROK) { DU_LOG("\nERROR --> F1AP : FillDrbItemList failed"); @@ -10099,7 +10243,7 @@ uint8_t BuildDrbToBeSetupList(CuUeCb *ueCb, DRBs_ToBeSetupMod_List_t *drbSet) * * ****************************************************************/ -uint8_t FillDrbToBeModItem(CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeModified_Item_t *drbItem) +uint8_t FillDrbToBeModItem(uint32_t duId, CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeModified_Item_t *drbItem) { uint8_t ret = ROK; uint drbIdx=0; @@ -10195,7 +10339,7 @@ uint8_t FillDrbToBeModItem(CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeModified_Item_ }/* End of QoS */ /*ULUPTNLInformation To Be Setup List*/ - ret = BuildUlTnlInfoforSetupMod(ueCb->gnbCuUeF1apId, drbItem->dRBID, &drbToBeMod->ulUpTnlInfo, &drbItem->uLUPTNLInformation_ToBeSetup_List,\ + ret = BuildUlTnlInfoforSetupMod(duId, ueCb->gnbCuUeF1apId, drbItem->dRBID, &drbToBeMod->ulUpTnlInfo, &drbItem->uLUPTNLInformation_ToBeSetup_List,\ ProtocolIE_ID_id_DRBs_ToBeModified_Item); if(ret != ROK) { @@ -10222,12 +10366,12 @@ uint8_t FillDrbToBeModItem(CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeModified_Item_ * * ****************************************************************/ -uint8_t FillDrbToBeModItemList(CuUeCb *ueCb, uint8_t arrIdx, struct DRBs_ToBeModified_ItemIEs *drbItemIe) +uint8_t FillDrbToBeModItemList(uint32_t duId, CuUeCb *ueCb, uint8_t arrIdx, struct DRBs_ToBeModified_ItemIEs *drbItemIe) { drbItemIe->id = ProtocolIE_ID_id_DRBs_ToBeModified_Item; drbItemIe->criticality = Criticality_reject; drbItemIe->value.present = DRBs_ToBeModified_ItemIEs__value_PR_DRBs_ToBeModified_Item; - if(FillDrbToBeModItem(ueCb, arrIdx, &(drbItemIe->value.choice.DRBs_ToBeModified_Item)) != ROK) + if(FillDrbToBeModItem(duId, ueCb, arrIdx, &(drbItemIe->value.choice.DRBs_ToBeModified_Item)) != ROK) { DU_LOG("\nERROR --> F1AP : FillDrbToBeModItem failed"); return RFAILED; @@ -10253,7 +10397,7 @@ uint8_t FillDrbToBeModItemList(CuUeCb *ueCb, uint8_t arrIdx, struct DRBs_ToBeMod * * ****************************************************************/ -uint8_t BuildDrbToBeModifiedList(CuUeCb *ueCb, DRBs_ToBeModified_List_t *drbSet) +uint8_t BuildDrbToBeModifiedList(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeModified_List_t *drbSet) { uint8_t ret = ROK; uint8_t arrIdx =0; @@ -10277,7 +10421,7 @@ uint8_t BuildDrbToBeModifiedList(CuUeCb *ueCb, DRBs_ToBeModified_List_t *drbSet) return RFAILED; } - ret = FillDrbToBeModItemList(ueCb, arrIdx, (DRBs_ToBeModified_ItemIEs_t *)drbSet->list.array[arrIdx]); + ret = FillDrbToBeModItemList(duId, ueCb, arrIdx, (DRBs_ToBeModified_ItemIEs_t *)drbSet->list.array[arrIdx]); if(ret != ROK) { DU_LOG("\nERROR --> F1AP : FillDrbToBeModItemList failed"); @@ -10503,7 +10647,6 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt CuUeCb *ueCb = (CuUeCb *)cuUeCb; F1AP_PDU_t *f1apMsg = NULLP; UEContextModificationRequest_t *ueContextModifyReq = NULLP; - action =RESTART_DATA_TX; asn_enc_rval_t encRetVal; DU_LOG("\nINFO --> F1AP : Building Ue context modification request\n"); while(1) @@ -10581,7 +10724,7 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject; ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present =\ UEContextModificationRequestIEs__value_PR_DRBs_ToBeSetupMod_List; - ret = BuildDrbToBeSetupList(ueCb, &(ueContextModifyReq->protocolIEs.list.array[ieIdx]->\ + ret = BuildDrbToBeSetupList(duId, ueCb, &(ueContextModifyReq->protocolIEs.list.array[ieIdx]->\ value.choice.DRBs_ToBeSetupMod_List)); /* DRB to be modified list */ @@ -10590,7 +10733,7 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject; ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present =\ UEContextModificationRequestIEs__value_PR_DRBs_ToBeModified_List; - ret = BuildDrbToBeModifiedList(ueCb, &(ueContextModifyReq->protocolIEs.list.array[ieIdx]->\ + ret = BuildDrbToBeModifiedList(duId, ueCb, &(ueContextModifyReq->protocolIEs.list.array[ieIdx]->\ value.choice.DRBs_ToBeModified_List)); /* TODO: DRB to be release list */ @@ -10643,6 +10786,7 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.TransmissionActionIndicator = \ TransmissionActionIndicator_restart; } + ieIdx++; ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_RRCContainer; ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject; @@ -10679,10 +10823,15 @@ uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxt else { DU_LOG("\nDEBUG --> F1AP : Created APER encodedbuffer for ueContextModifyReq\n"); +#if 0 + /* This for loop was going into an infinite loop even though encBufSize + * has a small value. Hence commented this + */ for(ieIdx=0; ieIdx< encBufSize; ieIdx++) { DU_LOG("%x",encBuf[ieIdx]); } +#endif } /* TODO : Hardcoding DU ID to 1 for messages other than F1 Setup Response. This will be made generic in future gerrit */ @@ -10993,8 +11142,7 @@ uint8_t procGnbDuUpdate(uint32_t duId, F1AP_PDU_t *f1apMsg) struct Served_Cells_To_Delete_ItemIEs *deleteItemIe = \ (struct Served_Cells_To_Delete_ItemIEs *)duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.\ Served_Cells_To_Delete_List.list.array[0]; - nrCellId = deleteItemIe->value.choice.Served_Cells_To_Delete_Item.oldNRCGI.nRCellIdentity.buf[4] >>\ - deleteItemIe->value.choice.Served_Cells_To_Delete_Item.oldNRCGI.nRCellIdentity.bits_unused; + bitStringToInt(&deleteItemIe->value.choice.Served_Cells_To_Delete_Item.oldNRCGI.nRCellIdentity, &nrCellId); cellToBeDelete = true; break; } @@ -11025,13 +11173,14 @@ uint8_t procGnbDuUpdate(uint32_t duId, F1AP_PDU_t *f1apMsg) { SEARCH_DU_DB(duIdx, duId, duDb); SEARCH_CELL_DB(cellIdx, duDb, nrCellId, cellCb); - for(ueIdx = 0; ueIdx < cellCb->numUe; ueIdx++) + if(cellCb->numUe == 0) { - CU_FREE(cellCb->ueCb[ueIdx]->f1apMsgDb.duToCuContainer.buf, cellCb->ueCb[ueIdx]->f1apMsgDb.duToCuContainer.size); - memset(cellCb->ueCb[ueIdx], 0, sizeof(CuUeCb)); + memset(cellCb, 0, sizeof(CuCellCb)); + duDb->numCells--; } + else + cellCb->cellStatus = CELL_DELETION_IN_PROGRESS; } - return ROK; } @@ -11146,7 +11295,7 @@ uint8_t procSrbSetupModList(CuUeCb *ueCb, SRBs_SetupMod_List_t *srbSetupList) * RFAILED - failure * * ****************************************************************/ -uint8_t procDrbSetupModList(CuUeCb *ueCb, DRBs_SetupMod_List_t *drbSetupList) +uint8_t procDrbSetupModList(uint32_t duId, CuUeCb *ueCb, DRBs_SetupMod_List_t *drbSetupList) { uint8_t arrIdx = 0, drbIdx; uint32_t teId = 0; @@ -11175,7 +11324,7 @@ uint8_t procDrbSetupModList(CuUeCb *ueCb, DRBs_SetupMod_List_t *drbSetupList) teId = extractTeId(&drbItemIe->value.choice.DRBs_SetupMod_Item.dLUPTNLInformation_ToBeSetup_List); if(teId > 0) { - if(addDrbTunnels(teId)== ROK) + if(addDrbTunnels(duId, teId)== ROK) { DU_LOG("\nDEBUG --> EGTP: Tunnel Added for TeId %d", teId); } @@ -11265,9 +11414,10 @@ uint8_t procServedCellPlmnList(ServedPLMNs_List_t *srvPlmn) * ****************************************************************/ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) { - uint8_t idx=0, duIdx=0, duUeF1apId; - DuDb *duDb; - CuUeCb *ueCb; + uint8_t idx=0, duIdx=0; + uint8_t duUeF1apId = 0, cuUeF1apId = 0; + DuDb *duDb = NULLP; + CuUeCb *ueCb = NULLP; UEContextModificationResponse_t *ueCtxtModRsp = NULLP; SEARCH_DU_DB(duIdx, duId, duDb); @@ -11277,6 +11427,11 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) { switch(ueCtxtModRsp->protocolIEs.list.array[idx]->id) { + case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + { + cuUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_CU_UE_F1AP_ID; + break; + } case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: { duUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_DU_UE_F1AP_ID; @@ -11286,7 +11441,7 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) case ProtocolIE_ID_id_DRBs_SetupMod_List: { /* Adding Tunnels for successful DRB */ - procDrbSetupModList(ueCb, &ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.DRBs_SetupMod_List); + procDrbSetupModList(duId, ueCb, &ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.DRBs_SetupMod_List); break; } @@ -11309,10 +11464,41 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) } } + + /* If UE is in handover and UE context is not yet created at target DU, then send + * UE context setup request to target DU */ if(ueCb->state == UE_HANDOVER_IN_PROGRESS) { - BuildAndSendUeContextSetupReq(ueCb->hoInfo.targetDuId, ueCb, 0, NULLP); - return ROK; + uint8_t ueIdx = 0; + DuDb *tgtDuDb = NULLP; + CuUeCb *ueCbInTgtDu = NULLP; + + SEARCH_DU_DB(duIdx, ueCb->hoInfo.targetDuId, 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++) + { + if(tgtDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId) + { + ueCbInTgtDu = &tgtDuDb->ueCb[ueIdx]; + break; + } + } + + /* If UE context is not found in Target DU DU, send UE context setup + * request */ + if(ueCbInTgtDu == NULLP) + { + if((BuildAndSendUeContextSetupReq(ueCb->hoInfo.targetDuId, ueCb)) != ROK) + { + DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextSetupReq"); + return RFAILED; + } + } + } } return ROK; @@ -11337,7 +11523,8 @@ uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg) void procF1SetupReq(uint32_t *destDuId, F1AP_PDU_t *f1apMsg) { uint8_t ieIdx = 0, plmnidx=0, duIdx = 0, ret=ROK, cellIdx = 0; - uint32_t duId = 0, nrCellId = 0; + uint32_t duId = 0; + uint64_t nrCellId = 0; DuDb *duDb = NULLP; CuCellCb *cellCb = NULLP; BIT_STRING_t nrcellIdentity; @@ -11357,13 +11544,11 @@ void procF1SetupReq(uint32_t *destDuId, F1AP_PDU_t *f1apMsg) if(duDb == NULLP) { duDb = &cuCb.duInfo[cuCb.numDu]; - memset(duDb, 0, sizeof(DuDb)); - duDb->duId = duId; cuCb.numDu++; - *destDuId = duId; } - else - return; + memset(duDb, 0, sizeof(DuDb)); + duDb->duId = duId; + *destDuId = duId; break; } case ProtocolIE_ID_id_gNB_DU_Name: @@ -11387,14 +11572,15 @@ void procF1SetupReq(uint32_t *destDuId, F1AP_PDU_t *f1apMsg) srvCellItem = &duServedCell->list.array[plmnidx]->value.choice.GNB_DU_Served_Cells_Item; ret = procServedCellPlmnList(&srvCellItem->served_Cell_Information.servedPLMNs); memcpy(&nrcellIdentity, &srvCellItem->served_Cell_Information.nRCGI.nRCellIdentity, sizeof(BIT_STRING_t)); - - nrCellId = nrcellIdentity.buf[4] >> nrcellIdentity.bits_unused; + + bitStringToInt(&nrcellIdentity, &nrCellId); SEARCH_CELL_DB(cellIdx, duDb, nrCellId, cellCb); if(cellCb == NULLP) { cellCb = &duDb->cellCb[duDb->numCells]; memset(cellCb, 0, sizeof(CuCellCb)); cellCb->nrCellId = nrCellId; + cellCb->cellStatus = CELL_ACTIVE; duDb->numCells++; } } @@ -11415,6 +11601,437 @@ void procF1SetupReq(uint32_t *destDuId, F1AP_PDU_t *f1apMsg) } } +/**************************************************************** +* +* @brief processing of UE Context Release Complete +* +* @details +* +* Function : procUeContextReleaseComplete +* +* Functionality: +* - processing of UE Context Release Complete +* +* @params[in] F1AP_PDU_t *f1apMsg +* @return ROK - success +* RFAILED - failure +* +* ****************************************************************/ +void procUeContextReleaseComplete(uint32_t duId, F1AP_PDU_t *f1apMsg) +{ + uint8_t duIdx = 0, ieIdx = 0, ueIdx = 0, drbIdx = 0; + uint8_t gnbDuUeF1apId = 0, gnbCuUeF1apId = 0; + DuDb *duDb = NULLP; + CuUeCb *ueCb = NULLP; + UEContextReleaseComplete_t *ueReleaseComplete = NULLP; + + SEARCH_DU_DB(duIdx, duId, duDb); + if(!duDb) + { + DU_LOG("\nERROR --> F1AP : No entry found for DU ID [%d]", duId); + return; + } + + ueReleaseComplete = &f1apMsg->choice.successfulOutcome->value.choice.UEContextReleaseComplete; + for(ieIdx=0; ieIdx < ueReleaseComplete->protocolIEs.list.count; ieIdx++) + { + switch(ueReleaseComplete->protocolIEs.list.array[ieIdx]->id) + { + case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + { + gnbCuUeF1apId = ueReleaseComplete->protocolIEs.list.array[ieIdx]->value.choice.GNB_CU_UE_F1AP_ID; + break; + } + case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + { + gnbDuUeF1apId = ueReleaseComplete->protocolIEs.list.array[ieIdx]->value.choice.GNB_DU_UE_F1AP_ID; + ueCb = &duDb->ueCb[gnbDuUeF1apId-1]; + for(ueIdx = 0; ueIdx cellCb && ueCb->cellCb->ueCb[ueIdx]) + { + if((ueCb->cellCb->ueCb[ueIdx]->gnbCuUeF1apId == gnbCuUeF1apId) && + (ueCb->cellCb->ueCb[ueIdx]->gnbDuUeF1apId == gnbDuUeF1apId)) + { + for(drbIdx = 0; drbIdx < ueCb->numDrb; drbIdx++) + { + deleteEgtpTunnel(duId, ueCb->drbList[drbIdx].dlUpTnlInfo.teId); + } + ueCb->cellCb->ueCb[ueIdx] = NULLP; + ueCb->cellCb->numUe--; + if((ueCb->cellCb->numUe == 0) && (ueCb->cellCb->cellStatus == CELL_DELETION_IN_PROGRESS)) + { + memset(ueCb->cellCb, 0, sizeof(CuCellCb)); + duDb->numCells--; + } + break; + } + } + } + memset(ueCb, 0, sizeof(CuUeCb)); + duDb->numUe--; + break; + } + } + } +} + +/******************************************************************* + * + * @brief Builds the Paging cell list + * + * @details + * + * Function : BuildPagingCellList + * + * Functionality: Build the paging cell list + * + * @params[in] PagingCell_list_t *pagingCelllist, + * + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t BuildPagingCellList(PagingCell_list_t *pagingCelllist, uint8_t numCells, CuCellCb *cellCb) +{ + uint8_t cellIdx =0; + PagingCell_ItemIEs_t *pagingCellItemIes; + PagingCell_Item_t *pagingCellItem; + + pagingCelllist->list.count = numCells; + pagingCelllist->list.size = pagingCelllist->list.count * (sizeof(PagingCell_ItemIEs_t*)); + CU_ALLOC(pagingCelllist->list.array, pagingCelllist->list.size); + if(pagingCelllist->list.array == NULLP) + { + DU_LOG("\nERROR --> F1AP : BuildPagingCellList(): Memory allocation failed "); + return RFAILED; + } + + for(cellIdx = 0; cellIdx < pagingCelllist->list.count; cellIdx++) + { + CU_ALLOC(pagingCelllist->list.array[cellIdx], sizeof(PagingCell_ItemIEs_t)); + if(pagingCelllist->list.array[cellIdx] == NULLP) + { + DU_LOG("\nERROR --> F1AP : BuildPagingCellList(): Memory allocation failed "); + return RFAILED; + } + } + + for(cellIdx = 0; cellIdx < pagingCelllist->list.count; cellIdx++) + { + pagingCellItemIes = (PagingCell_ItemIEs_t *)pagingCelllist->list.array[cellIdx]; + pagingCellItemIes->id = ProtocolIE_ID_id_PagingCell_Item; + pagingCellItemIes->criticality = Criticality_ignore; + pagingCellItemIes->value.present = PagingCell_ItemIEs__value_PR_PagingCell_Item; + pagingCellItem = &pagingCellItemIes->value.choice.PagingCell_Item; + + /* Fill NrCgi Information */ + BuildNrcgi(&pagingCellItem->nRCGI, cellCb[cellIdx].nrCellId); + } + + return ROK; +} + +/******************************************************************* + * + * @brief Deallocation of memory allocated in paging msg + * + * @details + * + * Function :FreePagingMsg + * + * Functionality: Deallocation of memory allocated in paging msg + * + * @params[in] F1AP_PDU_t *f1apMsg + * + * @return void + * + * ****************************************************************/ +void FreePagingMsg(F1AP_PDU_t *f1apMsg) +{ + uint8_t ieIdx, cellIdx; + Paging_t *paging; + PagingCell_ItemIEs_t *pagingCellItemIes; + PagingCell_Item_t *pagingCellItem; + PagingCell_list_t *pagingCelllist; + + if(f1apMsg) + { + if(f1apMsg->choice.initiatingMessage) + { + paging = &f1apMsg->choice.initiatingMessage->value.choice.Paging; + if(paging->protocolIEs.list.array) + { + for(ieIdx=0 ; ieIdxprotocolIEs.list.count; ieIdx++) + { + if(paging->protocolIEs.list.array[ieIdx]) + { + switch(paging->protocolIEs.list.array[ieIdx]->id) + { + case ProtocolIE_ID_id_UEIdentityIndexValue: + { + CU_FREE(paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.choice.indexLength10.buf,\ + paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.choice.indexLength10.size); + break; + } + + case ProtocolIE_ID_id_PagingIdentity: + { + if(paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.present == PagingIdentity_PR_cNUEPagingIdentity) + { + if(paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity) + { + if(paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->present == CNUEPagingIdentity_PR_fiveG_S_TMSI) + { + CU_FREE(paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI.buf,\ + paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI.size); + } + CU_FREE(paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity,\ + sizeof(struct CNUEPagingIdentity)); + } + } + break; + } + + case ProtocolIE_ID_id_PagingCell_List: + { + pagingCelllist = &paging->protocolIEs.list.array[ieIdx]->value.choice.PagingCell_list; + if(pagingCelllist->list.array) + { + for(cellIdx = 0; cellIdx < pagingCelllist->list.count; cellIdx++) + { + if(pagingCelllist->list.array[cellIdx]) + { + pagingCellItemIes = (PagingCell_ItemIEs_t *)pagingCelllist->list.array[cellIdx]; + if(pagingCellItemIes->id == ProtocolIE_ID_id_PagingCell_Item) + { + pagingCellItem = &pagingCellItemIes->value.choice.PagingCell_Item; + CU_FREE(pagingCellItem->nRCGI.pLMN_Identity.buf, pagingCellItem->nRCGI.pLMN_Identity.size); + CU_FREE(pagingCellItem->nRCGI.nRCellIdentity.buf, pagingCellItem->nRCGI.nRCellIdentity.size); + } + CU_FREE(pagingCelllist->list.array[cellIdx], sizeof(PagingCell_ItemIEs_t)); + } + } + CU_FREE(pagingCelllist->list.array, pagingCelllist->list.size); + } + break; + } + } + CU_FREE(paging->protocolIEs.list.array[ieIdx], sizeof(Paging_t)); + } + } + CU_FREE(paging->protocolIEs.list.array, paging->protocolIEs.list.size); + } + CU_FREE(f1apMsg->choice.initiatingMessage, sizeof(InitiatingMessage_t)); + } + CU_FREE(f1apMsg, sizeof(F1AP_PDU_t)); + } +} +/******************************************************************* + * + * @brief Builds and sends the paging message if UE is in idle mode + * + * @details + * + * Function : BuildAndSendPagingMsg + * + * Functionality: Builds and sends the paging message + * + * @params[in] uint32_t duId, uint8_t gsTmsi + * + * @return ROK - success + * RFAILED - failure + * + * ****************************************************************/ +uint8_t BuildAndSendPagingMsg(uint64_t gsTmsi, uint8_t duId) +{ + bool memAllocFailed = false; + uint8_t ieIdx = 0, elementCnt = 0, ret = RFAILED; + uint16_t ueId = 0, duIdx = 0; + + /*As per 38.473 Sec 9.3.1.39, UE Identity Index Value (10bits) > 2 Bytes + 6 Unused Bits + *5G-S-TMSI :48 Bits >> 6 Bytes and 0 UnusedBits */ + uint8_t totalByteInUeId = 2, totalByteInTmsi = 6; + uint8_t unusedBitsInUeId = 6, unusedBitsInTmsi = 0; + + F1AP_PDU_t *f1apMsg = NULLP; + Paging_t *paging = NULLP; + DuDb *duDb; + asn_enc_rval_t encRetVal; + + DU_LOG("\nINFO --> F1AP : Building PAGING Message command\n"); + + SEARCH_DU_DB(duIdx, duId, duDb); + if(duDb == NULLP) + { + DU_LOG("\nERROR --> F1AP : BuildAndSendPagingMsg(): DuDb is empty"); + return ret; + } + + while(true) + { + CU_ALLOC(f1apMsg, sizeof(F1AP_PDU_t)); + if(f1apMsg == NULLP) + { + DU_LOG("\nERROR --> F1AP : BuildAndSendPagingMsg(): Memory allocation for F1AP-PDU"); + break; + } + + f1apMsg->present = F1AP_PDU_PR_initiatingMessage; + + CU_ALLOC(f1apMsg->choice.initiatingMessage, sizeof(InitiatingMessage_t)); + if(f1apMsg->choice.initiatingMessage == NULLP) + { + DU_LOG("\nERROR --> F1AP : BuildAndSendPagingMsg(): Memory allocation for F1AP-PDU failed "); + break; + } + f1apMsg->choice.initiatingMessage->procedureCode = ProcedureCode_id_Paging; + f1apMsg->choice.initiatingMessage->criticality = Criticality_reject; + f1apMsg->choice.initiatingMessage->value.present = InitiatingMessage__value_PR_Paging; + + paging = &f1apMsg->choice.initiatingMessage->value.choice.Paging; + + elementCnt = 5; + paging->protocolIEs.list.count = elementCnt; + paging->protocolIEs.list.size = elementCnt * sizeof(Paging_t*); + + /* Initialize the Paging Message members */ + CU_ALLOC(paging->protocolIEs.list.array, paging->protocolIEs.list.size); + if(paging->protocolIEs.list.array == NULLP) + { + DU_LOG("\nERROR --> F1AP : BuildAndSendPagingMsg():Memory allocation failed"); + break; + } + + for(ieIdx=0 ; ieIdxprotocolIEs.list.array[ieIdx], sizeof(Paging_t)); + if(paging->protocolIEs.list.array[ieIdx] == NULLP) + { + DU_LOG("\nERROR --> F1AP : BuildAndSendPagingMsg(): Memory allocation failed "); + memAllocFailed = true; + break; + } + } + + if(memAllocFailed == true) + { + break; + } + + /* UE Identity Index Value */ + ieIdx=0; + paging->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_UEIdentityIndexValue; + paging->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject; + paging->protocolIEs.list.array[ieIdx]->value.present = PagingIEs__value_PR_UEIdentityIndexValue; + paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.present = UEIdentityIndexValue_PR_indexLength10; + paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.choice.indexLength10.size = totalByteInUeId*sizeof(uint8_t); + CU_ALLOC(paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.choice.indexLength10.buf,\ + paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.choice.indexLength10.size); + if(paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.choice.indexLength10.buf == NULLP) + { + DU_LOG("\nERROR --> F1AP : BuildAndSendPagingMsg(): Memory allocation failed "); + break; + } + + /*As per 3gpp Spec 38.304 Sec 7.1: UE_ID: 5G-S-TMSI mod 1024*/ + ueId = gsTmsi % 1024; + fillBitString(&paging->protocolIEs.list.array[ieIdx]->value.choice.UEIdentityIndexValue.choice.indexLength10, unusedBitsInUeId, totalByteInUeId, ueId); + + /* Paging Identity */ + ieIdx++; + paging->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_PagingIdentity; + paging->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject; + paging->protocolIEs.list.array[ieIdx]->value.present = PagingIEs__value_PR_PagingIdentity; + paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.present = \ + PagingIdentity_PR_cNUEPagingIdentity; + CU_ALLOC(paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity, \ + sizeof(struct CNUEPagingIdentity)); + if(!paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity) + { + DU_LOG("\nERROR --> F1AP : BuildAndSendPagingMsg(): Memory allocation failed "); + break; + } + + paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->present = \ + CNUEPagingIdentity_PR_fiveG_S_TMSI; + + paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI.size = totalByteInTmsi*sizeof(uint8_t); + CU_ALLOC(paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI.buf,\ + paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI.size); + if(!paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI.buf) + { + DU_LOG("\nERROR --> F1AP : BuildAndSendPagingMsg(): Memory allocation failed "); + break; + } + + fillBitString(&paging->protocolIEs.list.array[ieIdx]->value.choice.PagingIdentity.choice.cNUEPagingIdentity->choice.fiveG_S_TMSI,\ + unusedBitsInTmsi, totalByteInTmsi, gsTmsi); + + /* Paging Drx */ + ieIdx++; + paging->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_PagingDRX; + paging->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore; + paging->protocolIEs.list.array[ieIdx]->value.present = PagingIEs__value_PR_PagingDRX; + paging->protocolIEs.list.array[ieIdx]->value.choice.PagingDRX = PagingDRX_v32; + + /* Paging Priority */ + ieIdx++; + paging->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_PagingPriority; + paging->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore; + paging->protocolIEs.list.array[ieIdx]->value.present = PagingIEs__value_PR_PagingPriority; + paging->protocolIEs.list.array[ieIdx]->value.choice.PagingPriority = PagingPriority_priolevel2; + + /* Paging Cell List */ + ieIdx++; + paging->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_PagingCell_List; + paging->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore; + paging->protocolIEs.list.array[ieIdx]->value.present = PagingIEs__value_PR_PagingCell_list; + if(BuildPagingCellList(&paging->protocolIEs.list.array[ieIdx]->value.choice.PagingCell_list, duDb->numCells, duDb->cellCb) != ROK) + { + DU_LOG("\nERROR --> F1AP : BuildAndSendPagingMsg(): Failed to build Paging cell list "); + break; + } + + xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg); + + /* Encode the UE Context Release Command type as APER */ + memset(encBuf, 0, ENC_BUF_MAX_LEN); + encBufSize = 0; + encRetVal = aper_encode(&asn_DEF_F1AP_PDU, 0, f1apMsg, PrepFinalEncBuf,\ + encBuf); + + /* Encode results */ + if(encRetVal.encoded == ENCODE_FAIL) + { + DU_LOG("\nERROR --> F1AP : Could not encode Release Command structure (at %s)\n",\ + encRetVal.failed_type ? encRetVal.failed_type->name : "unknown"); + break; + } + else + { + DU_LOG("\nDEBUG --> F1AP : Created APER encoded buffer for Paging\n"); + for(ieIdx=0; ieIdx< encBufSize; ieIdx++) + { + DU_LOG("%x",encBuf[ieIdx]); + } + } + + if(SendF1APMsg(CU_APP_MEM_REG, CU_POOL, duId) != ROK) + { + DU_LOG("\nERROR --> F1AP : Sending Ue context Release Command failed"); + break; + } + + ret = ROK; + break; + + } + + FreePagingMsg(f1apMsg); + return ret; +} + /******************************************************************* * * @brief Handles received F1AP message and sends back response @@ -11565,6 +12182,7 @@ void F1APMsgHdlr(uint32_t *duId, Buffer *mBuf) case SuccessfulOutcome__value_PR_UEContextReleaseComplete: { DU_LOG("\nINFO --> F1AP : UE Context release complete received"); + procUeContextReleaseComplete(*duId, f1apMsg); break; } default: