+ srbToAddList->list.count = elementCnt;
+ srbToAddList->list.size = srbToAddList->list.count * sizeof(SRB_ToAddMod_t *);
+
+ CU_ALLOC(srbToAddList->list.array, srbToAddList->list.size);
+ if(!srbToAddList->list.array)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for SRB to AddMod list array in fillSrbToAddModList");
+ return RFAILED;
+ }
+
+ srbIdx = 0;
+ for(srbDbIdx = 0; srbDbIdx < ueCb->numSrb; srbDbIdx++)
+ {
+ if(!updateAllRbCfg && ueCb->srbList[srbDbIdx].cfgSentToUe)
+ continue;
+
+ CU_ALLOC(srbToAddList->list.array[srbIdx], sizeof(SRB_ToAddMod_t));
+ if(!srbToAddList->list.array[srbIdx])
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for SRB to AddMod list element in fillSrbToAddModList");
+ return RFAILED;
+ }
+
+ srbToAddList->list.array[srbIdx]->srb_Identity = ueCb->srbList[srbDbIdx].srbId;
+
+ /* Reestablish PDCP */
+ CU_ALLOC(srbToAddList->list.array[srbIdx]->reestablishPDCP, sizeof(long));
+ if(!srbToAddList->list.array[srbIdx]->reestablishPDCP)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for reestablish PDCP IE in fillSrbToAddModList");
+ return RFAILED;
+ }
+ *(srbToAddList->list.array[srbIdx]->reestablishPDCP) = SRB_ToAddMod__reestablishPDCP_true;
+
+ /* PDCP configuration */
+ CU_ALLOC(srbToAddList->list.array[srbIdx]->pdcp_Config, sizeof(PDCP_Config_t));
+ if(!srbToAddList->list.array[srbIdx]->pdcp_Config)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for PDCP config IE in fillSrbToAddModList");
+ return RFAILED;
+ }
+
+ /* Reordering timer */
+ CU_ALLOC(srbToAddList->list.array[srbIdx]->pdcp_Config->t_Reordering, sizeof(long));
+ if(!srbToAddList->list.array[srbIdx]->pdcp_Config->t_Reordering)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for reordering timer in fillSrbToAddModList");
+ return RFAILED;
+ }
+ *(srbToAddList->list.array[srbIdx]->pdcp_Config->t_Reordering) = PDCP_Config__t_Reordering_ms40;
+
+ srbIdx++;
+ }
+ return ROK;
+}
+
+/******************************************************************
+ *
+ * @biief Fill DRBeTo Add Mod list
+ *
+ * @details
+ *
+ * Function : fillDrbToAddModList
+ *
+ * Functionality: fill DRB to Add Mod list
+ *
+ * @params[in] UE control block
+ * DRB to Add/Mod list
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillDrbToAddModList(CuUeCb *ueCb, DRB_ToAddModList_t *drbToAddList, bool updateAllRbCfg)
+{
+ uint8_t drbIdx, drbDbIdx, elementCnt = 0;
+
+ if(updateAllRbCfg)
+ elementCnt = ueCb->numDrb;
+ else
+ {
+ for(drbDbIdx=0; drbDbIdx < ueCb->numDrb; drbDbIdx++)
+ {
+ if(ueCb->drbList[drbDbIdx].cfgSentToUe == false)
+ 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(!drbToAddList->list.array)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for DRB to AddMod list array in fillDrbToAddModList");
+ return RFAILED;
+ }
+
+ drbIdx = 0;
+ for(drbDbIdx=0; drbDbIdx < ueCb->numDrb; drbDbIdx++)
+ {
+ if(!updateAllRbCfg && ueCb->drbList[drbDbIdx].cfgSentToUe)
+ continue;
+
+ CU_ALLOC(drbToAddList->list.array[drbIdx], sizeof(DRB_ToAddMod_t));
+ if(!drbToAddList->list.array[drbIdx])
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for DRB to AddMod list elements in fillDrbToAddModList");
+ return RFAILED;
+ }
+
+ /* DRB Id */
+ drbToAddList->list.array[drbIdx]->drb_Identity = ueCb->drbList[drbDbIdx].drbId;
+
+ /* PDCP Config */
+ CU_ALLOC(drbToAddList->list.array[drbIdx]->pdcp_Config, sizeof(PDCP_Config_t));
+ if(!drbToAddList->list.array[drbIdx]->pdcp_Config)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for PDCP config IE in fillDrbToAddModList");
+ return RFAILED;
+ }
+
+ /* PDCP Config -> DRB */
+ CU_ALLOC(drbToAddList->list.array[drbIdx]->pdcp_Config->drb, sizeof(struct PDCP_Config__drb));
+ if(!drbToAddList->list.array[drbIdx]->pdcp_Config->drb)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for PDCP config drb in fillDrbToAddModList");
+ return RFAILED;
+ }
+
+ /* DRB -> Discard Timer */
+ CU_ALLOC(drbToAddList->list.array[drbIdx]->pdcp_Config->drb->discardTimer, sizeof(long));
+ if(!drbToAddList->list.array[drbIdx]->pdcp_Config->drb->discardTimer)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for DRB discard timer in fillDrbToAddModList");
+ return RFAILED;
+ }
+ *(drbToAddList->list.array[drbIdx]->pdcp_Config->drb->discardTimer) = PDCP_Config__drb__discardTimer_infinity;
+
+ /* UL PDCP SN length */
+ CU_ALLOC(drbToAddList->list.array[drbIdx]->pdcp_Config->drb->pdcp_SN_SizeUL, sizeof(long));
+ if(!drbToAddList->list.array[drbIdx]->pdcp_Config->drb->pdcp_SN_SizeUL)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for UL SN length in fillDrbToAddModList");
+ return RFAILED;
+ }
+ *(drbToAddList->list.array[drbIdx]->pdcp_Config->drb->pdcp_SN_SizeUL) = PDCP_Config__drb__pdcp_SN_SizeUL_len12bits;
+
+ /* DL PDCP SN length */
+ CU_ALLOC(drbToAddList->list.array[drbIdx]->pdcp_Config->drb->pdcp_SN_SizeDL, sizeof(long));
+ if(!drbToAddList->list.array[drbIdx]->pdcp_Config->drb->pdcp_SN_SizeDL)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for DL SN length in fillDrbToAddModList");
+ return RFAILED;
+ }
+ *(drbToAddList->list.array[drbIdx]->pdcp_Config->drb->pdcp_SN_SizeDL) = PDCP_Config__drb__pdcp_SN_SizeDL_len12bits;
+
+ /* Header Compression */
+ drbToAddList->list.array[drbIdx]->pdcp_Config->drb->headerCompression.present = PDCP_Config__drb__headerCompression_PR_notUsed;
+ drbToAddList->list.array[drbIdx]->pdcp_Config->drb->headerCompression.choice.notUsed = NULLP;
+
+ /* Reordering timer */
+ CU_ALLOC(drbToAddList->list.array[drbIdx]->pdcp_Config->t_Reordering, sizeof(long));
+ if(!drbToAddList->list.array[drbIdx]->pdcp_Config->t_Reordering)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for reordering timer in fillDrbToAddModList");
+ return RFAILED;
+ }
+ *(drbToAddList->list.array[drbIdx]->pdcp_Config->t_Reordering) = PDCP_Config__t_Reordering_ms40;
+
+ drbIdx++;
+ }
+
+ return ROK;
+}
+
+/******************************************************************
+ *
+ * @brief Fill Radio bearer configuration
+ *
+ * @details
+ *
+ * Function : fillRadioBearerConfig
+ *
+ * Functionality: Fill Radio bearer configuration
+ *
+ * @params[in] UE control block
+ * Radio bearer config pointer
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillRadioBearerConfig(CuUeCb *ueCb, RadioBearerConfig_t *radioBearerConfig, bool updateAllRbCfg)
+{
+ /* SRB To Add/Mod List */
+ CU_ALLOC(radioBearerConfig->srb_ToAddModList, sizeof(SRB_ToAddModList_t));
+ if(!radioBearerConfig->srb_ToAddModList)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for SRB to AddMod List in fillRadioBearerConfig");
+ return RFAILED;
+ }
+ if(fillSrbToAddModList(ueCb, radioBearerConfig->srb_ToAddModList, updateAllRbCfg) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP: failed to fill SRB to AddMod List");
+ return RFAILED;
+ }
+
+ /* DRB To Add/Mod List */
+ CU_ALLOC(radioBearerConfig->drb_ToAddModList, sizeof(DRB_ToAddModList_t));
+ if(!radioBearerConfig->drb_ToAddModList)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for DRB to AddMod List in fillRadioBearerConfig");
+ return RFAILED;
+ }
+ if(fillDrbToAddModList(ueCb, radioBearerConfig->drb_ToAddModList, updateAllRbCfg) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP: failed to fill DRB to AddMod List ");
+ return RFAILED;
+ }
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill measurement object to add/mod list
+ *
+ * @details
+ *
+ * Function : fillMeasObjToAddModList
+ *
+ * Functionality: Fill measurement object to add/mod list
+ *
+ * @params[in] Measurement object to add/mod list
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillMeasObjToAddModList(MeasObjectToAddModList_t *measObjList)
+{
+ uint8_t elementCnt, objIdx;
+ MeasObjectNR_t *measObject;
+
+ elementCnt = 1;
+ measObjList->list.count = elementCnt;
+ measObjList->list.size = measObjList->list.count * sizeof(MeasObjectToAddMod_t *);
+
+ CU_ALLOC(measObjList->list.array, measObjList->list.size);
+ if(!measObjList->list.array)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for measurement object list's array");
+ return RFAILED;
+ }
+
+ for(objIdx = 0; objIdx < measObjList->list.size; objIdx++)
+ {
+ CU_ALLOC(measObjList->list.array[objIdx], sizeof(MeasObjectToAddMod_t));
+ if(!measObjList->list.array[objIdx])
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for measurement object list's array element");
+ return RFAILED;
+ }
+ }
+
+ objIdx = 0;
+ measObjList->list.array[objIdx]->measObjectId = 1;
+ measObjList->list.array[objIdx]->measObject.present = MeasObjectToAddMod__measObject_PR_measObjectNR;
+ CU_ALLOC(measObjList->list.array[objIdx]->measObject.choice.measObjectNR, sizeof(MeasObjectNR_t));
+ if(!measObjList->list.array[objIdx]->measObject.choice.measObjectNR)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for mesurement object NR");
+ return RFAILED;
+ }
+
+ measObject = measObjList->list.array[objIdx]->measObject.choice.measObjectNR;
+
+ /* SSB frequency */
+ CU_ALLOC(measObject->ssbFrequency, sizeof(ARFCN_ValueNR_t));
+ if(!measObject->ssbFrequency)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for SSB frequency in fillMeasObjToAddModList");
+ return RFAILED;
+ }
+ *(measObject->ssbFrequency) = 620736; /* Value picked from reference PCAP logs */
+
+ /* Subcarrier spacing */
+ CU_ALLOC(measObject->ssbSubcarrierSpacing, sizeof(SubcarrierSpacing_t));
+ if(!measObject->ssbSubcarrierSpacing)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for SSB subcarrier spacing in fillMeasObjToAddModList");
+ return RFAILED;
+ }
+ *(measObject->ssbSubcarrierSpacing) = SubcarrierSpacing_kHz15;
+
+ /* SMTC1 */
+ CU_ALLOC(measObject->smtc1 , sizeof(SSB_MTC_t));
+ if(!measObject->smtc1)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for SMTC1 in fillMeasObjToAddModList");
+ return RFAILED;
+ }
+ measObject->smtc1->duration = SSB_MTC__duration_sf1;
+ measObject->smtc1->periodicityAndOffset.present = SSB_MTC__periodicityAndOffset_PR_sf20;
+ measObject->smtc1->periodicityAndOffset.choice.sf20 = 0;
+
+ /* Absoulute threshold SSB consolidation */
+ CU_ALLOC(measObject->absThreshSS_BlocksConsolidation, sizeof(ThresholdNR_t));
+ if(!measObject->absThreshSS_BlocksConsolidation)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for absolute threshold SSB consolidation in fillMeasObjToAddModList");
+ return RFAILED;
+ }
+
+ /* RSRP threshold */
+ CU_ALLOC(measObject->absThreshSS_BlocksConsolidation->thresholdRSRP, sizeof(RSRP_Range_t));
+ if(!measObject->absThreshSS_BlocksConsolidation->thresholdRSRP)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for threshold RSRP in fillMeasObjToAddModList");
+ return RFAILED;
+ }
+ *(measObject->absThreshSS_BlocksConsolidation->thresholdRSRP) = 1;
+
+ /* RSRQ threshold */
+ CU_ALLOC(measObject->absThreshSS_BlocksConsolidation->thresholdRSRQ, sizeof(RSRQ_Range_t));
+ if(!measObject->absThreshSS_BlocksConsolidation->thresholdRSRQ)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for threshold RSRQ in fillMeasObjToAddModList");
+ return RFAILED;
+ }
+ *(measObject->absThreshSS_BlocksConsolidation->thresholdRSRQ) = 1;
+
+ /* SINR threshold */
+ CU_ALLOC(measObject->absThreshSS_BlocksConsolidation->thresholdSINR, sizeof(SINR_Range_t));
+ if(!measObject->absThreshSS_BlocksConsolidation->thresholdSINR)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for threshold SINR in fillMeasObjToAddModList");
+ return RFAILED;
+ }
+ *(measObject->absThreshSS_BlocksConsolidation->thresholdSINR) = 1;
+
+ /* Number of SSBs to average */
+ CU_ALLOC(measObject->nrofSS_BlocksToAverage, sizeof(long));
+ if(!measObject->nrofSS_BlocksToAverage)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for number of SSB to average in fillMeasObjToAddModList");
+ return RFAILED;
+ }
+ *(measObject->nrofSS_BlocksToAverage) = 2;
+
+ /* Quantity Config index */
+ measObject->quantityConfigIndex = 1;
+
+ /* Offset MO */
+ /* RSRP offset for SSB */
+ CU_ALLOC(measObject->offsetMO.rsrpOffsetSSB, sizeof(Q_OffsetRange_t));
+ if(!measObject->offsetMO.rsrpOffsetSSB)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for SSB RSRP offset in fillMeasObjToAddModList");
+ return RFAILED;
+ }
+ *(measObject->offsetMO.rsrpOffsetSSB) = Q_OffsetRange_dB0;
+
+ /* RSRQ offset for SSB */
+ CU_ALLOC(measObject->offsetMO.rsrqOffsetSSB, sizeof(Q_OffsetRange_t));
+ if(!measObject->offsetMO.rsrpOffsetSSB)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for SSB RSRQ offset in fillMeasObjToAddModList");
+ return RFAILED;
+ }
+ *(measObject->offsetMO.rsrqOffsetSSB) = Q_OffsetRange_dB0;
+
+ /* SINR offset for SSB */
+ CU_ALLOC(measObject->offsetMO.sinrOffsetSSB, sizeof(Q_OffsetRange_t));
+ if(!measObject->offsetMO.sinrOffsetSSB)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for SSB SINR offset in fillMeasObjToAddModList");
+ return RFAILED;
+ }
+ *(measObject->offsetMO.sinrOffsetSSB) = Q_OffsetRange_dB0;
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill Report configuration to Add/mod list
+ *
+ * @details
+ *
+ * Function : fillReportCfgToAddModList
+ *
+ * Functionality: Fill Report configuration to Add/mod list
+ *
+ * @params[in] Report Config To Add/Mod List
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillReportCfgToAddModList(ReportConfigToAddModList_t *reportCfgList)
+{
+ uint8_t elementCnt;
+ uint8_t reportCfgIdx;
+ ReportConfigToAddMod_t *reportCfg;
+ ReportConfigNR_t *reportCfgNr;
+ EventTriggerConfig_t *eventTriggCfg;
+
+ elementCnt = 1;
+ reportCfgList->list.count = elementCnt;
+ reportCfgList->list.size = reportCfgList->list.count * sizeof(ReportConfigToAddMod_t *);
+
+ CU_ALLOC(reportCfgList->list.array, reportCfgList->list.size);
+ if(!reportCfgList->list.array)
+ {
+ DU_LOG("\nERROR --> F1AP: fillReportCfgToAddModList() :Memory allocation failed for report config list's array");
+ return RFAILED;
+ }
+
+ for(reportCfgIdx=0; reportCfgIdx < reportCfgList->list.count; reportCfgIdx++)
+ {
+ CU_ALLOC(reportCfgList->list.array[reportCfgIdx], sizeof(ReportConfigToAddMod_t));
+ if(!reportCfgList->list.array[reportCfgIdx])
+ {
+ DU_LOG("\nERROR --> F1AP: fillReportCfgToAddModList(): Memory allocation failed for report config list's array element");
+ return RFAILED;
+ }
+ }
+
+ reportCfgIdx = 0;
+ reportCfg = reportCfgList->list.array[reportCfgIdx];
+ reportCfg->reportConfigId = 1;
+ reportCfg->reportConfig.present = ReportConfigToAddMod__reportConfig_PR_reportConfigNR;
+
+ /* Report Configuration for NR */
+ CU_ALLOC(reportCfg->reportConfig.choice.reportConfigNR, sizeof(ReportConfigNR_t));
+ if(!reportCfg->reportConfig.choice.reportConfigNR)
+ {
+ DU_LOG("\nERROR --> F1AP: fillReportCfgToAddModList(): Memory allocation failed for report config NR");
+ return RFAILED;
+ }
+ reportCfgNr = reportCfg->reportConfig.choice.reportConfigNR;
+
+ /* Report Type */
+ reportCfgNr->reportType.present = ReportConfigNR__reportType_PR_eventTriggered;
+ CU_ALLOC(reportCfgNr->reportType.choice.eventTriggered, sizeof(EventTriggerConfig_t));
+ if(!reportCfgNr->reportType.choice.eventTriggered)
+ {
+ DU_LOG("\nERROR --> F1AP: fillReportCfgToAddModList(): Memory allocation failed for event triggerred");
+ return RFAILED;
+ }
+ eventTriggCfg = reportCfgNr->reportType.choice.eventTriggered;
+
+ /* Event 3 */
+ eventTriggCfg->eventId.present = EventTriggerConfig__eventId_PR_eventA3;
+ CU_ALLOC(eventTriggCfg->eventId.choice.eventA3, sizeof(struct EventTriggerConfig__eventId__eventA3));
+ if(!eventTriggCfg->eventId.choice.eventA3)
+ {
+ DU_LOG("\nERROR --> F1AP: fillReportCfgToAddModList(): Memory allocation failed for event A3");
+ return RFAILED;
+ }
+
+ eventTriggCfg->eventId.choice.eventA3->a3_Offset.present = MeasTriggerQuantityOffset_PR_rsrp;
+ eventTriggCfg->eventId.choice.eventA3->a3_Offset.choice.rsrp = 6; /* i.e. 3.0db . From Reference pcap log */
+ eventTriggCfg->eventId.choice.eventA3->reportOnLeave = false;
+ eventTriggCfg->eventId.choice.eventA3->hysteresis = 0;
+ eventTriggCfg->eventId.choice.eventA3->timeToTrigger = TimeToTrigger_ms40;
+ eventTriggCfg->eventId.choice.eventA3->useWhiteCellList = false;
+
+ /* Reference Signal Type */
+ eventTriggCfg->rsType = NR_RS_Type_ssb;
+
+ /* Report Interval */
+ eventTriggCfg->reportInterval = ReportInterval_ms1024;
+
+ /* Report Amount */
+ eventTriggCfg->reportAmount = EventTriggerConfig__reportAmount_r8;
+
+ /* Report Quantity cell */
+ eventTriggCfg->reportQuantityCell.rsrp = true;
+ eventTriggCfg->reportQuantityCell.rsrq = false;
+ eventTriggCfg->reportQuantityCell.sinr = false;
+
+ /* Maximum reported cells */
+ eventTriggCfg->maxReportCells = 3;
+
+ /* Report qunatity RS Indexes */
+ CU_ALLOC(eventTriggCfg->reportQuantityRS_Indexes, sizeof(MeasReportQuantity_t));
+ if(!eventTriggCfg->reportQuantityRS_Indexes)
+ {
+ DU_LOG("\nERROR --> F1AP: fillReportCfgToAddModList(): Memory allocation failed for report qunatity RS indexes");
+ return RFAILED;
+ }
+ eventTriggCfg->reportQuantityRS_Indexes->rsrp = true;
+ eventTriggCfg->reportQuantityRS_Indexes->rsrq = false;
+ eventTriggCfg->reportQuantityRS_Indexes->sinr = false;
+
+ /* Maximum number of RS indexes to report */
+ CU_ALLOC(eventTriggCfg->maxNrofRS_IndexesToReport, sizeof(long));
+ if(!eventTriggCfg->maxNrofRS_IndexesToReport)
+ {
+ DU_LOG("\nERROR --> F1AP: fillReportCfgToAddModList(): Memory allocation failed for max number of RS indexes to report");
+ return RFAILED;
+ }
+ *(eventTriggCfg->maxNrofRS_IndexesToReport) = 1;
+
+ /* Include Beam measurement */
+ eventTriggCfg->includeBeamMeasurements = false;
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill measurement Id to add/mod list
+
+ * @details
+ *
+ * Function : fillMeasIdToAddModList
+ *
+ * Functionality: Fill measurement Id to add/mod list
+ *
+ * @params[in] Measurement Id to add/mod list
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillMeasIdToAddModList(MeasIdToAddModList_t *measIdList)
+{
+ uint8_t elementCnt;
+ uint8_t measIdIdx;
+
+ elementCnt = 1;
+ measIdList->list.count = elementCnt;
+ measIdList->list.size = measIdList->list.count *sizeof(MeasIdToAddMod_t *);
+
+ CU_ALLOC(measIdList->list.array, measIdList->list.size);
+ if(!measIdList->list.array)
+ {
+ return RFAILED;
+ }
+
+ for(measIdIdx=0; measIdIdx < measIdList->list.count; measIdIdx++)
+ {
+ CU_ALLOC(measIdList->list.array[measIdIdx], sizeof(MeasIdToAddMod_t));
+ if(!measIdList->list.array[measIdIdx])
+ {
+ return RFAILED;
+ }
+
+ measIdIdx=0;
+ measIdList->list.array[measIdIdx]->measId = 1;
+ measIdList->list.array[measIdIdx]->measObjectId = 1;
+ measIdList->list.array[measIdIdx]->reportConfigId = 1;
+ }
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill s-measurement configuration
+ *
+ * @details
+ *
+ * Function : fillSMeasConfig
+ *
+ * Functionality: Fill s-measurement configuration
+ *
+ * @params[in] s-Measurement config
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillSMeasConfig(struct MeasConfigRrc__s_MeasureConfig *sMeasCfg)
+{
+ sMeasCfg->present = MeasConfigRrc__s_MeasureConfig_PR_ssb_RSRP;
+ sMeasCfg->choice.ssb_RSRP = 100; /* Value taken from reference PCAP log */
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill quantity config
+ *
+ * @details
+ *
+ * Function : fillQunatityConfig
+ *
+ * Functionality: Fill quantity config
+ *
+ * @params[in] Quantity Config
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillQuantityConfig(QuantityConfig_t *quantityCfg)
+{
+ uint8_t elementCnt = 0;
+ uint8_t quanCfgIdx = 0;
+ QuantityConfigNR_t *quantityCfgNr;
+
+ CU_ALLOC(quantityCfg->quantityConfigNR_List, sizeof(struct QuantityConfig__quantityConfigNR_List));
+ if(!quantityCfg->quantityConfigNR_List)
+ {
+ return RFAILED;
+ }
+
+ elementCnt = 1;
+ quantityCfg->quantityConfigNR_List->list.count = elementCnt;
+ quantityCfg->quantityConfigNR_List->list.size = elementCnt * sizeof(QuantityConfigNR_t *);
+
+ CU_ALLOC(quantityCfg->quantityConfigNR_List->list.array, quantityCfg->quantityConfigNR_List->list.size);
+ if(!quantityCfg->quantityConfigNR_List->list.array)
+ {
+ return RFAILED;
+ }
+
+ for(quanCfgIdx = 0; quanCfgIdx < quantityCfg->quantityConfigNR_List->list.count; quanCfgIdx++)
+ {
+ CU_ALLOC(quantityCfg->quantityConfigNR_List->list.array[quanCfgIdx], sizeof(QuantityConfigNR_t));
+ if(!quantityCfg->quantityConfigNR_List->list.array[quanCfgIdx])
+ {
+ return RFAILED;
+ }
+ }
+
+ quanCfgIdx = 0;
+ quantityCfgNr = quantityCfg->quantityConfigNR_List->list.array[quanCfgIdx];
+
+ /* Quantity Config of Reference signal */
+ CU_ALLOC(quantityCfgNr->quantityConfigCell.ssb_FilterConfig.filterCoefficientRSRP, sizeof(FilterCoefficient_t));
+ if(!quantityCfgNr->quantityConfigCell.ssb_FilterConfig.filterCoefficientRSRP)
+ {
+ return RFAILED;
+ }
+ *(quantityCfgNr->quantityConfigCell.ssb_FilterConfig.filterCoefficientRSRP) = FilterCoefficient_fc4;
+
+ CU_ALLOC(quantityCfgNr->quantityConfigCell.ssb_FilterConfig.filterCoefficientRSRQ, sizeof(FilterCoefficient_t));
+ if(!quantityCfgNr->quantityConfigCell.ssb_FilterConfig.filterCoefficientRSRQ)
+ {
+ return RFAILED;
+ }
+ *(quantityCfgNr->quantityConfigCell.ssb_FilterConfig.filterCoefficientRSRQ) = FilterCoefficient_fc4;
+
+ CU_ALLOC(quantityCfgNr->quantityConfigCell.ssb_FilterConfig.filterCoefficientRS_SINR, sizeof(FilterCoefficient_t));
+ if(!quantityCfgNr->quantityConfigCell.ssb_FilterConfig.filterCoefficientRS_SINR)
+ {
+ return RFAILED;
+ }
+ *(quantityCfgNr->quantityConfigCell.ssb_FilterConfig.filterCoefficientRS_SINR) = FilterCoefficient_fc4;
+
+ /* Quantity Config RS index */
+ CU_ALLOC(quantityCfgNr->quantityConfigRS_Index, sizeof(QuantityConfigRS_t));
+ if(!quantityCfgNr->quantityConfigRS_Index)
+ {
+ return RFAILED;
+ }
+
+ CU_ALLOC(quantityCfgNr->quantityConfigRS_Index->ssb_FilterConfig.filterCoefficientRSRP, sizeof(FilterCoefficient_t));
+ if(!quantityCfgNr->quantityConfigRS_Index->ssb_FilterConfig.filterCoefficientRSRP)
+ {
+ return RFAILED;
+ }
+ *(quantityCfgNr->quantityConfigRS_Index->ssb_FilterConfig.filterCoefficientRSRP) = FilterCoefficient_fc4;
+
+ CU_ALLOC(quantityCfgNr->quantityConfigRS_Index->ssb_FilterConfig.filterCoefficientRSRQ, sizeof(FilterCoefficient_t));
+ if(!quantityCfgNr->quantityConfigRS_Index->ssb_FilterConfig.filterCoefficientRSRQ)
+ {
+ return RFAILED;
+ }
+ *(quantityCfgNr->quantityConfigRS_Index->ssb_FilterConfig.filterCoefficientRSRQ) = FilterCoefficient_fc4;
+
+ CU_ALLOC(quantityCfgNr->quantityConfigRS_Index->ssb_FilterConfig.filterCoefficientRS_SINR, sizeof(FilterCoefficient_t));
+ if(!quantityCfgNr->quantityConfigRS_Index->ssb_FilterConfig.filterCoefficientRS_SINR)
+ {
+ return RFAILED;
+ }
+ *(quantityCfgNr->quantityConfigRS_Index->ssb_FilterConfig.filterCoefficientRS_SINR) = FilterCoefficient_fc4;
+
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill measurement configuration
+ *
+ * @details
+ *
+ * Function : fillMeasConfig
+ *
+ * Functionality: Fill measurement configuration
+ *
+ * @params[in] Measurement config
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillMeasConfig(MeasConfigRrc_t *measConfig)
+{
+ /* Measurement object to add/mod list */
+ CU_ALLOC(measConfig->measObjectToAddModList, sizeof(MeasObjectToAddModList_t));
+ if(!measConfig->measObjectToAddModList)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for measurement object list in fillMeasConfig");
+ return RFAILED;
+ }
+ if(fillMeasObjToAddModList(measConfig->measObjectToAddModList) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP: Failure in fillMeasObjToAddModList");
+ return RFAILED;
+ }
+
+ /* Report Config To add/mod list */
+ CU_ALLOC(measConfig->reportConfigToAddModList, sizeof(ReportConfigToAddModList_t));
+ if(!measConfig->reportConfigToAddModList)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for report config list in fillMeasConfig");
+ return RFAILED;
+ }
+ if(fillReportCfgToAddModList(measConfig->reportConfigToAddModList) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP: Failure in fillReportCfgToAddModList");
+ return RFAILED;
+ }
+
+ /* Measurement Id to add/mod list */
+ CU_ALLOC(measConfig->measIdToAddModList, sizeof(MeasIdToAddModList_t));
+ if(!measConfig->measIdToAddModList)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for measuerment id list in fillMeasConfig");
+ return RFAILED;
+ }
+ if(fillMeasIdToAddModList(measConfig->measIdToAddModList) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP: Failure in fillMeasIdToAddModList");
+ return RFAILED;
+ }
+
+ /* S-Measurement config */
+ CU_ALLOC(measConfig->s_MeasureConfig, sizeof(struct MeasConfigRrc__s_MeasureConfig));
+ if(!measConfig->s_MeasureConfig)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for s measuerment config in fillMeasConfig");
+ return RFAILED;
+ }
+ if(fillSMeasConfig(measConfig->s_MeasureConfig) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP: Failure in fillSMeasConfig");
+ return RFAILED;
+ }
+
+ /* Qunatity Config */
+ CU_ALLOC(measConfig->quantityConfig, sizeof(QuantityConfig_t));
+ if(!measConfig->quantityConfig)
+ {
+ DU_LOG("\nERROR --> F1AP: Memory allocation failed for quantity config in fillMeasConfig");
+ return RFAILED;
+ }
+ if(fillQuantityConfig(measConfig->quantityConfig) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP: Failure in fillQuantityConfig");
+ return RFAILED;
+ }
+
+return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill RRC reconfiguration non-critical extension IE
+ *
+ * @details
+ *
+ * Function : fillRrcReconfigNonCriticalExt
+ *
+ * Functionality: Fill RRC reconfiguration non-critical extension
+ *
+ * @params[in] RRC Reconfig Non-critical extension
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillRrcReconfigNonCriticalExt(CuUeCb *ueCb, RRCReconfiguration_v1530_IEs_t *rrcRecfg, bool updateAllRbCfg)
+{
+ 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;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill RRC reconfiguration structure
+ *
+ * @details
+ *
+ * Function : fillRrcReconfig
+ *
+ * Functionality: Fill RRC reconfiguration
+
+ *
+ * @params[in] UE Cb
+ * RRC reconfiguration structure
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillRrcReconfig(CuUeCb *ueCb, RRCReconfiguration_t *rrcReconfig, bool updateAllRbCfg)
+{
+ memset(rrcReconfig, 0, sizeof(RRCReconfiguration_t));
+
+ rrcReconfig->rrc_TransactionIdentifier = 1;
+ rrcReconfig->criticalExtensions.present = RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration;
+
+ CU_ALLOC(rrcReconfig->criticalExtensions.choice.rrcReconfiguration, sizeof(RRCReconfiguration_IEs_t));
+ if(!rrcReconfig->criticalExtensions.choice.rrcReconfiguration)
+ {
+ DU_LOG("\nERROR --> F1AP : Memormy allocation failed for RRC reconfiguration IE in fillRrcReconfig");
+ return RFAILED;
+ }
+
+ /* Radio Bearer Configuration */
+ CU_ALLOC(rrcReconfig->criticalExtensions.choice.rrcReconfiguration->radioBearerConfig, sizeof(RadioBearerConfig_t));
+ if(!rrcReconfig->criticalExtensions.choice.rrcReconfiguration->radioBearerConfig)
+ {
+ DU_LOG("\nERROR --> F1AP : Memormy allocation failed for radio bearer config in fillRrcReconfig");
+ return RFAILED;
+ }
+ if(fillRadioBearerConfig(ueCb, rrcReconfig->criticalExtensions.choice.rrcReconfiguration->radioBearerConfig, updateAllRbCfg) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : Failed to fill radio bearer config in fillRrcReconfig");
+ return RFAILED;
+ }
+
+ /* Measurement Configuration */
+ CU_ALLOC(rrcReconfig->criticalExtensions.choice.rrcReconfiguration->measConfig, sizeof(MeasConfigRrc_t));
+ if(!rrcReconfig->criticalExtensions.choice.rrcReconfiguration->measConfig)
+ {
+ DU_LOG("\nERROR --> F1AP : Memormy allocation failed for Measurement config IE in fillRrcReconfig");
+ return RFAILED;
+ }
+ if(fillMeasConfig(rrcReconfig->criticalExtensions.choice.rrcReconfiguration->measConfig) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : Failed to fill measurement config in fillRrcReconfig");
+ return RFAILED;
+ }
+
+ /* Non Critical extension */
+ CU_ALLOC(rrcReconfig->criticalExtensions.choice.rrcReconfiguration->nonCriticalExtension, sizeof(struct RRCReconfiguration_v1530_IEs));
+ if(!rrcReconfig->criticalExtensions.choice.rrcReconfiguration->nonCriticalExtension)
+ {
+ DU_LOG("\nERROR --> F1AP : Memormy allocation failed for non critical extension IE in fillRrcReconfig");
+ return RFAILED;
+ }
+ if(fillRrcReconfigNonCriticalExt(ueCb, rrcReconfig->criticalExtensions.choice.rrcReconfiguration->nonCriticalExtension, updateAllRbCfg) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : Failed to fill non critical extension in fillRrcReconfig");
+ return RFAILED;
+ }
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill RRC reconfiguration Octet string
+ *
+ * @details
+ *
+ * Function : fillRrcReconfigBuf
+ *
+ * Functionality: Fill RRC reconfiguration octet string
+
+ *
+ * @params[in] OCTET_STRING_t buffer
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillRrcReconfigBuf(CuUeCb *ueCb, OCTET_STRING_t *rrcReconfigBuf, bool updateAllRbCfg)
+{
+ uint8_t ret = RFAILED;
+ asn_enc_rval_t encRetVal;
+ RRCReconfiguration_t rrcRecfg, *rrcReconfig = NULLP;
+ rrcReconfig = &rrcRecfg;
+
+ while(true)
+ {
+ if(fillRrcReconfig(ueCb, rrcReconfig, updateAllRbCfg) != ROK)
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to fill RRC Reconfiguration in fillRrcReconfigBuf");
+ break;
+ }
+
+ /* Encode RRC Reconfiguration */
+ xer_fprint(stdout, &asn_DEF_RRCReconfiguration, rrcReconfig);
+ cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN);
+ encBufSize = 0;
+ encRetVal = aper_encode(&asn_DEF_RRCReconfiguration, 0, rrcReconfig, PrepFinalEncBuf, encBuf);
+
+ /* Encode results */
+ if(encRetVal.encoded == ENCODE_FAIL)
+ {
+ DU_LOG( "\nERROR --> F1AP : Could not encode RRC Reconfiguration (at %s)\n",\
+ encRetVal.failed_type ? encRetVal.failed_type->name : "unknown");
+ break;
+ }
+ else
+ {
+ DU_LOG("\nDEBUG --> F1AP : Created APER encoded buffer for RRC Reconfiguration\n");
+ for(int i=0; i< encBufSize; i++)
+ {
+ DU_LOG("%x",encBuf[i]);
+ }
+ }
+
+ rrcReconfigBuf->size = encBufSize;
+ CU_ALLOC(rrcReconfigBuf->buf, rrcReconfigBuf->size);
+ if(!rrcReconfigBuf->buf)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in fillRrcReconfigBuf");
+ break;
+ }
+ memcpy(rrcReconfigBuf->buf, encBuf, rrcReconfigBuf->size);
+ ret = ROK;
+ break;
+ }
+
+ freeRrcReconfig(rrcReconfig);
+ return ret;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill HO preparation information Octet string
+ *
+ * @details
+ *
+ * Function : fillHOPreparationInfoBuf
+ *
+ * Functionality: Fill HO preparation information Octet string
+
+ *
+ * @params[in] HandoverPreparationInformation_t buffer
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillHOPreparationInfoBuf(CuUeCb *ueCb, HandoverPreparationInformation_t *hoPrepInfoBuf)
+{
+ uint8_t ret = RFAILED;
+ asn_enc_rval_t encRetVal;
+ HandoverPreparationInformationRrc_t hoPrepInfo;
+ HandoverPreparationInformationRrc_IEs_t *hoPrepInfoIe;
+
+ while(true)
+ {
+
+ hoPrepInfo.criticalExtensions.present = HandoverPreparationInformationRrc__criticalExtensions_PR_c1;
+ CU_ALLOC(hoPrepInfo.criticalExtensions.choice.c1, sizeof(struct HandoverPreparationInformationRrc__criticalExtensions__c1));
+ if(!hoPrepInfo.criticalExtensions.choice.c1)
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to allocate memory for c1 in fillHOPreparationInfo");
+ break;
+ }
+ hoPrepInfo.criticalExtensions.choice.c1->present = \
+ HandoverPreparationInformationRrc__criticalExtensions__c1_PR_handoverPreparationInformation;
+
+ CU_ALLOC(hoPrepInfo.criticalExtensions.choice.c1->choice.handoverPreparationInformation , \
+ sizeof(HandoverPreparationInformationRrc_IEs_t));
+ if(!hoPrepInfo.criticalExtensions.choice.c1->choice.handoverPreparationInformation)
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to allocate memory for handover preparation information IE in fillHOPreparationInfo");
+ break;
+ }
+ hoPrepInfoIe = hoPrepInfo.criticalExtensions.choice.c1->choice.handoverPreparationInformation;
+
+ /* Fill UE Capability RAT container list */
+ ret = fillUeCapRatContList(&hoPrepInfoIe->ue_CapabilityRAT_List);
+ if(ret != ROK)
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to fill UE Capability RAT container list");
+ break;
+ }
+
+ /* Fill Source config */
+ hoPrepInfoIe->sourceConfig = NULLP;
+ CU_ALLOC(hoPrepInfoIe->sourceConfig, sizeof(AS_Config_t));
+ if(!hoPrepInfoIe->sourceConfig)
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to allocate memory for source config in fillHOPreparationInfo");
+ 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;
+ hoPrepInfoIe->nonCriticalExtension = NULLP;
+
+ /* encode UE Capability RAT Container List into duToCuRrcContainer */
+ xer_fprint(stdout, &asn_DEF_HandoverPreparationInformationRrc, &hoPrepInfo);
+ cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN);
+ encBufSize = 0;
+ encRetVal = aper_encode(&asn_DEF_HandoverPreparationInformationRrc, 0, \
+ &hoPrepInfo, PrepFinalEncBuf, encBuf);
+
+ /* Encode results */
+ if(encRetVal.encoded == ENCODE_FAIL)
+ {
+ DU_LOG( "\nERROR --> F1AP : Could not encode UE Capability RAT Container (at %s)\n",\
+ encRetVal.failed_type ? encRetVal.failed_type->name : "unknown");
+ break;
+ }
+ else
+ {
+ DU_LOG("\nDEBUG --> F1AP : Created APER encodedbuffer for UE Capability RAT Container\n");
+ for(int i=0; i< encBufSize; i++)
+ {
+ DU_LOG("%x",encBuf[i]);
+ }
+ }
+
+ hoPrepInfoBuf->size = encBufSize;
+ CU_ALLOC(hoPrepInfoBuf->buf, hoPrepInfoBuf->size);
+ if(!hoPrepInfoBuf->buf)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in fillUeCapabilityContainer");
+ break;
+ }
+ memcpy(hoPrepInfoBuf->buf, encBuf, hoPrepInfoBuf->size);
+ ret = ROK;
+ break;
+ }
+ freeHOPreparationInfo(&hoPrepInfo);
+ return ret;
+}
+
+/*******************************************************************
+ *
+ * @brief Fills CuToDuContainer
+ *
+ * @details
+ *
+ * Function : fillCuToDuContainer
+ *
+ * Functionality: Fills CuToDuContainer
+ *
+ * @params[in] pointer to CUtoDURRCInformation_t
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ ******************************************************************/
+
+uint8_t fillCuToDuContainer(CuUeCb *ueCb, CUtoDURRCInformation_t *rrcMsg)
+{
+ uint8_t elementCnt = 0;
+ uint8_t ret = ROK;
+ uint8_t idx;
+
+ /* UE Capabulity RAT Container List */
+ CU_ALLOC(rrcMsg->uE_CapabilityRAT_ContainerList, sizeof(UE_CapabilityRAT_ContainerList_t));
+ if(!rrcMsg->uE_CapabilityRAT_ContainerList)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation for UE capability RAT container list failed");
+ return RFAILED;
+ }
+ ret = fillUeCapRatContListBuf(rrcMsg->uE_CapabilityRAT_ContainerList);
+
+ CU_ALLOC(rrcMsg->measConfig, sizeof(MeasConfig_t));
+ if(!rrcMsg->measConfig)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation for measurement configuration failed");
+ return RFAILED;
+ }
+ ret = fillMeasTimingConfigBuf(rrcMsg->measConfig);
+
+ if(ueCb->state == UE_HANDOVER_IN_PROGRESS)
+ {
+ /* IE extensions */
+ CU_ALLOC(rrcMsg->iE_Extensions, sizeof(ProtocolExtensionContainer_4624P16_t));
+ if(rrcMsg->iE_Extensions)
+ {
+ elementCnt = 1;
+ rrcMsg->iE_Extensions->list.count = elementCnt;
+ rrcMsg->iE_Extensions->list.size = elementCnt * sizeof(CUtoDURRCInformation_ExtIEs_t *);
+
+ /* Initialize the CUtoDURRCInformation_ExtIEs */
+ CU_ALLOC(rrcMsg->iE_Extensions->list.array, rrcMsg->iE_Extensions->list.size);
+
+ if(rrcMsg->iE_Extensions->list.array == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation for CUtoDURRCInformation_ExtIEs failed");
+ ret = RFAILED;
+ }
+
+ for(idx=0; idx<elementCnt; idx++)
+ {
+ CU_ALLOC(rrcMsg->iE_Extensions->list.array[idx], sizeof(CUtoDURRCInformation_ExtIEs_t));
+ if(rrcMsg->iE_Extensions->list.array[idx] == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation for array elements failed");
+ ret = RFAILED;
+ }
+ }
+
+ idx = 0;
+#if 0
+ /* Cell Group Configuration */
+ rrcMsg->iE_Extensions->list.array[idx]->id = ProtocolIE_ID_id_CellGroupConfig;
+ rrcMsg->iE_Extensions->list.array[idx]->criticality = Criticality_ignore;
+ rrcMsg->iE_Extensions->list.array[idx]->extensionValue.present =\
+ CUtoDURRCInformation_ExtIEs__extensionValue_PR_CellGroupConfig;
+ ret = fillCellGrpCfg(ueCb, &rrcMsg->iE_Extensions->list.array[idx]->extensionValue.choice.CellGroupConfig, true);
+ idx++;
+#endif
+ /* Handover Preparation Information */
+ rrcMsg->iE_Extensions->list.array[idx]->id = ProtocolIE_ID_id_HandoverPreparationInformation;
+ rrcMsg->iE_Extensions->list.array[idx]->criticality = Criticality_ignore;
+ rrcMsg->iE_Extensions->list.array[idx]->extensionValue.present = \
+ CUtoDURRCInformation_ExtIEs__extensionValue_PR_HandoverPreparationInformation;
+ ret = fillHOPreparationInfoBuf(ueCb, &rrcMsg->iE_Extensions->list.array[idx]->extensionValue.choice.HandoverPreparationInformation);
+ }
+ }
+ 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_ms40;
+ 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
+ *
+ * @details
+ *
+ * Function : FreeCuToDuInfo
+ *
+ * Functionality: Free CuToDuContainer
+ *
+ * @params[in] pointer to CUtoDURRCInformation_t
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ ******************************************************************/
+
+void FreeCuToDuInfo(CUtoDURRCInformation_t *rrcMsg)
+{
+ uint8_t idx, idx2;
+
+ if(rrcMsg->uE_CapabilityRAT_ContainerList)
+ {
+ if(rrcMsg->uE_CapabilityRAT_ContainerList->buf)
+ CU_FREE(rrcMsg->uE_CapabilityRAT_ContainerList->buf, rrcMsg->uE_CapabilityRAT_ContainerList->size);
+ CU_FREE(rrcMsg->uE_CapabilityRAT_ContainerList, sizeof(UE_CapabilityRAT_ContainerList_t));
+ }
+ if(rrcMsg->iE_Extensions)
+ {
+ if(rrcMsg->iE_Extensions->list.array)
+ {
+ for(idx= 0; idx < rrcMsg->iE_Extensions->list.count; idx++)
+ {
+ if(rrcMsg->iE_Extensions->list.array[idx])
+ {
+ switch(rrcMsg->iE_Extensions->list.array[idx]->id)
+ {
+ case ProtocolIE_ID_id_CellGroupConfig:
+ if(rrcMsg->iE_Extensions->list.array[idx]->extensionValue.choice.CellGroupConfig.buf != NULLP)
+ {
+ CU_FREE(rrcMsg->iE_Extensions->list.array[idx]->extensionValue.choice.CellGroupConfig.buf,\
+ rrcMsg->iE_Extensions->list.array[idx]->extensionValue.choice.CellGroupConfig.size);
+
+ }
+ break;
+ default:
+ DU_LOG("\nERROR --> F1AP : Invalid Event type %ld at FreeCuToDuInfo()", \
+ rrcMsg->iE_Extensions->list.array[idx]->id);
+ break;
+ }
+ }
+ break;
+ }
+ for(idx2 = 0; idx2 < idx; idx2++)
+ {
+ CU_FREE(rrcMsg->iE_Extensions->list.array[idx2], sizeof(CUtoDURRCInformation_ExtIEs_t));
+ }
+ CU_FREE(rrcMsg->iE_Extensions->list.array, rrcMsg->iE_Extensions->list.size);
+
+ }
+
+ CU_FREE(rrcMsg->iE_Extensions, sizeof(ProtocolExtensionContainer_4624P16_t));
+ }
+}
+/*******************************************************************
+ *
+ * @brief Builds and sends the UE Setup Request
+ *
+ * @details
+ *
+ * Function : BuildAndSendUeContextSetupReq
+ *
+ * Functionality: Constructs the UE Setup Request and sends
+ * it to the CU through SCTP.
+ *
+ * @params[in]
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t BuildAndSendUeContextSetupReq(uint32_t duId, CuUeCb *ueCb)
+{
+ uint8_t Nrcgiret, SplCellListret, SrbSetupret;
+ uint8_t ret= RFAILED, ret1;
+ uint8_t elementCnt;
+ uint8_t idx, idx1, bufLen, duIdx;
+ uint32_t spCellId;
+ DuDb *targetDuDb = NULLP;
+ F1AP_PDU_t *f1apMsg = NULLP;
+ UEContextSetupRequest_t *ueSetReq = NULLP;
+ asn_enc_rval_t encRetVal; /* Encoder return value */
+ memset(&encRetVal, 0, sizeof(asn_enc_rval_t));
+
+ while(true)
+ {
+ DU_LOG("\nINFO --> F1AP : Building UE Context Setup Request\n");
+
+ CU_ALLOC(f1apMsg, sizeof(F1AP_PDU_t));
+ if(f1apMsg == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation for F1AP-PDU failed");
+ break;
+ }
+
+ f1apMsg->present = F1AP_PDU_PR_initiatingMessage;
+ CU_ALLOC(f1apMsg->choice.initiatingMessage, sizeof(InitiatingMessage_t));
+ if(f1apMsg->choice.initiatingMessage == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation for F1AP-PDU failed");
+ break;
+ }
+
+ f1apMsg->choice.initiatingMessage->procedureCode = ProcedureCode_id_UEContextSetup;
+ f1apMsg->choice.initiatingMessage->criticality = Criticality_reject;
+ f1apMsg->choice.initiatingMessage->value.present = InitiatingMessage__value_PR_UEContextSetupRequest;
+
+ ueSetReq = &f1apMsg->choice.initiatingMessage->value.choice.UEContextSetupRequest;
+
+ 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 *);
+
+ /* Initialize the UESetup members */
+ CU_ALLOC(ueSetReq->protocolIEs.list.array,ueSetReq->protocolIEs.list.size);
+
+ if(ueSetReq->protocolIEs.list.array == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation for UE Context SetupRequest failed");
+ break;
+ }
+
+ for(idx1=0; idx1<elementCnt; idx1++)
+ {
+ CU_ALLOC(ueSetReq->protocolIEs.list.array[idx1],sizeof(UEContextSetupRequestIEs_t));
+ if(ueSetReq->protocolIEs.list.array[idx1] == NULLP)
+ {
+ break;
+ }
+ }
+
+ idx = 0;
+
+ /*GNB CU UE F1AP ID*/
+ ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID;
+ ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_reject;
+ ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_GNB_CU_UE_F1AP_ID;
+ ueSetReq->protocolIEs.list.array[idx]->value.choice.GNB_CU_UE_F1AP_ID = ueCb->gnbCuUeF1apId;
+
+ if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
+ {
+ /*GNB DU UE F1AP ID*/
+ idx++;
+ ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID;
+ ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_ignore;
+ ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_GNB_DU_UE_F1AP_ID;
+ ueSetReq->protocolIEs.list.array[idx]->value.choice.GNB_DU_UE_F1AP_ID = ueCb->gnbDuUeF1apId;
+ }
+
+ /*Special Cell ID*/
+ idx++;
+ 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;
+ 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.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)
+ {
+ break;
+ }
+
+ /*Served Cell Index*/
+ idx++;
+ ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_ServCellIndex;
+ ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_reject;
+ ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_ServCellIndex;
+ ueSetReq->protocolIEs.list.array[idx]->value.choice.ServCellIndex = CELL_INDEX;
+
+ if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
+ {
+ /*CellULConfigured*/
+ idx++;
+ ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_SpCellULConfigured;
+ ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_ignore;
+ ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_CellULConfigured;
+ ueSetReq->protocolIEs.list.array[idx]->value.choice.CellULConfigured = CellULConfigured_none;
+ }
+
+ /*CUtoDURRCContainer*/
+ idx++;
+ ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_CUtoDURRCInformation;
+ ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_reject;
+ ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_CUtoDURRCInformation;
+ if(fillCuToDuContainer(ueCb, &ueSetReq->protocolIEs.list.array[idx]->value.choice.CUtoDURRCInformation))
+ {
+ break;
+ }
+
+ 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]->criticality = Criticality_ignore;
+ ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_SCell_ToBeSetup_List;
+ SplCellListret = BuildSplCellList(ueCb, &ueSetReq->protocolIEs.list.array[idx]->value.choice.SCell_ToBeSetup_List);
+ if(SplCellListret != ROK)
+ {
+ break;
+ }
+ }
+
+ /*SRBs To Be Setup List*/
+ idx++;
+ ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_SRBs_ToBeSetup_List;
+ ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_reject;
+ ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_SRBs_ToBeSetup_List;
+ SrbSetupret = BuildSRBSetup(ueCb, &ueSetReq->protocolIEs.list.array[idx]->value.choice.SRBs_ToBeSetup_List);
+ if(SrbSetupret != ROK)
+ {
+ break;
+ }
+
+ /*DRBs to Be Setup List*/
+ idx++;
+ 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(duId, ueCb, &ueSetReq->protocolIEs.list.array[idx]->value.choice.DRBs_ToBeSetup_List);
+ if(ret1 != ROK)
+ {
+ break;
+ }
+
+ if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
+ {
+ /* RRC delivery status request */
+ idx++;
+ ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_RRCDeliveryStatusRequest;
+ ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_ignore;
+ ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_RRCDeliveryStatusRequest;
+ ueSetReq->protocolIEs.list.array[idx]->value.choice.RRCDeliveryStatusRequest = RRCDeliveryStatusRequest_true;
+ }
+
+ /* GNB-DU UE Aggregate Maximum Bit Rate hardcoded as in reference logs */
+ idx++;
+ ueSetReq->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_GNB_DU_UE_AMBR_UL;
+ ueSetReq->protocolIEs.list.array[idx]->criticality = Criticality_ignore;
+ ueSetReq->protocolIEs.list.array[idx]->value.present = UEContextSetupRequestIEs__value_PR_BitRate;
+
+ char bitRateBuf[4]= {0x3B, 0x37, 0xF4, 0xCD};
+ bufLen = 4;
+ ueSetReq->protocolIEs.list.array[idx]->value.choice.BitRate.size = bufLen;
+ CU_ALLOC(ueSetReq->protocolIEs.list.array[idx]->value.choice.BitRate.buf,\
+ ueSetReq->protocolIEs.list.array[idx]->value.choice.BitRate.size);
+ if(!ueSetReq->protocolIEs.list.array[idx]->value.choice.BitRate.buf)
+ {
+ DU_LOG("\nERROR --> F1AP : Failed to allocate memory for Bit Rate in BuildAndSendUeContextSetupReq()");
+ break;
+ }
+ memset(ueSetReq->protocolIEs.list.array[idx]->value.choice.BitRate.buf, 0, bufLen);
+ memcpy(ueSetReq->protocolIEs.list.array[idx]->value.choice.BitRate.buf, bitRateBuf, bufLen);
+
+ xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg);
+
+ /* Encode the F1SetupRequest 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 UE Context Setup Request structure (at %s)\n",\
+ encRetVal.failed_type ? encRetVal.failed_type->name : "unknown");
+ break;
+ }
+ else
+ {
+ DU_LOG("\nDEBUG --> F1AP : Created APER encodedbuffer for UE Context Setup Request\n");
+ for(int i=0; i< encBufSize; i++)
+ {
+ DU_LOG("%x",encBuf[i]);
+ }
+ }
+
+ /* Sending msg */
+ if(SendF1APMsg(CU_APP_MEM_REG, CU_POOL, duId) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : Sending UE Context Setup Request Failed");
+ break;
+ }
+ ret = ROK;
+ break;
+ }
+ FreeUeContextSetupReq(f1apMsg);
+
+ return ret;
+}/* End of BuildAndSendUeContextSetupReq*/
+
+/**********************************************************************
+ * @brief Function to extractTeId received in UE context setup Response
+ *
+ * @details
+ *
+ * Function : extractTeId
+ *
+ * Functionality:
+ * - Function to extract TeId
+ *
+ * @params[in]
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ **********************************************************************/
+uint8_t extractTeId(DLUPTNLInformation_ToBeSetup_List_t *dlTnlInfo)
+{
+ uint8_t arrIdx = 0;
+ uint32_t teId = 0;
+ GTPTunnel_t *gtpDl = NULLP;
+
+ for(arrIdx =0; arrIdx < dlTnlInfo->list.count; arrIdx++)
+ {
+ if(dlTnlInfo->list.array[arrIdx]->dLUPTNLInformation.present == UPTransportLayerInformation_PR_gTPTunnel)
+ {
+ if(dlTnlInfo->list.array[arrIdx]->dLUPTNLInformation.choice.gTPTunnel != NULLP)
+ {
+ gtpDl = dlTnlInfo->list.array[arrIdx]->dLUPTNLInformation.choice.gTPTunnel;
+ if(gtpDl->gTP_TEID.size > 0)
+ {
+ teIdStringToInt(gtpDl->gTP_TEID.buf, &teId);
+ }
+ else
+ DU_LOG("\nERROR --> EGTP: No TeId received");
+ return(teId);
+ }
+ }
+ }
+ return teId;
+}
+
+/****************************************************************
+ * @brief Function to add Drb tunnels
+ *
+ * @details
+ *
+ * Function : addDrbTunnels
+ *
+ * Functionality:
+ * - Function to add Drb tunnels
+ *
+ * @params[in]
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t addDrbTunnels(uint32_t duId, uint8_t teId)
+{
+ uint8_t ret = ROK;
+ EgtpTnlEvt tnlEvt;
+
+ if(teId > MAX_TEID || teId < MIN_TEID)
+ {
+ DU_LOG("\nERROR --> EGTP : TEID(%x) OUT Of Range",teId);
+ }
+ memset(&tnlEvt, 0, sizeof(EgtpTnlEvt));
+ tnlEvt.action = EGTP_TNL_MGMT_ADD;
+ tnlEvt.lclTeid = teId;
+ tnlEvt.remTeid = teId;
+ ret = cuEgtpTnlMgmtReq(duId, tnlEvt);
+ if(ret != ROK)
+ {
+ DU_LOG("\nERROR --> EGTP : Tunnel management request failed for teId %x", teId);
+ }
+ return ROK;
+}
+
+/****************************************************************
+ * @brief Function to process Drb Setup List
+ *
+ * @details
+ *
+ * Function : procDrbSetupList
+ *
+ * Functionality:
+ * - Function to process DRB Setup List
+ *
+ * @params[in]
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t procDrbSetupList(uint32_t duId, CuUeCb *ueCb, DRBs_Setup_List_t *drbSetupList)
+{
+ uint8_t arrIdx = 0, drbIdx = 0;
+ uint32_t teId = 0;
+ DRBs_Setup_ItemIEs_t *drbItemIe = NULLP;
+
+ if(drbSetupList != NULLP)
+ {
+ for(arrIdx = 0; arrIdx < drbSetupList->list.count; arrIdx++)
+ {
+ drbItemIe = ((DRBs_Setup_ItemIEs_t *)drbSetupList->list.array[arrIdx]);
+ if(drbItemIe->value.present == DRBs_Setup_ItemIEs__value_PR_DRBs_Setup_Item)
+ {
+ /* extracting teId */
+ teId = extractTeId(&drbItemIe->value.choice.DRBs_Setup_Item.dLUPTNLInformation_ToBeSetup_List);
+ if(teId > 0)
+ {
+ 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;
+ }
+ }
+ }
+ return ROK;
+}
+
+/****************************************************************
+ * @brief Function to process Ue Context Setup Response
+ *
+ * @details
+ *
+ * Function : procUeContextSetupResponse
+ *
+ * Functionality:
+ * - Function to process Ue Context Setup Response
+ *
+ * @params[in]
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t procUeContextSetupResponse(uint32_t duId, F1AP_PDU_t *f1apMsg)
+{
+ 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;
+
+ for(idx=0; idx < ueCtxtSetupRsp->protocolIEs.list.count; idx++)
+ {
+ 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(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)
+ {
+ DU_LOG("\nERROR --> F1AP: Failed to extract Du to Cu RRC Information ");
+ return RFAILED;
+ }
+ break;
+ }
+ }
+ }
+
+ /* 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;
+}
+
+/****************************************************************
+ * @brief Function to process Ul Rrc Msg received from DU
+ *
+ * @details
+ *
+ * Function : procUlRrcMsg
+ *
+ * Functionality:
+ * - Function to process Ul Rrc Msg received from DU
+ *
+ * @params[in]
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+
+uint8_t procUlRrcMsg(uint32_t duId, F1AP_PDU_t *f1apMsg)
+{
+ 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;
+ SEARCH_DU_DB(duIdx, duId, duDb);
+ ulRrcMsg = &f1apMsg->choice.initiatingMessage->value.choice.ULRRCMessageTransfer;
+
+ for(idx=0; idx < ulRrcMsg->protocolIEs.list.count; idx++)
+ {
+ switch(ulRrcMsg->protocolIEs.list.array[idx]->id)
+ {
+ case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
+ {
+ cuUeF1apId = ulRrcMsg->protocolIEs.list.array[idx]->value.choice.GNB_CU_UE_F1AP_ID;
+ break;
+ }
+ case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
+ {
+ duUeF1apId = ulRrcMsg->protocolIEs.list.array[idx]->value.choice.GNB_DU_UE_F1AP_ID;
+ break;
+ }
+ case ProtocolIE_ID_id_SRBID:
+ srbId = ulRrcMsg->protocolIEs.list.array[idx]->value.choice.SRBID;
+ break;
+
+ case ProtocolIE_ID_id_RRCContainer:
+ {
+ rrcContLen = ulRrcMsg->protocolIEs.list.array[idx]->value.choice.RRCContainer.size;
+ CU_ALLOC(rrcContainer, rrcContLen);
+ if(!rrcContainer)
+ {
+ DU_LOG("\nERROR --> F1AP : Failed to allocated memory in procUlRrcMsg");
+ 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;
+ }
+
+ default:
+ DU_LOG("\nERROR --> F1AP : Invalid Event %ld", ulRrcMsg->protocolIEs.list.array[idx]->id);
+ break;
+ }
+ }
+
+ if(srbId == 1)
+ {
+ ueCb = &duDb->ueCb[duUeF1apId-1];
+ ueCb->f1apMsgDb.dlRrcMsgCount++;
+ rrcMsgType = setDlRRCMsgType(ueCb);
+ if(rrcMsgType == RRC_SETUP_COMPLETE)
+ {
+ DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for NAS Security Mode Command");
+ ret = BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType);
+ }
+ if(rrcMsgType == NAS_SECURITY_MODE_COMPLETE)
+ {
+ DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC Security Mode Command");
+ ret = BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType);
+ }
+ else if(rrcMsgType == RRC_SECURITY_MODE_COMPLETE)
+ {
+ DU_LOG("\nINFO --> F1AP: Sending DL RRC MSG for RRC Registration Accept");
+ BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType);
+ }
+ else if(rrcMsgType == REGISTRATION_COMPLETE)
+ {
+ 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;
+}
+
+/****************************************************************
+ * @brief Build And Send F1ResetAck
+ *
+ * @details
+ *
+ * Function : FreeF1ResetAck
+ *
+ * Functionality:
+ * - Build And Send F1ResetRSP
+ *
+ * @params[in]
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+void FreeF1ResetAck(F1AP_PDU_t *f1apMsg)
+{
+ uint8_t idx;
+ ResetAcknowledge_t *f1ResetAck;
+
+ if(f1apMsg)
+ {
+ if(f1apMsg->choice.successfulOutcome)
+ {
+ f1ResetAck= &f1apMsg->choice.successfulOutcome->value.choice.ResetAcknowledge;
+
+ if(f1ResetAck->protocolIEs.list.array)
+ {
+ for(idx=0; idx<f1ResetAck->protocolIEs.list.count ; idx++)
+ {
+ if(f1ResetAck->protocolIEs.list.array[idx])
+ {
+ CU_FREE(f1ResetAck->protocolIEs.list.array[idx], sizeof(ResetAcknowledgeIEs_t));
+ }
+ }
+ CU_FREE(f1ResetAck->protocolIEs.list.array, f1ResetAck->protocolIEs.list.size );
+ }
+ CU_FREE(f1apMsg->choice.successfulOutcome, sizeof(SuccessfulOutcome_t));
+ }
+ CU_FREE(f1apMsg, sizeof(F1AP_PDU_t));
+ }
+}
+
+/****************************************************************
+ * @brief Build And Send F1ResetAck
+ *
+ * @details
+ *
+ * Function : BuildAndSendF1ResetAck
+ *
+ * Functionality:
+ * - Build And Send F1ResetRSP
+ *
+ * @params[in]
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+
+uint8_t BuildAndSendF1ResetAck()
+{
+ uint8_t idx = 0;
+ uint8_t elementCnt = 0;
+ uint8_t ret = RFAILED;
+ F1AP_PDU_t *f1apMsg = NULL;
+ ResetAcknowledge_t *f1ResetAck = NULLP;
+ asn_enc_rval_t encRetVal;
+ DU_LOG("\nINFO --> F1AP : Building F1 Reset Acknowledgment \n");
+
+ do{
+ /* Allocate the memory for F1ResetRequest_t */
+ CU_ALLOC(f1apMsg, sizeof(F1AP_PDU_t));
+ if(f1apMsg == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation for F1AP-PDU failed");
+ break;
+ }
+
+ f1apMsg->present = F1AP_PDU_PR_successfulOutcome;
+
+ CU_ALLOC(f1apMsg->choice.successfulOutcome, sizeof(SuccessfulOutcome_t));