for(indexTable = 0; indexTable < 3; indexTable++)
{
- if(freq < arfcnFreqTable[indexTable][0])
+ if(freq < (arfcnFreqTable[indexTable][0] * 1000))
{
arfcn = arfcnFreqTable[indexTable][3] + ((freq - (arfcnFreqTable[indexTable][2] * 1000)) / (arfcnFreqTable[indexTable][1]));
return (arfcn);
#define ODU_PRINT_MSG SPrntMsg
#define ODU_REM_PRE_MSG SRemPreMsg
#define ODU_REM_PRE_MSG_MULT SRemPreMsgMult
+#define ODU_REM_POST_MSG_MULT SRemPstMsgMult
#define ODU_REG_TMR_MT SRegTmrMt
#define ODU_SEGMENT_MSG SSegMsg
#define ODU_CAT_MSG SCatMsg
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 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;
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 */
/**********************************************************************
{
ueCb->state = UE_HANDOVER_IN_PROGRESS;
ueCb->hoInfo.HOType = Inter_DU_HO;
- ueCb->hoInfo.sourceId = sourceDuId;
- ueCb->hoInfo.targetId = targetDuId;
+ ueCb->hoInfo.srcNodeId = sourceDuId;
+ ueCb->hoInfo.tgtNodeId = targetDuId;
BuildAndSendUeContextModificationReq(sourceDuId, ueCb, QUERY_CONFIG);
}
* RFAILED - failure
*
* ****************************************************************/
-void initiateInterCuHandover(uint32_t sourceCuId, uint32_t targetCuId, uint32_t cuUeF1apId)
+void initiateInterCuHandover(uint32_t targetCuId, uint32_t cellId, uint32_t cuUeF1apId)
{
uint8_t duIdx, ueIdx;
CuUeCb *ueCb = NULLP;
- DU_LOG("\nINFO --> CU_STUB: Inter-CU Handover Started for ueId [%d] from CU ID [%d] to CU ID [%d]", \
- cuUeF1apId, sourceCuId, targetCuId);
+ DU_LOG("\nINFO --> CU_STUB: Inter-CU Handover Started for ueId [%d] to CU ID [%d]", \
+ cuUeF1apId, targetCuId);
for(duIdx = 0; duIdx < cuCb.numDu; duIdx++)
{
{
ueCb->state = UE_HANDOVER_IN_PROGRESS;
ueCb->hoInfo.HOType = Xn_Based_Inter_CU_HO;
- ueCb->hoInfo.sourceId = sourceCuId;
- ueCb->hoInfo.targetId = targetCuId;
+ ueCb->hoInfo.srcNodeId = cuCb.cuCfgParams.cuId;
+ ueCb->hoInfo.tgtNodeId = targetCuId;
+ ueCb->hoInfo.tgtCellId = cellId;
+ ueCb->hoInfo.cuUeF1apIdSrc = ueCb->gnbCuUeF1apId;
+
BuildAndSendUeContextModificationReq(cuCb.duInfo[duIdx].duId, ueCb, QUERY_CONFIG);
}
else
else if(ch == 'h')
{
HandoverType hoType;
- uint32_t sourceId, targetId, ueId;
+ uint32_t srcNodeId, tgtNodeId, targetCellId, ueId;
DU_LOG("\n\nChoose the type of handover to initiate : \nEnter 1 for Inter-CU Handover over Xn interface\nEnter 2 for Inter-DU Handover\n");
scanf("%d", &hoType);
if(hoType == Xn_Based_Inter_CU_HO)
{
- DU_LOG("\nEnter Source CU ID for Inter-CU Handover : ");
- scanf("%d", &sourceId);
DU_LOG("\nEnter Target CU ID for Inter-CU Handover : ");
- scanf("%d", &targetId);
+ scanf("%d", &tgtNodeId);
+ DU_LOG("\nEnter Target Physical Cell ID for Inter-CU Handover : ");
+ scanf("%d", &targetCellId);
DU_LOG("\nEnter CU UE F1AP ID to be handed over : ");
scanf("%d", &ueId);
- initiateInterCuHandover(sourceId, targetId, ueId);
+ initiateInterCuHandover(tgtNodeId, targetCellId, ueId);
}
else if(hoType == Inter_DU_HO)
{
DU_LOG("\nEnter Source DU ID for Inter-DU Handover : ");
- scanf("%d", &sourceId);
+ scanf("%d", &srcNodeId);
DU_LOG("\nEnter Target DU ID for Inter-DU Handover : ");
- scanf("%d", &targetId);
+ scanf("%d", &tgtNodeId);
DU_LOG("\nEnter DU UE F1AP ID to be handed over : ");
scanf("%d", &ueId);
- initiateInterDuHandover(sourceId, targetId, ueId);
+ initiateInterDuHandover(srcNodeId, tgtNodeId, ueId);
}
}
/* Start Idle mode paging when 'p' is received from console input */
{
XN_SETUP_REQ,
XN_SETUP_RSP,
- HO_REQ
+ HO_REQ,
+ HO_REQ_ACK,
+ UE_CTXT_REL
}XnEventType;
typedef enum
typedef struct handoverInfo
{
HandoverType HOType;
- uint32_t sourceId; /* If Inter_DU HO, this is Source DU ID. In case of Inter CU HO, this is Source CU ID */
- uint32_t targetId; /* If Inter_DU HO, this is Taregt DU ID. In case of Inter CU HO, this is Target CU ID */
+ uint32_t srcNodeId; /* If Inter_DU HO, this is Source DU ID. In case of Inter CU HO, this is Source CU ID */
+ uint32_t tgtNodeId; /* If Inter_DU HO, this is Taregt DU ID. In case of Inter CU HO, this is Target CU ID */
+ uint32_t tgtCellId; /* Cell Id in target node to which UE is to be handed over */
+ uint8_t cuUeF1apIdSrc; /* Used for Inter-CU HO. CU UE F1AP ID of UE in source CU */
+ uint8_t cuUeF1apIdTgt; /* Used for Inter-CU HO. CU UE F1AP ID of UE in target CU */
}HandoverInfo;
typedef struct dlAmCfg
CuCellCb cellCb[MAX_NUM_CELL];
uint8_t numUe;
CuUeCb ueCb[MAX_NUM_CELL * MAX_NUM_UE];
+ CuUeCb *tempUeCtxtInHo;
}DuDb;
typedef struct cuGlobalCb
#include "cu_stub_sctp.h"
#include "cu_stub_egtp.h"
#include "OCTET_STRING.h"
+#include "F1AP-PDU.h"
#include "cu_f1ap_msg_hdl.h"
#include "cu_stub.h"
* @return void
*
******************************************************************/
-void BuildAndSendHOReq(CuUeCb *ueCb, XnEventType event, char *xnMsg, MsgLen xnMsgLen)
+void BuildAndSendHOReq(CuUeCb *ueCb, char *xnMsg, MsgLen xnMsgLen)
{
Buffer *mBuf = NULLP;
if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK)
{
if(ODU_ADD_POST_MSG_MULT((Data *)xnMsg, xnMsgLen, mBuf) == ROK)
- {
- CMCHKPK(oduUnpackUInt8, event, mBuf);
- if(sctpSend(XN_INTERFACE, ueCb->hoInfo.targetId, mBuf) != ROK)
+ {
+ CMCHKPK(oduUnpackUInt8, ueCb->hoInfo.cuUeF1apIdSrc, mBuf);
+ CMCHKPK(oduUnpackUInt32, ueCb->hoInfo.tgtCellId, mBuf);
+ CMCHKPK(oduUnpackUInt8, HO_REQ, mBuf);
+ if(sctpSend(XN_INTERFACE, ueCb->hoInfo.tgtNodeId, mBuf) != ROK)
{
DU_LOG("\nERROR --> CU_STUB: Failed to send handover request to peer CU");
ueCb->state = UE_ACTIVE;
}
}
+/*******************************************************************
+ *
+ * @brief Process received Handover Request
+ *
+ * @details
+ *
+ * Function : XNAPProcHandoverReq
+ *
+ * Functionality:
+ * 1. Unpack Cell Id from msg and find DU to which it belongs
+ * 2. Create UE context for UE in handover and store in DU DB
+ * 3. Decode the F1AP UE context modification msg received in
+ * XNAP message buffer and extract UE configurations
+ * 4. Send UE context setup request to DU with these configs
+ *
+ * @params[in] Pointer to destination Id
+ * Pointer to message buffer
+ * @return void
+ *
+ ******************************************************************/
+void XNAPProcHandoverReq(uint32_t destId, Buffer *mBuf)
+{
+ uint8_t duIdx, cellIdx;
+ uint8_t cuUeF1apIdSrc;
+ uint32_t cellId;
+ DuDb *duDb;
+ CuCellCb *cellCb;
+
+ DU_LOG("\nINFO --> CU STUB : Received Handover Request");
+
+ /* Find DU Db and Cell Cb from cellId */
+ CMCHKUNPK(oduPackUInt32, &(cellId), mBuf);
+ for(duIdx = 0; duIdx < cuCb.numDu; duIdx++)
+ {
+ duDb = &cuCb.duInfo[duIdx];
+ SEARCH_CELL_DB(cellIdx, duDb, cellId, cellCb)
+ if(cellCb)
+ break;
+ }
+ if(!cellCb)
+ {
+ DU_LOG("\nERROR --> CU_STUB: Failed to find Cell Id [%d] received in HO Request", cellId);
+ return;
+ }
+
+ /* Fetch CU UE F1AP ID of UE in handover assigned by source CU */
+ CMCHKUNPK(oduPackUInt8, &(cuUeF1apIdSrc), mBuf);
+
+ /* Filling temporary UE context which will be used to create actual UE context at
+ * CU later */
+ CU_ALLOC(duDb->tempUeCtxtInHo, sizeof(CuUeCb));
+ if(!duDb->tempUeCtxtInHo)
+ {
+ DU_LOG("\nERROR --> XNAP : Failed to allocate memory to temporary UE context for UE in handover");
+ return;
+ }
+ memset(duDb->tempUeCtxtInHo, 0, sizeof(CuUeCb));
+ duDb->tempUeCtxtInHo->cellCb = cellCb;
+ duDb->tempUeCtxtInHo->gnbCuUeF1apId = ++cuCb.gnbCuUeF1apIdGenerator;
+ duDb->tempUeCtxtInHo->state = UE_HANDOVER_IN_PROGRESS;
+ duDb->tempUeCtxtInHo->hoInfo.HOType = Xn_Based_Inter_CU_HO;
+ duDb->tempUeCtxtInHo->hoInfo.srcNodeId = destId;
+ duDb->tempUeCtxtInHo->hoInfo.tgtNodeId = cuCb.cuCfgParams.cuId;
+ duDb->tempUeCtxtInHo->hoInfo.tgtCellId = cellId;
+ duDb->tempUeCtxtInHo->hoInfo.cuUeF1apIdSrc = cuUeF1apIdSrc;
+ duDb->tempUeCtxtInHo->hoInfo.cuUeF1apIdTgt = duDb->tempUeCtxtInHo->gnbCuUeF1apId;
+
+ /* Decode UE context modification response msg received in Xn Msg */
+ char *recvBuf;
+ MsgLen recvBufLen, copyLen;
+ F1AP_PDU_t *f1apMsg = NULLP;
+ F1AP_PDU_t f1apasnmsg ;
+
+ f1apMsg = &f1apasnmsg;
+ memset(f1apMsg, 0, sizeof(F1AP_PDU_t));
+ if(F1APDecodeMsg(f1apMsg, mBuf, &recvBuf, &recvBufLen) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : F1AP PDU decode failed");
+ return;
+ }
+ CU_FREE(recvBuf, recvBufLen);
+ procUeContextModificationResponse(duDb->duId, f1apMsg, NULL, 0);
+}
+
+/*******************************************************************
+ *
+ * @brief Build And send dummy Handover request ack to Peer CU
+ *
+ * @details
+ *
+ * Function : BuildAndSendHOReqAck
+ *
+ * Functionality:
+ * Build And send dummy Handover request ack to Peer CU
+ *
+ * @params[in] Pointer to UE Cb
+ * Message to be sent
+ * Message Length
+ * @return void
+ *
+ ******************************************************************/
+void BuildAndSendHOReqAck(CuUeCb *ueCb, char *xnMsg, MsgLen xnMsgLen)
+{
+ Buffer *mBuf = NULLP;
+
+ if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK)
+ {
+ if(ODU_ADD_POST_MSG_MULT((Data *)xnMsg, xnMsgLen, mBuf) == ROK)
+ {
+ CMCHKPK(oduUnpackUInt8, ueCb->gnbCuUeF1apId, mBuf);
+ CMCHKPK(oduUnpackUInt8, ueCb->hoInfo.cuUeF1apIdSrc, mBuf);
+ CMCHKPK(oduUnpackUInt8, HO_REQ_ACK, mBuf);
+ if(sctpSend(XN_INTERFACE, ueCb->hoInfo.srcNodeId, mBuf) != ROK)
+ {
+ DU_LOG("\nERROR --> CU_STUB: Failed to send handover request ack to peer CU");
+ }
+ }
+ }
+}
+
+/*******************************************************************
+ *
+ * @brief Process received Handover Request Ack
+ *
+ * @details
+ *
+ * Function : XNAPProcHandoverReqAck
+ *
+ * Functionality:
+ * 1. Unpack CU UE F1AP ID (by SCU) and fetch UE CB and
+ * the corresponding DU DB (SDU)
+ * 2. Unpack CU UE F1AP ID (by TCU) and fill in UEcb->hoInfo
+ * 3. Decode DU to CU RRC Container received in XNAP message
+ * buffer and extract UE configurations.
+ * 4. Send UE Context modification response to SDU conatining
+ * RRC Reconfig Message and command to stop transmission
+ * to UE in handover.
+ *
+ * @params[in] Destination Id
+ * Pointer to message buffer
+ * @return void
+ *
+ ******************************************************************/
+void XNAPProcHandoverReqAck(uint32_t destId, Buffer *mBuf)
+{
+ uint8_t duIdx, duId, ueIdx;
+ uint8_t cuUeF1apIdSrc;
+ uint8_t cuUeF1apIdTgt;
+ DuDb *duDb;
+ CuUeCb *ueCb;
+
+ DU_LOG("\nINFO --> CU STUB : Received Handover Request Acknowledgement");
+
+ /* Fetch UE CB and DU DB in Source CU for UE under Inter-CU Handover */
+ CMCHKUNPK(oduPackUInt8, &(cuUeF1apIdSrc), mBuf);
+ for(duIdx = 0; duIdx < cuCb.numDu; duIdx++)
+ {
+ for(ueIdx = 0; ueIdx < MAX_NUM_CELL * MAX_NUM_UE; ueIdx++)
+ {
+ if(cuCb.duInfo[duIdx].ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apIdSrc)
+ {
+ duDb = &cuCb.duInfo[duIdx];
+ ueCb = &cuCb.duInfo[duIdx].ueCb[ueIdx];
+ break;
+ }
+ }
+ if(duDb && ueCb)
+ break;
+ }
+ if(!duDb || !ueCb)
+ {
+ DU_LOG("\nERROR --> CU STUB : UE CB not found for CU UE F1AP ID [%d]", cuUeF1apIdSrc);
+ return;
+ }
+
+ /* Decode CU UE F1AP ID assigned by Target CU to UE in handover and store
+ * this in hoInfo block for use during future message exchange between the
+ * two CUs */
+ CMCHKUNPK(oduPackUInt8, &(cuUeF1apIdTgt), mBuf);
+ ueCb->hoInfo.cuUeF1apIdTgt = cuUeF1apIdTgt;
+
+ /* Decode DU to CU RRC Container received in Xn Msg */
+ OCTET_STRING_t rrcCont;
+ MsgLen copyCnt;
+
+ /* Copy mBuf into char array to decode it */
+ memset(&rrcCont, 0, sizeof(OCTET_STRING_t));
+ ODU_GET_MSG_LEN(mBuf, &rrcCont.size);
+ CU_ALLOC(rrcCont.buf, rrcCont.size);
+ if(rrcCont.buf == NULLP)
+ {
+ DU_LOG("\nERROR --> XNAP : Memory allocation failed");
+ return;
+ }
+ if(ODU_COPY_MSG_TO_FIX_BUF(mBuf, 0, rrcCont.size, (Data *)rrcCont.buf, ©Cnt) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : Failed while copying %d", copyCnt);
+ return;
+ }
+
+ /* Extract DU to CU RRC container information and store in UE CB */
+ extractDuToCuRrcCont(ueCb, rrcCont);
+
+ CU_FREE(rrcCont.buf, rrcCont.size);
+
+ /* Send UE Context Modification request after filling it using the information received in
+ * Xn Handover Request Ack */
+ if(BuildAndSendUeContextModificationReq(duDb->duId, ueCb, STOP_DATA_TX) != ROK)
+ {
+ DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextModificationReq()");
+ return;
+ }
+}
+
+/*******************************************************************
+ *
+ * @brief Build And send dummy UE Context Release to Peer CU
+ *
+ * @details
+ *
+ * Function : BuildAndSendUeContextRelease
+ *
+ * Functionality:
+ * Build And send dummy UE Context Release to Peer CU
+ *
+ * @params[in] Pointer to UE Cb
+ * @return void
+ *
+ ******************************************************************/
+void BuildAndSendUeContextRelease(CuUeCb *ueCb)
+{
+ Buffer *mBuf = NULLP;
+
+ if(ODU_GET_MSG_BUF(1, 1, &mBuf) == ROK)
+ {
+ CMCHKPK(oduUnpackUInt8, ueCb->hoInfo.cuUeF1apIdSrc, mBuf);
+ CMCHKPK(oduUnpackUInt8, UE_CTXT_REL, mBuf);
+ if(sctpSend(XN_INTERFACE, ueCb->hoInfo.srcNodeId, mBuf) != ROK)
+ {
+ DU_LOG("\nERROR --> CU_STUB: Failed to send UE context release to peer CU");
+ }
+ }
+
+ return;
+}
+
+/*******************************************************************
+ * @brief Process received UE Context Release
+ *
+ * @details
+ *
+ * Function : XNAPProcUeContextRel
+ *
+ * Functionality:
+ * 1. Unpack CU UE F1AP ID (by SCU) and fetch UE CB and
+ * the corresponding DU DB (SDU)
+ * 2. Send UE Context release command to SDU
+ *
+ * @params[in] Destination Id
+ * Pointer to message buffer
+ * @return void
+ *
+ ******************************************************************/
+void XNAPProcUeContextRel(uint32_t destId, Buffer *mBuf)
+{
+ uint8_t duIdx, duId, ueIdx;
+ uint8_t cuUeF1apIdSrc;
+ DuDb *duDb;
+ CuUeCb *ueCb;
+
+ DU_LOG("\nINFO --> CU STUB : Received UE Context Release");
+
+ /* Fetch UE CB and DU DB in Source CU for UE under Inter-CU Handover */
+ CMCHKUNPK(oduPackUInt8, &(cuUeF1apIdSrc), mBuf);
+ for(duIdx = 0; duIdx < cuCb.numDu; duIdx++)
+ {
+ for(ueIdx = 0; ueIdx < MAX_NUM_CELL * MAX_NUM_UE; ueIdx++)
+ {
+ if(cuCb.duInfo[duIdx].ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apIdSrc)
+ {
+ duDb = &cuCb.duInfo[duIdx];
+ ueCb = &duDb->ueCb[ueIdx];
+ break;
+ }
+ }
+ if(duDb && ueCb)
+ break;
+ }
+ if(!duDb || !ueCb)
+ {
+ DU_LOG("\nERROR --> CU STUB : UE CB not found for CU UE F1AP ID [%d]", cuUeF1apIdSrc);
+ return;
+ }
+
+ BuildAndSendUeContextReleaseCommand(duDb->duId, ueCb->gnbCuUeF1apId, ueCb->gnbDuUeF1apId);
+}
+
/*******************************************************************
*
* @brief Handle incoming messages at Xn interface
case HO_REQ:
{
- DU_LOG("\nINFO --> CU STUB : Received Handover Request at XNAP");
-
-//Handling of HO Request to be added in next gerrit
-#if 0
- char *recvBuf;
- MsgLen copyCnt;
- MsgLen recvBufLen;
- F1AP_PDU_t *f1apMsg = NULLP;
- asn_dec_rval_t rval; /* Decoder return value */
- F1AP_PDU_t f1apasnmsg ;
-
- ODU_PRINT_MSG(mBuf, 0,0);
-
- /* Copy mBuf into char array to decode it */
- ODU_GET_MSG_LEN(mBuf, &recvBufLen);
- CU_ALLOC(recvBuf, (Size)recvBufLen);
-
- if(recvBuf == NULLP)
- {
- DU_LOG("\nERROR --> F1AP : Memory allocation failed");
- return;
- }
- if(ODU_COPY_MSG_TO_FIX_BUF(mBuf, 0, recvBufLen, (Data *)recvBuf, ©Cnt) != ROK)
- {
- DU_LOG("\nERROR --> F1AP : Failed while copying %d", copyCnt);
- return;
- }
-
- DU_LOG("\nDEBUG --> F1AP : Received flat buffer to be decoded : ");
- for(i=0; i< recvBufLen; i++)
- {
- DU_LOG("%x",recvBuf[i]);
- }
-
- /* Decoding flat buffer into F1AP messsage */
- f1apMsg = &f1apasnmsg;
- memset(f1apMsg, 0, sizeof(F1AP_PDU_t));
- rval = aper_decode(0, &asn_DEF_F1AP_PDU, (void **)&f1apMsg, recvBuf, recvBufLen, 0, 0);
- CU_FREE(recvBuf, (Size)recvBufLen);
-
- if(rval.code == RC_FAIL || rval.code == RC_WMORE)
- {
- DU_LOG("\nERROR --> F1AP : ASN decode failed");
- return;
- }
- DU_LOG("\n");
- xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg);
-
- procUeContextModificationResponse(0, f1apMsg, recvBuf, recvBufLen);
-#endif
+ XNAPProcHandoverReq(*destId, mBuf);
+ break;
+ }
+
+ case HO_REQ_ACK:
+ {
+ XNAPProcHandoverReqAck(*destId, mBuf);
+ break;
+ }
+ case UE_CTXT_REL:
+ {
+ XNAPProcUeContextRel(*destId, mBuf);
break;
}
default:
#include "PagingCycle.h"
#include "PCCH-Config.h"
#include "TimeAlignmentTimer.h"
+#include "BCCH-DL-SCH-Message.h"
#include "RACH-ConfigGeneric.h"
#include "PUSCH-TimeDomainResourceAllocation.h"
#include "PUCCH-ConfigCommon.h"
#include "CFRA-SSB-Resource.h"
#include "BWP-UplinkCommon.h"
#include "ReconfigurationWithSync.h"
+#include "BCCH-DL-SCH-Message.h"
#include "du_sys_info_hdl.h"
#include "DRX-ConfigRrc.h"
#include "MeasurementTimingConfigurationRrc.h"
#include "MeasurementTimingConfigurationRrc-IEs.h"
#include "MeasTimingList.h"
#include "MeasTiming.h"
+#include "Cells-Status-List.h"
+#include "Cells-Status-Item.h"
#ifdef O1_ENABLE
#include "CmInterface.h"
for(plmnidx=0; plmnidx<plmnCnt; plmnidx++)
{
DU_ALLOC(duServedCell->list.array[plmnidx],\
- sizeof(GNB_DU_Served_Cells_ItemIEs_t));
+ sizeof(GNB_DU_Served_Cells_ItemIEs_t));
if(duServedCell->list.array[plmnidx] == NULLP)
{
- return RFAILED;
+ return RFAILED;
}
}
idx = 0;
duServedCell->list.array[idx]->id = ProtocolIE_ID_id_GNB_DU_Served_Cells_Item;
duServedCell->list.array[idx]->criticality = Criticality_reject;
duServedCell->list.array[idx]->value.present = \
- GNB_DU_Served_Cells_ItemIEs__value_PR_GNB_DU_Served_Cells_Item;
+ GNB_DU_Served_Cells_ItemIEs__value_PR_GNB_DU_Served_Cells_Item;
srvCellItem = \
- &duServedCell->list.array[idx]->value.choice.GNB_DU_Served_Cells_Item;
+ &duServedCell->list.array[idx]->value.choice.GNB_DU_Served_Cells_Item;
/*nRCGI*/
BuildNrcgiret = BuildNrcgi(&srvCellItem->served_Cell_Information.nRCGI);
if(BuildNrcgiret != ROK)
}
/*nRPCI*/
srvCellItem->served_Cell_Information.nRPCI = \
- duCfgParam.srvdCellLst[0].duCellInfo.cellInfo.nrPci;
+ duCfgParam.srvdCellLst[0].duCellInfo.cellInfo.nrPci;
/* fiveGS_TAC */
BuildFiveGSTacret = BuildFiveGSTac(&srvCellItem->served_Cell_Information);
/* GNB DU System Information */
DU_ALLOC(srvCellItem->gNB_DU_System_Information,
- sizeof(GNB_DU_System_Information_t));
+ sizeof(GNB_DU_System_Information_t));
if(!srvCellItem->gNB_DU_System_Information)
{
return RFAILED;
/* MIB */
srvCellItem->gNB_DU_System_Information->mIB_message.size = duCfgParam.srvdCellLst[0].duSysInfo.mibLen;
DU_ALLOC(srvCellItem->gNB_DU_System_Information->mIB_message.buf,
- srvCellItem->gNB_DU_System_Information->mIB_message.size);
+ srvCellItem->gNB_DU_System_Information->mIB_message.size);
if(!srvCellItem->gNB_DU_System_Information->mIB_message.buf)
{
return RFAILED;
}
memcpy(srvCellItem->gNB_DU_System_Information->mIB_message.buf, duCfgParam.srvdCellLst[0].duSysInfo.mibMsg, \
- srvCellItem->gNB_DU_System_Information->mIB_message.size);
+ srvCellItem->gNB_DU_System_Information->mIB_message.size);
/* SIB1 */
srvCellItem->gNB_DU_System_Information->sIB1_message.size =\
- duCfgParam.srvdCellLst[0].duSysInfo.sib1Len;
+ duCfgParam.srvdCellLst[0].duSysInfo.sib1Len;
DU_ALLOC(srvCellItem->gNB_DU_System_Information->sIB1_message.buf,
- srvCellItem->gNB_DU_System_Information->sIB1_message.size);
+ srvCellItem->gNB_DU_System_Information->sIB1_message.size);
if(!srvCellItem->gNB_DU_System_Information->sIB1_message.buf)
{
return RFAILED;
for(int x=0; x<srvCellItem->gNB_DU_System_Information->sIB1_message.size; x++)
{
srvCellItem->gNB_DU_System_Information->sIB1_message.buf[x]=\
- duCfgParam.srvdCellLst[0].duSysInfo.sib1Msg[x];
+ duCfgParam.srvdCellLst[0].duSysInfo.sib1Msg[x];
}
return ROK;
}
elementCnt = 5;
f1SetupReq->protocolIEs.list.count = elementCnt;
- f1SetupReq->protocolIEs.list.size = elementCnt * sizeof(F1SetupRequestIEs_t );
+ f1SetupReq->protocolIEs.list.size = elementCnt * sizeof(F1SetupRequestIEs_t *);
/* Initialize the F1Setup members */
DU_ALLOC(f1SetupReq->protocolIEs.list.array,f1SetupReq->protocolIEs.list.size);
}
}
DU_FREE(modifyItem->served_Cell_Information.measurementTimingConfiguration.buf,\
- modifyItem->served_Cell_Information.measurementTimingConfiguration.size);
+ modifyItem->served_Cell_Information.measurementTimingConfiguration.size);
}
/*******************************************************************
* ****************************************************************/
void FreeDUConfigUpdate(F1AP_PDU_t *f1apDuCfg)
{
- uint8_t ieIdx=0, cellModifyIdx=0, cellDeleteIdx=0;
+ uint8_t idx=0,ieIdx=0, cellModifyIdx=0, cellDeleteIdx=0;
GNBDUConfigurationUpdate_t *duCfgUpdate = NULLP;
Served_Cells_To_Modify_List_t *cellsToModify=NULLP;
Served_Cells_To_Delete_List_t *cellsToDelete=NULLP;
Served_Cells_To_Delete_Item_t *deleteItem = NULLP;
Served_Cells_To_Delete_ItemIEs_t *deleteItemIe = NULLP;
+ Cells_Status_ItemIEs_t *cellStatusItemIE;
if(f1apDuCfg != NULLP)
{
duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.GNB_DU_ID.size);
break;
}
+ case ProtocolIE_ID_id_Cells_Status_List:
+ {
+ for(idx = 0; idx < duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.Cells_Status_List.list.count; idx++)
+ {
+ cellStatusItemIE = (Cells_Status_ItemIEs_t *)duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.Cells_Status_List.list.array[idx];
+ DU_FREE(cellStatusItemIE->value.choice.Cells_Status_Item.nRCGI.nRCellIdentity.buf, cellStatusItemIE->value.choice.Cells_Status_Item.nRCGI.nRCellIdentity.size);
+ DU_FREE(cellStatusItemIE->value.choice.Cells_Status_Item.nRCGI.pLMN_Identity.buf, cellStatusItemIE->value.choice.Cells_Status_Item.nRCGI.pLMN_Identity.size);
+ DU_FREE(duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.Cells_Status_List.list.array[idx],sizeof(Cells_Status_ItemIEs_t));
+ }
+ DU_FREE(duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.Cells_Status_List.list.array,\
+ duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.Cells_Status_List.list.size);
+ }
}
DU_FREE(duCfgUpdate->protocolIEs.list.array[ieIdx],\
sizeof(GNBDUConfigurationUpdateIEs_t));
fillBitString(&deleteItem->oldNRCGI.nRCellIdentity, ODU_VALUE_FOUR, ODU_VALUE_FIVE, duCfgParam.sib1Params.cellIdentity);
return ROK;
}
+
/*******************************************************************
*
* @brief Builds ServCellToDeleteList
return ROK;
}
+/*******************************************************************
+ *
+ * @brief Builds CellsStatusList
+ *
+ * @details
+ *
+ * Function : buildCellsStatusList
+ *
+ * Functionality: Builds the Cell Status List
+ *
+ * @params[in] Pointer to Cells_Status_List_t *
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ *****************************************************************/
+uint8_t buildCellsStatusList(Cells_Status_List_t *cellStatusList)
+{
+ uint8_t elementCnt = 0, idx = 0, ret = ROK;
+ Cells_Status_ItemIEs_t *cellStatusItemIE;
+
+ elementCnt = 1;
+ cellStatusList->list.count = elementCnt;
+ cellStatusList->list.size = elementCnt * sizeof(Cells_Status_ItemIEs_t *);
+ DU_ALLOC(cellStatusList->list.array, cellStatusList->list.size);
+
+ for(idx = 0; idx < elementCnt; idx++)
+ {
+ DU_ALLOC(cellStatusList->list.array[idx], sizeof(Cells_Status_ItemIEs_t));
+ if(!cellStatusList->list.array[idx])
+ {
+ DU_LOG("ERROR --> F1AP: buildCellsStatusList() memory allocation failure");
+ return RFAILED;
+ }
+ }
+ idx = 0;
+ cellStatusItemIE = (Cells_Status_ItemIEs_t *)cellStatusList->list.array[idx];
+ cellStatusItemIE->id = ProtocolIE_ID_id_Cells_Status_Item;
+ cellStatusItemIE->criticality = Criticality_reject;
+ cellStatusItemIE->value.present = Cells_Status_ItemIEs__value_PR_Cells_Status_Item;
+ ret = BuildNrcgi(&cellStatusItemIE->value.choice.Cells_Status_Item.nRCGI);
+ if(ret == RFAILED)
+ {
+ DU_LOG("ERROR --> F1AP: buildCellsStatusList() NRCGI failed");
+ return RFAILED;
+ }
+ cellStatusItemIE->value.choice.Cells_Status_Item.service_status.service_state = Service_State_in_service;
+ return ROK;
+}
+
/*******************************************************************
*
* @brief Builds and sends the DUConfigUpdate
InitiatingMessage__value_PR_GNBDUConfigurationUpdate;
duCfgUpdate = &f1apDuCfg->choice.initiatingMessage->value.\
choice.GNBDUConfigurationUpdate;
- elementCnt = 3;
+ elementCnt = 4;
duCfgUpdate->protocolIEs.list.count = elementCnt;
duCfgUpdate->protocolIEs.list.size = \
elementCnt * sizeof(GNBDUConfigurationUpdateIEs_t*);
}
}
- // NOTE :GNB DU SYS INFO:MIB AND SIB1 INFORMATION TO BE BUILT AND FILLED HERE
+ // TODO :GNB DU SYS INFO:MIB AND SIB1 INFORMATION TO BE BUILT AND FILLED HERE
+
+ /*Cell Status List*/
+ ieIdx++;
+ duCfgUpdate->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_Cells_Status_List;
+ duCfgUpdate->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+ duCfgUpdate->protocolIEs.list.array[ieIdx]->value.present = \
+ GNBDUConfigurationUpdateIEs__value_PR_Cells_Status_List;
+ ret = buildCellsStatusList(&duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.Cells_Status_List);
+ if(ret == RFAILED)
+ {
+ DU_LOG("ERROR --> DU APP : BuildAndSendDUConfigUpdate(): Cell Status List building failed");
+ break;
+ }
+
/*GNB DU ID */
ieIdx++;
duCfgUpdate->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_gNB_DU_ID;
#include "TDD-UL-DL-ConfigCommon.h"
#include "ServingCellConfigCommonSIB.h"
#include "MCC.h"
-#include "BCCH-DL-SCH-Message.h"
#include "SIB1.h"
#include "odu_common_codec.h"
-#include "du_sys_info_hdl.h"
+#include "BCCH-DL-SCH-Message.h"
#include "du_f1ap_conversions.h"
+#include "du_sys_info_hdl.h"
void FreeSib1Msg(SIB1_t *sib1Msg);
uint8_t FreqInfoUlret = RFAILED;
FreeSib1Msg(bcchMsg.message.choice.c1->choice.systemInformationBlockType1);
break;
}
+ case BCCH_DL_SCH_MessageType__c1_PR_systemInformation:
+ break;
+ case BCCH_DL_SCH_MessageType__c1_PR_NOTHING:
+ break;
}
DU_FREE(bcchMsg.message.choice.c1, sizeof(struct BCCH_DL_SCH_MessageType__c1));
break;
}
+ case BCCH_DL_SCH_MessageType_PR_messageClassExtension:
+ break;
+ case BCCH_DL_SCH_MessageType_PR_NOTHING:
+ break;
}
}
uint8_t BuildTddUlDlCfgComm(TDD_UL_DL_ConfigCommon_t *tddCfg);
void FreeBwpDlCommon(BWP_DownlinkCommon_t *bwp);
void FreeBwpUlCommon(BWP_UplinkCommon_t *bwp);
+void FreeBcchDlSchMsg(BCCH_DL_SCH_Message_t bcchMsg);
char encBuf[ENC_BUF_MAX_LEN];
DuCfgParams duCfgParam;