X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=src%2Fcu_stub%2Fcu_f1ap_msg_hdl.c;h=7e1b9ac4245d3509ba3a9261061d0123353b20ab;hb=bd2905b5f651349abafb7934a952414d7c24e291;hp=601e18efaa036fb8ed8d2c9fd5e51993a4ffadc7;hpb=9f07d42c8d327e4009833fc4c673e4086c4e726e;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 601e18efa..7e1b9ac42 100644 --- a/src/cu_stub/cu_f1ap_msg_hdl.c +++ b/src/cu_stub/cu_f1ap_msg_hdl.c @@ -127,6 +127,8 @@ #include "MeasConfigRrc.h" #include "AS-Config.h" #include "RRCReconfiguration-v1530-IEs.h" +#include "CNUEPagingIdentity.h" +#include "PagingCell-Item.h" #include "cu_stub_sctp.h" #include "cu_stub_egtp.h" @@ -2115,7 +2117,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 +2137,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 +2550,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,7 +2662,7 @@ 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) { uint8_t idx = 0, extIeIdx = 0; uint8_t elementCnt = 0, drbCnt = 0; @@ -2758,10 +2759,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) { @@ -7402,7 +7403,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; @@ -9034,7 +9035,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; @@ -9181,7 +9182,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 +9195,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,7 +9218,7 @@ uint8_t addDrbTunnels(uint8_t teId) * RFAILED - failure * * ****************************************************************/ -uint8_t procDrbSetupList(DRBs_Setup_List_t *drbSetupList) +uint8_t procDrbSetupList(uint32_t duId, DRBs_Setup_List_t *drbSetupList) { uint8_t arrIdx = 0; uint32_t teId = 0; @@ -9234,7 +9235,7 @@ 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) + if(addDrbTunnels(duId, teId)== ROK) { DU_LOG("\nDEBUG --> EGTP: Tunnel Added for TeId %d", teId); } @@ -9264,9 +9265,10 @@ 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; + uint8_t duUeF1apId = 0, cuUeF1apId = 0; + DuDb *duDb = NULLP; + CuUeCb *ueCb = NULLP; UEContextSetupResponse_t *ueCtxtSetupRsp = NULLP; SEARCH_DU_DB(duIdx, duId, duDb); @@ -9276,16 +9278,43 @@ 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, &ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.DRBs_Setup_List); break; } case ProtocolIE_ID_id_DUtoCURRCInformation: @@ -9301,7 +9330,54 @@ 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; + if(BuildAndSendUeContextModificationReq(srcDuDb->duId, ueCbInSrcDu, STOP_DATA_TX) != ROK) + { + DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextModificationReq()"); + return RFAILED; + } + break; + } + } + } + if(srcDuDb && ueCbInSrcDu) + break; + } + } return ROK; } @@ -9621,7 +9697,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 +9712,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 +9735,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 +9940,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 +10020,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 +10053,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 +10123,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 +10148,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 +10175,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 +10271,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 +10298,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 +10329,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 +10353,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 +10579,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 +10656,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 +10665,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 */ @@ -11025,13 +11100,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 +11222,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 +11251,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 +11341,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 +11354,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 +11368,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 +11391,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, 0, NULLP)) != ROK) + { + DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextSetupReq"); + return RFAILED; + } + } + } } return ROK; @@ -11395,6 +11508,7 @@ void procF1SetupReq(uint32_t *destDuId, F1AP_PDU_t *f1apMsg) cellCb = &duDb->cellCb[duDb->numCells]; memset(cellCb, 0, sizeof(CuCellCb)); cellCb->nrCellId = nrCellId; + cellCb->cellStatus = CELL_ACTIVE; duDb->numCells++; } } @@ -11460,16 +11574,22 @@ void procUeContextReleaseComplete(uint32_t duId, F1AP_PDU_t *f1apMsg) { gnbDuUeF1apId = ueReleaseComplete->protocolIEs.list.array[ieIdx]->value.choice.GNB_DU_UE_F1AP_ID; ueCb = &duDb->ueCb[gnbDuUeF1apId-1]; - - for(ueIdx = 0; ueIdx < ueCb->cellCb->numUe; ueIdx++) + for(ueIdx = 0; ueIdx cellCb->ueCb[ueIdx]->gnbCuUeF1apId == gnbCuUeF1apId) && - (ueCb->cellCb->ueCb[ueIdx]->gnbDuUeF1apId == gnbDuUeF1apId)) + if(ueCb->cellCb && ueCb->cellCb->ueCb[ueIdx]) { - ueCb->cellCb->ueCb[ueIdx] = NULLP; - ueCb->cellCb->numUe--; - break; - + if((ueCb->cellCb->ueCb[ueIdx]->gnbCuUeF1apId == gnbCuUeF1apId) && + (ueCb->cellCb->ueCb[ueIdx]->gnbDuUeF1apId == gnbDuUeF1apId)) + { + 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)); @@ -11480,6 +11600,362 @@ void procUeContextReleaseComplete(uint32_t duId, F1AP_PDU_t *f1apMsg) } } +/******************************************************************* + * + * @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