Files
openairinterface5g/openair2/GNB_APP/gnb_config.c
T
Robert Schmidt 67d5f56a3c Read F1 Setup Req at MAC initialization
Previously, filling of F1 Setup Request depended on reading the RRC;
hence, for timing reasons, we only initialized and sent the F1 Setup
Request once the MAC and RRC are ready.

After moving SCC, SCD, MIB, and SIB1 to MAC, the MAC does not depend on
an RRC being present anymore, and hence, the F1 Setup Request does
neither. In this commit, we read the F1 Setup Request after initializing
the MAC.
2023-09-22 08:22:15 +02:00

2168 lines
121 KiB
C

/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*
gnb_config.c
-------------------
AUTHOR : Lionel GAUTHIER, navid nikaein, Laurent Winckel, WEI-TAI CHEN
COMPANY : EURECOM, NTUST
EMAIL : Lionel.Gauthier@eurecom.fr, navid.nikaein@eurecom.fr, kroempa@gmail.com
*/
#include <string.h>
#include <inttypes.h>
#include "common/utils/LOG/log.h"
#include "common/utils/nr/nr_common.h"
#include "common/utils/LOG/log_extern.h"
#include "assertions.h"
#include "oai_asn1.h"
#include "executables/softmodem-common.h"
#include "gnb_config.h"
#include "gnb_paramdef.h"
#include "enb_paramdef.h"
#include "UTIL/OTG/otg.h"
#include "UTIL/OTG/otg_externs.h"
#include "intertask_interface.h"
#include "s1ap_eNB.h"
#include "ngap_gNB.h"
#include "sctp_eNB_task.h"
#include "sctp_default_values.h"
#include "F1AP_CauseRadioNetwork.h"
#include "f1ap_common.h"
// #include "SystemInformationBlockType2.h"
// #include "LAYER2/MAC/extern.h"
// #include "LAYER2/MAC/proto.h"
#include "PHY/INIT/nr_phy_init.h"
#include "radio/ETHERNET/ethernet_lib.h"
#include "nfapi_vnf.h"
#include "nfapi_pnf.h"
#include "nr_pdcp/nr_pdcp_oai_api.h"
//#include "L1_paramdef.h"
#include "prs_nr_paramdef.h"
#include "L1_nr_paramdef.h"
#include "MACRLC_nr_paramdef.h"
#include "common/config/config_userapi.h"
//#include "RRC_config_tools.h"
#include "gnb_paramdef.h"
#include "NR_MAC_gNB/mac_proto.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "NR_asn_constant.h"
#include "executables/thread-common.h"
#include "NR_SCS-SpecificCarrier.h"
#include "NR_TDD-UL-DL-ConfigCommon.h"
#include "NR_FrequencyInfoUL.h"
#include "NR_RACH-ConfigGeneric.h"
#include "NR_RACH-ConfigCommon.h"
#include "NR_PUSCH-TimeDomainResourceAllocation.h"
#include "NR_PUSCH-ConfigCommon.h"
#include "NR_PUCCH-ConfigCommon.h"
#include "NR_PDSCH-TimeDomainResourceAllocation.h"
#include "NR_PDSCH-ConfigCommon.h"
#include "NR_RateMatchPattern.h"
#include "NR_RateMatchPatternLTE-CRS.h"
#include "NR_SearchSpace.h"
#include "NR_ControlResourceSet.h"
#include "NR_EUTRA-MBSFN-SubframeConfig.h"
#include "uper_decoder.h"
#include "uper_encoder.h"
#include "RRC/NR/MESSAGES/asn1_msg.h"
#include "RRC/NR/nr_rrc_extern.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp.h"
#include "nfapi/oai_integration/vendor_ext.h"
extern uint16_t sf_ahead;
int macrlc_has_f1 = 0;
// synchronization raster per band tables (Rel.15)
// (38.101-1 Table 5.4.3.3-1 and 38.101-2 Table 5.4.3.3-1)
// band nb, sub-carrier spacing index, Range of gscn (First, Step size, Last)
const sync_raster_t sync_raster[] = {
{1, 0, 5279, 1, 5419},
{2, 0, 4829, 1, 4969},
{3, 0, 4517, 1, 4693},
{5, 0, 2177, 1, 2230},
{5, 1, 2183, 1, 2224},
{7, 0, 6554, 1, 6718},
{8, 0, 2318, 1, 2395},
{12, 0, 1828, 1, 1858},
{20, 0, 1982, 1, 2047},
{25, 0, 4829, 1, 4981},
{28, 0, 1901, 1, 2002},
{34, 0, 5030, 1, 5056},
{38, 0, 6431, 1, 6544},
{39, 0, 4706, 1, 4795},
{40, 1, 5762, 1, 5989},
{41, 0, 6246, 3, 6717},
{41, 1, 6252, 3, 6714},
{48, 1, 7884, 1, 7982},
{50, 0, 3584, 1, 3787},
{51, 0, 3572, 1, 3574},
{66, 0, 5279, 1, 5494},
{66, 1, 5285, 1, 5488},
{70, 0, 4993, 1, 5044},
{71, 0, 1547, 1, 1624},
{74, 0, 3692, 1, 3790},
{75, 0, 3584, 1, 3787},
{76, 0, 3572, 1, 3574},
{77, 1, 7711, 1, 8329},
{78, 1, 7711, 1, 8051},
{79, 1, 8480, 16, 8880},
{257, 3, 22388, 1, 22558},
{257, 4, 22390, 2, 22556},
{258, 3, 22257, 1, 22443},
{258, 4, 22258, 2, 22442},
{260, 3, 22995, 1, 23166},
{260, 4, 22996, 2, 23164},
{261, 3, 22446, 1, 22492},
{261, 4, 22446, 2, 22490},
};
extern int config_check_band_frequencies(int ind, int16_t band, uint64_t downlink_frequency,
int32_t uplink_frequency_offset, uint32_t frame_type);
void prepare_scc(NR_ServingCellConfigCommon_t *scc) {
NR_FreqBandIndicatorNR_t *dl_frequencyBandList,*ul_frequencyBandList;
struct NR_SCS_SpecificCarrier *dl_scs_SpecificCarrierList,*ul_scs_SpecificCarrierList;
// struct NR_RateMatchPattern *ratematchpattern;
// NR_RateMatchPatternId_t *ratematchpatternid;
// NR_TCI_StateId_t *TCI_StateId;
// struct NR_ControlResourceSet *bwp_dl_controlresourceset;
// NR_SearchSpace_t *bwp_dl_searchspace;
scc->physCellId = CALLOC(1,sizeof(NR_PhysCellId_t));
scc->downlinkConfigCommon = CALLOC(1,sizeof(struct NR_DownlinkConfigCommon));
scc->downlinkConfigCommon->frequencyInfoDL = CALLOC(1,sizeof(struct NR_FrequencyInfoDL));
scc->downlinkConfigCommon->initialDownlinkBWP = CALLOC(1,sizeof(struct NR_BWP_DownlinkCommon));
scc->uplinkConfigCommon = CALLOC(1,sizeof(struct NR_UplinkConfigCommon));
scc->uplinkConfigCommon->frequencyInfoUL = CALLOC(1,sizeof(struct NR_FrequencyInfoUL));
scc->uplinkConfigCommon->initialUplinkBWP = CALLOC(1,sizeof(struct NR_BWP_UplinkCommon));
//scc->supplementaryUplinkConfig = CALLOC(1,sizeof(struct NR_UplinkConfigCommon));
scc->ssb_PositionsInBurst = CALLOC(1,sizeof(struct NR_ServingCellConfigCommon__ssb_PositionsInBurst));
scc->ssb_periodicityServingCell = CALLOC(1,sizeof(long));
// scc->rateMatchPatternToAddModList = CALLOC(1,sizeof(struct NR_ServingCellConfigCommon__rateMatchPatternToAddModList));
// scc->rateMatchPatternToReleaseList = CALLOC(1,sizeof(struct NR_ServingCellConfigCommon__rateMatchPatternToReleaseList));
scc->ssbSubcarrierSpacing = CALLOC(1,sizeof(NR_SubcarrierSpacing_t));
scc->tdd_UL_DL_ConfigurationCommon = CALLOC(1,sizeof(struct NR_TDD_UL_DL_ConfigCommon));
scc->tdd_UL_DL_ConfigurationCommon->pattern2 = CALLOC(1,sizeof(struct NR_TDD_UL_DL_Pattern));
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB = CALLOC(1,sizeof(NR_ARFCN_ValueNR_t));
dl_frequencyBandList = CALLOC(1,sizeof(NR_FreqBandIndicatorNR_t));
dl_scs_SpecificCarrierList = CALLOC(1,sizeof(struct NR_SCS_SpecificCarrier));
asn1cSeqAdd(&scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list,dl_frequencyBandList);
asn1cSeqAdd(&scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list,dl_scs_SpecificCarrierList);
// scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.cyclicPrefix = CALLOC(1,sizeof(long));
scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon = CALLOC(1,sizeof(struct NR_SetupRelease_PDCCH_ConfigCommon));
scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->present=NR_SetupRelease_PDCCH_ConfigCommon_PR_setup;
scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_PDCCH_ConfigCommon));
scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero = CALLOC(1,sizeof(long));
scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero = CALLOC(1,sizeof(long));
scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonControlResourceSet = NULL;
// scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList = CALLOC(1,sizeof(struct NR_PDCCH_ConfigCommon__commonSearchSpaceList));
// scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1 = CALLOC(1,sizeof(NR_SearchSpaceId_t));
// scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation = CALLOC(1,sizeof(NR_SearchSpaceId_t));
// scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->pagingSearchSpace = CALLOC(1,sizeof(NR_SearchSpaceId_t));
// scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->ra_SearchSpace = CALLOC(1,sizeof(NR_SearchSpaceId_t));
scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon = CALLOC(1,sizeof(struct NR_SetupRelease_PDSCH_ConfigCommon));
scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->present = NR_SetupRelease_PDSCH_ConfigCommon_PR_setup;
scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_PDSCH_ConfigCommon));
scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList = CALLOC(1,sizeof(struct NR_PDSCH_TimeDomainResourceAllocationList));
ul_frequencyBandList = CALLOC(1,sizeof(NR_FreqBandIndicatorNR_t));
scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList = CALLOC(1,sizeof(struct NR_MultiFrequencyBandListNR));
asn1cSeqAdd(&scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list,ul_frequencyBandList);
scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA = CALLOC(1,sizeof(NR_ARFCN_ValueNR_t));
// scc->uplinkConfigCommon->frequencyInfoUL->additionalSpectrumEmission = CALLOC(1,sizeof(NR_AdditionalSpectrumEmission_t));
scc->uplinkConfigCommon->frequencyInfoUL->p_Max = CALLOC(1,sizeof(NR_P_Max_t));
// scc->uplinkConfigCommon->frequencyInfoUL->frequencyShift7p5khz = CALLOC(1,sizeof(long));
// scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.cyclicPrefix = CALLOC(1,sizeof(long));
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon = CALLOC(1,sizeof(NR_SetupRelease_RACH_ConfigCommon_t));
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->present = NR_SetupRelease_RACH_ConfigCommon_PR_setup;
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_RACH_ConfigCommon));
// scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles = CALLOC(1,sizeof(long));
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB = CALLOC(1,sizeof(struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB));
// scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->groupBconfigured = CALLOC(1,sizeof(struct NR_RACH_ConfigCommon__groupBconfigured));
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rsrp_ThresholdSSB = CALLOC(1,sizeof(NR_RSRP_Range_t));
// scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rsrp_ThresholdSSB_SUL = CALLOC(1,sizeof(NR_RSRP_Range_t));
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing = CALLOC(1,sizeof(NR_SubcarrierSpacing_t));
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder = CALLOC(1,sizeof(long));
// 0 - ENABLE, 1 - DISABLE, hence explicitly setting to DISABLED.
*scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder = NR_PUSCH_Config__transformPrecoder_disabled;
scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon = CALLOC(1,sizeof(NR_SetupRelease_PUSCH_ConfigCommon_t));
scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->present = NR_SetupRelease_PUSCH_ConfigCommon_PR_setup;
scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_PUSCH_ConfigCommon));
scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->groupHoppingEnabledTransformPrecoding = NULL;
scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocationList));
scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble = CALLOC(1,sizeof(long));
scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->p0_NominalWithGrant = CALLOC(1,sizeof(long));
scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon = CALLOC(1,sizeof(struct NR_SetupRelease_PUCCH_ConfigCommon));
scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->present= NR_SetupRelease_PUCCH_ConfigCommon_PR_setup;
scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup = CALLOC(1,sizeof(struct NR_PUCCH_ConfigCommon));
scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->p0_nominal = CALLOC(1,sizeof(long));
scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon = CALLOC(1,sizeof(long));
scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->hoppingId = CALLOC(1,sizeof(long));
// scc->ssb_PositionsInBurst->choice.shortBitmap.buf = MALLOC(1);
// scc->ssb_PositionsInBurst->choice.mediumBitmap.buf = MALLOC(1);
// scc->ssb_PositionsInBurst->choice.longBitmap.buf = MALLOC(8);
ul_scs_SpecificCarrierList = CALLOC(1,sizeof(struct NR_SCS_SpecificCarrier));
asn1cSeqAdd(&scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list,ul_scs_SpecificCarrierList);
//ratematchpattern = CALLOC(1,sizeof(struct NR_RateMatchPattern));
//ratematchpattern->patternType.choice.bitmaps = CALLOC(1,sizeof(struct NR_RateMatchPattern__patternType__bitmaps));
//ratematchpattern->patternType.choice.bitmaps->resourceBlocks.buf = MALLOC(35);
//ratematchpattern->patternType.choice.bitmaps->symbolsInResourceBlock.choice.oneSlot.buf = MALLOC(2);
//ratematchpattern->patternType.choice.bitmaps->symbolsInResourceBlock.choice.twoSlots.buf = MALLOC(4);
//ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern = CALLOC(1,sizeof(struct NR_RateMatchPattern__patternType__bitmaps__periodicityAndPattern));
//ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern->choice.n2.buf = MALLOC(1);
//ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern->choice.n4.buf = MALLOC(1);
//ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern->choice.n5.buf = MALLOC(1);
//ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern->choice.n8.buf = MALLOC(1);
//ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern->choice.n10.buf = MALLOC(2);
//ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern->choice.n20.buf = MALLOC(3);
//ratematchpattern->patternType.choice.bitmaps->periodicityAndPattern->choice.n40.buf = MALLOC(5);
//ratematchpattern->subcarrierSpacing = CALLOC(1,sizeof(NR_SubcarrierSpacing_t));
//ratematchpatternid = CALLOC(1,sizeof(NR_RateMatchPatternId_t));
}
void fill_scc_sim(NR_ServingCellConfigCommon_t *scc,uint64_t *ssb_bitmap,int N_RB_DL,int N_RB_UL,int mu_dl,int mu_ul) {
*scc->physCellId=0; \
// *scc->n_TimingAdvanceOffset=NR_ServingCellConfigCommon__n_TimingAdvanceOffset_n0;
*scc->ssb_periodicityServingCell=NR_ServingCellConfigCommon__ssb_periodicityServingCell_ms20;
scc->dmrs_TypeA_Position=NR_ServingCellConfigCommon__dmrs_TypeA_Position_pos2;
*scc->ssbSubcarrierSpacing=mu_dl;
if (mu_dl == 0) {
*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB=520432;
*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]=38;
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA=520000;
} else {
*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB=641032;
*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]=78;
scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA=640000;
}
scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier=0;
scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing=mu_dl;
scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth=N_RB_DL;
scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth=275*(N_RB_DL-1);
scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing=mu_dl;//NR_SubcarrierSpacing_kHz30;
*scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->controlResourceSetZero=12;
*scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceZero=0;
struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation0 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t));
timedomainresourceallocation0->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA;
timedomainresourceallocation0->startSymbolAndLength=54;
asn1cSeqAdd(&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list,
timedomainresourceallocation0);
struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation1 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t));
timedomainresourceallocation1->mappingType=NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA;
timedomainresourceallocation1->startSymbolAndLength=57;
asn1cSeqAdd(&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list,
timedomainresourceallocation1);
*scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0]=mu_ul?78:38;
*scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA=-1;
scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier=0;
scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing=mu_ul;
scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth=N_RB_UL;
*scc->uplinkConfigCommon->frequencyInfoUL->p_Max=20;
scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth=275*(N_RB_UL-1);
scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing=mu_ul;//NR_SubcarrierSpacing_kHz30;
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex=98;
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM=NR_RACH_ConfigGeneric__msg1_FDM_one;
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FrequencyStart=0;
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig=13;
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleReceivedTargetPower=-118;
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.preambleTransMax=NR_RACH_ConfigGeneric__preambleTransMax_n10;
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.powerRampingStep=NR_RACH_ConfigGeneric__powerRampingStep_dB2;
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow=NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20;
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present=NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one;
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one=NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB__one_n64;
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer=NR_RACH_ConfigCommon__ra_ContentionResolutionTimer_sf64;
*scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rsrp_ThresholdSSB=19;
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.present=NR_RACH_ConfigCommon__prach_RootSequenceIndex_PR_l139;
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->prach_RootSequenceIndex.choice.l139=0;
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig=NR_RACH_ConfigCommon__restrictedSetConfig_unrestrictedSet;
struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation0 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation));
pusch_timedomainresourceallocation0->k2 = CALLOC(1,sizeof(long));
*pusch_timedomainresourceallocation0->k2=6;
pusch_timedomainresourceallocation0->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB;
pusch_timedomainresourceallocation0->startSymbolAndLength=55;
asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation0);
struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation1 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation));
pusch_timedomainresourceallocation1->k2 = CALLOC(1,sizeof(long));
*pusch_timedomainresourceallocation1->k2=6;
pusch_timedomainresourceallocation1->mappingType=NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB;
pusch_timedomainresourceallocation1->startSymbolAndLength=38;
asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation1);
*scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble=1;
*scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->p0_NominalWithGrant=-90;
scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_GroupHopping=NR_PUCCH_ConfigCommon__pucch_GroupHopping_neither;
*scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->hoppingId=40;
*scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->p0_nominal=-90;
scc->ssb_PositionsInBurst->present=NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap;
*ssb_bitmap=0xff;
scc->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing=mu_dl;
if (mu_dl == 0)
scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity=NR_TDD_UL_DL_Pattern__dl_UL_TransmissionPeriodicity_ms10;
else
scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity=NR_TDD_UL_DL_Pattern__dl_UL_TransmissionPeriodicity_ms5;
scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots=7;
scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols=6;
scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots=2;
scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols=4;
scc->tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity=321;
scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots=-1;
scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols=-1;
scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSlots=-1;
scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSymbols=-1;
scc->ss_PBCH_BlockPower=20;
*scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing=-1;
}
void fix_scc(NR_ServingCellConfigCommon_t *scc,uint64_t ssbmap) {
int ssbmaplen = (int)scc->ssb_PositionsInBurst->present;
uint8_t curr_bit;
AssertFatal(ssbmaplen==NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap ||
ssbmaplen==NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap ||
ssbmaplen==NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap, "illegal ssbmaplen %d\n",ssbmaplen);
// changing endianicity of ssbmap and filling the ssb_PositionsInBurst buffers
if(ssbmaplen==NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap){
scc->ssb_PositionsInBurst->choice.shortBitmap.size = 1;
scc->ssb_PositionsInBurst->choice.shortBitmap.bits_unused = 4;
scc->ssb_PositionsInBurst->choice.shortBitmap.buf = CALLOC(1,1);
scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0] = 0;
for (int i=0; i<8; i++) {
if (i<scc->ssb_PositionsInBurst->choice.shortBitmap.bits_unused)
curr_bit = 0;
else
curr_bit = (ssbmap>>(7-i))&0x01;
scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0] |= curr_bit<<i;
}
}else if(ssbmaplen==NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap){
scc->ssb_PositionsInBurst->choice.mediumBitmap.size = 1;
scc->ssb_PositionsInBurst->choice.mediumBitmap.bits_unused = 0;
scc->ssb_PositionsInBurst->choice.mediumBitmap.buf = CALLOC(1,1);
scc->ssb_PositionsInBurst->choice.mediumBitmap.buf[0] = 0;
for (int i=0; i<8; i++)
scc->ssb_PositionsInBurst->choice.mediumBitmap.buf[0] |= (((ssbmap>>(7-i))&0x01)<<i);
}else {
scc->ssb_PositionsInBurst->choice.longBitmap.size = 8;
scc->ssb_PositionsInBurst->choice.longBitmap.bits_unused = 0;
scc->ssb_PositionsInBurst->choice.longBitmap.buf = CALLOC(1,8);
for (int j=0; j<8; j++) {
scc->ssb_PositionsInBurst->choice.longBitmap.buf[j] = 0;
curr_bit = (ssbmap>>(j<<3))&(0xff);
for (int i=0; i<8; i++)
scc->ssb_PositionsInBurst->choice.longBitmap.buf[j] |= (((curr_bit>>(7-i))&0x01)<<i);
}
}
// fix SS0 and Coreset0
NR_PDCCH_ConfigCommon_t *pdcch_cc = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup;
if((int)*pdcch_cc->searchSpaceZero == -1) {
free(pdcch_cc->searchSpaceZero);
pdcch_cc->searchSpaceZero = NULL;
}
if((int)*pdcch_cc->controlResourceSetZero == -1) {
free(pdcch_cc->controlResourceSetZero);
pdcch_cc->controlResourceSetZero = NULL;
}
// fix UL absolute frequency
if ((int)*scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA==-1) {
free(scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA);
scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA = NULL;
}
// default value for msg3 precoder is NULL (0 means enabled)
if (*scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder!=0)
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder = NULL;
frame_type_t frame_type = get_frame_type((int)*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing);
// prepare DL Allocation lists
nr_rrc_config_dl_tda(scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList,
frame_type, scc->tdd_UL_DL_ConfigurationCommon,
scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth);
if (frame_type == FDD) {
ASN_STRUCT_FREE(asn_DEF_NR_TDD_UL_DL_ConfigCommon, scc->tdd_UL_DL_ConfigurationCommon);
scc->tdd_UL_DL_ConfigurationCommon = NULL;
} else { // TDD
if (scc->tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity > 320 ) {
free(scc->tdd_UL_DL_ConfigurationCommon->pattern2);
scc->tdd_UL_DL_ConfigurationCommon->pattern2 = NULL;
}
}
if ((int)*scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing == -1) {
free(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing);
scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing=NULL;
}
// check pucch_ResourceConfig
AssertFatal(*scc->uplinkConfigCommon->initialUplinkBWP->pucch_ConfigCommon->choice.setup->pucch_ResourceCommon < 2,
"pucch_ResourceConfig should be 0 or 1 for now\n");
}
/* Function to allocate dedicated serving cell config strutures */
void prepare_scd(NR_ServingCellConfig_t *scd) {
// Allocate downlink structures
scd->downlinkBWP_ToAddModList = CALLOC(1, sizeof(*scd->downlinkBWP_ToAddModList));
scd->uplinkConfig = CALLOC(1, sizeof(*scd->uplinkConfig));
scd->uplinkConfig->uplinkBWP_ToAddModList = CALLOC(1, sizeof(*scd->uplinkConfig->uplinkBWP_ToAddModList));
scd->bwp_InactivityTimer = CALLOC(1, sizeof(*scd->bwp_InactivityTimer));
scd->uplinkConfig->firstActiveUplinkBWP_Id = CALLOC(1, sizeof(*scd->uplinkConfig->firstActiveUplinkBWP_Id));
scd->firstActiveDownlinkBWP_Id = CALLOC(1, sizeof(*scd->firstActiveDownlinkBWP_Id));
*scd->firstActiveDownlinkBWP_Id = 1;
*scd->uplinkConfig->firstActiveUplinkBWP_Id = 1;
scd->defaultDownlinkBWP_Id = CALLOC(1, sizeof(*scd->defaultDownlinkBWP_Id));
*scd->defaultDownlinkBWP_Id = 0;
for (int j = 0; j < NR_MAX_NUM_BWP; j++) {
// Downlink bandwidth part
NR_BWP_Downlink_t *bwp = calloc(1, sizeof(*bwp));
bwp->bwp_Id = j+1;
// Allocate downlink dedicated bandwidth part and PDSCH structures
bwp->bwp_Common = calloc(1, sizeof(*bwp->bwp_Common));
bwp->bwp_Common->pdcch_ConfigCommon = calloc(1, sizeof(*bwp->bwp_Common->pdcch_ConfigCommon));
bwp->bwp_Common->pdsch_ConfigCommon = calloc(1, sizeof(*bwp->bwp_Common->pdsch_ConfigCommon));
bwp->bwp_Dedicated = calloc(1, sizeof(*bwp->bwp_Dedicated));
bwp->bwp_Dedicated->pdsch_Config = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config));
bwp->bwp_Dedicated->pdsch_Config->present = NR_SetupRelease_PDSCH_Config_PR_setup;
bwp->bwp_Dedicated->pdsch_Config->choice.setup = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup));
bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA));
bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->present = NR_SetupRelease_DMRS_DownlinkConfig_PR_setup;
// Allocate DL DMRS and PTRS configuration
bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup));
NR_DMRS_DownlinkConfig_t *NR_DMRS_DownlinkCfg = bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup;
NR_DMRS_DownlinkCfg->phaseTrackingRS=CALLOC(1, sizeof(*NR_DMRS_DownlinkCfg->phaseTrackingRS));
NR_DMRS_DownlinkCfg->phaseTrackingRS->present = NR_SetupRelease_PTRS_DownlinkConfig_PR_setup;
NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup = CALLOC(1, sizeof(*NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup));
NR_PTRS_DownlinkConfig_t *NR_PTRS_DownlinkCfg = NR_DMRS_DownlinkCfg->phaseTrackingRS->choice.setup;
NR_PTRS_DownlinkCfg->frequencyDensity = CALLOC(1, sizeof(*NR_PTRS_DownlinkCfg->frequencyDensity));
long *dl_rbs = CALLOC(2, sizeof(long));
for (int i=0;i<2;i++) {
asn1cSeqAdd(&NR_PTRS_DownlinkCfg->frequencyDensity->list, &dl_rbs[i]);
}
NR_PTRS_DownlinkCfg->timeDensity = CALLOC(1, sizeof(*NR_PTRS_DownlinkCfg->timeDensity));
long *dl_mcs = CALLOC(3, sizeof(long));
for (int i=0;i<3;i++) {
asn1cSeqAdd(&NR_PTRS_DownlinkCfg->timeDensity->list, &dl_mcs[i]);
}
NR_PTRS_DownlinkCfg->epre_Ratio = CALLOC(1, sizeof(*NR_PTRS_DownlinkCfg->epre_Ratio));
NR_PTRS_DownlinkCfg->resourceElementOffset = CALLOC(1, sizeof(*NR_PTRS_DownlinkCfg->resourceElementOffset));
*NR_PTRS_DownlinkCfg->resourceElementOffset = 0;
asn1cSeqAdd(&scd->downlinkBWP_ToAddModList->list,bwp);
// Allocate uplink structures
NR_PUSCH_Config_t *pusch_Config = CALLOC(1, sizeof(*pusch_Config));
// Allocate UL DMRS and PTRS structures
pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB = CALLOC(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB));
pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->present = NR_SetupRelease_DMRS_UplinkConfig_PR_setup;
pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup = CALLOC(1, sizeof(*pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup));
NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig = pusch_Config->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup;
NR_DMRS_UplinkConfig->phaseTrackingRS = CALLOC(1, sizeof(*NR_DMRS_UplinkConfig->phaseTrackingRS));
NR_DMRS_UplinkConfig->phaseTrackingRS->present = NR_SetupRelease_PTRS_UplinkConfig_PR_setup;
NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup = CALLOC(1, sizeof(*NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup));
NR_PTRS_UplinkConfig_t *NR_PTRS_UplinkConfig = NR_DMRS_UplinkConfig->phaseTrackingRS->choice.setup;
NR_PTRS_UplinkConfig->transformPrecoderDisabled = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled));
NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity));
long *n_rbs = CALLOC(2, sizeof(long));
for (int i=0;i<2;i++) {
asn1cSeqAdd(&NR_PTRS_UplinkConfig->transformPrecoderDisabled->frequencyDensity->list, &n_rbs[i]);
}
NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity));
long *ptrs_mcs = CALLOC(3, sizeof(long));
for (int i = 0; i < 3; i++) {
asn1cSeqAdd(&NR_PTRS_UplinkConfig->transformPrecoderDisabled->timeDensity->list, &ptrs_mcs[i]);
}
NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset = CALLOC(1, sizeof(*NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset));
*NR_PTRS_UplinkConfig->transformPrecoderDisabled->resourceElementOffset = 0;
// UL bandwidth part
NR_BWP_Uplink_t *ubwp = CALLOC(1, sizeof(*ubwp));
ubwp->bwp_Id = j+1;
ubwp->bwp_Common = CALLOC(1, sizeof(*ubwp->bwp_Common));
ubwp->bwp_Dedicated = CALLOC(1, sizeof(*ubwp->bwp_Dedicated));
ubwp->bwp_Dedicated->pusch_Config = CALLOC(1, sizeof(*ubwp->bwp_Dedicated->pusch_Config));
ubwp->bwp_Dedicated->pusch_Config->present = NR_SetupRelease_PUSCH_Config_PR_setup;
ubwp->bwp_Dedicated->pusch_Config->choice.setup = pusch_Config;
asn1cSeqAdd(&scd->uplinkConfig->uplinkBWP_ToAddModList->list,ubwp);
}
}
/* This function checks dedicated serving cell configuration and performs fixes as needed */
void fix_scd(NR_ServingCellConfig_t *scd) {
// Remove unused BWPs
int b = 0;
while (b<scd->downlinkBWP_ToAddModList->list.count) {
if (scd->downlinkBWP_ToAddModList->list.array[b]->bwp_Common->genericParameters.locationAndBandwidth == 0) {
asn_sequence_del(&scd->downlinkBWP_ToAddModList->list,b,1);
} else {
b++;
}
}
b = 0;
while (b<scd->uplinkConfig->uplinkBWP_ToAddModList->list.count) {
if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[b]->bwp_Common->genericParameters.locationAndBandwidth == 0) {
asn_sequence_del(&scd->uplinkConfig->uplinkBWP_ToAddModList->list,b,1);
} else {
b++;
}
}
// Check for DL PTRS parameters validity
for (int bwp_i = 0 ; bwp_i<scd->downlinkBWP_ToAddModList->list.count; bwp_i++) {
NR_DMRS_DownlinkConfig_t *dmrs_dl_config = scd->downlinkBWP_ToAddModList->list.array[bwp_i]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup;
if (dmrs_dl_config->phaseTrackingRS) {
// If any of the frequencyDensity values are not set or are out of bounds, PTRS is assumed to be not present
for (int i = dmrs_dl_config->phaseTrackingRS->choice.setup->frequencyDensity->list.count - 1; i >= 0; i--) {
if ((*dmrs_dl_config->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] < 1)
|| (*dmrs_dl_config->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] > 276)) {
LOG_I(GNB_APP, "DL PTRS frequencyDensity %d not set. Assuming PTRS not present! \n", i);
free(dmrs_dl_config->phaseTrackingRS);
dmrs_dl_config->phaseTrackingRS = NULL;
break;
}
}
}
if (dmrs_dl_config->phaseTrackingRS) {
// If any of the timeDensity values are not set or are out of bounds, PTRS is assumed to be not present
for (int i = dmrs_dl_config->phaseTrackingRS->choice.setup->timeDensity->list.count - 1; i >= 0; i--) {
if ((*dmrs_dl_config->phaseTrackingRS->choice.setup->timeDensity->list.array[i] < 0)
|| (*dmrs_dl_config->phaseTrackingRS->choice.setup->timeDensity->list.array[i] > 29)) {
LOG_I(GNB_APP, "DL PTRS timeDensity %d not set. Assuming PTRS not present! \n", i);
free(dmrs_dl_config->phaseTrackingRS);
dmrs_dl_config->phaseTrackingRS = NULL;
break;
}
}
}
if (dmrs_dl_config->phaseTrackingRS) {
if (*dmrs_dl_config->phaseTrackingRS->choice.setup->resourceElementOffset > 2) {
LOG_I(GNB_APP, "Freeing DL PTRS resourceElementOffset \n");
free(dmrs_dl_config->phaseTrackingRS->choice.setup->resourceElementOffset);
dmrs_dl_config->phaseTrackingRS->choice.setup->resourceElementOffset = NULL;
}
if (*dmrs_dl_config->phaseTrackingRS->choice.setup->epre_Ratio > 1) {
LOG_I(GNB_APP, "Freeing DL PTRS epre_Ratio \n");
free(dmrs_dl_config->phaseTrackingRS->choice.setup->epre_Ratio);
dmrs_dl_config->phaseTrackingRS->choice.setup->epre_Ratio = NULL;
}
}
}
// Check for UL PTRS parameters validity
for (int bwp_i = 0 ; bwp_i<scd->uplinkConfig->uplinkBWP_ToAddModList->list.count; bwp_i++) {
NR_DMRS_UplinkConfig_t *dmrs_ul_config = scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_i]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup;
if (dmrs_ul_config->phaseTrackingRS) {
// If any of the frequencyDensity values are not set or are out of bounds, PTRS is assumed to be not present
for (int i = dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.count-1; i >= 0; i--) {
if ((*dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[i] < 1)
|| (*dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[i] > 276)) {
LOG_I(GNB_APP, "UL PTRS frequencyDensity %d not set. Assuming PTRS not present! \n", i);
free(dmrs_ul_config->phaseTrackingRS);
dmrs_ul_config->phaseTrackingRS = NULL;
break;
}
}
}
if (dmrs_ul_config->phaseTrackingRS) {
// If any of the timeDensity values are not set or are out of bounds, PTRS is assumed to be not present
for (int i = dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.count-1; i >= 0; i--) {
if ((*dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[i] < 0)
|| (*dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[i] > 29)) {
LOG_I(GNB_APP, "UL PTRS timeDensity %d not set. Assuming PTRS not present! \n", i);
free(dmrs_ul_config->phaseTrackingRS);
dmrs_ul_config->phaseTrackingRS = NULL;
break;
}
}
}
if (dmrs_ul_config->phaseTrackingRS) {
// Check for UL PTRS parameters validity
if (*dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset > 2) {
LOG_I(GNB_APP, "Freeing UL PTRS resourceElementOffset \n");
free(dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset);
dmrs_ul_config->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset = NULL;
}
}
}
}
void RCconfig_nr_prs(void)
{
uint16_t j = 0, k = 0;
prs_config_t *prs_config = NULL;
char str[7][100] = {0};
paramdef_t PRS_Params[] = PRS_PARAMS_DESC;
paramlist_def_t PRS_ParamList = {CONFIG_STRING_PRS_CONFIG,NULL,0};
if (RC.gNB == NULL) {
RC.gNB = (PHY_VARS_gNB **)malloc((1+NUMBER_OF_gNB_MAX)*sizeof(PHY_VARS_gNB*));
LOG_I(NR_PHY,"RC.gNB = %p\n",RC.gNB);
memset(RC.gNB,0,(1+NUMBER_OF_gNB_MAX)*sizeof(PHY_VARS_gNB*));
}
config_getlist( &PRS_ParamList,PRS_Params,sizeof(PRS_Params)/sizeof(paramdef_t), NULL);
if (PRS_ParamList.numelt > 0) {
for (j = 0; j < RC.nb_nr_L1_inst; j++) {
if (RC.gNB[j] == NULL) {
RC.gNB[j] = (PHY_VARS_gNB *)malloc(sizeof(PHY_VARS_gNB));
LOG_I(NR_PHY,"RC.gNB[%d] = %p\n",j,RC.gNB[j]);
memset(RC.gNB[j],0,sizeof(PHY_VARS_gNB));
RC.gNB[j]->Mod_id = j;
}
RC.gNB[j]->prs_vars.NumPRSResources = *(PRS_ParamList.paramarray[j][NUM_PRS_RESOURCES].uptr);
for (k = 0; k < RC.gNB[j]->prs_vars.NumPRSResources; k++)
{
prs_config = &RC.gNB[j]->prs_vars.prs_cfg[k];
prs_config->PRSResourceSetPeriod[0] = PRS_ParamList.paramarray[j][PRS_RESOURCE_SET_PERIOD_LIST].uptr[0];
prs_config->PRSResourceSetPeriod[1] = PRS_ParamList.paramarray[j][PRS_RESOURCE_SET_PERIOD_LIST].uptr[1];
// per PRS resources parameters
prs_config->SymbolStart = PRS_ParamList.paramarray[j][PRS_SYMBOL_START_LIST].uptr[k];
prs_config->NumPRSSymbols = PRS_ParamList.paramarray[j][PRS_NUM_SYMBOLS_LIST].uptr[k];
prs_config->REOffset = PRS_ParamList.paramarray[j][PRS_RE_OFFSET_LIST].uptr[k];
prs_config->PRSResourceOffset = PRS_ParamList.paramarray[j][PRS_RESOURCE_OFFSET_LIST].uptr[k];
prs_config->NPRSID = PRS_ParamList.paramarray[j][PRS_ID_LIST].uptr[k];
// Common parameters to all PRS resources
prs_config->NumRB = *(PRS_ParamList.paramarray[j][PRS_NUM_RB].uptr);
prs_config->RBOffset = *(PRS_ParamList.paramarray[j][PRS_RB_OFFSET].uptr);
prs_config->CombSize = *(PRS_ParamList.paramarray[j][PRS_COMB_SIZE].uptr);
prs_config->PRSResourceRepetition = *(PRS_ParamList.paramarray[j][PRS_RESOURCE_REPETITION].uptr);
prs_config->PRSResourceTimeGap = *(PRS_ParamList.paramarray[j][PRS_RESOURCE_TIME_GAP].uptr);
prs_config->MutingBitRepetition = *(PRS_ParamList.paramarray[j][PRS_MUTING_BIT_REPETITION].uptr);
for (int l = 0; l < PRS_ParamList.paramarray[j][PRS_MUTING_PATTERN1_LIST].numelt; l++)
{
prs_config->MutingPattern1[l] = PRS_ParamList.paramarray[j][PRS_MUTING_PATTERN1_LIST].uptr[l];
if (k == 0) // print only for 0th resource
snprintf(str[5]+strlen(str[5]),sizeof(str[5])-strlen(str[5]),"%d, ",prs_config->MutingPattern1[l]);
}
for (int l = 0; l < PRS_ParamList.paramarray[j][PRS_MUTING_PATTERN2_LIST].numelt; l++)
{
prs_config->MutingPattern2[l] = PRS_ParamList.paramarray[j][PRS_MUTING_PATTERN2_LIST].uptr[l];
if (k == 0) // print only for 0th resource
snprintf(str[6]+strlen(str[6]),sizeof(str[6])-strlen(str[6]),"%d, ",prs_config->MutingPattern2[l]);
}
// print to buffer
snprintf(str[0]+strlen(str[0]),sizeof(str[0])-strlen(str[0]),"%d, ",prs_config->SymbolStart);
snprintf(str[1]+strlen(str[1]),sizeof(str[1])-strlen(str[1]),"%d, ",prs_config->NumPRSSymbols);
snprintf(str[2]+strlen(str[2]),sizeof(str[2])-strlen(str[2]),"%d, ",prs_config->REOffset);
snprintf(str[3]+strlen(str[3]),sizeof(str[3])-strlen(str[3]),"%d, ",prs_config->PRSResourceOffset);
snprintf(str[4]+strlen(str[4]),sizeof(str[4])-strlen(str[4]),"%d, ",prs_config->NPRSID);
} // for k
prs_config = &RC.gNB[j]->prs_vars.prs_cfg[0];
LOG_I(PHY, "-----------------------------------------\n");
LOG_I(PHY, "PRS Config for gNB_id %d @ %p\n", j, prs_config);
LOG_I(PHY, "-----------------------------------------\n");
LOG_I(PHY, "NumPRSResources \t%d\n", RC.gNB[j]->prs_vars.NumPRSResources);
LOG_I(PHY, "PRSResourceSetPeriod \t[%d, %d]\n", prs_config->PRSResourceSetPeriod[0], prs_config->PRSResourceSetPeriod[1]);
LOG_I(PHY, "NumRB \t\t\t%d\n", prs_config->NumRB);
LOG_I(PHY, "RBOffset \t\t%d\n", prs_config->RBOffset);
LOG_I(PHY, "CombSize \t\t%d\n", prs_config->CombSize);
LOG_I(PHY, "PRSResourceRepetition \t%d\n", prs_config->PRSResourceRepetition);
LOG_I(PHY, "PRSResourceTimeGap \t%d\n", prs_config->PRSResourceTimeGap);
LOG_I(PHY, "MutingBitRepetition \t%d\n", prs_config->MutingBitRepetition);
LOG_I(PHY, "SymbolStart \t\t[%s\b\b]\n", str[0]);
LOG_I(PHY, "NumPRSSymbols \t\t[%s\b\b]\n", str[1]);
LOG_I(PHY, "REOffset \t\t[%s\b\b]\n", str[2]);
LOG_I(PHY, "PRSResourceOffset \t[%s\b\b]\n", str[3]);
LOG_I(PHY, "NPRS_ID \t\t[%s\b\b]\n", str[4]);
LOG_I(PHY, "MutingPattern1 \t\t[%s\b\b]\n", str[5]);
LOG_I(PHY, "MutingPattern2 \t\t[%s\b\b]\n", str[6]);
LOG_I(PHY, "-----------------------------------------\n");
} // for j
}
else
{
LOG_I(PHY,"No " CONFIG_STRING_PRS_CONFIG " configuration found..!!\n");
}
}
void RCconfig_NR_L1(void)
{
int j = 0;
if (RC.gNB == NULL) {
RC.gNB = (PHY_VARS_gNB **)malloc((1 + NUMBER_OF_gNB_MAX) * sizeof(PHY_VARS_gNB *));
LOG_I(NR_PHY, "RC.gNB = %p\n", RC.gNB);
memset(RC.gNB, 0, (1 + NUMBER_OF_gNB_MAX) * sizeof(PHY_VARS_gNB *));
if (RC.gNB[j] == NULL) {
RC.gNB[j] = calloc(1, sizeof(PHY_VARS_gNB));
}
}
if (NFAPI_MODE != NFAPI_MODE_PNF) {
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
////////// Identification parameters
paramdef_t GNBParams[] = GNBPARAMS_DESC;
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST, NULL, 0};
config_get(GNBSParams, sizeof(GNBSParams) / sizeof(paramdef_t), NULL);
int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
AssertFatal(num_gnbs > 0, "Failed to parse config file no gnbs %s \n", GNB_CONFIG_STRING_ACTIVE_GNBS);
config_getlist(&GNBParamList, GNBParams, sizeof(GNBParams) / sizeof(paramdef_t), NULL);
int N1 = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_N1_IDX].iptr;
int N2 = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_N2_IDX].iptr;
int XP = *GNBParamList.paramarray[0][GNB_PDSCH_ANTENNAPORTS_XP_IDX].iptr;
char *ulprbbl = *GNBParamList.paramarray[0][GNB_ULPRBBLACKLIST_IDX].strptr;
if (ulprbbl)
LOG_I(NR_PHY, "PRB blacklist %s\n", ulprbbl);
char *save = NULL;
char *pt = strtok_r(ulprbbl, ",", &save);
int prbbl[275];
int num_prbbl = 0;
memset(prbbl, 0, 275 * sizeof(int));
while (pt) {
const int rb = atoi(pt);
AssertFatal(rb < 275, "RB %d out of bounds (max 275)\n", rb);
prbbl[rb] = 0x3FFF; // all symbols taken
LOG_I(NR_PHY, "Blacklisting prb %d\n", atoi(pt));
pt = strtok_r(NULL, ",", &save);
num_prbbl++;
}
RC.gNB[j]->num_ulprbbl = num_prbbl;
LOG_I(NR_PHY, "Copying %d blacklisted PRB to L1 context\n", num_prbbl);
memcpy(RC.gNB[j]->ulprbbl, prbbl, 275 * sizeof(int));
RC.gNB[j]->ap_N1 = N1;
RC.gNB[j]->ap_N2 = N2;
RC.gNB[j]->ap_XP = XP;
}
paramdef_t L1_Params[] = L1PARAMS_DESC;
paramlist_def_t L1_ParamList = {CONFIG_STRING_L1_LIST, NULL, 0};
config_getlist(&L1_ParamList, L1_Params, sizeof(L1_Params) / sizeof(paramdef_t), NULL);
if (L1_ParamList.numelt > 0) {
for (j = 0; j < RC.nb_nr_L1_inst; j++) {
if (RC.gNB[j] == NULL) {
RC.gNB[j] = (PHY_VARS_gNB *)malloc(sizeof(PHY_VARS_gNB));
LOG_I(NR_PHY, "RC.gNB[%d] = %p\n", j, RC.gNB[j]);
memset(RC.gNB[j], 0, sizeof(PHY_VARS_gNB));
RC.gNB[j]->Mod_id = j;
}
AssertFatal(*L1_ParamList.paramarray[j][L1_THREAD_POOL_SIZE].uptr == 2022, "thread_pool_size removed, please use --thread-pool\n");
RC.gNB[j]->ofdm_offset_divisor = *(L1_ParamList.paramarray[j][L1_OFDM_OFFSET_DIVISOR].uptr);
RC.gNB[j]->pucch0_thres = *(L1_ParamList.paramarray[j][L1_PUCCH0_DTX_THRESHOLD].uptr);
RC.gNB[j]->prach_thres = *(L1_ParamList.paramarray[j][L1_PRACH_DTX_THRESHOLD].uptr);
RC.gNB[j]->pusch_thres = *(L1_ParamList.paramarray[j][L1_PUSCH_DTX_THRESHOLD].uptr);
RC.gNB[j]->srs_thres = *(L1_ParamList.paramarray[j][L1_SRS_DTX_THRESHOLD].uptr);
RC.gNB[j]->max_ldpc_iterations = *(L1_ParamList.paramarray[j][L1_MAX_LDPC_ITERATIONS].uptr);
RC.gNB[j]->L1_rx_thread_core = *(L1_ParamList.paramarray[j][L1_RX_THREAD_CORE].iptr);
RC.gNB[j]->L1_tx_thread_core = *(L1_ParamList.paramarray[j][L1_TX_THREAD_CORE].iptr);
LOG_I(PHY,"L1_RX_THREAD_CORE %d (%d)\n",*(L1_ParamList.paramarray[j][L1_RX_THREAD_CORE].iptr),L1_RX_THREAD_CORE);
RC.gNB[j]->TX_AMP = (int16_t)(32767.0 / pow(10.0, .05 * (double)(*L1_ParamList.paramarray[j][L1_TX_AMP_BACKOFF_dB].uptr)));
LOG_I(PHY, "TX_AMP = %d (-%d dBFS)\n", RC.gNB[j]->TX_AMP, *L1_ParamList.paramarray[j][L1_TX_AMP_BACKOFF_dB].uptr);
AssertFatal(RC.gNB[j]->TX_AMP > 300, "TX_AMP is too small, must be larger than 300 (is %d)\n", RC.gNB[j]->TX_AMP);
if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_mac") == 0) {
// sf_ahead = 2; // Need 4 subframe gap between RX and TX
} else if (strcmp(*(L1_ParamList.paramarray[j][L1_TRANSPORT_N_PREFERENCE_IDX].strptr), "nfapi") == 0) {
RC.gNB[j]->eth_params_n.local_if_name = strdup(*(L1_ParamList.paramarray[j][L1_LOCAL_N_IF_NAME_IDX].strptr));
RC.gNB[j]->eth_params_n.my_addr = strdup(*(L1_ParamList.paramarray[j][L1_LOCAL_N_ADDRESS_IDX].strptr));
RC.gNB[j]->eth_params_n.remote_addr = strdup(*(L1_ParamList.paramarray[j][L1_REMOTE_N_ADDRESS_IDX].strptr));
RC.gNB[j]->eth_params_n.my_portc = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTC_IDX].iptr);
RC.gNB[j]->eth_params_n.remote_portc = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTC_IDX].iptr);
RC.gNB[j]->eth_params_n.my_portd = *(L1_ParamList.paramarray[j][L1_LOCAL_N_PORTD_IDX].iptr);
RC.gNB[j]->eth_params_n.remote_portd = *(L1_ParamList.paramarray[j][L1_REMOTE_N_PORTD_IDX].iptr);
RC.gNB[j]->eth_params_n.transp_preference = ETH_UDP_MODE;
// sf_ahead = 2; // Cannot cope with 4 subframes betweem RX and TX - set it to 2
RC.nb_nr_macrlc_inst = 1; // This is used by mac_top_init_gNB()
// This is used by init_gNB_afterRU()
RC.nb_nr_CC = (int *)malloc((1 + RC.nb_nr_inst) * sizeof(int));
RC.nb_nr_CC[0] = 1;
LOG_I(PHY, "%s() NFAPI PNF mode - RC.nb_nr_inst=1 this is because phy_init_RU() uses that to index and not RC.num_gNB - why the 2 similar variables?\n", __FUNCTION__);
LOG_I(PHY, "%s() NFAPI PNF mode - RC.nb_nr_CC[0]=%d for init_gNB_afterRU()\n", __FUNCTION__, RC.nb_nr_CC[0]);
LOG_I(PHY, "%s() NFAPI PNF mode - RC.nb_nr_macrlc_inst:%d because used by mac_top_init_gNB()\n", __FUNCTION__, RC.nb_nr_macrlc_inst);
configure_nr_nfapi_pnf(RC.gNB[j]->eth_params_n.remote_addr,
RC.gNB[j]->eth_params_n.remote_portc,
RC.gNB[j]->eth_params_n.my_addr,
RC.gNB[j]->eth_params_n.my_portd,
RC.gNB[j]->eth_params_n.remote_portd);
} else { // other midhaul
}
} // for (j = 0; j < RC.nb_nr_L1_inst; j++)
printf("Initializing northbound interface for L1\n");
l1_north_init_gNB();
} else {
LOG_I(PHY, "No " CONFIG_STRING_L1_LIST " configuration found");
// need to create some structures for VNF
j = 0;
if (RC.gNB[j] == NULL) {
RC.gNB[j] = (PHY_VARS_gNB *)malloc(sizeof(PHY_VARS_gNB));
memset((void *)RC.gNB[j], 0, sizeof(PHY_VARS_gNB));
LOG_I(PHY, "RC.gNB[%d] = %p\n", j, RC.gNB[j]);
RC.gNB[j]->Mod_id = j;
}
}
}
static void check_ssb_raster(uint64_t freq, int band, int scs);
static NR_ServingCellConfigCommon_t *get_scc_config(int minRXTXTIME)
{
NR_ServingCellConfigCommon_t *scc = calloc(1,sizeof(*scc));
uint64_t ssb_bitmap=0xff;
prepare_scc(scc);
paramdef_t SCCsParams[] = SCCPARAMS_DESC(scc);
paramlist_def_t SCCsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, NULL, 0};
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0);
config_getlist(&SCCsParamList, NULL, 0, aprefix);
if (SCCsParamList.numelt > 0) {
sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, 0);
config_get(SCCsParams,sizeof(SCCsParams) / sizeof(paramdef_t), aprefix);
LOG_I(RRC,
"Read in ServingCellConfigCommon (PhysCellId %d, ABSFREQSSB %d, DLBand %d, ABSFREQPOINTA %d, DLBW "
"%d,RACH_TargetReceivedPower %d\n",
(int)*scc->physCellId,
(int)*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB,
(int)*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0],
(int)scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
(int)scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth,
(int)scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric
.preambleReceivedTargetPower);
// SSB of the PCell is always on the sync raster
uint64_t ssb_freq = from_nrarfcn(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0],
*scc->ssbSubcarrierSpacing,
*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB);
LOG_I(RRC, "absoluteFrequencySSB %ld corresponds to %lu Hz\n",
*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB, ssb_freq);
if (get_softmodem_params()->sa)
check_ssb_raster(ssb_freq,
*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0],
*scc->ssbSubcarrierSpacing);
fix_scc(scc, ssb_bitmap);
}
nr_rrc_config_ul_tda(scc, minRXTXTIME);
return scc;
}
static NR_ServingCellConfig_t *get_scd_config(void)
{
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
NR_ServingCellConfig_t *scd = calloc(1, sizeof(*scd));
prepare_scd(scd);
paramdef_t SCDsParams[] = SCDPARAMS_DESC(scd);
paramlist_def_t SCDsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, NULL, 0};
config_getlist(&SCDsParamList, NULL, 0, aprefix);
if (SCDsParamList.numelt > 0) {
sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, 0);
config_get(SCDsParams, sizeof(SCDsParams) / sizeof(paramdef_t), aprefix);
const NR_BWP_UplinkDedicated_t *bwp_Dedicated = scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated;
const NR_PTRS_UplinkConfig_t *setup =
bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup;
LOG_I(RRC,
"Read in ServingCellConfigDedicated UL (FreqDensity_0 %ld, FreqDensity_1 %ld, TimeDensity_0 %ld, TimeDensity_1 %ld, "
"TimeDensity_2 %ld, RE offset %ld, First_active_BWP_ID %ld SCS %ld, LocationandBW %ld\n",
*setup->transformPrecoderDisabled->frequencyDensity->list.array[0],
*setup->transformPrecoderDisabled->frequencyDensity->list.array[1],
*setup->transformPrecoderDisabled->timeDensity->list.array[0],
*setup->transformPrecoderDisabled->timeDensity->list.array[1],
*setup->transformPrecoderDisabled->timeDensity->list.array[2],
*setup->transformPrecoderDisabled->resourceElementOffset,
*scd->firstActiveDownlinkBWP_Id,
scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Common->genericParameters.subcarrierSpacing,
scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Common->genericParameters.locationAndBandwidth);
}
fix_scd(scd);
return scd;
}
// temporary minRXTXTIME, to be taken out once all radio config is read at DU
static int minRXTXTIME = 6;
static f1ap_setup_req_t *RC_read_F1Setup(const NR_ServingCellConfigCommon_t *scc, NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1);
void RCconfig_nr_macrlc() {
int j = 0;
uint16_t prbbl[275] = {0};
int num_prbbl = 0;
if (NFAPI_MODE != NFAPI_MODE_PNF) {
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
////////// Identification parameters
paramdef_t GNBParams[] = GNBPARAMS_DESC;
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST, NULL, 0};
config_get(GNBSParams, sizeof(GNBSParams) / sizeof(paramdef_t), NULL);
int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
AssertFatal(num_gnbs > 0, "Failed to parse config file no gnbs %s \n", GNB_CONFIG_STRING_ACTIVE_GNBS);
config_getlist(&GNBParamList, GNBParams, sizeof(GNBParams) / sizeof(paramdef_t), NULL);
char *ulprbbl = *GNBParamList.paramarray[0][GNB_ULPRBBLACKLIST_IDX].strptr;
char *save = NULL;
char *pt = strtok_r(ulprbbl, ",", &save);
memset(prbbl, 0, sizeof(prbbl));
while (pt) {
const int prb = atoi(pt);
AssertFatal(prb < 275, "RB %d out of bounds (max 275)\n", prb);
prbbl[prb] = 0x3FFF; // all symbols taken
pt = strtok_r(NULL, ",", &save);
num_prbbl++;
}
}
paramdef_t MacRLC_Params[] = MACRLCPARAMS_DESC;
paramlist_def_t MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST, NULL, 0};
/* map parameter checking array instances to parameter definition array instances */
checkedparam_t config_check_MacRLCParams[] = MACRLCPARAMS_CHECK;
for (int i = 0; i < sizeof(MacRLC_Params) / sizeof(paramdef_t); ++i)
MacRLC_Params[i].chkPptr = &(config_check_MacRLCParams[i]);
config_getlist(&MacRLC_ParamList, MacRLC_Params, sizeof(MacRLC_Params) / sizeof(paramdef_t), NULL);
NR_ServingCellConfigCommon_t *scc = get_scc_config(minRXTXTIME);
//xer_fprint(stdout, &asn_DEF_NR_ServingCellConfigCommon, scc);
NR_ServingCellConfig_t *scd = get_scd_config();
if (MacRLC_ParamList.numelt > 0) {
RC.nb_nr_macrlc_inst = MacRLC_ParamList.numelt;
ngran_node_t node_type = get_node_type();
mac_top_init_gNB(node_type, scc, scd);
RC.nb_nr_mac_CC = (int *)malloc(RC.nb_nr_macrlc_inst * sizeof(int));
for (j = 0; j < RC.nb_nr_macrlc_inst; j++) {
RC.nb_nr_mac_CC[j] = *(MacRLC_ParamList.paramarray[j][MACRLC_CC_IDX].iptr);
RC.nrmac[j]->pusch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCHTARGETSNRX10_IDX].iptr);
RC.nrmac[j]->pucch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHTARGETSNRX10_IDX].iptr);
RC.nrmac[j]->ul_prbblack_SNR_threshold = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_PRBBLACK_SNR_THRESHOLD_IDX].iptr);
RC.nrmac[j]->pucch_failure_thres = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHFAILURETHRES_IDX].iptr);
RC.nrmac[j]->pusch_failure_thres = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCHFAILURETHRES_IDX].iptr);
LOG_I(NR_MAC,
"PUSCH Target %d, PUCCH Target %d, PUCCH Failure %d, PUSCH Failure %d\n",
RC.nrmac[j]->pusch_target_snrx10,
RC.nrmac[j]->pucch_target_snrx10,
RC.nrmac[j]->pucch_failure_thres,
RC.nrmac[j]->pusch_failure_thres);
if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "local_RRC") == 0) {
// check number of instances is same as RRC/PDCP
} else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "f1") == 0) {
printf("Configuring F1 interfaces for MACRLC\n");
RC.nrmac[j]->eth_params_n.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_IF_NAME_IDX].strptr));
RC.nrmac[j]->eth_params_n.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_ADDRESS_IDX].strptr));
RC.nrmac[j]->eth_params_n.remote_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_ADDRESS_IDX].strptr));
RC.nrmac[j]->eth_params_n.my_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTC_IDX].iptr);
RC.nrmac[j]->eth_params_n.remote_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTC_IDX].iptr);
RC.nrmac[j]->eth_params_n.my_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTD_IDX].iptr);
RC.nrmac[j]->eth_params_n.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTD_IDX].iptr);
;
RC.nrmac[j]->eth_params_n.transp_preference = ETH_UDP_MODE;
macrlc_has_f1 = 1;
} else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "cudu") == 0) {
RC.nrmac[j]->eth_params_n.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_IF_NAME_IDX].strptr));
RC.nrmac[j]->eth_params_n.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_ADDRESS_IDX].strptr));
RC.nrmac[j]->eth_params_n.remote_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_ADDRESS_IDX].strptr));
RC.nrmac[j]->eth_params_n.my_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTC_IDX].iptr);
RC.nrmac[j]->eth_params_n.remote_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTC_IDX].iptr);
RC.nrmac[j]->eth_params_n.my_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_N_PORTD_IDX].iptr);
RC.nrmac[j]->eth_params_n.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_N_PORTD_IDX].iptr);
;
RC.nrmac[j]->eth_params_n.transp_preference = ETH_UDP_MODE;
} else { // other midhaul
AssertFatal(1 == 0, "MACRLC %d: %s unknown northbound midhaul\n", j, *(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr));
}
if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr), "local_L1") == 0) {
} else if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr), "nfapi") == 0) {
RC.nrmac[j]->eth_params_s.local_if_name = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_IF_NAME_IDX].strptr));
RC.nrmac[j]->eth_params_s.my_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_ADDRESS_IDX].strptr));
RC.nrmac[j]->eth_params_s.remote_addr = strdup(*(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_ADDRESS_IDX].strptr));
RC.nrmac[j]->eth_params_s.my_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_PORTC_IDX].iptr);
RC.nrmac[j]->eth_params_s.remote_portc = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_PORTC_IDX].iptr);
RC.nrmac[j]->eth_params_s.my_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_LOCAL_S_PORTD_IDX].iptr);
RC.nrmac[j]->eth_params_s.remote_portd = *(MacRLC_ParamList.paramarray[j][MACRLC_REMOTE_S_PORTD_IDX].iptr);
RC.nrmac[j]->eth_params_s.transp_preference = ETH_UDP_MODE;
printf("**************** vnf_port:%d\n", RC.nrmac[j]->eth_params_s.my_portc);
configure_nr_nfapi_vnf(
RC.nrmac[j]->eth_params_s.my_addr, RC.nrmac[j]->eth_params_s.my_portc, RC.nrmac[j]->eth_params_s.remote_addr, RC.nrmac[j]->eth_params_s.remote_portd, RC.nrmac[j]->eth_params_s.my_portd);
printf("**************** RETURNED FROM configure_nfapi_vnf() vnf_port:%d\n", RC.nrmac[j]->eth_params_s.my_portc);
} else { // other midhaul
AssertFatal(1 == 0, "MACRLC %d: %s unknown southbound midhaul\n", j, *(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_S_PREFERENCE_IDX].strptr));
}
RC.nrmac[j]->ulsch_max_frame_inactivity = *(MacRLC_ParamList.paramarray[j][MACRLC_ULSCH_MAX_FRAME_INACTIVITY].uptr);
NR_bler_options_t *dl_bler_options = &RC.nrmac[j]->dl_bler;
dl_bler_options->upper = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_UPPER_IDX].dblptr);
dl_bler_options->lower = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_BLER_TARGET_LOWER_IDX].dblptr);
dl_bler_options->max_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_MAX_MCS_IDX].u8ptr);
dl_bler_options->harq_round_max = *(MacRLC_ParamList.paramarray[j][MACRLC_DL_HARQ_ROUND_MAX_IDX].u8ptr);
NR_bler_options_t *ul_bler_options = &RC.nrmac[j]->ul_bler;
ul_bler_options->upper = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_BLER_TARGET_UPPER_IDX].dblptr);
ul_bler_options->lower = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_BLER_TARGET_LOWER_IDX].dblptr);
ul_bler_options->max_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_MAX_MCS_IDX].u8ptr);
ul_bler_options->harq_round_max = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_HARQ_ROUND_MAX_IDX].u8ptr);
RC.nrmac[j]->min_grant_prb = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_PRB_IDX].u8ptr);
RC.nrmac[j]->min_grant_mcs = *(MacRLC_ParamList.paramarray[j][MACRLC_MIN_GRANT_MCS_IDX].u8ptr);
RC.nrmac[j]->identity_pm = *(MacRLC_ParamList.paramarray[j][MACRLC_IDENTITY_PM_IDX].u8ptr);
RC.nrmac[j]->num_ulprbbl = num_prbbl;
memcpy(RC.nrmac[j]->ulprbbl, prbbl, 275 * sizeof(prbbl[0]));
} // for (j=0;j<RC.nb_nr_macrlc_inst;j++)
// read F1 Setup information from config and generated MIB/SIB1
// and store it at MAC for sending later
NR_BCCH_BCH_Message_t *mib = RC.nrmac[0]->common_channels[0].mib;
const NR_BCCH_DL_SCH_Message_t *sib1 = RC.nrmac[0]->common_channels[0].sib1;
f1ap_setup_req_t *req = RC_read_F1Setup(scc, mib, sib1);
AssertFatal(req != NULL, "could not read F1 Setup information\n");
RC.nrmac[0]->f1_config.setup_req = req;
} else { // MacRLC_ParamList.numelt > 0
LOG_E(PHY, "No %s configuration found\n", CONFIG_STRING_MACRLC_LIST);
// AssertFatal (0,"No " CONFIG_STRING_MACRLC_LIST " configuration found");
}
}
void config_security(gNB_RRC_INST *rrc)
{
paramdef_t sec_params[] = SECURITY_GLOBALPARAMS_DESC;
int ret = config_get(sec_params,
sizeof(sec_params) / sizeof(paramdef_t),
CONFIG_STRING_SECURITY);
int i;
if (ret < 0) {
LOG_W(RRC, "configuration file does not contain a \"security\" section, applying default parameters (nia2 nea0, integrity disabled for DRBs)\n");
rrc->security.ciphering_algorithms[0] = 0; /* nea0 = no ciphering */
rrc->security.ciphering_algorithms_count = 1;
rrc->security.integrity_algorithms[0] = 2; /* nia2 */
rrc->security.integrity_algorithms[1] = 0; /* nia0 = no integrity, as a fallback (but nia2 should be supported by all UEs) */
rrc->security.integrity_algorithms_count = 2;
rrc->security.do_drb_ciphering = 1; /* even if nea0 let's activate so that we don't generate cipheringDisabled in pdcp_Config */
rrc->security.do_drb_integrity = 0;
return;
}
if (sec_params[SECURITY_CONFIG_CIPHERING_IDX].numelt > 4) {
LOG_E(RRC, "too much ciphering algorithms in section \"security\" of the configuration file, maximum is 4\n");
exit(1);
}
if (sec_params[SECURITY_CONFIG_INTEGRITY_IDX].numelt > 4) {
LOG_E(RRC, "too much integrity algorithms in section \"security\" of the configuration file, maximum is 4\n");
exit(1);
}
/* get ciphering algorithms */
rrc->security.ciphering_algorithms_count = 0;
for (i = 0; i < sec_params[SECURITY_CONFIG_CIPHERING_IDX].numelt; i++) {
if (!strcmp(sec_params[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea0")) {
rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 0;
rrc->security.ciphering_algorithms_count++;
continue;
}
if (!strcmp(sec_params[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea1")) {
rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 1;
rrc->security.ciphering_algorithms_count++;
continue;
}
if (!strcmp(sec_params[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea2")) {
rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 2;
rrc->security.ciphering_algorithms_count++;
continue;
}
if (!strcmp(sec_params[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i], "nea3")) {
rrc->security.ciphering_algorithms[rrc->security.ciphering_algorithms_count] = 3;
rrc->security.ciphering_algorithms_count++;
continue;
}
LOG_E(RRC, "unknown ciphering algorithm \"%s\" in section \"security\" of the configuration file\n",
sec_params[SECURITY_CONFIG_CIPHERING_IDX].strlistptr[i]);
exit(1);
}
/* get integrity algorithms */
rrc->security.integrity_algorithms_count = 0;
for (i = 0; i < sec_params[SECURITY_CONFIG_INTEGRITY_IDX].numelt; i++) {
if (!strcmp(sec_params[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia0")) {
rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 0;
rrc->security.integrity_algorithms_count++;
continue;
}
if (!strcmp(sec_params[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia1")) {
rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 1;
rrc->security.integrity_algorithms_count++;
continue;
}
if (!strcmp(sec_params[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia2")) {
rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 2;
rrc->security.integrity_algorithms_count++;
continue;
}
if (!strcmp(sec_params[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i], "nia3")) {
rrc->security.integrity_algorithms[rrc->security.integrity_algorithms_count] = 3;
rrc->security.integrity_algorithms_count++;
continue;
}
LOG_E(RRC, "unknown integrity algorithm \"%s\" in section \"security\" of the configuration file\n",
sec_params[SECURITY_CONFIG_INTEGRITY_IDX].strlistptr[i]);
exit(1);
}
if (rrc->security.ciphering_algorithms_count == 0) {
LOG_W(RRC, "no preferred ciphering algorithm set in configuration file, applying default parameters (no security)\n");
rrc->security.ciphering_algorithms[0] = 0; /* nea0 = no ciphering */
rrc->security.ciphering_algorithms_count = 1;
}
if (rrc->security.integrity_algorithms_count == 0) {
LOG_W(RRC, "no preferred integrity algorithm set in configuration file, applying default parameters (nia2)\n");
rrc->security.integrity_algorithms[0] = 2; /* nia2 */
rrc->security.integrity_algorithms[1] = 0; /* nia0 = no integrity */
rrc->security.integrity_algorithms_count = 2;
}
if (!strcmp(*sec_params[SECURITY_CONFIG_DO_DRB_CIPHERING_IDX].strptr, "yes")) {
rrc->security.do_drb_ciphering = 1;
} else if (!strcmp(*sec_params[SECURITY_CONFIG_DO_DRB_CIPHERING_IDX].strptr, "no")) {
rrc->security.do_drb_ciphering = 0;
} else {
LOG_E(RRC, "in configuration file, bad drb_ciphering value '%s', only 'yes' and 'no' allowed\n",
*sec_params[SECURITY_CONFIG_DO_DRB_CIPHERING_IDX].strptr);
exit(1);
}
if (!strcmp(*sec_params[SECURITY_CONFIG_DO_DRB_INTEGRITY_IDX].strptr, "yes")) {
rrc->security.do_drb_integrity = 1;
} else if (!strcmp(*sec_params[SECURITY_CONFIG_DO_DRB_INTEGRITY_IDX].strptr, "no")) {
rrc->security.do_drb_integrity = 0;
} else {
LOG_E(RRC, "in configuration file, bad drb_integrity value '%s', only 'yes' and 'no' allowed\n",
*sec_params[SECURITY_CONFIG_DO_DRB_INTEGRITY_IDX].strptr);
exit(1);
}
}
// Section 5.4.3 of 38.101-1 and -2
static void check_ssb_raster(uint64_t freq, int band, int scs)
{
int start_gscn = 0, step_gscn = 0, end_gscn = 0;
for (int i = 0; i < sizeof(sync_raster) / sizeof(sync_raster_t); i++) {
if (sync_raster[i].band == band &&
sync_raster[i].scs_index == scs) {
start_gscn = sync_raster[i].first_gscn;
step_gscn = sync_raster[i].step_gscn;
end_gscn = sync_raster[i].last_gscn;
break;
}
}
AssertFatal(start_gscn != 0, "Couldn't find band %d with SCS %d\n", band, scs);
int gscn;
if (freq < 3000000000) {
int N = 0;
int M = 0;
for (int k = 0; k < 3; k++) {
M = (k << 1) + 1;
if ((freq - M * 50000) % 1200000 == 0) {
N = (freq - M * 50000) / 1200000;
break;
}
}
AssertFatal(N != 0, "SSB frequency %lu Hz not on the synchronization raster (N * 1200kHz + M * 50 kHz)\n",
freq);
gscn = (3 * N) + (M - 3) / 2;
}
else if (freq < 24250000000) {
AssertFatal((freq - 3000000000) % 1440000 == 0,
"SSB frequency %lu Hz not on the synchronization raster (3000 MHz + N * 1.44 MHz)\n",
freq);
gscn = ((freq - 3000000000) / 1440000) + 7499;
}
else {
AssertFatal((freq - 24250080000) % 17280000 == 0,
"SSB frequency %lu Hz not on the synchronization raster (24250.08 MHz + N * 17.28 MHz)\n",
freq);
gscn = ((freq - 24250080000) / 17280000) + 22256;
}
AssertFatal(gscn >= start_gscn && gscn <= end_gscn,
"GSCN %d corresponding to SSB frequency %lu does not belong to GSCN range for band %d\n",
gscn, freq, band);
int rel_gscn = gscn - start_gscn;
AssertFatal(rel_gscn % step_gscn == 0,
"GSCN %d corresponding to SSB frequency %lu not in accordance with GSCN step for band %d\n",
gscn, freq, band);
}
void RCconfig_NRRRC(gNB_RRC_INST *rrc)
{
int num_gnbs = 0;
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
int32_t gnb_id = 0;
int k = 0;
int i = 0;
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
////////// Identification parameters
paramdef_t GNBParams[] = GNBPARAMS_DESC;
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0};
////////// Physical parameters
/* get global parameters, defined outside any section in the config file */
config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL);
num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
AssertFatal (i<num_gnbs,"Failed to parse config file no %uth element in %s \n",i, GNB_CONFIG_STRING_ACTIVE_GNBS);
AssertFatal(num_gnbs == 1, "required section \"gNBs\" not in config!\n");
if (num_gnbs > 0) {
// Output a list of all gNBs. ////////// Identification parameters
config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL);
if (GNBParamList.paramarray[i][GNB_GNB_ID_IDX].uptr == NULL) {
// Calculate a default gNB ID
if (get_softmodem_params()->sa) {
uint32_t hash;
hash = ngap_generate_gNB_id ();
gnb_id = i + (hash & 0xFFFFFF8);
} else {
gnb_id = i;
}
} else {
gnb_id = *(GNBParamList.paramarray[i][GNB_GNB_ID_IDX].uptr);
}
sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0);
printf("NRRRC %u: Southbound Transport %s\n",i,*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr));
rrc->node_type = get_node_type();
if (NODE_IS_CU(rrc->node_type)) {
paramdef_t SCTPParams[] = GNBSCTPPARAMS_DESC;
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
sprintf(aprefix,"%s.[%u].%s",GNB_CONFIG_STRING_GNB_LIST,i,GNB_CONFIG_STRING_SCTP_CONFIG);
config_get(SCTPParams,sizeof(SCTPParams)/sizeof(paramdef_t),aprefix);
rrc->node_id = *(GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr);
LOG_I(GNB_APP,"F1AP: gNB_CU_id[%d] %d\n",k,rrc->node_id);
rrc->node_name = strdup(*(GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr));
LOG_I(GNB_APP,"F1AP: gNB_CU_name[%d] %s\n",k,rrc->node_name);
rrc->eth_params_s.local_if_name = strdup(*(GNBParamList.paramarray[i][GNB_LOCAL_S_IF_NAME_IDX].strptr));
rrc->eth_params_s.my_addr = strdup(*(GNBParamList.paramarray[i][GNB_LOCAL_S_ADDRESS_IDX].strptr));
rrc->eth_params_s.remote_addr = strdup(*(GNBParamList.paramarray[i][GNB_REMOTE_S_ADDRESS_IDX].strptr));
rrc->eth_params_s.my_portc = *(GNBParamList.paramarray[i][GNB_LOCAL_S_PORTC_IDX].uptr);
rrc->eth_params_s.remote_portc = *(GNBParamList.paramarray[i][GNB_REMOTE_S_PORTC_IDX].uptr);
rrc->eth_params_s.my_portd = *(GNBParamList.paramarray[i][GNB_LOCAL_S_PORTD_IDX].uptr);
rrc->eth_params_s.remote_portd = *(GNBParamList.paramarray[i][GNB_REMOTE_S_PORTD_IDX].uptr);
rrc->eth_params_s.transp_preference = ETH_UDP_MODE;
}
rrc->nr_cellid = (uint64_t)*(GNBParamList.paramarray[i][GNB_NRCELLID_IDX].u64ptr);
rrc->um_on_default_drb = *(GNBParamList.paramarray[i][GNB_UMONDEFAULTDRB_IDX].uptr);
if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "local_mac") == 0) {
} else if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "cudu") == 0) {
rrc->eth_params_s.local_if_name = strdup(*(GNBParamList.paramarray[i][GNB_LOCAL_S_IF_NAME_IDX].strptr));
rrc->eth_params_s.my_addr = strdup(*(GNBParamList.paramarray[i][GNB_LOCAL_S_ADDRESS_IDX].strptr));
rrc->eth_params_s.remote_addr = strdup(*(GNBParamList.paramarray[i][GNB_REMOTE_S_ADDRESS_IDX].strptr));
rrc->eth_params_s.my_portc = *(GNBParamList.paramarray[i][GNB_LOCAL_S_PORTC_IDX].uptr);
rrc->eth_params_s.remote_portc = *(GNBParamList.paramarray[i][GNB_REMOTE_S_PORTC_IDX].uptr);
rrc->eth_params_s.my_portd = *(GNBParamList.paramarray[i][GNB_LOCAL_S_PORTD_IDX].uptr);
rrc->eth_params_s.remote_portd = *(GNBParamList.paramarray[i][GNB_REMOTE_S_PORTD_IDX].uptr);
rrc->eth_params_s.transp_preference = ETH_UDP_MODE;
} else { // other midhaul
}
// search if in active list
gNB_RrcConfigurationReq nrrrc_config = {0};
for (k=0; k <num_gnbs ; k++) {
if (strcmp(GNBSParams[GNB_ACTIVE_GNBS_IDX].strlistptr[k], *(GNBParamList.paramarray[i][GNB_GNB_NAME_IDX].strptr) )== 0) {
char gnbpath[MAX_OPTNAME_SIZE + 8];
sprintf(gnbpath,"%s.[%i]",GNB_CONFIG_STRING_GNB_LIST,k);
paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
/* map parameter checking array instances to parameter definition array instances */
checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;
for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I)
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
nrrrc_config.cell_identity = gnb_id;
nrrrc_config.tac = *GNBParamList.paramarray[i][GNB_TRACKING_AREA_CODE_IDX].uptr;
AssertFatal(!GNBParamList.paramarray[i][GNB_MOBILE_COUNTRY_CODE_IDX_OLD].strptr
&& !GNBParamList.paramarray[i][GNB_MOBILE_NETWORK_CODE_IDX_OLD].strptr,
"It seems that you use an old configuration file. Please change the existing\n"
" tracking_area_code = \"1\";\n"
" mobile_country_code = \"208\";\n"
" mobile_network_code = \"93\";\n"
"to\n"
" tracking_area_code = 1; // no string!!\n"
" plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } )\n");
config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), gnbpath);
if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6)
AssertFatal(0, "The number of PLMN IDs must be in [1,6], but is %d\n",
PLMNParamList.numelt);
nrrrc_config.num_plmn = PLMNParamList.numelt;
for (int l = 0; l < PLMNParamList.numelt; ++l) {
nrrrc_config.mcc[l] = *PLMNParamList.paramarray[l][GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
nrrrc_config.mnc[l] = *PLMNParamList.paramarray[l][GNB_MOBILE_NETWORK_CODE_IDX].uptr;
nrrrc_config.mnc_digit_length[l] = *PLMNParamList.paramarray[l][GNB_MNC_DIGIT_LENGTH].u8ptr;
AssertFatal((nrrrc_config.mnc_digit_length[l] == 2) ||
(nrrrc_config.mnc_digit_length[l] == 3),"BAD MNC DIGIT LENGTH %d",
nrrrc_config.mnc_digit_length[l]);
}
LOG_I(GNB_APP,"pdsch_AntennaPorts N1 %d\n",*GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_N1_IDX].iptr);
nrrrc_config.pdsch_AntennaPorts.N1 = *GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_N1_IDX].iptr;
LOG_I(GNB_APP,"pdsch_AntennaPorts N2 %d\n",*GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_N2_IDX].iptr);
nrrrc_config.pdsch_AntennaPorts.N2 = *GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_N2_IDX].iptr;
LOG_I(GNB_APP,"pdsch_AntennaPorts XP %d\n",*GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_XP_IDX].iptr);
nrrrc_config.pdsch_AntennaPorts.XP = *GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_XP_IDX].iptr;
LOG_I(GNB_APP,"pusch_AntennaPorts %d\n",*GNBParamList.paramarray[i][GNB_PUSCH_ANTENNAPORTS_IDX].iptr);
nrrrc_config.pusch_AntennaPorts = *GNBParamList.paramarray[i][GNB_PUSCH_ANTENNAPORTS_IDX].iptr;
LOG_I(GNB_APP,"minTXRXTIME %d\n",*GNBParamList.paramarray[i][GNB_MINRXTXTIME_IDX].iptr);
nrrrc_config.minRXTXTIME = *GNBParamList.paramarray[i][GNB_MINRXTXTIME_IDX].iptr;
DevAssert(nrrrc_config.minRXTXTIME == minRXTXTIME);
LOG_I(GNB_APP,"SIB1 TDA %d\n",*GNBParamList.paramarray[i][GNB_SIB1_TDA_IDX].iptr);
nrrrc_config.sib1_tda = *GNBParamList.paramarray[i][GNB_SIB1_TDA_IDX].iptr;
LOG_I(GNB_APP,"Do CSI-RS %d\n",*GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr);
nrrrc_config.do_CSIRS = *GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr;
LOG_I(GNB_APP, "Do SRS %d\n",*GNBParamList.paramarray[i][GNB_DO_SRS_IDX].iptr);
nrrrc_config.do_SRS = *GNBParamList.paramarray[i][GNB_DO_SRS_IDX].iptr;
nrrrc_config.force_256qam_off = *GNBParamList.paramarray[i][GNB_FORCE256QAMOFF_IDX].iptr;
LOG_I(GNB_APP, "256 QAM: %s\n", nrrrc_config.force_256qam_off ? "force off" : "may be on");
nrrrc_config.enable_sdap = *GNBParamList.paramarray[i][GNB_ENABLE_SDAP_IDX].iptr;
LOG_I(GNB_APP, "SDAP layer is %s\n", nrrrc_config.enable_sdap ? "enabled" : "disabled");
nrrrc_config.drbs = *GNBParamList.paramarray[i][GNB_DRBS].iptr;
LOG_I(GNB_APP, "Data Radio Bearer count %d\n", nrrrc_config.drbs);
}//
}//End for (k=0; k <num_gnbs ; k++)
openair_rrc_gNB_configuration(rrc, &nrrrc_config);
}//End if (num_gnbs>0)
config_security(rrc);
}//End RCconfig_NRRRC function
int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i) {
int j,k = 0;
int gnb_id;
int32_t my_int;
const char* active_gnb[MAX_GNB];
char *address = NULL;
char *cidr = NULL;
// for no gcc warnings
(void) my_int;
memset((char*)active_gnb,0,MAX_GNB* sizeof(char*));
char* gnb_ipv4_address_for_NGU = NULL;
uint32_t gnb_port_for_NGU = 0;
char* gnb_ipv4_address_for_S1U = NULL;
uint32_t gnb_port_for_S1U = 0;
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
paramdef_t GNBParams[] = GNBPARAMS_DESC;
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0};
/* get global parameters, defined outside any section in the config file */
config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL);
AssertFatal (i<GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt,
"Failed to parse config file %s, %uth attribute %s \n",
RC.config_file_name, i, GNB_CONFIG_STRING_ACTIVE_GNBS);
if (GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt>0) {
// Output a list of all gNBs.
config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL);
if (GNBParamList.numelt > 0) {
for (k = 0; k < GNBParamList.numelt; k++) {
if (GNBParamList.paramarray[k][GNB_GNB_ID_IDX].uptr == NULL) {
// Calculate a default gNB ID
if (get_softmodem_params()->sa) {
uint32_t hash;
hash = ngap_generate_gNB_id ();
gnb_id = k + (hash & 0xFFFFFF8);
} else {
gnb_id = k;
}
} else {
gnb_id = *(GNBParamList.paramarray[k][GNB_GNB_ID_IDX].uptr);
}
// search if in active list
for (j=0; j < GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; j++) {
if (strcmp(GNBSParams[GNB_ACTIVE_GNBS_IDX].strlistptr[j], *(GNBParamList.paramarray[k][GNB_GNB_NAME_IDX].strptr)) == 0) {
paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
paramdef_t SNSSAIParams[] = GNBSNSSAIPARAMS_DESC;
paramlist_def_t SNSSAIParamList = {GNB_CONFIG_STRING_SNSSAI_LIST, NULL, 0};
/* map parameter checking array instances to parameter definition array instances */
checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;
checkedparam_t config_check_SNSSAIParams [] = SNSSAIPARAMS_CHECK;
for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I)
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
for (int J = 0; J < sizeof(SNSSAIParams) / sizeof(paramdef_t); ++J)
SNSSAIParams[J].chkPptr = &(config_check_SNSSAIParams[J]);
paramdef_t NGParams[] = GNBNGPARAMS_DESC;
paramlist_def_t NGParamList = {GNB_CONFIG_STRING_AMF_IP_ADDRESS,NULL,0};
paramdef_t SCTPParams[] = GNBSCTPPARAMS_DESC;
paramdef_t NETParams[] = GNBNETPARAMS_DESC;
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, k);
NGAP_REGISTER_GNB_REQ (msg_p).gNB_id = gnb_id;
if (strcmp(*(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr), "CELL_MACRO_GNB") == 0) {
NGAP_REGISTER_GNB_REQ (msg_p).cell_type = CELL_MACRO_GNB;
} else if (strcmp(*(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr), "CELL_HOME_GNB") == 0) {
NGAP_REGISTER_GNB_REQ (msg_p).cell_type = CELL_HOME_ENB;
} else {
AssertFatal (0,
"Failed to parse gNB configuration file %s, gnb %u unknown value \"%s\" for cell_type choice: CELL_MACRO_GNB or CELL_HOME_GNB !\n",
RC.config_file_name, i, *(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr));
}
NGAP_REGISTER_GNB_REQ (msg_p).gNB_name = strdup(*(GNBParamList.paramarray[k][GNB_GNB_NAME_IDX].strptr));
NGAP_REGISTER_GNB_REQ (msg_p).tac = *GNBParamList.paramarray[k][GNB_TRACKING_AREA_CODE_IDX].uptr;
AssertFatal(!GNBParamList.paramarray[k][GNB_MOBILE_COUNTRY_CODE_IDX_OLD].strptr
&& !GNBParamList.paramarray[k][GNB_MOBILE_NETWORK_CODE_IDX_OLD].strptr,
"It seems that you use an old configuration file. Please change the existing\n"
" tracking_area_code = \"1\";\n"
" mobile_country_code = \"208\";\n"
" mobile_network_code = \"93\";\n"
"to\n"
" tracking_area_code = 1; // no string!!\n"
" plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } )\n");
config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), aprefix);
if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6)
AssertFatal(0, "The number of PLMN IDs must be in [1,6], but is %d\n",
PLMNParamList.numelt);
NGAP_REGISTER_GNB_REQ(msg_p).num_plmn = PLMNParamList.numelt;
for (int l = 0; l < PLMNParamList.numelt; ++l) {
char snssaistr[MAX_OPTNAME_SIZE*2 + 8];
sprintf(snssaistr, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, k, GNB_CONFIG_STRING_PLMN_LIST, l);
config_getlist(&SNSSAIParamList, SNSSAIParams, sizeof(SNSSAIParams)/sizeof(paramdef_t), snssaistr);
NGAP_REGISTER_GNB_REQ (msg_p).mcc[l] = *PLMNParamList.paramarray[l][GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
NGAP_REGISTER_GNB_REQ (msg_p).mnc[l] = *PLMNParamList.paramarray[l][GNB_MOBILE_NETWORK_CODE_IDX].uptr;
NGAP_REGISTER_GNB_REQ (msg_p).mnc_digit_length[l] = *PLMNParamList.paramarray[l][GNB_MNC_DIGIT_LENGTH].u8ptr;
NGAP_REGISTER_GNB_REQ (msg_p).default_drx = 0;
AssertFatal((NGAP_REGISTER_GNB_REQ (msg_p).mnc_digit_length[l] == 2) ||
(NGAP_REGISTER_GNB_REQ (msg_p).mnc_digit_length[l] == 3),
"BAD MNC DIGIT LENGTH %d",
NGAP_REGISTER_GNB_REQ (msg_p).mnc_digit_length[l]);
NGAP_REGISTER_GNB_REQ (msg_p).num_nssai[l] = SNSSAIParamList.numelt;
for (int s = 0; s < SNSSAIParamList.numelt; ++s) {
NGAP_REGISTER_GNB_REQ (msg_p).s_nssai[l][s].sST = *SNSSAIParamList.paramarray[s][GNB_SLICE_SERVICE_TYPE_IDX].uptr;
NGAP_REGISTER_GNB_REQ (msg_p).s_nssai[l][s].sD_flag = 0;
if(SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr != 0 // SD is optional
&& *SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr != 0xffffff) { // 0xffffff is "no SD", see 23.003 Sec 28.4.2
NGAP_REGISTER_GNB_REQ (msg_p).s_nssai[l][s].sD_flag = 1;
NGAP_REGISTER_GNB_REQ (msg_p).s_nssai[l][s].sD[0] = (*SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr & 0xFF0000) >> 16;
NGAP_REGISTER_GNB_REQ (msg_p).s_nssai[l][s].sD[1] = (*SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr & 0x00FF00) >> 8;
NGAP_REGISTER_GNB_REQ (msg_p).s_nssai[l][s].sD[2] = (*SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr & 0x0000FF);
}
}
}
sprintf(aprefix,"%s.[%i]",GNB_CONFIG_STRING_GNB_LIST,k);
config_getlist( &NGParamList,NGParams,sizeof(NGParams)/sizeof(paramdef_t),aprefix);
NGAP_REGISTER_GNB_REQ (msg_p).nb_amf = 0;
for (int l = 0; l < NGParamList.numelt; l++) {
NGAP_REGISTER_GNB_REQ (msg_p).nb_amf += 1;
strcpy(NGAP_REGISTER_GNB_REQ (msg_p).amf_ip_address[l].ipv4_address,*(NGParamList.paramarray[l][GNB_AMF_IPV4_ADDRESS_IDX].strptr));
strcpy(NGAP_REGISTER_GNB_REQ (msg_p).amf_ip_address[l].ipv6_address,*(NGParamList.paramarray[l][GNB_AMF_IPV6_ADDRESS_IDX].strptr));
if (strcmp(*(NGParamList.paramarray[l][GNB_AMF_IP_ADDRESS_ACTIVE_IDX].strptr), "yes") == 0) {
}
if (strcmp(*(NGParamList.paramarray[l][GNB_AMF_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) {
NGAP_REGISTER_GNB_REQ (msg_p).amf_ip_address[j].ipv4 = 1;
} else if (strcmp(*(NGParamList.paramarray[l][GNB_AMF_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) {
NGAP_REGISTER_GNB_REQ (msg_p).amf_ip_address[j].ipv6 = 1;
} else if (strcmp(*(NGParamList.paramarray[l][GNB_AMF_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) {
NGAP_REGISTER_GNB_REQ (msg_p).amf_ip_address[j].ipv4 = 1;
NGAP_REGISTER_GNB_REQ (msg_p).amf_ip_address[j].ipv6 = 1;
}
/* not in configuration yet ...
if (NGParamList.paramarray[l][GNB_AMF_BROADCAST_PLMN_INDEX].iptr)
NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l] = NGParamList.paramarray[l][GNB_AMF_BROADCAST_PLMN_INDEX].numelt;
else
NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l] = 0;
*/
AssertFatal(NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l] <= NGAP_REGISTER_GNB_REQ(msg_p).num_plmn,
"List of broadcast PLMN to be sent to AMF can not be longer than actual "
"PLMN list (max %d, but is %d)\n",
NGAP_REGISTER_GNB_REQ(msg_p).num_plmn,
NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l]);
for (int el = 0; el < NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l]; ++el) {
/* UINTARRAY gets mapped to int, see config_libconfig.c:223 */
NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_index[l][el] = NGParamList.paramarray[l][GNB_AMF_BROADCAST_PLMN_INDEX].iptr[el];
AssertFatal(NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_index[l][el] >= 0
&& NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_index[l][el] < NGAP_REGISTER_GNB_REQ(msg_p).num_plmn,
"index for AMF's MCC/MNC (%d) is an invalid index for the registered PLMN IDs (%d)\n",
NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_index[l][el],
NGAP_REGISTER_GNB_REQ(msg_p).num_plmn);
}
/* if no broadcasst_plmn array is defined, fill default values */
if (NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l] == 0) {
NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l] = NGAP_REGISTER_GNB_REQ(msg_p).num_plmn;
for (int el = 0; el < NGAP_REGISTER_GNB_REQ(msg_p).num_plmn; ++el)
NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_index[l][el] = el;
}
}
// SCTP SETTING
NGAP_REGISTER_GNB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS;
NGAP_REGISTER_GNB_REQ (msg_p).sctp_in_streams = SCTP_IN_STREAMS;
if (get_softmodem_params()->sa) {
sprintf(aprefix,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,k,GNB_CONFIG_STRING_SCTP_CONFIG);
config_get( SCTPParams,sizeof(SCTPParams)/sizeof(paramdef_t),aprefix);
NGAP_REGISTER_GNB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr);
NGAP_REGISTER_GNB_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr);
}
sprintf(aprefix,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,k,GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
// NETWORK_INTERFACES
config_get( NETParams,sizeof(NETParams)/sizeof(paramdef_t),aprefix);
// NGAP_REGISTER_GNB_REQ (msg_p).enb_interface_name_for_NGU = strdup(enb_interface_name_for_NGU);
cidr = *(NETParams[GNB_IPV4_ADDRESS_FOR_NG_AMF_IDX].strptr);
char *save = NULL;
address = strtok_r(cidr, "/", &save);
NGAP_REGISTER_GNB_REQ (msg_p).gnb_ip_address.ipv6 = 0;
NGAP_REGISTER_GNB_REQ (msg_p).gnb_ip_address.ipv4 = 1;
strcpy(NGAP_REGISTER_GNB_REQ (msg_p).gnb_ip_address.ipv4_address, address);
break;
}
}
}
}
}
return 0;
}
int RCconfig_nr_parallel(void) {
char *parallel_conf = NULL;
char *worker_conf = NULL;
extern char *parallel_config;
extern char *worker_config;
paramdef_t ThreadParams[] = THREAD_CONF_DESC;
paramlist_def_t THREADParamList = {THREAD_CONFIG_STRING_THREAD_STRUCT,NULL,0};
config_getlist( &THREADParamList,NULL,0,NULL);
if(THREADParamList.numelt>0) {
config_getlist( &THREADParamList,ThreadParams,sizeof(ThreadParams)/sizeof(paramdef_t),NULL);
parallel_conf = strdup(*(THREADParamList.paramarray[0][THREAD_PARALLEL_IDX].strptr));
} else {
parallel_conf = strdup("PARALLEL_RU_L1_TRX_SPLIT");
}
if(THREADParamList.numelt>0) {
config_getlist( &THREADParamList,ThreadParams,sizeof(ThreadParams)/sizeof(paramdef_t),NULL);
worker_conf = strdup(*(THREADParamList.paramarray[0][THREAD_WORKER_IDX].strptr));
} else {
worker_conf = strdup("WORKER_ENABLE");
}
if(parallel_config == NULL) set_parallel_conf(parallel_conf);
if(worker_config == NULL) set_worker_conf(worker_conf);
return 0;
}
void NRRCConfig(void) {
paramlist_def_t MACRLCParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0};
paramlist_def_t L1ParamList = {CONFIG_STRING_L1_LIST,NULL,0};
paramlist_def_t RUParamList = {CONFIG_STRING_RU_LIST,NULL,0};
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
/* get global parameters, defined outside any section in the config file */
LOG_I(GNB_APP, "Getting GNBSParams\n");
config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL);
RC.nb_nr_inst = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
// Get num MACRLC instances
config_getlist( &MACRLCParamList,NULL,0, NULL);
RC.nb_nr_macrlc_inst = MACRLCParamList.numelt;
// Get num L1 instances
config_getlist( &L1ParamList,NULL,0, NULL);
RC.nb_nr_L1_inst = L1ParamList.numelt;
// Get num RU instances
config_getlist( &RUParamList,NULL,0, NULL);
RC.nb_RU = RUParamList.numelt;
RCconfig_nr_parallel();
}
int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i) {
int J, l;
char *address = NULL;
char *cidr = NULL;
//int num_gnbs = 0;
//int num_component_carriers = 0;
int j,k = 0;
int32_t gnb_id = 0;
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
////////// Identification parameters
paramdef_t GNBParams[] = GNBPARAMS_DESC;
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0};
/* get global parameters, defined outside any section in the config file */
config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL);
NR_ServingCellConfigCommon_t *scc = calloc(1,sizeof(NR_ServingCellConfigCommon_t));
uint64_t ssb_bitmap=0xff;
memset((void*)scc,0,sizeof(NR_ServingCellConfigCommon_t));
prepare_scc(scc);
paramdef_t SCCsParams[] = SCCPARAMS_DESC(scc);
paramlist_def_t SCCsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, NULL, 0};
AssertFatal(i < GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt,
"Failed to parse config file %s, %uth attribute %s \n",
RC.config_file_name, i, GNB_CONFIG_STRING_ACTIVE_GNBS);
if (GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt > 0) {
// Output a list of all gNBs.
config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL);
if (GNBParamList.numelt > 0) {
for (k = 0; k < GNBParamList.numelt; k++) {
if (GNBParamList.paramarray[k][GNB_GNB_ID_IDX].uptr == NULL) {
// Calculate a default eNB ID
if (get_softmodem_params()->sa) {
uint32_t hash;
hash = ngap_generate_gNB_id ();
gnb_id = k + (hash & 0xFFFFFF8);
} else {
gnb_id = k;
}
} else {
gnb_id = *(GNBParamList.paramarray[k][GNB_GNB_ID_IDX].uptr);
}
// search if in active list
for (j = 0; j < GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; j++) {
if (strcmp(GNBSParams[GNB_ACTIVE_GNBS_IDX].strlistptr[j], *(GNBParamList.paramarray[k][GNB_GNB_NAME_IDX].strptr)) == 0) {
paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
/* map parameter checking array instances to parameter definition array instances */
checkedparam_t config_check_PLMNParams [] = PLMNPARAMS_CHECK;
for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I)
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
paramdef_t X2Params[] = X2PARAMS_DESC;
paramlist_def_t X2ParamList = {ENB_CONFIG_STRING_TARGET_ENB_X2_IP_ADDRESS,NULL,0};
paramdef_t SCTPParams[] = GNBSCTPPARAMS_DESC;
char* gnb_ipv4_address_for_NGU = NULL;
uint32_t gnb_port_for_NGU = 0;
char* gnb_ipv4_address_for_S1U = NULL;
uint32_t gnb_port_for_S1U = 0;
paramdef_t NETParams[] = GNBNETPARAMS_DESC;
/* TODO: fix the size - if set lower we have a crash (MAX_OPTNAME_SIZE was 64 when this code was written) */
/* this is most probably a problem with the config module */
char aprefix[MAX_OPTNAME_SIZE*80 + 8];
sprintf(aprefix,"%s.[%i]",GNB_CONFIG_STRING_GNB_LIST,k);
/* Some default/random parameters */
X2AP_REGISTER_ENB_REQ (msg_p).eNB_id = gnb_id;
if (strcmp(*(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr), "CELL_MACRO_GNB") == 0) {
X2AP_REGISTER_ENB_REQ (msg_p).cell_type = CELL_MACRO_GNB;
}else {
AssertFatal (0,
"Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for cell_type choice: CELL_MACRO_ENB or CELL_HOME_ENB !\n",
RC.config_file_name, i, *(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr));
}
X2AP_REGISTER_ENB_REQ (msg_p).eNB_name = strdup(*(GNBParamList.paramarray[k][GNB_GNB_NAME_IDX].strptr));
X2AP_REGISTER_ENB_REQ (msg_p).tac = *GNBParamList.paramarray[k][GNB_TRACKING_AREA_CODE_IDX].uptr;
config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), aprefix);
if (PLMNParamList.numelt < 1 || PLMNParamList.numelt > 6)
AssertFatal(0, "The number of PLMN IDs must be in [1,6], but is %d\n",
PLMNParamList.numelt);
if (PLMNParamList.numelt > 1)
LOG_W(X2AP, "X2AP currently handles only one PLMN, ignoring the others!\n");
X2AP_REGISTER_ENB_REQ (msg_p).mcc = *PLMNParamList.paramarray[0][GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
X2AP_REGISTER_ENB_REQ (msg_p).mnc = *PLMNParamList.paramarray[0][GNB_MOBILE_NETWORK_CODE_IDX].uptr;
X2AP_REGISTER_ENB_REQ (msg_p).mnc_digit_length = *PLMNParamList.paramarray[0][GNB_MNC_DIGIT_LENGTH].u8ptr;
AssertFatal(X2AP_REGISTER_ENB_REQ(msg_p).mnc_digit_length == 3
|| X2AP_REGISTER_ENB_REQ(msg_p).mnc < 100,
"MNC %d cannot be encoded in two digits as requested (change mnc_digit_length to 3)\n",
X2AP_REGISTER_ENB_REQ(msg_p).mnc);
sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0);
config_getlist(&SCCsParamList, NULL, 0, aprefix);
if (SCCsParamList.numelt > 0) {
sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, 0);
config_get( SCCsParams,sizeof(SCCsParams)/sizeof(paramdef_t),aprefix);
fix_scc(scc,ssb_bitmap);
}
X2AP_REGISTER_ENB_REQ (msg_p).num_cc = SCCsParamList.numelt;
for (J = 0; J < SCCsParamList.numelt ; J++) {
X2AP_REGISTER_ENB_REQ (msg_p).nr_band[J] = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; //nr_band; //78
X2AP_REGISTER_ENB_REQ (msg_p).nrARFCN[J] = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA;
X2AP_REGISTER_ENB_REQ (msg_p).uplink_frequency_offset[J] = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier; //0
X2AP_REGISTER_ENB_REQ (msg_p).Nid_cell[J]= *scc->physCellId; //0
X2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J]= scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;//106
X2AP_REGISTER_ENB_REQ (msg_p).frame_type[J] = TDD;
LOG_I(X2AP, "gNB configuration parameters: nr_band: %d, nr_ARFCN: %d, DL_RBs: %d, num_cc: %d \n",
X2AP_REGISTER_ENB_REQ (msg_p).nr_band[J],
X2AP_REGISTER_ENB_REQ (msg_p).nrARFCN[J],
X2AP_REGISTER_ENB_REQ (msg_p).N_RB_DL[J],
X2AP_REGISTER_ENB_REQ (msg_p).num_cc);
}
sprintf(aprefix,"%s.[%i]",GNB_CONFIG_STRING_GNB_LIST,k);
config_getlist( &X2ParamList,X2Params,sizeof(X2Params)/sizeof(paramdef_t),aprefix);
AssertFatal(X2ParamList.numelt <= X2AP_MAX_NB_ENB_IP_ADDRESS,
"value of X2ParamList.numelt %d must be lower than X2AP_MAX_NB_ENB_IP_ADDRESS %d value: reconsider to increase X2AP_MAX_NB_ENB_IP_ADDRESS\n",
X2ParamList.numelt,X2AP_MAX_NB_ENB_IP_ADDRESS);
X2AP_REGISTER_ENB_REQ (msg_p).nb_x2 = 0;
for (l = 0; l < X2ParamList.numelt; l++) {
X2AP_REGISTER_ENB_REQ (msg_p).nb_x2 += 1;
strcpy(X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4_address,*(X2ParamList.paramarray[l][ENB_X2_IPV4_ADDRESS_IDX].strptr));
strcpy(X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6_address,*(X2ParamList.paramarray[l][ENB_X2_IPV6_ADDRESS_IDX].strptr));
if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv4") == 0) {
X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4 = 1;
X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6 = 0;
} else if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "ipv6") == 0) {
X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4 = 0;
X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6 = 1;
} else if (strcmp(*(X2ParamList.paramarray[l][ENB_X2_IP_ADDRESS_PREFERENCE_IDX].strptr), "no") == 0) {
X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv4 = 1;
X2AP_REGISTER_ENB_REQ (msg_p).target_enb_x2_ip_address[l].ipv6 = 1;
}
}
// timers
{
int t_reloc_prep = 0;
int tx2_reloc_overall = 0;
int t_dc_prep = 0;
int t_dc_overall = 0;
paramdef_t p[] = {
{ "t_reloc_prep", "t_reloc_prep", 0, .iptr=&t_reloc_prep, .defintval=0, TYPE_INT, 0 },
{ "tx2_reloc_overall", "tx2_reloc_overall", 0, .iptr=&tx2_reloc_overall, .defintval=0, TYPE_INT, 0 },
{ "t_dc_prep", "t_dc_prep", 0, .iptr=&t_dc_prep, .defintval=0, TYPE_INT, 0 },
{ "t_dc_overall", "t_dc_overall", 0, .iptr=&t_dc_overall, .defintval=0, TYPE_INT, 0 }
};
config_get(p, sizeof(p)/sizeof(paramdef_t), aprefix);
if (t_reloc_prep <= 0 || t_reloc_prep > 10000 ||
tx2_reloc_overall <= 0 || tx2_reloc_overall > 20000 ||
t_dc_prep <= 0 || t_dc_prep > 10000 ||
t_dc_overall <= 0 || t_dc_overall > 20000) {
LOG_E(X2AP, "timers in configuration file have wrong values. We must have [0 < t_reloc_prep <= 10000] and [0 < tx2_reloc_overall <= 20000] and [0 < t_dc_prep <= 10000] and [0 < t_dc_overall <= 20000]\n");
exit(1);
}
X2AP_REGISTER_ENB_REQ (msg_p).t_reloc_prep = t_reloc_prep;
X2AP_REGISTER_ENB_REQ (msg_p).tx2_reloc_overall = tx2_reloc_overall;
X2AP_REGISTER_ENB_REQ (msg_p).t_dc_prep = t_dc_prep;
X2AP_REGISTER_ENB_REQ (msg_p).t_dc_overall = t_dc_overall;
}
// SCTP SETTING
X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS;
X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = SCTP_IN_STREAMS;
if (get_softmodem_params()->sa) {
sprintf(aprefix,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,k,GNB_CONFIG_STRING_SCTP_CONFIG);
config_get( SCTPParams,sizeof(SCTPParams)/sizeof(paramdef_t),aprefix);
X2AP_REGISTER_ENB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr);
X2AP_REGISTER_ENB_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr);
}
sprintf(aprefix,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,k,GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
// NETWORK_INTERFACES
config_get( NETParams,sizeof(NETParams)/sizeof(paramdef_t),aprefix);
X2AP_REGISTER_ENB_REQ (msg_p).enb_port_for_X2C = (uint32_t)*(NETParams[GNB_PORT_FOR_X2C_IDX].uptr);
//temp out
if ((NETParams[GNB_IPV4_ADDR_FOR_X2C_IDX].strptr == NULL) || (X2AP_REGISTER_ENB_REQ (msg_p).enb_port_for_X2C == 0)) {
LOG_E(RRC,"Add eNB IPv4 address and/or port for X2C in the CONF file!\n");
exit(1);
}
cidr = *(NETParams[ENB_IPV4_ADDR_FOR_X2C_IDX].strptr);
char *save = NULL;
address = strtok_r(cidr, "/", &save);
X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv6 = 0;
X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv4 = 1;
strcpy(X2AP_REGISTER_ENB_REQ (msg_p).enb_x2_ip_address.ipv4_address, address);
}
}
}
}
}
return 0;
}
static f1ap_setup_req_t *RC_read_F1Setup(const NR_ServingCellConfigCommon_t *scc, NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1)
{
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
paramdef_t GNBParams[] = GNBPARAMS_DESC;
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0};
config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL);
int num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
AssertFatal(num_gnbs == 1, "cannot configure DU: required config section \"gNBs\" missing\n");
// Output a list of all eNBs.
config_getlist(&GNBParamList, GNBParams, sizeof(GNBParams) / sizeof(paramdef_t), NULL);
AssertFatal(GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr != NULL, "gNB id %u is not defined in configuration file\n", 0);
AssertFatal(strcmp(GNBSParams[GNB_ACTIVE_GNBS_IDX].strlistptr[0], *GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr) == 0,
"no active gNB found/mismatch of gNBs: %s vs %s\n",
GNBSParams[GNB_ACTIVE_GNBS_IDX].strlistptr[0],
*GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr);
char aprefix[MAX_OPTNAME_SIZE * 2 + 8];
sprintf(aprefix, "%s.[0]", GNB_CONFIG_STRING_GNB_LIST);
paramdef_t PLMNParams[] = GNBPLMNPARAMS_DESC;
paramlist_def_t PLMNParamList = {GNB_CONFIG_STRING_PLMN_LIST, NULL, 0};
/* map parameter checking array instances to parameter definition array instances */
checkedparam_t config_check_PLMNParams[] = PLMNPARAMS_CHECK;
for (int I = 0; I < sizeof(PLMNParams) / sizeof(paramdef_t); ++I)
PLMNParams[I].chkPptr = &(config_check_PLMNParams[I]);
config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams) / sizeof(paramdef_t), aprefix);
f1ap_setup_req_t *req = calloc(1, sizeof(*req));
req->num_cells_available = 1;
req->gNB_DU_id = *(GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr);
req->gNB_DU_name = strdup(*(GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr));
req->cell[0].info.tac = malloc(sizeof(*req->cell[0].info.tac));
AssertFatal(req->cell[0].info.tac != NULL, "out of memory\n");
*req->cell[0].info.tac = *GNBParamList.paramarray[0][GNB_TRACKING_AREA_CODE_IDX].uptr;
req->cell[0].info.plmn.mcc = *PLMNParamList.paramarray[0][GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
req->cell[0].info.plmn.mnc = *PLMNParamList.paramarray[0][GNB_MOBILE_NETWORK_CODE_IDX].uptr;
req->cell[0].info.plmn.mnc_digit_length = *PLMNParamList.paramarray[0][GNB_MNC_DIGIT_LENGTH].u8ptr;
AssertFatal((req->cell[0].info.plmn.mnc_digit_length == 2) || (req->cell[0].info.plmn.mnc_digit_length == 3),
"BAD MNC DIGIT LENGTH %d",
req->cell[0].info.plmn.mnc_digit_length);
req->cell[0].info.nr_cellid = (uint64_t) * (GNBParamList.paramarray[0][GNB_NRCELLID_IDX].u64ptr);
LOG_I(GNB_APP,
"F1AP: gNB idx %d gNB_DU_id %ld, gNB_DU_name %s, TAC %d MCC/MNC/length %d/%d/%d cellID %ld\n",
0,
req->gNB_DU_id,
req->gNB_DU_name,
*req->cell[0].info.tac,
req->cell[0].info.plmn.mcc,
req->cell[0].info.plmn.mnc,
req->cell[0].info.plmn.mnc_digit_length,
req->cell[0].info.nr_cellid);
req->cell[0].info.nr_pci = *scc->physCellId;
LOG_W(GNB_APP, "no slices transported via F1 Setup Request!\n");
req->cell[0].info.num_ssi = 0;
if (scc->tdd_UL_DL_ConfigurationCommon) {
LOG_I(GNB_APP, "ngran_DU: Configuring Cell %d for TDD\n", 0);
req->cell[0].info.mode = F1AP_MODE_TDD;
f1ap_tdd_info_t *tdd = &req->cell[0].info.tdd;
tdd->freqinfo.arfcn = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA;
tdd->tbw.scs = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
tdd->tbw.nrb = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
tdd->freqinfo.band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
} else {
LOG_I(GNB_APP, "ngran_DU: Configuring Cell %d for FDD\n", 0);
req->cell[0].info.mode = F1AP_MODE_FDD;
f1ap_fdd_info_t *fdd = &req->cell[0].info.fdd;
fdd->dl_freqinfo.arfcn = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA;
fdd->ul_freqinfo.arfcn = *scc->uplinkConfigCommon->frequencyInfoUL->absoluteFrequencyPointA;
fdd->dl_tbw.scs = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
fdd->ul_tbw.scs = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
fdd->dl_tbw.nrb = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
fdd->ul_tbw.nrb = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
fdd->dl_freqinfo.band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
fdd->ul_freqinfo.band = *scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList->list.array[0];
}
req->cell[0].info.measurement_timing_information = "0";
int buf_len = 3; // this is what we assume in monolithic
req->cell[0].sys_info = calloc(1, sizeof(*req->cell[0].sys_info));
AssertFatal(req->cell[0].sys_info != NULL, "out of memory\n");
f1ap_gnb_du_system_info_t *sys_info = req->cell[0].sys_info;
sys_info->mib = calloc(buf_len, sizeof(*sys_info->mib));
DevAssert(sys_info->mib != NULL);
DevAssert(mib != NULL);
sys_info->mib_length = encode_MIB_NR(mib, 0, sys_info->mib, buf_len);
DevAssert(sys_info->mib_length == buf_len);
DevAssert(sib1 != NULL);
NR_SIB1_t *bcch_SIB1 = sib1->message.choice.c1->choice.systemInformationBlockType1;
sys_info->sib1 = calloc(NR_MAX_SIB_LENGTH / 8, sizeof(*sys_info->sib1));
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_SIB1, NULL, (void *)bcch_SIB1, sys_info->sib1, NR_MAX_SIB_LENGTH / 8);
AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n", enc_rval.failed_type->name, enc_rval.encoded);
sys_info->sib1_length = (enc_rval.encoded + 7) / 8;
return req;
}
void wait_f1_setup_response(void)
{
gNB_MAC_INST *mac = RC.nrmac[0];
NR_SCHED_LOCK(&mac->sched_lock);
if (mac->f1_config.setup_resp != NULL) {
NR_SCHED_UNLOCK(&mac->sched_lock);
return;
}
LOG_W(GNB_APP, "waiting for F1 Setup Response before activating radio\n");
/* for the moment, we keep it simple and just sleep to periodically check.
* The actual check is protected by a mutex */
while (mac->f1_config.setup_resp == NULL) {
NR_SCHED_UNLOCK(&mac->sched_lock);
sleep(1);
NR_SCHED_LOCK(&mac->sched_lock);
}
NR_SCHED_UNLOCK(&mac->sched_lock);
}
static bool check_plmn_identity(const f1ap_plmn_t *check_plmn, const f1ap_plmn_t *plmn)
{
return plmn->mcc == check_plmn->mcc && plmn->mnc_digit_length == check_plmn->mnc_digit_length && plmn->mnc == check_plmn->mnc;
}
int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update) {
int i, j, ret=0;
LOG_I(GNB_APP, "cells_to_activate %d, RRC instances %d\n",
gnb_cu_cfg_update->num_cells_to_activate, RC.nb_nr_inst);
AssertFatal(gnb_cu_cfg_update->num_cells_to_activate == 1, "only one cell supported at the moment\n");
AssertFatal(RC.nb_nr_inst == 1, "expected one instance\n");
gNB_MAC_INST *mac = RC.nrmac[0];
NR_SCHED_LOCK(&mac->sched_lock);
for (j = 0; j < gnb_cu_cfg_update->num_cells_to_activate; j++) {
for (i = 0; i < RC.nb_nr_inst; i++) {
f1ap_setup_req_t *setup_req = RC.nrmac[i]->f1_config.setup_req;
// identify local index of cell j by nr_cellid, plmn identity and physical cell ID
if (setup_req->cell[0].info.nr_cellid == gnb_cu_cfg_update->cells_to_activate[j].nr_cellid
&& check_plmn_identity(&setup_req->cell[0].info.plmn, &gnb_cu_cfg_update->cells_to_activate[j].plmn) > 0
&& setup_req->cell[0].info.nr_pci == gnb_cu_cfg_update->cells_to_activate[j].nrpci) {
// copy system information and decode it
AssertFatal(gnb_cu_cfg_update->cells_to_activate[j].num_SI == 0,
"gNB-CU Configuration Update: handling of additional SIs not implemend\n");
ret++;
mac->f1_config.setup_resp = malloc(sizeof(*mac->f1_config.setup_resp));
AssertFatal(mac->f1_config.setup_resp != NULL, "out of memory\n");
mac->f1_config.setup_resp->gNB_CU_name = gnb_cu_cfg_update->gNB_CU_name;
mac->f1_config.setup_resp->num_cells_to_activate = gnb_cu_cfg_update->num_cells_to_activate;
mac->f1_config.setup_resp->cells_to_activate[0] = gnb_cu_cfg_update->cells_to_activate[0];
} else {
LOG_E(GNB_APP, "GNB_CU_CONFIGURATION_UPDATE not matching\n");
}
}
}
NR_SCHED_UNLOCK(&mac->sched_lock);
MessageDef *msg_ack_p = NULL;
if (ret > 0) {
// generate gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE
msg_ack_p = itti_alloc_new_message (TASK_GNB_APP, 0, F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE);
F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).num_cells_failed_to_be_activated = 0;
F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).have_criticality = 0;
F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).noofTNLAssociations_to_setup =0;
F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).noofTNLAssociations_failed = 0;
F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).noofDedicatedSIDeliveryNeededUEs = 0;
itti_send_msg_to_task (TASK_DU_F1, INSTANCE_DEFAULT, msg_ack_p);
}
else {
// generate gNB_CU_CONFIGURATION_UPDATE_FAILURE
msg_ack_p = itti_alloc_new_message (TASK_GNB_APP, 0, F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE);
F1AP_GNB_CU_CONFIGURATION_UPDATE_FAILURE(msg_ack_p).cause = F1AP_CauseRadioNetwork_cell_not_available;
itti_send_msg_to_task (TASK_DU_F1, INSTANCE_DEFAULT, msg_ack_p);
}
return(ret);
}
ngran_node_t get_node_type(void)
{
paramdef_t MacRLC_Params[] = MACRLCPARAMS_DESC;
paramlist_def_t MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0};
paramdef_t GNBParams[] = GNBPARAMS_DESC;
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0};
paramdef_t GNBE1Params[] = GNBE1PARAMS_DESC;
paramlist_def_t GNBE1ParamList = {GNB_CONFIG_STRING_E1_PARAMETERS, NULL, 0};
config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL);
if (GNBParamList.numelt == 0) // We have no valid configuration, let's return a default
return ngran_gNB;
config_getlist( &MacRLC_ParamList,MacRLC_Params,sizeof(MacRLC_Params)/sizeof(paramdef_t), NULL);
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0);
config_getlist( &GNBE1ParamList, GNBE1Params, sizeof(GNBE1Params)/sizeof(paramdef_t), aprefix);
if ( MacRLC_ParamList.numelt > 0) {
RC.nb_nr_macrlc_inst = MacRLC_ParamList.numelt;
for (int j = 0; j < RC.nb_nr_macrlc_inst; j++) {
if (strcmp(*(MacRLC_ParamList.paramarray[j][MACRLC_TRANSPORT_N_PREFERENCE_IDX].strptr), "f1") == 0) {
macrlc_has_f1 = 1;
}
}
}
if (strcmp(*(GNBParamList.paramarray[0][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "f1") == 0) {
if ( GNBE1ParamList.paramarray == NULL || GNBE1ParamList.numelt == 0 )
return ngran_gNB_CU;
else if (strcmp(*(GNBE1ParamList.paramarray[0][GNB_CONFIG_E1_CU_TYPE_IDX].strptr), "cp") == 0)
return ngran_gNB_CUCP;
else if (strcmp(*(GNBE1ParamList.paramarray[0][GNB_CONFIG_E1_CU_TYPE_IDX].strptr), "up") == 0)
return ngran_gNB_CUUP;
else
return ngran_gNB_CU;
} else if (macrlc_has_f1 == 0)
return ngran_gNB;
else
return ngran_gNB_DU;
}
#ifdef E2_AGENT
e2_agent_args_t RCconfig_NR_E2agent(void)
{
paramdef_t e2agent_params[] = E2AGENT_PARAMS_DESC;
int ret = config_get(e2agent_params, sizeof(e2agent_params) / sizeof(paramdef_t), CONFIG_STRING_E2AGENT);
if (ret < 0) {
LOG_W(GNB_APP, "configuration file does not contain a \"%s\" section, applying default parameters from FlexRIC\n", CONFIG_STRING_E2AGENT);
return (e2_agent_args_t) { 0 };
}
e2_agent_args_t dst = {0};
if (e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr != NULL)
dst.sm_dir = *e2agent_params[E2AGENT_CONFIG_SMDIR_IDX].strptr;
if (e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr != NULL)
dst.ip = *e2agent_params[E2AGENT_CONFIG_IP_IDX].strptr;
return dst;
}
#endif // E2_AGENT