Note: some modifications have been done to the UE too, but for syntactic reasons. The UE may fail to work, not tested. For the UE, we have the problem of handling properly SecurityModeCommand. We don't verify its integrity. This is a bit complicated to handle properly and may require some API changes in the PDCP layer. So, as of today, the integrity of this message is not verified. Also, NSA mode has been touched, but it should not be a problem. But not tested, so not sure.
2093 lines
121 KiB
C
2093 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/LOG/log_extern.h"
|
|
#include "assertions.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 "SystemInformationBlockType2.h"
|
|
// #include "LAYER2/MAC/extern.h"
|
|
// #include "LAYER2/MAC/proto.h"
|
|
#include "PHY/phy_extern.h"
|
|
#include "PHY/INIT/phy_init.h"
|
|
#include "targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h"
|
|
#include "nfapi_vnf.h"
|
|
#include "nfapi_pnf.h"
|
|
|
|
//#include "L1_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 "RRC/NR/MESSAGES/asn1_msg.h"
|
|
#include "openair2/LAYER2/nr_pdcp/nr_pdcp.h"
|
|
|
|
extern uint16_t sf_ahead;
|
|
int macrlc_has_f1 = 0;
|
|
extern ngran_node_t node_type;
|
|
|
|
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_PDSCH_TimeDomainResourceAllocation *bwp_dl_timedomainresourceallocation;
|
|
struct NR_PUSCH_TimeDomainResourceAllocation *pusch_configcommontimedomainresourceallocation;
|
|
// 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));
|
|
|
|
ASN_SEQUENCE_ADD(&scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list,dl_frequencyBandList);
|
|
ASN_SEQUENCE_ADD(&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));
|
|
//
|
|
for (int i=0;i<NR_maxNrofDL_Allocations;i++) {
|
|
bwp_dl_timedomainresourceallocation = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t));
|
|
bwp_dl_timedomainresourceallocation->k0 = CALLOC(1,sizeof(long));
|
|
*bwp_dl_timedomainresourceallocation->k0=0;
|
|
ASN_SEQUENCE_ADD(&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list,
|
|
bwp_dl_timedomainresourceallocation);
|
|
}
|
|
|
|
ul_frequencyBandList = CALLOC(1,sizeof(NR_FreqBandIndicatorNR_t));
|
|
scc->uplinkConfigCommon->frequencyInfoUL->frequencyBandList = CALLOC(1,sizeof(struct NR_MultiFrequencyBandListNR));
|
|
ASN_SEQUENCE_ADD(&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 = CALLOC(1,sizeof(long));
|
|
|
|
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));
|
|
ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list,ul_scs_SpecificCarrierList);
|
|
|
|
for (int i=0;i<NR_maxNrofUL_Allocations;i++) {
|
|
pusch_configcommontimedomainresourceallocation = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation));
|
|
pusch_configcommontimedomainresourceallocation->k2 = CALLOC(1,sizeof(long));
|
|
*pusch_configcommontimedomainresourceallocation->k2=0;
|
|
ASN_SEQUENCE_ADD(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_configcommontimedomainresourceallocation);
|
|
}
|
|
//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 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 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;
|
|
|
|
// fix DL and UL Allocation lists
|
|
|
|
for (int i=scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count-1;i>=0;i--) {
|
|
printf("Checking element %d : %ld\n",i,*scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0);
|
|
if (*scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0>32) {
|
|
printf("removing pdsch_TimeDomainAllocationList element %d\n",i);
|
|
free(scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->k0);
|
|
asn_sequence_del(&scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list,i,1);
|
|
printf("List size now %d\n",scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count);
|
|
}
|
|
}
|
|
|
|
for (int i=scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count-1;i>=0;i--) {
|
|
if (*scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[i]->k2>32) {
|
|
free(scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[i]->k2);
|
|
asn_sequence_del(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,i,1);
|
|
}
|
|
}
|
|
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));
|
|
|
|
// Downlink bandwidth part
|
|
NR_BWP_Downlink_t *bwp = calloc(1, sizeof(*bwp));
|
|
bwp->bwp_Id = 1;
|
|
|
|
// Allocate downlink dedicated bandwidth part and PDSCH structures
|
|
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++) {
|
|
ASN_SEQUENCE_ADD(&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++) {
|
|
ASN_SEQUENCE_ADD(&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;
|
|
ASN_SEQUENCE_ADD(&scd->downlinkBWP_ToAddModList->list,bwp);
|
|
|
|
// Allocate uplink structures
|
|
|
|
scd->uplinkConfig = CALLOC(1, sizeof(*scd->uplinkConfig));
|
|
scd->uplinkConfig->uplinkBWP_ToAddModList = CALLOC(1, sizeof(*scd->uplinkConfig->uplinkBWP_ToAddModList));
|
|
|
|
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++) {
|
|
ASN_SEQUENCE_ADD(&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++) {
|
|
ASN_SEQUENCE_ADD(&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 = 1;
|
|
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;
|
|
|
|
ASN_SEQUENCE_ADD(&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) {
|
|
// Check for DL PTRS parameters validity
|
|
if (scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->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 = scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.count-1; i >= 0; i--) {
|
|
if ((*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] < 1)
|
|
|| (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] > 276)) {
|
|
LOG_I(RRC, "DL PTRS frequencyDensity %d not set. Assuming PTRS not present! \n", i);
|
|
free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS);
|
|
scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->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 = scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.count-1; i >= 0; i--) {
|
|
if ((*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[i] < 0)
|
|
|| (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[i] > 29)) {
|
|
LOG_I(RRC, "DL PTRS timeDensity %d not set. Assuming PTRS not present! \n", i);
|
|
free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS);
|
|
scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS) {
|
|
if (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset > 2) {
|
|
LOG_I(RRC, "Freeing DL PTRS resourceElementOffset \n");
|
|
free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset);
|
|
scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset = NULL;
|
|
}
|
|
if (*scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio > 1) {
|
|
LOG_I(RRC, "Freeing DL PTRS epre_Ratio \n");
|
|
free(scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio);
|
|
scd->downlinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio = NULL;
|
|
}
|
|
}
|
|
|
|
if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->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 = scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.count-1; i >= 0; i--) {
|
|
if ((*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[i] < 1)
|
|
|| (*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[i] > 276)) {
|
|
LOG_I(RRC, "UL PTRS frequencyDensity %d not set. Assuming PTRS not present! \n", i);
|
|
free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS);
|
|
scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->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 = scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.count-1; i >= 0; i--) {
|
|
if ((*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[i] < 0)
|
|
|| (*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[i] > 29)) {
|
|
LOG_I(RRC, "UL PTRS timeDensity %d not set. Assuming PTRS not present! \n", i);
|
|
free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS);
|
|
scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS) {
|
|
// Check for UL PTRS parameters validity
|
|
if (*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset > 2) {
|
|
LOG_I(RRC, "Freeing UL PTRS resourceElementOffset \n");
|
|
free(scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset);
|
|
scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void RCconfig_nr_flexran()
|
|
{
|
|
uint16_t i;
|
|
uint16_t num_gnbs;
|
|
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
|
|
/* this will possibly truncate the cell id (RRC assumes int32_t).
|
|
* Both Nid_cell and gnb_id are signed in RRC case, but we use unsigned for
|
|
* the bitshifting to work properly */
|
|
uint16_t Nid_cell_tr = 0;
|
|
uint32_t gnb_id = 0;
|
|
|
|
|
|
/* get number of gNBs */
|
|
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
|
|
config_get(GNBSParams, sizeof(GNBSParams)/sizeof(paramdef_t), NULL);
|
|
num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
|
|
|
|
/* for gNB ID */
|
|
paramdef_t GNBParams[] = GNBPARAMS_DESC;
|
|
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST, NULL, 0};
|
|
|
|
paramdef_t flexranParams[] = FLEXRANPARAMS_DESC;
|
|
config_get(flexranParams, sizeof(flexranParams)/sizeof(paramdef_t), CONFIG_STRING_NETWORK_CONTROLLER_CONFIG);
|
|
|
|
if (!RC.flexran) {
|
|
RC.flexran = calloc(num_gnbs, sizeof(flexran_agent_info_t*));
|
|
AssertFatal(RC.flexran,
|
|
"can't ALLOCATE %zu Bytes for %d flexran agent info with size %zu\n",
|
|
num_gnbs * sizeof(flexran_agent_info_t*),
|
|
num_gnbs, sizeof(flexran_agent_info_t*));
|
|
}
|
|
|
|
for (i = 0; i < num_gnbs; i++) {
|
|
RC.flexran[i] = calloc(1, sizeof(flexran_agent_info_t));
|
|
AssertFatal(RC.flexran[i],
|
|
"can't ALLOCATE %zu Bytes for flexran agent info (iteration %d/%d)\n",
|
|
sizeof(flexran_agent_info_t), i + 1, num_gnbs);
|
|
/* if config says "yes", enable Agent, in all other cases it's like "no" */
|
|
RC.flexran[i]->enabled = strcasecmp(*(flexranParams[FLEXRAN_ENABLED].strptr), "yes") == 0;
|
|
/* if not enabled, simply skip the rest, it is not needed anyway */
|
|
if (!RC.flexran[i]->enabled)
|
|
continue;
|
|
RC.flexran[i]->interface_name = strdup(*(flexranParams[FLEXRAN_INTERFACE_NAME_IDX].strptr));
|
|
//inet_ntop(AF_INET, &(enb_properties->properties[mod_id]->flexran_agent_ipv4_address), in_ip, INET_ADDRSTRLEN);
|
|
RC.flexran[i]->remote_ipv4_addr = strdup(*(flexranParams[FLEXRAN_IPV4_ADDRESS_IDX].strptr));
|
|
RC.flexran[i]->remote_port = *(flexranParams[FLEXRAN_PORT_IDX].uptr);
|
|
RC.flexran[i]->cache_name = strdup(*(flexranParams[FLEXRAN_CACHE_IDX].strptr));
|
|
RC.flexran[i]->node_ctrl_state = strcasecmp(*(flexranParams[FLEXRAN_AWAIT_RECONF_IDX].strptr), "yes") == 0 ? ENB_WAIT : ENB_NORMAL_OPERATION;
|
|
|
|
config_getlist(&GNBParamList, GNBParams, sizeof(GNBParams)/sizeof(paramdef_t),NULL);
|
|
/* gNB ID from configuration, as read in by RCconfig_RRC() */
|
|
if (!GNBParamList.paramarray[i][GNB_GNB_ID_IDX].uptr) {
|
|
// Calculate a default gNB ID
|
|
if (AMF_MODE_ENABLED)
|
|
gnb_id = i + (ngap_generate_gNB_id () & 0xFFFFFF8);
|
|
else
|
|
gnb_id = i;
|
|
} else {
|
|
gnb_id = *(GNBParamList.paramarray[i][GNB_GNB_ID_IDX].uptr);
|
|
}
|
|
|
|
/* cell ID */
|
|
sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, i);
|
|
|
|
RC.flexran[i]->mod_id = i;
|
|
RC.flexran[i]->agent_id = (((uint64_t)i) << 48) | (((uint64_t)gnb_id) << 16) | ((uint64_t)Nid_cell_tr);
|
|
|
|
/*
|
|
* Assume for the moment the monolithic case, i.e. agent can provide information for all layers
|
|
* Consider using uint16_t flexran_get_capabilities_mask(mid_t mod_id),
|
|
* with RC.rrc[mod_id]->node_type = ngran_gNB
|
|
*/
|
|
RC.flexran[i]->capability_mask = (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOPHY)
|
|
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIPHY)
|
|
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__LOMAC)
|
|
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__HIMAC)
|
|
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__RLC)
|
|
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__PDCP)
|
|
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__SDAP)
|
|
| (1 << PROTOCOL__FLEX_BS_CAPABILITY__RRC);
|
|
|
|
}
|
|
}
|
|
|
|
void RCconfig_NR_L1(void) {
|
|
int j;
|
|
paramdef_t L1_Params[] = L1PARAMS_DESC;
|
|
paramlist_def_t L1_ParamList = {CONFIG_STRING_L1_LIST,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( &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;
|
|
}
|
|
|
|
RC.gNB[j]->pusch_proc_threads = *(L1_ParamList.paramarray[j][L1_PUSCH_PROC_THREADS].uptr);
|
|
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);
|
|
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);
|
|
|
|
mac_top_init_gNB();
|
|
|
|
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");
|
|
|
|
// DJP 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
void RCconfig_nr_macrlc() {
|
|
int j;
|
|
|
|
paramdef_t MacRLC_Params[] = MACRLCPARAMS_DESC;
|
|
paramlist_def_t MacRLC_ParamList = {CONFIG_STRING_MACRLC_LIST,NULL,0};
|
|
|
|
config_getlist( &MacRLC_ParamList,MacRLC_Params,sizeof(MacRLC_Params)/sizeof(paramdef_t), NULL);
|
|
|
|
if ( MacRLC_ParamList.numelt > 0) {
|
|
|
|
RC.nb_nr_macrlc_inst=MacRLC_ParamList.numelt;
|
|
mac_top_init_gNB();
|
|
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]->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);
|
|
|
|
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);
|
|
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_slots_inactivity = *(MacRLC_ParamList.paramarray[j][MACRLC_ULSCH_MAX_SLOTS_INACTIVITY].uptr);
|
|
}// for (j=0;j<RC.nb_nr_macrlc_inst;j++)
|
|
}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);
|
|
}
|
|
}
|
|
|
|
void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
|
|
|
|
int num_gnbs = 0;
|
|
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
|
|
int32_t gnb_id = 0;
|
|
int k = 0;
|
|
|
|
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
|
|
////////// Identification parameters
|
|
paramdef_t GNBParams[] = GNBPARAMS_DESC;
|
|
paramlist_def_t GNBParamList = {GNB_CONFIG_STRING_GNB_LIST,NULL,0};
|
|
|
|
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};
|
|
|
|
// Serving Cell Config Dedicated
|
|
NR_ServingCellConfig_t *scd = calloc(1,sizeof(NR_ServingCellConfig_t));
|
|
memset((void*)scd,0,sizeof(NR_ServingCellConfig_t));
|
|
prepare_scd(scd);
|
|
paramdef_t SCDsParams[] = SCDPARAMS_DESC(scd);
|
|
paramlist_def_t SCDsParamList = {GNB_CONFIG_STRING_SERVINGCELLCONFIGDEDICATED, 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 %ith element in %s \n",i, GNB_CONFIG_STRING_ACTIVE_GNBS);
|
|
|
|
/*
|
|
if (AMF_MODE_ENABLED) {
|
|
if (strcasecmp( *(GNBSParams[GNB_ASN1_VERBOSITY_IDX].strptr), GNB_CONFIG_STRING_ASN1_VERBOSITY_NONE) == 0) {
|
|
asn_debug = 0;
|
|
asn1_xer_print = 0;
|
|
} else if (strcasecmp( *(GNBSParams[GNB_ASN1_VERBOSITY_IDX].strptr), GNB_CONFIG_STRING_ASN1_VERBOSITY_INFO) == 0) {
|
|
asn_debug = 1;
|
|
asn1_xer_print = 1;
|
|
} else if (strcasecmp(*(GNBSParams[GNB_ASN1_VERBOSITY_IDX].strptr) , GNB_CONFIG_STRING_ASN1_VERBOSITY_ANNOYING) == 0) {
|
|
asn_debug = 1;
|
|
asn1_xer_print = 2;
|
|
} else {
|
|
asn_debug = 0;
|
|
asn1_xer_print = 0;
|
|
}
|
|
}
|
|
*/
|
|
|
|
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 (AMF_MODE_ENABLED) {
|
|
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);
|
|
}
|
|
|
|
// pdcch_ConfigSIB1
|
|
rrc->carrier.pdcch_ConfigSIB1 = calloc(1,sizeof(NR_PDCCH_ConfigSIB1_t));
|
|
paramdef_t pdcch_ConfigSIB1[] = PDCCH_CONFIGSIB1PARAMS_DESC(rrc->carrier.pdcch_ConfigSIB1);
|
|
paramlist_def_t pdcch_ConfigSIB1ParamList = {GNB_CONFIG_STRING_PDCCH_CONFIGSIB1, NULL, 0};
|
|
sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 0);
|
|
config_getlist(&pdcch_ConfigSIB1ParamList, NULL, 0, aprefix);
|
|
if (pdcch_ConfigSIB1ParamList.numelt > 0) {
|
|
sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_PDCCH_CONFIGSIB1, 0);
|
|
config_get(pdcch_ConfigSIB1,sizeof(pdcch_ConfigSIB1)/sizeof(paramdef_t),aprefix);
|
|
}
|
|
|
|
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);
|
|
fix_scc(scc,ssb_bitmap);
|
|
}
|
|
|
|
sprintf(aprefix, "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, 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);
|
|
LOG_I(RRC,"Read in ServingCellConfigDedicated UL (FreqDensity_0 %d, FreqDensity_1 %d, TimeDensity_0 %d, TimeDensity_1 %d, TimeDensity_2 %d, RE offset %d \n",
|
|
(int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[0],
|
|
(int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->frequencyDensity->list.array[1],
|
|
(int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[0],
|
|
(int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[1],
|
|
(int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->timeDensity->list.array[2],
|
|
(int)*scd->uplinkConfig->uplinkBWP_ToAddModList->list.array[0]->bwp_Dedicated->pusch_Config->choice.setup->dmrs_UplinkForPUSCH_MappingTypeB->choice.setup->phaseTrackingRS->choice.setup->transformPrecoderDisabled->resourceElementOffset);
|
|
}
|
|
fix_scd(scd);
|
|
|
|
printf("NRRRC %d: Southbound Transport %s\n",i,*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr));
|
|
|
|
if (strcmp(*(GNBParamList.paramarray[i][GNB_TRANSPORT_S_PREFERENCE_IDX].strptr), "f1") == 0) {
|
|
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->node_type = ngran_gNB_CU;
|
|
rrc->sctp_in_streams = (uint16_t)*(SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr);
|
|
rrc->sctp_out_streams = (uint16_t)*(SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr);
|
|
} else {
|
|
// set to ngran_gNB for now, it will get set to ngran_gNB_DU if macrlc entity which uses F1 is present
|
|
// Note: we will have to handle the case of ngran_ng_gNB_DU
|
|
if (macrlc_has_f1 == 0) {
|
|
rrc->node_type = ngran_gNB;
|
|
LOG_I(NR_RRC,"Setting node_type to ngran_gNB\n");
|
|
} else {
|
|
rrc->node_type = ngran_gNB_DU;
|
|
LOG_I(NR_RRC,"Setting node_type to ngran_gNB_DU\n");
|
|
}
|
|
}
|
|
|
|
rrc->nr_cellid = (uint64_t)*(GNBParamList.paramarray[i][GNB_NRCELLID_IDX].u64ptr);
|
|
|
|
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
|
|
|
|
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_CONFIGURATION_REQ (msg_p).cell_identity = gnb_id;
|
|
NRRRC_CONFIGURATION_REQ (msg_p).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_CONFIGURATION_REQ(msg_p).num_plmn = PLMNParamList.numelt;
|
|
|
|
for (int l = 0; l < PLMNParamList.numelt; ++l) {
|
|
|
|
NRRRC_CONFIGURATION_REQ (msg_p).mcc[l] = *PLMNParamList.paramarray[l][GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
|
|
NRRRC_CONFIGURATION_REQ (msg_p).mnc[l] = *PLMNParamList.paramarray[l][GNB_MOBILE_NETWORK_CODE_IDX].uptr;
|
|
NRRRC_CONFIGURATION_REQ (msg_p).mnc_digit_length[l] = *PLMNParamList.paramarray[l][GNB_MNC_DIGIT_LENGTH].u8ptr;
|
|
AssertFatal((NRRRC_CONFIGURATION_REQ (msg_p).mnc_digit_length[l] == 2) ||
|
|
(NRRRC_CONFIGURATION_REQ (msg_p).mnc_digit_length[l] == 3),"BAD MNC DIGIT LENGTH %d",
|
|
NRRRC_CONFIGURATION_REQ (msg_p).mnc_digit_length[l]);
|
|
}
|
|
printf("SSB SCO %d\n",*GNBParamList.paramarray[i][GNB_SSB_SUBCARRIEROFFSET_IDX].iptr);
|
|
NRRRC_CONFIGURATION_REQ (msg_p).ssb_SubcarrierOffset = *GNBParamList.paramarray[i][GNB_SSB_SUBCARRIEROFFSET_IDX].iptr;
|
|
printf("pdsch_AntennaPorts %d\n",*GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_IDX].iptr);
|
|
NRRRC_CONFIGURATION_REQ (msg_p).pdsch_AntennaPorts = *GNBParamList.paramarray[i][GNB_PDSCH_ANTENNAPORTS_IDX].iptr;
|
|
printf("pusch_AntennaPorts %d\n",*GNBParamList.paramarray[i][GNB_PUSCH_ANTENNAPORTS_IDX].iptr);
|
|
NRRRC_CONFIGURATION_REQ (msg_p).pusch_AntennaPorts = *GNBParamList.paramarray[i][GNB_PUSCH_ANTENNAPORTS_IDX].iptr;
|
|
NRRRC_CONFIGURATION_REQ (msg_p).sib1_tda = *GNBParamList.paramarray[i][GNB_SIB1_TDA_IDX].iptr;
|
|
printf("Do CSI-RS %d\n",*GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr);
|
|
NRRRC_CONFIGURATION_REQ (msg_p).do_CSIRS = *GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr;
|
|
NRRRC_CONFIGURATION_REQ (msg_p).scc = scc;
|
|
NRRRC_CONFIGURATION_REQ (msg_p).scd = scd;
|
|
|
|
|
|
}//
|
|
}//End for (k=0; k <num_gnbs ; k++)
|
|
memcpy(&rrc->configuration, &NRRRC_CONFIGURATION_REQ(msg_p), sizeof(NRRRC_CONFIGURATION_REQ(msg_p)));
|
|
}//End if (num_gnbs>0)
|
|
|
|
config_security(rrc);
|
|
}//End RCconfig_NRRRC function
|
|
|
|
int RCconfig_nr_gtpu(void ) {
|
|
|
|
int num_gnbs = 0;
|
|
|
|
|
|
|
|
char* gnb_interface_name_for_NGU = NULL;
|
|
char* gnb_ipv4_address_for_NGU = NULL;
|
|
uint32_t gnb_port_for_NGU = 0;
|
|
char* gnb_interface_name_for_S1U = NULL;
|
|
char* gnb_ipv4_address_for_S1U = NULL;
|
|
uint32_t gnb_port_for_S1U = 0;
|
|
char *address = NULL;
|
|
char *cidr = NULL;
|
|
char gtpupath[MAX_OPTNAME_SIZE*2 + 8];
|
|
uint8_t gnb_mode = 0;
|
|
|
|
paramdef_t GNBSParams[] = GNBSPARAMS_DESC;
|
|
paramdef_t NETParams[] = GNBNETPARAMS_DESC;
|
|
paramdef_t GTPUParams[] = GNBGTPUPARAMS_DESC;
|
|
LOG_I(GTPU,"Configuring GTPu\n");
|
|
|
|
/* get number of active eNodeBs */
|
|
config_get( GNBSParams,sizeof(GNBSParams)/sizeof(paramdef_t),NULL);
|
|
num_gnbs = GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt;
|
|
AssertFatal (num_gnbs >0,
|
|
"Failed to parse config file no active gNodeBs in %s \n", GNB_CONFIG_STRING_ACTIVE_GNBS);
|
|
|
|
sprintf(gtpupath,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
|
|
config_get(GTPUParams,sizeof(GTPUParams)/sizeof(paramdef_t),gtpupath);
|
|
|
|
config_get(NETParams,sizeof(NETParams)/sizeof(paramdef_t),gtpupath);
|
|
|
|
if (NETParams[0].strptr != NULL) { // SA
|
|
LOG_I(GTPU, "SA mode \n");
|
|
cidr = gnb_ipv4_address_for_NGU;
|
|
gnb_mode = 0;
|
|
} else {// NSA
|
|
LOG_I(GTPU, "NSA mode \n");
|
|
cidr = gnb_ipv4_address_for_S1U;
|
|
gnb_mode = 1;
|
|
}
|
|
|
|
address = strtok(cidr, "/");
|
|
|
|
if (address) {
|
|
MessageDef *message;
|
|
|
|
if (gnb_mode == 1) { // NSA
|
|
message = itti_alloc_new_message(TASK_GNB_APP, 0, GTPV1U_ENB_S1_REQ);
|
|
AssertFatal(message!=NULL,"");
|
|
// IPV4_STR_ADDR_TO_INT_NWBO ( address, RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up, "BAD IP ADDRESS FORMAT FOR eNB S1_U !\n" );
|
|
// LOG_I(GTPU,"Configuring GTPu address : %s -> %x\n",address,RC.gtpv1u_data_g->enb_ip_address_for_S1u_S12_S4_up);
|
|
IPV4_STR_ADDR_TO_INT_NWBO (address, GTPV1U_ENB_S1_REQ(message).enb_ip_address_for_S1u_S12_S4_up, "BAD IP ADDRESS FORMAT FOR eNB S1_U !\n" );
|
|
LOG_I(GTPU,"Configuring GTPu address : %s -> %x\n",address,GTPV1U_ENB_S1_REQ(message).enb_ip_address_for_S1u_S12_S4_up);
|
|
GTPV1U_ENB_S1_REQ(message).enb_port_for_S1u_S12_S4_up = gnb_port_for_S1U;
|
|
strcpy(GTPV1U_ENB_S1_REQ(message).addrStr,address);
|
|
sprintf(GTPV1U_ENB_S1_REQ(message).portStr,"%d", gnb_port_for_NGU);
|
|
} else {// TODO SA
|
|
message = itti_alloc_new_message(TASK_GNB_APP, 0, GTPV1U_GNB_NG_REQ);
|
|
AssertFatal(message!=NULL,"");
|
|
IPV4_STR_ADDR_TO_INT_NWBO (address, GTPV1U_GNB_NG_REQ(message).gnb_ip_address_for_NGu_up, "BAD IP ADDRESS FORMAT FOR gNB NG_U !\n" );
|
|
LOG_I(GTPU,"Configuring GTPu address : %s -> %x\n",address,GTPV1U_GNB_NG_REQ(message).gnb_ip_address_for_NGu_up);
|
|
GTPV1U_GNB_NG_REQ(message).gnb_port_for_NGu_up = gnb_port_for_NGU;
|
|
strcpy(GTPV1U_GNB_NG_REQ(message).addrStr,address);
|
|
sprintf(GTPV1U_GNB_NG_REQ(message).portStr,"%d", gnb_port_for_NGU);
|
|
}
|
|
itti_send_msg_to_task (TASK_VARIABLE, 0, message); // data model is wrong: gtpu doesn't have enb_id (or module_id)
|
|
} else
|
|
LOG_E(GTPU,"invalid address for NGU\n");
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
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*));
|
|
|
|
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);
|
|
|
|
/*
|
|
if (AMF_MODE_ENABLED) {
|
|
if (strcasecmp( *(GNBSParams[GNB_ASN1_VERBOSITY_IDX].strptr), GNB_CONFIG_STRING_ASN1_VERBOSITY_NONE) == 0) {
|
|
asn_debug = 0;
|
|
asn1_xer_print = 0;
|
|
} else if (strcasecmp( *(GNBSParams[GNB_ASN1_VERBOSITY_IDX].strptr), GNB_CONFIG_STRING_ASN1_VERBOSITY_INFO) == 0) {
|
|
asn_debug = 1;
|
|
asn1_xer_print = 1;
|
|
} else if (strcasecmp(*(GNBSParams[GNB_ASN1_VERBOSITY_IDX].strptr) , GNB_CONFIG_STRING_ASN1_VERBOSITY_ANNOYING) == 0) {
|
|
asn_debug = 1;
|
|
asn1_xer_print = 2;
|
|
} else {
|
|
asn_debug = 0;
|
|
asn1_xer_print = 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 gNB ID
|
|
if (AMF_MODE_ENABLED) {
|
|
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 %d 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_SERIVE_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) {
|
|
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 (AMF_MODE_ENABLED) {
|
|
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);
|
|
address = strtok(cidr, "/");
|
|
|
|
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 (AMF_MODE_ENABLED) {
|
|
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;
|
|
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 %d 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 (AMF_MODE_ENABLED) {
|
|
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);
|
|
address = strtok(cidr, "/");
|
|
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;
|
|
}
|
|
|
|
int RCconfig_NR_DU_F1(MessageDef *msg_p, uint32_t i) {
|
|
int k;
|
|
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 (i < num_gnbs,
|
|
"Failed to parse config file no %uth element in %s \n",i, GNB_CONFIG_STRING_ACTIVE_GNBS);
|
|
|
|
if (num_gnbs > 0) {
|
|
// Output a list of all eNBs.
|
|
config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL);
|
|
AssertFatal(GNBParamList.paramarray[i][GNB_GNB_ID_IDX].uptr != NULL,
|
|
"gNB id %u is not defined in configuration file\n",i);
|
|
F1AP_SETUP_REQ (msg_p).num_cells_available = 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 aprefix[MAX_OPTNAME_SIZE*2 + 8];
|
|
sprintf(aprefix,"%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]);
|
|
|
|
config_getlist(&PLMNParamList, PLMNParams, sizeof(PLMNParams)/sizeof(paramdef_t), aprefix);
|
|
paramdef_t SCTPParams[] = SCTPPARAMS_DESC;
|
|
F1AP_SETUP_REQ (msg_p).num_cells_available++;
|
|
F1AP_SETUP_REQ (msg_p).gNB_DU_id = *(GNBParamList.paramarray[0][GNB_GNB_ID_IDX].uptr);
|
|
LOG_I(GNB_APP,"F1AP: gNB_DU_id[%d] %ld\n",k,F1AP_SETUP_REQ (msg_p).gNB_DU_id);
|
|
F1AP_SETUP_REQ (msg_p).gNB_DU_name = strdup(*(GNBParamList.paramarray[0][GNB_GNB_NAME_IDX].strptr));
|
|
LOG_I(GNB_APP,"F1AP: gNB_DU_name[%d] %s\n",k,F1AP_SETUP_REQ (msg_p).gNB_DU_name);
|
|
F1AP_SETUP_REQ (msg_p).tac[k] = *GNBParamList.paramarray[i][GNB_TRACKING_AREA_CODE_IDX].uptr;
|
|
LOG_I(GNB_APP,"F1AP: tac[%d] %d\n",k,F1AP_SETUP_REQ (msg_p).tac[k]);
|
|
F1AP_SETUP_REQ (msg_p).mcc[k] = *PLMNParamList.paramarray[0][GNB_MOBILE_COUNTRY_CODE_IDX].uptr;
|
|
LOG_I(GNB_APP,"F1AP: mcc[%d] %d\n",k,F1AP_SETUP_REQ (msg_p).mcc[k]);
|
|
F1AP_SETUP_REQ (msg_p).mnc[k] = *PLMNParamList.paramarray[0][GNB_MOBILE_NETWORK_CODE_IDX].uptr;
|
|
LOG_I(GNB_APP,"F1AP: mnc[%d] %d\n",k,F1AP_SETUP_REQ (msg_p).mnc[k]);
|
|
F1AP_SETUP_REQ (msg_p).mnc_digit_length[k] = *PLMNParamList.paramarray[0][GNB_MNC_DIGIT_LENGTH].u8ptr;
|
|
LOG_I(GNB_APP,"F1AP: mnc_digit_length[%d] %d\n",k,F1AP_SETUP_REQ (msg_p).mnc_digit_length[k]);
|
|
AssertFatal((F1AP_SETUP_REQ (msg_p).mnc_digit_length[k] == 2) ||
|
|
(F1AP_SETUP_REQ (msg_p).mnc_digit_length[k] == 3),
|
|
"BAD MNC DIGIT LENGTH %d",
|
|
F1AP_SETUP_REQ (msg_p).mnc_digit_length[k]);
|
|
F1AP_SETUP_REQ (msg_p).nr_cellid[k] = (uint64_t)*(GNBParamList.paramarray[i][GNB_NRCELLID_IDX].u64ptr);
|
|
LOG_I(GNB_APP,"F1AP: nr_cellid[%d] %ld\n",k,F1AP_SETUP_REQ (msg_p).nr_cellid[k]);
|
|
LOG_I(GNB_APP,"F1AP: CU_ip4_address in DU %s\n",RC.nrmac[k]->eth_params_n.remote_addr);
|
|
LOG_I(GNB_APP,"FIAP: CU_ip4_address in DU %p, strlen %d\n",F1AP_SETUP_REQ (msg_p).CU_f1_ip_address.ipv4_address,(int)strlen(RC.nrmac[k]->eth_params_n.remote_addr));
|
|
F1AP_SETUP_REQ (msg_p).CU_f1_ip_address.ipv6 = 0;
|
|
F1AP_SETUP_REQ (msg_p).CU_f1_ip_address.ipv4 = 1;
|
|
//strcpy(F1AP_SETUP_REQ (msg_p).CU_f1_ip_address.ipv6_address, "");
|
|
strcpy(F1AP_SETUP_REQ (msg_p).CU_f1_ip_address.ipv4_address, RC.nrmac[k]->eth_params_n.remote_addr);
|
|
LOG_I(GNB_APP,"F1AP: DU_ip4_address in DU %s\n",RC.nrmac[k]->eth_params_n.my_addr);
|
|
LOG_I(GNB_APP,"FIAP: DU_ip4_address in DU %p, strlen %d\n",F1AP_SETUP_REQ (msg_p).DU_f1_ip_address.ipv4_address,(int)strlen(RC.nrmac[k]->eth_params_n.my_addr));
|
|
F1AP_SETUP_REQ (msg_p).DU_f1_ip_address.ipv6 = 0;
|
|
F1AP_SETUP_REQ (msg_p).DU_f1_ip_address.ipv4 = 1;
|
|
//strcpy(F1AP_SETUP_REQ (msg_p).DU_f1_ip_address.ipv6_address, "");
|
|
strcpy(F1AP_SETUP_REQ (msg_p).DU_f1_ip_address.ipv4_address, RC.nrmac[k]->eth_params_n.my_addr);
|
|
//strcpy(F1AP_SETUP_REQ (msg_p).CU_ip_address[l].ipv6_address,*(F1ParamList.paramarray[l][ENB_CU_IPV6_ADDRESS_IDX].strptr));
|
|
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);
|
|
F1AP_SETUP_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr);
|
|
F1AP_SETUP_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr);
|
|
gNB_RRC_INST *rrc = RC.nrrrc[k];
|
|
// wait until RRC cell information is configured
|
|
int cell_info_configured = 0;
|
|
|
|
do {
|
|
LOG_I(GNB_APP,"ngran_gNB_DU: Waiting for basic cell configuration\n");
|
|
usleep(100000);
|
|
pthread_mutex_lock(&rrc->cell_info_mutex);
|
|
cell_info_configured = rrc->cell_info_configured;
|
|
pthread_mutex_unlock(&rrc->cell_info_mutex);
|
|
} while (cell_info_configured == 0);
|
|
|
|
rrc->configuration.mcc[0] = F1AP_SETUP_REQ (msg_p).mcc[k];
|
|
rrc->configuration.mnc[0] = F1AP_SETUP_REQ (msg_p).mnc[k];
|
|
rrc->configuration.tac = F1AP_SETUP_REQ (msg_p).tac[k];
|
|
rrc->nr_cellid = F1AP_SETUP_REQ (msg_p).nr_cellid[k];
|
|
F1AP_SETUP_REQ (msg_p).nr_pci[k] = *rrc->configuration.scc->physCellId;
|
|
F1AP_SETUP_REQ (msg_p).num_ssi[k] = 0;
|
|
|
|
if (rrc->configuration.scc->tdd_UL_DL_ConfigurationCommon) {
|
|
LOG_I(GNB_APP,"ngran_DU: Configuring Cell %d for TDD\n",k);
|
|
F1AP_SETUP_REQ (msg_p).fdd_flag = 0;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.nr_arfcn = rrc->configuration.scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.scs = rrc->configuration.scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.nrb = rrc->configuration.scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.num_frequency_bands = 1;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.nr_band[0] = *rrc->configuration.scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0];
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].tdd.sul_active = 0;
|
|
} else {
|
|
/***************** for test *****************/
|
|
LOG_I(GNB_APP,"ngran_DU: Configuring Cell %d for FDD\n",k);
|
|
F1AP_SETUP_REQ (msg_p).fdd_flag = 1;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.dl_nr_arfcn = 26200UL;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_nr_arfcn = 26200UL;
|
|
// For LTE use scs field to carry prefix type and number of antennas
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.dl_scs = 0;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_scs = 0;
|
|
// use nrb field to hold LTE N_RB_DL (0...5)
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_nrb = 3;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_nrb = 3;
|
|
// RK: we need to check there value for FDD's frequency_bands DL/UL
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_num_frequency_bands = 1;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_nr_band[0] = 7;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.dl_num_frequency_bands = 1;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.dl_nr_band[0] = 7;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_num_sul_frequency_bands = 0;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.ul_nr_sul_band[0] = 7;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.dl_num_sul_frequency_bands = 0;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.dl_nr_sul_band[0] = 7;
|
|
F1AP_SETUP_REQ (msg_p).nr_mode_info[k].fdd.sul_active = 0;
|
|
/***************** for test *****************/
|
|
}
|
|
|
|
F1AP_SETUP_REQ (msg_p).measurement_timing_information[k] = "0";
|
|
F1AP_SETUP_REQ (msg_p).ranac[k] = 0;
|
|
F1AP_SETUP_REQ (msg_p).mib[k] = rrc->carrier.MIB;
|
|
F1AP_SETUP_REQ (msg_p).sib1[k] = rrc->carrier.SIB1;
|
|
F1AP_SETUP_REQ (msg_p).mib_length[k] = rrc->carrier.sizeof_MIB;
|
|
F1AP_SETUP_REQ (msg_p).sib1_length[k] = rrc->carrier.sizeof_SIB1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int du_check_plmn_identity(rrc_gNB_carrier_data_t *carrier,uint16_t mcc,uint16_t mnc,uint8_t mnc_digit_length) {
|
|
NR_SIB1_t *sib1 = carrier->siblock1->message.choice.c1->choice.systemInformationBlockType1;
|
|
AssertFatal(sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]->plmn_IdentityList.list.count > 0,
|
|
"plmn info isn't there\n");
|
|
AssertFatal(mnc_digit_length == 2 || mnc_digit_length == 3,
|
|
"impossible mnc_digit_length %d\n", mnc_digit_length);
|
|
NR_PLMN_Identity_t *plmn_Identity = sib1->cellAccessRelatedInfo.plmn_IdentityList.list.array[0]
|
|
->plmn_IdentityList.list.array[0];
|
|
|
|
// check if mcc is different and return failure if so
|
|
if (mcc !=
|
|
((*plmn_Identity->mcc->list.array[0])*100)+
|
|
((*plmn_Identity->mcc->list.array[1])*10) +
|
|
(*plmn_Identity->mcc->list.array[2])) {
|
|
LOG_E(GNB_APP, "mcc in F1AP_SETUP_RESP message is different from mcc in DU \n");
|
|
return(0);
|
|
}
|
|
|
|
// check that mnc digit length is different and return failure if so
|
|
if (mnc_digit_length != plmn_Identity->mnc.list.count) {
|
|
LOG_E(GNB_APP, "mnc(length: %d) in F1AP_SETUP_RESP message is different from mnc(length: %d) in DU \n",
|
|
mnc_digit_length, plmn_Identity->mnc.list.count);
|
|
return 0;
|
|
}
|
|
|
|
// check that 2 digit mnc is different and return failure if so
|
|
if (mnc_digit_length == 2 &&
|
|
(mnc !=
|
|
(*plmn_Identity->mnc.list.array[0]*10) +
|
|
(*plmn_Identity->mnc.list.array[1]))) {
|
|
LOG_E(GNB_APP, "mnc(%d) in F1AP_SETUP_RESP message is different from mnc(%ld%ld) in DU \n",
|
|
mnc, *plmn_Identity->mnc.list.array[0], *plmn_Identity->mnc.list.array[1]);
|
|
return(0);
|
|
}
|
|
else if (mnc_digit_length == 3 &&
|
|
(mnc !=
|
|
(*plmn_Identity->mnc.list.array[0]*100) +
|
|
(*plmn_Identity->mnc.list.array[1]*10) +
|
|
(*plmn_Identity->mnc.list.array[2]))) {
|
|
LOG_E(GNB_APP, "mnc(%d) in F1AP_SETUP_RESP message is different from mnc(%ld%ld%ld) in DU \n",
|
|
mnc, *plmn_Identity->mnc.list.array[0], *plmn_Identity->mnc.list.array[1], *plmn_Identity->mnc.list.array[2]);
|
|
return(0);
|
|
}
|
|
|
|
// if we're here, the mcc/mnc match so return success
|
|
return(1);
|
|
}
|
|
|
|
void du_extract_and_decode_SI(int inst, int si_ind, uint8_t *si_container, int si_container_length) {
|
|
gNB_RRC_INST *rrc = RC.nrrrc[inst];
|
|
rrc_gNB_carrier_data_t *carrier = &rrc->carrier;
|
|
NR_BCCH_DL_SCH_Message_t *bcch_message ;
|
|
AssertFatal(si_ind == 0, "Can only handle a single SI block for now\n");
|
|
LOG_I(GNB_APP, "rrc inst %d: Trying to decode SI block %d @ %p, length %d\n", inst, si_ind, si_container, si_container_length);
|
|
// point to first SI block
|
|
bcch_message = &carrier->systemInformation;
|
|
asn_dec_rval_t dec_rval = uper_decode_complete( NULL,
|
|
&asn_DEF_NR_BCCH_DL_SCH_Message,
|
|
(void **)&bcch_message,
|
|
(const void *)si_container,
|
|
si_container_length);
|
|
|
|
if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) {
|
|
AssertFatal(1==0, "[GNB_APP][NR_RRC inst %"PRIu8"] Failed to decode BCCH_DLSCH_MESSAGE (%zu bits)\n",
|
|
inst,
|
|
dec_rval.consumed );
|
|
}
|
|
|
|
if (bcch_message->message.present == NR_BCCH_DL_SCH_MessageType_PR_c1) {
|
|
switch (bcch_message->message.choice.c1->present) {
|
|
case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1:
|
|
AssertFatal(1 == 0, "Should have received SIB1 from CU\n");
|
|
break;
|
|
|
|
case NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformation:
|
|
{
|
|
NR_SystemInformation_t *si = bcch_message->message.choice.c1->choice.systemInformation;
|
|
|
|
if (si->criticalExtensions.present == NR_SystemInformation__criticalExtensions_PR_systemInformation) {
|
|
for (int i = 0; i < si->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.count; i++) {
|
|
LOG_I(GNB_APP, "Extracting SI %d/%d\n", i, si->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.count);
|
|
SystemInformation_IEs__sib_TypeAndInfo__Member *typeAndInfo;
|
|
typeAndInfo = si->criticalExtensions.choice.systemInformation->sib_TypeAndInfo.list.array[i];
|
|
|
|
switch(typeAndInfo->present) {
|
|
case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_NOTHING:
|
|
AssertFatal(0, "Should have received SIB2 SIB3 from CU\n");
|
|
break;
|
|
case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib2:
|
|
LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB2 in CU F1AP_SETUP_RESP message\n", inst);
|
|
carrier->sib2 = typeAndInfo->choice.sib2;
|
|
carrier->SIB23 = (uint8_t *)malloc(64);
|
|
memcpy((void *)carrier->SIB23, (void *)si_container, si_container_length);
|
|
carrier->sizeof_SIB23 = si_container_length;
|
|
break;
|
|
case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib3:
|
|
carrier->sib3 = typeAndInfo->choice.sib3;
|
|
LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB3 in CU F1AP_SETUP_RESP message\n", inst);
|
|
break;
|
|
case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib4:
|
|
LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB4 in CU F1AP_SETUP_RESP message\n", inst);
|
|
break;
|
|
case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib5:
|
|
LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB5 in CU F1AP_SETUP_RESP message\n", inst);
|
|
break;
|
|
case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib6:
|
|
LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB6 in CU F1AP_SETUP_RESP message\n", inst);
|
|
break;
|
|
case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib7:
|
|
LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB7 in CU F1AP_SETUP_RESP message\n", inst);
|
|
break;
|
|
case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib8:
|
|
LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB8 in CU F1AP_SETUP_RESP message\n", inst);
|
|
break;
|
|
case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib9:
|
|
LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB9 in CU F1AP_SETUP_RESP message\n", inst);
|
|
break;
|
|
case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib10_v1610:
|
|
LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB10 in CU F1AP_SETUP_RESP message\n", inst);
|
|
break;
|
|
case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib11_v1610:
|
|
LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB11 in CU F1AP_SETUP_RESP message\n", inst);
|
|
break;
|
|
case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib12_v1610:
|
|
LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB12 in CU F1AP_SETUP_RESP message\n", inst);
|
|
break;
|
|
case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib13_v1610:
|
|
LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB13 in CU F1AP_SETUP_RESP message\n", inst);
|
|
break;
|
|
case NR_SystemInformation_IEs__sib_TypeAndInfo__Member_PR_sib14_v1610:
|
|
LOG_I(GNB_APP, "[NR_RRC %"PRIu8"] Found SIB14 in CU F1AP_SETUP_RESP message\n", inst);
|
|
break;
|
|
default:
|
|
AssertFatal(1 == 0,"Shouldn't have received this SI %d\n", typeAndInfo->present);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case NR_BCCH_DL_SCH_MessageType__c1_PR_NOTHING:
|
|
AssertFatal(0, "Should have received SIB1 from CU\n");
|
|
break;
|
|
}
|
|
} else AssertFatal(1 == 0, "No SI messages\n");
|
|
}
|
|
|
|
void configure_gnb_du_mac(int inst) {
|
|
gNB_RRC_INST *rrc = RC.nrrrc[inst];
|
|
// LOG_I(GNB_APP,"Configuring MAC/L1 %d, carrier->sib2 %p\n", inst, &carrier->sib2->radioResourceConfigCommon);
|
|
LOG_I(GNB_APP,"Configuring gNB DU MAC/L1 %d \n", inst);
|
|
rrc_mac_config_req_gNB(rrc->module_id,
|
|
rrc->configuration.ssb_SubcarrierOffset,
|
|
rrc->configuration.pdsch_AntennaPorts,
|
|
rrc->configuration.pusch_AntennaPorts,
|
|
rrc->configuration.sib1_tda,
|
|
rrc->configuration.scc,
|
|
0,
|
|
0, // rnti
|
|
(NR_CellGroupConfig_t *)NULL
|
|
);
|
|
}
|
|
|
|
|
|
int gNB_app_handle_f1ap_setup_resp(f1ap_setup_resp_t *resp) {
|
|
int i, j, si_ind;
|
|
int ret=0;
|
|
LOG_I(GNB_APP, "cells_to_activate %d, RRC instances %d\n",
|
|
resp->num_cells_to_activate, RC.nb_nr_inst);
|
|
|
|
for (j = 0; j < resp->num_cells_to_activate; j++) {
|
|
for (i = 0; i < RC.nb_nr_inst; i++) {
|
|
rrc_gNB_carrier_data_t *carrier = &RC.nrrrc[i]->carrier;
|
|
// identify local index of cell j by nr_cellid, plmn identity and physical cell ID
|
|
LOG_I(GNB_APP, "Checking cell %d, rrc inst %d : rrc->nr_cellid %lx, resp->nr_cellid %lx\n",
|
|
j, i, RC.nrrrc[i]->nr_cellid, resp->cells_to_activate[j].nr_cellid);
|
|
|
|
if (RC.nrrrc[i]->nr_cellid == resp->cells_to_activate[j].nr_cellid &&
|
|
(du_check_plmn_identity(carrier, resp->cells_to_activate[j].mcc, resp->cells_to_activate[j].mnc, resp->cells_to_activate[j].mnc_digit_length)>0 &&
|
|
resp->cells_to_activate[j].nrpci == carrier->physCellId)) {
|
|
// copy system information and decode it
|
|
for (si_ind=0; si_ind<resp->cells_to_activate[j].num_SI; si_ind++) {
|
|
|
|
du_extract_and_decode_SI(i,
|
|
si_ind,
|
|
resp->cells_to_activate[j].SI_container[2+si_ind],
|
|
resp->cells_to_activate[j].SI_container_length[2+si_ind]);
|
|
}
|
|
|
|
// perform MAC/L1 common configuration
|
|
configure_gnb_du_mac(i);
|
|
ret++;
|
|
} else {
|
|
LOG_E(GNB_APP, "F1 Setup Response not matching\n");
|
|
}
|
|
}
|
|
}
|
|
return(ret);
|
|
}
|
|
|
|
int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_update_t *gnb_cu_cfg_update) {
|
|
int i, j, si_ind, 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);
|
|
|
|
for (j = 0; j < gnb_cu_cfg_update->num_cells_to_activate; j++) {
|
|
for (i = 0; i < RC.nb_nr_inst; i++) {
|
|
rrc_gNB_carrier_data_t *carrier = &RC.nrrrc[i]->carrier;
|
|
// identify local index of cell j by nr_cellid, plmn identity and physical cell ID
|
|
LOG_I(GNB_APP, "Checking cell %d, rrc inst %d : rrc->nr_cellid %lx, gnb_cu_cfg_updatenr_cellid %lx\n",
|
|
j, i, RC.nrrrc[i]->nr_cellid, gnb_cu_cfg_update->cells_to_activate[j].nr_cellid);
|
|
|
|
if (RC.nrrrc[i]->nr_cellid == gnb_cu_cfg_update->cells_to_activate[j].nr_cellid &&
|
|
(du_check_plmn_identity(carrier, gnb_cu_cfg_update->cells_to_activate[j].mcc, gnb_cu_cfg_update->cells_to_activate[j].mnc, gnb_cu_cfg_update->cells_to_activate[j].mnc_digit_length)>0 &&
|
|
gnb_cu_cfg_update->cells_to_activate[j].nrpci == carrier->physCellId)) {
|
|
// copy system information and decode it
|
|
for (si_ind=0; si_ind<gnb_cu_cfg_update->cells_to_activate[j].num_SI; si_ind++) {
|
|
|
|
du_extract_and_decode_SI(i,
|
|
si_ind,
|
|
gnb_cu_cfg_update->cells_to_activate[j].SI_container[2+si_ind],
|
|
gnb_cu_cfg_update->cells_to_activate[j].SI_container_length[2+si_ind]);
|
|
}
|
|
|
|
// perform MAC/L1 common configuration
|
|
configure_gnb_du_mac(i);
|
|
ret++;
|
|
} else {
|
|
LOG_E(GNB_APP, "GNB_CU_CONFIGURATION_UPDATE not matching\n");
|
|
}
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
|
|
void set_node_type(void) {
|
|
int j;
|
|
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};
|
|
|
|
config_getlist( &MacRLC_ParamList,MacRLC_Params,sizeof(MacRLC_Params)/sizeof(paramdef_t), NULL);
|
|
config_getlist( &GNBParamList,GNBParams,sizeof(GNBParams)/sizeof(paramdef_t),NULL);
|
|
|
|
if ( MacRLC_ParamList.numelt > 0) {
|
|
RC.nb_nr_macrlc_inst = MacRLC_ParamList.numelt;
|
|
for (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) {
|
|
node_type = ngran_gNB_CU;
|
|
} else {
|
|
if (macrlc_has_f1 == 0) {
|
|
node_type = ngran_gNB;
|
|
LOG_I(NR_RRC,"Setting node_type to ngran_gNB\n");
|
|
} else {
|
|
node_type = ngran_gNB_DU;
|
|
LOG_I(NR_RRC,"Setting node_type to ngran_gNB_DU\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
void nr_read_config_and_init(void) {
|
|
MessageDef *msg_p = NULL;
|
|
uint32_t gnb_id;
|
|
uint32_t gnb_nb = RC.nb_nr_inst;
|
|
|
|
RCconfig_NR_L1();
|
|
set_node_type();
|
|
RCconfig_nr_macrlc();
|
|
|
|
LOG_I(PHY, "%s() RC.nb_nr_L1_inst:%d\n", __FUNCTION__, RC.nb_nr_L1_inst);
|
|
|
|
if (RC.nb_nr_L1_inst>0) AssertFatal(l1_north_init_gNB()==0,"could not initialize L1 north interface\n");
|
|
|
|
AssertFatal (gnb_nb <= RC.nb_nr_inst,
|
|
"Number of gNB is greater than gNB defined in configuration file (%d/%d)!",
|
|
gnb_nb, RC.nb_nr_inst);
|
|
|
|
LOG_I(GNB_APP,"Allocating gNB_RRC_INST for %d instances\n",RC.nb_nr_inst);
|
|
|
|
RC.nrrrc = (gNB_RRC_INST **)malloc(RC.nb_nr_inst*sizeof(gNB_RRC_INST *));
|
|
LOG_I(PHY, "%s() RC.nb_nr_inst:%d RC.nrrrc:%p\n", __FUNCTION__, RC.nb_nr_inst, RC.nrrrc);
|
|
|
|
for (gnb_id = 0; gnb_id < RC.nb_nr_inst ; gnb_id++) {
|
|
RC.nrrrc[gnb_id] = (gNB_RRC_INST*)malloc(sizeof(gNB_RRC_INST));
|
|
LOG_I(PHY, "%s() Creating RRC instance RC.nrrrc[%d]:%p (%d of %d)\n", __FUNCTION__, gnb_id, RC.nrrrc[gnb_id], gnb_id+1, RC.nb_nr_inst);
|
|
memset((void *)RC.nrrrc[gnb_id],0,sizeof(gNB_RRC_INST));
|
|
msg_p = itti_alloc_new_message (TASK_GNB_APP, 0, NRRRC_CONFIGURATION_REQ);
|
|
RCconfig_NRRRC(msg_p,gnb_id, RC.nrrrc[gnb_id]);
|
|
}
|
|
|
|
if (NODE_IS_CU(RC.nrrrc[0]->node_type)) {
|
|
pdcp_layer_init();
|
|
// nr_DRB_preconfiguration(0x1234);
|
|
rrc_init_nr_global_param();
|
|
}
|
|
}
|