+ if(fillFeatureSets(ueNrCap.featureSets) != ROK)
+ {
+ DU_LOG("\nERROR --> fillDLFeatureSets() failed ");
+ ret = RFAILED;
+ break;
+ }
+
+ ueNrCap.featureSetCombinations = NULLP;
+ ueNrCap.lateNonCriticalExtension = NULLP;
+ ueNrCap.nonCriticalExtension = NULLP;
+
+ /* encode UE Capability RAT Container List into duToCuRrcContainer */
+ xer_fprint(stdout, &asn_DEF_UE_NR_Capability, &ueNrCap);
+ cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN);
+ encBufSize = 0;
+ encRetVal = uper_encode(&asn_DEF_UE_NR_Capability, 0, &ueNrCap, 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]);
+ }
+ }
+
+ ueCapRatContBuf->size = encBufSize;
+ CU_ALLOC(ueCapRatContBuf->buf, ueCapRatContBuf->size);
+ if(!ueCapRatContBuf->buf)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in fillUeCapabilityContainer");
+ break;
+ }
+ memcpy(ueCapRatContBuf->buf, encBuf, ueCapRatContBuf->size);
+ ret = ROK;
+ break;
+ }
+ freeUeCapRatCont(&ueNrCap);
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill UE Capability RAT container list
+ *
+ * @details
+ *
+ * Function : fillUeCapRatContList
+ *
+ * Functionality: Fill UE Capability RAT container list
+
+ *
+ * @params[in] UE capability RAT container list
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillUeCapRatContList(UE_CapabilityRAT_ContainerListRRC_t *ueCapablityList)
+{
+ uint8_t ret = RFAILED;
+ uint8_t idx, elementCnt;
+
+ while(true)
+ {
+ elementCnt = 1;
+ ueCapablityList->list.count = elementCnt;
+ ueCapablityList->list.size = elementCnt * sizeof(UE_CapabilityRAT_Container_t *);
+
+ CU_ALLOC(ueCapablityList->list.array, ueCapablityList->list.size);
+ if(!ueCapablityList->list.array)
+ {
+ DU_LOG("\nERROR --> Memory allocation failed in fillUeCapRatContList");
+ ret = RFAILED;
+ break;
+ }
+
+ for(idx=0; idx<elementCnt; idx++)
+ {
+ CU_ALLOC(ueCapablityList->list.array[idx], sizeof(UE_CapabilityRAT_Container_t));
+ if(ueCapablityList->list.array[idx] == NULLP)
+ {
+ DU_LOG("\nERROR --> Memory allocation failed in fillUeCapRatContList");
+ ret = RFAILED;
+ break;
+ }
+ }
+ idx = 0;
+ ueCapablityList->list.array[idx]->rat_Type = RAT_Type_nr;
+ if(fillUeCapRatCont(&ueCapablityList->list.array[idx]->ue_CapabilityRAT_Container) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : Failed to fill UE capability RAT Conatiner");
+ ret = RFAILED;
+ break;
+ }
+
+ ret = ROK;
+ break;
+ }
+ return ret;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill UE Capability RAT container list octet string
+ *
+ * @details
+ *
+ * Function : fillUeCapRatContListBuf
+ *
+ * Functionality: Fill UE Capability RAT container list octet string
+
+ *
+ * @params[in] UE capability RAT container list buffer
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillUeCapRatContListBuf(UE_CapabilityRAT_ContainerList_t *ueCapablityListBuf)
+{
+ uint8_t ret = RFAILED;
+ asn_enc_rval_t encRetVal;
+ UE_CapabilityRAT_ContainerListRRC_t ueCapablityList;
+
+ while(true)
+ {
+ ret = fillUeCapRatContList(&ueCapablityList);
+ if(ret != ROK)
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to fill UE Capability RAT container list");
+ break;
+ }
+
+ /* encode UE Capability RAT Container List into duToCuRrcContainer */
+ xer_fprint(stdout, &asn_DEF_UE_CapabilityRAT_ContainerListRRC, &ueCapablityList);
+ cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN);
+ encBufSize = 0;
+ encRetVal = uper_encode(&asn_DEF_UE_CapabilityRAT_ContainerListRRC, 0, \
+ &ueCapablityList, 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]);
+ }
+ }
+
+ ueCapablityListBuf->size = encBufSize;
+ CU_ALLOC(ueCapablityListBuf->buf, ueCapablityListBuf->size);
+ if(!ueCapablityListBuf->buf)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in fillUeCapabilityContainer");
+ break;
+ }
+ memcpy(ueCapablityListBuf->buf, encBuf, ueCapablityListBuf->size);
+ ret = ROK;
+ break;
+ }
+ freeUeCapRatContList(&ueCapablityList);
+ return ret;
+}
+
+/*******************************************************************
+ *
+ * @brief Free Measurement Timing Configuration
+ *
+ * @details
+ *
+ * Function : freeMeasuementTimingConfig
+ *
+ * Functionality: Free Measurement Timing Configuration
+ *
+ * @params[in] MeasurementTimingConfiguration_IEs_t measTimingCfg
+ * @return void
+ *
+ * ****************************************************************/
+void freeMeasuementTimingConfig(MeasurementTimingConfigurationRrc_t measTimingConfig)
+{
+ uint8_t measCfgIdx;
+ MeasurementTimingConfigurationRrc_IEs_t *measTimingCfg = NULLP;
+ MeasTiming_t *measTiming = NULLP;
+
+ if(measTimingConfig.criticalExtensions.choice.c1)
+ {
+ if(measTimingConfig.criticalExtensions.choice.c1->choice.measTimingConf)
+ {
+ measTimingCfg = measTimingConfig.criticalExtensions.choice.c1->choice.measTimingConf;
+ if(measTimingCfg->measTiming)
+ {
+ if(measTimingCfg->measTiming->list.array)
+ {
+ for(measCfgIdx = 0; measCfgIdx < measTimingCfg->measTiming->list.count; measCfgIdx++)
+ {
+ measTiming = measTimingCfg->measTiming->list.array[measCfgIdx];
+ CU_FREE(measTiming->frequencyAndTiming, sizeof(struct MeasTiming__frequencyAndTiming));
+ CU_FREE(measTimingCfg->measTiming->list.array[measCfgIdx], sizeof(MeasTiming_t));
+ }
+ CU_FREE(measTimingCfg->measTiming->list.array, measTimingCfg->measTiming->list.size);
+ }
+ CU_FREE(measTimingCfg->measTiming, sizeof(MeasTimingList_t));
+ }
+ CU_FREE(measTimingConfig.criticalExtensions.choice.c1->choice.measTimingConf, sizeof(struct MeasurementTimingConfigurationRrc_IEs));
+ }
+ CU_FREE(measTimingConfig.criticalExtensions.choice.c1, sizeof(struct MeasurementTimingConfigurationRrc__criticalExtensions__c1));
+ }
+}
+
+/*******************************************************************
+ *
+ * @brief Fill Measurement Timing Configuration
+ *
+ * @details
+ *
+ * Function : fillMeasTimingCfg
+ *
+ * Functionality: Fill Measurement Timing Configuration
+ *
+ * @params[in] MeasurementTimingConfiguration_IEs_t measTimingCfg
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillMeasTimingCfg(MeasurementTimingConfigurationRrc_IEs_t *measTimingCfg)
+{
+ uint8_t elementCnt = 0;
+ uint8_t measCfgIdx = 0;
+ MeasTiming_t *measTiming;
+ SSB_MTC_t *smtc;
+
+ CU_ALLOC(measTimingCfg->measTiming, sizeof(MeasTimingList_t));
+ if(!measTimingCfg->measTiming)
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to allocated memory for measTiming in fillMeasTimingCfg");
+ return RFAILED;
+ }
+
+ elementCnt = 1;
+ measTimingCfg->measTiming->list.count = elementCnt;
+ measTimingCfg->measTiming->list.size = measTimingCfg->measTiming->list.count * sizeof(MeasTiming_t *);
+ CU_ALLOC(measTimingCfg->measTiming->list.array, measTimingCfg->measTiming->list.size);
+ if(!measTimingCfg->measTiming->list.array)
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to allocated memory for measTiming array in fillMeasTimingCfg");
+ return RFAILED;
+ }
+
+ for(measCfgIdx = 0; measCfgIdx < measTimingCfg->measTiming->list.count; measCfgIdx++)
+ {
+ CU_ALLOC(measTimingCfg->measTiming->list.array[measCfgIdx], sizeof(MeasTiming_t));
+ if(!measTimingCfg->measTiming->list.array[measCfgIdx])
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to allocated memory for measTiming array element in fillMeasTimingCfg");
+ return RFAILED;
+ }
+ }
+
+ measCfgIdx = 0;
+ measTiming = measTimingCfg->measTiming->list.array[measCfgIdx];
+ CU_ALLOC(measTiming->frequencyAndTiming, sizeof(struct MeasTiming__frequencyAndTiming));
+ if(!measTiming->frequencyAndTiming)
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to allocated memory for frequency and timing IE in fillMeasTimingCfg");
+ return RFAILED;
+ }
+
+ measTiming->frequencyAndTiming->carrierFreq = 623800; /* This is a randomly chosen value since ARFCN configured in DU is 623400 */
+ measTiming->frequencyAndTiming->ssbSubcarrierSpacing = SubcarrierSpacing_kHz15;
+
+ smtc = &measTiming->frequencyAndTiming->ssb_MeasurementTimingConfiguration;
+ smtc->periodicityAndOffset.present = SSB_MTC__periodicityAndOffset_PR_sf20;
+ smtc->periodicityAndOffset.choice.sf20 = 0;
+ smtc->duration = SSB_MTC__duration_sf1;
+ return ROK;
+}
+
+/*******************************************************************
+ *
+ * @brief Fill Measurement Timing Configuration Octet string
+ *
+ * @details
+ *
+ * Function : fillMeasConfigBuf
+ *
+ * Functionality: Fill Measurement Timing Configuration Octet string
+
+ *
+ * @params[in] MeasConfig_t *measConfgBuf
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillMeasTimingConfigBuf(MeasConfig_t *measTimingConfigBuf)
+{
+ uint8_t ret = RFAILED;
+ asn_enc_rval_t encRetVal;
+ MeasurementTimingConfigurationRrc_t measTimingConfig;
+
+ while(true)
+ {
+ measTimingConfig.criticalExtensions.present = MeasurementTimingConfigurationRrc__criticalExtensions_PR_c1;
+ CU_ALLOC(measTimingConfig.criticalExtensions.choice.c1, sizeof(struct MeasurementTimingConfigurationRrc__criticalExtensions__c1));
+ if(!measTimingConfig.criticalExtensions.choice.c1)
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to allocated memory for measurement configuration extension");
+ return RFAILED;
+ }
+ measTimingConfig.criticalExtensions.choice.c1->present = MeasurementTimingConfigurationRrc__criticalExtensions__c1_PR_measTimingConf;
+
+ CU_ALLOC(measTimingConfig.criticalExtensions.choice.c1->choice.measTimingConf, sizeof(struct MeasurementTimingConfigurationRrc_IEs));
+ if(!measTimingConfig.criticalExtensions.choice.c1->choice.measTimingConf)
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to allocated memory for measurement timing configuration IE");
+ return RFAILED;
+ }
+
+ ret = fillMeasTimingCfg(measTimingConfig.criticalExtensions.choice.c1->choice.measTimingConf);
+ if(ret != ROK)
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to fill measurement timing configuration IE");
+ break;
+ }
+
+ /* Encode measurement timing configuration into octet string */
+ xer_fprint(stdout, &asn_DEF_MeasurementTimingConfigurationRrc, &measTimingConfig);
+ cmMemset((uint8_t *)encBuf, 0, ENC_BUF_MAX_LEN);
+ encBufSize = 0;
+ encRetVal = uper_encode(&asn_DEF_MeasurementTimingConfigurationRrc, 0, &measTimingConfig, PrepFinalEncBuf, encBuf);
+
+ /* Encode results */
+ if(encRetVal.encoded == ENCODE_FAIL)
+ {
+ DU_LOG( "\nERROR --> F1AP : Could not encode Measurement Timing Configuration (at %s)\n",\
+ encRetVal.failed_type ? encRetVal.failed_type->name : "unknown");
+ break;
+ }
+ else
+ {
+ DU_LOG("\nDEBUG --> F1AP : Created APER encodedbuffer for Measurement timing configuration\n");
+ for(int i=0; i< encBufSize; i++)
+ {
+ DU_LOG("%x",encBuf[i]);
+ }
+ }
+
+ measTimingConfigBuf->size = encBufSize;
+ CU_ALLOC(measTimingConfigBuf->buf, measTimingConfigBuf->size);
+ if(!measTimingConfigBuf->buf)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed fillMeasTimingConfigBuf");
+ break;
+ }
+ memcpy(measTimingConfigBuf->buf, encBuf, measTimingConfigBuf->size);
+ ret = ROK;
+ break;
+ }
+ freeMeasuementTimingConfig(measTimingConfig);
+ return ret;
+}
+
+/******************************************************************
+ *
+ * @brief Free RRC reconfiguration non-critical extension
+ *
+ * @details
+ *
+ * Function : freeRrcReconfigNonCriticalExt
+ *
+ * Functionality: Free RRC reconfiguration non-critical extension
+ *
+ * @params[in] RRC reconfiguration IE
+ * @return void
+ *
+ * ****************************************************************/
+void freeRrcReconfigNonCriticalExt(RRCReconfiguration_v1530_IEs_t *rrcRecfg)
+{
+ if(rrcRecfg->masterCellGroup)
+ {
+ CU_FREE(rrcRecfg->masterCellGroup, sizeof(OCTET_STRING_t));
+ }
+}
+
+/******************************************************************
+ *
+ * @brief Free measurement object addmod list
+ *
+ * @details
+ *
+ * Function : freeMeasObjToAddModList
+ *
+ * Functionality: Free measurement object add mod list
+ *
+ * @params[in] Measurement object add/mod list
+ * @return void
+ *
+ * ****************************************************************/
+void freeMeasObjToAddModList(MeasObjectToAddModList_t *measObjList)
+{
+ uint8_t objIdx;
+ MeasObjectNR_t *measObject;
+
+ if(measObjList->list.array)
+ {
+ for(objIdx = 0; objIdx < measObjList->list.size; objIdx++)
+ {
+ if(measObjList->list.array[objIdx])
+ {
+ if(measObjList->list.array[objIdx]->measObject.choice.measObjectNR)
+ {
+ measObject = measObjList->list.array[objIdx]->measObject.choice.measObjectNR;
+ CU_FREE(measObject->ssbFrequency, sizeof(ARFCN_ValueNR_t));
+ CU_FREE(measObject->ssbSubcarrierSpacing, sizeof(SubcarrierSpacing_t));
+ CU_FREE(measObject->smtc1 , sizeof(SSB_MTC_t));
+ if(measObject->absThreshSS_BlocksConsolidation)
+ {
+ CU_FREE(measObject->absThreshSS_BlocksConsolidation->thresholdRSRP, sizeof(RSRP_Range_t));
+ CU_FREE(measObject->absThreshSS_BlocksConsolidation->thresholdRSRQ, sizeof(RSRQ_Range_t));
+ CU_FREE(measObject->absThreshSS_BlocksConsolidation->thresholdSINR, sizeof(SINR_Range_t));
+ CU_FREE(measObject->absThreshSS_BlocksConsolidation, sizeof(ThresholdNR_t));
+ }
+ CU_FREE(measObject->nrofSS_BlocksToAverage, sizeof(long));
+ CU_FREE(measObject->offsetMO.rsrpOffsetSSB, sizeof(Q_OffsetRange_t));
+ CU_FREE(measObject->offsetMO.rsrqOffsetSSB, sizeof(Q_OffsetRange_t));
+ CU_FREE(measObject->offsetMO.sinrOffsetSSB, sizeof(Q_OffsetRange_t));
+ CU_FREE(measObjList->list.array[objIdx]->measObject.choice.measObjectNR, sizeof(MeasObjectNR_t));
+ }
+ CU_FREE(measObjList->list.array[objIdx], sizeof(MeasObjectToAddMod_t));
+ }
+ }
+ CU_FREE(measObjList->list.array, measObjList->list.size);
+ }
+}
+
+/******************************************************************
+ *
+ * @brief Free report config add mod list
+ *
+ * @details
+ *
+ * Function : freeReportCfgToAddModList
+ *
+ * Functionality: Free report config add mod list
+ *
+ * @params[in] Report config list
+ * @return void
+ *
+ * ****************************************************************/
+void freeReportCfgToAddModList(ReportConfigToAddModList_t *reportCfgList)
+{
+ uint8_t reportCfgIdx;
+ ReportConfigToAddMod_t *reportCfg;
+ ReportConfigNR_t *reportCfgNr;
+ EventTriggerConfig_t *eventTriggCfg;
+
+ if(reportCfgList->list.array)
+ {
+ for(reportCfgIdx=0; reportCfgIdx < reportCfgList->list.count; reportCfgIdx++)
+ {
+ if(reportCfgList->list.array[reportCfgIdx])
+ {
+ reportCfg = reportCfgList->list.array[reportCfgIdx];
+ if(reportCfg->reportConfig.choice.reportConfigNR)
+ {
+ reportCfgNr = reportCfg->reportConfig.choice.reportConfigNR;
+ if(reportCfgNr->reportType.choice.eventTriggered)
+ {
+ eventTriggCfg = reportCfgNr->reportType.choice.eventTriggered;
+ CU_FREE(eventTriggCfg->eventId.choice.eventA3, sizeof(struct EventTriggerConfig__eventId__eventA3));
+ CU_FREE(eventTriggCfg->reportQuantityRS_Indexes, sizeof(MeasReportQuantity_t));
+ CU_FREE(eventTriggCfg->maxNrofRS_IndexesToReport, sizeof(long));
+ CU_FREE(reportCfgNr->reportType.choice.eventTriggered, sizeof(EventTriggerConfig_t));
+ }
+ }
+ }
+ CU_FREE(reportCfgList->list.array[reportCfgIdx], sizeof(ReportConfigToAddMod_t));
+ }
+ CU_FREE(reportCfgList->list.array, reportCfgList->list.size);
+ }
+}
+
+/******************************************************************
+ *
+ * @brief Free measurement id to add mod list
+ *
+ * @details
+ *
+ * Function : freeMeasIdToAddModList
+ *
+ * Functionality: Free measurement id to add mod list
+ *
+ * @params[in] Measurement id to add mod list
+ * @return void
+ *
+ * ****************************************************************/
+void freeMeasIdToAddModList(MeasIdToAddModList_t *measIdList)
+{
+ uint8_t measIdIdx;
+ if(measIdList->list.array)
+ {
+ for(measIdIdx=0; measIdIdx < measIdList->list.count; measIdIdx++)
+ {
+ CU_FREE(measIdList->list.array[measIdIdx], sizeof(MeasIdToAddMod_t));
+ }
+ CU_FREE(measIdList->list.array, measIdList->list.size);
+ }
+}
+
+/*******************************************************************
+ *
+ * @brief Free quantity config
+ *
+ * @details
+ *
+ * Function : freeQunatityConfig
+ *
+ * Functionality: Free quantity config
+ *
+ * @params[in] Quantity Config
+ * @return void
+ *
+ * ****************************************************************/
+void freeQuantityConfig(QuantityConfig_t *quantityCfg)
+{
+ uint8_t quanCfgIdx;
+ QuantityConfigNR_t *quantityCfgNr;
+
+ if(quantityCfg->quantityConfigNR_List)
+ {
+ if(quantityCfg->quantityConfigNR_List->list.array)
+ {
+ for(quanCfgIdx = 0; quanCfgIdx < quantityCfg->quantityConfigNR_List->list.count; quanCfgIdx++)
+ {
+ if(quantityCfg->quantityConfigNR_List->list.array[quanCfgIdx])
+ {
+ quantityCfgNr = quantityCfg->quantityConfigNR_List->list.array[quanCfgIdx];
+ CU_FREE(quantityCfgNr->quantityConfigCell.ssb_FilterConfig.filterCoefficientRSRP, sizeof(FilterCoefficient_t));
+ CU_FREE(quantityCfgNr->quantityConfigCell.ssb_FilterConfig.filterCoefficientRSRQ, sizeof(FilterCoefficient_t));
+ CU_FREE(quantityCfgNr->quantityConfigCell.ssb_FilterConfig.filterCoefficientRS_SINR, sizeof(FilterCoefficient_t));
+ if(quantityCfgNr->quantityConfigRS_Index)
+ {
+ CU_FREE(quantityCfgNr->quantityConfigRS_Index->ssb_FilterConfig.filterCoefficientRSRP, sizeof(FilterCoefficient_t));
+ CU_FREE(quantityCfgNr->quantityConfigRS_Index->ssb_FilterConfig.filterCoefficientRSRQ, sizeof(FilterCoefficient_t));
+ CU_FREE(quantityCfgNr->quantityConfigRS_Index->ssb_FilterConfig.filterCoefficientRS_SINR, sizeof(FilterCoefficient_t));
+ CU_FREE(quantityCfgNr->quantityConfigRS_Index, sizeof(QuantityConfigRS_t));
+ }
+ CU_FREE(quantityCfg->quantityConfigNR_List->list.array[quanCfgIdx], sizeof(QuantityConfigNR_t));
+ }
+ }
+ CU_FREE(quantityCfg->quantityConfigNR_List->list.array, quantityCfg->quantityConfigNR_List->list.size);
+ }
+ CU_FREE(quantityCfg->quantityConfigNR_List, sizeof(struct QuantityConfig__quantityConfigNR_List));
+ }
+}
+
+/******************************************************************
+ *
+ * @brief Free measurement Config
+ *
+ * @details
+ *
+ * Function : freeMeasConfig
+ *
+ * Functionality: Free measurement config
+ *
+ * @params[in] Measurement config
+ * @return void
+ *
+ * ****************************************************************/
+void freeMeasConfig(MeasConfigRrc_t *measConfig)
+{
+ if(measConfig->measObjectToAddModList)
+ {
+ freeMeasObjToAddModList(measConfig->measObjectToAddModList);
+ CU_FREE(measConfig->measObjectToAddModList, sizeof(MeasObjectToAddModList_t));
+ }
+ if(measConfig->reportConfigToAddModList)
+ {
+ freeReportCfgToAddModList(measConfig->reportConfigToAddModList);
+ CU_FREE(measConfig->reportConfigToAddModList, sizeof(ReportConfigToAddModList_t));
+ }
+ if(measConfig->measIdToAddModList)
+ {
+ freeMeasIdToAddModList(measConfig->measIdToAddModList);
+ CU_FREE(measConfig->measIdToAddModList, sizeof(MeasIdToAddModList_t));
+ }
+ if(measConfig->s_MeasureConfig)
+ {
+ CU_FREE(measConfig->s_MeasureConfig, sizeof(struct MeasConfigRrc__s_MeasureConfig));
+ }
+ if(measConfig->quantityConfig)
+ {
+ freeQuantityConfig(measConfig->quantityConfig);
+ CU_FREE(measConfig->quantityConfig, sizeof(QuantityConfig_t));
+ }
+}
+/******************************************************************
+ *
+ * @brief Free DRB to AddMod List
+ *
+ * @details
+ *
+ * Function : freeDrbToAddModList
+ *
+ * Functionality: Free SRB to AddMod List
+ *
+ * @params[in] SBR to add/mod list
+ * @return void
+ *
+ * ****************************************************************/
+void freeDrbToAddModList(DRB_ToAddModList_t *drbToAddList)
+{
+ uint8_t drbIdx;
+ if(drbToAddList->list.array)
+ {
+ for(drbIdx = 0; drbIdx < drbToAddList->list.count; drbIdx++)
+ {
+ if(drbToAddList->list.array[drbIdx]->pdcp_Config)
+ {
+ if(drbToAddList->list.array[drbIdx]->pdcp_Config->drb)
+ {
+ CU_FREE(drbToAddList->list.array[drbIdx]->pdcp_Config->drb->discardTimer, sizeof(long));
+ CU_FREE(drbToAddList->list.array[drbIdx]->pdcp_Config->drb->pdcp_SN_SizeUL, sizeof(long));
+ CU_FREE(drbToAddList->list.array[drbIdx]->pdcp_Config->drb->pdcp_SN_SizeDL, sizeof(long));
+ CU_FREE(drbToAddList->list.array[drbIdx]->pdcp_Config->drb, sizeof(struct PDCP_Config__drb));
+ }
+ CU_FREE(drbToAddList->list.array[drbIdx]->pdcp_Config->t_Reordering, sizeof(long));
+ CU_FREE(drbToAddList->list.array[drbIdx]->pdcp_Config, sizeof(PDCP_Config_t));
+ }
+ CU_FREE(drbToAddList->list.array[drbIdx], sizeof(DRB_ToAddMod_t));
+ }
+ CU_FREE(drbToAddList->list.array, drbToAddList->list.size);
+ }
+}
+
+/******************************************************************
+ *
+ * @brief Free SRB to AddMod List
+ *
+ * @details
+ *
+ * Function : freeSrbToAddModList
+ *
+ * Functionality: Free SRB to AddMod List
+ *
+ * @params[in] SBR to add/mod list
+ * @return void
+ *
+ * ****************************************************************/
+void freeSrbToAddModList(SRB_ToAddModList_t *srbToAddList)
+{
+ uint8_t srbIdx;
+ if(srbToAddList->list.array)
+ {
+ for(srbIdx = 0; srbIdx < srbToAddList->list.count; srbIdx++)
+ {
+ CU_FREE(srbToAddList->list.array[srbIdx]->reestablishPDCP, sizeof(long));
+ if(srbToAddList->list.array[srbIdx]->pdcp_Config)
+ {
+ CU_FREE(srbToAddList->list.array[srbIdx]->pdcp_Config->t_Reordering, sizeof(long));
+ CU_FREE(srbToAddList->list.array[srbIdx]->pdcp_Config, sizeof(PDCP_Config_t));
+ }
+
+ CU_FREE(srbToAddList->list.array[srbIdx], sizeof(SRB_ToAddMod_t));
+ }
+ CU_FREE(srbToAddList->list.array, srbToAddList->list.size);
+ }
+}
+
+/******************************************************************
+ *
+ * @brief Free Radio Bearer Config
+ *
+ * @details
+ *
+ * Function : freeRadioBearerConfig
+ *
+ * Functionality: Free Radio Bearer config
+ *
+ * @params[in] Radio bearer config
+ * @return void
+ *
+ * ****************************************************************/
+void freeRadioBearerConfig(RadioBearerConfig_t *radioBearerConfig)
+{
+ if(radioBearerConfig->srb_ToAddModList)
+ {
+ freeSrbToAddModList(radioBearerConfig->srb_ToAddModList);
+ CU_FREE(radioBearerConfig->srb_ToAddModList, sizeof(SRB_ToAddModList_t));
+ }
+ if(radioBearerConfig->drb_ToAddModList)
+ {
+ freeDrbToAddModList(radioBearerConfig->drb_ToAddModList);
+ CU_FREE(radioBearerConfig->drb_ToAddModList, sizeof(DRB_ToAddModList_t));
+ }
+}
+
+/******************************************************************
+ *
+ * @brief Free reconfiguration message
+ *
+ * @details
+ *
+ * Function : freeRrcReconfig
+ *
+ * Functionality: Free reconfiguration message
+ *
+ * @params[in] RRC Reconfiguration message
+ * @return void
+ *
+ * ****************************************************************/
+void freeRrcReconfig(RRCReconfiguration_t *rrcReconfig)
+{
+ if(rrcReconfig->criticalExtensions.choice.rrcReconfiguration)
+ {
+ if(rrcReconfig->criticalExtensions.choice.rrcReconfiguration->radioBearerConfig)
+ {
+ freeRadioBearerConfig(rrcReconfig->criticalExtensions.choice.rrcReconfiguration->radioBearerConfig);
+ CU_FREE(rrcReconfig->criticalExtensions.choice.rrcReconfiguration->radioBearerConfig, sizeof(RadioBearerConfig_t));
+ }
+ if(rrcReconfig->criticalExtensions.choice.rrcReconfiguration->measConfig)
+ {
+ freeMeasConfig(rrcReconfig->criticalExtensions.choice.rrcReconfiguration->measConfig);
+ CU_FREE(rrcReconfig->criticalExtensions.choice.rrcReconfiguration->measConfig, sizeof(MeasConfigRrc_t));
+ }
+ if(rrcReconfig->criticalExtensions.choice.rrcReconfiguration->nonCriticalExtension)
+ {
+ freeRrcReconfigNonCriticalExt(rrcReconfig->criticalExtensions.choice.rrcReconfiguration->nonCriticalExtension);
+ CU_FREE(rrcReconfig->criticalExtensions.choice.rrcReconfiguration->nonCriticalExtension, sizeof(struct RRCReconfiguration_v1530_IEs));
+ }
+ CU_FREE(rrcReconfig->criticalExtensions.choice.rrcReconfiguration, sizeof(RRCReconfiguration_IEs_t));
+ }
+}
+
+/******************************************************************
+ *
+ * @brief Fill SRB To Add Mod list
+ *
+ * @details
+ *
+ * Function : fillSrbToAddModList
+ *
+ * Functionality: fill SRB to Add Mod list
+ *
+ * @params[in] UE control block
+ * SRB to Add/Mod list
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t fillSrbToAddModList(CuUeCb *ueCb, SRB_ToAddModList_t *srbToAddList, bool updateAllRbCfg)
+{
+ uint8_t srbIdx, srbDbIdx, elementCnt = 0;
+
+ if(updateAllRbCfg)
+ elementCnt = ueCb->numSrb;
+ else
+ {
+ for(srbDbIdx=0; srbDbIdx < ueCb->numSrb; srbDbIdx++)
+ {
+ if(ueCb->srbList[srbDbIdx].cfgSentToUe == false)
+ 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);
+ 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.rsrqOffsetSSB)
+ {
+ 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 = uper_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 = uper_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;
+
+ if((ueCb->state != UE_HANDOVER_IN_PROGRESS) || ((ueCb->state == UE_HANDOVER_IN_PROGRESS) && (ueCb->hoInfo.HOType == Inter_DU_HO)))
+ {
+ /* 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);
+ }
+
+#if 0
+
+ /* Commenting this because:
+ * CUToDURRCInformation->MeasConfig contains measurement gap configurations.
+ * Howeever measurement gap is not supported in our code. Measurement Gap will
+ * be required if we want to support inter-RAT handover or handover to
+ * neighbouring cells operating on a different frequency than serving cell.
+ *
+ * In case we plan to use this IE in future, following fixes are required:
+ * As of now, we are filling MeasurementTimingConfigurationRrc_t into rrcMsg->measConfig.
+ * This is incorrect. We must fill MeasConfigRrc_t in rrcMsg->measConfig.
+ * MeasurementTimingConfigurationRrc_t should be filled in
+ * rrcMsg->iE_Extensions->MeasurementTimingConfiguration, if required.
+ */
+
+ 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);
+#endif
+
+ 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_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
+ *
+ * @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;
+ uint32_t targetDuId;
+ 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;
+
+ /* Spec 38.473 Sec 9.2.2.1 : For handover case, this IE shall be considered as target cell. */
+ if(ueCb->state == UE_HANDOVER_IN_PROGRESS)
+ {
+ if(ueCb->hoInfo.HOType == Inter_DU_HO)
+ targetDuId = ueCb->hoInfo.tgtNodeId;
+ else
+ targetDuId = duId;
+
+ SEARCH_DU_DB(duIdx, targetDuId, targetDuDb);
+ /* Since we are supporting only one cell per DU, accessing 0th index to
+ * get target cell info */
+ spCellId = targetDuDb->cellCb[0].nrCellId;
+ }
+ else
+ spCellId = ueCb->cellCb->nrCellId;
+
+ Nrcgiret = BuildNrcgi(&ueSetReq->protocolIEs.list.array[idx]->value.choice.NRCGI, spCellId);
+ if(Nrcgiret != ROK)
+ {
+ 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, char *recvBuf, MsgLen recvBufLen)
+{
+ 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));
+
+ /* Check if UE is under Inter-CU handover */
+ if(duDb->tempUeCtxtInHo && (duDb->tempUeCtxtInHo->gnbCuUeF1apId == cuUeF1apId))
+ {
+ memcpy(ueCb, duDb->tempUeCtxtInHo, sizeof(CuUeCb));
+ ueCb->gnbDuUeF1apId = duUeF1apId;
+ CU_FREE(duDb->tempUeCtxtInHo, sizeof(CuUeCb));
+ }
+ else
+ {
+ /* In case of Inter DU Handover */
+ ueCb->cellCb = &duDb->cellCb[0];
+ ueCb->gnbDuUeF1apId = duUeF1apId;
+ ueCb->gnbCuUeF1apId = cuUeF1apId;
+ ueCb->state = UE_HANDOVER_IN_PROGRESS;
+ ueCb->hoInfo.HOType = Inter_DU_HO;
+ ueCb->hoInfo.tgtNodeId = duId;
+ }
+ (duDb->numUe)++;
+
+ ueCb->cellCb->ueCb[ueCb->cellCb->numUe] = ueCb;
+ 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(ueCb->state != UE_HANDOVER_IN_PROGRESS)
+ {
+ 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;
+ }
+ }
+ else
+ {
+ if(ueCb->hoInfo.HOType == Inter_DU_HO)
+ {
+ /* If the UE is in Inter-DU handover, UE context modification request is to be sent to
+ * source DU once UE context setup response is received from target DU */
+
+ DuDb *srcDuDb = NULLP;
+ CuUeCb *ueCbInSrcDu = NULLP;
+
+ /* Since Source DU Id and DU UE F1AP ID assigned to UE by source DU is not known here, we
+ * need to find Source DU and UE CB in source DU using CU UE F1AP ID */
+ for(duIdx=0; duIdx < cuCb.numDu; duIdx++)
+ {
+ /* 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.srcNodeId = 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 if(ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO)
+ {
+ BuildAndSendHOReqAck(ueCb, duToCuRrcContainer->buf, duToCuRrcContainer->size);
+ }
+ }
+
+ 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)
+ {
+ if(duDb->ueCb[duUeF1apId-1].hoInfo.HOType == Inter_DU_HO)
+ {
+ uint8_t ueIdx = 0;
+ uint8_t srcDuId = duDb->ueCb[duUeF1apId-1].hoInfo.srcNodeId;
+ DuDb *srcDuDb = NULLP;
+
+ /* Release UE context in source DU because the UE is now
+ * attached to target DU */
+ SEARCH_DU_DB(duIdx, srcDuId, srcDuDb);
+ for(ueIdx = 0; ueIdx < srcDuDb->numUe; ueIdx++)
+ {
+ 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;
+ }
+ }
+ }
+ else
+ {
+ BuildAndSendUeContextRelease(&duDb->ueCb[duUeF1apId-1]);
+ }
+
+ /* In target DU DB, mark UE as active and delete HO info */
+ duDb->ueCb[duUeF1apId-1].state = UE_ACTIVE;
+ memset(&duDb->ueCb[duUeF1apId-1].hoInfo, 0, sizeof(HandoverInfo));
+ return ret;
+ }
+ break;
+ }
+
+ 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 == 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);
+ }
+ else
+ {
+ /* In case rrcMsgType is RRC_SETUP_COMPLETE / NAS_AUTHENTICATION_RSP / NAS_SECURITY_MODE_COMPLETE / RRC_SECURITY_MODE_COMPLETE */
+ BuildAndSendDLRRCMessageTransfer(duId, ueCb, srbId, rrcMsgType);
+ }
+ }
+ 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));
+ if(f1apMsg->choice.successfulOutcome == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation for F1AP-PDU failed");
+ break;
+ }
+
+ f1apMsg->choice.successfulOutcome->procedureCode = ProcedureCode_id_Reset;
+ f1apMsg->choice.successfulOutcome->criticality = Criticality_reject;
+ f1apMsg->choice.successfulOutcome->value.present = SuccessfulOutcome__value_PR_ResetAcknowledge;
+ f1ResetAck = &f1apMsg->choice.successfulOutcome->value.choice.ResetAcknowledge;
+
+ elementCnt = 1;
+
+ f1ResetAck->protocolIEs.list.count = elementCnt;
+ f1ResetAck->protocolIEs.list.size = elementCnt*sizeof(ResetAcknowledgeIEs_t *);
+
+ CU_ALLOC(f1ResetAck->protocolIEs.list.array, f1ResetAck->protocolIEs.list.size );
+ if(f1ResetAck->protocolIEs.list.array == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation for F1ResetAckIEs failed");
+ break;
+ }
+
+ for(idx=0; idx<elementCnt; idx++)
+ {
+ CU_ALLOC(f1ResetAck->protocolIEs.list.array[idx], sizeof(ResetAcknowledgeIEs_t));
+ if(f1ResetAck->protocolIEs.list.array[idx] == NULLP)
+ {
+ break;
+ }
+ }
+ /*TransactionID*/
+ idx = 0;
+ f1ResetAck->protocolIEs.list.array[idx]->id = ProtocolIE_ID_id_TransactionID;
+ f1ResetAck->protocolIEs.list.array[idx]->criticality = Criticality_reject;
+ f1ResetAck->protocolIEs.list.array[idx]->value.present = ResetAcknowledgeIEs__value_PR_TransactionID;
+ f1ResetAck->protocolIEs.list.array[idx]->value.choice.TransactionID = TRANS_ID;
+
+ xer_fprint(stdout, &asn_DEF_F1AP_PDU, f1apMsg);
+
+ /* Encode the F1SetupRequest type as UPER */
+ memset(encBuf, 0, ENC_BUF_MAX_LEN);
+ encBufSize = 0;
+ encRetVal = aper_encode(&asn_DEF_F1AP_PDU, 0, f1apMsg, PrepFinalEncBuf, encBuf);
+
+ /* Check encode results */
+ if(encRetVal.encoded == ENCODE_FAIL)
+ {
+ DU_LOG("\nERROR --> F1AP : Could not encode F1ResetAck structure (at %s)\n",\
+ encRetVal.failed_type ? encRetVal.failed_type->name : "unknown");
+ break;
+ }
+ else
+ {
+ DU_LOG("\nDEBUG --> F1AP : Created APER encodedbuffer for F1ResetAck \n");
+ for(int i=0; i< encBufSize; i++)
+ {
+ DU_LOG("%x",encBuf[i]);
+ }
+ }
+
+ /* Sending msg */
+ /* TODO : Hardcoding DU ID to 1 for messages other than F1 Setup Response. This will be made generic in future gerrit */
+ if(SendF1APMsg(CU_APP_MEM_REG, CU_POOL, DU_ID) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : Sending F1 Reset Response failed");
+ break;
+ }
+
+ ret = ROK;
+ break;
+ }while(true);
+
+ FreeF1ResetAck(f1apMsg);
+ return ret;
+}
+
+void FreeUlTnlInfoforDrb2(ULUPTNLInformation_ToBeSetup_List_t *ulInfo)
+{
+ uint8_t arrIdx =0;
+
+ if(ulInfo->list.array)
+ {
+ for(arrIdx=0; arrIdx<ulInfo->list.count ; arrIdx++)
+ {
+ if(ulInfo->list.array[arrIdx])
+ {
+ if(ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel )
+ {
+ if(ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->transportLayerAddress.buf)
+ {
+ if(ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf)
+ {
+ CU_FREE(ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
+ gTP_TEID.buf,ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.\
+ gTPTunnel->gTP_TEID.size);
+ }
+ CU_FREE(ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
+ transportLayerAddress.buf,ulInfo->list.array[arrIdx]->\
+ uLUPTNLInformation.choice.gTPTunnel->transportLayerAddress.size);
+ }
+ CU_FREE(ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel,\
+ sizeof(GTPTunnel_t));
+ }
+ CU_FREE(ulInfo->list.array[arrIdx],sizeof(ULUPTNLInformation_ToBeSetup_Item_t));
+ }
+ }
+ CU_FREE(ulInfo->list.array,ulInfo->list.size);
+ }
+}
+
+/*******************************************************************
+*
+* @brief Deletes the EGTP tunnel
+*
+* @details
+*
+* Function : deleteEgtpTunnel
+*
+* Functionality: Deletes the EGTP tunnel
+*
+* @params[in] uint8_t *buf
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+uint8_t deleteEgtpTunnel(uint32_t duId, uint8_t *buf)
+{
+ uint32_t teId = 0;
+ EgtpTnlEvt tnlEvt;
+
+ teIdStringToInt(buf, &teId);
+ if(teId > MAX_TEID || teId < MIN_TEID)
+ {
+ DU_LOG("\nERROR --> EGTP : TEID(%d) OUT Of Range", teId);
+ return RFAILED;
+ }
+ memset(&tnlEvt, 0, sizeof(EgtpTnlEvt));
+ tnlEvt.action = EGTP_TNL_MGMT_DEL;
+ tnlEvt.lclTeid = teId;
+ tnlEvt.remTeid = teId;
+ if((cuEgtpTnlMgmtReq(duId, tnlEvt)) != ROK)
+ {
+ DU_LOG("\nERROR --> EGTP : Failed to delete tunnel Id %d", teId);
+ }
+ return ROK;
+}
+
+/*******************************************************************
+*
+* @brief Builds the Uplink Tunnel Info
+*
+* @details
+*
+* Function : BuildUlTnlInfoforSetupMod
+*
+* Functionality: Constructs the UL TnlInfo For DRB list
+*
+* @params[in] ULUPTNLInformation_ToBeSetup_List_t *ulInfo
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+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;
+
+ ulCnt = 1;
+ ulInfo->list.count = ulCnt;
+ ulInfo->list.size = ulCnt * sizeof(ULUPTNLInformation_ToBeSetup_Item_t *);
+ CU_ALLOC(ulInfo->list.array,ulInfo->list.size);
+ if(ulInfo->list.array == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in BuildUlTnlInfoforSetupMod");
+ return RFAILED;
+ }
+ for(arrIdx=0; arrIdx<ulCnt; arrIdx++)
+ {
+ CU_ALLOC(ulInfo->list.array[arrIdx],sizeof(ULUPTNLInformation_ToBeSetup_Item_t));
+ if(ulInfo->list.array[arrIdx] == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in BuildUlTnlInfoforSetupMod");
+ return RFAILED;
+ }
+ }
+
+ arrIdx = 0;
+ ulInfo->list.array[arrIdx]->uLUPTNLInformation.present = \
+ UPTransportLayerInformation_PR_gTPTunnel;
+
+ /*GTP TUNNEL*/
+ CU_ALLOC(ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel,\
+ sizeof(GTPTunnel_t));
+ if(ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in BuildUlTnlInfoforSetupMod");
+ return RFAILED;
+ }
+ ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
+ transportLayerAddress.size = 4*sizeof(uint8_t);
+ CU_ALLOC(ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
+ transportLayerAddress.buf,ulInfo->list.array[arrIdx]->\
+ uLUPTNLInformation.choice.gTPTunnel->transportLayerAddress.size);
+ if(ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
+ transportLayerAddress.buf == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in BuildUlTnlInfoforSetupMod");
+ return RFAILED;
+ }
+
+ ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
+ transportLayerAddress.buf[0] = 192;
+ ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
+ transportLayerAddress.buf[1] = 168;
+ ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
+ transportLayerAddress.buf[2] = 130;
+ ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
+ transportLayerAddress.buf[3] = 82;
+ ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
+ transportLayerAddress.bits_unused = 0;
+
+ ulTnlInfo->address[0] = ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->transportLayerAddress.buf[0];
+ ulTnlInfo->address[1] = ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->transportLayerAddress.buf[1];
+ ulTnlInfo->address[2] = ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->transportLayerAddress.buf[2];
+ ulTnlInfo->address[3] = ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->transportLayerAddress.buf[3];
+
+ /*GTP TEID*/
+ ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.size\
+ = 4 * sizeof(uint8_t);
+ CU_ALLOC(ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
+ gTP_TEID.buf,ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.\
+ gTPTunnel->gTP_TEID.size);
+ if(ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf\
+ == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in BuildUlTnlInfoforSetupMod");
+ return RFAILED;
+ }
+ ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
+ gTP_TEID.buf[0] = 0;
+ ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
+ gTP_TEID.buf[1] = 0;
+ ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
+ gTP_TEID.buf[2] = 0;
+ if(actionType == ProtocolIE_ID_id_DRBs_ToBeModified_Item)
+ {
+ /*TODO: DRB context to be stored in CU STUB so that tunnel Id can be easily
+ * fetched based on the Drb Id */
+
+ /*For For UE Id=1, DRB=2 is modified. For UE Id = 2, DRB=5 is modified and so on.*/
+ ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[3]=\
+ (MAX_NUM_DRB_ADDED_PER_UE *(ueId - 1)) + drbId;
+ }
+ else
+ {
+ ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->\
+ gTP_TEID.buf[3] = cuCb.cuCfgParams.egtpParams.currTunnelId++;
+ }
+
+ ulTnlInfo->teId[0] = ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[0];
+ ulTnlInfo->teId[1] = ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[1];
+ ulTnlInfo->teId[2] = ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[2];
+ ulTnlInfo->teId[3] = ulInfo->list.array[arrIdx]->uLUPTNLInformation.choice.gTPTunnel->gTP_TEID.buf[3];
+ return ROK;
+}/*End of BuildULTnlInfo*/
+
+/*******************************************************************
+*
+* @brief freeing the DRB item
+*
+* @details
+*
+* Function : FreeDrbItem
+*
+* Functionality: freeing the DRB item
+*
+* @params[in] DRBs_ToBeSetupMod_Item_t *drbItem
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+
+void FreeDrbItem(DRBs_ToBeSetupMod_Item_t *drbItem)
+{
+ uint8_t arrIdx =0;
+ SNSSAI_t *snssai =NULLP;
+ Flows_Mapped_To_DRB_List_t *flowMap = NULLP;
+
+ drbItem->qoSInformation.present = QoSInformation_PR_choice_extension;
+ switch(drbItem->qoSInformation.present)
+ {
+ case QoSInformation_PR_NOTHING:
+ break;
+ case QoSInformation_PR_eUTRANQoS:
+ {
+ if(drbItem->qoSInformation.choice.eUTRANQoS)
+ {
+ CU_FREE(drbItem->qoSInformation.choice.eUTRANQoS, sizeof(EUTRANQoS_t));
+ }
+ break;
+ }
+ case QoSInformation_PR_choice_extension:
+ {
+ if(drbItem->qoSInformation.choice.choice_extension)
+ {
+ FreeQOSInfo(&drbItem->qoSInformation.choice.choice_extension->value.choice.DRB_Information.dRB_QoS);
+
+ snssai = &drbItem->qoSInformation.choice.choice_extension->value.choice.DRB_Information.sNSSAI;
+ if(snssai->sST.buf)
+ {
+ CU_FREE(snssai->sST.buf,snssai->sST.size);
+ }
+ if(snssai->sD)
+ {
+ if(snssai->sD->buf)
+ {
+ CU_FREE(snssai->sD->buf,snssai->sD->size);
+ }
+ CU_FREE(snssai->sD,sizeof(OCTET_STRING_t));
+ }
+
+ flowMap = &drbItem->qoSInformation.choice.choice_extension->value.choice.DRB_Information.flows_Mapped_To_DRB_List;
+ if(flowMap->list.array)
+ {
+ for(arrIdx=0; arrIdx<flowMap->list.count; arrIdx++)
+ {
+ if(flowMap->list.array[arrIdx] )
+ {
+ FreeQOSInfo(&flowMap->list.array[arrIdx]->qoSFlowLevelQoSParameters);
+ CU_FREE(flowMap->list.array[arrIdx],sizeof(Flows_Mapped_To_DRB_Item_t));
+ }
+ }
+ CU_FREE(flowMap->list.array,flowMap->list.size);
+ }
+
+ CU_FREE(drbItem->qoSInformation.choice.choice_extension,sizeof(QoSInformation_ExtIEs_t));
+ }
+ break;
+ }
+
+ }
+ FreeUlTnlInfoforDrb2(&drbItem->uLUPTNLInformation_ToBeSetup_List);
+ if(drbItem->uLConfiguration)
+ {
+ CU_FREE(drbItem->uLConfiguration,sizeof(ULConfiguration_t));
+ }
+}
+
+/*******************************************************************
+*
+* @brief filling the DRB setup Mod item
+*
+* @details
+*
+* Function : FillDrbItemToSetupMod
+*
+* Functionality: filling the DRB setup Mod item
+*
+*
+* @params[in] DRBs_ToBeSetupMod_Item_t *drbItem
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+
+uint8_t FillDrbItemToSetupMod(uint32_t duId, CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeSetupMod_Item_t *drbItem)
+{
+ uint8_t ret = ROK;
+
+ /*Drb Id */
+ drbItem->dRBID = arrIdx + DRB_ID_TO_ADD_MOD;
+ ueCb->drbList[ueCb->numDrb].drbId = drbItem->dRBID;
+
+ /*qoSInformation*/
+ drbItem->qoSInformation.present = QoSInformation_PR_choice_extension;
+
+ switch(drbItem->qoSInformation.present)
+ {
+ case QoSInformation_PR_NOTHING:
+ {
+ break;
+ }
+ case QoSInformation_PR_eUTRANQoS:
+ {
+
+ CU_ALLOC(drbItem->qoSInformation.choice.eUTRANQoS, sizeof(EUTRANQoS_t));
+ if(drbItem->qoSInformation.choice.eUTRANQoS)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in FillDrbItemToSetupMod");
+ return RFAILED;
+ }
+ drbItem->qoSInformation.choice.eUTRANQoS->qCI = QCI;
+ drbItem->qoSInformation.choice.eUTRANQoS->allocationAndRetentionPriority.priorityLevel =
+ PriorityLevel_no_priority;
+
+ drbItem->qoSInformation.choice.eUTRANQoS->allocationAndRetentionPriority.pre_emptionCapability =
+ Pre_emptionCapability_may_trigger_pre_emption;
+
+ drbItem->qoSInformation.choice.eUTRANQoS->allocationAndRetentionPriority.pre_emptionVulnerability =
+ Pre_emptionVulnerability_pre_emptable;
+
+ break;
+ }
+ case QoSInformation_PR_choice_extension:
+ {
+ CU_ALLOC(drbItem->qoSInformation.choice.choice_extension,sizeof(QoSInformation_ExtIEs_t));
+ if(drbItem->qoSInformation.choice.choice_extension == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in FillDrbItemToSetupMod");
+ return RFAILED;
+ }
+
+ drbItem->qoSInformation.choice.choice_extension->id = ProtocolIE_ID_id_DRB_Information;
+ drbItem->qoSInformation.choice.choice_extension->criticality = Criticality_ignore;
+ drbItem->qoSInformation.choice.choice_extension->value.present = QoSInformation_ExtIEs__value_PR_DRB_Information;
+ ret = BuildQOSInfo(&ueCb->drbList[ueCb->numDrb].qos, &drbItem->qoSInformation.choice.choice_extension->value.choice.DRB_Information.dRB_QoS,\
+ ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item, PDU_SESSION_ID_2, FALSE);
+ if(ret != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildQOSInfo failed");
+ return RFAILED;
+ }
+
+ /*SNSSAI*/
+ ret = BuildSNSSAI(&ueCb->drbList[ueCb->numDrb], &drbItem->qoSInformation.choice.\
+ choice_extension->value.choice.DRB_Information.sNSSAI, cuCb.snssaiList[1], FALSE);
+ if(ret != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildSNSSAI failed");
+ return RFAILED;
+ }
+
+ /*Flows mapped to DRB List*/
+ ret = BuildFlowsMap(&ueCb->drbList[ueCb->numDrb], &drbItem->qoSInformation.choice.\
+ choice_extension->value.choice.DRB_Information.flows_Mapped_To_DRB_List,\
+ ProtocolIE_ID_id_DRBs_ToBeSetupMod_Item, FALSE);
+ if(ret != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildFlowsMap failed");
+ return RFAILED;
+ }
+ }
+ }
+
+ /*ULUPTNLInformation To Be Setup List*/
+ 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)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildUlTnlInfoforSetupMod failed");
+ return RFAILED;
+ }
+
+ /*RLCMode*/
+ drbItem->rLCMode = RLCMode_rlc_um_bidirectional;
+ ueCb->drbList[ueCb->numDrb].rlcMode = drbItem->rLCMode;
+
+ ueCb->numDrb++;
+ return ROK;
+}
+
+/*******************************************************************
+*
+* @brief Builds the DRB to be Setup Mod ItemIes
+*
+* @details
+*
+* Function : FillDrbItemList
+*
+* Functionality: Constructs the DRB to be Setup Mod Item Ies
+*
+* @params[in] struct DRBs_ToBeSetupMod_ItemIEs *drbItemIe
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+
+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(duId, ueCb, arrIdx, (&(drbItemIe->value.choice.DRBs_ToBeSetupMod_Item))) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : FillDrbItemToSetupMod failed");
+ return RFAILED;
+ }
+ return ROK;
+}
+/*******************************************************************
+*
+* @brief free the DRB to be Setup Mod list
+*
+* @details
+*
+* Function : FreeDrbToBeSetupModList
+*
+* Functionality: free the DRB to be Setup Mod list
+*
+* @params[in] DRBs_ToBeSetupMod_List_t *drbSet
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+void FreeDrbToBeSetupModList(DRBs_ToBeSetupMod_List_t *drbSet)
+{
+ uint8_t arrIdx =0;
+ struct DRBs_ToBeSetupMod_ItemIEs *drbItemIe;
+
+ if(drbSet->list.array)
+ {
+ for(arrIdx=0; arrIdx<drbSet->list.count ; arrIdx++)
+ {
+ if(drbSet->list.array[arrIdx] != NULLP)
+ {
+ if(arrIdx == 0)
+ {
+ drbItemIe = (DRBs_ToBeSetupMod_ItemIEs_t *)drbSet->list.array[arrIdx];
+ FreeDrbItem(&(drbItemIe->value.choice.DRBs_ToBeSetupMod_Item));
+ }
+ CU_FREE(drbSet->list.array[arrIdx], sizeof(DRBs_ToBeSetupMod_ItemIEs_t));
+ }
+ }
+ CU_FREE(drbSet->list.array, drbSet->list.size);
+ }
+
+}
+
+/*******************************************************************
+*
+* @brief Builds the DRB to be Setup Mod list
+*
+* @details
+*
+* Function : BuildDrbToBeSetupList
+*
+* Functionality: Constructs the DRB to be Setup Mod list
+*
+* @params[in] DRBs_ToBeSetupMod_List_t *drbSet
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+
+uint8_t BuildDrbToBeSetupList(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeSetupMod_List_t *drbSet)
+{
+ uint8_t ret = ROK;
+ uint8_t arrIdx =0;
+ uint8_t drbCnt =0;
+
+ drbCnt = MAX_DRB_SET_UE_CONTEXT_MOD_REQ;
+ drbSet->list.count = drbCnt;
+ drbSet->list.size = drbCnt * sizeof(DRBs_ToBeSetupMod_ItemIEs_t *);
+ CU_ALLOC(drbSet->list.array, drbSet->list.size);
+ if(drbSet->list.array == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in BuildDrbToBeSetupList");
+ return RFAILED;
+ }
+
+ for(arrIdx=0; arrIdx<drbCnt; arrIdx++)
+ {
+ CU_ALLOC(drbSet->list.array[arrIdx], sizeof(DRBs_ToBeSetupMod_ItemIEs_t));
+ if(drbSet->list.array[arrIdx] == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in BuildDrbToBeSetupList for array idx [%d]", arrIdx);
+ return RFAILED;
+ }
+
+ ret = FillDrbItemList(duId, ueCb, arrIdx, (DRBs_ToBeSetupMod_ItemIEs_t *)drbSet->list.array[arrIdx]);
+ if(ret != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : FillDrbItemList failed");
+ }
+ }
+
+ return ret;
+}
+
+/*******************************************************************
+*
+* @brief Filling the DRB to be modified item
+*
+* @details
+*
+* Function : FillDrbToBeModItem
+*
+* Functionality: filling the DRB to be modified item
+*
+* @params[in] DRBs_ToBeModified_Item_t *drbItem
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+
+uint8_t FillDrbToBeModItem(uint32_t duId, CuUeCb *ueCb, uint8_t arrIdx, DRBs_ToBeModified_Item_t *drbItem)
+{
+ uint8_t ret = ROK;
+ uint drbIdx=0;
+ DrbInfo *drbToBeMod;
+
+ /*Drb Id */
+ drbItem->dRBID = DRB2 + arrIdx;
+
+ /* Search for DRB ID in CU databse */
+ for(drbIdx = 0; drbIdx < ueCb->numDrb; drbIdx++)
+ {
+ if(ueCb->drbList[drbIdx].drbId == drbItem->dRBID)
+ {
+ drbToBeMod = &ueCb->drbList[drbIdx];
+ break;
+ }
+ }
+
+ /*qoSInformation*/
+ drbItem->qoSInformation = NULLP;
+ CU_ALLOC(drbItem->qoSInformation, sizeof(QoSInformation_t));
+ if(drbItem->qoSInformation != NULLP)
+ {
+ drbItem->qoSInformation->present = QoSInformation_PR_choice_extension;
+
+ switch(drbItem->qoSInformation->present)
+ {
+ case QoSInformation_PR_NOTHING:
+ {
+ break;
+ }
+ case QoSInformation_PR_eUTRANQoS:
+ {
+
+ CU_ALLOC(drbItem->qoSInformation->choice.eUTRANQoS, sizeof(EUTRANQoS_t));
+ if(drbItem->qoSInformation->choice.eUTRANQoS)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in FillDrbToBeModItem");
+ return RFAILED;
+ }
+ drbItem->qoSInformation->choice.eUTRANQoS->qCI = QCI;
+ drbItem->qoSInformation->choice.eUTRANQoS->allocationAndRetentionPriority.priorityLevel =
+ PriorityLevel_no_priority;
+
+ drbItem->qoSInformation->choice.eUTRANQoS->allocationAndRetentionPriority.pre_emptionCapability =
+ Pre_emptionCapability_may_trigger_pre_emption;
+
+ drbItem->qoSInformation->choice.eUTRANQoS->allocationAndRetentionPriority.pre_emptionVulnerability =
+ Pre_emptionVulnerability_pre_emptable;
+
+ break;
+ }
+ case QoSInformation_PR_choice_extension:
+ {
+ CU_ALLOC(drbItem->qoSInformation->choice.choice_extension,sizeof(QoSInformation_ExtIEs_t));
+ if(drbItem->qoSInformation->choice.choice_extension == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in FillDrbItemToSetupMod");
+ return RFAILED;
+ }
+
+ drbItem->qoSInformation->choice.choice_extension->id = ProtocolIE_ID_id_DRB_Information;
+ drbItem->qoSInformation->choice.choice_extension->criticality = Criticality_ignore;
+ drbItem->qoSInformation->choice.choice_extension->value.present = QoSInformation_ExtIEs__value_PR_DRB_Information;
+ ret = BuildQOSInfo(&drbToBeMod->qos, &drbItem->qoSInformation->choice.choice_extension->value.choice.DRB_Information.dRB_QoS,\
+ ProtocolIE_ID_id_DRBs_ToBeModified_Item, INVALID_PDU_SESSION_ID, FALSE);
+ if(ret != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildQOSInfo failed");
+ return RFAILED;
+ }
+
+ /*SNSSAI*/
+ ret = BuildSNSSAI(drbToBeMod, &drbItem->qoSInformation->choice.\
+ choice_extension->value.choice.DRB_Information.sNSSAI, cuCb.snssaiList[0], FALSE);
+ if(ret != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildSNSSAI failed");
+ return RFAILED;
+ }
+
+ /*Flows mapped to DRB List*/
+ ret = BuildFlowsMap(drbToBeMod, &drbItem->qoSInformation->choice.\
+ choice_extension->value.choice.DRB_Information.flows_Mapped_To_DRB_List,\
+ ProtocolIE_ID_id_DRBs_ToBeModified_Item, FALSE);
+ if(ret != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildFlowsMap failed");
+ return RFAILED;
+ }
+ }
+ }
+ }/* End of QoS */
+
+ /*ULUPTNLInformation To Be Setup List*/
+ ret = BuildUlTnlInfoforSetupMod(duId, ueCb->gnbCuUeF1apId, drbItem->dRBID, &drbToBeMod->ulUpTnlInfo, &drbItem->uLUPTNLInformation_ToBeSetup_List,\
+ ProtocolIE_ID_id_DRBs_ToBeModified_Item);
+ if(ret != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildUlTnlInfoforSetupMod failed");
+ return RFAILED;
+ }
+ return ROK;
+}
+
+/*******************************************************************
+*
+* @brief Builds the DRB to be modified Item IE
+*
+* @details
+*
+* Function : FillDrbToBeModItemList
+*
+* Functionality: Constructs the DRB to be modified Mod Item Ies
+*
+* @params[in] struct DRBs_ToBeModified_ItemIEs *drbItemIe
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+
+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(duId, ueCb, arrIdx, &(drbItemIe->value.choice.DRBs_ToBeModified_Item)) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : FillDrbToBeModItem failed");
+ return RFAILED;
+ }
+
+ return ROK;
+}
+
+/*******************************************************************
+*
+* @brief Builds the DRB to be modified list
+*
+* @details
+*
+* Function : BuildDrbToBeModList
+*
+* Functionality: Constructs the DRB to be modified list
+*
+* @params[in] DRBs_ToBeModified_List_t *drbSet
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+
+uint8_t BuildDrbToBeModifiedList(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeModified_List_t *drbSet)
+{
+ uint8_t ret = ROK;
+ uint8_t arrIdx =0;
+ uint8_t drbCnt =0;
+
+ drbCnt = MAX_DRB_MODIFIED_UE_MOD_REQ;
+ drbSet->list.count = drbCnt;
+ drbSet->list.size = drbCnt * sizeof(DRBs_ToBeModified_ItemIEs_t *);
+ CU_ALLOC(drbSet->list.array, drbSet->list.size);
+ if(drbSet->list.array == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in BuildDrbToBeModifiedList");
+ return RFAILED;
+ }
+ for(arrIdx=0; arrIdx<drbCnt; arrIdx++)
+ {
+ CU_ALLOC(drbSet->list.array[arrIdx], sizeof(DRBs_ToBeModified_ItemIEs_t));
+ if(drbSet->list.array[arrIdx] == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in BuildDrbToBeSetupList");
+ return RFAILED;
+ }
+
+ ret = FillDrbToBeModItemList(duId, ueCb, arrIdx, (DRBs_ToBeModified_ItemIEs_t *)drbSet->list.array[arrIdx]);
+ if(ret != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : FillDrbToBeModItemList failed");
+ }
+ }
+
+ return ret;
+}
+
+/*******************************************************************
+*
+* @brief Builds the DRB to be released Item IE
+*
+* @details
+*
+* Function : FillDrbToBeRelItemList
+*
+* Functionality: Constructs the DRB to be modified Mod Item Ies
+*
+* @params[in] struct DRBs_ToBeReleased_ItemIEs *drbItemIe
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+
+uint8_t FillDrbToBeRelItemList(uint32_t duId, CuUeCb *ueCb, uint8_t arrIdx, struct DRBs_ToBeReleased_ItemIEs *drbItemIe)
+{
+ uint8_t drbIdx;
+
+ drbItemIe->id = ProtocolIE_ID_id_DRBs_ToBeReleased_Item;
+ drbItemIe->criticality = Criticality_reject;
+ drbItemIe->value.present = DRBs_ToBeReleased_ItemIEs__value_PR_DRBs_ToBeReleased_Item;
+ drbItemIe->value.choice.DRBs_ToBeReleased_Item.dRBID = DRB1 + arrIdx;
+
+ for(drbIdx = 0; drbIdx < ueCb->numDrb; drbIdx++)
+ {
+ if(ueCb->drbList[drbIdx].drbId == drbItemIe->value.choice.DRBs_ToBeReleased_Item.dRBID)
+ {
+ deleteEgtpTunnel(duId, ueCb->drbList[drbIdx].dlUpTnlInfo.teId);
+ CU_FREE(ueCb->drbList[drbIdx].snssai, sizeof(Snssai));
+ break;
+ }
+ }
+ return ROK;
+}
+
+/*******************************************************************
+*
+* @brief Builds the DRB to be released list
+*
+* @details
+*
+* Function : BuildDrbToBeReleasedList
+*
+* Functionality: Constructs the DRB to be released list
+*
+* @params[in] DRBs_ToBeReleased_List_t *drbSet
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+
+uint8_t BuildDrbToBeReleasedList(uint32_t duId, CuUeCb *ueCb, DRBs_ToBeReleased_List_t *drbSet)
+{
+ uint8_t ret = ROK;
+ uint8_t arrIdx =0;
+ uint8_t drbCnt =0;
+
+ drbCnt = MAX_DRB_MODIFIED_UE_MOD_REQ;
+ drbSet->list.count = drbCnt;
+ drbSet->list.size = drbCnt * sizeof(DRBs_ToBeReleased_ItemIEs_t *);
+ CU_ALLOC(drbSet->list.array, drbSet->list.size);
+ if(drbSet->list.array == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in BuildDrbToBeReleasedList");
+ return RFAILED;
+ }
+ for(arrIdx=0; arrIdx<drbCnt; arrIdx++)
+ {
+ CU_ALLOC(drbSet->list.array[arrIdx], sizeof(DRBs_ToBeReleased_ItemIEs_t));
+ if(drbSet->list.array[arrIdx] == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation failed in BuildDrbToBeReleasedList");
+ return RFAILED;
+ }
+
+ ret = FillDrbToBeRelItemList(duId, ueCb, arrIdx, (DRBs_ToBeReleased_ItemIEs_t *)drbSet->list.array[arrIdx]);
+ if(ret != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : FillDrbToBeRelItemList failed");
+ }
+ }
+
+ return ret;
+}
+
+/*******************************************************************
+*
+* @brief freeing the DRB item
+*
+* @details
+*
+* Function : FreeModifiedDrbItem
+*
+* Functionality: freeing the DRB 2 item
+*
+* @params[in] DRBs_ToBeSetupMod_Item_t *drbItem
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+
+void FreeModifiedDrbItem(DRBs_ToBeModified_Item_t *drbItem)
+{
+ uint8_t arrIdx =0;
+ SNSSAI_t *snssai =NULLP;
+ Flows_Mapped_To_DRB_List_t *flowMap = NULLP;
+
+ if(drbItem->qoSInformation != NULLP)
+ {
+ switch(drbItem->qoSInformation->present)
+ {
+ case QoSInformation_PR_NOTHING:
+ break;
+ case QoSInformation_PR_eUTRANQoS:
+ {
+ if(drbItem->qoSInformation->choice.eUTRANQoS)
+ {
+ CU_FREE(drbItem->qoSInformation->choice.eUTRANQoS, sizeof(EUTRANQoS_t));
+ }
+ break;
+ }
+ case QoSInformation_PR_choice_extension:
+ {
+ if(drbItem->qoSInformation->choice.choice_extension)
+ {
+ FreeQOSInfo(&drbItem->qoSInformation->choice.choice_extension->value.choice.DRB_Information.dRB_QoS);
+
+ snssai = &drbItem->qoSInformation->choice.choice_extension->value.choice.DRB_Information.sNSSAI;
+ if(snssai->sST.buf)
+ {
+ CU_FREE(snssai->sST.buf,snssai->sST.size);
+ }
+ if(snssai->sD)
+ {
+ if(snssai->sD->buf)
+ {
+ CU_FREE(snssai->sD->buf,snssai->sD->size);
+ }
+ CU_FREE(snssai->sD,sizeof(OCTET_STRING_t));
+ }
+
+ flowMap = &drbItem->qoSInformation->choice.choice_extension->value.choice.DRB_Information.flows_Mapped_To_DRB_List;
+ if(flowMap->list.array)
+ {
+ for(arrIdx=0; arrIdx<flowMap->list.count; arrIdx++)
+ {
+ if(flowMap->list.array[arrIdx] )
+ {
+ FreeQOSInfo(&flowMap->list.array[arrIdx]->qoSFlowLevelQoSParameters);
+ CU_FREE(flowMap->list.array[arrIdx],sizeof(Flows_Mapped_To_DRB_Item_t));
+ }
+ }
+ CU_FREE(flowMap->list.array,flowMap->list.size);
+ }
+
+ CU_FREE(drbItem->qoSInformation->choice.choice_extension,sizeof(QoSInformation_ExtIEs_t));
+ }
+ break;
+ }
+ }
+ }
+ FreeUlTnlInfoforDrb2(&drbItem->uLUPTNLInformation_ToBeSetup_List);
+ if(drbItem->uLConfiguration)
+ {
+ CU_FREE(drbItem->uLConfiguration,sizeof(ULConfiguration_t));
+ }
+}
+
+/*******************************************************************
+*
+* @brief free the DRB to be modfified list
+*
+* @details
+*
+* Function : FreeDrbToBeModifiedList
+*
+* Functionality: free the DRB to be Setup Mod list
+*
+* @params[in] FreeDrbToBeModifiedList_t *drbSet
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+void FreeDrbToBeModifiedList(DRBs_ToBeModified_List_t *drbSet)
+{
+ uint8_t arrIdx =0;
+ struct DRBs_ToBeModified_ItemIEs *drbItemIe;
+
+ if(drbSet->list.array)
+ {
+ for(arrIdx=0; arrIdx<drbSet->list.count ; arrIdx++)
+ {
+ if(drbSet->list.array[arrIdx] != NULLP)
+ {
+ drbItemIe = (struct DRBs_ToBeModified_ItemIEs *)drbSet->list.array[arrIdx];
+ FreeModifiedDrbItem(&(drbItemIe->value.choice.DRBs_ToBeModified_Item));
+ CU_FREE(drbSet->list.array[arrIdx], sizeof(DRBs_ToBeModified_ItemIEs_t));
+ }
+ }
+ CU_FREE(drbSet->list.array, drbSet->list.size);
+ }
+
+}
+
+/*******************************************************************
+*
+* @brief free the DRB to be modfified list
+*
+* @details
+*
+* Function : FreeDrbToBeReleasedList
+*
+* Functionality: free the DRB to be Release list
+*
+* @params[in] FreeDrbToBeReleasedList_t *drbSet
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+void FreeDrbToBeReleasedList(DRBs_ToBeReleased_List_t *drbSet)
+{
+ uint8_t arrIdx =0;
+ struct DRBs_ToBeReleased_ItemIEs *drbItemIe;
+
+ if(drbSet->list.array)
+ {
+ for(arrIdx=0; arrIdx<drbSet->list.count ; arrIdx++)
+ {
+ if(drbSet->list.array[arrIdx] != NULLP)
+ {
+ CU_FREE(drbSet->list.array[arrIdx], sizeof(DRBs_ToBeReleased_ItemIEs_t));
+ }
+ }
+ CU_FREE(drbSet->list.array, drbSet->list.size);
+ }
+}
+
+/*******************************************************************
+ *
+ * @brief free the UeContextModification Request
+ *
+ * @details
+ *
+ * Function : FreeUeContextModicationRequest
+ *
+ * Functionality : deallocation of memory allocated in UeContextModiification
+ request
+ *
+ * @params[in] F1AP_PDU_t *f1apMsg
+ *
+ * @return void
+*
+* ****************************************************************/
+void FreeUeContextModicationRequest(F1AP_PDU_t *f1apMsg)
+{
+ uint8_t arrIdx =0 , ieId=0;
+ UEContextModificationRequest_t *ueContextModifyReq = NULLP;
+
+ if(f1apMsg)
+ {
+ if(f1apMsg->choice.initiatingMessage)
+ {
+ ueContextModifyReq =&f1apMsg->choice.initiatingMessage->value.choice.UEContextModificationRequest;
+ if(ueContextModifyReq->protocolIEs.list.array)
+ {
+ for( arrIdx = 0 ; arrIdx<ueContextModifyReq->protocolIEs.list.count ; arrIdx++)
+ {
+ if(ueContextModifyReq->protocolIEs.list.array[arrIdx])
+ {
+ ieId = ueContextModifyReq->protocolIEs.list.array[arrIdx]->id;
+ switch(ieId)
+ {
+ case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
+ break;
+ case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
+ break;
+ case ProtocolIE_ID_id_DRBs_ToBeSetupMod_List:
+ {
+ 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_ToBeModified_List);
+ break;
+ }
+ case ProtocolIE_ID_id_DRBs_ToBeReleased_List:
+ {
+ FreeDrbToBeReleasedList(&ueContextModifyReq->protocolIEs.list.array[arrIdx]->value.\
+ choice.DRBs_ToBeReleased_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, ueContextModifyReq->protocolIEs.list.size);
+ }
+ CU_FREE(f1apMsg->choice.initiatingMessage, sizeof(InitiatingMessage_t));
+ }
+ CU_FREE(f1apMsg, sizeof(F1AP_PDU_t));
+ }
+}
+
+/*******************************************************************
+ *
+ * @brief Builds the Ue Context Modification Req
+ *
+ * @details
+ *
+ * Function : BuildAndSendUeContextModificationReq
+ *
+ * Functionality: Constructs the Ue Context Modification Req
+ *
+ * @params[in]
+ *
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t BuildAndSendUeContextModificationReq(uint32_t duId, void *cuUeCb, UeCtxtModAction action)
+{
+ uint8_t ieIdx = 0;
+ uint8_t elementCnt = 0;
+ uint8_t ret = RFAILED;
+ uint16_t tmpBufIdx = 0, bufIdx = 0;
+ CuUeCb *ueCb = (CuUeCb *)cuUeCb;
+ F1AP_PDU_t *f1apMsg = NULLP;
+ UEContextModificationRequest_t *ueContextModifyReq = NULLP;
+ RRCContainer_t rrcContainerTmp, *rrcContainer = 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));
+ if(f1apMsg == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation for F1AP-PDU failed Ue context modification");
+ 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 Ue context modification");
+ break;
+ }
+ f1apMsg->choice.initiatingMessage->procedureCode = ProcedureCode_id_UEContextModification;
+ f1apMsg->choice.initiatingMessage->criticality = Criticality_reject;
+ f1apMsg->choice.initiatingMessage->value.present = InitiatingMessage__value_PR_UEContextModificationRequest;
+
+ ueContextModifyReq =&f1apMsg->choice.initiatingMessage->value.choice.UEContextModificationRequest;
+
+ if(action == MODIFY_UE)
+ elementCnt = 5;
+ else if(action == QUERY_CONFIG)
+ elementCnt = 3;
+ else if(action == RRC_RECONFIG_COMPLETE_IND)
+ elementCnt = 3;
+ else if((action == STOP_DATA_TX) || (action == RESTART_DATA_TX))
+ {
+ if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
+ elementCnt = 5;
+ else
+ elementCnt = 4;
+ }
+
+#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 *);
+
+ /* Initialize the UE context modification members */
+ CU_ALLOC(ueContextModifyReq->protocolIEs.list.array, ueContextModifyReq->protocolIEs.list.size);
+ if(ueContextModifyReq->protocolIEs.list.array == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation for UE context modifcation Request failed");
+ break;
+ }
+
+ for(ieIdx=0 ; ieIdx<elementCnt; ieIdx++)
+ {
+ CU_ALLOC(ueContextModifyReq->protocolIEs.list.array[ieIdx], sizeof(UEContextModificationRequest_t));
+ if(ueContextModifyReq->protocolIEs.list.array[ieIdx] == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation for UE context modifcation Request failed");
+ break;
+ }
+ }
+
+ ieIdx=0;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = \
+ UEContextModificationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.GNB_CU_UE_F1AP_ID = ueCb->gnbCuUeF1apId;
+
+ ieIdx++;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present=\
+ UEContextModificationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.GNB_DU_UE_F1AP_ID = ueCb->gnbDuUeF1apId;
+
+ if(action == MODIFY_UE)
+ {
+ /* DRB to be setup list */
+ ieIdx++;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_DRBs_ToBeSetupMod_List;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present =\
+ UEContextModificationRequestIEs__value_PR_DRBs_ToBeSetupMod_List;
+ ret = BuildDrbToBeSetupList(duId, ueCb, &(ueContextModifyReq->protocolIEs.list.array[ieIdx]->\
+ value.choice.DRBs_ToBeSetupMod_List));
+
+ /* DRB to be modified list */
+ ieIdx++;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_DRBs_ToBeModified_List;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present =\
+ UEContextModificationRequestIEs__value_PR_DRBs_ToBeModified_List;
+ ret = BuildDrbToBeModifiedList(duId, ueCb, &(ueContextModifyReq->protocolIEs.list.array[ieIdx]->\
+ value.choice.DRBs_ToBeModified_List));
+
+ if(ret != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildAndSendUeContextModificationReq(): Failed to build drb to be modified list");
+ break;
+ }
+
+ /* DRB to be released list */
+ ieIdx++;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_DRBs_ToBeReleased_List;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present =\
+ UEContextModificationRequestIEs__value_PR_DRBs_ToBeReleased_List;
+ ret = BuildDrbToBeReleasedList(duId, ueCb, &(ueContextModifyReq->protocolIEs.list.array[ieIdx]->\
+ value.choice.DRBs_ToBeReleased_List));
+
+ if(ret != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildAndSendUeContextModificationReq(): Failed to build drb to be deleted list");
+ break;
+ }
+ }
+ else if(action == QUERY_CONFIG)
+ {
+ ieIdx++;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_GNB_DUConfigurationQuery;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = \
+ UEContextModificationRequestIEs__value_PR_GNB_DUConfigurationQuery;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.GNB_DUConfigurationQuery = GNB_DUConfigurationQuery_true;
+ }
+ else if(action == RRC_RECONFIG_COMPLETE_IND)
+ {
+ ieIdx++;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_RRCReconfigurationCompleteIndicator;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = \
+ UEContextModificationRequestIEs__value_PR_RRCReconfigurationCompleteIndicator;
+ 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(fillDlDcchRrcMsg(ueCb, &rrcContainerTmp, true) != ROK)
+ {
+ DU_LOG( "\nERROR --> F1AP : Failed to fill Rrc reconfiguration buffer");
+ return RFAILED;
+ }
+
+ rrcContainer = &ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer;
+ rrcContainer->size = rrcContainerTmp.size + 2; /* 2 bytes of PDCP SN */
+ CU_ALLOC(rrcContainer->buf, rrcContainer->size);
+ memset(rrcContainer->buf, 0, rrcContainer->size);
+ rrcContainer->buf[0] = 0x00;
+ rrcContainer->buf[1] = ueCb->pdcpSn; //PDCP SN
+ for(bufIdx = 2, tmpBufIdx = 0; bufIdx < rrcContainer->size; bufIdx++, tmpBufIdx++)
+ {
+ rrcContainer->buf[bufIdx] = rrcContainerTmp.buf[tmpBufIdx];
+ }
+
+ /* RRC delivery status request */
+ if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
+ {
+ ieIdx++;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_RRCDeliveryStatusRequest;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.present = UEContextModificationRequestIEs__value_PR_RRCDeliveryStatusRequest;
+ ueContextModifyReq->protocolIEs.list.array[ieIdx]->value.choice.RRCDeliveryStatusRequest = RRCDeliveryStatusRequest_true;
+ }
+ }
+
+#ifdef NR_DRX
+ if(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);
+
+ /* 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 ueContextModifyReq structure (at %s)\n",\
+ encRetVal.failed_type ? encRetVal.failed_type->name : "unknown");
+ break;
+ }
+ 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 */
+ if(SendF1APMsg(CU_APP_MEM_REG, CU_POOL, duId) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : Sending Ue context modification request failed");
+ break;
+ }
+
+ ret = ROK;
+ break;
+
+ }
+ FreeUeContextModicationRequest(f1apMsg);
+ return ret;
+}
+
+/*****************************************************************i
+ *
+* @brief Free memory allocated for UE Context Release Command
+*
+* @details
+*
+* Function : FreeUeContextReleaseCommand
+*
+* Functionality:
+* - Free memory allocated for UE Context Release Command
+*
+* @params[in] F1AP_PDU_t *f1apMsg
+* @return void
+*
+* *************************************************************/
+void FreeUeContextReleaseCommand(F1AP_PDU_t *f1apMsg)
+{
+ uint8_t ieIdx;
+ UEContextReleaseCommand_t *ueReleaseCommand = NULLP;
+
+ if(f1apMsg)
+ {
+ if(f1apMsg->choice.initiatingMessage)
+ {
+ ueReleaseCommand =&f1apMsg->choice.initiatingMessage->value.choice.UEContextReleaseCommand;
+ if(ueReleaseCommand->protocolIEs.list.array)
+ {
+ for(ieIdx=0 ; ieIdx<ueReleaseCommand->protocolIEs.list.count; ieIdx++)
+ {
+ CU_FREE(ueReleaseCommand->protocolIEs.list.array[ieIdx], sizeof(UEContextReleaseCommand_t));
+ }
+ CU_FREE(ueReleaseCommand->protocolIEs.list.array, ueReleaseCommand->protocolIEs.list.size);
+ }
+ CU_FREE(f1apMsg->choice.initiatingMessage, sizeof(InitiatingMessage_t));
+ }
+ CU_FREE(f1apMsg, sizeof(F1AP_PDU_t));
+ }
+}
+/*******************************************************************
+ *
+ * @brief Builds the Ue Context Release Command
+ *
+ * @details
+*
+* Function : BuildAndSendUeContextReleaseCommand
+*
+* Functionality: Constructs the Ue Context Release Command
+*
+* @params[in]
+*
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+uint8_t BuildAndSendUeContextReleaseCommand(uint32_t duId, uint8_t cuUeF1apId, uint8_t duUeF1apId)
+{
+ bool memAllocFailed = false;
+ uint8_t duIdx = 0, ieIdx = 0,elementCnt = 0, ret = RFAILED, bufLen=0;
+ DuDb *duDb;
+ CuUeCb *ueCb;
+ F1AP_PDU_t *f1apMsg = NULLP;
+ UEContextReleaseCommand_t *ueContextReleaseCommand = NULLP;
+
+ asn_enc_rval_t encRetVal;
+ DU_LOG("\nINFO --> F1AP : Building Ue context release command\n");
+
+ while(true)
+ {
+ CU_ALLOC(f1apMsg, sizeof(F1AP_PDU_t));
+ if(f1apMsg == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildAndSendUeContextReleaseCommand(): 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 : BuildAndSendUeContextReleaseCommand(): Memory allocation for F1AP-PDU failed ");
+ break;
+ }
+ f1apMsg->choice.initiatingMessage->procedureCode = ProcedureCode_id_UEContextRelease;
+ f1apMsg->choice.initiatingMessage->criticality = Criticality_reject;
+ f1apMsg->choice.initiatingMessage->value.present = InitiatingMessage__value_PR_UEContextReleaseCommand;
+
+ ueContextReleaseCommand =&f1apMsg->choice.initiatingMessage->value.choice.UEContextReleaseCommand;
+
+ SEARCH_DU_DB(duIdx, duId, duDb);
+ ueCb = &duDb->ueCb[duUeF1apId-1];
+ if(ueCb->state == UE_HANDOVER_IN_PROGRESS)
+ elementCnt = 3;
+ else
+ elementCnt = 4;
+
+ ueContextReleaseCommand->protocolIEs.list.count = elementCnt;
+ ueContextReleaseCommand->protocolIEs.list.size = elementCnt*sizeof(UEContextReleaseCommand_t*);
+
+ /* Initialize the UE context modification members */
+ CU_ALLOC(ueContextReleaseCommand->protocolIEs.list.array, ueContextReleaseCommand->protocolIEs.list.size);
+ if(ueContextReleaseCommand->protocolIEs.list.array == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildAndSendUeContextReleaseCommand():Memory allocation failed");
+ break;
+ }
+
+ for(ieIdx=0 ; ieIdx<elementCnt; ieIdx++)
+ {
+ CU_ALLOC(ueContextReleaseCommand->protocolIEs.list.array[ieIdx], sizeof(UEContextReleaseCommand_t));
+ if(ueContextReleaseCommand->protocolIEs.list.array[ieIdx] == NULLP)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildAndSendUeContextReleaseCommand(): Memory allocation failed ");
+ memAllocFailed = true;
+ break;
+ }
+ }
+
+ if(memAllocFailed == true)
+ {
+ break;
+ }
+
+ ieIdx=0;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->value.present = \
+ UEContextReleaseCommandIEs__value_PR_GNB_CU_UE_F1AP_ID;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->value.choice.GNB_CU_UE_F1AP_ID =cuUeF1apId;
+
+ ieIdx++;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->criticality = Criticality_reject;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->value.present=\
+ UEContextReleaseCommandIEs__value_PR_GNB_DU_UE_F1AP_ID;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->value.choice.GNB_DU_UE_F1AP_ID =duUeF1apId;
+
+ /* Cause of UE context release */
+ ieIdx++;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_Cause;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->value.present=\
+ UEContextReleaseCommandIEs__value_PR_Cause;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->value.choice.Cause.present = Cause_PR_radioNetwork;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->value.choice.Cause.choice.radioNetwork=\
+ CauseRadioNetwork_normal_release;
+ if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
+ {
+ /* RRC Container for RRC release */
+ ieIdx++;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->id = ProtocolIE_ID_id_RRCContainer;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->criticality = Criticality_ignore;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->value.present = \
+ UEContextReleaseCommandIEs__value_PR_RRCContainer;
+ char secModeBuf[7]={ 0x00, 0x05, 0x13, 0x00, 0x00, 0x00, 0x00};
+ bufLen =7;
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer.size = bufLen;
+ CU_ALLOC(ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer.buf,
+ ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer.size);
+ if(!ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer.buf)
+ {
+ DU_LOG("\nERROR --> F1AP : Memory allocation for BuildAndSendUeContextReleaseCommand failed");
+ break;
+ }
+ memset(ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer.buf, 0, bufLen);
+ memcpy(ueContextReleaseCommand->protocolIEs.list.array[ieIdx]->value.choice.RRCContainer.buf, secModeBuf, bufLen);
+ }
+ 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 Ue Context Release Command\n");
+ for(ieIdx=0; ieIdx< encBufSize; ieIdx++)
+ {
+ DU_LOG("%x",encBuf[ieIdx]);
+ }
+ }
+
+ /* TODO : Hardcoding DU ID to 1 for messages other than F1 Setup Response. This will be made generic in future gerrit */
+ if(SendF1APMsg(CU_APP_MEM_REG, CU_POOL, duId) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : Sending Ue context Release Command failed");
+ break;
+ }
+
+ ret = ROK;
+ break;
+
+ }
+ FreeUeContextReleaseCommand(f1apMsg);
+ return ret;
+}
+/*******************************************************************
+*
+* @brief process Ue context release request
+*
+* @details
+*
+* Function : procUeContextReleaseReq
+*
+* Functionality:
+* - process Ue context release request
+*
+* @params[in] F1AP_PDU_t *f1apMsg
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+uint8_t procUeContextReleaseReq(uint32_t duId, F1AP_PDU_t *f1apMsg)
+{
+ uint8_t ieIdx=0, duUeF1apId=0,cuUeF1apId=0;
+
+ UEContextReleaseRequest_t *ueReleaseReq = NULLP;
+ ueReleaseReq = &f1apMsg->choice.initiatingMessage->value.choice.UEContextReleaseRequest;
+
+ for(ieIdx=0; ieIdx < ueReleaseReq->protocolIEs.list.count; ieIdx++)
+ {
+ switch(ueReleaseReq->protocolIEs.list.array[ieIdx]->id)
+ {
+ case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
+ {
+ cuUeF1apId = ueReleaseReq->protocolIEs.list.array[ieIdx]->value.choice.GNB_CU_UE_F1AP_ID;
+ break;
+ }
+ case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
+ {
+ duUeF1apId = ueReleaseReq->protocolIEs.list.array[ieIdx]->value.choice.GNB_DU_UE_F1AP_ID;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if(BuildAndSendUeContextReleaseCommand(duId, cuUeF1apId, duUeF1apId) != ROK)
+ {
+ DU_LOG("\nERROR --> F1AP : procUeContextReleaseReq(): Failed to build Ue Context Release Command ");
+ return RFAILED;
+ }
+ return ROK;
+}
+/*******************************************************************
+*
+* @brief processing of Gnb-DU config update
+*
+* @details
+*
+* Function : procGnbDuUpdate
+*
+* Functionality:
+* - processing of Gnb-DU config update
+*
+* @params[in] F1AP_PDU_t *f1apMsg
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+uint8_t procGnbDuUpdate(uint32_t duId, F1AP_PDU_t *f1apMsg)
+{
+ bool cellToBeDelete = false;
+ uint8_t ieIdx = 0, ueIdx = 0, duIdx = 0, cellIdx=0;
+ uint16_t nrCellId;
+ DuDb *duDb;
+ CuCellCb *cellCb;
+ GNBDUConfigurationUpdate_t *duCfgUpdate = NULLP;
+
+ duCfgUpdate = &f1apMsg->choice.initiatingMessage->value.choice.GNBDUConfigurationUpdate;
+ for(ieIdx=0; ieIdx < duCfgUpdate->protocolIEs.list.count; ieIdx++)
+ {
+ switch(duCfgUpdate->protocolIEs.list.array[ieIdx]->id)
+ {
+ case ProtocolIE_ID_id_TransactionID:
+ break;
+ case ProtocolIE_ID_id_Served_Cells_To_Modify_List:
+ break;
+ case ProtocolIE_ID_id_Served_Cells_To_Delete_List:
+ {
+ 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];
+ bitStringToInt(&deleteItemIe->value.choice.Served_Cells_To_Delete_Item.oldNRCGI.nRCellIdentity, &nrCellId);
+ cellToBeDelete = true;
+ break;
+ }
+ case ProtocolIE_ID_id_gNB_DU_ID:
+ break;
+ }
+ }
+ if(BuildAndSendDUUpdateAck(duId) != ROK)
+ {
+ DU_LOG("ERROR --> F1AP : Failed to build and send DUUpdateAck");
+ return RFAILED;
+ }
+#if 0
+ /* We don't require F1 Reset message in Cell Up and Broadcast Procedure flow, So that's why
+ * commented this trigger for now */
+
+ if(cellToBeDelete == false)
+ {
+ DU_LOG("\nINFO --> F1AP : Sending F1 reset request");
+ if(BuildAndSendF1ResetReq() != ROK)
+ {
+ DU_LOG("ERROR --> F1AP : Failed to build and send F1 reset request");
+ return RFAILED;
+ }
+ }
+#endif
+ if(cellToBeDelete == true)
+ {
+ SEARCH_DU_DB(duIdx, duId, duDb);
+ SEARCH_CELL_DB(cellIdx, duDb, nrCellId, cellCb);
+ if(cellCb->numUe == 0)
+ {
+ memset(cellCb, 0, sizeof(CuCellCb));
+ duDb->numCells--;
+ }
+ else
+ cellCb->cellStatus = CELL_DELETION_IN_PROGRESS;
+ }
+ return ROK;
+}
+
+/*******************************************************************
+*
+* @brief storing slice list in CU database
+*
+* @details
+*
+* Function : buildSliceList
+*
+* Functionality:
+* - storing slice list in CU database
+*
+* @params[in] SliceSupportList_t *sliceSupportList
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+uint8_t buildSliceList(SliceSupportList_t *sliceSupportList)
+{
+ uint8_t sliceListIdx = 0;
+
+ if(sliceSupportList)
+ {
+ if(sliceSupportList->list.array)
+ {
+ cuCb.numSnssaiSupported = sliceSupportList->list.count;
+ for(sliceListIdx=0; sliceListIdx<sliceSupportList->list.count; sliceListIdx++)
+ {
+ if(sliceSupportList->list.array[sliceListIdx])
+ {
+ CU_ALLOC(cuCb.snssaiList[sliceListIdx], sizeof(Snssai));
+ if(cuCb.snssaiList[sliceListIdx] == NULLP)
+ {
+ DU_LOG("\nERROR --> CU_STUB: buildSliceList(): Memory allocation failed");
+ return RFAILED;
+ }
+ if(sliceSupportList->list.array[sliceListIdx]->sNSSAI.sST.buf)
+ {
+ memcpy(&cuCb.snssaiList[sliceListIdx]->sst, sliceSupportList->list.array[sliceListIdx]->\
+ sNSSAI.sST.buf, sliceSupportList->list.array[sliceListIdx]->sNSSAI.sST.size);
+ }
+ if(sliceSupportList->list.array[sliceListIdx]->sNSSAI.sD->size)
+ {
+ memcpy(&cuCb.snssaiList[sliceListIdx]->sd,\
+ sliceSupportList->list.array[sliceListIdx]->sNSSAI.sD->buf,\
+ sliceSupportList->list.array[sliceListIdx]->sNSSAI.sD->size);
+ }
+ }
+ }
+ }
+ }
+ return ROK;
+}
+
+/****************************************************************
+ * @brief Function to process Srb Setup Mod List
+ *
+ * @details
+ *
+ * Function : procSrbSetupModList
+ *
+ * Functionality:
+ * - Function to process SRB Setup Mod List
+ *
+ * @params[in]
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t procSrbSetupModList(CuUeCb *ueCb, SRBs_SetupMod_List_t *srbSetupList)
+{
+ uint8_t arrIdx = 0, srbIdx;
+ struct SRBs_SetupMod_ItemIEs *srbItemIe = NULLP;
+
+ if(srbSetupList != NULLP)
+ {
+ for(arrIdx = 0; arrIdx < srbSetupList->list.count; arrIdx++)
+ {
+ srbItemIe = ((struct SRBs_SetupMod_ItemIEs *)srbSetupList->list.array[arrIdx]);
+ if(srbItemIe->value.present == SRBs_SetupMod_ItemIEs__value_PR_SRBs_SetupMod_Item)
+ {
+ for(srbIdx = 0; srbIdx < ueCb->numSrb; srbIdx++)
+ {
+ if(ueCb->srbList[srbIdx].srbId == srbItemIe->value.choice.SRBs_SetupMod_Item.sRBID)
+ {
+ ueCb->srbList[srbIdx].lcId = srbItemIe->value.choice.SRBs_SetupMod_Item.lCID;
+ break;
+ }
+ }
+ }
+
+ }
+ }
+ return ROK;
+}
+
+
+/****************************************************************
+ * @brief Function to process Drb Setup Mod List
+ *
+ * @details
+ *
+ * Function : procDrbSetupModList
+ *
+ * Functionality:
+ * - Function to process DRB Setup Mod List
+ *
+ * @params[in]
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t procDrbSetupModList(uint32_t duId, CuUeCb *ueCb, DRBs_SetupMod_List_t *drbSetupList)
+{
+ uint8_t arrIdx = 0, drbIdx;
+ uint32_t teId = 0;
+ struct DRBs_SetupMod_ItemIEs *drbItemIe = NULLP;
+
+ if(drbSetupList != NULLP)
+ {
+ for(arrIdx = 0; arrIdx < drbSetupList->list.count; arrIdx++)
+ {
+ drbItemIe = ((struct DRBs_SetupMod_ItemIEs *)drbSetupList->list.array[arrIdx]);
+ if(drbItemIe->value.present == DRBs_SetupMod_ItemIEs__value_PR_DRBs_SetupMod_Item)
+ {
+ for(drbIdx = 0; drbIdx < ueCb->numDrb; drbIdx++)
+ {
+ if(ueCb->drbList[drbIdx].drbId == drbItemIe->value.choice.DRBs_SetupMod_Item.dRBID)
+ {
+ if(drbItemIe->value.choice.DRBs_SetupMod_Item.lCID)
+ ueCb->drbList[drbIdx].lcId = *(drbItemIe->value.choice.DRBs_SetupMod_Item.lCID);
+ break;
+ }
+ }
+
+ if(ueCb->state != UE_HANDOVER_IN_PROGRESS)
+ {
+ /* extracting teId */
+ teId = extractTeId(&drbItemIe->value.choice.DRBs_SetupMod_Item.dLUPTNLInformation_ToBeSetup_List);
+ if(teId > 0)
+ {
+ if(addDrbTunnels(duId, teId)== ROK)
+ {
+ DU_LOG("\nDEBUG --> EGTP: Tunnel Added for TeId %d", teId);
+ }
+ }
+ else
+ return RFAILED;
+ }
+ }
+ }
+ }
+ return ROK;
+}
+
+/*******************************************************************
+*
+* @brief processing of GNB_DU_Served_Cells Plmn list information
+*
+* @details
+*
+* Function : procServedCellPlmnList
+*
+* Functionality:
+* - processing of GNB_DU_Served_Cells Plmn list information for storing
+* SNSSAI list
+*
+* @params[in] F1AP_PDU_t *f1apMsg
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+uint8_t procServedCellPlmnList(ServedPLMNs_List_t *srvPlmn)
+{
+ uint8_t srvPlmnIdx=0, ieExtensionsLstIdx=0;
+ ProtocolExtensionContainer_4624P3_t **ieExtend;
+
+ if(srvPlmn->list.array)
+ {
+ for(srvPlmnIdx=0; srvPlmnIdx<srvPlmn->list.count; srvPlmnIdx++)
+ {
+ if(srvPlmn->list.array[srvPlmnIdx])
+ {
+ ieExtend = &srvPlmn->list.array[srvPlmnIdx]->iE_Extensions;
+ if(*ieExtend)
+ {
+ if((*ieExtend)->list.array)
+ {
+ for(ieExtensionsLstIdx = 0; ieExtensionsLstIdx<(*ieExtend)->list.count; ieExtensionsLstIdx++)
+ {
+ if((*ieExtend)->list.array[ieExtensionsLstIdx])
+ {
+ switch((*ieExtend)->list.array[ieExtensionsLstIdx]->id )
+ {
+ case ProtocolIE_ID_id_TAISliceSupportList:
+ {
+ if(buildSliceList(&(*ieExtend)->list.array[ieExtensionsLstIdx]->\
+ extensionValue.choice.SliceSupportList) != ROK)
+ {
+ DU_LOG("\nERROR --> CU_STUB: procServedCellPlmnList(): Failed to build slice List");
+ return RFAILED;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return ROK;
+}
+
+/****************************************************************
+ * @brief Function to process Ue Context Modification Response
+ *
+ * @details
+ *
+ * Function : procUeContextModificationResponse
+ *
+ * Functionality:
+ * - Function to process Ue Context Modification Response
+ *
+ * @params[in]
+ * @return ROK - success
+ * RFAILED - failure
+ *
+ * ****************************************************************/
+uint8_t procUeContextModificationResponse(uint32_t duId, F1AP_PDU_t *f1apMsg, char *recvBuf, MsgLen recvBufLen)
+{
+ 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);
+ ueCtxtModRsp = &f1apMsg->choice.successfulOutcome->value.choice.UEContextModificationResponse;
+
+ /* In case of Inter-CU Handover request received from peer CU */
+ if(duDb->tempUeCtxtInHo)
+ ueCb = duDb->tempUeCtxtInHo;
+
+ for(idx=0; idx < ueCtxtModRsp->protocolIEs.list.count; idx++)
+ {
+ switch(ueCtxtModRsp->protocolIEs.list.array[idx]->id)
+ {
+ case ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID:
+ {
+ if(ueCb == NULLP)
+ {
+ cuUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_CU_UE_F1AP_ID;
+ }
+ else
+ {
+ /* In case of Inter-CU Handover request received from peer CU */
+ cuUeF1apId = ueCb->gnbCuUeF1apId;
+ }
+ break;
+ }
+ case ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID:
+ {
+ if(!ueCb)
+ {
+ duUeF1apId = ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.GNB_DU_UE_F1AP_ID;
+ ueCb = &duDb->ueCb[duUeF1apId-1];
+
+ /* In case UE context modification response is received at source GNB CU from source GNB DU
+ * for a UE in handover, send HO request to target GNB only if not sent already.
+ * If HO Req is already sent to target GNB, and an HO Req Ack is received, then
+ * ueCb->hoInfo.cuUeF1apIdTgt will be non-zero
+ */
+ if((ueCb->state == UE_HANDOVER_IN_PROGRESS) && (ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO) && \
+ (ueCb->hoInfo.cuUeF1apIdTgt == 0))
+ {
+ BuildAndSendHOReq(ueCb, recvBuf, recvBufLen);
+ }
+ }
+ break;
+ }
+ case ProtocolIE_ID_id_DRBs_SetupMod_List:
+ {
+ /* Adding Tunnels for successful DRB */
+ procDrbSetupModList(duId, ueCb, &ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.DRBs_SetupMod_List);
+ break;
+
+ }
+ case ProtocolIE_ID_id_DRBs_Modified_List:
+ {
+ DU_LOG("\nINFO --> Received DRBs Modified List");
+ break;
+ }
+ case ProtocolIE_ID_id_SRBs_SetupMod_List:
+ {
+ procSrbSetupModList(ueCb, &ueCtxtModRsp->protocolIEs.list.array[idx]->value.choice.SRBs_SetupMod_List);
+ break;
+ }
+ case ProtocolIE_ID_id_DUtoCURRCInformation:
+ {
+ DU_LOG("\nINFO --> Received Du to Cu RRC Information ");
+ if((extractDuToCuRrcCont(ueCb, ueCtxtModRsp->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 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)
+ {
+ uint8_t ueIdx = 0;
+ uint8_t tgtDuId = 0;
+ DuDb *tgtDuDb = NULLP;
+ CuUeCb *ueCbInTgtDu = NULLP;
+
+ if(ueCb->hoInfo.HOType == Inter_DU_HO)
+ {
+ tgtDuId = ueCb->hoInfo.tgtNodeId;
+ }
+ else if (ueCb->hoInfo.HOType == Xn_Based_Inter_CU_HO)
+ {
+ tgtDuId = duId;
+ }
+
+ SEARCH_DU_DB(duIdx, tgtDuId, tgtDuDb);
+ if(tgtDuDb)
+ {
+ /* Since DU UE F1AP ID assigned by target DU to this UE in handover is
+ * not known here, using CU UE F1AP ID to search for UE Cb in target DU
+ * DB */
+ for(ueIdx = 0; ueIdx < MAX_NUM_UE; ueIdx++)
+ {
+ if(tgtDuDb->ueCb[ueIdx].gnbCuUeF1apId == cuUeF1apId)
+ {
+ ueCbInTgtDu = &tgtDuDb->ueCb[ueIdx];
+ break;
+ }
+ }
+
+ /* If UE context is not found in Target DU, send UE context setup
+ * request */
+ if(ueCbInTgtDu == NULLP)
+ {
+ if((BuildAndSendUeContextSetupReq(tgtDuId, ueCb)) != ROK)
+ {
+ DU_LOG("\nERROR -> F1AP : Failed at BuildAndSendUeContextSetupReq");
+ return RFAILED;
+ }
+ }
+ }
+ }
+
+#ifdef START_DL_UL_DATA
+ startDlData();
+#endif
+
+ return ROK;
+}
+
+/*******************************************************************
+*
+* @brief processing of F1 setup request
+*
+* @details
+*
+* Function : procF1SetupReq
+*
+* Functionality:
+* - processing of F1 setup request
+*
+* @params[in] F1AP_PDU_t *f1apMsg
+* @return ROK - success
+* RFAILED - failure
+*
+* ****************************************************************/
+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;
+ uint64_t nrCellId = 0;
+ DuDb *duDb = NULLP;
+ CuCellCb *cellCb = NULLP;
+ BIT_STRING_t nrcellIdentity;
+ F1SetupRequest_t *f1SetupReq = NULLP;
+ GNB_DU_Served_Cells_Item_t *srvCellItem = NULLP;
+ GNB_DU_Served_Cells_List_t *duServedCell = NULLP;
+
+ /* Triggering XN setup request before F1 setup establishment */
+ if(LOCAL_NODE_TYPE == CLIENT)
+ BuildAndSendXnSetupReq();
+
+ f1SetupReq = &f1apMsg->choice.initiatingMessage->value.choice.F1SetupRequest;
+ for(ieIdx=0; ieIdx < f1SetupReq->protocolIEs.list.count; ieIdx++)
+ {
+ switch(f1SetupReq->protocolIEs.list.array[ieIdx]->id)
+ {
+ case ProtocolIE_ID_id_gNB_DU_ID:
+ {
+ duId = f1SetupReq->protocolIEs.list.array[ieIdx]->value.choice.GNB_DU_ID.buf[0];
+ SEARCH_DU_DB(duIdx, duId, duDb);
+ if(duDb == NULLP)
+ {
+ duDb = &cuCb.duInfo[cuCb.numDu];
+ cuCb.numDu++;
+ }
+ memset(duDb, 0, sizeof(DuDb));
+ duDb->duId = duId;
+ *destDuId = duId;
+ break;
+ }
+ case ProtocolIE_ID_id_gNB_DU_Name:
+ {
+ strcpy((char *)duDb->duName, (char*)f1SetupReq->protocolIEs.list.array[ieIdx]->value.choice.GNB_DU_Name.buf);
+ break;
+ }
+ case ProtocolIE_ID_id_gNB_DU_Served_Cells_List:
+ {
+ duServedCell = &f1SetupReq->protocolIEs.list.array[ieIdx]->value.choice.GNB_DU_Served_Cells_List;
+ if(duServedCell->list.array)
+ {
+ for(plmnidx=0; plmnidx<duServedCell->list.count; plmnidx++)
+ {
+ if(duServedCell->list.array[plmnidx])
+ {
+ switch(duServedCell->list.array[plmnidx]->id)
+ {
+ case ProtocolIE_ID_id_GNB_DU_Served_Cells_Item:
+ {
+ 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));
+
+ 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++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if(ret == ROK)
+ {
+ BuildAndSendF1SetupRsp(duId, &nrcellIdentity);
+ }
+ else
+ {
+ DU_LOG("\nERROR --> CU_STUB: procF1SetupReq(): Failed to process F1 setup request");
+ }
+}
+
+/****************************************************************
+*
+* @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;
+ }
+ if(duDb->numCells == 0)
+ {
+ DU_LOG("\nERROR --> F1AP : BuildAndSendPagingMsg(): No CELL is UP!");
+ 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;