#include "ProtocolIE-Field.h"
#include "ProtocolExtensionField.h"
#include "ProtocolIE-SingleContainer.h"
+#include "F1SetupResponse.h"
+#include "SuccessfulOutcome.h"
+#include "InitiatingMessage.h"
+#include "NonDynamic5QIDescriptor.h"
+#include "AveragingWindow.h"
+#include "MaxDataBurstVolume.h"
+#include "Flows-Mapped-To-DRB-Item.h"
+#include "SliceSupportItem.h"
+#include "ServedPLMNs-Item.h"
#include "F1AP-PDU.h"
+#include "ULUPTNLInformation-ToBeSetup-Item.h"
+#include "ULConfiguration.h"
#include "ModulationOrder.h"
#include "BandNR.h"
#include "UE-CapabilityRAT-Container.h"
#include "MeasConfigRrc.h"
#include "AS-Config.h"
#include "RRCReconfiguration-v1530-IEs.h"
+#include "CNUEPagingIdentity.h"
+#include "PagingCell-Item.h"
+#include "UL-DCCH-Message.h"
+#include "DRX-ConfigRrc.h"
#include "cu_stub_sctp.h"
#include "cu_stub_egtp.h"
return ROK;
} /* SendF1APMsg */
-/*******************************************************************
- *
- * @brief Builds NRCell ID
- *
- * @details
- *
- * Function : BuildNrCellId
- *
- * Functionality: Building the NR Cell ID
- *
- * @params[in] BIT_STRING_t *nrcell
- * @return ROK - success
- * RFAILED - failure
- *
- * ****************************************************************/
-
-S16 BuildNrCellId(BIT_STRING_t *nrcell)
-{
- memset(nrcell->buf, 0, nrcell->size);
- nrcell->buf[4] = 16;
- nrcell->bits_unused = 4;
- nrcell->size = 5 * sizeof(uint8_t);
- return ROK;
-}
-
/********************************************************************
*
* @brief Builds and sends the F1SetupResponse
buildPlmnId(cuCb.cuCfgParams.plmn , cellToActivate->list.array[0]->value.choice.\
Cells_to_be_Activated_List_Item.nRCGI.pLMN_Identity.buf);
cellToActivate->list.array[0]->value.choice.Cells_to_be_Activated_List_Item.\
- nRCGI.nRCellIdentity.size = 5;
+ nRCGI.nRCellIdentity.size = 5*sizeof(uint8_t);
CU_ALLOC(cellToActivate->list.array[0]->value.choice.\
Cells_to_be_Activated_List_Item.nRCGI.nRCellIdentity.buf,\
- 5*sizeof(uint8_t));
+ cellToActivate->list.array[0]->value.choice.Cells_to_be_Activated_List_Item.\
+ nRCGI.nRCellIdentity.size);
if(cellToActivate->list.array[0]->value.choice.\
Cells_to_be_Activated_List_Item.nRCGI.nRCellIdentity.buf == NULLP)
{
}
}
+/*******************************************************************
+ *
+ * @brief Fills QOS flow configuration
+ *
+ * @details
+ *
+ * Function : fillQosFlowsToAdd
+ *
+ * Functionality: Fills QOS flow configuration
+ *
+ * @params[in] struct SDAP_Config__mappedQoS_FlowsToAdd *qosFlow
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
uint8_t fillQosFlowsToAdd(struct SDAP_Config__mappedQoS_FlowsToAdd *qosFlow)
{
uint8_t idx, ied, elementCnt;
if(ret == RFAILED)
DU_LOG("\nERROR --> F1AP: Failed to fill DL-CCCH Msg at RRC SETUP");
}
- else if(rrcMsgType == REGISTRATION_ACCEPT)
+ else if(rrcMsgType == RRC_SETUP_COMPLETE)
+ {
+ DU_LOG("\nINFO --> F1AP : Sending NAS Security mode command");
+ char secModeBuf[30]={0x00, 0x02, 0x2e, 0x82, 0xaf, 0xc0, 0x7d, 0x1c, 0x4e, 0xfc, 0x80, 0x0f, 0xc0,
+ 0x0b, 0xa0, 0x20, 0x40, 0x9e, 0x0e, 0x1e, 0x0e, 0x1c, 0x26, 0xc0, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00};
+ bufLen =30;
+ rrcContainer->size = bufLen;
+ CU_ALLOC(rrcContainer->buf, rrcContainer->size);
+ if(rrcContainer->buf != NULLP)
+ {
+ memset(rrcContainer->buf, 0, bufLen);
+ memcpy(rrcContainer->buf, secModeBuf, bufLen);
+ }
+ else
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failure for RRC Container buffer");
+ ret = RFAILED;
+ }
+ }
+ else if(rrcMsgType == NAS_SECURITY_MODE_COMPLETE)
+ {
+ DU_LOG("\nINFO --> F1AP : Sending RRC Security mode command");
+ char secModeBuf[9]={0x00, 0x03, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00};
+ bufLen =9;
+ rrcContainer->size = bufLen;
+ CU_ALLOC(rrcContainer->buf, rrcContainer->size);
+ if(rrcContainer->buf != NULLP)
+ {
+ memset(rrcContainer->buf, 0, bufLen);
+ memcpy(rrcContainer->buf, secModeBuf, bufLen);
+ }
+ else
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failure for RRC Container buffer");
+ ret = RFAILED;
+ }
+ }
+ else if(rrcMsgType == RRC_SECURITY_MODE_COMPLETE)
{
/*Hardcoded RRC Container from reference logs*/
- char buf[14] ={0x00, 0x03, 0x2a, 0x80, 0xaf, 0xc0, 0x08, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00};
+ DU_LOG("\nINFO --> F1AP : Sending Registration accept");
+ char buf[14] ={0x00, 0x04, 0x2a, 0x80, 0xaf, 0xc0, 0x08, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00};
bufLen =14;
rrcContainer->size = bufLen;
CU_ALLOC(rrcContainer->buf, rrcContainer->size);
ret = RFAILED;
}
}
- else if(rrcMsgType == RRC_RECONFIG)
+ else if(rrcMsgType == UE_CONTEXT_SETUP_RSP)
{
- DU_LOG("\nDEBUG --> F1AP : Filling DL DCCH RRC Message ");
+ DU_LOG("\nINFO --> F1AP : Filling DL DCCH RRC Message for RRC Reconfiguration ");
ret = fillDlDcchRrcMsg(ueCb, rrcContainer);
if(ret == RFAILED)
DU_LOG("\nERROR --> F1AP: Failed to fill DL-DCCH Msg for RRC Reconfiguration");
case RRC_SETUP:
rrcMsgType = RRC_SETUP;
break;
- case REGISTRATION_ACCEPT:
- rrcMsgType = REGISTRATION_ACCEPT;
+ case RRC_SETUP_COMPLETE:
+ rrcMsgType = RRC_SETUP_COMPLETE;
break;
- case UE_CONTEXT_SETUP_REQ:
- rrcMsgType = UE_CONTEXT_SETUP_REQ;
+ case NAS_SECURITY_MODE_COMPLETE:
+ rrcMsgType = NAS_SECURITY_MODE_COMPLETE;
break;
- case SECURITY_MODE_COMPLETE:
- rrcMsgType = SECURITY_MODE_COMPLETE;
+ case RRC_SECURITY_MODE_COMPLETE:
+ rrcMsgType = RRC_SECURITY_MODE_COMPLETE;
break;
- case RRC_RECONFIG:
- rrcMsgType = RRC_RECONFIG;
+ case REGISTRATION_COMPLETE:
+ rrcMsgType = REGISTRATION_COMPLETE;
+ break;
+ case UE_CONTEXT_SETUP_RSP:
+ rrcMsgType = UE_CONTEXT_SETUP_RSP;
break;
case RRC_RECONFIG_COMPLETE:
rrcMsgType = RRC_RECONFIG_COMPLETE;
break;
- case UE_CONTEXT_MOD_REQ:
- rrcMsgType = UE_CONTEXT_MOD_REQ;
- break;
default:
break;
}
return rrcMsgType;
}
+#ifdef NR_DRX
+/*******************************************************************
+ *
+ * @brief fill long cycle offset value of drx
+ *
+ * @details
+ *
+ * Function : fillLongCycleOffsetValue
+ *
+ * Functionality: fill long cycle offset value of drx
+ *
+ * @params[in] DrxLongCycleStartOffset drxLongCycleStartOffset,
+ * struct DRX_ConfigRrc__drx_LongCycleStartOffset recvedLongCycleOffsetVal
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+void fillLongCycleOffsetValue(DrxLongCycleStartOffset *drxLongCycleStartOffset, struct DRX_ConfigRrc__drx_LongCycleStartOffset *recvedLongCycleOffsetVal)
+{
+
+ drxLongCycleStartOffset->drxLongCycleStartOffsetChoice = recvedLongCycleOffsetVal->present;
+ switch(recvedLongCycleOffsetVal->present)
+ {
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms10:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms10;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms20:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms20;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms32:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms32;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms40:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms40;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms60:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms60;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms64:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms64;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms70:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms70;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms80:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms80;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms128:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms128;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms160:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms160;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms256:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms256;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms320:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms320;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms512:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms512;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms640:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms640;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms1024:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms1024;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms1280:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms1280;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms2048:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms2048;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms2560:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms2560;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms5120:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms5120;
+ break;
+ }
+ case DRX_ConfigRrc__drx_LongCycleStartOffset_PR_ms10240:
+ {
+ drxLongCycleStartOffset->drxLongCycleStartOffsetVal = recvedLongCycleOffsetVal->choice.ms10240;
+ break;
+ }
+ default :
+ break;
+ }
+}
+
+/*******************************************************************
+ *
+ * @brief Extract configuration from DRX_ConfigRrc
+ * and store the drx configuration in UeCb
+ *
+ * @details
+ *
+ * Function : storeDrxCfgInUeCb
+ *
+ * Functionality: Store drx configuration in UeCb
+ *
+ * @params[in] (struct DRX_ConfigRrc *setup, DrxCfg *drxCfg)
+ *
+ * @return void
+ * ****************************************************************/
+void storeDrxCfgInUeCb(struct DRX_ConfigRrc *drxSetup, DrxCfg *drxCfg)
+{
+ switch(drxSetup->drx_onDurationTimer.present)
+ {
+ case DRX_ConfigRrc__drx_onDurationTimer_PR_NOTHING:
+ break;
+ case DRX_ConfigRrc__drx_onDurationTimer_PR_milliSeconds:
+ {
+ drxCfg->drxOnDurationTimer.onDurationTimerValInMs = true;
+ drxCfg->drxOnDurationTimer.onDurationtimerValue.milliSeconds=drxSetup->drx_onDurationTimer.choice.milliSeconds;
+ break;
+ }
+ case DRX_ConfigRrc__drx_onDurationTimer_PR_subMilliSeconds:
+ {
+ drxCfg->drxOnDurationTimer.onDurationTimerValInMs = false;
+ drxCfg->drxOnDurationTimer.onDurationtimerValue.subMilliSeconds = drxSetup->drx_onDurationTimer.choice.subMilliSeconds;
+ break;
+ }
+ }
+ fillLongCycleOffsetValue(&drxCfg->drxLongCycleStartOffset, &drxSetup->drx_LongCycleStartOffset);
+ drxCfg->drxInactivityTimer = drxSetup->drx_InactivityTimer;
+ drxCfg->drxHarqRttTimerDl = drxSetup->drx_HARQ_RTT_TimerDL;
+ drxCfg->drxHarqRttTimerUl = drxSetup->drx_HARQ_RTT_TimerUL;
+ drxCfg->drxRetransmissionTimerDl = drxSetup->drx_RetransmissionTimerDL;
+ drxCfg->drxRetransmissionTimerUl = drxSetup->drx_RetransmissionTimerUL;
+ drxCfg->drxSlotOffset = drxSetup->drx_SlotOffset;
+ if(drxSetup->shortDRX)
+ {
+ drxCfg->shortDrxPres=true;
+ drxCfg->shortDrx.drxShortCycle = drxSetup->shortDRX->drx_ShortCycle;
+ drxCfg->shortDrx.drxShortCycleTimer = drxSetup->shortDRX->drx_ShortCycleTimer;
+ }
+ else
+ drxCfg->shortDrxPres=false;
+}
+#endif
+
/*******************************************************************
*
* @brief Extract configuration from CellGroupConfig
RLC_BearerConfig_t *rlcCfg = NULLP;
RLC_Config_t *rlcLcCfg = NULLP;
LogicalChannelConfig_t *macLcCfg = NULLP;
+#ifdef NR_DRX
+ DrxCfg drxCfg;
+#endif
if(ueCb == NULLP)
{
return RFAILED;
}
+#ifdef NR_DRX
+ if(cellGrpCfg->mac_CellGroupConfig)
+ {
+ if(cellGrpCfg->mac_CellGroupConfig->drx_ConfigRrc)
+ {
+ switch(cellGrpCfg->mac_CellGroupConfig->drx_ConfigRrc->present)
+ {
+ case MAC_CellGroupConfig__drx_ConfigRrc_PR_NOTHING:
+ break;
+
+ case MAC_CellGroupConfig__drx_ConfigRrc_PR_setup:
+ {
+ if(cellGrpCfg->mac_CellGroupConfig->drx_ConfigRrc->choice.setup)
+ {
+ ueCb->drxCfgPresent = true;
+ storeDrxCfgInUeCb(cellGrpCfg->mac_CellGroupConfig->drx_ConfigRrc->choice.setup, &ueCb->drxCfg);
+ }
+ break;
+ }
+
+ case MAC_CellGroupConfig__drx_ConfigRrc_PR_release:
+ break;
+ }
+ }
+ }
+#endif
+
for(rbIdx = 0; rbIdx < cellGrpCfg->rlc_BearerToAddModList->list.count; rbIdx++)
{
srbFound = false;
CellGroupConfigRrc_t cellGrpCfg, *cellGrpCfgMsg = NULLP;
asn_dec_rval_t rval; /* Decoder return value */
+ /* Copy the received container to UeCb */
+ memcpy(&ueCb->f1apMsgDb.duToCuContainer, &rrcCont, sizeof(OCTET_STRING_t));
+
/* Decoding DU to CU RRC container octet string to cell group config */
cellGrpCfgMsg = &cellGrpCfg;
memset(cellGrpCfgMsg, 0, sizeof(CellGroupConfigRrc_t));
if(rval.code == RC_FAIL || rval.code == RC_WMORE)
{
- DU_LOG("\nERROR --> F1AP : ASN decode failed");
+ DU_LOG("\nERROR --> F1AP : ASN decode failed in extractDuToCuRrcCont");
return RFAILED;
}
printf("\n");
uint8_t procInitULRRCMsg(uint32_t duId, F1AP_PDU_t *f1apMsg)
{
- uint8_t idx,cellIdx=0, duIdx=0, rrcMsgType, gnbDuUeF1apId;
+ uint8_t idx = 0, duIdx=0, rrcMsgType=0, gnbDuUeF1apId=0;
uint8_t ret =ROK;
- uint32_t nrCellId, crnti;
+ uint16_t cellIdx=0, nrCellId = 0;
+ uint32_t crnti;
DuDb *duDb;
CuCellCb *cellCb;
CuUeCb *ueCb;
break;
case ProtocolIE_ID_id_NRCGI:
- nrCellId = initULRRCMsg->protocolIEs.list.array[idx]->value.choice.NRCGI.nRCellIdentity.buf[4] >>
- initULRRCMsg->protocolIEs.list.array[idx]->value.choice.NRCGI.nRCellIdentity.bits_unused;
+ bitStringToInt(&initULRRCMsg->protocolIEs.list.array[idx]->value.choice.NRCGI.nRCellIdentity, &nrCellId);
SEARCH_CELL_DB(cellIdx, duDb, nrCellId, cellCb);
if(cellCb == NULLP)
return RFAILED;
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);
{
return RFAILED;
}
- fillBitString(&nrcgi->nRCellIdentity, unused_bits, byteSize, val);
+ fillBitString(&nrcgi->nRCellIdentity, unused_bits, byteSize, nrCellId);
return ROK;
}
* 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;
* RFAILED - failure
*
* ****************************************************************/
-uint8_t BuildDRBSetup(CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet)
+uint8_t BuildDRBSetup(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetup_List_t *drbSet)
{
+ uint16_t snssaiIdx=0;
uint8_t idx = 0, extIeIdx = 0;
uint8_t elementCnt = 0, drbCnt = 0;
uint8_t BuildQOSInforet = 0,BuildSNSSAIret = 0;
}
/*SNSSAI*/
+ snssaiIdx = (idx% cuCb.numSnssaiSupported);
if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
BuildSNSSAIret = BuildSNSSAI(&ueCb->drbList[ueCb->numDrb], &drbSetItem->qoSInformation.choice.\
- choice_extension->value.choice.DRB_Information.sNSSAI, cuCb.snssaiList[0], FALSE);
+ choice_extension->value.choice.DRB_Information.sNSSAI, cuCb.snssaiList[snssaiIdx], FALSE);
else
BuildSNSSAIret = BuildSNSSAI(&ueCb->drbList[idx], &drbSetItem->qoSInformation.choice.\
- choice_extension->value.choice.DRB_Information.sNSSAI, cuCb.snssaiList[0], TRUE);
+ choice_extension->value.choice.DRB_Information.sNSSAI, NULLP, TRUE);
if(BuildSNSSAIret != ROK)
{
DU_LOG("\nERROR --> F1AP : Failed to build SNSSAI Info in BuildDRBSetup");
/*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)
{
* ****************************************************************/
uint8_t BuildMacCellGrpCfg(MAC_CellGroupConfig_t *macCellGrpCfg)
{
- macCellGrpCfg->drx_Config = NULLP;
+ macCellGrpCfg->drx_ConfigRrc = NULLP;
macCellGrpCfg->schedulingRequestConfig = NULLP;
CU_ALLOC(macCellGrpCfg->schedulingRequestConfig, sizeof(struct SchedulingRequestConfig));
if(!macCellGrpCfg->schedulingRequestConfig)
}
}
+ if(!elementCnt)
+ {
+ DU_LOG("INFO --> F1AP : No RLC Bearer available to add or modify");
+ return ROK;
+ }
+ CU_ALLOC(rlcBearerList, sizeof(struct CellGroupConfigRrc__rlc_BearerToAddModList));
+ if(!rlcBearerList)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failure in CellGrpConfig");
+ return RFAILED;
+ }
rlcBearerList->list.count = elementCnt;
rlcBearerList->list.size = elementCnt * sizeof(struct RLC_BearerConfig *);
for(drbIdx=0; drbIdx < ueCb->numDrb; drbIdx++)
{
- if(!updateAllRbCfg && ueCb->srbList[srbIdx].cfgSentToUe)
+ if(!updateAllRbCfg && ueCb->drbList[drbIdx].cfgSentToUe)
continue;
rlcBearerList->list.array[idx]->logicalChannelIdentity = ueCb->drbList[drbIdx].lcId;
cellGrpCfg.cellGroupId = CELL_GRP_ID;
cellGrpCfg.rlc_BearerToAddModList = NULLP;
- CU_ALLOC(cellGrpCfg.rlc_BearerToAddModList, sizeof(struct CellGroupConfigRrc__rlc_BearerToAddModList));
- if(!cellGrpCfg.rlc_BearerToAddModList)
- {
- DU_LOG("\nERROR --> F1AP : Memory allocation failure in CellGrpConfig");
- break;
- }
+
if(BuildRlcBearerToAddModList(ueCb, cellGrpCfg.rlc_BearerToAddModList, updateAllRbCfg) != ROK)
{
DU_LOG("\nERROR --> F1AP : fillCellGrpCfg failed");
* @return void
*
* ****************************************************************/
-uint8_t freeQuantityConfig(QuantityConfig_t *quantityCfg)
+void freeQuantityConfig(QuantityConfig_t *quantityCfg)
{
uint8_t quanCfgIdx;
QuantityConfigNR_t *quantityCfgNr;
*
* @details
*
- * Function : fillRadioBearerConfig
+ * Function : freeRadioBearerConfig
*
* Functionality: Free Radio Bearer config
*
* ****************************************************************/
uint8_t fillSrbToAddModList(CuUeCb *ueCb, SRB_ToAddModList_t *srbToAddList, bool updateAllRbCfg)
{
- uint8_t srbIdx, srbDbIdx;
+ uint8_t srbIdx, srbDbIdx, elementCnt = 0;
if(updateAllRbCfg)
- srbToAddList->list.count = ueCb->numSrb;
+ elementCnt = ueCb->numSrb;
else
{
- srbToAddList->list.count = 0;
for(srbDbIdx=0; srbDbIdx < ueCb->numSrb; srbDbIdx++)
{
if(ueCb->srbList[srbDbIdx].cfgSentToUe == false)
- srbToAddList->list.count++;
+ elementCnt++;
}
}
+
+ if(!elementCnt)
+ {
+ DU_LOG("INFO --> F1AP : No SRB available to add or modify");
+ return ROK;
+ }
+
+ srbToAddList->list.count = elementCnt;
srbToAddList->list.size = srbToAddList->list.count * sizeof(SRB_ToAddMod_t *);
CU_ALLOC(srbToAddList->list.array, srbToAddList->list.size);
* ****************************************************************/
uint8_t fillDrbToAddModList(CuUeCb *ueCb, DRB_ToAddModList_t *drbToAddList, bool updateAllRbCfg)
{
- uint8_t drbIdx, drbDbIdx;
+ uint8_t drbIdx, drbDbIdx, elementCnt = 0;
if(updateAllRbCfg)
- drbToAddList->list.count = ueCb->numDrb;
+ elementCnt = ueCb->numDrb;
else
{
- drbToAddList->list.count = 0;
for(drbDbIdx=0; drbDbIdx < ueCb->numDrb; drbDbIdx++)
{
if(ueCb->drbList[drbDbIdx].cfgSentToUe == false)
- drbToAddList->list.count++;
+ elementCnt++;
}
}
+
+ if(!elementCnt)
+ {
+ DU_LOG("INFO --> F1AP : No DRB available to add or modify");
+ return ROK;
+ }
+
+
+ drbToAddList->list.count = elementCnt;
drbToAddList->list.size = drbToAddList->list.count * sizeof(DRB_ToAddMod_t *);
CU_ALLOC(drbToAddList->list.array, drbToAddList->list.size);
}
if(fillSrbToAddModList(ueCb, radioBearerConfig->srb_ToAddModList, updateAllRbCfg) != ROK)
{
+ DU_LOG("\nERROR --> F1AP: failed to fill SRB to AddMod List");
return RFAILED;
}
{
DU_LOG("\nERROR --> F1AP: Memory allocation failed for DRB to AddMod List in fillRadioBearerConfig");
return RFAILED;
- }
+ }
if(fillDrbToAddModList(ueCb, radioBearerConfig->drb_ToAddModList, updateAllRbCfg) != ROK)
{
+ DU_LOG("\nERROR --> F1AP: failed to fill DRB to AddMod List ");
return RFAILED;
}
CU_ALLOC(rrcRecfg->masterCellGroup, sizeof(OCTET_STRING_t));
if(!rrcRecfg->masterCellGroup)
{
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in fillRrcReconfigNonCriticalExt");
return RFAILED;
}
+ rrcRecfg->masterCellGroup->size = ueCb->f1apMsgDb.duToCuContainer.size;
+ CU_ALLOC(rrcRecfg->masterCellGroup->buf, rrcRecfg->masterCellGroup->size);
+ if(!rrcRecfg->masterCellGroup->buf)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in fillRrcReconfigNonCriticalExt");
+ return RFAILED;
+ }
+ memcpy(rrcRecfg->masterCellGroup->buf, ueCb->f1apMsgDb.duToCuContainer.buf, rrcRecfg->masterCellGroup->size);
+
+#if 0
+ /* Use below code if masterCEllGroup is to be filled explicitly at CU rather than copying from DUToCURRCContainer
+ * received from DU */
if(fillCellGrpCfg(ueCb, rrcRecfg->masterCellGroup, updateAllRbCfg) != ROK)
{
+ DU_LOG("\nERROR --> F1AP : Failed to fill CellGroupCfg in fillRrcReconfigNonCriticalExt");
return RFAILED;
}
+#endif
return ROK;
}
return RFAILED;
}
ret = fillRrcReconfigBuf(ueCb, &hoPrepInfoIe->sourceConfig->rrcReconfiguration, true);
+
+ if(ret != ROK)
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to fill Rrc reconfiguration buffer");
+ return RFAILED;
+ }
hoPrepInfoIe->rrm_Config = NULLP;
hoPrepInfoIe->as_Context = NULLP;
{
uint8_t elementCnt = 0;
uint8_t ret = ROK;
- uint8_t idx, idx2, rrcBufLen;
+ uint8_t idx;
/* UE Capabulity RAT Container List */
CU_ALLOC(rrcMsg->uE_CapabilityRAT_ContainerList, sizeof(UE_CapabilityRAT_ContainerList_t));
}
return ret;
}
-
+/*******************************************************************
+ *
+ * @brief Build the drx cycle
+ *
+ * @details
+ *
+ * Function : BuildDrxCycle
+ *
+ * Functionality: Build drx cycle IE
+ *
+ * @params[in] pointer to DRXCycle_t
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ ******************************************************************/
+uint8_t BuildDrxCycle(DRXCycle_t *drxCycle)
+{
+ drxCycle->longDRXCycleLength = LongDRXCycleLength_ms80;
+ CU_ALLOC(drxCycle->shortDRXCycleLength, sizeof(ShortDRXCycleLength_t));
+ if(!drxCycle->shortDRXCycleLength)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed for shortDRXCycleLength");
+ return RFAILED;
+ }
+ *(drxCycle->shortDRXCycleLength) = ShortDRXCycleLength_ms4;
+
+ CU_ALLOC(drxCycle->shortDRXCycleTimer, sizeof(ShortDRXCycleTimer_t));
+ if(!drxCycle->shortDRXCycleTimer)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed for shortDRXCycleTimer");
+ return RFAILED;
+ }
+ *(drxCycle->shortDRXCycleTimer) = 4;
+ return ROK;
+}
/*******************************************************************
*
* @brief Free CuToDuContainer
* RFAILED - failure
*
* ****************************************************************/
-uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb, uint16_t rrcContLen, uint8_t *rrcContainer)
+uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb)
{
uint8_t Nrcgiret, SplCellListret, SrbSetupret;
uint8_t ret= RFAILED, ret1;
if(ueCb->state == UE_HANDOVER_IN_PROGRESS)
elementCnt = 7;
else
+ {
+#ifdef NR_DRX
elementCnt = 12;
+#else
+ elementCnt = 11;
+#endif
+ }
ueSetReq->protocolIEs.list.count = elementCnt;
ueSetReq->protocolIEs.list.size = elementCnt * sizeof(UEContextSetupRequestIEs_t *);
if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
{
+ /*Drx cycle*/
+#ifdef NR_DRX
+ idx++;
+ ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_DRXCycle;
+ ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_ignore;
+ ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_DRXCycle;
+ if(BuildDrxCycle(&ueSetReq->protocolIEs.list.array[idx]->value.choice.DRXCycle) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : Failed to build drx cycle");
+ break;
+ }
+#endif
/*Special Cells to be SetupList*/
idx++;
ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_SCell_ToBeSetup_List;
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;
if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
{
- /* RRC Container for security mode */
- idx++;
- ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_RRCContainer;
- ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_reject;
- ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_RRCContainer;
-
- char secModeBuf[9]={0x00, 0x02, 0x22, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00};
- bufLen =9;
- ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.size = bufLen;
- CU_ALLOC(ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.buf,
- ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.size);
- if(!ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.buf)
- {
- DU_LOG("\nERROR --> F1AP : Memory allocation for BuildAndSendUeContextSetupReq failed");
- break;
- }
- memset(ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.buf, 0, bufLen);
- memcpy(ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCContainer.buf, secModeBuf, bufLen);
-
/* RRC delivery status request */
idx++;
ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_RRCDeliveryStatusRequest;
* RFAILED - failure
*
* ****************************************************************/
-uint8_t addDrbTunnels(uint8_t teId)
+uint8_t addDrbTunnels(uint32_t duId, uint8_t teId)
{
uint8_t ret = ROK;
EgtpTnlEvt tnlEvt;
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);
* RFAILED - failure
*
* ****************************************************************/
-uint8_t procDrbSetupList(DRBs_Setup_List_t *drbSetupList)
+uint8_t procDrbSetupList(uint32_t duId, CuUeCb *ueCb, DRBs_Setup_List_t *drbSetupList)
{
- uint8_t arrIdx = 0;
+ uint8_t arrIdx = 0, drbIdx = 0;
uint32_t teId = 0;
DRBs_Setup_ItemIEs_t *drbItemIe = NULLP;
teId = extractTeId(&drbItemIe->value.choice.DRBs_Setup_Item.dLUPTNLInformation_ToBeSetup_List);
if(teId > 0)
{
- if(addDrbTunnels(teId)== ROK)
- {
- DU_LOG("\nDEBUG --> EGTP: Tunnel Added for TeId %d", teId);
- }
+ if(addDrbTunnels(duId, teId)== ROK)
+ {
+ DU_LOG("\nDEBUG --> EGTP: Tunnel Added for TeId %d", teId);
+ }
+ /* As per Spec 38.473, in UE COntext Response, Tunnel information
+ * are sent to CU for setting up of Tunnels in DL direction.
+ * Search for DRB ID in CU databse */
+ for(drbIdx = 0; drbIdx < ueCb->numDrb; drbIdx++)
+ {
+ if(ueCb->drbList[drbIdx].drbId == drbItemIe->value.choice.DRBs_Setup_Item.dRBID)
+ {
+ fillTeIdString(3, teId, ueCb->drbList[drbIdx].dlUpTnlInfo.teId);
+ break;
+ }
+ }
}
else
return RFAILED;
* ****************************************************************/
uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg)
{
- uint8_t duIdx=0, idx, duUeF1apId;
- DuDb *duDb;
- CuUeCb *ueCb;
+ uint8_t duIdx = 0, idx = 0, ueIdx = 0, rrcMsgType=0;
+ uint8_t duUeF1apId = 0, cuUeF1apId = 0;
+ DuDb *duDb = NULLP;
+ CuUeCb *ueCb = NULLP;
UEContextSetupResponse_t *ueCtxtSetupRsp = NULLP;
+ OCTET_STRING_t *duToCuRrcContainer;
SEARCH_DU_DB(duIdx, duId, duDb);
ueCtxtSetupRsp = &f1apMsg->choice.successfulOutcome->value.choice.UEContextSetupResponse;
{
switch(ueCtxtSetupRsp->protocolIEs.list.array[idx]->id)
{
+ case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
+ {
+ cuUeF1apId = ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.GNB_CU_UE_F1AP_ID;
+ break;
+ }
case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
{
duUeF1apId = ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.GNB_DU_UE_F1AP_ID;
ueCb = &duDb->ueCb[duUeF1apId-1];
+ /* If ue context is not present in du db, then create UE context
+ * here. This flow is hit in case of UE handover where UE
+ * context is created before UE performs RACH on target DU */
+ if(ueCb->gnbDuUeF1apId == 0)
+ {
+ /* Creating UE context in target DU */
+ memset(ueCb, 0, sizeof(CuUeCb));
+ ueCb->cellCb = &duDb->cellCb[0];
+ ueCb->gnbDuUeF1apId = duUeF1apId;
+ ueCb->gnbCuUeF1apId = cuUeF1apId;
+ ueCb->state = UE_HANDOVER_IN_PROGRESS;
+ ueCb->hoInfo.targetDuId = duId;
+ (duDb->numUe)++;
+
+ ueCb->cellCb->ueCb[ueCb->cellCb->numUe] = ueCb;
+ ueCb->cellCb->numUe++;
+ }
+ break;
+ }
+ case ProtocolIE_ID_id_C_RNTI:
+ {
+ ueCb->crnti = ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.C_RNTI;
break;
}
case ProtocolIE_ID_id_DRBs_Setup_List:
{
/* Adding Tunnels for successful DRB */
- procDrbSetupList(&ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.DRBs_Setup_List);
+ procDrbSetupList(duId, ueCb, &ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.DRBs_Setup_List);
break;
}
case ProtocolIE_ID_id_DUtoCURRCInformation:
{
DU_LOG("\nINFO --> Received Du to Cu RRC Information ");
+ duToCuRrcContainer = &ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.\
+ DUtoCURRCInformation.cellGroupConfig;
if((extractDuToCuRrcCont(ueCb, ueCtxtSetupRsp->protocolIEs.list.array[idx]->value.choice.\
DUtoCURRCInformation.cellGroupConfig)) != ROK)
{
}
}
}
- ueCb->f1apMsgDb.dlRrcMsgCount++; /* keeping DL RRC Msg Count */
+
+ /* If the UE is in handover, UE context modification request is to be sent to
+ * source DU once UE context setup response is received from target DU */
+ if(ueCb->state == UE_HANDOVER_IN_PROGRESS)
+ {
+ DuDb *srcDuDb = NULLP;
+ CuUeCb *ueCbInSrcDu = NULLP;
+
+ /* Since Source DU Id and DU UE F1AP ID assigned to UE by source DU is not known here, we
+ * need to find Source DU and UE CB in source DU using CU UE F1AP ID */
+ for(duIdx=0; duIdx < cuCb.numDu; duIdx++)
+ {
+ /* UE context setup response is received from target DU. Search all
+ * DUs to find source DU except this target DU Id.*/
+ if(cuCb.duInfo[duIdx].duId != duId)
+ {
+ for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++)
+ {
+ /* Check following:
+ * 1. CU UE F1AP ID in srcDU->ueCb should be same as cuUeF1apId
+ * received in UE context setup response since CU UE F1AP ID does not
+ * change for UE in handover.
+ * 2. srcDU->UeCb->uestate should be UE_HANDOVER_IN_PROGRESS
+ */
+ if((cuCb.duInfo[duIdx].ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId) &&
+ (cuCb.duInfo[duIdx].ueCb[ueIdx].state == UE_HANDOVER_IN_PROGRESS))
+ {
+ srcDuDb = &cuCb.duInfo[duIdx];
+ ueCbInSrcDu = &cuCb.duInfo[duIdx].ueCb[ueIdx];
+
+ /* Store source DU info in the new UE context created in
+ * tareget DU */
+ ueCb->hoInfo.sourceDuId = srcDuDb->duId;
+
+ /* Copy the received container to UeCb */
+ memcpy(&ueCbInSrcDu->f1apMsgDb.duToCuContainer, duToCuRrcContainer, sizeof(OCTET_STRING_t));
+
+ if(BuildAndSendUeContextModificationReq(srcDuDb->duId, ueCbInSrcDu, STOP_DATA_TX) != ROK)
+ {
+ DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextModificationReq()");
+ return RFAILED;
+ }
+ break;
+ }
+ }
+ }
+ if(srcDuDb && ueCbInSrcDu)
+ break;
+ }
+ }
+ else
+ {
+ ueCb->f1apMsgDb.dlRrcMsgCount++;
+ rrcMsgType = setDlRRCMsgType(ueCb);
+
+ DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC reconfiguration");
+ if(BuildAndSendDLRRCMessageTransfer(duId, ueCb, SRB1, rrcMsgType) != ROK)
+ {
+ DU_LOG("\nINFO --> F1AP: Failed to build and send DL RRC MSG for RRC reconfiguration");
+ return RFAILED;
+ }
+ }
+
return ROK;
}
uint8_t procUlRrcMsg(uint32_t duId, F1AP_PDU_t *f1apMsg)
{
- uint8_t idx, ret, srbId, rrcMsgType, duIdx=0;
- uint8_t cuUeF1apId, duUeF1apId;
- uint8_t *rrcContainer = NULLP;
- uint16_t rrcContLen;
- DuDb *duDb;
- CuUeCb *ueCb;
+ uint8_t idx = 0, ret = ROK, srbId = 0, rrcMsgType = 0, duIdx=0;
+ uint8_t *rrcContainer = NULLP;
+ uint16_t rrcContLen = 0;
+ uint32_t cuUeF1apId = 0, duUeF1apId = 0;
+ DuDb *duDb = NULLP;
+ CuUeCb *ueCb = NULLP;
ULRRCMessageTransfer_t *ulRrcMsg = NULLP;
ret = ROK;
return RFAILED;
}
memcpy(rrcContainer, ulRrcMsg->protocolIEs.list.array[idx]->value.choice.RRCContainer.buf, rrcContLen);
+
+ if(duDb->ueCb[duUeF1apId-1].state == UE_HANDOVER_IN_PROGRESS)
+ {
+ uint8_t ueIdx = 0;
+ uint8_t srcDuId = duDb->ueCb[duUeF1apId-1].hoInfo.sourceDuId;
+ DuDb *srcDuDb = NULLP;
+
+ /* In target DU DB, mark UE as active and delete HO info */
+ duDb->ueCb[duUeF1apId-1].state = UE_ACTIVE;
+ memset(&duDb->ueCb[duUeF1apId-1].hoInfo, 0, sizeof(HandoverInfo));
+
+ /* Release UE context in source DU because the UE is now
+ * attached to target DU */
+ SEARCH_DU_DB(duIdx, srcDuId, srcDuDb);
+ for(ueIdx = 0; ueIdx < srcDuDb->numUe; ueIdx++)
+ {
+ if(srcDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId)
+ {
+ ret = BuildAndSendUeContextReleaseCommand(srcDuId, srcDuDb->ueCb[ueIdx].gnbCuUeF1apId, srcDuDb->ueCb[ueIdx].gnbDuUeF1apId);
+ if(ret != ROK)
+ {
+ DU_LOG("\nINFO --> F1AP: Failed to build and send UE context release command to source DU Id [%d]", srcDuId);
+ }
+ break;
+ }
+ }
+ return ret;
+ }
break;
}
ueCb = &duDb->ueCb[duUeF1apId-1];
ueCb->f1apMsgDb.dlRrcMsgCount++;
rrcMsgType = setDlRRCMsgType(ueCb);
- if(rrcMsgType == REGISTRATION_ACCEPT)
+ if(rrcMsgType == RRC_SETUP_COMPLETE)
{
- DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC Registration Accept");
+ DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for NAS Security Mode Command");
ret = BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType);
}
- if(rrcMsgType == UE_CONTEXT_SETUP_REQ)
+ if(rrcMsgType == NAS_SECURITY_MODE_COMPLETE)
{
- DU_LOG("\nINFO --> F1AP: Sending Ue Context Setup Req");
- ret = BuildAndSendUeContextSetupReq(duId, ueCb, rrcContLen, rrcContainer);
+ DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC Security Mode Command");
+ ret = BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType);
}
- if(rrcMsgType == SECURITY_MODE_COMPLETE)
+ else if(rrcMsgType == RRC_SECURITY_MODE_COMPLETE)
{
- /* To trigger the DL RRC Msg for RRC Reconfig */
- ueCb->f1apMsgDb.dlRrcMsgCount++;
- rrcMsgType = setDlRRCMsgType(ueCb);
- if(rrcMsgType == RRC_RECONFIG)
- {
- DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC Reconfig");
- BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType);
- }
+ DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC Registration Accept");
+ BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType);
}
- if(rrcMsgType == RRC_RECONFIG_COMPLETE)
+ else if(rrcMsgType == REGISTRATION_COMPLETE)
{
- ueCb->state = UE_ACTIVE;
- ueCb->f1apMsgDb.dlRrcMsgCount++;
- rrcMsgType = setDlRRCMsgType(ueCb);
- if(rrcMsgType == UE_CONTEXT_MOD_REQ)
- {
- DU_LOG("\nINFO --> F1AP: Sending UE Context Modification Request");
- BuildAndSendUeContextModificationReq(duId, ueCb, RRC_RECONFIG_COMPLETE_IND);
- }
+ DU_LOG("\nINFO --> F1AP: Sending Ue Context Setup Request");
+ ret = BuildAndSendUeContextSetupReq(duId, ueCb);
+ }
+ else if(rrcMsgType == RRC_RECONFIG_COMPLETE)
+ {
+ DU_LOG("\nINFO --> F1AP: Sending UE Context Modification Request");
+ BuildAndSendUeContextModificationReq(duId, ueCb, RRC_RECONFIG_COMPLETE_IND);
}
}
return ret;
* RFAILED - failure
*
* ****************************************************************/
-uint8_t deleteEgtpTunnel(uint8_t *buf)
+uint8_t deleteEgtpTunnel(uint32_t duId, uint8_t *buf)
{
uint32_t teId = 0;
EgtpTnlEvt tnlEvt;
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);
}
* 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;
*
* ****************************************************************/
-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;
}
/*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)
{
*
* ****************************************************************/
-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;
*
* ****************************************************************/
-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;
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");
*
* ****************************************************************/
-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;
}/* 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)
{
*
* ****************************************************************/
-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;
*
* ****************************************************************/
-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;
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");
void FreeUeContextModicationRequest(F1AP_PDU_t *f1apMsg)
{
uint8_t arrIdx =0 , ieId=0;
- UEContextModificationRequest_t *UeContextModifyReq = NULLP;
+ UEContextModificationRequest_t *ueContextModifyReq = NULLP;
if(f1apMsg)
{
if(f1apMsg->choice.initiatingMessage)
{
- UeContextModifyReq =&f1apMsg->choice.initiatingMessage->value.choice.UEContextModificationRequest;
- if(UeContextModifyReq->protocolIEs.list.array)
+ ueContextModifyReq =&f1apMsg->choice.initiatingMessage->value.choice.UEContextModificationRequest;
+ if(ueContextModifyReq->protocolIEs.list.array)
{
- for( arrIdx = 0 ; arrIdx<UeContextModifyReq->protocolIEs.list.count ; arrIdx++)
+ for( arrIdx = 0 ; arrIdx<ueContextModifyReq->protocolIEs.list.count ; arrIdx++)
{
- if(UeContextModifyReq->protocolIEs.list.array[arrIdx])
+ if(ueContextModifyReq->protocolIEs.list.array[arrIdx])
{
- ieId = UeContextModifyReq->protocolIEs.list.array[arrIdx]->id;
+ ieId = ueContextModifyReq->protocolIEs.list.array[arrIdx]->id;
switch(ieId)
{
case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
break;
case ProtocolIE_ID_id_DRBs_ToBeSetupMod_List:
{
- FreeDrbToBeSetupModList(&UeContextModifyReq->protocolIEs.list.array[arrIdx]->value.\
+ FreeDrbToBeSetupModList(&ueContextModifyReq->protocolIEs.list.array[arrIdx]->value.\
choice.DRBs_ToBeSetupMod_List);
break;
}
case ProtocolIE_ID_id_DRBs_ToBeModified_List:
{
- FreeDrbToBeModifiedList(&UeContextModifyReq->protocolIEs.list.array[arrIdx]->value.\
- choice.DRBs_ToBeSetupMod_List);
+ FreeDrbToBeModifiedList(&ueContextModifyReq->protocolIEs.list.array[arrIdx]->value.\
+ choice.DRBs_ToBeModified_List);
break;
}
+ case ProtocolIE_ID_id_TransmissionActionIndicator:
+ break;
+ case ProtocolIE_ID_id_RRCContainer:
+ {
+ CU_FREE(ueContextModifyReq->protocolIEs.list.array[arrIdx]->value.choice.RRCContainer.buf,\
+ ueContextModifyReq->protocolIEs.list.array[arrIdx]->value.choice.RRCContainer.size);
+ }
}
- CU_FREE(UeContextModifyReq->protocolIEs.list.array[arrIdx], sizeof(UEContextModificationRequest_t));
+ CU_FREE(ueContextModifyReq->protocolIEs.list.array[arrIdx], sizeof(UEContextModificationRequest_t));
}
}
- CU_FREE(UeContextModifyReq->protocolIEs.list.array, UeContextModifyReq->protocolIEs.list.size);
+ CU_FREE(ueContextModifyReq->protocolIEs.list.array, ueContextModifyReq->protocolIEs.list.size);
}
CU_FREE(f1apMsg->choice.initiatingMessage, sizeof(InitiatingMessage_t));
}
CuUeCb *ueCb = (CuUeCb *)cuUeCb;
F1AP_PDU_t *f1apMsg = NULLP;
UEContextModificationRequest_t *ueContextModifyReq = NULLP;
-
asn_enc_rval_t encRetVal;
DU_LOG("\nINFO --> F1AP : Building Ue context modification request\n");
-
while(1)
{
CU_ALLOC(f1apMsg, sizeof(F1AP_PDU_t));
elementCnt = 3;
else if(action == RRC_RECONFIG_COMPLETE_IND)
elementCnt = 3;
+ else if((action == STOP_DATA_TX) || (action == RESTART_DATA_TX))
+ elementCnt = 5;
+
+#ifdef NR_DRX
+ if(DRX_TO_BE_RELEASE && ueCb->drxCfgPresent)
+ elementCnt++;
+#endif
ueContextModifyReq->protocolIEs.list.count = elementCnt;
ueContextModifyReq->protocolIEs.list.size = elementCnt*sizeof(UEContextModificationRequest_t *);
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 */
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 */
if(ret != ROK)
{
+ DU_LOG("\nERROR --> F1AP : BuildAndSendUeContextModificationReq(): Failed to build drb to be modified list");
break;
}
+
+ /* TODO: fill the RRC reconfiguration information in RRC Contaiiner ie in case of MODIFY_UE */
}
else if(action == QUERY_CONFIG)
{
ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCReconfigurationCompleteIndicator = \
RRCReconfigurationCompleteIndicator_true;
}
+ else if((action == STOP_DATA_TX) || (action == RESTART_DATA_TX))
+ {
+ ieIdx++;
+ if(action == STOP_DATA_TX)
+ {
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_TransmissionActionIndicator;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = \
+ UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.TransmissionActionIndicator = \
+ TransmissionActionIndicator_stop;
+ }
+ else if (action == RESTART_DATA_TX)
+ {
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_TransmissionActionIndicator;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = \
+ UEContextModificationRequestIEs__value_PR_TransmissionActionIndicator;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.TransmissionActionIndicator = \
+ TransmissionActionIndicator_restart;
+ }
+
+ ieIdx++;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_RRCContainer;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = \
+ UEContextModificationRequestIEs__value_PR_RRCContainer;
+ if(fillRrcReconfigBuf(ueCb, &ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer, true) != ROK)
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to fill Rrc reconfiguration buffer");
+ return RFAILED;
+ }
+
+ /* 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;
+ }
+
+#ifdef NR_DRX
+ if(DRX_TO_BE_RELEASE && ueCb->drxCfgPresent)
+ {
+ /* DRX Configuration Indicator */
+ ieIdx++;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_DRXConfigurationIndicator;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = UEContextModificationRequestIEs__value_PR_DRXConfigurationIndicator;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.DRXConfigurationIndicator = DRXConfigurationIndicator_release;
+ ueCb->drxCfgPresent = false;
+ memset(&ueCb->drxCfg, 0, sizeof(DrxCfg));
+ }
+#endif
xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg);
else
{
DU_LOG("\nDEBUG --> F1AP : Created APER encodedbuffer for ueContextModifyReq\n");
+#if 0
+ /* This for loop was going into an infinite loop even though encBufSize
+ * has a small value. Hence commented this
+ */
for(ieIdx=0; ieIdx< encBufSize; ieIdx++)
{
DU_LOG("%x",encBuf[ieIdx]);
}
+#endif
}
/* TODO : Hardcoding DU ID to 1 for messages other than F1 Setup Response. This will be made generic in future gerrit */
struct Served_Cells_To_Delete_ItemIEs *deleteItemIe = \
(struct Served_Cells_To_Delete_ItemIEs *)duCfgUpdate->protocolIEs.list.array[ieIdx]->value.choice.\
Served_Cells_To_Delete_List.list.array[0];
- nrCellId = deleteItemIe->value.choice.Served_Cells_To_Delete_Item.oldNRCGI.nRCellIdentity.buf[4] >>\
- deleteItemIe->value.choice.Served_Cells_To_Delete_Item.oldNRCGI.nRCellIdentity.bits_unused;
+ bitStringToInt(&deleteItemIe->value.choice.Served_Cells_To_Delete_Item.oldNRCGI.nRCellIdentity, &nrCellId);
cellToBeDelete = true;
break;
}
{
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;
}
* 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;
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);
}
* ****************************************************************/
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);
{
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;
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;
}
}
}
+
+ /* If UE is in handover and UE context is not yet created at target DU, then send
+ * UE context setup request to target DU */
if(ueCb->state == UE_HANDOVER_IN_PROGRESS)
{
- BuildAndSendUeContextSetupReq(ueCb->hoInfo.targetDuId, ueCb, 0, NULLP);
- return ROK;
+ uint8_t ueIdx = 0;
+ DuDb *tgtDuDb = NULLP;
+ CuUeCb *ueCbInTgtDu = NULLP;
+
+ SEARCH_DU_DB(duIdx, ueCb->hoInfo.targetDuId, tgtDuDb);
+ if(tgtDuDb)
+ {
+ /* Since DU UE F1AP ID assigned by target DU to this UE in handover is
+ * not known here, using CU UE F1AP ID to search for UE Cb in target DU
+ * DB */
+ for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++)
+ {
+ if(tgtDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId)
+ {
+ ueCbInTgtDu = &tgtDuDb->ueCb[ueIdx];
+ break;
+ }
+ }
+
+ /* If UE context is not found in Target DU DU, send UE context setup
+ * request */
+ if(ueCbInTgtDu == NULLP)
+ {
+ if((BuildAndSendUeContextSetupReq(ueCb->hoInfo.targetDuId, ueCb)) != ROK)
+ {
+ DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextSetupReq");
+ return RFAILED;
+ }
+ }
+ }
}
return ROK;
void procF1SetupReq(uint32_t *destDuId, F1AP_PDU_t *f1apMsg)
{
uint8_t ieIdx = 0, plmnidx=0, duIdx = 0, ret=ROK, cellIdx = 0;
- uint32_t duId = 0, nrCellId = 0;
+ uint32_t duId = 0;
+ uint64_t nrCellId = 0;
DuDb *duDb = NULLP;
CuCellCb *cellCb = NULLP;
BIT_STRING_t nrcellIdentity;
if(duDb == NULLP)
{
duDb = &cuCb.duInfo[cuCb.numDu];
- memset(duDb, 0, sizeof(DuDb));
- duDb->duId = duId;
cuCb.numDu++;
- *destDuId = duId;
}
- else
- return;
+ memset(duDb, 0, sizeof(DuDb));
+ duDb->duId = duId;
+ *destDuId = duId;
break;
}
case ProtocolIE_ID_id_gNB_DU_Name:
srvCellItem = &duServedCell->list.array[plmnidx]->value.choice.GNB_DU_Served_Cells_Item;
ret = procServedCellPlmnList(&srvCellItem->served_Cell_Information.servedPLMNs);
memcpy(&nrcellIdentity, &srvCellItem->served_Cell_Information.nRCGI.nRCellIdentity, sizeof(BIT_STRING_t));
-
- nrCellId = nrcellIdentity.buf[4] >> nrcellIdentity.bits_unused;
+
+ bitStringToInt(&nrcellIdentity, &nrCellId);
SEARCH_CELL_DB(cellIdx, duDb, nrCellId, cellCb);
if(cellCb == NULLP)
{
cellCb = &duDb->cellCb[duDb->numCells];
memset(cellCb, 0, sizeof(CuCellCb));
cellCb->nrCellId = nrCellId;
+ cellCb->cellStatus = CELL_ACTIVE;
duDb->numCells++;
}
}
}
}
+/****************************************************************
+*
+* @brief processing of UE Context Release Complete
+*
+* @details
+*
+* Function : procUeContextReleaseComplete
+*
+* Functionality:
+* - processing of UE Context Release Complete
+*
+* @params[in] F1AP_PDU_t *f1apMsg
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+void procUeContextReleaseComplete(uint32_t duId, F1AP_PDU_t *f1apMsg)
+{
+ uint8_t duIdx = 0, ieIdx = 0, ueIdx = 0, drbIdx = 0;
+ uint8_t gnbDuUeF1apId = 0, gnbCuUeF1apId = 0;
+ DuDb *duDb = NULLP;
+ CuUeCb *ueCb = NULLP;
+ UEContextReleaseComplete_t *ueReleaseComplete = NULLP;
+
+ SEARCH_DU_DB(duIdx, duId, duDb);
+ if(!duDb)
+ {
+ DU_LOG("\nERROR --> F1AP : No entry found for DU ID [%d]", duId);
+ return;
+ }
+
+ ueReleaseComplete = &f1apMsg->choice.successfulOutcome->value.choice.UEContextReleaseComplete;
+ for(ieIdx=0; ieIdx < ueReleaseComplete->protocolIEs.list.count; ieIdx++)
+ {
+ switch(ueReleaseComplete->protocolIEs.list.array[ieIdx]->id)
+ {
+ case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
+ {
+ gnbCuUeF1apId = ueReleaseComplete->protocolIEs.list.array[ieIdx]->value.choice.GNB_CU_UE_F1AP_ID;
+ break;
+ }
+ case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
+ {
+ gnbDuUeF1apId = ueReleaseComplete->protocolIEs.list.array[ieIdx]->value.choice.GNB_DU_UE_F1AP_ID;
+ ueCb = &duDb->ueCb[gnbDuUeF1apId-1];
+ for(ueIdx = 0; ueIdx <MAX_NUM_UE; ueIdx++)
+ {
+ if(ueCb->cellCb && ueCb->cellCb->ueCb[ueIdx])
+ {
+ if((ueCb->cellCb->ueCb[ueIdx]->gnbCuUeF1apId == gnbCuUeF1apId) &&
+ (ueCb->cellCb->ueCb[ueIdx]->gnbDuUeF1apId == gnbDuUeF1apId))
+ {
+ for(drbIdx = 0; drbIdx < ueCb->numDrb; drbIdx++)
+ {
+ deleteEgtpTunnel(duId, ueCb->drbList[drbIdx].dlUpTnlInfo.teId);
+ }
+ ueCb->cellCb->ueCb[ueIdx] = NULLP;
+ ueCb->cellCb->numUe--;
+ if((ueCb->cellCb->numUe == 0) && (ueCb->cellCb->cellStatus == CELL_DELETION_IN_PROGRESS))
+ {
+ memset(ueCb->cellCb, 0, sizeof(CuCellCb));
+ duDb->numCells--;
+ }
+ break;
+ }
+ }
+ }
+ memset(ueCb, 0, sizeof(CuUeCb));
+ duDb->numUe--;
+ break;
+ }
+ }
+ }
+}
+
+/*******************************************************************
+ *
+ * @brief Builds the Paging cell list
+ *
+ * @details
+ *
+ * Function : BuildPagingCellList
+ *
+ * Functionality: Build the paging cell list
+ *
+ * @params[in] PagingCell_list_t *pagingCelllist,
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t BuildPagingCellList(PagingCell_list_t *pagingCelllist, uint8_t numCells, CuCellCb *cellCb)
+{
+ uint8_t cellIdx =0;
+ PagingCell_ItemIEs_t *pagingCellItemIes;
+ PagingCell_Item_t *pagingCellItem;
+
+ pagingCelllist->list.count = numCells;
+ pagingCelllist->list.size = pagingCelllist->list.count * (sizeof(PagingCell_ItemIEs_t*));
+ CU_ALLOC(pagingCelllist->list.array, pagingCelllist->list.size);
+ if(pagingCelllist->list.array == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildPagingCellList(): Memory allocation failed ");
+ return RFAILED;
+ }
+
+ for(cellIdx = 0; cellIdx < pagingCelllist->list.count; cellIdx++)
+ {
+ CU_ALLOC(pagingCelllist->list.array[cellIdx], sizeof(PagingCell_ItemIEs_t));
+ if(pagingCelllist->list.array[cellIdx] == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildPagingCellList(): Memory allocation failed ");
+ return RFAILED;
+ }
+ }
+
+ for(cellIdx = 0; cellIdx < pagingCelllist->list.count; cellIdx++)
+ {
+ pagingCellItemIes = (PagingCell_ItemIEs_t *)pagingCelllist->list.array[cellIdx];
+ pagingCellItemIes->id = ProtocolIE_ID_id_PagingCell_Item;
+ pagingCellItemIes->criticality = Criticality_ignore;
+ pagingCellItemIes->value.present = PagingCell_ItemIEs__value_PR_PagingCell_Item;
+ pagingCellItem = &pagingCellItemIes->value.choice.PagingCell_Item;
+
+ /* Fill NrCgi Information */
+ BuildNrcgi(&pagingCellItem->nRCGI, cellCb[cellIdx].nrCellId);
+ }
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Deallocation of memory allocated in paging msg
+ *
+ * @details
+ *
+ * Function :FreePagingMsg
+ *
+ * Functionality: Deallocation of memory allocated in paging msg
+ *
+ * @params[in] F1AP_PDU_t *f1apMsg
+ *
+ * @return void
+ *
+ * ****************************************************************/
+void FreePagingMsg(F1AP_PDU_t *f1apMsg)
+{
+ uint8_t ieIdx, cellIdx;
+ Paging_t *paging;
+ PagingCell_ItemIEs_t *pagingCellItemIes;
+ PagingCell_Item_t *pagingCellItem;
+ PagingCell_list_t *pagingCelllist;
+
+ if(f1apMsg)
+ {
+ if(f1apMsg->choice.initiatingMessage)
+ {
+ paging = &f1apMsg->choice.initiatingMessage->value.choice.Paging;
+ if(paging->protocolIEs.list.array)
+ {
+ for(ieIdx=0 ; ieIdx<paging->protocolIEs.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 ; ieIdx<elementCnt; ieIdx++)
+ {
+ CU_ALLOC(paging->protocolIEs.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
case SuccessfulOutcome__value_PR_UEContextReleaseComplete:
{
DU_LOG("\nINFO --> F1AP : UE Context release complete received");
+ procUeContextReleaseComplete(*duId, f1apMsg);
break;
}
default: