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)
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;
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);
{
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));
{
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*/
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);
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)
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;
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;
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;
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");
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");
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");
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");
}
/*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;
uint8_t ret = ROK;
uint8_t idx;
- /* UE Capabulity RAT Container List */
- CU_ALLOC(rrcMsg->uE_CapabilityRAT_ContainerList, sizeof(UE_CapabilityRAT_ContainerList_t));
- if(!rrcMsg->uE_CapabilityRAT_ContainerList)
+ if((ueCb->state != UE_HANDOVER_IN_PROGRESS) || ((ueCb->state == UE_HANDOVER_IN_PROGRESS) && (ueCb->hoInfo.HOType == Inter_DU_HO)))
{
- DU_LOG("\nERROR --> F1AP : Memory allocation for UE capability RAT container list failed");
- return RFAILED;
+ /* UE Capabulity RAT Container List */
+ CU_ALLOC(rrcMsg->uE_CapabilityRAT_ContainerList, sizeof(UE_CapabilityRAT_ContainerList_t));
+ if(!rrcMsg->uE_CapabilityRAT_ContainerList)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation for UE capability RAT container list failed");
+ return RFAILED;
+ }
+ ret = fillUeCapRatContListBuf(rrcMsg->uE_CapabilityRAT_ContainerList);
}
- ret = fillUeCapRatContListBuf(rrcMsg->uE_CapabilityRAT_ContainerList);
#if 0
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;
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)
{
* 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;
{
/* 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;
}
}
- /* 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);
}
}
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;
else if(action == RRC_RECONFIG_COMPLETE_IND)
elementCnt = 3;
else if((action == STOP_DATA_TX) || (action == RESTART_DATA_TX))
- elementCnt = 5;
+ {
+ if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
+ elementCnt = 5;
+ else
+ elementCnt = 4;
+ }
#ifdef NR_DRX
if(DRX_TO_BE_RELEASE && ueCb->drxCfgPresent)
}
/* RRC delivery status request */
- ieIdx++;
- ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_RRCDeliveryStatusRequest;
- ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore;
- ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = UEContextModificationRequestIEs__value_PR_RRCDeliveryStatusRequest;
- ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCDeliveryStatusRequest = RRCDeliveryStatusRequest_true;
+ if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
+ {
+ ieIdx++;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_RRCDeliveryStatusRequest;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = UEContextModificationRequestIEs__value_PR_RRCDeliveryStatusRequest;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCDeliveryStatusRequest = RRCDeliveryStatusRequest_true;
+ }
}
#ifdef NR_DRX
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;
}
}
}
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++)
{
{
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;
}
* 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
/*******************************************************************
*
- * @brief Handles received F1AP message and sends back response
+ * @brief Decode received character string into F1AP message
*
* @details
*
*
* 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)
{
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:
}
}/* End of switch(f1apMsg->present) */
+ CU_FREE(recvBuf, (Size)(recvBufLen));
} /* End of F1APMsgHdlr */
/**********************************************************************