From 952a216b92433e06c3c725263e187fd51799241c Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Mon, 2 May 2022 11:37:19 +0100 Subject: [PATCH 01/60] Remove sib1_tda from configuration files to use default value --- targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf | 1 - targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf | 1 - .../CONF/gnb.band78.tm1.106PRB.usrpn300.gtp-itti.conf | 1 - .../GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf | 1 - .../GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.106PRB.usrpn300.conf | 1 - .../CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf | 1 - .../GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf | 1 - 7 files changed, 7 deletions(-) diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf index c07a0db649..92d1ce432c 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/cu_gnb.conf @@ -48,7 +48,6 @@ gNBs = pdsch_AntennaPorts = 1; pusch_AntennaPorts = 1; min_rxtxtime = 6; - sib1_tda = 0; pdcch_ConfigSIB1 = ( { diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf index 256d724f3f..f95bdf91ae 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/du_gnb.conf @@ -38,7 +38,6 @@ gNBs = ssb_SubcarrierOffset = 0; min_rxtxtime = 6; - sib1_tda = 0; pdcch_ConfigSIB1 = ( { diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.tm1.106PRB.usrpn300.gtp-itti.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.tm1.106PRB.usrpn300.gtp-itti.conf index 726e43d7ad..74f6c34f57 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.tm1.106PRB.usrpn300.gtp-itti.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.band78.tm1.106PRB.usrpn300.gtp-itti.conf @@ -37,7 +37,6 @@ gNBs = ////////// Physical parameters: ssb_SubcarrierOffset = 0; - sib1_tda = 0; servingCellConfigCommon = ( { #spCellConfigCommon diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf index 7e2db64aaa..d124c5692f 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf @@ -34,7 +34,6 @@ gNBs = ssb_SubcarrierOffset = 0; min_rxtxtime = 6; - sib1_tda = 0; do_SRS = 1; pdcch_ConfigSIB1 = ( diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.106PRB.usrpn300.conf index cab801525b..ff64fe718a 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.106PRB.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.106PRB.usrpn300.conf @@ -36,7 +36,6 @@ gNBs = pdsch_AntennaPorts = 1; pusch_AntennaPorts = 1; min_rxtxtime = 6; - sib1_tda = 0; pdcch_ConfigSIB1 = ( { diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf index 950e9c1d38..1bc6de3bfe 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf @@ -35,7 +35,6 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts_N1 = 2; pusch_AntennaPorts = 2; - sib1_tda = 0; do_SRS = 1; ul_prbblacklist = "51,52,53,54" diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index 1dc903b811..a0cee6f9ca 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -34,7 +34,6 @@ gNBs = ssb_SubcarrierOffset = 0; min_rxtxtime = 6; - sib1_tda = 0; pdcch_ConfigSIB1 = ( { From 39ea2c936fd16f551cc7a32d5c3c0aaa73b82084 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Wed, 4 May 2022 15:05:23 +0100 Subject: [PATCH 02/60] Creation of config_srs() function --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 123 +++------------------------- openair2/RRC/NR/nr_rrc_config.c | 107 +++++++++++++++++++++++- openair2/RRC/NR/nr_rrc_config.h | 4 + 3 files changed, 121 insertions(+), 113 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 9252a23596..c0676814f7 100755 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -395,7 +395,6 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier, NR_BWP_DownlinkCommon_t *initialDownlinkBWP=&ServCellCom->downlinkConfigCommon.initialDownlinkBWP; initialDownlinkBWP->genericParameters= configuration->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; - for(int i = 0; i< configuration->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.count; i++) { asn1cSequenceAdd(ServCellCom->downlinkConfigCommon.frequencyInfoDL.frequencyBandList.list, @@ -403,7 +402,6 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier, nrMultiBandInfo->freqBandIndicatorNR = configuration->scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[i]; } - int scs_scaling0 = 1<<(configuration->scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing); int scs_scaling = scs_scaling0; int scs_scaling2 = scs_scaling0; @@ -512,7 +510,6 @@ uint8_t do_SIB1_NR(rrc_gNB_carrier_data_t *carrier, ss7->searchSpaceType->choice.common=calloc(1,sizeof(*ss7->searchSpaceType->choice.common)); ss7->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0 = calloc(1,sizeof(*ss7->searchSpaceType->choice.common->dci_Format0_0_AndFormat1_0)); - asn1cCallocOne(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1, 0); asn1cCallocOne(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation, 7); asn1cCallocOne(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->pagingSearchSpace, 5); @@ -980,36 +977,11 @@ uint8_t do_RRCReject(uint8_t Mod_id, return((enc_rval.encoded+7)/8); } -// TODO: Implement to b_SRS = 1 and b_SRS = 2 -long rrc_get_max_nr_csrs(uint8_t max_rbs, long b_SRS) { - - if(b_SRS>0) { - LOG_E(NR_RRC,"rrc_get_max_nr_csrs(): Not implemented yet for b_SRS>0\n"); - return 0; // This c_srs is always valid - } - - const uint16_t m_SRS[64] = { 4, 8, 12, 16, 16, 20, 24, 24, 28, 32, 36, 40, 48, 48, 52, 56, 60, 64, 72, 72, 76, 80, 88, - 96, 96, 104, 112, 120, 120, 120, 128, 128, 128, 132, 136, 144, 144, 144, 144, 152, 160, - 160, 160, 168, 176, 184, 192, 192, 192, 192, 208, 216, 224, 240, 240, 240, 240, 256, 256, - 256, 264, 272, 272, 272 }; - - long c_srs = 0; - uint16_t m = 4; - for(int c = 1; c<64; c++) { - if(m_SRS[c]>m && m_SRS[c]tp_pi2BPSK=NULL; initialUplinkBWP->srs_Config = calloc(1,sizeof(*initialUplinkBWP->srs_Config)); - initialUplinkBWP->srs_Config->present = NR_SetupRelease_SRS_Config_PR_setup; - NR_SRS_Config_t *srs_Config = calloc(1,sizeof(*srs_Config)); - initialUplinkBWP->srs_Config->choice.setup=srs_Config; - srs_Config->srs_ResourceSetToReleaseList=NULL; - srs_Config->srs_ResourceSetToAddModList=calloc(1,sizeof(*srs_Config->srs_ResourceSetToAddModList)); - NR_SRS_ResourceSet_t *srs_resset0=calloc(1,sizeof(*srs_resset0)); - srs_resset0->srs_ResourceSetId = 0; - srs_resset0->srs_ResourceIdList=calloc(1,sizeof(*srs_resset0->srs_ResourceIdList)); - NR_SRS_ResourceId_t *srs_resset0_id=calloc(1,sizeof(*srs_resset0_id)); - *srs_resset0_id=0; - ASN_SEQUENCE_ADD(&srs_resset0->srs_ResourceIdList->list,srs_resset0_id); - srs_Config->srs_ResourceToReleaseList=NULL; - - if (configuration->do_SRS) { - srs_resset0->resourceType.present = NR_SRS_ResourceSet__resourceType_PR_periodic; - srs_resset0->resourceType.choice.periodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.periodic)); - srs_resset0->resourceType.choice.periodic->associatedCSI_RS = NULL; - } else { - srs_resset0->resourceType.present = NR_SRS_ResourceSet__resourceType_PR_aperiodic; - srs_resset0->resourceType.choice.aperiodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic)); - srs_resset0->resourceType.choice.aperiodic->aperiodicSRS_ResourceTrigger=1; - srs_resset0->resourceType.choice.aperiodic->csi_RS=NULL; - srs_resset0->resourceType.choice.aperiodic->slotOffset= calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic->slotOffset)); - *srs_resset0->resourceType.choice.aperiodic->slotOffset=2; - srs_resset0->resourceType.choice.aperiodic->ext1=NULL; - } - - srs_resset0->usage=NR_SRS_ResourceSet__usage_codebook; - srs_resset0->alpha = calloc(1,sizeof(*srs_resset0->alpha)); - *srs_resset0->alpha = NR_Alpha_alpha1; - srs_resset0->p0=calloc(1,sizeof(*srs_resset0->p0)); - *srs_resset0->p0=-80; - srs_resset0->pathlossReferenceRS=NULL; - srs_resset0->srs_PowerControlAdjustmentStates=NULL; - ASN_SEQUENCE_ADD(&srs_Config->srs_ResourceSetToAddModList->list,srs_resset0); - srs_Config->srs_ResourceToReleaseList=NULL; - srs_Config->srs_ResourceToAddModList=calloc(1,sizeof(*srs_Config->srs_ResourceToAddModList)); - NR_SRS_Resource_t *srs_res0=calloc(1,sizeof(*srs_res0)); - srs_res0->srs_ResourceId=0; - srs_res0->nrofSRS_Ports=NR_SRS_Resource__nrofSRS_Ports_port1; - srs_res0->ptrs_PortIndex=NULL; - srs_res0->transmissionComb.present=NR_SRS_Resource__transmissionComb_PR_n2; - srs_res0->transmissionComb.choice.n2=calloc(1,sizeof(*srs_res0->transmissionComb.choice.n2)); - srs_res0->transmissionComb.choice.n2->combOffset_n2=0; - srs_res0->transmissionComb.choice.n2->cyclicShift_n2=0; - srs_res0->resourceMapping.startPosition = 2 + uid%2; - srs_res0->resourceMapping.nrofSymbols=NR_SRS_Resource__resourceMapping__nrofSymbols_n1; - srs_res0->resourceMapping.repetitionFactor=NR_SRS_Resource__resourceMapping__repetitionFactor_n1; - srs_res0->freqDomainPosition=0; - srs_res0->freqDomainShift=0; - srs_res0->freqHopping.b_SRS=0; - srs_res0->freqHopping.b_hop=0; - srs_res0->freqHopping.c_SRS = rrc_get_max_nr_csrs( - NRRIV2BW(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, 275), - srs_res0->freqHopping.b_SRS); - srs_res0->groupOrSequenceHopping=NR_SRS_Resource__groupOrSequenceHopping_neither; - - if (configuration->do_SRS) { - srs_res0->resourceType.present= NR_SRS_Resource__resourceType_PR_periodic; - srs_res0->resourceType.choice.periodic=calloc(1,sizeof(*srs_res0->resourceType.choice.periodic)); - srs_res0->resourceType.choice.periodic->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl160; - srs_res0->resourceType.choice.periodic->periodicityAndOffset_p.choice.sl160 = 17 + (uid>1)*10; // 17/17/.../147/157 are mixed slots - } else { - srs_res0->resourceType.present= NR_SRS_Resource__resourceType_PR_aperiodic; - srs_res0->resourceType.choice.aperiodic=calloc(1,sizeof(*srs_res0->resourceType.choice.aperiodic)); - } - - srs_res0->sequenceId=40; - srs_res0->spatialRelationInfo=calloc(1,sizeof(*srs_res0->spatialRelationInfo)); - srs_res0->spatialRelationInfo->servingCellId=NULL; - srs_res0->spatialRelationInfo->referenceSignal.present=NR_SRS_SpatialRelationInfo__referenceSignal_PR_csi_RS_Index; - srs_res0->spatialRelationInfo->referenceSignal.choice.csi_RS_Index=0; - ASN_SEQUENCE_ADD(&srs_Config->srs_ResourceToAddModList->list,srs_res0); + config_srs(initialUplinkBWP->srs_Config, scc, uid, configuration->do_SRS); // configure Scheduling request // 40 slot period @@ -1325,13 +1225,13 @@ void fill_initial_SpCellConfig(int uid, bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->maxLength=NULL; bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = calloc(1,sizeof(*bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition)); - *bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos1; - bwp_Dedicated->pdsch_Config->choice.setup->resourceAllocation = NR_PDSCH_Config__resourceAllocation_resourceAllocationType1; - bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.present = NR_PDSCH_Config__prb_BundlingType_PR_staticBundling; - bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling = calloc(1,sizeof(*bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling)); - bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling->bundleSize = - calloc(1,sizeof(*bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling->bundleSize)); - *bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling->bundleSize = NR_PDSCH_Config__prb_BundlingType__staticBundling__bundleSize_wideband; + *bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos1; + bwp_Dedicated->pdsch_Config->choice.setup->resourceAllocation = NR_PDSCH_Config__resourceAllocation_resourceAllocationType1; + bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.present = NR_PDSCH_Config__prb_BundlingType_PR_staticBundling; + bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling = calloc(1,sizeof(*bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling)); + bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling->bundleSize = + calloc(1,sizeof(*bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling->bundleSize)); + *bwp_Dedicated->pdsch_Config->choice.setup->prb_BundlingType.choice.staticBundling->bundleSize = NR_PDSCH_Config__prb_BundlingType__staticBundling__bundleSize_wideband; bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList=calloc(1,sizeof(*bwp_Dedicated->pdsch_Config->choice.setup->tci_StatesToAddModList)); NR_TCI_State_t *tcic; @@ -1351,6 +1251,7 @@ void fill_initial_SpCellConfig(int uid, NR_PDSCH_ServingCellConfig_t *pdsch_servingcellconfig = calloc(1,sizeof(*pdsch_servingcellconfig)); SpCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->present = NR_SetupRelease_PDSCH_ServingCellConfig_PR_setup; SpCellConfig->spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup = pdsch_servingcellconfig; + pdsch_servingcellconfig->codeBlockGroupTransmission = NULL; pdsch_servingcellconfig->xOverhead = NULL; pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH = calloc(1, sizeof(*pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH)); @@ -1452,7 +1353,6 @@ void fill_mastercellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, NR_CellGr ASN_SEQUENCE_ADD(&ue_context_mastercellGroup->rlc_BearerToAddModList->list, rlc_BearerConfig_drb); } - void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, NR_UE_NR_Capability_t *uecap, const gNB_RrcConfigurationReq* configuration) { @@ -1476,7 +1376,6 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, } } - void fill_initial_cellGroupConfig(int uid, NR_CellGroupConfig_t *cellGroupConfig, NR_ServingCellConfigCommon_t *scc, diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 54fb5a168b..5bcdf86a95 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -81,7 +81,6 @@ void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0, int uid, int nb_sl } } - void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon, NR_CSI_MeasConfig_t *csi_MeasConfig, int uid, @@ -170,6 +169,112 @@ void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon, csi_MeasConfig->nzp_CSI_RS_ResourceToReleaseList = NULL; } +// TODO: Implement to b_SRS = 1 and b_SRS = 2 +long rrc_get_max_nr_csrs(uint8_t max_rbs, long b_SRS) { + + if(b_SRS>0) { + LOG_E(NR_RRC,"rrc_get_max_nr_csrs(): Not implemented yet for b_SRS>0\n"); + return 0; // This c_srs is always valid + } + + const uint16_t m_SRS[64] = { 4, 8, 12, 16, 16, 20, 24, 24, 28, 32, 36, 40, 48, 48, 52, 56, 60, 64, 72, 72, 76, 80, 88, + 96, 96, 104, 112, 120, 120, 120, 128, 128, 128, 132, 136, 144, 144, 144, 144, 152, 160, + 160, 160, 168, 176, 184, 192, 192, 192, 192, 208, 216, 224, 240, 240, 240, 240, 256, 256, + 256, 264, 272, 272, 272 }; + + long c_srs = 0; + uint16_t m = 4; + for(int c = 1; c<64; c++) { + if(m_SRS[c]>m && m_SRS[c]present = NR_SetupRelease_SRS_Config_PR_setup; + setup_release_srs_Config->choice.setup = calloc(1,sizeof(*setup_release_srs_Config->choice.setup)); + + NR_SRS_Config_t *srs_Config = setup_release_srs_Config->choice.setup; + + srs_Config->srs_ResourceSetToReleaseList = NULL; + + srs_Config->srs_ResourceSetToAddModList = calloc(1,sizeof(*srs_Config->srs_ResourceSetToAddModList)); + NR_SRS_ResourceSet_t *srs_resset0 = calloc(1,sizeof(*srs_resset0)); + srs_resset0->srs_ResourceSetId = 0; + srs_resset0->srs_ResourceIdList = calloc(1,sizeof(*srs_resset0->srs_ResourceIdList)); + NR_SRS_ResourceId_t *srs_resset0_id = calloc(1,sizeof(*srs_resset0_id)); + *srs_resset0_id = 0; + ASN_SEQUENCE_ADD(&srs_resset0->srs_ResourceIdList->list, srs_resset0_id); + srs_Config->srs_ResourceToReleaseList=NULL; + if (do_srs) { + srs_resset0->resourceType.present = NR_SRS_ResourceSet__resourceType_PR_periodic; + srs_resset0->resourceType.choice.periodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.periodic)); + srs_resset0->resourceType.choice.periodic->associatedCSI_RS = NULL; + } else { + srs_resset0->resourceType.present = NR_SRS_ResourceSet__resourceType_PR_aperiodic; + srs_resset0->resourceType.choice.aperiodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic)); + srs_resset0->resourceType.choice.aperiodic->aperiodicSRS_ResourceTrigger=1; + srs_resset0->resourceType.choice.aperiodic->csi_RS=NULL; + srs_resset0->resourceType.choice.aperiodic->slotOffset = calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic->slotOffset)); + *srs_resset0->resourceType.choice.aperiodic->slotOffset = 2; + srs_resset0->resourceType.choice.aperiodic->ext1 = NULL; + } + srs_resset0->usage=NR_SRS_ResourceSet__usage_codebook; + srs_resset0->alpha = calloc(1,sizeof(*srs_resset0->alpha)); + *srs_resset0->alpha = NR_Alpha_alpha1; + srs_resset0->p0 = calloc(1,sizeof(*srs_resset0->p0)); + *srs_resset0->p0 =-80; + srs_resset0->pathlossReferenceRS = NULL; + srs_resset0->srs_PowerControlAdjustmentStates = NULL; + ASN_SEQUENCE_ADD(&srs_Config->srs_ResourceSetToAddModList->list,srs_resset0); + + srs_Config->srs_ResourceToReleaseList = NULL; + + srs_Config->srs_ResourceToAddModList = calloc(1,sizeof(*srs_Config->srs_ResourceToAddModList)); + NR_SRS_Resource_t *srs_res0=calloc(1,sizeof(*srs_res0)); + srs_res0->srs_ResourceId = 0; + srs_res0->nrofSRS_Ports = NR_SRS_Resource__nrofSRS_Ports_port1; + srs_res0->ptrs_PortIndex = NULL; + srs_res0->transmissionComb.present = NR_SRS_Resource__transmissionComb_PR_n2; + srs_res0->transmissionComb.choice.n2 = calloc(1,sizeof(*srs_res0->transmissionComb.choice.n2)); + srs_res0->transmissionComb.choice.n2->combOffset_n2 = 0; + srs_res0->transmissionComb.choice.n2->cyclicShift_n2 = 0; + srs_res0->resourceMapping.startPosition = 2 + uid%2; + srs_res0->resourceMapping.nrofSymbols = NR_SRS_Resource__resourceMapping__nrofSymbols_n1; + srs_res0->resourceMapping.repetitionFactor = NR_SRS_Resource__resourceMapping__repetitionFactor_n1; + srs_res0->freqDomainPosition = 0; + srs_res0->freqDomainShift = 0; + srs_res0->freqHopping.b_SRS = 0; + srs_res0->freqHopping.b_hop = 0; + srs_res0->freqHopping.c_SRS = rrc_get_max_nr_csrs( + NRRIV2BW(servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, 275), + srs_res0->freqHopping.b_SRS); + srs_res0->groupOrSequenceHopping = NR_SRS_Resource__groupOrSequenceHopping_neither; + if (do_srs) { + srs_res0->resourceType.present = NR_SRS_Resource__resourceType_PR_periodic; + srs_res0->resourceType.choice.periodic = calloc(1,sizeof(*srs_res0->resourceType.choice.periodic)); + srs_res0->resourceType.choice.periodic->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl160; + srs_res0->resourceType.choice.periodic->periodicityAndOffset_p.choice.sl160 = 17 + (uid>1)*10; // 17/17/.../147/157 are mixed slots + } else { + srs_res0->resourceType.present = NR_SRS_Resource__resourceType_PR_aperiodic; + srs_res0->resourceType.choice.aperiodic = calloc(1,sizeof(*srs_res0->resourceType.choice.aperiodic)); + } + srs_res0->sequenceId = 40; + srs_res0->spatialRelationInfo = calloc(1,sizeof(*srs_res0->spatialRelationInfo)); + srs_res0->spatialRelationInfo->servingCellId = NULL; + srs_res0->spatialRelationInfo->referenceSignal.present = NR_SRS_SpatialRelationInfo__referenceSignal_PR_csi_RS_Index; + srs_res0->spatialRelationInfo->referenceSignal.choice.csi_RS_Index = 0; + ASN_SEQUENCE_ADD(&srs_Config->srs_ResourceToAddModList->list,srs_res0); +} + void prepare_sim_uecap(NR_UE_NR_Capability_t *cap, NR_ServingCellConfigCommon_t *scc, int numerology, diff --git a/openair2/RRC/NR/nr_rrc_config.h b/openair2/RRC/NR/nr_rrc_config.h index 7a0fe892fd..ff71f73333 100644 --- a/openair2/RRC/NR/nr_rrc_config.h +++ b/openair2/RRC/NR/nr_rrc_config.h @@ -119,6 +119,10 @@ void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon, int num_dl_antenna_ports, int curr_bwp, int do_csirs); +void config_srs(NR_SetupRelease_SRS_Config_t *setup_release_srs_Config, + NR_ServingCellConfigCommon_t *servingcellconfigcommon, + int uid, + int do_srs); void set_dl_mcs_table(int scs, NR_UE_NR_Capability_t *cap, NR_BWP_DownlinkDedicated_t *bwp_Dedicated, NR_ServingCellConfigCommon_t *scc); From 70cfd057ec317f6d3cc7b791e1f6156f2ea10ebb Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Wed, 4 May 2022 15:09:59 +0100 Subject: [PATCH 03/60] Add do_SRS flag in gnb.sa.band78.fr1.106PRB.usrpb210.conf --- .../GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index a0cee6f9ca..22f02f66e4 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -34,6 +34,7 @@ gNBs = ssb_SubcarrierOffset = 0; min_rxtxtime = 6; + do_SRS = 1; pdcch_ConfigSIB1 = ( { From 2fb8d96f1153bc229668e127218e01872de32d14 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Wed, 4 May 2022 16:25:15 +0100 Subject: [PATCH 04/60] Move SRS config to update_cellGroupConfig() --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 21 ++++++++++++++++++++- openair2/RRC/NR/MESSAGES/asn1_msg.h | 1 + openair2/RRC/NR/nr_rrc_config.c | 29 ++++++++++++++++++++++++----- 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index c0676814f7..3e38c772da 100755 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -1098,8 +1098,9 @@ void fill_initial_SpCellConfig(int uid, pusch_Config->uci_OnPUSCH=NULL; pusch_Config->tp_pi2BPSK=NULL; + // We are using do_srs = 0 here because the periodic SRS will only be enabled in update_cellGroupConfig() if do_srs == 1 initialUplinkBWP->srs_Config = calloc(1,sizeof(*initialUplinkBWP->srs_Config)); - config_srs(initialUplinkBWP->srs_Config, scc, uid, configuration->do_SRS); + config_srs(initialUplinkBWP->srs_Config, scc, uid, 0); // configure Scheduling request // 40 slot period @@ -1354,6 +1355,7 @@ void fill_mastercellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, NR_CellGr } void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, + int uid, NR_UE_NR_Capability_t *uecap, const gNB_RrcConfigurationReq* configuration) { @@ -1362,6 +1364,22 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, NR_ServingCellConfigCommon_t *scc = configuration->scc; + if (configuration && + configuration->do_SRS && + SpCellConfig && + SpCellConfig->spCellConfigDedicated && + SpCellConfig->spCellConfigDedicated->uplinkConfig && + SpCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) { + if (!SpCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->srs_Config) { + SpCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->srs_Config = + calloc(1,sizeof(*SpCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->srs_Config)); + } + config_srs(SpCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->srs_Config, + scc, + uid, + configuration->do_SRS); + } + NR_BWP_DownlinkDedicated_t *bwp_Dedicated = SpCellConfig->spCellConfigDedicated->initialDownlinkBWP; set_dl_mcs_table(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.subcarrierSpacing, configuration->force_256qam_off ? NULL : uecap, bwp_Dedicated, scc); @@ -1850,6 +1868,7 @@ int16_t do_RRCReconfiguration( if(cellGroupConfig!=NULL){ update_cellGroupConfig(cellGroupConfig, + ue_context_pP->local_uid, ue_context_pP->ue_context.UE_Capability_nr, configuration); diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index aeef5f93a7..f056088da8 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -112,6 +112,7 @@ void fill_initial_cellGroupConfig(int uid, const gNB_RrcConfigurationReq *configuration); void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, + int uid, NR_UE_NR_Capability_t *uecap, const gNB_RrcConfigurationReq *configuration); diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 5bcdf86a95..2e44a8022e 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -200,9 +200,27 @@ void config_srs(NR_SetupRelease_SRS_Config_t *setup_release_srs_Config, int do_srs) { setup_release_srs_Config->present = NR_SetupRelease_SRS_Config_PR_setup; - setup_release_srs_Config->choice.setup = calloc(1,sizeof(*setup_release_srs_Config->choice.setup)); - NR_SRS_Config_t *srs_Config = setup_release_srs_Config->choice.setup; + NR_SRS_Config_t *srs_Config; + if (setup_release_srs_Config->choice.setup) { + srs_Config = setup_release_srs_Config->choice.setup; + if (srs_Config->srs_ResourceSetToReleaseList) { + free(srs_Config->srs_ResourceSetToReleaseList); + } + if (srs_Config->srs_ResourceSetToAddModList) { + free(srs_Config->srs_ResourceSetToAddModList); + } + if (srs_Config->srs_ResourceToReleaseList) { + free(srs_Config->srs_ResourceToReleaseList); + } + if (srs_Config->srs_ResourceToAddModList) { + free(srs_Config->srs_ResourceToAddModList); + } + free(srs_Config); + } + + setup_release_srs_Config->choice.setup = calloc(1,sizeof(*setup_release_srs_Config->choice.setup)); + srs_Config = setup_release_srs_Config->choice.setup; srs_Config->srs_ResourceSetToReleaseList = NULL; @@ -254,9 +272,10 @@ void config_srs(NR_SetupRelease_SRS_Config_t *setup_release_srs_Config, srs_res0->freqDomainShift = 0; srs_res0->freqHopping.b_SRS = 0; srs_res0->freqHopping.b_hop = 0; - srs_res0->freqHopping.c_SRS = rrc_get_max_nr_csrs( - NRRIV2BW(servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, 275), - srs_res0->freqHopping.b_SRS); + srs_res0->freqHopping.c_SRS = servingcellconfigcommon ? + rrc_get_max_nr_csrs( + NRRIV2BW(servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, 275), + srs_res0->freqHopping.b_SRS) : 0; srs_res0->groupOrSequenceHopping = NR_SRS_Resource__groupOrSequenceHopping_neither; if (do_srs) { srs_res0->resourceType.present = NR_SRS_Resource__resourceType_PR_periodic; From b106913dc0c72a8c276067892e95e81ba6269956 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Thu, 5 May 2022 18:10:08 +0100 Subject: [PATCH 05/60] Send SRS measurements (still empty) from PHY to MAC --- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 13 +++++++ .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 12 +++++++ openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 12 ++++++- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 36 +++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 46816d0373..c071127717 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -829,6 +829,19 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { T(T_GNB_PHY_UL_TIME_CHANNEL_ESTIMATE, T_INT(0), T_INT(srs_pdu->rnti), T_INT(frame_rx), T_INT(0), T_INT(0), T_BUFFER(gNB->nr_srs_info[i]->srs_estimated_channel_time_shifted[0], gNB->frame_parms.ofdm_symbol_size*sizeof(int32_t))); + uint16_t num_srs = gNB->UL_INFO.srs_ind.number_of_pdus; + gNB->UL_INFO.srs_ind.pdu_list = &gNB->srs_pdu_list[0]; + gNB->UL_INFO.srs_ind.sfn = frame_rx; + gNB->UL_INFO.srs_ind.slot = slot_rx; + //gNB->srs_pdu_list[num_srs].handle; + gNB->srs_pdu_list[num_srs].rnti = srs_pdu->rnti; + //gNB->srs_pdu_list[num_srs].timing_advance; + gNB->srs_pdu_list[num_srs].num_symbols = 1<num_symbols; + //gNB->srs_pdu_list[num_srs].wide_band_snr; + //gNB->srs_pdu_list[num_srs].num_reported_symbols; + //gNB->srs_pdu_list[num_srs].reported_symbol_list; + gNB->UL_INFO.srs_ind.number_of_pdus += 1; + srs->active = 0; } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 72061bb9ba..b3a241af0b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -879,6 +879,18 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, } } +void handle_nr_srs_measurements(const module_id_t module_id, + const frame_t frame, + const sub_frame_t slot, + const rnti_t rnti, + const uint16_t timing_advance, + const uint8_t num_symbols, + const uint8_t wide_band_snr, + const uint8_t num_reported_symbols, + nfapi_nr_srs_indication_reported_symbol_t* reported_symbol_list) { + LOG_I(NR_MAC, "(%d.%d) Received SRS indication for rnti: 0x%04x\n", frame, slot, rnti); +} + long get_K2(NR_ServingCellConfigCommon_t *scc, NR_ServingCellConfigCommonSIB_t *scc_sib1, NR_BWP_Uplink_t *ubwp, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 399033abd0..9b299eb1a3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -482,9 +482,19 @@ void handle_nr_ul_harq(const int CC_idP, sub_frame_t slot, const nfapi_nr_crc_t *crc_pdu); +void handle_nr_srs_measurements(const module_id_t module_id, + const frame_t frame, + const sub_frame_t slot, + const rnti_t rnti, + const uint16_t timing_advance, + const uint8_t num_symbols, + const uint8_t wide_band_snr, + const uint8_t num_reported_symbols, + nfapi_nr_srs_indication_reported_symbol_t* reported_symbol_list); + int16_t ssb_index_from_prach(module_id_t module_idP, frame_t frameP, - sub_frame_t slotP, + sub_frame_t slotP, uint16_t preamble_index, uint8_t freq_index, uint8_t symbol); diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 2654988557..4b8edd526f 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -217,6 +217,41 @@ void handle_nr_ulsch(NR_UL_IND_t *UL_info) UL_info->crc_ind.number_crcs = 0; } +void handle_nr_srs(NR_UL_IND_t *UL_info) { + + if(NFAPI_MODE == NFAPI_MODE_PNF) { + if (UL_info->srs_ind.number_of_pdus > 0) { + LOG_D(PHY,"PNF Sending UL_info->srs_ind.number_of_pdus: %d, SFN/SF:%d.%d \n", + UL_info->srs_ind.number_of_pdus, UL_info->frame, UL_info->slot); + oai_nfapi_nr_srs_indication(&UL_info->srs_ind); + UL_info->srs_ind.number_of_pdus = 0; + } + return; + } + + const module_id_t module_id = UL_info->module_id; + const frame_t frame = UL_info->srs_ind.sfn; + const sub_frame_t slot = UL_info->srs_ind.slot; + int num_srs = UL_info->srs_ind.number_of_pdus; + nfapi_nr_srs_indication_pdu_t *srs_list = UL_info->srs_ind.pdu_list; + + for (int i = 0; i < num_srs; i++) { + const nfapi_nr_srs_indication_pdu_t *srs_ind = &srs_list[i]; + LOG_D(NR_PHY, "(%d.%d) UL_info->srs_ind.pdu_list[%d].rnti: 0x%04x\n", frame, slot, i, srs_ind->rnti); + handle_nr_srs_measurements(module_id, + frame, + slot, + srs_ind->rnti, + srs_ind->timing_advance, + srs_ind->num_symbols, + srs_ind->wide_band_snr, + srs_ind->num_reported_symbols, + srs_ind->reported_symbol_list); + } + + UL_info->srs_ind.number_of_pdus = 0; +} + static void free_unqueued_nfapi_indications(nfapi_nr_rach_indication_t *rach_ind, nfapi_nr_uci_indication_t *uci_ind, nfapi_nr_rx_data_indication_t *rx_ind, @@ -436,6 +471,7 @@ void NR_UL_indication(NR_UL_IND_t *UL_info) { // clear UL DCI prior to handling ULSCH mac->UL_dci_req[CC_id].numPdus = 0; handle_nr_ulsch(UL_info); + handle_nr_srs(UL_info); if (get_softmodem_params()->emulate_l1) { free_unqueued_nfapi_indications(rach_ind, uci_ind, rx_ind, crc_ind); From dce83a05089e225706fe8380ae924ae1bf8d3420 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Thu, 5 May 2022 19:49:06 +0100 Subject: [PATCH 06/60] Add comments in FAPI for SRS indication --- .../nfapi/public_inc/nfapi_nr_interface_scf.h | 47 ++++++++----------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index c3a173758c..0326bd20b1 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -1665,41 +1665,34 @@ typedef struct } nfapi_nr_uci_indication_t; -//3.4.10 srs_indication -//table 3-73 -typedef struct -{ - uint8_t rb_snr; -}nfapi_nr_srs_indication_reported_symbol_resource_block_t; +/// 5G PHY FAPI Specification: SRS indication - Section 3.4.10, Table 3-73 -typedef struct -{ - uint16_t num_rbs; +typedef struct { + uint8_t rb_snr; // SNR value in dB. Value: 0 -> 255 representing -64 dB to 63 dB with a step size 0.5 dB, 0xff will be set if this field is invalid. +} nfapi_nr_srs_indication_reported_symbol_resource_block_t; + +typedef struct { + uint16_t num_rbs; // Number of PRBs to be reported for this SRS PDU. Value: 0 -> 272. nfapi_nr_srs_indication_reported_symbol_resource_block_t* rb_list; -}nfapi_nr_srs_indication_reported_symbol_t; +} nfapi_nr_srs_indication_reported_symbol_t; -#define NFAPI_NR_SRS_IND_MAX_PDU 100 -typedef struct -{ - uint32_t handle; - uint16_t rnti; - uint16_t timing_advance; - uint8_t num_symbols; - uint8_t wide_band_snr; - uint8_t num_reported_symbols; +typedef struct { + uint32_t handle; // The handle passed to the PHY in the the UL_TTI.request SRS PDU. + uint16_t rnti; // The RNTI passed to the PHY in the UL_TTI.request SRS PDU. Value: 1 -> 65535. + uint16_t timing_advance; // Timing advance TA measured for the UE [TS 38.213, Section 4.2]. NTA_new = NTA_old + (TA − 31) * 16 * 64 / (2^u). Value: 0 -> 63. 0xffff should be set if this field is invalid. + uint8_t num_symbols; // Number of symbols for SRS. Value: 1 -> 4. If a PHY does not report for individual symbols then this parameter should be set to 1. + uint8_t wide_band_snr; // SNR value in dB measured within configured SRS bandwidth on each symbol. Value: 0 -> 255 representing -64 dB to 63 dB with a step size 0.5 dB. 0xff will be set if this field is invalid. + uint8_t num_reported_symbols; // Number of symbols reported in this message. This allows PHY to report individual symbols or aggregated symbols where this field will be set to 1. Value: 1 -> 4. nfapi_nr_srs_indication_reported_symbol_t* reported_symbol_list; +} nfapi_nr_srs_indication_pdu_t; -}nfapi_nr_srs_indication_pdu_t; - -typedef struct -{ +typedef struct { nfapi_p7_message_header_t header; - uint16_t sfn; - uint16_t slot; - uint8_t number_of_pdus; + uint16_t sfn; // SFN. Value: 0 -> 1023 + uint16_t slot; // Slot. Value: 0 -> 159 + uint8_t number_of_pdus; // Number of PDUs included in this message. Value: 0 -> 255 nfapi_nr_srs_indication_pdu_t* pdu_list; - } nfapi_nr_srs_indication_t; From dcf4fd1db2270e1780680712e905f964a83d44ee Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Fri, 6 May 2022 19:07:59 +0100 Subject: [PATCH 07/60] Compute the noise power per RB --- openair1/PHY/INIT/nr_init.c | 1 + .../NR_ESTIMATION/nr_ul_channel_estimation.c | 45 +++++++++++++++++++ openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 1 + openair1/PHY/defs_nr_common.h | 1 + openair1/SCHED_NR/phy_procedures_nr_gNB.c | 1 + 5 files changed, 49 insertions(+) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 9ffc0f75ad..64bbdfa487 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -618,6 +618,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, gNB->nr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t)); gNB->nr_srs_info[id]->sc_list = (uint16_t *) malloc16_clear(6*fp->N_RB_UL*sizeof(uint16_t)); gNB->nr_srs_info[id]->srs_generated_signal = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t)); + gNB->nr_srs_info[id]->noise_power_per_rb = (uint32_t*)malloc16_clear(fp->N_RB_UL*sizeof(uint32_t)); gNB->nr_srs_info[id]->noise_power = (uint32_t*)malloc16_clear(sizeof(uint32_t)); gNB->nr_srs_info[id]->srs_received_signal = (int32_t **)malloc16(Prx*sizeof(int32_t*)); gNB->nr_srs_info[id]->srs_ls_estimated_channel = (int32_t **)malloc16(Prx*sizeof(int32_t*)); diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 4a6f8ef9af..ffdf07860d 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -1099,6 +1099,7 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, int32_t **srs_estimated_channel_freq, int32_t **srs_estimated_channel_time, int32_t **srs_estimated_channel_time_shifted, + uint32_t *noise_power_per_rb, uint32_t *noise_power) { if(nr_srs_info->sc_list_length == 0) { @@ -1216,6 +1217,50 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, (gNB->frame_parms.ofdm_symbol_size>>1)*sizeof(int32_t)); } + // Compute noise power + + uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*12; + uint8_t srs_symbols_per_rb = srs_pdu->comb_size == 0 ? 6 : 3; + uint8_t n_noise_estimates = frame_parms->nb_antennas_rx*srs_symbols_per_rb; + uint8_t count_estimates = 0; + uint64_t sum_re = 0; + uint64_t sum_re2 = 0; + uint64_t sum_im = 0; + uint64_t sum_im2 = 0; + + for (int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) { + + int subcarrier0 = nr_srs_info->sc_list[sc_idx]-subcarrier_offset; + if(subcarrier0 < 0) { + subcarrier0 = subcarrier0 + frame_parms->ofdm_symbol_size; + } + int rb = subcarrier0/NR_NB_SC_PER_RB; + + for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { + + sum_re = sum_re + noise_real[ant*nr_srs_info->sc_list_length+sc_idx]; + sum_re2 = sum_re2 + noise_real[ant*nr_srs_info->sc_list_length+sc_idx]*noise_real[ant*nr_srs_info->sc_list_length+sc_idx]; + sum_im = sum_im + noise_imag[ant*nr_srs_info->sc_list_length+sc_idx]; + sum_im2 = sum_im2 + noise_imag[ant*nr_srs_info->sc_list_length+sc_idx]*noise_imag[ant*nr_srs_info->sc_list_length+sc_idx]; + + count_estimates++; + if (count_estimates == n_noise_estimates) { + noise_power_per_rb[rb] = sum_re2/n_noise_estimates - (sum_re/n_noise_estimates)*(sum_re/n_noise_estimates) + + sum_im2/n_noise_estimates - (sum_im/n_noise_estimates)*(sum_im/n_noise_estimates); + count_estimates = 0; + sum_re = 0; + sum_re2 = 0; + sum_im = 0; + sum_im2 = 0; + +#ifdef SRS_DEBUG + LOG_I(NR_PHY,"noise_power_per_rb[%i] = %i\n", rb, noise_power_per_rb[rb]); +#endif + + } + } + } + *noise_power = calc_power(noise_real,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length) + calc_power(noise_imag,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length); diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index a01106adb5..9c7d67b25d 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -73,5 +73,6 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, int32_t **srs_estimated_channel_freq, int32_t **srs_estimated_channel_time, int32_t **srs_estimated_channel_time_shifted, + uint32_t *noise_power_per_rb, uint32_t *noise_power); #endif diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index b24abd7de3..80842eef38 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -244,6 +244,7 @@ typedef struct { int32_t **srs_estimated_channel_freq; int32_t **srs_estimated_channel_time; int32_t **srs_estimated_channel_time_shifted; + uint32_t *noise_power_per_rb; uint32_t *noise_power; } nr_srs_info_t; diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index c9f4cf7b33..aa75cc64ef 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -834,6 +834,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { gNB->nr_srs_info[i]->srs_estimated_channel_freq, gNB->nr_srs_info[i]->srs_estimated_channel_time, gNB->nr_srs_info[i]->srs_estimated_channel_time_shifted, + gNB->nr_srs_info[i]->noise_power_per_rb, gNB->nr_srs_info[i]->noise_power); T(T_GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE, T_INT(0), T_INT(srs_pdu->rnti), T_INT(frame_rx), T_INT(0), T_INT(0), From ab6d7afd09b02963ba345c983acef44acfdf8322 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Mon, 9 May 2022 15:54:20 +0100 Subject: [PATCH 08/60] Compute the SNR per RB using the SRS --- openair1/PHY/INIT/nr_init.c | 2 + .../NR_ESTIMATION/nr_ul_channel_estimation.c | 37 ++++++++++++++----- openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 4 +- openair1/PHY/defs_nr_common.h | 2 + openair1/SCHED_NR/phy_procedures_nr_gNB.c | 4 +- 5 files changed, 38 insertions(+), 11 deletions(-) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 64bbdfa487..21ebcc1405 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -618,8 +618,10 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, gNB->nr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t)); gNB->nr_srs_info[id]->sc_list = (uint16_t *) malloc16_clear(6*fp->N_RB_UL*sizeof(uint16_t)); gNB->nr_srs_info[id]->srs_generated_signal = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t)); + gNB->nr_srs_info[id]->signal_power = (uint32_t*)malloc16_clear(sizeof(uint32_t)); gNB->nr_srs_info[id]->noise_power_per_rb = (uint32_t*)malloc16_clear(fp->N_RB_UL*sizeof(uint32_t)); gNB->nr_srs_info[id]->noise_power = (uint32_t*)malloc16_clear(sizeof(uint32_t)); + gNB->nr_srs_info[id]->snr_per_rb = (int8_t*)malloc16_clear(fp->N_RB_UL*sizeof(int8_t)); gNB->nr_srs_info[id]->srs_received_signal = (int32_t **)malloc16(Prx*sizeof(int32_t*)); gNB->nr_srs_info[id]->srs_ls_estimated_channel = (int32_t **)malloc16(Prx*sizeof(int32_t*)); gNB->nr_srs_info[id]->srs_estimated_channel_freq = (int32_t **)malloc16(Prx*sizeof(int32_t*)); diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index ffdf07860d..8db33e3e18 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -1079,9 +1079,9 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, }//Antenna loop } -uint32_t calc_power(uint16_t *x, uint32_t size) { - uint64_t sum_x = 0; - uint64_t sum_x2 = 0; +uint32_t calc_power(const int16_t *x, uint32_t size) { + int64_t sum_x = 0; + int64_t sum_x2 = 0; for(int k = 0; ksc_list_length == 0) { LOG_E(NR_PHY, "(%d.%d) nr_srs_info was not generated yet!\n", frame, slot); @@ -1110,8 +1112,10 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; int32_t **srs_ls_estimated_channel = nr_srs_info->srs_ls_estimated_channel; - uint16_t noise_real[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length]; - uint16_t noise_imag[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length]; + int16_t ch_real[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length]; + int16_t ch_imag[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length]; + int16_t noise_real[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length]; + int16_t noise_imag[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length]; int16_t ls_estimated[2]; @@ -1199,8 +1203,10 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, // Compute noise for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) { - noise_real[ant*nr_srs_info->sc_list_length + sc_idx] = abs((int16_t)((srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]]-srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]]) & 0xFFFF)); - noise_imag[ant*nr_srs_info->sc_list_length + sc_idx] = abs((int16_t)(((srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]]-srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]]) >> 16) & 0xFFFF)); + ch_real[ant*nr_srs_info->sc_list_length + sc_idx] = (int16_t)(srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]] & 0xFFFF); + ch_imag[ant*nr_srs_info->sc_list_length + sc_idx] = (int16_t)((srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]] >> 16) & 0xFFFF); + noise_real[ant*nr_srs_info->sc_list_length + sc_idx] = abs((int16_t)(srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]] & 0xFFFF) - ch_real[ant*nr_srs_info->sc_list_length + sc_idx]); + noise_imag[ant*nr_srs_info->sc_list_length + sc_idx] = abs((int16_t)((srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]] >> 16) & 0xFFFF) - ch_imag[ant*nr_srs_info->sc_list_length + sc_idx]); } // Convert to time domain @@ -1217,8 +1223,20 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, (gNB->frame_parms.ofdm_symbol_size>>1)*sizeof(int32_t)); } + // Compute signal power + *signal_power = calc_power(ch_real,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length) + + calc_power(ch_imag,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length); + +#ifdef SRS_DEBUG + LOG_I(NR_PHY,"signal_power = %u\n", *signal_power); +#endif + // Compute noise power + uint8_t signal_power_bits = log2_approx(*signal_power); + uint8_t factor_bits = signal_power_bits < 32 ? 32 - signal_power_bits : 0; // 32 due to input of dB_fixed(uint32_t x) + int32_t factor_dB = dB_fixed(1<first_carrier_offset + srs_pdu->bwp_start*12; uint8_t srs_symbols_per_rb = srs_pdu->comb_size == 0 ? 6 : 3; uint8_t n_noise_estimates = frame_parms->nb_antennas_rx*srs_symbols_per_rb; @@ -1247,6 +1265,7 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, if (count_estimates == n_noise_estimates) { noise_power_per_rb[rb] = sum_re2/n_noise_estimates - (sum_re/n_noise_estimates)*(sum_re/n_noise_estimates) + sum_im2/n_noise_estimates - (sum_im/n_noise_estimates)*(sum_im/n_noise_estimates); + snr_per_rb[rb] = dB_fixed((int32_t)((*signal_power<nr_srs_info[i]->srs_estimated_channel_freq, gNB->nr_srs_info[i]->srs_estimated_channel_time, gNB->nr_srs_info[i]->srs_estimated_channel_time_shifted, + gNB->nr_srs_info[i]->signal_power, gNB->nr_srs_info[i]->noise_power_per_rb, - gNB->nr_srs_info[i]->noise_power); + gNB->nr_srs_info[i]->noise_power, + gNB->nr_srs_info[i]->snr_per_rb); T(T_GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE, T_INT(0), T_INT(srs_pdu->rnti), T_INT(frame_rx), T_INT(0), T_INT(0), T_BUFFER(gNB->nr_srs_info[i]->srs_estimated_channel_freq[0], gNB->frame_parms.ofdm_symbol_size*sizeof(int32_t))); From d914817806a331335cf40dde50cfedf54cd57db2 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Mon, 9 May 2022 17:58:42 +0100 Subject: [PATCH 09/60] Fill srs_reported_symbol_list in SRS indication --- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 49 ++++++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index b342b87fa8..597b165f9e 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -45,6 +45,7 @@ #include "intertask_interface.h" //#define DEBUG_RXDATA +//#define SRS_IND_DEBUG uint8_t SSB_Table[38]={0,2,4,6,8,10,12,14,254,254,16,18,20,22,24,26,28,30,254,254,32,34,36,38,40,42,44,46,254,254,48,50,52,54,56,58,60,62}; @@ -624,6 +625,30 @@ void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) } +int fill_srs_reported_symbol_list(nfapi_nr_srs_indication_reported_symbol_t* reported_symbol_list, + nfapi_nr_srs_pdu_t *srs_pdu, + int N_RB_UL, + const int8_t *snr_per_rb) { + + reported_symbol_list->num_rbs = srs_bandwidth_config[srs_pdu->config_index][srs_pdu->bandwidth_index][0]; + + if (!reported_symbol_list->rb_list) { + reported_symbol_list->rb_list = (nfapi_nr_srs_indication_reported_symbol_resource_block_t*) calloc(1, N_RB_UL*sizeof(nfapi_nr_srs_indication_reported_symbol_resource_block_t)); + } + + for(int rb = 0; rb < reported_symbol_list->num_rbs; rb++) { + if (snr_per_rb[rb] < -64) { + reported_symbol_list->rb_list[rb].rb_snr = 0; + } else if (snr_per_rb[rb] > 63) { + reported_symbol_list->rb_list[rb].rb_snr = 255; + } else { + reported_symbol_list->rb_list[rb].rb_snr = (snr_per_rb[rb] + 64)<<1; + } + } + + return 0; +} + int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { /* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */ int pucch_decode_done = 0; @@ -854,10 +879,30 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { //gNB->srs_pdu_list[num_srs].timing_advance; gNB->srs_pdu_list[num_srs].num_symbols = 1<num_symbols; //gNB->srs_pdu_list[num_srs].wide_band_snr; - //gNB->srs_pdu_list[num_srs].num_reported_symbols; - //gNB->srs_pdu_list[num_srs].reported_symbol_list; + gNB->srs_pdu_list[num_srs].num_reported_symbols = 1<num_symbols; + if(!gNB->srs_pdu_list[num_srs].reported_symbol_list) { + gNB->srs_pdu_list[num_srs].reported_symbol_list = (nfapi_nr_srs_indication_reported_symbol_t*) calloc(1, gNB->srs_pdu_list[num_srs].num_reported_symbols*sizeof(nfapi_nr_srs_indication_reported_symbol_t)); + } + fill_srs_reported_symbol_list(&gNB->srs_pdu_list[num_srs].reported_symbol_list[0], + srs_pdu, + gNB->frame_parms.N_RB_UL, + gNB->nr_srs_info[i]->snr_per_rb); + gNB->UL_INFO.srs_ind.number_of_pdus += 1; +#ifdef SRS_IND_DEBUG + LOG_I(NR_PHY, "gNB->UL_INFO.srs_ind.sfn = %i\n", gNB->UL_INFO.srs_ind.sfn); + LOG_I(NR_PHY, "gNB->UL_INFO.srs_ind.slot = %i\n", gNB->UL_INFO.srs_ind.slot); + LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].rnti = 0x%04x\n", num_srs, gNB->srs_pdu_list[num_srs].rnti); + LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].num_symbols = %i\n", num_srs, gNB->srs_pdu_list[num_srs].num_symbols); + LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].num_reported_symbols = %i\n", num_srs, gNB->srs_pdu_list[num_srs].num_reported_symbols); + LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].reported_symbol_list[0].num_rbs = %i\n", num_srs, gNB->srs_pdu_list[num_srs].reported_symbol_list[0].num_rbs); + for(int rb = 0; rb < gNB->srs_pdu_list[num_srs].reported_symbol_list[0].num_rbs; rb++) { + LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].reported_symbol_list[0].rb_list[%3i].rb_snr = %i\n", + num_srs, rb, gNB->srs_pdu_list[num_srs].reported_symbol_list[0].rb_list[rb].rb_snr); + } +#endif + srs->active = 0; } } From bdff42cf77e5a304f5337472b7a75c8758dceb75 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Mon, 9 May 2022 18:21:04 +0100 Subject: [PATCH 10/60] Compute and fill wide_band_snr field for SRS indication --- openair1/PHY/INIT/nr_init.c | 1 + openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c | 7 +++++-- openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 3 ++- openair1/PHY/defs_nr_common.h | 1 + openair1/SCHED_NR/phy_procedures_nr_gNB.c | 8 +++++--- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 21ebcc1405..1722dfb861 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -622,6 +622,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, gNB->nr_srs_info[id]->noise_power_per_rb = (uint32_t*)malloc16_clear(fp->N_RB_UL*sizeof(uint32_t)); gNB->nr_srs_info[id]->noise_power = (uint32_t*)malloc16_clear(sizeof(uint32_t)); gNB->nr_srs_info[id]->snr_per_rb = (int8_t*)malloc16_clear(fp->N_RB_UL*sizeof(int8_t)); + gNB->nr_srs_info[id]->snr = (int8_t*)malloc16_clear(sizeof(int8_t)); gNB->nr_srs_info[id]->srs_received_signal = (int32_t **)malloc16(Prx*sizeof(int32_t*)); gNB->nr_srs_info[id]->srs_ls_estimated_channel = (int32_t **)malloc16(Prx*sizeof(int32_t*)); gNB->nr_srs_info[id]->srs_estimated_channel_freq = (int32_t **)malloc16(Prx*sizeof(int32_t*)); diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 8db33e3e18..4ff9952077 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -1102,7 +1102,8 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, uint32_t *signal_power, uint32_t *noise_power_per_rb, uint32_t *noise_power, - int8_t *snr_per_rb) { + int8_t *snr_per_rb, + int8_t *snr) { if(nr_srs_info->sc_list_length == 0) { LOG_E(NR_PHY, "(%d.%d) nr_srs_info was not generated yet!\n", frame, slot); @@ -1283,6 +1284,8 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, *noise_power = calc_power(noise_real,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length) + calc_power(noise_imag,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length); + *snr = dB_fixed((int32_t)((*signal_power<first_carrier_offset + srs_pdu->bwp_start*12; uint8_t R = srs_pdu->comb_size == 0 ? 2 : 4; @@ -1312,7 +1315,7 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, } } - LOG_I(NR_PHY,"noise_power = %u\n", *noise_power); + LOG_I(NR_PHY,"noise_power = %u, SNR = %i dB\n", *noise_power, *snr); #endif return 0; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index f7ac055dcc..38b6556948 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -76,5 +76,6 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, uint32_t *signal_power, uint32_t *noise_power_per_rb, uint32_t *noise_power, - int8_t *snr_per_rb); + int8_t *snr_per_rb, + int8_t *snr); #endif diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 4109b13831..a30baabd10 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -248,6 +248,7 @@ typedef struct { uint32_t *noise_power_per_rb; uint32_t *noise_power; int8_t *snr_per_rb; + int8_t *snr; } nr_srs_info_t; typedef struct NR_DL_FRAME_PARMS NR_DL_FRAME_PARMS; diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 597b165f9e..b8aa108f10 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -862,7 +862,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { gNB->nr_srs_info[i]->signal_power, gNB->nr_srs_info[i]->noise_power_per_rb, gNB->nr_srs_info[i]->noise_power, - gNB->nr_srs_info[i]->snr_per_rb); + gNB->nr_srs_info[i]->snr_per_rb, + gNB->nr_srs_info[i]->snr); T(T_GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE, T_INT(0), T_INT(srs_pdu->rnti), T_INT(frame_rx), T_INT(0), T_INT(0), T_BUFFER(gNB->nr_srs_info[i]->srs_estimated_channel_freq[0], gNB->frame_parms.ofdm_symbol_size*sizeof(int32_t))); @@ -874,11 +875,11 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { gNB->UL_INFO.srs_ind.pdu_list = &gNB->srs_pdu_list[0]; gNB->UL_INFO.srs_ind.sfn = frame_rx; gNB->UL_INFO.srs_ind.slot = slot_rx; - //gNB->srs_pdu_list[num_srs].handle; + gNB->srs_pdu_list[num_srs].handle = srs_pdu->handle; gNB->srs_pdu_list[num_srs].rnti = srs_pdu->rnti; //gNB->srs_pdu_list[num_srs].timing_advance; gNB->srs_pdu_list[num_srs].num_symbols = 1<num_symbols; - //gNB->srs_pdu_list[num_srs].wide_band_snr; + gNB->srs_pdu_list[num_srs].wide_band_snr = (*gNB->nr_srs_info[i]->snr + 64)<<1; gNB->srs_pdu_list[num_srs].num_reported_symbols = 1<num_symbols; if(!gNB->srs_pdu_list[num_srs].reported_symbol_list) { gNB->srs_pdu_list[num_srs].reported_symbol_list = (nfapi_nr_srs_indication_reported_symbol_t*) calloc(1, gNB->srs_pdu_list[num_srs].num_reported_symbols*sizeof(nfapi_nr_srs_indication_reported_symbol_t)); @@ -895,6 +896,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { LOG_I(NR_PHY, "gNB->UL_INFO.srs_ind.slot = %i\n", gNB->UL_INFO.srs_ind.slot); LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].rnti = 0x%04x\n", num_srs, gNB->srs_pdu_list[num_srs].rnti); LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].num_symbols = %i\n", num_srs, gNB->srs_pdu_list[num_srs].num_symbols); + LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].wide_band_snr = %i\n", num_srs, gNB->srs_pdu_list[num_srs].wide_band_snr); LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].num_reported_symbols = %i\n", num_srs, gNB->srs_pdu_list[num_srs].num_reported_symbols); LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].reported_symbol_list[0].num_rbs = %i\n", num_srs, gNB->srs_pdu_list[num_srs].reported_symbol_list[0].num_rbs); for(int rb = 0; rb < gNB->srs_pdu_list[num_srs].reported_symbol_list[0].num_rbs; rb++) { From 99b262d7647121cdaa786e9402d07eda88904ea2 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Mon, 9 May 2022 19:25:33 +0100 Subject: [PATCH 11/60] Compute and fill timing_advance field for SRS indication --- .../PHY/NR_ESTIMATION/nr_measurements_gNB.c | 43 +++++++++++++++++++ openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 3 ++ openair1/SCHED_NR/phy_procedures_nr_gNB.c | 3 +- 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index fb56322e54..a2ee62fbde 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -67,6 +67,49 @@ int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) return max_pos - sync_pos; } +int nr_est_timing_advance_srs(NR_DL_FRAME_PARMS *frame_parms, + int32_t **srs_estimated_channel_time) { + int timing_advance = 0; + int max_val = 0; + + for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) { + int temp = 0; + for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { + int Re = ((int16_t*)srs_estimated_channel_time[aa])[(i<<1)]; + int Im = ((int16_t*)srs_estimated_channel_time[aa])[1+(i<<1)]; + temp += (Re*Re/2) + (Im*Im/2); + } + if (temp > max_val) { + timing_advance = i; + max_val = temp; + } + } + + if (timing_advance > frame_parms->ofdm_symbol_size/2) { + timing_advance = timing_advance - frame_parms->ofdm_symbol_size; + } + + // Scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size + uint16_t bw_scaling = frame_parms->ofdm_symbol_size >> 11; + + // do some integer rounding to improve TA accuracy + int sync_pos_rounded; + if (timing_advance > 0) { + sync_pos_rounded = timing_advance + (bw_scaling >> 1) - 1; + } else { + sync_pos_rounded = timing_advance - (bw_scaling >> 1) + 1; + } + + int timing_advance_update = sync_pos_rounded / bw_scaling; + + // put timing advance command in 0..63 range + timing_advance_update += 31; + + if (timing_advance_update < 0) timing_advance_update = 0; + if (timing_advance_update > 63) timing_advance_update = 63; + + return timing_advance_update; +} void dump_nr_I0_stats(FILE *fd,PHY_VARS_gNB *gNB) { diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 38b6556948..914b0d7385 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -55,6 +55,9 @@ void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq int nr_est_timing_advance_pusch(PHY_VARS_gNB* phy_vars_gNB, int UE_id); +int nr_est_timing_advance_srs(NR_DL_FRAME_PARMS *frame_parms, + int32_t **srs_estimated_channel_time); + void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, NR_DL_FRAME_PARMS *frame_parms, nfapi_nr_pusch_pdu_t *rel15_ul, diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index b8aa108f10..4e75090d4b 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -877,7 +877,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { gNB->UL_INFO.srs_ind.slot = slot_rx; gNB->srs_pdu_list[num_srs].handle = srs_pdu->handle; gNB->srs_pdu_list[num_srs].rnti = srs_pdu->rnti; - //gNB->srs_pdu_list[num_srs].timing_advance; + gNB->srs_pdu_list[num_srs].timing_advance = nr_est_timing_advance_srs(&gNB->frame_parms, gNB->nr_srs_info[i]->srs_estimated_channel_time); gNB->srs_pdu_list[num_srs].num_symbols = 1<num_symbols; gNB->srs_pdu_list[num_srs].wide_band_snr = (*gNB->nr_srs_info[i]->snr + 64)<<1; gNB->srs_pdu_list[num_srs].num_reported_symbols = 1<num_symbols; @@ -895,6 +895,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { LOG_I(NR_PHY, "gNB->UL_INFO.srs_ind.sfn = %i\n", gNB->UL_INFO.srs_ind.sfn); LOG_I(NR_PHY, "gNB->UL_INFO.srs_ind.slot = %i\n", gNB->UL_INFO.srs_ind.slot); LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].rnti = 0x%04x\n", num_srs, gNB->srs_pdu_list[num_srs].rnti); + LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].timing_advance = %i\n", num_srs, gNB->srs_pdu_list[num_srs].timing_advance); LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].num_symbols = %i\n", num_srs, gNB->srs_pdu_list[num_srs].num_symbols); LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].wide_band_snr = %i\n", num_srs, gNB->srs_pdu_list[num_srs].wide_band_snr); LOG_I(NR_PHY, "gNB->srs_pdu_list[%i].num_reported_symbols = %i\n", num_srs, gNB->srs_pdu_list[num_srs].num_reported_symbols); From 61a2f398db15e386981bd4e523f1f423049a8bcb Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Tue, 10 May 2022 10:43:24 +0100 Subject: [PATCH 12/60] Add LOGs of SRS indication in handle_nr_srs_measurements --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 03cb48e5da..e763548ea3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -37,6 +37,8 @@ #include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h" +//#define SRS_IND_DEBUG + int get_dci_format(NR_UE_sched_ctrl_t *sched_ctrl) { int dci_format = sched_ctrl->search_space && sched_ctrl->search_space->searchSpaceType && @@ -887,7 +889,23 @@ void handle_nr_srs_measurements(const module_id_t module_id, const uint8_t wide_band_snr, const uint8_t num_reported_symbols, nfapi_nr_srs_indication_reported_symbol_t* reported_symbol_list) { + LOG_I(NR_MAC, "(%d.%d) Received SRS indication for rnti: 0x%04x\n", frame, slot, rnti); + +#ifdef SRS_IND_DEBUG + LOG_I(NR_MAC, "frame = %i\n", frame); + LOG_I(NR_MAC, "slot = %i\n", slot); + LOG_I(NR_MAC, "rnti = 0x%04x\n", rnti); + LOG_I(NR_MAC, "timing_advance = %i\n", timing_advance); + LOG_I(NR_MAC, "num_symbols = %i\n", num_symbols); + LOG_I(NR_MAC, "wide_band_snr = %i (%i dB)\n", wide_band_snr, (wide_band_snr>>1)-64); + LOG_I(NR_MAC, "num_reported_symbols = %i\n", num_reported_symbols); + LOG_I(NR_MAC, "reported_symbol_list[0].num_rbs = %i\n", reported_symbol_list[0].num_rbs); + for(int rb = 0; rb < reported_symbol_list[0].num_rbs; rb++) { + LOG_I(NR_MAC, "reported_symbol_list[0].rb_list[%3i].rb_snr = %i (%i dB)\n", + rb, reported_symbol_list[0].rb_list[rb].rb_snr, (reported_symbol_list[0].rb_list[rb].rb_snr>>1)-64); + } +#endif } long get_K2(NR_ServingCellConfigCommon_t *scc, From 5ed67b85a78b4ff7be4dda5b2c93b8b3207bd24f Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Tue, 10 May 2022 13:03:41 +0100 Subject: [PATCH 13/60] Free allocated memory --- openair1/PHY/INIT/nr_init.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 1722dfb861..e2f549f12e 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -788,7 +788,11 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) } free_and_zero(gNB->nr_srs_info[id]->sc_list); free_and_zero(gNB->nr_srs_info[id]->srs_generated_signal); + free_and_zero(gNB->nr_srs_info[id]->signal_power); + free_and_zero(gNB->nr_srs_info[id]->noise_power_per_rb); free_and_zero(gNB->nr_srs_info[id]->noise_power); + free_and_zero(gNB->nr_srs_info[id]->snr_per_rb); + free_and_zero(gNB->nr_srs_info[id]->snr); free_and_zero(gNB->nr_srs_info[id]->srs_received_signal); free_and_zero(gNB->nr_srs_info[id]->srs_ls_estimated_channel); free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_freq); From 08975e451fd9110ff6401589d45437c5cdb5115e Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Tue, 10 May 2022 14:03:24 +0100 Subject: [PATCH 14/60] Update the ul_prbblacklist based on SRS measurements and an ul_prbblack_SNR_threshold --- openair2/GNB_APP/MACRLC_nr_paramdef.h | 21 +++++++++++-------- openair2/GNB_APP/gnb_config.c | 1 + .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 14 ++++++++++++- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 4 +++- ...gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf | 1 + .../gnb.sa.band78.fr1.106PRB.usrpb210.conf | 1 + 6 files changed, 31 insertions(+), 11 deletions(-) diff --git a/openair2/GNB_APP/MACRLC_nr_paramdef.h b/openair2/GNB_APP/MACRLC_nr_paramdef.h index e634f077e2..3cc0396a3e 100644 --- a/openair2/GNB_APP/MACRLC_nr_paramdef.h +++ b/openair2/GNB_APP/MACRLC_nr_paramdef.h @@ -58,6 +58,7 @@ #define CONFIG_STRING_MACRLC_ULSCH_MAX_FRAME_INACTIVITY "ulsch_max_frame_inactivity" #define CONFIG_STRING_MACRLC_PUSCHTARGETSNRX10 "pusch_TargetSNRx10" #define CONFIG_STRING_MACRLC_PUCCHTARGETSNRX10 "pucch_TargetSNRx10" +#define CONFIG_STRING_MACRLC_UL_PRBBLACK_SNR_THRESHOLD "ul_prbblack_SNR_threshold" #define CONFIG_STRING_MACRLC_PUCCHFAILURETHRES "pucch_FailureThres" #define CONFIG_STRING_MACRLC_PUSCHFAILURETHRES "pusch_FailureThres" #define CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER "dl_bler_target_upper" @@ -93,6 +94,7 @@ {CONFIG_STRING_MACRLC_ULSCH_MAX_FRAME_INACTIVITY, NULL, 0, uptr:NULL, defintval:10, TYPE_UINT, 0}, \ {CONFIG_STRING_MACRLC_PUSCHTARGETSNRX10, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_PUCCHTARGETSNRX10, NULL, 0, iptr:NULL, defintval:150, TYPE_INT, 0}, \ +{CONFIG_STRING_MACRLC_UL_PRBBLACK_SNR_THRESHOLD, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_PUCCHFAILURETHRES, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_PUSCHFAILURETHRES, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER, "Upper threshold of BLER to decrease DL MCS", 0, dblptr:NULL, defdblval:0.15, TYPE_DOUBLE, 0}, \ @@ -123,14 +125,15 @@ #define MACRLC_ULSCH_MAX_FRAME_INACTIVITY 17 #define MACRLC_PUSCHTARGETSNRX10_IDX 18 #define MACRLC_PUCCHTARGETSNRX10_IDX 19 -#define MACRLC_PUCCHFAILURETHRES_IDX 20 -#define MACRLC_PUSCHFAILURETHRES_IDX 21 -#define MACRLC_DL_BLER_TARGET_UPPER_IDX 22 -#define MACRLC_DL_BLER_TARGET_LOWER_IDX 23 -#define MACRLC_DL_RD2_BLER_THRESHOLD_IDX 24 -#define MACRLC_DL_MAX_MCS_IDX 25 -#define MACRLC_HARQ_ROUND_MAX_IDX 26 -#define MACRLC_MIN_GRANT_PRB_IDX 27 -#define MACRLC_MIN_GRANT_MCS_IDX 28 +#define MACRLC_UL_PRBBLACK_SNR_THRESHOLD_IDX 20 +#define MACRLC_PUCCHFAILURETHRES_IDX 21 +#define MACRLC_PUSCHFAILURETHRES_IDX 22 +#define MACRLC_DL_BLER_TARGET_UPPER_IDX 23 +#define MACRLC_DL_BLER_TARGET_LOWER_IDX 24 +#define MACRLC_DL_RD2_BLER_THRESHOLD_IDX 25 +#define MACRLC_DL_MAX_MCS_IDX 26 +#define MACRLC_HARQ_ROUND_MAX_IDX 27 +#define MACRLC_MIN_GRANT_PRB_IDX 28 +#define MACRLC_MIN_GRANT_MCS_IDX 29 /*---------------------------------------------------------------------------------------------------------------------------------------------------------*/ #endif diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 62dc72a857..530725bb51 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -770,6 +770,7 @@ void RCconfig_nr_macrlc() { RC.nb_nr_mac_CC[j] = *(MacRLC_ParamList.paramarray[j][MACRLC_CC_IDX].iptr); RC.nrmac[j]->pusch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCHTARGETSNRX10_IDX].iptr); RC.nrmac[j]->pucch_target_snrx10 = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHTARGETSNRX10_IDX].iptr); + RC.nrmac[j]->ul_prbblack_SNR_threshold = *(MacRLC_ParamList.paramarray[j][MACRLC_UL_PRBBLACK_SNR_THRESHOLD_IDX].iptr); RC.nrmac[j]->pucch_failure_thres = *(MacRLC_ParamList.paramarray[j][MACRLC_PUCCHFAILURETHRES_IDX].iptr); RC.nrmac[j]->pusch_failure_thres = *(MacRLC_ParamList.paramarray[j][MACRLC_PUSCHFAILURETHRES_IDX].iptr); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index e763548ea3..39a6f52327 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -890,7 +890,7 @@ void handle_nr_srs_measurements(const module_id_t module_id, const uint8_t num_reported_symbols, nfapi_nr_srs_indication_reported_symbol_t* reported_symbol_list) { - LOG_I(NR_MAC, "(%d.%d) Received SRS indication for rnti: 0x%04x\n", frame, slot, rnti); + LOG_D(NR_MAC, "(%d.%d) Received SRS indication for rnti: 0x%04x\n", frame, slot, rnti); #ifdef SRS_IND_DEBUG LOG_I(NR_MAC, "frame = %i\n", frame); @@ -906,6 +906,18 @@ void handle_nr_srs_measurements(const module_id_t module_id, rb, reported_symbol_list[0].rb_list[rb].rb_snr, (reported_symbol_list[0].rb_list[rb].rb_snr>>1)-64); } #endif + + int ul_prbblack_SNR_threshold = RC.nrmac[module_id]->ul_prbblack_SNR_threshold; + uint16_t *ulprbbl = RC.nrmac[module_id]->ulprbbl; + + memset(ulprbbl, 0, reported_symbol_list[0].num_rbs*sizeof(uint16_t)); + for (int rb = 0; rb < reported_symbol_list[0].num_rbs; rb++) { + int snr = (reported_symbol_list[0].rb_list[rb].rb_snr>>1)-64; + if (snr < ul_prbblack_SNR_threshold) { + ulprbbl[rb] = 0x3FFF; // all symbols taken + } + LOG_D(NR_MAC, "ulprbbl[%3i] = 0x%x\n", rb, ulprbbl[rb]); + } } long get_K2(NR_ServingCellConfigCommon_t *scc, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index a2c77234c0..5ddeacf4ed 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -721,6 +721,8 @@ typedef struct gNB_MAC_INST_s { int pusch_target_snrx10; /// Pucch target SNR int pucch_target_snrx10; + /// SNR threshold needed to put or not a PRB in the black list + int ul_prbblack_SNR_threshold; /// PUCCH Failure threshold (compared to consecutive PUCCH DTX) int pucch_failure_thres; /// PUSCH Failure threshold (compared to consecutive PUSCH DTX) @@ -735,7 +737,7 @@ typedef struct gNB_MAC_INST_s { /// current PDU index (BCH,DLSCH) uint16_t pdu_index[NFAPI_CC_MAX]; int num_ulprbbl; - uint16_t ulprbbl[275]; + uint16_t ulprbbl[MAX_BWP_SIZE]; /// NFAPI Config Request Structure nfapi_nr_config_request_scf_t config[NFAPI_CC_MAX]; /// NFAPI DL Config Request Structure diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf index 2881a77d48..33c7353151 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf @@ -207,6 +207,7 @@ MACRLCs = ( tr_n_preference = "local_RRC"; #pusch_TargetSNRx10 = 150; #pucch_TargetSNRx10 = 200; + ul_prbblack_SNR_threshold = 10; ulsch_max_frame_inactivity = 0; } ); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index c83565e8bb..12feb0d4b0 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -205,6 +205,7 @@ MACRLCs = ( tr_n_preference = "local_RRC"; pusch_TargetSNRx10 = 150; pucch_TargetSNRx10 = 200; + ul_prbblack_SNR_threshold = 10; ulsch_max_frame_inactivity = 0; } ); From ba5bda5c6e25c3d4674394f32a753360249f8d32 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Tue, 10 May 2022 15:00:43 +0100 Subject: [PATCH 15/60] Fix bw_scaling --- openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index a2ee62fbde..403a96983c 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -90,7 +90,7 @@ int nr_est_timing_advance_srs(NR_DL_FRAME_PARMS *frame_parms, } // Scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size - uint16_t bw_scaling = frame_parms->ofdm_symbol_size >> 11; + uint16_t bw_scaling = frame_parms->ofdm_symbol_size >> 7; // do some integer rounding to improve TA accuracy int sync_pos_rounded; From 9e2086c77c4ce562fcd22fcd4c379927ac9a0c46 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Wed, 18 May 2022 12:51:18 +0100 Subject: [PATCH 16/60] Fix warning after merge --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 1e019a4744..906a5d2d6c 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -840,12 +840,13 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac, mappingtype, add_pos, dmrslength, pusch_config_pdu->start_symbol_index, mac->scc ? mac->scc->dmrs_TypeA_Position : mac->mib->dmrs_TypeA_Position); - if ((mac->ULbwp[ul_bwp_id-1] && pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_disabled)) + if ((mac->ULbwp[ul_bwp_id-1] && pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_disabled)) { if (*dci_format != NR_UL_DCI_FORMAT_0_1) { pusch_config_pdu->num_dmrs_cdm_grps_no_data = 1; } - else if (*dci_format == NR_UL_DCI_FORMAT_0_0 || (mac->ULbwp[ul_bwp_id-1] && pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled)) + } else if (*dci_format == NR_UL_DCI_FORMAT_0_0 || (mac->ULbwp[ul_bwp_id-1] && pusch_config_pdu->transform_precoding == NR_PUSCH_Config__transformPrecoder_enabled)) { pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; + } // Num PRB Overhead from PUSCH-ServingCellConfig if (mac->cg && From 0eeb174253f93847e5990adf2ea210345ec28eed Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Mon, 23 May 2022 11:43:32 +0100 Subject: [PATCH 17/60] Add wideband SNR based on SRS in MAC stats --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 15 +++++++++++++-- openair2/LAYER2/NR_MAC_gNB/main.c | 5 +++-- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 + 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 7c61eb3b5a..38e6ca0d6f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -907,8 +907,19 @@ void handle_nr_srs_measurements(const module_id_t module_id, } #endif - int ul_prbblack_SNR_threshold = RC.nrmac[module_id]->ul_prbblack_SNR_threshold; - uint16_t *ulprbbl = RC.nrmac[module_id]->ulprbbl; + const int UE_id = find_nr_UE_id(module_id,rnti); + if (UE_id < 0) { + LOG_W(NR_MAC, "Could not find UE for RNTI 0x%04x\n", rnti); + return; + } + + gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + NR_UE_info_t *UE_info = &nr_mac->UE_info; + NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; + stats->srs_wide_band_snr = (wide_band_snr>>1)-64; + + int ul_prbblack_SNR_threshold = nr_mac->ul_prbblack_SNR_threshold; + uint16_t *ulprbbl = nr_mac->ulprbbl; memset(ulprbbl, 0, reported_symbol_list[0].num_rbs*sizeof(uint16_t)); for (int rb = 0; rb < reported_symbol_list[0].num_rbs; rb++) { diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index e047494b52..b7bf30f056 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -84,7 +84,7 @@ void dump_mac_stats(gNB_MAC_INST *gNB, char *output, int strlen, bool reset_rsrp const NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0; - stroff+=sprintf(output+stroff,"UE ID %d RNTI %04x (%d/%d) PH %d dB PCMAX %d dBm, average RSRP %d (%d meas)\n", + stroff+=sprintf(output+stroff,"UE ID %d RNTI %04x (%d/%d) PH %d dB PCMAX %d dBm, average RSRP %d (%d meas), UL-SNR %d dB\n", UE_id, UE_info->rnti[UE_id], num++, @@ -92,7 +92,8 @@ void dump_mac_stats(gNB_MAC_INST *gNB, char *output, int strlen, bool reset_rsrp sched_ctrl->ph, sched_ctrl->pcmax, avg_rsrp, - stats->num_rsrp_meas); + stats->num_rsrp_meas, + stats->srs_wide_band_snr); stroff+=sprintf(output+stroff,"UE %d: CQI %d, RI %d, PMI (%d,%d)\n", UE_id, UE_info->UE_sched_ctrl[UE_id].CSI_report.cri_ri_li_pmi_cqi_report.wb_cqi_1tb, diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index b2b6d3d516..4e896c2f49 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -690,6 +690,7 @@ typedef struct { uint32_t pucch0_DTX; int cumul_rsrp; uint8_t num_rsrp_meas; + int8_t srs_wide_band_snr; } NR_mac_stats_t; From 5092eca8cbd6d0d5e877593a37f9f4e99289e3ab Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Mon, 23 May 2022 13:30:38 +0100 Subject: [PATCH 18/60] Some robustness improvements --- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 5 +++ openair1/PHY/NR_TRANSPORT/srs_rx.c | 13 +++++- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 42 +++++++++++-------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c | 3 +- 4 files changed, 43 insertions(+), 20 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index be2d03d0db..70a06d4727 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -1089,6 +1089,11 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, LOG_I(NR_PHY,"signal_power = %u\n", *signal_power); #endif + if (*signal_power == 0) { + LOG_W(NR_PHY, "Received SRS signal power is 0\n"); + return -1; + } + // Compute noise power uint8_t signal_power_bits = log2_approx(*signal_power); diff --git a/openair1/PHY/NR_TRANSPORT/srs_rx.c b/openair1/PHY/NR_TRANSPORT/srs_rx.c index 2d7aefdee0..ffcd7362f3 100644 --- a/openair1/PHY/NR_TRANSPORT/srs_rx.c +++ b/openair1/PHY/NR_TRANSPORT/srs_rx.c @@ -113,6 +113,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, uint64_t symbol_offset = (n_symbols+l0)*frame_parms->ofdm_symbol_size; int32_t *rx_signal; + bool no_srs_signal = true; for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { memset(srs_received_signal[ant], 0, frame_parms->ofdm_symbol_size*sizeof(int32_t)); @@ -121,6 +122,10 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) { srs_received_signal[ant][nr_srs_info->sc_list[sc_idx]] = rx_signal[nr_srs_info->sc_list[sc_idx]]; + if (rx_signal[nr_srs_info->sc_list[sc_idx]] != 0) { + no_srs_signal = false; + } + #ifdef SRS_DEBUG uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*12; int subcarrier_log = nr_srs_info->sc_list[sc_idx]-subcarrier_offset; @@ -140,5 +145,11 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, #endif } } - return 0; + + if (no_srs_signal) { + LOG_W(NR_PHY, "No SRS signal\n"); + return -1; + } else { + return 0; + } } \ No newline at end of file diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 84370f2509..a8e5f84d9c 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -636,7 +636,8 @@ void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) int fill_srs_reported_symbol_list(nfapi_nr_srs_indication_reported_symbol_t* reported_symbol_list, nfapi_nr_srs_pdu_t *srs_pdu, int N_RB_UL, - const int8_t *snr_per_rb) { + const int8_t *snr_per_rb, + int srs_est) { reported_symbol_list->num_rbs = srs_bandwidth_config[srs_pdu->config_index][srs_pdu->bandwidth_index][0]; @@ -645,10 +646,12 @@ int fill_srs_reported_symbol_list(nfapi_nr_srs_indication_reported_symbol_t* rep } for(int rb = 0; rb < reported_symbol_list->num_rbs; rb++) { - if (snr_per_rb[rb] < -64) { + if (srs_est<0) { + reported_symbol_list->rb_list[rb].rb_snr = 0xFF; + } else if (snr_per_rb[rb] < -64) { reported_symbol_list->rb_list[rb].rb_snr = 0; } else if (snr_per_rb[rb] > 63) { - reported_symbol_list->rb_list[rb].rb_snr = 255; + reported_symbol_list->rb_list[rb].rb_snr = 0xFE; } else { reported_symbol_list->rb_list[rb].rb_snr = (snr_per_rb[rb] + 64)<<1; } @@ -858,20 +861,22 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { generate_srs_nr(srs_pdu, &gNB->frame_parms, gNB->nr_srs_info[i]->srs_generated_signal, gNB->nr_srs_info[i], AMP, frame_rx, slot_rx); } - nr_get_srs_signal(gNB,frame_rx,slot_rx,srs_pdu, gNB->nr_srs_info[i], gNB->nr_srs_info[i]->srs_received_signal); + int srs_est = nr_get_srs_signal(gNB,frame_rx,slot_rx,srs_pdu, gNB->nr_srs_info[i], gNB->nr_srs_info[i]->srs_received_signal); - nr_srs_channel_estimation(gNB,frame_rx,slot_rx,srs_pdu, - gNB->nr_srs_info[i], - gNB->nr_srs_info[i]->srs_generated_signal, - gNB->nr_srs_info[i]->srs_received_signal, - gNB->nr_srs_info[i]->srs_estimated_channel_freq, - gNB->nr_srs_info[i]->srs_estimated_channel_time, - gNB->nr_srs_info[i]->srs_estimated_channel_time_shifted, - gNB->nr_srs_info[i]->signal_power, - gNB->nr_srs_info[i]->noise_power_per_rb, - gNB->nr_srs_info[i]->noise_power, - gNB->nr_srs_info[i]->snr_per_rb, - gNB->nr_srs_info[i]->snr); + if (srs_est >= 0) { + nr_srs_channel_estimation(gNB,frame_rx,slot_rx,srs_pdu, + gNB->nr_srs_info[i], + gNB->nr_srs_info[i]->srs_generated_signal, + gNB->nr_srs_info[i]->srs_received_signal, + gNB->nr_srs_info[i]->srs_estimated_channel_freq, + gNB->nr_srs_info[i]->srs_estimated_channel_time, + gNB->nr_srs_info[i]->srs_estimated_channel_time_shifted, + gNB->nr_srs_info[i]->signal_power, + gNB->nr_srs_info[i]->noise_power_per_rb, + gNB->nr_srs_info[i]->noise_power, + gNB->nr_srs_info[i]->snr_per_rb, + gNB->nr_srs_info[i]->snr); + } T(T_GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE, T_INT(0), T_INT(srs_pdu->rnti), T_INT(frame_rx), T_INT(0), T_INT(0), T_BUFFER(gNB->nr_srs_info[i]->srs_estimated_channel_freq[0], gNB->frame_parms.ofdm_symbol_size*sizeof(int32_t))); @@ -887,7 +892,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { gNB->srs_pdu_list[num_srs].rnti = srs_pdu->rnti; gNB->srs_pdu_list[num_srs].timing_advance = nr_est_timing_advance_srs(&gNB->frame_parms, gNB->nr_srs_info[i]->srs_estimated_channel_time); gNB->srs_pdu_list[num_srs].num_symbols = 1<num_symbols; - gNB->srs_pdu_list[num_srs].wide_band_snr = (*gNB->nr_srs_info[i]->snr + 64)<<1; + gNB->srs_pdu_list[num_srs].wide_band_snr = srs_est >= 0 ? (*gNB->nr_srs_info[i]->snr + 64)<<1 : 0xFF; // 0xFF will be set if this field is invalid gNB->srs_pdu_list[num_srs].num_reported_symbols = 1<num_symbols; if(!gNB->srs_pdu_list[num_srs].reported_symbol_list) { gNB->srs_pdu_list[num_srs].reported_symbol_list = (nfapi_nr_srs_indication_reported_symbol_t*) calloc(1, gNB->srs_pdu_list[num_srs].num_reported_symbols*sizeof(nfapi_nr_srs_indication_reported_symbol_t)); @@ -895,7 +900,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { fill_srs_reported_symbol_list(&gNB->srs_pdu_list[num_srs].reported_symbol_list[0], srs_pdu, gNB->frame_parms.N_RB_UL, - gNB->nr_srs_info[i]->snr_per_rb); + gNB->nr_srs_info[i]->snr_per_rb, + srs_est); gNB->UL_INFO.srs_ind.number_of_pdus += 1; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index 8680cc25d1..35b2c4b167 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -125,7 +125,8 @@ void nr_schedule_srs(int module_id, frame_t frame) { sched_ctrl->sched_srs.slot = -1; sched_ctrl->sched_srs.srs_scheduled = false; - if(!UE_info->Msg4_ACKed[UE_id] || sched_ctrl->rrc_processing_timer > 0) { + if((sched_ctrl->ul_failure == 1 && get_softmodem_params()->phy_test==0) || + !UE_info->Msg4_ACKed[UE_id] || sched_ctrl->rrc_processing_timer > 0) { continue; } From af95f834f1f03d7cef7fa9690344431d79513e10 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Wed, 25 May 2022 10:36:30 +0100 Subject: [PATCH 19/60] Fix scheduling SRS reception at gNB when there is Dedicated BWPs --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index 35b2c4b167..18b723ccc0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -41,15 +41,16 @@ void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, int module_id, int CC_id, int NR_UE_info_t *UE_info = &nrmac->UE_info; NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id]; - NR_BWP_t ubwp = sched_ctrl->active_ubwp ? - sched_ctrl->active_ubwp->bwp_Common->genericParameters : - scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; + const NR_SIB1_t *sib1 = nrmac->common_channels[0].sib1 ? nrmac->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL; + NR_BWP_t *genericParameters = get_ul_bwp_genericParameters(sched_ctrl->active_ubwp, + scc, + sib1); srs_pdu->rnti = UE_info->rnti[UE_id]; srs_pdu->handle = 0; - srs_pdu->bwp_size = NRRIV2BW(ubwp.locationAndBandwidth, MAX_BWP_SIZE);; - srs_pdu->bwp_start = NRRIV2PRBOFFSET(ubwp.locationAndBandwidth, MAX_BWP_SIZE);; - srs_pdu->subcarrier_spacing = ubwp.subcarrierSpacing; + srs_pdu->bwp_size = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);; + srs_pdu->bwp_start = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);; + srs_pdu->subcarrier_spacing = genericParameters->subcarrierSpacing; srs_pdu->cyclic_prefix = 0; srs_pdu->num_ant_ports = srs_resource->nrofSRS_Ports; srs_pdu->num_symbols = srs_resource->resourceMapping.nrofSymbols; @@ -131,13 +132,20 @@ void nr_schedule_srs(int module_id, frame_t frame) { } NR_SRS_Config_t *srs_config = NULL; - if (cg && - cg->spCellConfig && - cg->spCellConfig->spCellConfigDedicated && - cg->spCellConfig->spCellConfigDedicated->uplinkConfig && - cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) { + if (sched_ctrl->active_ubwp) { + if (sched_ctrl->active_ubwp->bwp_Dedicated && + sched_ctrl->active_ubwp->bwp_Dedicated->srs_Config) { + srs_config = sched_ctrl->active_ubwp->bwp_Dedicated->srs_Config->choice.setup; + } + } else if (cg && + cg->spCellConfig && + cg->spCellConfig->spCellConfigDedicated && + cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) { srs_config = cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->srs_Config->choice.setup; - } else { + } + + if (!srs_config) { continue; } @@ -167,14 +175,15 @@ void nr_schedule_srs(int module_id, frame_t frame) { continue; } - NR_BWP_t ubwp = sched_ctrl->active_ubwp ? - sched_ctrl->active_ubwp->bwp_Common->genericParameters : - scc->uplinkConfigCommon->initialUplinkBWP->genericParameters; + const NR_SIB1_t *sib1 = nrmac->common_channels[0].sib1 ? nrmac->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL; + NR_BWP_t *genericParameters = get_ul_bwp_genericParameters(sched_ctrl->active_ubwp, + scc, + sib1); uint16_t period = srs_period[srs_resource->resourceType.choice.periodic->periodicityAndOffset_p.present]; uint16_t offset = get_nr_srs_offset(srs_resource->resourceType.choice.periodic->periodicityAndOffset_p); - int n_slots_frame = nr_slots_per_frame[ubwp.subcarrierSpacing]; + int n_slots_frame = nr_slots_per_frame[genericParameters->subcarrierSpacing]; // Check if UE will transmit the SRS in this frame if ( ((frame - offset/n_slots_frame)*n_slots_frame)%period == 0) { From 8d02c2c0fcecc100002e5d627ec71956248112be Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Wed, 25 May 2022 11:06:55 +0100 Subject: [PATCH 20/60] Fix scheduling SRS transmission at UE when there is Dedicated BWPs --- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 906a5d2d6c..b394d18cb8 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -929,15 +929,23 @@ bool nr_ue_periodic_srs_scheduling(module_id_t mod_id, frame_t frame, slot_t slo bool srs_scheduled = false; NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); + NR_BWP_Id_t ul_bwp_id = mac->UL_BWP_Id; NR_SRS_Config_t *srs_config = NULL; - if (mac->cg && - mac->cg->spCellConfig && - mac->cg->spCellConfig->spCellConfigDedicated && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && - mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) { + if (ul_bwp_id > 0 && mac->ULbwp[ul_bwp_id-1]) { + if (mac->ULbwp[ul_bwp_id-1]->bwp_Dedicated && + mac->ULbwp[ul_bwp_id-1]->bwp_Dedicated->srs_Config) { + srs_config = mac->ULbwp[ul_bwp_id-1]->bwp_Dedicated->srs_Config->choice.setup; + } + } else if (mac->cg && + mac->cg->spCellConfig && + mac->cg->spCellConfig->spCellConfigDedicated && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig && + mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) { srs_config = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->srs_Config->choice.setup; - } else { + } + + if (!srs_config) { return false; } @@ -965,7 +973,6 @@ bool nr_ue_periodic_srs_scheduling(module_id_t mod_id, frame_t frame, slot_t slo continue; } - NR_BWP_Id_t ul_bwp_id = mac->UL_BWP_Id; NR_BWP_t ubwp = ul_bwp_id > 0 && mac->ULbwp[ul_bwp_id-1] ? mac->ULbwp[ul_bwp_id-1]->bwp_Common->genericParameters : mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters; From 264eebfb3f4d25cbdb10a7201d2b32fff574172d Mon Sep 17 00:00:00 2001 From: rmagueta Date: Fri, 27 May 2022 11:54:53 +0100 Subject: [PATCH 21/60] Fix build after merge --- openair2/GNB_APP/MACRLC_nr_paramdef.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/openair2/GNB_APP/MACRLC_nr_paramdef.h b/openair2/GNB_APP/MACRLC_nr_paramdef.h index 1f57087194..22b83f4064 100644 --- a/openair2/GNB_APP/MACRLC_nr_paramdef.h +++ b/openair2/GNB_APP/MACRLC_nr_paramdef.h @@ -130,18 +130,18 @@ #define MACRLC_ULSCH_MAX_FRAME_INACTIVITY 17 #define MACRLC_PUSCHTARGETSNRX10_IDX 18 #define MACRLC_PUCCHTARGETSNRX10_IDX 19 -#define MACRLC_UL_PRBBLACK_SNR_THRESHOLD_IDX -#define MACRLC_PUCCHFAILURETHRES_IDX 20 -#define MACRLC_PUSCHFAILURETHRES_IDX 21 -#define MACRLC_DL_BLER_TARGET_UPPER_IDX 22 -#define MACRLC_DL_BLER_TARGET_LOWER_IDX 23 -#define MACRLC_DL_MAX_MCS_IDX 24 -#define MACRLC_UL_BLER_TARGET_UPPER_IDX 25 -#define MACRLC_UL_BLER_TARGET_LOWER_IDX 26 -#define MACRLC_UL_MAX_MCS_IDX 27 -#define MACRLC_HARQ_ROUND_MAX_IDX 28 -#define MACRLC_MIN_GRANT_PRB_IDX 29 -#define MACRLC_MIN_GRANT_MCS_IDX 30 +#define MACRLC_UL_PRBBLACK_SNR_THRESHOLD_IDX 20 +#define MACRLC_PUCCHFAILURETHRES_IDX 21 +#define MACRLC_PUSCHFAILURETHRES_IDX 22 +#define MACRLC_DL_BLER_TARGET_UPPER_IDX 23 +#define MACRLC_DL_BLER_TARGET_LOWER_IDX 24 +#define MACRLC_DL_MAX_MCS_IDX 25 +#define MACRLC_UL_BLER_TARGET_UPPER_IDX 26 +#define MACRLC_UL_BLER_TARGET_LOWER_IDX 27 +#define MACRLC_UL_MAX_MCS_IDX 28 +#define MACRLC_HARQ_ROUND_MAX_IDX 29 +#define MACRLC_MIN_GRANT_PRB_IDX 30 +#define MACRLC_MIN_GRANT_MCS_IDX 31 /*---------------------------------------------------------------------------------------------------------------------------------------------------------*/ #endif From 616927c04d993820cefc25fb5276c22bf7a19837 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Wed, 1 Jun 2022 17:22:59 +0100 Subject: [PATCH 22/60] Fixes after merge --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 5571d27597..ad7db304bf 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -789,15 +789,14 @@ void handle_nr_srs_measurements(const module_id_t module_id, } #endif - const int UE_id = find_nr_UE_id(module_id,rnti); - if (UE_id < 0) { + NR_UE_info_t* UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, rnti); + if (!UE) { LOG_W(NR_MAC, "Could not find UE for RNTI 0x%04x\n", rnti); return; } gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; - NR_UE_info_t *UE_info = &nr_mac->UE_info; - NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id]; + NR_mac_stats_t *stats = &UE->mac_stats; stats->srs_wide_band_snr = (wide_band_snr>>1)-64; int ul_prbblack_SNR_threshold = nr_mac->ul_prbblack_SNR_threshold; From f6cbde534391d2a3d73ecbe3a91f2f92c22304c2 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Thu, 16 Jun 2022 12:49:13 +0100 Subject: [PATCH 23/60] Add const qualifier in some variables --- .../PHY/NR_ESTIMATION/nr_measurements_gNB.c | 6 ++-- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 30 +++++++++---------- openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 18 +++++------ openair1/SCHED_NR/phy_procedures_nr_gNB.c | 22 ++++++++------ openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c | 14 ++++----- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 4 +-- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 4 +-- openair2/RRC/NR/MESSAGES/asn1_msg.c | 2 +- openair2/RRC/NR/MESSAGES/asn1_msg.h | 2 +- openair2/RRC/NR/nr_rrc_config.c | 8 ++--- openair2/RRC/NR/nr_rrc_config.h | 6 ++-- 12 files changed, 61 insertions(+), 57 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index 403a96983c..c1be11c468 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -67,8 +67,8 @@ int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) return max_pos - sync_pos; } -int nr_est_timing_advance_srs(NR_DL_FRAME_PARMS *frame_parms, - int32_t **srs_estimated_channel_time) { +int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms, + const int32_t **srs_estimated_channel_time) { int timing_advance = 0; int max_val = 0; @@ -90,7 +90,7 @@ int nr_est_timing_advance_srs(NR_DL_FRAME_PARMS *frame_parms, } // Scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size - uint16_t bw_scaling = frame_parms->ofdm_symbol_size >> 7; + const uint16_t bw_scaling = frame_parms->ofdm_symbol_size >> 7; // do some integer rounding to improve TA accuracy int sync_pos_rounded; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 448df9b468..f28f68acbd 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -950,7 +950,7 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, }//Antenna loop } -uint32_t calc_power(const int16_t *x, uint32_t size) { +uint32_t calc_power(const int16_t *x, const uint32_t size) { int64_t sum_x = 0; int64_t sum_x2 = 0; for(int k = 0; kframe_parms; + const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; int32_t **srs_ls_estimated_channel = nr_srs_info->srs_ls_estimated_channel; int16_t ch_real[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length]; @@ -1110,13 +1110,13 @@ int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, // Compute noise power - uint8_t signal_power_bits = log2_approx(*signal_power); - uint8_t factor_bits = signal_power_bits < 32 ? 32 - signal_power_bits : 0; // 32 due to input of dB_fixed(uint32_t x) - int32_t factor_dB = dB_fixed(1<first_carrier_offset + srs_pdu->bwp_start*12; - uint8_t srs_symbols_per_rb = srs_pdu->comb_size == 0 ? 6 : 3; - uint8_t n_noise_estimates = frame_parms->nb_antennas_rx*srs_symbols_per_rb; + const uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*12; + const uint8_t srs_symbols_per_rb = srs_pdu->comb_size == 0 ? 6 : 3; + const uint8_t n_noise_estimates = frame_parms->nb_antennas_rx*srs_symbols_per_rb; uint8_t count_estimates = 0; uint64_t sum_re = 0; uint64_t sum_re2 = 0; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 914b0d7385..01af743473 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -55,8 +55,8 @@ void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq int nr_est_timing_advance_pusch(PHY_VARS_gNB* phy_vars_gNB, int UE_id); -int nr_est_timing_advance_srs(NR_DL_FRAME_PARMS *frame_parms, - int32_t **srs_estimated_channel_time); +int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms, + const int32_t **srs_estimated_channel_time); void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, NR_DL_FRAME_PARMS *frame_parms, @@ -66,13 +66,13 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, unsigned char symbol, uint32_t nb_re_pusch); -int nr_srs_channel_estimation(PHY_VARS_gNB *gNB, - int frame, - int slot, - nfapi_nr_srs_pdu_t *srs_pdu, - nr_srs_info_t *nr_srs_info, - int32_t *srs_generated_signal, - int32_t **srs_received_signal, +int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB, + const int frame, + const int slot, + const nfapi_nr_srs_pdu_t *srs_pdu, + const nr_srs_info_t *nr_srs_info, + const int32_t *srs_generated_signal, + const int32_t **srs_received_signal, int32_t **srs_estimated_channel_freq, int32_t **srs_estimated_channel_time, int32_t **srs_estimated_channel_time_shifted, diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 0198298101..522487c53a 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -633,11 +633,11 @@ void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) } -int fill_srs_reported_symbol_list(nfapi_nr_srs_indication_reported_symbol_t* reported_symbol_list, - nfapi_nr_srs_pdu_t *srs_pdu, - int N_RB_UL, +int fill_srs_reported_symbol_list(nfapi_nr_srs_indication_reported_symbol_t *reported_symbol_list, + const nfapi_nr_srs_pdu_t *srs_pdu, + const int N_RB_UL, const int8_t *snr_per_rb, - int srs_est) { + const int srs_est) { reported_symbol_list->num_rbs = srs_bandwidth_config[srs_pdu->config_index][srs_pdu->bandwidth_index][0]; @@ -865,13 +865,16 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { generate_srs_nr(srs_pdu, &gNB->frame_parms, gNB->nr_srs_info[i]->srs_generated_signal, gNB->nr_srs_info[i], AMP, frame_rx, slot_rx); } - int srs_est = nr_get_srs_signal(gNB,frame_rx,slot_rx,srs_pdu, gNB->nr_srs_info[i], gNB->nr_srs_info[i]->srs_received_signal); + const int srs_est = nr_get_srs_signal(gNB,frame_rx,slot_rx,srs_pdu, gNB->nr_srs_info[i], gNB->nr_srs_info[i]->srs_received_signal); if (srs_est >= 0) { - nr_srs_channel_estimation(gNB,frame_rx,slot_rx,srs_pdu, + nr_srs_channel_estimation(gNB, + frame_rx, + slot_rx, + srs_pdu, gNB->nr_srs_info[i], gNB->nr_srs_info[i]->srs_generated_signal, - gNB->nr_srs_info[i]->srs_received_signal, + (const int32_t **)gNB->nr_srs_info[i]->srs_received_signal, gNB->nr_srs_info[i]->srs_estimated_channel_freq, gNB->nr_srs_info[i]->srs_estimated_channel_time, gNB->nr_srs_info[i]->srs_estimated_channel_time_shifted, @@ -888,13 +891,14 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { T(T_GNB_PHY_UL_TIME_CHANNEL_ESTIMATE, T_INT(0), T_INT(srs_pdu->rnti), T_INT(frame_rx), T_INT(0), T_INT(0), T_BUFFER(gNB->nr_srs_info[i]->srs_estimated_channel_time_shifted[0], gNB->frame_parms.ofdm_symbol_size*sizeof(int32_t))); - uint16_t num_srs = gNB->UL_INFO.srs_ind.number_of_pdus; + const uint16_t num_srs = gNB->UL_INFO.srs_ind.number_of_pdus; gNB->UL_INFO.srs_ind.pdu_list = &gNB->srs_pdu_list[0]; gNB->UL_INFO.srs_ind.sfn = frame_rx; gNB->UL_INFO.srs_ind.slot = slot_rx; gNB->srs_pdu_list[num_srs].handle = srs_pdu->handle; gNB->srs_pdu_list[num_srs].rnti = srs_pdu->rnti; - gNB->srs_pdu_list[num_srs].timing_advance = nr_est_timing_advance_srs(&gNB->frame_parms, gNB->nr_srs_info[i]->srs_estimated_channel_time); + gNB->srs_pdu_list[num_srs].timing_advance = nr_est_timing_advance_srs(&gNB->frame_parms, + (const int32_t **)gNB->nr_srs_info[i]->srs_estimated_channel_time); gNB->srs_pdu_list[num_srs].num_symbols = 1<num_symbols; gNB->srs_pdu_list[num_srs].wide_band_snr = srs_est >= 0 ? (*gNB->nr_srs_info[i]->snr + 64)<<1 : 0xFF; // 0xFF will be set if this field is invalid gNB->srs_pdu_list[num_srs].num_reported_symbols = 1<num_symbols; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 9f7fa89146..ce4b16fdc7 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -928,7 +928,7 @@ bool nr_ue_periodic_srs_scheduling(module_id_t mod_id, frame_t frame, slot_t slo bool srs_scheduled = false; NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id); - NR_BWP_Id_t ul_bwp_id = mac->UL_BWP_Id; + const NR_BWP_Id_t ul_bwp_id = mac->UL_BWP_Id; NR_SRS_Config_t *srs_config = NULL; if (ul_bwp_id > 0 && mac->ULbwp[ul_bwp_id-1]) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index 7a21ad82e8..e737fc7107 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -41,9 +41,9 @@ void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, int module_id, int CC_id,NR_U NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; const NR_SIB1_t *sib1 = nrmac->common_channels[0].sib1 ? nrmac->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL; - NR_BWP_t *genericParameters = get_ul_bwp_genericParameters(sched_ctrl->active_ubwp, - scc, - sib1); + const NR_BWP_t *genericParameters = get_ul_bwp_genericParameters(sched_ctrl->active_ubwp, + scc, + sib1); srs_pdu->rnti = UE->rnti; srs_pdu->handle = 0; @@ -173,14 +173,14 @@ void nr_schedule_srs(int module_id, frame_t frame) { } const NR_SIB1_t *sib1 = nrmac->common_channels[0].sib1 ? nrmac->common_channels[0].sib1->message.choice.c1->choice.systemInformationBlockType1 : NULL; - NR_BWP_t *genericParameters = get_ul_bwp_genericParameters(sched_ctrl->active_ubwp, - scc, - sib1); + const NR_BWP_t *genericParameters = get_ul_bwp_genericParameters(sched_ctrl->active_ubwp, + scc, + sib1); uint16_t period = srs_period[srs_resource->resourceType.choice.periodic->periodicityAndOffset_p.present]; uint16_t offset = get_nr_srs_offset(srs_resource->resourceType.choice.periodic->periodicityAndOffset_p); - int n_slots_frame = nr_slots_per_frame[genericParameters->subcarrierSpacing]; + const int n_slots_frame = nr_slots_per_frame[genericParameters->subcarrierSpacing]; // Check if UE will transmit the SRS in this frame if ( ((frame - offset/n_slots_frame)*n_slots_frame)%period == 0) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index e815ffcc47..21045cd21e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -789,7 +789,7 @@ void handle_nr_srs_measurements(const module_id_t module_id, } #endif - NR_UE_info_t* UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, rnti); + NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, rnti); if (!UE) { LOG_W(NR_MAC, "Could not find UE for RNTI 0x%04x\n", rnti); return; @@ -799,7 +799,7 @@ void handle_nr_srs_measurements(const module_id_t module_id, NR_mac_stats_t *stats = &UE->mac_stats; stats->srs_wide_band_snr = (wide_band_snr>>1)-64; - int ul_prbblack_SNR_threshold = nr_mac->ul_prbblack_SNR_threshold; + const int ul_prbblack_SNR_threshold = nr_mac->ul_prbblack_SNR_threshold; uint16_t *ulprbbl = nr_mac->ulprbbl; memset(ulprbbl, 0, reported_symbol_list[0].num_rbs*sizeof(uint16_t)); diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index c78a4e926e..47705082d1 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -230,8 +230,8 @@ void handle_nr_srs(NR_UL_IND_t *UL_info) { const module_id_t module_id = UL_info->module_id; const frame_t frame = UL_info->srs_ind.sfn; const sub_frame_t slot = UL_info->srs_ind.slot; - int num_srs = UL_info->srs_ind.number_of_pdus; - nfapi_nr_srs_indication_pdu_t *srs_list = UL_info->srs_ind.pdu_list; + const int num_srs = UL_info->srs_ind.number_of_pdus; + const nfapi_nr_srs_indication_pdu_t *srs_list = UL_info->srs_ind.pdu_list; for (int i = 0; i < num_srs; i++) { const nfapi_nr_srs_indication_pdu_t *srs_ind = &srs_list[i]; diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index a2fb44aac9..fff4043a4d 100755 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -2067,7 +2067,7 @@ void fill_mastercellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, NR_CellGr } void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, - int uid, + const int uid, NR_UE_NR_Capability_t *uecap, const gNB_RrcConfigurationReq* configuration) { diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 3b881231b0..bff7dcfce5 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -114,7 +114,7 @@ void fill_initial_cellGroupConfig(int uid, const gNB_RrcConfigurationReq *configuration); void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, - int uid, + const int uid, NR_UE_NR_Capability_t *uecap, const gNB_RrcConfigurationReq *configuration); diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index c71e21f999..fd2c92d867 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -324,7 +324,7 @@ void config_csiim(int do_csirs, int dl_antenna_ports, int curr_bwp, } // TODO: Implement to b_SRS = 1 and b_SRS = 2 -long rrc_get_max_nr_csrs(uint8_t max_rbs, long b_SRS) { +long rrc_get_max_nr_csrs(const uint8_t max_rbs, const long b_SRS) { if(b_SRS>0) { LOG_E(NR_RRC,"rrc_get_max_nr_csrs(): Not implemented yet for b_SRS>0\n"); @@ -349,9 +349,9 @@ long rrc_get_max_nr_csrs(uint8_t max_rbs, long b_SRS) { } void config_srs(NR_SetupRelease_SRS_Config_t *setup_release_srs_Config, - NR_ServingCellConfigCommon_t *servingcellconfigcommon, - int uid, - int do_srs) { + const NR_ServingCellConfigCommon_t *servingcellconfigcommon, + const int uid, + const int do_srs) { setup_release_srs_Config->present = NR_SetupRelease_SRS_Config_PR_setup; diff --git a/openair2/RRC/NR/nr_rrc_config.h b/openair2/RRC/NR/nr_rrc_config.h index 31d8ad9c80..4544f9e92f 100644 --- a/openair2/RRC/NR/nr_rrc_config.h +++ b/openair2/RRC/NR/nr_rrc_config.h @@ -129,9 +129,9 @@ void config_csirs(NR_ServingCellConfigCommon_t *servingcellconfigcommon, void config_csiim(int do_csirs, int dl_antenna_ports, int curr_bwp, NR_CSI_MeasConfig_t *csi_MeasConfig); void config_srs(NR_SetupRelease_SRS_Config_t *setup_release_srs_Config, - NR_ServingCellConfigCommon_t *servingcellconfigcommon, - int uid, - int do_srs); + const NR_ServingCellConfigCommon_t *servingcellconfigcommon, + const int uid, + const int do_srs); void set_dl_mcs_table(int scs, NR_UE_NR_Capability_t *cap, NR_SpCellConfig_t *SpCellConfig, NR_BWP_DownlinkDedicated_t *bwp_Dedicated, From 61e42ce9c61a14a827dfe323807b78f6674fa55f Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Thu, 16 Jun 2022 13:29:30 +0100 Subject: [PATCH 24/60] Consider the invalid timing advance value case for SRS estimation --- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 522487c53a..fb4e5a85ef 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -897,8 +897,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { gNB->UL_INFO.srs_ind.slot = slot_rx; gNB->srs_pdu_list[num_srs].handle = srs_pdu->handle; gNB->srs_pdu_list[num_srs].rnti = srs_pdu->rnti; - gNB->srs_pdu_list[num_srs].timing_advance = nr_est_timing_advance_srs(&gNB->frame_parms, - (const int32_t **)gNB->nr_srs_info[i]->srs_estimated_channel_time); + gNB->srs_pdu_list[num_srs].timing_advance = srs_est >= 0 ? nr_est_timing_advance_srs(&gNB->frame_parms, + (const int32_t **)gNB->nr_srs_info[i]->srs_estimated_channel_time) : 0xFFFF; gNB->srs_pdu_list[num_srs].num_symbols = 1<num_symbols; gNB->srs_pdu_list[num_srs].wide_band_snr = srs_est >= 0 ? (*gNB->nr_srs_info[i]->snr + 64)<<1 : 0xFF; // 0xFF will be set if this field is invalid gNB->srs_pdu_list[num_srs].num_reported_symbols = 1<num_symbols; From 6f481e09f6aceefacca0e547ea7a4bb466a20864 Mon Sep 17 00:00:00 2001 From: francescomani Date: Wed, 22 Jun 2022 16:15:31 +0200 Subject: [PATCH 25/60] abort rtx if RI decreased --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 25 ++++++++++++++++++- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 10 ++------ openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 ++ openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 + 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 3b5c9ffad4..dce798f24f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -365,6 +365,18 @@ void nr_store_dlsch_buffer(module_id_t module_id, } } +void abort_nr_dl_harq(NR_UE_info_t* UE, int8_t harq_pid) { + + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + NR_UE_harq_t *harq = &sched_ctrl->harq_processes[harq_pid]; + + harq->ndi ^= 1; + harq->round = 0; + UE->mac_stats.dl.errors++; + add_tail_nr_list(&sched_ctrl->available_dl_harq, harq_pid); + +} + bool allocate_dl_retransmission(module_id_t module_id, frame_t frame, sub_frame_t slot, @@ -378,6 +390,16 @@ bool allocate_dl_retransmission(module_id_t module_id, NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_sched_pdsch_t *retInfo = &sched_ctrl->harq_processes[current_harq_pid].sched_pdsch; NR_CellGroupConfig_t *cg = UE->CellGroup; + NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; + + //TODO remove this and handle retransmission with old nrOfLayers + // once ps structure is removed + if(ps->nrOfLayers < retInfo->nrOfLayers) { + LOG_W(NR_MAC,"Cannot schedule retransmission. RI changed from %d to %d\n", + retInfo->nrOfLayers, ps->nrOfLayers); + abort_nr_dl_harq(UE, current_harq_pid); + return false; + } NR_BWP_DownlinkDedicated_t *bwpd = cg && @@ -401,7 +423,6 @@ bool allocate_dl_retransmission(module_id_t module_id, const uint16_t bwpSize = coresetid == 0 ? RC.nrmac[module_id]->cset0_bwp_size : NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE); int rbStart = 0; // start wrt BWPstart - NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static; int rbSize = 0; const int tda = get_dl_tda(RC.nrmac[module_id], scc, slot); AssertFatal(tda>=0,"Unable to find PDSCH time domain allocation in list\n"); @@ -1355,6 +1376,8 @@ void nr_schedule_ue_spec(module_id_t module_id, /* save which time allocation has been used, to be used on * retransmissions */ harq->sched_pdsch.time_domain_allocation = ps->time_domain_allocation; + /* save nr of layers for retransmissions */ + harq->sched_pdsch.nrOfLayers = ps->nrOfLayers; // ta command is sent, values are reset if (sched_ctrl->ta_apply) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index d64b9c43db..a9a67141a2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -826,14 +826,8 @@ static void handle_dl_harq(NR_UE_info_t * UE, harq->ndi ^= 1; } else if (harq->round >= harq_round_max - 1) { - add_tail_nr_list(&UE->UE_sched_ctrl.available_dl_harq, harq_pid); - harq->round = 0; - harq->ndi ^= 1; - - NR_mac_stats_t *stats = &UE->mac_stats; - stats->dl.errors++; - LOG_D(NR_MAC, "retransmission error for UE %04x (total %"PRIu64")\n", UE->rnti, stats->dl.errors); - + abort_nr_dl_harq(UE, harq_pid); + LOG_D(NR_MAC, "retransmission error for UE %04x (total %"PRIu64")\n", UE->rnti, UE->mac_stats.dl.errors); } else { LOG_D(PHY,"NACK for: pid %d, ue %04x\n",harq_pid, UE->rnti); add_tail_nr_list(&UE->UE_sched_ctrl.retrans_dl_harq, harq_pid); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 7911275f70..bf36264b9d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -532,4 +532,6 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset void process_CellGroup(NR_CellGroupConfig_t *CellGroup, NR_UE_sched_ctrl_t *sched_ctrl); +void abort_nr_dl_harq(NR_UE_info_t* UE, int8_t harq_pid); + #endif /*__LAYER2_NR_MAC_PROTO_H__*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 7658441aed..049c7547ec 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -440,6 +440,7 @@ typedef struct NR_sched_pdsch { /// only important for retransmissions; otherwise, the TDA in /// NR_pdsch_semi_static_t has precedence int time_domain_allocation; + uint8_t nrOfLayers; } NR_sched_pdsch_t; typedef struct NR_UE_harq { From 586aa46c2c6032ddc29329f7beae27460f687168 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 22 Jun 2022 16:54:35 +0200 Subject: [PATCH 26/60] Set correct master clock rate for N320 --- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 8976284345..cdd8f22b98 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -1030,9 +1030,13 @@ extern "C" { } if (device_adds[0].get("type") == "n3xx") { - printf("Found USRP n300\n"); + const std::string product = device_adds[0].get("product"); + printf("Found USRP %s\n", product.c_str()); device->type=USRP_N300_DEV; - usrp_master_clock = 122.88e6; + if (product == "n320") + usrp_master_clock = 245.76e6; // N320 does not support 122.88e6 master clock rate + else + usrp_master_clock = 122.88e6; args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); if ( 0 != system("sysctl -w net.core.rmem_max=62500000 net.core.wmem_max=62500000") ) From 1a4686b021fac4581383ca0823664dee2867744a Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Thu, 23 Jun 2022 14:52:05 +0100 Subject: [PATCH 27/60] Remove UE->Msg4_ACKed from condition in nr_schedule_srs --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index e737fc7107..4be176714e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -124,7 +124,7 @@ void nr_schedule_srs(int module_id, frame_t frame) { sched_ctrl->sched_srs.srs_scheduled = false; if((sched_ctrl->ul_failure == 1 && get_softmodem_params()->phy_test==0) || - !UE->Msg4_ACKed || sched_ctrl->rrc_processing_timer > 0) { + sched_ctrl->rrc_processing_timer > 0) { continue; } From 15656679087734702d93d84f3dfd0db8d0c8ca86 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 23 Jun 2022 17:42:55 +0200 Subject: [PATCH 28/60] remove rtx from list --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index dce798f24f..d9a0a50b7e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -398,6 +398,7 @@ bool allocate_dl_retransmission(module_id_t module_id, LOG_W(NR_MAC,"Cannot schedule retransmission. RI changed from %d to %d\n", retInfo->nrOfLayers, ps->nrOfLayers); abort_nr_dl_harq(UE, current_harq_pid); + remove_front_nr_list(&sched_ctrl->retrans_dl_harq); return false; } From 07a3634e4523ceb43c18b29eaa52dd8694615b75 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Thu, 23 Jun 2022 18:23:23 +0100 Subject: [PATCH 29/60] Change some heap allocations to stack allocations --- openair1/PHY/INIT/nr_init.c | 14 -------------- openair1/PHY/INIT/nr_init_ue.c | 6 ------ openair1/PHY/defs_nr_common.h | 14 +++++++------- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 8 ++++---- 4 files changed, 11 insertions(+), 31 deletions(-) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 1f2383c60c..bd349d146a 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -613,13 +613,6 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, for (int id=0; idnr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t)); - gNB->nr_srs_info[id]->sc_list = (uint16_t *) malloc16_clear(6*fp->N_RB_UL*sizeof(uint16_t)); - gNB->nr_srs_info[id]->srs_generated_signal = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t)); - gNB->nr_srs_info[id]->signal_power = (uint32_t*)malloc16_clear(sizeof(uint32_t)); - gNB->nr_srs_info[id]->noise_power_per_rb = (uint32_t*)malloc16_clear(fp->N_RB_UL*sizeof(uint32_t)); - gNB->nr_srs_info[id]->noise_power = (uint32_t*)malloc16_clear(sizeof(uint32_t)); - gNB->nr_srs_info[id]->snr_per_rb = (int8_t*)malloc16_clear(fp->N_RB_UL*sizeof(int8_t)); - gNB->nr_srs_info[id]->snr = (int8_t*)malloc16_clear(sizeof(int8_t)); gNB->nr_srs_info[id]->srs_received_signal = (int32_t **)malloc16(Prx*sizeof(int32_t*)); gNB->nr_srs_info[id]->srs_ls_estimated_channel = (int32_t **)malloc16(Prx*sizeof(int32_t*)); gNB->nr_srs_info[id]->srs_estimated_channel_freq = (int32_t **)malloc16(Prx*sizeof(int32_t*)); @@ -796,13 +789,6 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_time[i]); free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_time_shifted[i]); } - free_and_zero(gNB->nr_srs_info[id]->sc_list); - free_and_zero(gNB->nr_srs_info[id]->srs_generated_signal); - free_and_zero(gNB->nr_srs_info[id]->signal_power); - free_and_zero(gNB->nr_srs_info[id]->noise_power_per_rb); - free_and_zero(gNB->nr_srs_info[id]->noise_power); - free_and_zero(gNB->nr_srs_info[id]->snr_per_rb); - free_and_zero(gNB->nr_srs_info[id]->snr); free_and_zero(gNB->nr_srs_info[id]->srs_received_signal); free_and_zero(gNB->nr_srs_info[id]->srs_ls_estimated_channel); free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_freq); diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index c6e6ecd463..254a25097c 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -377,9 +377,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) } ue->nr_srs_info = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t)); - ue->nr_srs_info->sc_list = (uint16_t *) malloc16_clear(6*fp->N_RB_UL*sizeof(uint16_t)); - ue->nr_srs_info->srs_generated_signal = (int32_t *) malloc16_clear( (2*(fp->samples_per_frame)+2048)*sizeof(int32_t) ); - ue->nr_srs_info->noise_power = (uint32_t*)malloc16_clear(sizeof(uint32_t)); ue->nr_srs_info->srs_received_signal = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) ); ue->nr_srs_info->srs_ls_estimated_channel = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) ); ue->nr_srs_info->srs_estimated_channel_freq = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) ); @@ -527,9 +524,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) free_and_zero(ue->nr_srs_info->srs_estimated_channel_time[i]); free_and_zero(ue->nr_srs_info->srs_estimated_channel_time_shifted[i]); } - free_and_zero(ue->nr_srs_info->sc_list); - free_and_zero(ue->nr_srs_info->srs_generated_signal); - free_and_zero(ue->nr_srs_info->noise_power); free_and_zero(ue->nr_srs_info->srs_received_signal); free_and_zero(ue->nr_srs_info->srs_ls_estimated_channel); free_and_zero(ue->nr_srs_info->srs_estimated_channel_freq); diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 657d05fc6e..fe895d1770 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -241,19 +241,19 @@ typedef struct { typedef struct { uint16_t sc_list_length; - uint16_t *sc_list; + uint16_t sc_list[6*273]; uint8_t srs_generated_signal_bits; - int32_t *srs_generated_signal; + int32_t srs_generated_signal[OFDM_SYMBOL_SIZE_SAMPLES_MAX * MAX_NUM_NR_SRS_SYMBOLS]; int32_t **srs_received_signal; int32_t **srs_ls_estimated_channel; int32_t **srs_estimated_channel_freq; int32_t **srs_estimated_channel_time; int32_t **srs_estimated_channel_time_shifted; - uint32_t *signal_power; - uint32_t *noise_power_per_rb; - uint32_t *noise_power; - int8_t *snr_per_rb; - int8_t *snr; + uint32_t signal_power; + uint32_t noise_power_per_rb[273]; + uint32_t noise_power; + int8_t snr_per_rb[273]; + int8_t snr; } nr_srs_info_t; typedef struct { diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index fb4e5a85ef..56ee0d8db2 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -878,11 +878,11 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { gNB->nr_srs_info[i]->srs_estimated_channel_freq, gNB->nr_srs_info[i]->srs_estimated_channel_time, gNB->nr_srs_info[i]->srs_estimated_channel_time_shifted, - gNB->nr_srs_info[i]->signal_power, + &gNB->nr_srs_info[i]->signal_power, gNB->nr_srs_info[i]->noise_power_per_rb, - gNB->nr_srs_info[i]->noise_power, + &gNB->nr_srs_info[i]->noise_power, gNB->nr_srs_info[i]->snr_per_rb, - gNB->nr_srs_info[i]->snr); + &gNB->nr_srs_info[i]->snr); } T(T_GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE, T_INT(0), T_INT(srs_pdu->rnti), T_INT(frame_rx), T_INT(0), T_INT(0), @@ -900,7 +900,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { gNB->srs_pdu_list[num_srs].timing_advance = srs_est >= 0 ? nr_est_timing_advance_srs(&gNB->frame_parms, (const int32_t **)gNB->nr_srs_info[i]->srs_estimated_channel_time) : 0xFFFF; gNB->srs_pdu_list[num_srs].num_symbols = 1<num_symbols; - gNB->srs_pdu_list[num_srs].wide_band_snr = srs_est >= 0 ? (*gNB->nr_srs_info[i]->snr + 64)<<1 : 0xFF; // 0xFF will be set if this field is invalid + gNB->srs_pdu_list[num_srs].wide_band_snr = srs_est >= 0 ? (gNB->nr_srs_info[i]->snr + 64)<<1 : 0xFF; // 0xFF will be set if this field is invalid gNB->srs_pdu_list[num_srs].num_reported_symbols = 1<num_symbols; if(!gNB->srs_pdu_list[num_srs].reported_symbol_list) { gNB->srs_pdu_list[num_srs].reported_symbol_list = (nfapi_nr_srs_indication_reported_symbol_t*) calloc(1, gNB->srs_pdu_list[num_srs].num_reported_symbols*sizeof(nfapi_nr_srs_indication_reported_symbol_t)); From c5b8fa5418bceb033a5fa02a758a8760b8dd0e95 Mon Sep 17 00:00:00 2001 From: Ilario FAVERO Date: Thu, 9 Jun 2022 12:53:44 +0200 Subject: [PATCH 30/60] New command line arg for disabling stats: --disable-stats --- executables/nr-gnb.c | 2 +- executables/nr-ue.c | 6 ++++-- executables/softmodem-common.c | 3 +++ executables/softmodem-common.h | 4 ++++ openair2/LAYER2/NR_MAC_gNB/main.c | 4 ++-- 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c index 327c01af6a..bc3dccf4fa 100644 --- a/executables/nr-gnb.c +++ b/executables/nr-gnb.c @@ -466,7 +466,7 @@ void init_gNB_Tpool(int inst) { pushNotifiedFIFO(gNB->L1_tx_free,msgL1Tx); // to unblock the process in the beginning } - if (!get_softmodem_params()->emulate_l1) + if ((!get_softmodem_params()->emulate_l1) && (!IS_SOFTMODEM_NOSTATS_BIT)) threadCreate(&proc->L1_stats_thread,nrL1_stats_thread,(void*)gNB,"L1_stats",-1,OAI_PRIORITY_RT_LOW); threadCreate(&proc->pthread_tx_reorder, tx_reorder_thread, (void *)gNB, "thread_tx_reorder", -1, OAI_PRIORITY_RT_MAX); diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 01e6c62138..7b39dfdcaa 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -1109,8 +1109,10 @@ void init_NR_UE_threads(int nb_inst) { LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]); threadCreate(&threads[inst], UE_thread, (void *)UE, "UEthread", -1, OAI_PRIORITY_RT_MAX); - pthread_t stat_pthread; - threadCreate(&stat_pthread, nrL1_UE_stats_thread, UE, "L1_UE_stats", -1, OAI_PRIORITY_RT_LOW); + if (!IS_SOFTMODEM_NOSTATS_BIT) { + pthread_t stat_pthread; + threadCreate(&stat_pthread, nrL1_UE_stats_thread, UE, "L1_UE_stats", -1, OAI_PRIORITY_RT_LOW); + } } } diff --git a/executables/softmodem-common.c b/executables/softmodem-common.c index c78fc70243..bf30cab847 100644 --- a/executables/softmodem-common.c +++ b/executables/softmodem-common.c @@ -85,6 +85,7 @@ char *get_softmodem_function(uint64_t *sofmodemfunc_mask_ptr) { } void get_common_options(uint32_t execmask) { + int32_t stats_disabled = 0; uint32_t online_log_messages=0; uint32_t glog_level=0 ; uint32_t start_telnetsrv = 0, start_telnetclt = 0; @@ -149,6 +150,8 @@ void get_common_options(uint32_t execmask) { if(worker_config != NULL) set_worker_conf(worker_config); nfapi_setmode(nfapi_mode); + if (stats_disabled) + set_softmodem_optmask(SOFTMODEM_NOSTATS_BIT); } void softmodem_printresources(int sig, telnet_printfunc_t pf) { struct rusage usage; diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 0310453ca0..a2ba680234 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -101,6 +101,7 @@ extern "C" #define CONFIG_HLP_NFAPI "Change the nFAPI mode for NR\n" #define CONFIG_L1_EMULATOR "Run in L1 emulated mode (disable PHY layer)\n" #define CONFIG_HLP_CONTINUOUS_TX "perform continuous transmission, even in TDD mode (to work around USRP issues)\n" +#define CONFIG_HLP_STATS_DISABLE "disable globally the stats generation and persistence" /*-----------------------------------------------------------------------------------------------------------------------------------------------------*/ /* command line parameters common to eNodeB and UE */ @@ -171,6 +172,7 @@ extern int usrp_tx_thread; {"non-stop", CONFIG_HLP_NONSTOP, PARAMFLAG_BOOL, iptr:&NON_STOP, defintval:0, TYPE_INT, 0}, \ {"emulate-l1", CONFIG_L1_EMULATOR, PARAMFLAG_BOOL, iptr:&EMULATE_L1, defintval:0, TYPE_INT, 0}, \ {"continuous-tx", CONFIG_HLP_CONTINUOUS_TX,PARAMFLAG_BOOL, iptr:&CONTINUOUS_TX, defintval:0, TYPE_INT, 0}, \ + {"disable-stats", CONFIG_HLP_STATS_DISABLE, PARAMFLAG_BOOL, iptr:&stats_disabled, defintval:0, TYPE_INT, 0}, \ } #define CONFIG_HLP_NSA "Enable NSA mode \n" @@ -217,6 +219,7 @@ extern int usrp_tx_thread; #define SOFTMODEM_GNB_BIT (1<<21) #define SOFTMODEM_4GUE_BIT (1<<22) #define SOFTMODEM_5GUE_BIT (1<<23) +#define SOFTMODEM_NOSTATS_BIT (1<<24) #define SOFTMODEM_FUNC_BITS (SOFTMODEM_ENB_BIT | SOFTMODEM_GNB_BIT | SOFTMODEM_5GUE_BIT | SOFTMODEM_4GUE_BIT) #define MAPPING_SOFTMODEM_FUNCTIONS {{"enb",SOFTMODEM_ENB_BIT},{"gnb",SOFTMODEM_GNB_BIT},{"4Gue",SOFTMODEM_4GUE_BIT},{"5Gue",SOFTMODEM_5GUE_BIT}} @@ -234,6 +237,7 @@ extern int usrp_tx_thread; #define IS_SOFTMODEM_GNB_BIT ( get_softmodem_optmask() & SOFTMODEM_GNB_BIT) #define IS_SOFTMODEM_4GUE_BIT ( get_softmodem_optmask() & SOFTMODEM_4GUE_BIT) #define IS_SOFTMODEM_5GUE_BIT ( get_softmodem_optmask() & SOFTMODEM_5GUE_BIT) +#define IS_SOFTMODEM_NOSTATS_BIT ( get_softmodem_optmask() & SOFTMODEM_NOSTATS_BIT) typedef struct { uint64_t optmask; diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 9b9fd4e76c..c05af4d4a8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -211,8 +211,8 @@ void mac_top_init_gNB(void) RC.nrmac[i]->pre_processor_dl = nr_init_fr1_dlsch_preprocessor(i, 0); RC.nrmac[i]->pre_processor_ul = nr_init_fr1_ulsch_preprocessor(i, 0); } - pthread_create(&RC.nrmac[i]->stats_thread,NULL,nrmac_stats_thread,(void*)RC.nrmac[i]); - + if (!IS_SOFTMODEM_NOSTATS_BIT) + pthread_create(&RC.nrmac[i]->stats_thread, NULL, nrmac_stats_thread, (void*)RC.nrmac[i]); }//END for (i = 0; i < RC.nb_nr_macrlc_inst; i++) AssertFatal(rlc_module_init(1) == 0,"Could not initialize RLC layer\n"); From 0b91791f674376c97d70c52fe0a2efa7e8798d80 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 24 Jun 2022 17:53:20 +0200 Subject: [PATCH 31/60] Use (std) bool instead of custom bool types OAI is riddled with boolean_t, FALSE, TRUE, etc. This makes no sense, as there is a standard bool type, and could lead to nasty bugs if a definition of a bool is non-standard (0 == false, true == !false). This commit removes all non-standard bools in the whole project. --- nfapi/oai_integration/nfapi_vnf.c | 4 +- openair1/PHY/LTE_TRANSPORT/dci_tools.c | 4 +- openair1/PHY/LTE_TRANSPORT/defs_NB_IoT.h | 2 +- .../PHY/NR_UE_TRANSPORT/nr_transport_ue.h | 2 +- openair1/PHY/TOOLS/calibration_scope.c | 4 +- openair1/PHY/TOOLS/nr_phy_scope.c | 4 +- openair1/PHY/defs_common.h | 6 +- openair1/SCHED_UE/phy_procedures_lte_ue.c | 2 +- .../NR_UE_PHY/unit_tests/src/pucch_uci_test.c | 96 ++++---- openair2/COMMON/commonDef.h | 21 -- openair2/COMMON/mac_rlc_primitives.h | 2 +- openair2/COMMON/platform_types.h | 61 ++--- openair2/ENB_APP/enb_config.c | 38 ++-- openair2/ENB_APP/enb_config_eMTC.c | 70 +++--- openair2/ENB_APP/flexran_agent_ran_api.c | 8 +- openair2/F1AP/dummy_enb.c | 26 +-- openair2/F1AP/f1ap_common.h | 7 - openair2/F1AP/f1ap_du_rrc_message_transfer.c | 18 +- openair2/F1AP/f1ap_du_ue_context_management.c | 24 +- openair2/LAYER2/MAC/config.c | 14 +- openair2/LAYER2/MAC/defs_NB_IoT.h | 11 +- openair2/LAYER2/MAC/eNB_scheduler.c | 44 ++-- openair2/LAYER2/MAC/eNB_scheduler_RA.c | 2 +- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 2 +- openair2/LAYER2/MAC/eNB_scheduler_fairRR.c | 24 +- .../LAYER2/MAC/eNB_scheduler_primitives.c | 24 +- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 8 +- openair2/LAYER2/MAC/mac.h | 34 +-- openair2/LAYER2/MAC/mac_extern.h | 2 +- openair2/LAYER2/MAC/mac_proto.h | 17 +- openair2/LAYER2/MAC/pre_processor.c | 2 +- openair2/LAYER2/MAC/ue_procedures.c | 28 +-- openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h | 2 +- openair2/LAYER2/NR_MAC_UE/config_ue.c | 2 +- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 4 +- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 18 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c | 14 +- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 14 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 - openair2/LAYER2/PDCP_v10.1.0/pdcp.c | 208 +++++++++--------- openair2/LAYER2/PDCP_v10.1.0/pdcp.h | 121 +++++----- .../LAYER2/PDCP_v10.1.0/pdcp_primitives.c | 33 +-- .../LAYER2/PDCP_v10.1.0/pdcp_primitives.h | 19 +- .../PDCP_v10.1.0/pdcp_sequence_manager.c | 36 +-- .../PDCP_v10.1.0/pdcp_sequence_manager.h | 16 +- openair2/LAYER2/PDCP_v10.1.0/pdcp_util.c | 6 +- openair2/LAYER2/PDCP_v10.1.0/pdcp_util.h | 4 +- openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c | 2 +- openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_entity.h | 8 +- openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c | 10 +- .../LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.c | 10 +- .../LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.h | 4 +- .../LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c | 2 +- .../LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.c | 82 ++++--- .../LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.h | 24 +- .../LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c | 35 ++- .../LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.h | 6 +- .../LAYER2/RLC/AM_v9.3.0/rlc_am_segment.c | 11 +- .../LAYER2/RLC/AM_v9.3.0/rlc_am_segment.h | 4 +- .../RLC/AM_v9.3.0/rlc_am_status_report.c | 16 +- openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c | 2 +- .../AM_v9.3.0/rlc_am_timer_poll_retransmit.c | 2 +- openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.c | 12 +- openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h | 13 +- openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_entity.h | 7 +- openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c | 7 +- openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h | 17 +- .../RLC/UM_v9.3.0/rlc_um_control_primitives.c | 2 +- openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_entity.h | 11 +- openair2/LAYER2/RLC/rlc.c | 15 +- openair2/LAYER2/RLC/rlc.h | 2 +- openair2/LAYER2/RLC/rlc_mac.c | 4 +- openair2/LAYER2/RLC/rlc_rrc.c | 10 +- openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c | 146 ++++++------ openair2/M2AP/m2ap_common.h | 5 - openair2/RRC/LITE/rrc_common.c | 2 +- openair2/RRC/LTE/L2_interface.c | 2 +- openair2/RRC/LTE/L2_interface_common.c | 4 +- openair2/RRC/LTE/L2_interface_ue.c | 2 +- openair2/RRC/LTE/MESSAGES/asn1_msg.c | 12 +- openair2/RRC/LTE/defs_NB_IoT.h | 2 +- openair2/RRC/LTE/rrc_UE.c | 9 +- openair2/RRC/LTE/rrc_defs.h | 4 +- openair2/RRC/LTE/rrc_eNB.c | 65 +++--- openair2/RRC/LTE/rrc_eNB_GTPV1U.c | 48 ++-- openair2/RRC/LTE/rrc_eNB_GTPV1U.h | 19 +- openair2/RRC/LTE/rrc_eNB_S1AP.c | 52 +++-- openair2/RRC/LTE/rrc_proto.h | 4 +- openair2/RRC/NR/L2_nr_interface.c | 6 +- openair2/RRC/NR/nr_rrc_defs.h | 2 +- openair2/RRC/NR/nr_rrc_proto.h | 47 ++-- openair2/RRC/NR/rrc_gNB.c | 41 ++-- openair2/RRC/NR/rrc_gNB_NGAP.c | 24 +- openair2/RRC/NR_UE/L2_interface_ue.c | 2 +- openair2/RRC/NR_UE/rrc_UE.c | 2 +- openair2/SDAP/nr_sdap/nr_sdap.c | 52 ++--- openair2/SDAP/nr_sdap/nr_sdap.h | 27 ++- openair2/SDAP/nr_sdap/nr_sdap_entity.c | 33 ++- openair2/SDAP/nr_sdap/nr_sdap_entity.h | 35 ++- openair2/X2AP/x2ap_common.h | 5 - openair3/M3AP/m3ap_common.h | 5 - openair3/NAS/COMMON/UTIL/nas_timer.c | 20 +- openair3/NAS/COMMON/UTIL/socket.c | 8 +- openair3/NAS/COMMON/UTIL/stty.c | 14 +- openair3/NAS/TEST/AS_SIMULATOR/as_simulator.c | 16 +- openair3/NAS/TEST/NETWORK/network_simulator.c | 8 +- openair3/NAS/TEST/USER/user_simulator.c | 4 +- openair3/NAS/UE/API/USER/at_command.c | 18 +- openair3/NAS/UE/API/USER/at_error.c | 6 +- openair3/NAS/UE/API/USER/at_response.c | 6 +- openair3/NAS/UE/EMM/Attach.c | 36 +-- openair3/NAS/UE/EMM/Authentication.c | 12 +- openair3/NAS/UE/EMM/Detach.c | 9 +- openair3/NAS/UE/EMM/EmmStatusHdl.c | 3 +- openair3/NAS/UE/EMM/Identification.c | 3 +- openair3/NAS/UE/EMM/IdleMode.c | 28 +-- openair3/NAS/UE/EMM/LowerLayer.c | 8 +- openair3/NAS/UE/EMM/LowerLayer.h | 2 +- openair3/NAS/UE/EMM/LowerLayer_defs.h | 2 +- .../SAP/EmmDeregisteredAttemptingToAttach.c | 2 +- .../EMM/SAP/EmmDeregisteredLimitedService.c | 2 +- .../UE/EMM/SAP/EmmDeregisteredNormalService.c | 2 +- openair3/NAS/UE/EMM/SAP/EmmRegistered.c | 2 +- .../NAS/UE/EMM/SAP/EmmRegisteredInitiated.c | 2 +- openair3/NAS/UE/EMM/SAP/emm_as.c | 6 +- openair3/NAS/UE/EMM/SAP/emm_asDef.h | 4 +- openair3/NAS/UE/EMM/SAP/emm_esmDef.h | 4 +- openair3/NAS/UE/EMM/SAP/emm_regDef.h | 4 +- openair3/NAS/UE/EMM/SecurityModeControl.c | 8 +- openair3/NAS/UE/EMM/emmData.h | 6 +- openair3/NAS/UE/EMM/emm_main.c | 36 +-- openair3/NAS/UE/EMM/emm_main.h | 4 +- openair3/NAS/UE/EMM/emm_proc.h | 6 +- .../ESM/DedicatedEpsBearerContextActivation.c | 18 +- .../ESM/DefaultEpsBearerContextActivation.c | 22 +- .../NAS/UE/ESM/EpsBearerContextDeactivation.c | 20 +- openair3/NAS/UE/ESM/EsmStatusHdl.c | 6 +- openair3/NAS/UE/ESM/PdnConnectivity.c | 28 +-- openair3/NAS/UE/ESM/PdnDisconnect.c | 10 +- openair3/NAS/UE/ESM/SAP/esm_sap.c | 40 ++-- openair3/NAS/UE/ESM/SAP/esm_sapDef.h | 6 +- openair3/NAS/UE/ESM/SAP/esm_send.c | 2 +- openair3/NAS/UE/ESM/SAP/esm_send.h | 4 +- openair3/NAS/UE/ESM/esmData.h | 9 +- openair3/NAS/UE/ESM/esm_ebr.c | 17 +- openair3/NAS/UE/ESM/esm_ebr.h | 8 +- openair3/NAS/UE/ESM/esm_ebr_context.c | 26 +-- openair3/NAS/UE/ESM/esm_ebr_context.h | 2 +- openair3/NAS/UE/ESM/esm_main.c | 28 +-- openair3/NAS/UE/ESM/esm_main.h | 7 +- openair3/NAS/UE/ESM/esm_proc.h | 37 ++-- openair3/NAS/UE/ESM/esm_pt.c | 8 +- openair3/NAS/UE/ESM/esm_pt.h | 4 +- openair3/NAS/UE/UEprocess.c | 4 +- openair3/NAS/UE/nas_proc.c | 80 +++---- openair3/NAS/UE/nas_proc.h | 8 +- openair3/NAS/UE/nas_proc_defs.h | 4 +- openair3/NAS/UE/nas_ue_task.c | 6 +- openair3/NAS/UE/nas_user.c | 22 +- openair3/NAS/UE/nas_user.h | 2 +- openair3/NGAP/ngap_common.h | 7 - openair3/S1AP/s1ap_common.h | 7 - openair3/S1AP/s1ap_eNB_trace.c | 2 +- openair3/ocp-gtpu/gtp_itf.cpp | 4 +- openair3/ocp-gtpu/gtp_itf.h | 48 ++-- targets/ARCH/COMMON/common_lib.h | 4 +- targets/ARCH/IRIS/USERSPACE/LIB/iris_lib.cpp | 2 +- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 6 +- targets/ARCH/iqplayer/iqplayer_lib.c | 2 +- targets/ARCH/rfsimulator/stored_node.c | 2 +- targets/RT/USER/lte-enb.c | 4 +- targets/RT/USER/lte-ru.c | 2 +- targets/TEST/PDCP/test_pdcp.c | 66 +++--- targets/TEST/PDCP/test_pdcp.h | 14 +- targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c | 12 +- 176 files changed, 1414 insertions(+), 1573 deletions(-) diff --git a/nfapi/oai_integration/nfapi_vnf.c b/nfapi/oai_integration/nfapi_vnf.c index d13dc5d1c5..8cc1bda782 100644 --- a/nfapi/oai_integration/nfapi_vnf.c +++ b/nfapi/oai_integration/nfapi_vnf.c @@ -217,7 +217,7 @@ void oai_create_enb(void) { } // This will cause phy_config_request to be installed. That will result in RRC configuring the PHY - // that will result in eNB->configured being set to TRUE. + // that will result in eNB->configured being set to true. // See we need to wait for that to happen otherwise the NFAPI message exchanges won't contain the right parameter values if (RC.eNB[0][0]->if_inst==0 || RC.eNB[0][0]->if_inst->PHY_config_req==0 || RC.eNB[0][0]->if_inst->schedule_response==0) { NFAPI_TRACE(NFAPI_TRACE_INFO, "RC.eNB[0][0]->if_inst->PHY_config_req is not installed - install it\n"); @@ -267,7 +267,7 @@ void oai_create_gnb(void) { // This will cause phy_config_request to be installed. That will result in RRC configuring the PHY - // that will result in gNB->configured being set to TRUE. + // that will result in gNB->configured being set to true. // See we need to wait for that to happen otherwise the NFAPI message exchanges won't contain the right parameter values if (RC.gNB[0]->if_inst==0 || RC.gNB[0]->if_inst->NR_PHY_config_req==0 || RC.gNB[0]->if_inst->NR_Schedule_response==0) { NFAPI_TRACE(NFAPI_TRACE_INFO, "RC.gNB[0][0]->if_inst->NR_PHY_config_req is not installed - install it\n"); diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index 1bbe9eb39a..dc73a56568 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -1997,7 +1997,7 @@ int get_narrowband_index(int N_RB_UL,int rb) { void fill_ulsch(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_ulsch_pdu *ulsch_pdu,int frame,int subframe) { uint8_t harq_pid; //uint8_t UE_id; - boolean_t new_ulsch = (find_ulsch(ulsch_pdu->ulsch_pdu_rel8.rnti,eNB,SEARCH_EXIST)==-1) ? TRUE : FALSE; + const bool new_ulsch = find_ulsch(ulsch_pdu->ulsch_pdu_rel8.rnti,eNB,SEARCH_EXIST) == -1; //AssertFatal((UE_id=find_ulsch(ulsch_pdu->ulsch_pdu_rel8.rnti,eNB,SEARCH_EXIST_OR_FREE))>=0, // "No existing/free UE ULSCH for rnti %x\n",ulsch_pdu->ulsch_pdu_rel8.rnti); LTE_eNB_ULSCH_t *ulsch=eNB->ulsch[UE_id]; @@ -2063,7 +2063,7 @@ void fill_ulsch(PHY_VARS_eNB *eNB,int UE_id,nfapi_ul_config_ulsch_pdu *ulsch_pdu if ((ulsch->harq_processes[harq_pid]->status == SCH_IDLE) || (ulsch->harq_processes[harq_pid]->ndi != ulsch_pdu->ulsch_pdu_rel8.new_data_indication) || - (new_ulsch == TRUE)) { + (new_ulsch == true)) { ulsch->harq_processes[harq_pid]->status = ACTIVE; ulsch->harq_processes[harq_pid]->TBS = ulsch_pdu->ulsch_pdu_rel8.size<<3; ulsch->harq_processes[harq_pid]->Msc_initial = 12*ulsch_pdu->ulsch_pdu_rel8.number_of_resource_blocks; diff --git a/openair1/PHY/LTE_TRANSPORT/defs_NB_IoT.h b/openair1/PHY/LTE_TRANSPORT/defs_NB_IoT.h index 3574ba6740..d90216c3e6 100644 --- a/openair1/PHY/LTE_TRANSPORT/defs_NB_IoT.h +++ b/openair1/PHY/LTE_TRANSPORT/defs_NB_IoT.h @@ -509,7 +509,7 @@ typedef struct { /// Position of first CCE of the dci int firstCCE; /// flag to indicate that this is a RA response - boolean_t ra_flag; + bool ra_flag; /// rnti rnti_t rnti; /// Format diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h index 7ecba40c3a..fd8eada245 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h @@ -342,7 +342,7 @@ typedef struct { /// Position of first CCE of the dci int firstCCE; /// flag to indicate that this is a RA response - boolean_t ra_flag; + bool ra_flag; /// rnti rnti_t rnti; /// rnti type diff --git a/openair1/PHY/TOOLS/calibration_scope.c b/openair1/PHY/TOOLS/calibration_scope.c index da1acb5175..d3397b033f 100644 --- a/openair1/PHY/TOOLS/calibration_scope.c +++ b/openair1/PHY/TOOLS/calibration_scope.c @@ -34,7 +34,7 @@ typedef struct OAIgraph { int h; int waterFallh; double *waterFallAvg; - boolean_t initDone; + bool initDone; int iteration; void (*funct) (struct OAIgraph *graph, calibData_t *); } OAIgraph_t; @@ -159,7 +159,7 @@ static void oai_xygraph_getbuff(OAIgraph_t *graph, float **x, float **y, int len *y=old_y; } -static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int layer, boolean_t NoAutoScale) { +static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int layer, bool NoAutoScale) { fl_redraw_object(graph->graph); if ( NoAutoScale && graph->iteration%NoAutoScale == 0) { diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index 723813fbb6..d4b28361d2 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -60,7 +60,7 @@ typedef struct OAIgraph { int h; int waterFallh; double *waterFallAvg; - boolean_t initDone; + bool initDone; int iteration; void (*gNBfunct) (struct OAIgraph *graph, scopeData_t *p, int UE_id); void (*nrUEfunct)(scopeGraphData_t **data, struct OAIgraph *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id); @@ -208,7 +208,7 @@ static void oai_xygraph_getbuff(OAIgraph_t *graph, float **x, float **y, int len *y=old_y; } -static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int layer, boolean_t NoAutoScale) { +static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int layer, bool NoAutoScale) { fl_redraw_object(graph->graph); if ( NoAutoScale && graph->iteration%NoAutoScale == 0) { diff --git a/openair1/PHY/defs_common.h b/openair1/PHY/defs_common.h index 47e17cc935..c93e3a7de9 100644 --- a/openair1/PHY/defs_common.h +++ b/openair1/PHY/defs_common.h @@ -754,7 +754,7 @@ typedef struct { /// Position of first CCE of the dci int firstCCE; /// flag to indicate that this is a RA response - boolean_t ra_flag; + bool ra_flag; /// rnti rnti_t rnti; /// harq_pid @@ -775,7 +775,7 @@ typedef struct { /// Position of first CCE of the dci int firstCCE; /// flag to indicate that this is a RA response - boolean_t ra_flag; + bool ra_flag; /// rnti rnti_t rnti; /// Format @@ -806,7 +806,7 @@ typedef struct { /// Position of first CCE of the dci int firstCCE; /// flag to indicate that this is a RA response - boolean_t ra_flag; + bool ra_flag; /// rnti rnti_t rnti; /// Format diff --git a/openair1/SCHED_UE/phy_procedures_lte_ue.c b/openair1/SCHED_UE/phy_procedures_lte_ue.c index aa0ff0db80..cdf4cf39f9 100644 --- a/openair1/SCHED_UE/phy_procedures_lte_ue.c +++ b/openair1/SCHED_UE/phy_procedures_lte_ue.c @@ -460,7 +460,7 @@ void ue_compute_srs_occasion(PHY_VARS_UE *ue, is_pucch2_subframe = (is_ri_TXOp(ue,proc,eNB_id) && (ue->cqi_report_config[eNB_id].CQI_ReportPeriodic.ri_ConfigIndex>0)) || is_pucch2_subframe; // check ACK/SR transmission - if(frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission == FALSE) { + if(frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission == false) { if(is_SR_TXOp(ue,proc,eNB_id)) { uint32_t SR_payload = 0; diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c index 31fe15a6de..12d50065fa 100644 --- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c +++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c @@ -165,7 +165,7 @@ void common_pucch_configuration(PHY_VARS_NR_UE *ue, uint8_t gNB_id, int pucch_in int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *proc) { int v_return = 0; - bool reset_harq = FALSE; + bool reset_harq = false; printf("%s", tst_separator); @@ -175,7 +175,7 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr common_pucch_configuration(ue, gNB_id, TST_PUCCH_COMMON_CONFIG_INDEX_KO); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != FALSE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != false) { v_return = -1; } @@ -186,7 +186,7 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr printf("\n => Test : Error due to acknownlegment not set \n"); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != FALSE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != false) { v_return = -1; } @@ -194,7 +194,7 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr printf("\n => Test : Error due to DAI not set \n"); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != FALSE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != false) { v_return = -1; } @@ -202,7 +202,7 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr harq_status->vDAI_DL = NR_DL_MAX_DAI + 1; - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != FALSE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != false) { v_return = -1; } @@ -210,7 +210,7 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr harq_status->vDAI_DL = 0; - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != FALSE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != false) { v_return = -1; } @@ -218,7 +218,7 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr harq_status->send_harq_status = 1; /* ack ready to be send */ - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != FALSE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != false) { v_return = -1; } @@ -228,7 +228,7 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr harq_status->vDAI_DL = 1; - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != FALSE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != false) { v_return = -1; } @@ -236,7 +236,7 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr printf("\n => Test : Error due to PUCCH format with multiple cells not already implemented \n"); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != FALSE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != false) { v_return = -1; } @@ -260,7 +260,7 @@ int test_pucch_basic_error(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pr int test_pucch_common_config_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *proc) { int v_return = 0; - bool reset_harq = FALSE; + bool reset_harq = false; printf("%s", tst_separator); @@ -273,7 +273,7 @@ int test_pucch_common_config_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_ printf("\n => Test : PUCCH format from common config in prach mode: one positive downlink ACKnowledgment \n"); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { v_return = -1; } @@ -281,7 +281,7 @@ int test_pucch_common_config_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_ printf("\n => Test : PUCCH format from common config in prach mode: one negative downlink ACKnowledgment \n"); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { v_return = -1; } @@ -304,7 +304,7 @@ int test_pucch_common_config_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_ printf("\n => Test : PUCCH format from common config in dedicated mode: two positive downlink ACKnowledgments \n"); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { v_return = -1; } @@ -312,7 +312,7 @@ int test_pucch_common_config_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_ printf("\n => Test : PUCCH format from common config in dedicated mode: one positive and one negative downlink ACKnowledgments \n"); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { v_return = -1; } @@ -320,22 +320,22 @@ int test_pucch_common_config_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_ printf("\n => Test : PUCCH format from common config in dedicated mode: two negative downlink ACKnowledgments \n"); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { v_return = -1; } harq_status->ack = DL_ACK; - reset_harq = TRUE; + reset_harq = true; printf("\n => Test : PUCCH format from common config in dedicated mode: no resource is found \n"); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != FALSE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != false) { v_return = -1; } printf("\n => Test : PUCCH format from common config in dedicated mode: no PUCCH after reset of pending harq ACKnowledgments \n"); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != FALSE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != false) { v_return = -1; } @@ -362,7 +362,7 @@ void init_pucch_dedicated_configuration(PHY_VARS_NR_UE *ue, uint8_t gNB_id) int i,j; /* set cell group parameters which are supported */ - ue->cell_group_config.physicalCellGroupConfig.harq_ACK_SpatialBundlingPUCCH = FALSE; + ue->cell_group_config.physicalCellGroupConfig.harq_ACK_SpatialBundlingPUCCH = false; ue->cell_group_config.physicalCellGroupConfig.pdsch_HARQ_ACK_Codebook = dynamic; ue->PDSCH_ServingCellConfig.codeBlockGroupTransmission = NULL; @@ -554,7 +554,7 @@ int test_pucch_dedicated_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_id, #define TST_NB_STEP_SINGLE_TRANSPORT_BLOCK (4) int v_return = 0; - int reset_harq = FALSE; + int reset_harq = false; int dl_harq_pid[TST_NB_STEP_SINGLE_TRANSPORT_BLOCK] = {TST_DL_HARQ_PID_FIRST, TST_DL_HARQ_PID_SECOND, TST_DL_HARQ_PID_THIRD, TST_DL_HARQ_PID_FOURTH }; int pucch_resource_indicator[TST_NB_STEP_SINGLE_TRANSPORT_BLOCK][2] = { { 0, 4 }, { 1, 0 } , { 1, 3 } , { 5, 7 } }; NR_UE_HARQ_STATUS_t *harq_status; @@ -575,7 +575,7 @@ int test_pucch_dedicated_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_id, printf("\n => Test : PUCCH format from dedicated config : pucch resource indicator is invalid \n"); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != FALSE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != false) { v_return = -1; } @@ -595,14 +595,14 @@ int test_pucch_dedicated_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_id, /* reset ack context on last test */ if ((i == (TST_NB_STEP_SINGLE_TRANSPORT_BLOCK-1)) && (j == 1)) { - reset_harq = TRUE; + reset_harq = true; } harq_status->pucch_resource_indicator = pucch_resource_indicator[i][j]; printf("\n => Test : PUCCH format from dedicated config with 1 transport block : with %d downlink ACKnowledgments and pucch resource indicator %d \n", i+1, pucch_resource_indicator[i][j]); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { v_return = -1; } } @@ -627,11 +627,11 @@ int test_pucch_dedicated_single_transport_block(PHY_VARS_NR_UE *ue, int gNB_id, harq_status->pucch_resource_indicator = pucch_resource_indicator[i][0]; } - reset_harq = TRUE; + reset_harq = true; printf("\n => Test : PUCCH format from dedicated config with 1 transport block and missed PDSCH : with %d downlink ACKnowledgments and pucch resource indicator %d \n", i+1, pucch_resource_indicator[3][0]); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { v_return = -1; } @@ -659,7 +659,7 @@ int test_pucch_dedicated_two_transport_blocks(PHY_VARS_NR_UE *ue, int gNB_id, UE #define TST_NB_STEP_TWO_TRANSPORT_BLOCKS (4) int v_return = 0; - int reset_harq = FALSE; + int reset_harq = false; int dl_harq_pid[TST_NB_STEP_TWO_TRANSPORT_BLOCKS] = {TST_DL_HARQ_PID_FIRST, TST_DL_HARQ_PID_SECOND, TST_DL_HARQ_PID_THIRD, TST_DL_HARQ_PID_FOURTH }; int pucch_resource_indicator[TST_NB_STEP_TWO_TRANSPORT_BLOCKS][2] = { { 0, 1 }, { 3, 7 } , { 2 , 4 } , { 4 , 6 } }; NR_UE_HARQ_STATUS_t *harq_status; @@ -694,7 +694,7 @@ int test_pucch_dedicated_two_transport_blocks(PHY_VARS_NR_UE *ue, int gNB_id, UE /* reset ack context on last test */ if ((i == (TST_NB_STEP_TWO_TRANSPORT_BLOCKS-1)) && (j == 1)) { - reset_harq = TRUE; + reset_harq = true; } harq_status = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[dl_harq_pid[i]].harq_ack; @@ -703,7 +703,7 @@ int test_pucch_dedicated_two_transport_blocks(PHY_VARS_NR_UE *ue, int gNB_id, UE printf("\n => Test : PUCCH format from dedicated config with 2 transport blocks : with %d downlink ACKnowledgments and pucch resource indicator %d \n", i+1, pucch_resource_indicator[i][j]); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { printf("Test fail \n"); v_return = -1; } @@ -714,7 +714,7 @@ int test_pucch_dedicated_two_transport_blocks(PHY_VARS_NR_UE *ue, int gNB_id, UE /* some transport blocks have been missed and they need to be nack by UE in order to be retransmitted by the network */ /* here first and third block receptions have been missed */ - reset_harq = TRUE; + reset_harq = true; for (int i = 1; i < TST_NB_STEP_TWO_TRANSPORT_BLOCKS; i = i + 1) { @@ -743,7 +743,7 @@ int test_pucch_dedicated_two_transport_blocks(PHY_VARS_NR_UE *ue, int gNB_id, UE printf("\n => Test : PUCCH format from dedicated config with 2 transport blocks and 1 missed PDSCH : with %d downlink ACKnowledgments and pucch resource indicator %d \n", 4, pucch_resource_indicator[3][0]); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { printf("Test fail \n"); v_return = -1; } @@ -775,7 +775,7 @@ int test_pucch_dedicated_two_transport_blocks(PHY_VARS_NR_UE *ue, int gNB_id, UE } } - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { printf("Test fail \n"); v_return = -1; } @@ -907,7 +907,7 @@ int test_sr_alone_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *p tst_scheduling_request_payload = 0; - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != FALSE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != false) { printf("Test fail \n"); v_return = -1; } @@ -916,7 +916,7 @@ int test_sr_alone_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *p tst_scheduling_request_payload = 1; - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { printf("Test fail \n"); v_return = -1; } @@ -929,7 +929,7 @@ int test_sr_alone_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *p tst_scheduling_request_payload = 1; - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { printf("Test fail \n"); v_return = -1; } @@ -958,7 +958,7 @@ int test_sr_alone_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *p int test_sr_ack_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *proc) { int v_return = 0; - int reset_harq = 0; + bool reset_harq = false; int sr_config_id = 0; int sr_resource_id = 0; int sr_offset = 0; @@ -988,7 +988,7 @@ int test_sr_ack_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pro tst_scheduling_request_payload = 0; /* set sr payload */ - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { printf("Test fail \n"); v_return = -1; } @@ -997,7 +997,7 @@ int test_sr_ack_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pro tst_scheduling_request_payload = 1; /* set sr payload */ - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { printf("Test fail \n"); v_return = -1; } @@ -1006,7 +1006,7 @@ int test_sr_ack_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pro harq_status->pucch_resource_indicator = pucch_resource_indicator[1]; - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { printf("Test fail \n"); v_return = -1; } @@ -1027,7 +1027,7 @@ int test_sr_ack_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pro tst_scheduling_request_payload = 1; /* set sr payload */ - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { printf("Test fail \n"); v_return = -1; } @@ -1035,9 +1035,9 @@ int test_sr_ack_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pro printf("\n => Test : PUCCH format from dedicated config with a positive scheduling request and two positive acks \n"); harq_status->pucch_resource_indicator = pucch_resource_indicator[1]; - reset_harq = TRUE; + reset_harq = true; - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { printf("Test fail \n"); v_return = -1; } @@ -1065,7 +1065,7 @@ int test_sr_ack_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *pro int test_csi_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *proc) { int v_return = 0; - int reset_harq = FALSE; + int reset_harq = false; int sr_config_id = 0; int sr_resource_id = 0; int sr_offset = 0; @@ -1079,7 +1079,7 @@ int test_csi_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *proc) printf("\n => Test : PUCCH format from dedicated config with CSI alone \n"); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { printf("Test fail \n"); v_return = -1; } @@ -1102,7 +1102,7 @@ int test_csi_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *proc) ue->pucch_config_dedicated_nr[gNB_id].formatConfig[2-1]->simultaneousHARQ_ACK_CSI = enable_feature; /* format 2 */ - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { printf("Test fail \n"); v_return = -1; } @@ -1115,9 +1115,9 @@ int test_csi_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *proc) tst_scheduling_request_payload = 0; /* set sr payload */ - reset_harq = TRUE; + reset_harq = true; - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { printf("Test fail \n"); v_return = -1; } @@ -1126,7 +1126,7 @@ int test_csi_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *proc) harq_status->pucch_resource_indicator = pucch_resource_indicator[4]; - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { printf("Test fail \n"); v_return = -1; } @@ -1135,7 +1135,7 @@ int test_csi_dedicated(PHY_VARS_NR_UE *ue, int gNB_id, UE_nr_rxtx_proc_t *proc) printf("\n => Test : PUCCH format from dedicated config with positive SR and CSI \n"); - if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != TRUE) { + if (pucch_procedures_ue_nr(ue, gNB_id, proc, reset_harq) != true) { printf("Test fail \n"); v_return = -1; } diff --git a/openair2/COMMON/commonDef.h b/openair2/COMMON/commonDef.h index b37230cdd4..e18db881f0 100644 --- a/openair2/COMMON/commonDef.h +++ b/openair2/COMMON/commonDef.h @@ -43,27 +43,6 @@ Description Contains global common definitions #include #include -/* boolean_t is also defined in openair2/COMMON/platform_types.h - * let's protect potential redefinition - */ - -#ifndef _BOOLEAN_T_DEFINED_ -#define _BOOLEAN_T_DEFINED_ - -typedef signed char boolean_t; - -#if !defined(TRUE) -#define TRUE (boolean_t)0x01 -#endif - -#if !defined(FALSE) -#define FALSE (boolean_t)0x00 -#endif - -#define BOOL_NOT(b) (b^TRUE) - -#endif /* _BOOLEAN_T_DEFINED_ */ - #define NAS_UE_ID_FMT "0x%06x" /****************************************************************************/ diff --git a/openair2/COMMON/mac_rlc_primitives.h b/openair2/COMMON/mac_rlc_primitives.h index 4e3e22781c..3d6dcc8100 100644 --- a/openair2/COMMON/mac_rlc_primitives.h +++ b/openair2/COMMON/mac_rlc_primitives.h @@ -145,7 +145,7 @@ struct mac_tx_tb_management { struct mac_rx_tb_management { unsigned char *data_ptr; tb_size_t tb_size; // in bits - boolean_t valid_checksum; + bool valid_checksum; unsigned char first_bit; // 0 if data starts on byte boundary(b7), 1 if b6, 2 if b5, etc }; diff --git a/openair2/COMMON/platform_types.h b/openair2/COMMON/platform_types.h index 67300da308..f229721993 100644 --- a/openair2/COMMON/platform_types.h +++ b/openair2/COMMON/platform_types.h @@ -32,35 +32,12 @@ #if !defined(NAS_NETLINK) #include +#include #else #include typedef void * intptr_t; #endif -//----------------------------------------------------------------------------- -// GENERIC TYPES -//----------------------------------------------------------------------------- - -/* boolean_t is also defined in openair2/COMMON/commonDef.h, - * let's protect potential redefinition - */ -#ifndef _BOOLEAN_T_DEFINED_ - #define _BOOLEAN_T_DEFINED_ - - typedef signed char boolean_t; - - #if !defined(TRUE) - #define TRUE (boolean_t)0x01 - #endif - - #if !defined(FALSE) - #define FALSE (boolean_t)0x00 - #endif - - #define BOOL_NOT(b) (b^TRUE) - -#endif /* _BOOLEAN_T_DEFINED_ */ - //----------------------------------------------------------------------------- // GENERIC ACCESS STRATUM TYPES //----------------------------------------------------------------------------- @@ -77,25 +54,25 @@ typedef int16_t smodule_id_t; typedef long rb_id_t; typedef long srb_id_t; -typedef boolean_t MBMS_flag_t; -#define MBMS_FLAG_NO FALSE -#define MBMS_FLAG_YES TRUE +typedef bool MBMS_flag_t; +#define MBMS_FLAG_NO false +#define MBMS_FLAG_YES true -typedef boolean_t eNB_flag_t; -#define ENB_FLAG_NO FALSE -#define ENB_FLAG_YES TRUE +typedef bool eNB_flag_t; +#define ENB_FLAG_NO false +#define ENB_FLAG_YES true -typedef boolean_t gNB_flag_t; -#define GNB_FLAG_NO FALSE -#define GNB_FLAG_YES TRUE +typedef bool gNB_flag_t; +#define GNB_FLAG_NO false +#define GNB_FLAG_YES true -typedef boolean_t srb_flag_t; -#define SRB_FLAG_NO FALSE -#define SRB_FLAG_YES TRUE +typedef bool srb_flag_t; +#define SRB_FLAG_NO false +#define SRB_FLAG_YES true -typedef boolean_t sl_discovery_flag_t; -#define SL_DISCOVERY_FLAG_NO FALSE -#define SL_DISCOVERY_FLAG_YES TRUE +typedef bool sl_discovery_flag_t; +#define SL_DISCOVERY_FLAG_NO false +#define SL_DISCOVERY_FLAG_YES true typedef enum link_direction_e { UNKNOWN_DIR = 0, @@ -152,8 +129,8 @@ typedef uint16_t rlc_usn_t; typedef int32_t rlc_buffer_occupancy_t; typedef signed int rlc_op_status_t; -#define SDU_CONFIRM_NO FALSE -#define SDU_CONFIRM_YES TRUE +#define SDU_CONFIRM_NO false +#define SDU_CONFIRM_YES true //----------------------------------------------------------------------------- // PDCP TYPES //----------------------------------------------------------------------------- @@ -242,7 +219,7 @@ typedef struct protocol_ctxt_s { frame_t frame; /*!< \brief LTE frame number.*/ sub_frame_t subframe; /*!< \brief LTE sub frame number.*/ eNB_index_t eNB_index; /*!< \brief valid for UE indicating the index of connected eNB(s) */ - boolean_t brOption; + bool brOption; } protocol_ctxt_t; // warning time hardcoded #define PROTOCOL_CTXT_TIME_MILLI_SECONDS(CtXt_h) ((CtXt_h)->frame*10+(CtXt_h)->subframe) diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index f4550f63a1..00ffd4cc13 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -583,9 +583,9 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) { "Failed to parse eNB configuration file %s, enb %u define %s: ENABLE,DISABLE!\n", RC.config_file_name, i, ENB_CONFIG_STRING_PRACH_HIGH_SPEED); else if (strcmp(ccparams_lte.prach_high_speed, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].prach_high_speed = TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].prach_high_speed = true; } else if (strcmp(ccparams_lte.prach_high_speed, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].prach_high_speed = FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].prach_high_speed = false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for prach_config choice: ENABLE,DISABLE !\n", @@ -689,9 +689,9 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) { "Failed to parse eNB configuration file %s, enb %u define %s: ENABLE,DISABLE!\n", RC.config_file_name, i, ENB_CONFIG_STRING_PUSCH_ENABLE64QAM); else if (strcmp(ccparams_lte.pusch_enable64QAM, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].pusch_enable64QAM = TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].pusch_enable64QAM = true; } else if (strcmp(ccparams_lte.pusch_enable64QAM, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].pusch_enable64QAM = FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].pusch_enable64QAM = false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pusch_enable64QAM choice: ENABLE,DISABLE!\n", @@ -702,9 +702,9 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) { "Failed to parse eNB configuration file %s, enb %u define %s: ENABLE,DISABLE!\n", RC.config_file_name, i, ENB_CONFIG_STRING_PUSCH_GROUP_HOPPING_EN); else if (strcmp(ccparams_lte.pusch_groupHoppingEnabled, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].pusch_groupHoppingEnabled = TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].pusch_groupHoppingEnabled = true; } else if (strcmp(ccparams_lte.pusch_groupHoppingEnabled, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].pusch_groupHoppingEnabled= FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].pusch_groupHoppingEnabled= false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pusch_groupHoppingEnabled choice: ENABLE,DISABLE!\n", @@ -723,9 +723,9 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) { "Failed to parse eNB configuration file %s, enb %u define %s: ENABLE,DISABLE!\n", RC.config_file_name, i, ENB_CONFIG_STRING_PUSCH_SEQUENCE_HOPPING_EN); else if (strcmp(ccparams_lte.pusch_sequenceHoppingEnabled, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].pusch_sequenceHoppingEnabled = TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].pusch_sequenceHoppingEnabled = true; } else if (strcmp(ccparams_lte.pusch_sequenceHoppingEnabled, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].pusch_sequenceHoppingEnabled = FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].pusch_sequenceHoppingEnabled = false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for pusch_sequenceHoppingEnabled choice: ENABLE,DISABLE!\n", @@ -766,15 +766,15 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) { RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].phich_duration,ccparams_lte.phich_duration); if (strcmp(ccparams_lte.srs_enable, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].srs_enable= TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].srs_enable= true; } else if (strcmp(ccparams_lte.srs_enable, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].srs_enable= FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].srs_enable= false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for srs_BandwidthConfig choice: ENABLE,DISABLE !\n", RC.config_file_name, i, ccparams_lte.srs_enable); - if (RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].srs_enable== TRUE) { + if (RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].srs_enable== true) { RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].srs_BandwidthConfig= ccparams_lte.srs_BandwidthConfig; if ((ccparams_lte.srs_BandwidthConfig < 0) || @@ -791,18 +791,18 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) { RC.config_file_name, i, ccparams_lte.srs_SubframeConfig); if (strcmp(ccparams_lte.srs_ackNackST, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].srs_ackNackST= TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].srs_ackNackST= true; } else if (strcmp(ccparams_lte.srs_ackNackST, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].srs_ackNackST= FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].srs_ackNackST= false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for srs_BandwidthConfig choice: ENABLE,DISABLE !\n", RC.config_file_name, i, ccparams_lte.srs_ackNackST); if (strcmp(ccparams_lte.srs_MaxUpPts, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].srs_MaxUpPts= TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].srs_MaxUpPts= true; } else if (strcmp(ccparams_lte.srs_MaxUpPts, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].srs_MaxUpPts= FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].srs_MaxUpPts= false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for srs_MaxUpPts choice: ENABLE,DISABLE !\n", @@ -921,7 +921,7 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) { RC.config_file_name, i, ccparams_lte.rach_numberOfRA_Preambles); if (strcmp(ccparams_lte.rach_preamblesGroupAConfig, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].rach_preamblesGroupAConfig= TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].rach_preamblesGroupAConfig= true; RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].rach_sizeOfRA_PreamblesGroupA= (ccparams_lte.rach_sizeOfRA_PreamblesGroupA/4)-1; if ((ccparams_lte.rach_numberOfRA_Preambles <4) || @@ -976,7 +976,7 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) { "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for rach_messagePowerOffsetGroupB choice: minusinfinity,dB0,dB5,dB8,dB10,dB12,dB15,dB18!\n", RC.config_file_name, i, ccparams_lte.rach_messagePowerOffsetGroupB); } else if (strcmp(ccparams_lte.rach_preamblesGroupAConfig, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].rach_preamblesGroupAConfig= FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].rach_preamblesGroupAConfig= false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for rach_preamblesGroupAConfig choice: ENABLE,DISABLE !\n", @@ -1254,9 +1254,9 @@ int RCconfig_RRC(uint32_t i, eNB_RRC_INST *rrc, int macrlc_has_f1) { "Failed to parse eNB configuration file %s, enb %u define %s: TRUE,FALSE!\n", RC.config_file_name, i, ENB_CONFIG_STRING_MBMS_DEDICATED_SERVING_CELL); else if (strcmp(ccparams_lte.mbms_dedicated_serving_cell, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].mbms_dedicated_serving_cell = TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].mbms_dedicated_serving_cell = true; } else if (strcmp(ccparams_lte.mbms_dedicated_serving_cell, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].mbms_dedicated_serving_cell = FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig[j].mbms_dedicated_serving_cell = false; } else { AssertFatal (0, "Failed to parse eNB configuration file %s, enb %u unknown value \"%s\" for mbms_dedicated_serving_cell choice: TRUE or FALSE !\n", diff --git a/openair2/ENB_APP/enb_config_eMTC.c b/openair2/ENB_APP/enb_config_eMTC.c index 2e71f17e9d..e4ff458886 100644 --- a/openair2/ENB_APP/enb_config_eMTC.c +++ b/openair2/ENB_APP/enb_config_eMTC.c @@ -61,18 +61,18 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in if (!strcmp(eMTCconfig->cellSelectionInfoCE_r13, "ENABLE")) { - RRC_CONFIGURATION_REQ(msg_p).cellSelectionInfoCE_r13[cc_idx] = TRUE; + RRC_CONFIGURATION_REQ(msg_p).cellSelectionInfoCE_r13[cc_idx] = true; RRC_CONFIGURATION_REQ(msg_p).q_RxLevMinCE_r13[cc_idx]= eMTCconfig->q_RxLevMinCE_r13; // RRC_CONFIGURATION_REQ(msg_p).q_QualMinRSRQ_CE_r13[cc_idx]= calloc(1, sizeof(long)); // *RRC_CONFIGURATION_REQ(msg_p).q_QualMinRSRQ_CE_r13[cc_idx]= q_QualMinRSRQ_CE_r13; } else { - RRC_CONFIGURATION_REQ(msg_p).cellSelectionInfoCE_r13[cc_idx] = FALSE; + RRC_CONFIGURATION_REQ(msg_p).cellSelectionInfoCE_r13[cc_idx] = false; } if (!strcmp(eMTCconfig->bandwidthReducedAccessRelatedInfo_r13, "ENABLE")) { - RRC_CONFIGURATION_REQ(msg_p).bandwidthReducedAccessRelatedInfo_r13[cc_idx] = TRUE; + RRC_CONFIGURATION_REQ(msg_p).bandwidthReducedAccessRelatedInfo_r13[cc_idx] = true; @@ -106,7 +106,7 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in } } else { - RRC_CONFIGURATION_REQ(msg_p).bandwidthReducedAccessRelatedInfo_r13[cc_idx] = FALSE; + RRC_CONFIGURATION_REQ(msg_p).bandwidthReducedAccessRelatedInfo_r13[cc_idx] = false; } char schedulingInfoBrPath[MAX_OPTNAME_SIZE * 2]; @@ -127,10 +127,10 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in RRC_CONFIGURATION_REQ(msg_p).fdd_DownlinkOrTddSubframeBitmapBR_r13[cc_idx] = CALLOC(1, sizeof(BOOLEAN_t)); if (!strcmp(eMTCconfig->fdd_DownlinkOrTddSubframeBitmapBR_r13, "subframePattern40-r13")) { - *RRC_CONFIGURATION_REQ(msg_p).fdd_DownlinkOrTddSubframeBitmapBR_r13[cc_idx] = FALSE; + *RRC_CONFIGURATION_REQ(msg_p).fdd_DownlinkOrTddSubframeBitmapBR_r13[cc_idx] = false; RRC_CONFIGURATION_REQ(msg_p).fdd_DownlinkOrTddSubframeBitmapBR_val_r13[cc_idx] = eMTCconfig->fdd_DownlinkOrTddSubframeBitmapBR_val_r13; } else { - *RRC_CONFIGURATION_REQ(msg_p).fdd_DownlinkOrTddSubframeBitmapBR_r13[cc_idx] = TRUE; + *RRC_CONFIGURATION_REQ(msg_p).fdd_DownlinkOrTddSubframeBitmapBR_r13[cc_idx] = true; RRC_CONFIGURATION_REQ(msg_p).fdd_DownlinkOrTddSubframeBitmapBR_val_r13[cc_idx] = eMTCconfig->fdd_DownlinkOrTddSubframeBitmapBR_val_r13; } @@ -156,18 +156,18 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in if (!strcmp(eMTCconfig->freqHoppingParametersDL_r13, "ENABLE")) { - RRC_CONFIGURATION_REQ(msg_p).freqHoppingParametersDL_r13[cc_idx] = TRUE; + RRC_CONFIGURATION_REQ(msg_p).freqHoppingParametersDL_r13[cc_idx] = true; if (!strcmp(eMTCconfig->interval_DLHoppingConfigCommonModeA_r13, "interval-TDD-r13")) - RRC_CONFIGURATION_REQ(msg_p).interval_DLHoppingConfigCommonModeA_r13[cc_idx] = FALSE; + RRC_CONFIGURATION_REQ(msg_p).interval_DLHoppingConfigCommonModeA_r13[cc_idx] = false; else - RRC_CONFIGURATION_REQ(msg_p).interval_DLHoppingConfigCommonModeA_r13[cc_idx] = TRUE; + RRC_CONFIGURATION_REQ(msg_p).interval_DLHoppingConfigCommonModeA_r13[cc_idx] = true; RRC_CONFIGURATION_REQ(msg_p).interval_DLHoppingConfigCommonModeA_r13_val[cc_idx] = eMTCconfig->interval_DLHoppingConfigCommonModeA_r13_val; if (!strcmp(eMTCconfig->interval_DLHoppingConfigCommonModeB_r13, "interval-TDD-r13")) - RRC_CONFIGURATION_REQ(msg_p).interval_DLHoppingConfigCommonModeB_r13[cc_idx] = FALSE; + RRC_CONFIGURATION_REQ(msg_p).interval_DLHoppingConfigCommonModeB_r13[cc_idx] = false; else - RRC_CONFIGURATION_REQ(msg_p).interval_DLHoppingConfigCommonModeB_r13[cc_idx] = TRUE; + RRC_CONFIGURATION_REQ(msg_p).interval_DLHoppingConfigCommonModeB_r13[cc_idx] = true; RRC_CONFIGURATION_REQ(msg_p).interval_DLHoppingConfigCommonModeB_r13_val[cc_idx] = eMTCconfig->interval_DLHoppingConfigCommonModeB_r13_val; RRC_CONFIGURATION_REQ(msg_p).mpdcch_pdsch_HoppingNB_r13[cc_idx] = calloc(1, sizeof(long)); @@ -188,7 +188,7 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in } else { - RRC_CONFIGURATION_REQ(msg_p).freqHoppingParametersDL_r13[cc_idx] = FALSE; + RRC_CONFIGURATION_REQ(msg_p).freqHoppingParametersDL_r13[cc_idx] = false; } /** ------------------------------SIB2/3 BR------------------------------------------ */ @@ -213,9 +213,9 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in "Failed to parse eNB configuration file %s, enb %d define %s: ENABLE,DISABLE!\n", config_fname, cell_idx,ENB_CONFIG_STRING_PRACH_HIGH_SPEED); else if (strcmp(eMTCconfig->ccparams.prach_high_speed, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].prach_high_speed = TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].prach_high_speed = true; } else if (strcmp(eMTCconfig->ccparams.prach_high_speed, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].prach_high_speed = FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].prach_high_speed = false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for prach_config choice: ENABLE,DISABLE !\n", @@ -310,9 +310,9 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in "Failed to parse eNB configuration file %s, enb %d define %s: ENABLE,DISABLE!\n", config_fname, cell_idx,ENB_CONFIG_STRING_PUSCH_ENABLE64QAM); else if (strcmp(eMTCconfig->ccparams.pusch_enable64QAM, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].pusch_enable64QAM = TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].pusch_enable64QAM = true; } else if (strcmp(eMTCconfig->ccparams.pusch_enable64QAM, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].pusch_enable64QAM = FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].pusch_enable64QAM = false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for pusch_enable64QAM choice: ENABLE,DISABLE!\n", @@ -323,9 +323,9 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in "Failed to parse eNB configuration file %s, enb %d define %s: ENABLE,DISABLE!\n", config_fname, cell_idx,ENB_CONFIG_STRING_PUSCH_GROUP_HOPPING_EN); else if (strcmp(eMTCconfig->ccparams.pusch_groupHoppingEnabled, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].pusch_groupHoppingEnabled = TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].pusch_groupHoppingEnabled = true; } else if (strcmp(eMTCconfig->ccparams.pusch_groupHoppingEnabled, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].pusch_groupHoppingEnabled= FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].pusch_groupHoppingEnabled= false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for pusch_groupHoppingEnabled choice: ENABLE,DISABLE!\n", @@ -343,9 +343,9 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in "Failed to parse eNB configuration file %s, enb %d define %s: ENABLE,DISABLE!\n", config_fname, cell_idx,ENB_CONFIG_STRING_PUSCH_SEQUENCE_HOPPING_EN); else if (strcmp(eMTCconfig->ccparams.pusch_sequenceHoppingEnabled, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].pusch_sequenceHoppingEnabled = TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].pusch_sequenceHoppingEnabled = true; } else if (strcmp(eMTCconfig->ccparams.pusch_sequenceHoppingEnabled, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].pusch_sequenceHoppingEnabled = FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].pusch_sequenceHoppingEnabled = false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for pusch_sequenceHoppingEnabled choice: ENABLE,DISABLE!\n", @@ -385,15 +385,15 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].phich_duration,eMTCconfig->ccparams.phich_duration); if (strcmp(eMTCconfig->ccparams.srs_enable, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].srs_enable= TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].srs_enable= true; } else if (strcmp(eMTCconfig->ccparams.srs_enable, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].srs_enable= FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].srs_enable= false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for srs_BandwidthConfig choice: ENABLE,DISABLE !\n", config_fname, cell_idx,eMTCconfig->ccparams.srs_enable); - if (RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].srs_enable== TRUE) { + if (RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].srs_enable== true) { RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].srs_BandwidthConfig= eMTCconfig->ccparams.srs_BandwidthConfig; if ((eMTCconfig->ccparams.srs_BandwidthConfig < 0) || (eMTCconfig->ccparams.srs_BandwidthConfig >7)) @@ -408,18 +408,18 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in config_fname, cell_idx,eMTCconfig->ccparams.srs_SubframeConfig); if (strcmp(eMTCconfig->ccparams.srs_ackNackST, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].srs_ackNackST= TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].srs_ackNackST= true; } else if (strcmp(eMTCconfig->ccparams.srs_ackNackST, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].srs_ackNackST= FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].srs_ackNackST= false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for srs_BandwidthConfig choice: ENABLE,DISABLE !\n", config_fname, cell_idx,eMTCconfig->ccparams.srs_ackNackST); if (strcmp(eMTCconfig->ccparams.srs_MaxUpPts, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].srs_MaxUpPts= TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].srs_MaxUpPts= true; } else if (strcmp(eMTCconfig->ccparams.srs_MaxUpPts, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].srs_MaxUpPts= FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].srs_MaxUpPts= false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for srs_MaxUpPts choice: ENABLE,DISABLE !\n", @@ -535,7 +535,7 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in config_fname, cell_idx,eMTCconfig->ccparams.rach_numberOfRA_Preambles); if (strcmp(eMTCconfig->ccparams.rach_preamblesGroupAConfig, "ENABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].rach_preamblesGroupAConfig= TRUE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].rach_preamblesGroupAConfig= true; RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].rach_sizeOfRA_PreamblesGroupA= (eMTCconfig->ccparams.rach_sizeOfRA_PreamblesGroupA/4)-1; if ((eMTCconfig->ccparams.rach_numberOfRA_Preambles <4) || (eMTCconfig->ccparams.rach_numberOfRA_Preambles>60) || ((eMTCconfig->ccparams.rach_numberOfRA_Preambles&3)!=0)) @@ -588,7 +588,7 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for rach_messagePowerOffsetGroupB choice: minusinfinity,dB0,dB5,dB8,dB10,dB12,dB15,dB18!\n", config_fname, cell_idx,eMTCconfig->ccparams.rach_messagePowerOffsetGroupB); } else if (strcmp(eMTCconfig->ccparams.rach_preamblesGroupAConfig, "DISABLE") == 0) { - RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].rach_preamblesGroupAConfig= FALSE; + RRC_CONFIGURATION_REQ (msg_p).radioresourceconfig_BR[cc_idx].rach_preamblesGroupAConfig= false; } else AssertFatal (0, "Failed to parse eNB configuration file %s, enb %d unknown value \"%s\" for rach_preamblesGroupAConfig choice: ENABLE,DISABLE !\n", @@ -847,14 +847,14 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in if (!strcmp(eMTCconfig->prach_ConfigCommon_v1310, "ENABLE")) { - RRC_CONFIGURATION_REQ(msg_p).radioresourceconfig_BR[cc_idx].prach_ConfigCommon_v1310 = TRUE; + RRC_CONFIGURATION_REQ(msg_p).radioresourceconfig_BR[cc_idx].prach_ConfigCommon_v1310 = true; RRC_CONFIGURATION_REQ(msg_p).radioresourceconfig_BR[cc_idx].mpdcch_startSF_CSS_RA_r13 = calloc(1, sizeof(BOOLEAN_t)); if (!strcmp(eMTCconfig->mpdcch_startSF_CSS_RA_r13, "tdd-r13")) { - *RRC_CONFIGURATION_REQ(msg_p).radioresourceconfig_BR[cc_idx].mpdcch_startSF_CSS_RA_r13 = FALSE; + *RRC_CONFIGURATION_REQ(msg_p).radioresourceconfig_BR[cc_idx].mpdcch_startSF_CSS_RA_r13 = false; } else { - *RRC_CONFIGURATION_REQ(msg_p).radioresourceconfig_BR[cc_idx].mpdcch_startSF_CSS_RA_r13 = TRUE; + *RRC_CONFIGURATION_REQ(msg_p).radioresourceconfig_BR[cc_idx].mpdcch_startSF_CSS_RA_r13 = true; } if (!strcmp(eMTCconfig->mpdcch_startSF_CSS_RA_r13_val, "v1")) { @@ -882,7 +882,7 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in RRC_CONFIGURATION_REQ(msg_p).radioresourceconfig_BR[cc_idx].prach_HoppingOffset_r13 = calloc(1, sizeof(long)); *RRC_CONFIGURATION_REQ(msg_p).radioresourceconfig_BR[cc_idx].prach_HoppingOffset_r13 = eMTCconfig->prach_HoppingOffset_r13; } else { - RRC_CONFIGURATION_REQ(msg_p).radioresourceconfig_BR[cc_idx].prach_ConfigCommon_v1310 = FALSE; + RRC_CONFIGURATION_REQ(msg_p).radioresourceconfig_BR[cc_idx].prach_ConfigCommon_v1310 = false; } @@ -1169,7 +1169,7 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in /** PCCH CONFIG V1310 */ - RRC_CONFIGURATION_REQ(msg_p).pcch_config_v1310[cc_idx] = TRUE; + RRC_CONFIGURATION_REQ(msg_p).pcch_config_v1310[cc_idx] = true; RRC_CONFIGURATION_REQ(msg_p).paging_narrowbands_r13[cc_idx] = eMTCconfig->paging_narrowbands_r13; RRC_CONFIGURATION_REQ(msg_p).mpdcch_numrepetition_paging_r13[cc_idx] = eMTCconfig->mpdcch_numrepetition_paging_r13; @@ -1220,7 +1220,7 @@ void fill_eMTC_configuration(MessageDef *msg_p, ccparams_eMTC_t *eMTCconfig, in /** SIB2 FREQ HOPPING PARAMETERS R13 */ - RRC_CONFIGURATION_REQ(msg_p).sib2_freq_hoppingParameters_r13_exists[cc_idx] = TRUE; + RRC_CONFIGURATION_REQ(msg_p).sib2_freq_hoppingParameters_r13_exists[cc_idx] = true; char sib2FreqHoppingParametersR13Path[MAX_OPTNAME_SIZE*2 + 16]; sprintf(sib2FreqHoppingParametersR13Path, "%s.%s", brparamspath, ENB_CONFIG_STRING_SIB2_FREQ_HOPPINGPARAMETERS_R13); diff --git a/openair2/ENB_APP/flexran_agent_ran_api.c b/openair2/ENB_APP/flexran_agent_ran_api.c index 9926ec9e20..3113c07798 100644 --- a/openair2/ENB_APP/flexran_agent_ran_api.c +++ b/openair2/ENB_APP/flexran_agent_ran_api.c @@ -127,7 +127,7 @@ int flexran_get_mac_ue_id_rnti(mid_t mod_id, rnti_t rnti) { /* get the (active) UE with RNTI i */ for (n = 0; n < MAX_MOBILES_PER_ENB; ++n) { - if (RC.mac[mod_id]->UE_info.active[n] == TRUE + if (RC.mac[mod_id]->UE_info.active[n] == true && rnti == UE_RNTI(mod_id, n)) { return n; } @@ -143,7 +143,7 @@ int flexran_get_mac_ue_id(mid_t mod_id, int i) { /* get the (i+1)'th active UE */ for (n = 0; n < MAX_MOBILES_PER_ENB; ++n) { - if (RC.mac[mod_id]->UE_info.active[n] == TRUE) { + if (RC.mac[mod_id]->UE_info.active[n] == true) { if (i == 0) return n; @@ -580,7 +580,7 @@ uint8_t flexran_get_n_SB(mid_t mod_id, uint8_t cc_id) { Protocol__FlexQam flexran_get_enable64QAM(mid_t mod_id, uint8_t cc_id) { if (!phy_is_present(mod_id, cc_id)) return 0; - if (RC.eNB[mod_id][cc_id]->frame_parms.pusch_config_common.enable64QAM == TRUE) + if (RC.eNB[mod_id][cc_id]->frame_parms.pusch_config_common.enable64QAM == true) return PROTOCOL__FLEX_QAM__FLEQ_MOD_64QAM; else return PROTOCOL__FLEX_QAM__FLEQ_MOD_16QAM; @@ -3585,7 +3585,7 @@ int flexran_set_new_plmn_id(mid_t mod_id, int CC_id, size_t n_plmn, Protocol__Fl int CC_id, BOOLEAN_t brOption, RrcConfigurationReq *configuration); - carrier->sizeof_SIB1 = do_SIB1(carrier, mod_id, CC_id, FALSE, conf); + carrier->sizeof_SIB1 = do_SIB1(carrier, mod_id, CC_id, false, conf); if (carrier->sizeof_SIB1 < 0) return -1337; /* SIB1 encoding failed, hell will probably break loose */ diff --git a/openair2/F1AP/dummy_enb.c b/openair2/F1AP/dummy_enb.c index 9085fdb57c..8e185c951d 100644 --- a/openair2/F1AP/dummy_enb.c +++ b/openair2/F1AP/dummy_enb.c @@ -32,18 +32,18 @@ void apply_macrlc_config(gNB_RRC_INST *rrc, abort(); } -boolean_t sdap_data_req(protocol_ctxt_t *ctxt_p, - const srb_flag_t srb_flag, - const rb_id_t rb_id, - const mui_t mui, - const confirm_t confirm, - const sdu_size_t sdu_buffer_size, - unsigned char *const sdu_buffer, - const pdcp_transmission_mode_t pt_mode, - const uint32_t *sourceL2Id, - const uint32_t *destinationL2Id, - const uint8_t qfi, - const boolean_t rqi, - const int pdusession_id) { +bool sdap_data_req(protocol_ctxt_t *ctxt_p, + const srb_flag_t srb_flag, + const rb_id_t rb_id, + const mui_t mui, + const confirm_t confirm, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t pt_mode, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id, + const uint8_t qfi, + const bool rqi, + const int pdusession_id) { abort(); } diff --git a/openair2/F1AP/f1ap_common.h b/openair2/F1AP/f1ap_common.h index 66451530a6..6b64e1b59e 100644 --- a/openair2/F1AP/f1ap_common.h +++ b/openair2/F1AP/f1ap_common.h @@ -363,13 +363,6 @@ # error "You are compiling f1ap with the wrong version of ASN1C" #endif -#ifndef FALSE - #define FALSE (0) -#endif -#ifndef TRUE - #define TRUE (!FALSE) -#endif - #define F1AP_UE_ID_FMT "0x%06"PRIX32 #include "assertions.h" diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.c b/openair2/F1AP/f1ap_du_rrc_message_transfer.c index a9f82f42b3..e158e9519a 100644 --- a/openair2/F1AP/f1ap_du_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.c @@ -509,7 +509,7 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, LOG_I(F1AP, "Received DL RRC Transfer on srb_id %ld\n", srb_id); rlc_op_status_t rlc_status; - boolean_t ret = TRUE; + bool ret = true; mem_block_t *pdcp_pdu_p = NULL; pdcp_pdu_p = get_free_mem_block(rrc_dl_sdu_len, __func__); @@ -539,27 +539,27 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, switch (rlc_status) { case RLC_OP_STATUS_OK: //LOG_I(F1AP, "Data sending request over RLC succeeded!\n"); - ret=TRUE; + ret=true; break; case RLC_OP_STATUS_BAD_PARAMETER: LOG_W(F1AP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n"); - ret= FALSE; + ret= false; break; case RLC_OP_STATUS_INTERNAL_ERROR: LOG_W(F1AP, "Data sending request over RLC failed with 'Internal Error' reason!\n"); - ret= FALSE; + ret= false; break; case RLC_OP_STATUS_OUT_OF_RESSOURCES: LOG_W(F1AP, "Data sending request over RLC failed with 'Out of Resources' reason!\n"); - ret= FALSE; + ret= false; break; default: LOG_W(F1AP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status); - ret= FALSE; + ret= false; break; } // switch case @@ -667,9 +667,9 @@ int DU_send_UL_RRC_MESSAGE_TRANSFER(instance_t instance, UE_sched_ctrl_t *UE_scheduling_control = &(RC.mac[instance]->UE_info.UE_sched_ctrl[UE_id_mac]); - if (UE_scheduling_control->cdrx_waiting_ack == TRUE) { - UE_scheduling_control->cdrx_waiting_ack = FALSE; - UE_scheduling_control->cdrx_configured = TRUE; // Set to TRUE when RRC Connection Reconfiguration Complete is received + if (UE_scheduling_control->cdrx_waiting_ack == true) { + UE_scheduling_control->cdrx_waiting_ack = false; + UE_scheduling_control->cdrx_configured = true; // Set to TRUE when RRC Connection Reconfiguration Complete is received LOG_I(F1AP, "CDRX configuration activated after RRC Connection Reconfiguration Complete reception\n"); } diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index 6dbe820465..74e0200f09 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -42,16 +42,16 @@ #include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" #include -boolean_t lteDURecvCb( protocol_ctxt_t *ctxt_pP, - const srb_flag_t srb_flagP, - const rb_id_t rb_idP, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_sizeP, - unsigned char *const sdu_buffer_pP, - const pdcp_transmission_mode_t modeP, - const uint32_t *sourceL2Id, - const uint32_t *destinationL2Id) { +bool lteDURecvCb(protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_sizeP, + unsigned char *const sdu_buffer_pP, + const pdcp_transmission_mode_t modeP, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id) { // The buffer comes from the stack in gtp-u thread, we have a make a separate buffer to enqueue in a inter-thread message queue mem_block_t *sdu=get_free_mem_block(sdu_buffer_sizeP, __func__); memcpy(sdu->data, sdu_buffer_pP, sdu_buffer_sizeP); @@ -704,7 +704,7 @@ int DU_send_UE_CONTEXT_RELEASE_REQUEST(instance_t instance, LOG_E(F1AP,"Not found rnti: %x\n", rnti); } else { for (int n = 0; n < MAX_MOBILES_PER_ENB; ++n) { - if (RC.mac[instance]->UE_info.active[n] == TRUE + if (RC.mac[instance]->UE_info.active[n] == true && rnti == UE_RNTI(instance, n)) { UE_out_of_sync = RC.mac[instance]->UE_info.UE_sched_ctrl[n].ul_out_of_sync; break; @@ -856,7 +856,7 @@ int DU_handle_UE_CONTEXT_RELEASE_COMMAND(instance_t instance, if(RC.rrc && RC.rrc[instance]->node_type == ngran_eNB_DU){ for (int n = 0; n < MAX_MOBILES_PER_ENB; ++n) { - if (RC.mac[instance]->UE_info.active[n] == TRUE + if (RC.mac[instance]->UE_info.active[n] == true && rnti == UE_RNTI(instance, n)) { UE_out_of_sync = RC.mac[instance]->UE_info.UE_sched_ctrl[n].ul_out_of_sync; break; diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c index d22485d23f..52a9048cd0 100644 --- a/openair2/LAYER2/MAC/config.c +++ b/openair2/LAYER2/MAC/config.c @@ -1104,7 +1104,7 @@ void eNB_Config_Local_DRX(instance_t Mod_id, /* Get struct to modify */ UE_scheduling_control = &(UE_info_mac->UE_sched_ctrl[UE_id]); - UE_scheduling_control->cdrx_configured = FALSE; // will be set to true when no error + UE_scheduling_control->cdrx_configured = false; // will be set to true when no error /* Check drx_Configuration */ if (drx_Configuration == NULL) { @@ -1119,9 +1119,9 @@ void eNB_Config_Local_DRX(instance_t Mod_id, } /* Modify scheduling control structure according to DRX configuration: doesn't support every configurations! */ - UE_scheduling_control->cdrx_configured = FALSE; // will be set to true when receiving RRC Reconfiguration Complete - UE_scheduling_control->cdrx_waiting_ack = TRUE; // waiting for RRC Reconfiguration Complete message - UE_scheduling_control->in_active_time = FALSE; + UE_scheduling_control->cdrx_configured = false; // will be set to true when receiving RRC Reconfiguration Complete + UE_scheduling_control->cdrx_waiting_ack = true; // waiting for RRC Reconfiguration Complete message + UE_scheduling_control->in_active_time = false; UE_scheduling_control->dci0_ongoing_timer = 0; UE_scheduling_control->on_duration_timer = 0; struct LTE_DRX_Config__setup *choiceSetup = &drx_Configuration->choice.setup; @@ -1297,13 +1297,13 @@ void eNB_Config_Local_DRX(instance_t Mod_id, } if (choiceSetup->shortDRX == NULL) { - UE_scheduling_control->in_short_drx_cycle = FALSE; + UE_scheduling_control->in_short_drx_cycle = false; UE_scheduling_control->drx_shortCycle_timer_value = 0; UE_scheduling_control->short_drx_cycle_duration = 0; UE_scheduling_control->drx_shortCycle_timer = 0; UE_scheduling_control->drx_shortCycle_timer_thres = -1; } else { - UE_scheduling_control->in_short_drx_cycle = FALSE; + UE_scheduling_control->in_short_drx_cycle = false; UE_scheduling_control->drx_shortCycle_timer_value = (uint8_t) choiceSetup->shortDRX->drxShortCycleTimer; switch (choiceSetup->shortDRX->shortDRX_Cycle) { @@ -1380,7 +1380,7 @@ void eNB_Config_Local_DRX(instance_t Mod_id, UE_scheduling_control->drx_shortCycle_timer_thres = UE_scheduling_control->drx_shortCycle_timer_value * UE_scheduling_control->short_drx_cycle_duration; } - UE_scheduling_control->in_long_drx_cycle = FALSE; + UE_scheduling_control->in_long_drx_cycle = false; UE_scheduling_control->drx_longCycle_timer = 0; switch (choiceSetup->longDRX_CycleStartOffset.present) { diff --git a/openair2/LAYER2/MAC/defs_NB_IoT.h b/openair2/LAYER2/MAC/defs_NB_IoT.h index d4945f0182..abe780741c 100644 --- a/openair2/LAYER2/MAC/defs_NB_IoT.h +++ b/openair2/LAYER2/MAC/defs_NB_IoT.h @@ -243,7 +243,6 @@ typedef struct { // -1:No UE in list int tail; int num_UEs; - //boolean_t active[MAX_MAX_MOBILES_PER_ENB_NB_IoT]; } UE_list_NB_IoT_t; @@ -403,7 +402,7 @@ typedef struct schedule_result{ // pointer to DCI void *DCI_pdu; // when all the procedure related to this DCI, enable this flag - boolean_t DCI_release; + bool DCI_release; // Indicate the channel which to transmit channel_NB_IoT_t channel; // rnti @@ -452,7 +451,7 @@ typedef enum ce_level_e{ /*! \brief eNB template for the Random access information */ typedef struct RA_TEMPLATE_NB_IoT_s{ - boolean_t active; + bool active; uint32_t msg3_retransmit_count; uint32_t msg4_retransmit_count; uint16_t ta; @@ -461,8 +460,8 @@ typedef struct RA_TEMPLATE_NB_IoT_s{ rnti_t ue_rnti; rnti_t ra_rnti; struct RA_TEMPLATE_NB_IoT_s *next, *prev; - boolean_t wait_msg4_ack; - boolean_t wait_msg3_ack; + bool wait_msg4_ack; + bool wait_msg3_ack; uint8_t rar_buffer[7]; } RA_TEMPLATE_NB_IoT; @@ -530,7 +529,7 @@ typedef struct { uint32_t pdus_in_buffer; /*!< \brief Number of PDUs buffered in RLC protocol instance (OBSOLETE). */ uint32_t head_sdu_creation_time; /*!< \brief Head SDU creation time. */ uint32_t head_sdu_remaining_size_to_send; /*!< \brief remaining size of sdu: could be the total size or the remaining size of already segmented sdu */ - boolean_t head_sdu_is_segmented; /*!< \brief 0 if head SDU has not been segmented, 1 if already segmented */ + bool head_sdu_is_segmented; /*!< \brief 0 if head SDU has not been segmented, 1 if already segmented */ } mac_rlc_status_resp_NB_IoT_t; // global variables diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index d647eff7cb..53ab98a33f 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -135,7 +135,7 @@ void schedule_SRS(module_id_t module_idP, UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]); /* Test if Active Time not running since 6+ subframes */ - if (UE_scheduling_control->cdrx_configured == TRUE && UE_scheduling_control->in_active_time == FALSE) { + if (UE_scheduling_control->cdrx_configured == true && UE_scheduling_control->in_active_time == false) { /* * TODO: 6+ subframes condition not checked here */ @@ -204,7 +204,7 @@ void schedule_CSI(module_id_t module_idP, cc = &eNB->common_channels[CC_id]; for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (UE_info->active[UE_id] == FALSE) { + if (UE_info->active[UE_id] == false) { continue; } @@ -223,9 +223,9 @@ void schedule_CSI(module_id_t module_idP, */ UE_scheduling_control = &(UE_info->UE_sched_ctrl[UE_id]); - if (UE_scheduling_control->cdrx_configured == TRUE) { + if (UE_scheduling_control->cdrx_configured == true) { /* Test if CQI masking activated */ - if (UE_scheduling_control->cqi_mask_boolean == TRUE) { + if (UE_scheduling_control->cqi_mask_boolean == true) { // CQI masking => test if onDurationTime not running since 6+ subframe if (UE_scheduling_control->on_duration_timer == 0) { /* @@ -234,7 +234,7 @@ void schedule_CSI(module_id_t module_idP, continue; } } else { // No CQI masking => test if Active Time not running since 6+ subframe - if (UE_scheduling_control->in_active_time == FALSE) { + if (UE_scheduling_control->in_active_time == false) { /* * TODO: 6+ subframes condition not checked here */ @@ -677,8 +677,8 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, } /* Set and increment CDRX related timers */ - if (UE_scheduling_control->cdrx_configured == TRUE) { - boolean_t harq_active_time_condition = FALSE; + if (UE_scheduling_control->cdrx_configured == true) { + bool harq_active_time_condition = false; UE_TEMPLATE *UE_template = NULL; unsigned long active_time_condition = 0; // variable used only for tracing purpose @@ -721,7 +721,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, UE_scheduling_control->ul_synchronous_harq_timer[CC_id][harq_process_id]++; if (UE_scheduling_control->ul_synchronous_harq_timer[CC_id][harq_process_id] > 5) { - harq_active_time_condition = TRUE; + harq_active_time_condition = true; UE_scheduling_control->ul_synchronous_harq_timer[CC_id][harq_process_id] = 0; active_time_condition = 5; // for tracing purpose } @@ -747,24 +747,24 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, /* When timer expires switch into short or long DRX cycle */ if (UE_scheduling_control->drx_shortCycle_timer_thres > 0) { - UE_scheduling_control->in_short_drx_cycle = TRUE; + UE_scheduling_control->in_short_drx_cycle = true; UE_scheduling_control->drx_shortCycle_timer = 0; - UE_scheduling_control->in_long_drx_cycle = FALSE; + UE_scheduling_control->in_long_drx_cycle = false; } else { - UE_scheduling_control->in_long_drx_cycle = TRUE; + UE_scheduling_control->in_long_drx_cycle = true; } } } /* Short DRX Cycle */ - if (UE_scheduling_control->in_short_drx_cycle == TRUE) { + if (UE_scheduling_control->in_short_drx_cycle == true) { UE_scheduling_control->drx_shortCycle_timer++; /* When the Short DRX cycles are over, switch to long DRX cycle */ if (UE_scheduling_control->drx_shortCycle_timer > UE_scheduling_control->drx_shortCycle_timer_thres) { UE_scheduling_control->drx_shortCycle_timer = 0; - UE_scheduling_control->in_short_drx_cycle = FALSE; - UE_scheduling_control->in_long_drx_cycle = TRUE; + UE_scheduling_control->in_short_drx_cycle = false; + UE_scheduling_control->in_long_drx_cycle = true; UE_scheduling_control->drx_longCycle_timer = 0; } } else { @@ -772,7 +772,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, } /* Long DRX Cycle */ - if (UE_scheduling_control->in_long_drx_cycle == TRUE) { + if (UE_scheduling_control->in_long_drx_cycle == true) { UE_scheduling_control->drx_longCycle_timer++; if (UE_scheduling_control->drx_longCycle_timer > UE_scheduling_control->drx_longCycle_timer_thres) { @@ -783,18 +783,18 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, } /* Check for error cases */ - if ((UE_scheduling_control->in_short_drx_cycle == TRUE) && (UE_scheduling_control->in_long_drx_cycle == TRUE)) { + if ((UE_scheduling_control->in_short_drx_cycle == true) && (UE_scheduling_control->in_long_drx_cycle == true)) { LOG_E(MAC, "Error in C-DRX: UE id %d is in both short and long DRX cycle. Should not happen. Back it to long cycle only\n", UE_id); - UE_scheduling_control->in_short_drx_cycle = FALSE; + UE_scheduling_control->in_short_drx_cycle = false; } /* Condition to start On Duration Timer */ - if (UE_scheduling_control->in_short_drx_cycle == TRUE && UE_scheduling_control->on_duration_timer == 0) { + if (UE_scheduling_control->in_short_drx_cycle == true && UE_scheduling_control->on_duration_timer == 0) { if (((frameP * 10) + subframeP) % (UE_scheduling_control->short_drx_cycle_duration) == (UE_scheduling_control->drx_start_offset) % (UE_scheduling_control->short_drx_cycle_duration)) { UE_scheduling_control->on_duration_timer = 1; } - } else if (UE_scheduling_control->in_long_drx_cycle == TRUE && UE_scheduling_control->on_duration_timer == 0) { + } else if (UE_scheduling_control->in_long_drx_cycle == true && UE_scheduling_control->on_duration_timer == 0) { if (((frameP * 10) + subframeP) % (UE_scheduling_control->drx_longCycle_timer_thres) == (UE_scheduling_control->drx_start_offset)) { UE_scheduling_control->on_duration_timer = 1; @@ -811,7 +811,7 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, /* (a)synchronous HARQ processes handling for Active Time */ for (int harq_process_id = 0; harq_process_id < 8; harq_process_id++) { if (UE_scheduling_control->drx_retransmission_timer[harq_process_id] > 0) { - harq_active_time_condition = TRUE; + harq_active_time_condition = true; active_time_condition = 2; // for tracing purpose break; } @@ -822,9 +822,9 @@ eNB_dlsch_ulsch_scheduler(module_id_t module_idP, UE_scheduling_control->drx_inactivity_timer > 1 || harq_active_time_condition || UE_template->ul_SR > 0) { - UE_scheduling_control->in_active_time = TRUE; + UE_scheduling_control->in_active_time = true; } else { - UE_scheduling_control->in_active_time = FALSE; + UE_scheduling_control->in_active_time = false; } /* BEGIN VCD */ diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA.c b/openair2/LAYER2/MAC/eNB_scheduler_RA.c index e5b95a7f47..c659df8d31 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_RA.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_RA.c @@ -1225,7 +1225,7 @@ check_Msg4_retransmission(module_id_t module_idP, int CC_idP, LOG_D(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d: state:IDLE\n", module_idP, frameP, subframeP); UE_id = find_UE_id(module_idP, ra->rnti); DevAssert(UE_id != -1); - mac->UE_info.UE_template[UE_PCCID(module_idP, UE_id)][UE_id].configured = TRUE; + mac->UE_info.UE_template[UE_PCCID(module_idP, UE_id)][UE_id].configured = true; mac->UE_info.UE_template[UE_PCCID(module_idP, UE_id)][UE_id].pusch_repetition_levels=ra->pusch_repetition_levels; cancel_ra_proc(module_idP, CC_idP, frameP, ra->rnti); } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 596d978a98..0898622115 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -2075,7 +2075,7 @@ schedule_PCH(module_id_t module_idP, for (uint16_t i = 0; i < MAX_MOBILES_PER_ENB; i++) { ue_pf_po = &UE_PF_PO[CC_id][i]; - if (ue_pf_po->enable_flag != TRUE) { + if (ue_pf_po->enable_flag != true) { continue; } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c index 6c9ffabd4f..9836b643d4 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_fairRR.c @@ -69,7 +69,7 @@ int last_ulsch_ue_id_volte[MAX_NUM_CCs] = {-1}; uint16_t pre_nb_rbs_required[2][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; uint8_t dlsch_ue_select_tbl_in_use; uint8_t new_dlsch_ue_select_tbl_in_use; - boolean_t pre_scd_activeUE[NUMBER_OF_UE_MAX]; + bool pre_scd_activeUE[NUMBER_OF_UE_MAX]; eNB_UE_STATS pre_scd_eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; #endif @@ -125,7 +125,7 @@ void pre_scd_nb_rbs_required( module_id_t module_idP, UE_info_t *UE_info = &RC.mac[module_idP]->UE_info; for (UE_id = 0; UE_id DL_req[CC_id].dl_config_request_body; for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) { - if (UE_info->active[UE_id] == FALSE) { + if (UE_info->active[UE_id] == false) { continue; } @@ -331,7 +331,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( break; } - if (UE_info->active[UE_id] == FALSE) { + if (UE_info->active[UE_id] == false) { continue; } @@ -459,7 +459,7 @@ void dlsch_scheduler_pre_ue_select_fairRR( break; } - if (UE_info->active[UE_id] == FALSE) { + if (UE_info->active[UE_id] == false) { continue; } @@ -607,7 +607,7 @@ static void dlsch_scheduler_pre_processor_reset_fairRR( if (rnti == NOT_A_RNTI) continue; - if (UE_info->active[UE_id] != TRUE) + if (UE_info->active[UE_id] != true) continue; LOG_D(MAC, "Running preprocessor for UE %d (%x)\n", UE_id, rnti); @@ -755,7 +755,7 @@ static void assign_rbs_required_fairRR( // clear rb allocations across all CC_id for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (UE_info->active[UE_id] != TRUE) + if (UE_info->active[UE_id] != true) continue; pCCid = UE_PCCID(Mod_id, UE_id); @@ -945,7 +945,7 @@ void dlsch_scheduler_pre_processor_fairRR (module_id_t Mod_id, min_rb_unit[CC_id] = get_min_rb_unit(Mod_id, CC_id); for (i = 0; i < NUMBER_OF_UE_MAX; i++) { - if (UE_info->active[i] != TRUE) + if (UE_info->active[i] != true) continue; UE_id = i; @@ -2241,7 +2241,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( // UE round >0 for ( UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++ ) { - if (UE_info->active[UE_id] == FALSE) + if (UE_info->active[UE_id] == false) continue; rnti = UE_RNTI(module_idP,UE_id); @@ -2251,7 +2251,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( CC_id = UE_PCCID(module_idP,UE_id); - if (UE_info->UE_template[CC_id][UE_id].configured == FALSE) + if (UE_info->UE_template[CC_id][UE_id].configured == false) continue; if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer > 0 @@ -2401,7 +2401,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( } for ( UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++ ) { - if (UE_info->active[UE_id] == FALSE) + if (UE_info->active[UE_id] == false) continue; rnti = UE_RNTI(module_idP,UE_id); @@ -2414,7 +2414,7 @@ void ulsch_scheduler_pre_ue_select_fairRR( if (UE_id > last_ulsch_ue_id[CC_id]) continue; - if (UE_info->UE_template[CC_id][UE_id].configured == FALSE) + if (UE_info->UE_template[CC_id][UE_id].configured == false) continue; if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer > 0 diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index d53e0cadd3..4469d0a3f9 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -1989,7 +1989,7 @@ find_UE_id(module_id_t mod_idP, return -1; for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) { - if (UE_info->active[UE_id] == TRUE) { + if (UE_info->active[UE_id] == true) { int CC_id = UE_PCCID(mod_idP, UE_id); if (CC_id>=0 && CC_idUE_template[CC_id][UE_id].rnti == rntiP) { return UE_id; @@ -2063,7 +2063,7 @@ UE_RNTI(module_id_t mod_idP, } //------------------------------------------------------------------------------ -boolean_t +bool is_UE_active(module_id_t mod_idP, int ue_idP) //------------------------------------------------------------------------------ @@ -2187,20 +2187,20 @@ add_new_ue(module_id_t mod_idP, UE_info->num_UEs); for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { - if (UE_info->active[i] == TRUE) + if (UE_info->active[i] == true) continue; UE_id = i; memset(&UE_info->UE_template[cc_idP][UE_id], 0, sizeof(UE_TEMPLATE)); UE_info->UE_template[cc_idP][UE_id].rnti = rntiP; - UE_info->UE_template[cc_idP][UE_id].configured = FALSE; + UE_info->UE_template[cc_idP][UE_id].configured = false; UE_info->numactiveCCs[UE_id] = 1; UE_info->numactiveULCCs[UE_id] = 1; UE_info->pCC_id[UE_id] = cc_idP; UE_info->ordered_CCids[0][UE_id] = cc_idP; UE_info->ordered_ULCCids[0][UE_id] = cc_idP; UE_info->num_UEs++; - UE_info->active[UE_id] = TRUE; + UE_info->active[UE_id] = true; add_ue_list(&UE_info->list, UE_id); dump_ue_list(&UE_info->list); pp_impl_param_t* dl = &RC.mac[mod_idP]->pre_processor_dl; @@ -2280,7 +2280,7 @@ rrc_mac_remove_ue(module_id_t mod_idP, UE_id, pCC_id, rntiP); - UE_info->active[UE_id] = FALSE; + UE_info->active[UE_id] = false; UE_info->num_UEs--; remove_ue_list(&UE_info->list, UE_id); @@ -3488,7 +3488,7 @@ has_ul_grant(module_id_t module_idP, } //------------------------------------------------------------------------------ -boolean_t +bool CCE_allocation_infeasible(int module_idP, int CC_idP, int format_flag, @@ -3501,7 +3501,7 @@ CCE_allocation_infeasible(int module_idP, nfapi_dl_config_request_pdu_t *dl_config_pdu = &DL_req->dl_config_pdu_list[DL_req->number_pdu]; nfapi_hi_dci0_request_body_t *HI_DCI0_req = &RC.mac[module_idP]->HI_DCI0_req[CC_idP][subframe].hi_dci0_request_body; nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci + HI_DCI0_req->number_of_hi]; - boolean_t res = TRUE; + bool res = true; if (format_flag != 2) { // DL DCI if (DL_req->number_pdu == MAX_NUM_DL_PDU) { @@ -3517,7 +3517,7 @@ CCE_allocation_infeasible(int module_idP, subframe, format_flag, rnti, aggregation); if (allocate_CCEs(module_idP, CC_idP, 0, subframe, 0) != -1) - res = FALSE; + res = false; DL_req->number_pdu--; } @@ -3532,7 +3532,7 @@ CCE_allocation_infeasible(int module_idP, HI_DCI0_req->number_of_dci++; if (allocate_CCEs(module_idP, CC_idP, 0, subframe, 0) != -1) - res = FALSE; + res = false; HI_DCI0_req->number_of_dci--; } @@ -5029,7 +5029,7 @@ SR_indication(module_id_t mod_idP, if (UE_id != -1) { UE_scheduling_ctrl = &(UE_info->UE_sched_ctrl[UE_id]); - if ((UE_scheduling_ctrl->cdrx_configured == TRUE) && + if ((UE_scheduling_ctrl->cdrx_configured == true) && (UE_scheduling_ctrl->dci0_ongoing_timer > 0) && (UE_scheduling_ctrl->dci0_ongoing_timer < 8)) { LOG_D(MAC, "[eNB %d][SR %x] Frame %d subframeP %d Signaling SR for UE %d on CC_id %d. \ @@ -5052,7 +5052,7 @@ SR_indication(module_id_t mod_idP, } UE_info->UE_template[cc_idP][UE_id].ul_SR = 1; - UE_info->UE_template[cc_idP][UE_id].ul_active = TRUE; + UE_info->UE_template[cc_idP][UE_id].ul_active = true; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SR_INDICATION, 1); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SR_INDICATION, 0); } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index d4f486f761..a31b8bdd03 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -242,7 +242,7 @@ rx_sdu(const module_id_t enb_mod_idP, } /* CDRX UL HARQ timers */ - if (UE_scheduling_control->cdrx_configured == TRUE) { + if (UE_scheduling_control->cdrx_configured == true) { /* Synchronous UL HARQ */ UE_scheduling_control->ul_synchronous_harq_timer[CC_idP][harq_pid] = 5; /* @@ -1003,7 +1003,7 @@ rx_sdu(const module_id_t enb_mod_idP, /* CDRX UL HARQ timers */ if (UE_id != -1) { - if (UE_scheduling_control->cdrx_configured == TRUE) { + if (UE_scheduling_control->cdrx_configured == true) { /* Synchronous UL HARQ */ UE_scheduling_control->ul_synchronous_harq_timer[CC_idP][harq_pid] = 5; /* @@ -1447,7 +1447,7 @@ schedule_ulsch_rnti(module_id_t module_idP, continue; // don't schedule if Msg5 is not received yet - if (UE_info->UE_template[CC_id][UE_id].configured == FALSE) { + if (UE_info->UE_template[CC_id][UE_id].configured == false) { LOG_D(MAC, "[eNB %d] frame %d, subframe %d, UE %d: not configured, skipping " "UE scheduling \n", @@ -2033,7 +2033,7 @@ void schedule_ulsch_rnti_emtc(module_id_t module_idP, } /* Don't schedule if Msg4 is not received yet */ - if (UE_template->configured == FALSE) { + if (UE_template->configured == false) { LOG_D(MAC,"[eNB %d] frame %d subframe %d, UE %d: not configured, skipping UE scheduling \n", module_idP, frameP, diff --git a/openair2/LAYER2/MAC/mac.h b/openair2/LAYER2/MAC/mac.h index 6637d05a8a..2392c8506b 100644 --- a/openair2/LAYER2/MAC/mac.h +++ b/openair2/LAYER2/MAC/mac.h @@ -811,9 +811,9 @@ typedef struct { /// TBS from last UL scheduling int TBS_UL[8]; /// Flag to indicate UL has been scheduled at least once - boolean_t ul_active; + bool ul_active; /// Flag to indicate UE has been configured (ACK from RRCConnectionSetup received) - boolean_t configured; + bool configured; /// MCS from last scheduling uint8_t mcs[8]; @@ -1026,16 +1026,16 @@ typedef struct { /* C-DRX related timers */ /* Note: only valid for FDD and LTE UE when this comment is written (11-01-19)*/ - /// is TRUE if the cqi mask feature is activated by RRC configuration - boolean_t cqi_mask_boolean; - /// is TRUE if the following drx parameters are configured for UE - boolean_t cdrx_configured; + /// is true if the cqi mask feature is activated by RRC configuration + bool cqi_mask_boolean; + /// is true if the following drx parameters are configured for UE + bool cdrx_configured; /* - * if TRUE, the eNB has configured the CDRX locally, but is waiting for the UE to acknowledge + * if true, the eNB has configured the CDRX locally, but is waiting for the UE to acknowledge * the activation. This is needed, during the RRC configuration process, when the context is * configured on the eNB side, but not yet on the UE side... */ - boolean_t cdrx_waiting_ack; + bool cdrx_waiting_ack; /* * Is set when a ULSCH scheduling is done and run until the first corresponding transmission is done (4 subframes). * When set, SR cannot be set for the UE. This allows OAI to avoid concidering a SR as uncompleted if the UE sends @@ -1043,16 +1043,16 @@ typedef struct { * create a lost in timers synchronization. */ uint8_t dci0_ongoing_timer; - /// is TRUE if the UE is in "Active Time", hence listening to PDCCH - boolean_t in_active_time; + /// is true if the UE is in "Active Time", hence listening to PDCCH + bool in_active_time; /// OnDurationTimer uint16_t on_duration_timer; uint16_t on_duration_timer_thres; /// drx-InactivityTimer uint16_t drx_inactivity_timer; uint16_t drx_inactivity_timer_thres; - /// is TRUE if UE is currently in short DRX cycle - boolean_t in_short_drx_cycle; + /// is true if UE is currently in short DRX cycle + bool in_short_drx_cycle; /// drxShortCycleTimer int (1..16) (number of short DRX cycles duration before long DRX cycles) uint8_t drx_shortCycle_timer_value; /// shortDRX-Cycle (duration of one short DRX cycle) @@ -1060,8 +1060,8 @@ typedef struct { /// DRX short cycle timer before switching to long DRX cycle = drx_shortCycle_timer_value * short_drx_cycle_duration uint16_t drx_shortCycle_timer; uint16_t drx_shortCycle_timer_thres; - /// is TRUE if UE is currently in long DRX cycle - boolean_t in_long_drx_cycle; + /// is true if UE is currently in long DRX cycle + bool in_long_drx_cycle; /// longDRX-CycleStartOffset (long DRX cycle timer) uint16_t drx_longCycle_timer; uint16_t drx_longCycle_timer_thres; @@ -1183,7 +1183,7 @@ typedef struct { UE_sched_ctrl_t UE_sched_ctrl[MAX_MOBILES_PER_ENB]; UE_list_t list; int num_UEs; - boolean_t active[MAX_MOBILES_PER_ENB]; + bool active[MAX_MOBILES_PER_ENB]; } UE_info_t; /*! \brief deleting control information*/ @@ -1191,9 +1191,9 @@ typedef struct { ///rnti of UE rnti_t rnti; ///remove UE context flag - boolean_t removeContextFlg; + bool removeContextFlg; ///remove RA flag - boolean_t raFlag; + bool raFlag; } UE_free_ctrl_t; /*! \brief REMOVE UE list used by eNB to order UEs/CC for deleting*/ typedef struct { diff --git a/openair2/LAYER2/MAC/mac_extern.h b/openair2/LAYER2/MAC/mac_extern.h index 522dc2721f..212422898b 100644 --- a/openair2/LAYER2/MAC/mac_extern.h +++ b/openair2/LAYER2/MAC/mac_extern.h @@ -71,7 +71,7 @@ extern rb_id_t mbms_rab_id; extern uint16_t pre_nb_rbs_required[2][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; extern uint8_t dlsch_ue_select_tbl_in_use; extern uint8_t new_dlsch_ue_select_tbl_in_use; -extern boolean_t pre_scd_activeUE[NUMBER_OF_UE_MAX]; +extern bool pre_scd_activeUE[NUMBER_OF_UE_MAX]; extern eNB_UE_STATS pre_scd_eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; #endif diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index b92ce85608..889c727fdd 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -400,7 +400,7 @@ int find_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP); rnti_t UE_RNTI(module_id_t module_idP, int UE_id); int UE_PCCID(module_id_t module_idP, int UE_id); uint8_t find_active_UEs(module_id_t module_idP); -boolean_t is_UE_active(module_id_t module_idP, int UE_id); +bool is_UE_active(module_id_t module_idP, int UE_id); uint8_t get_aggregation(uint8_t bw_index, uint8_t cqi, uint8_t dci_fmt); int8_t find_active_UEs_with_traffic(module_id_t module_idP); @@ -416,11 +416,11 @@ int get_nCCE_offset(int *CCE_table, int allocate_CCEs(int module_idP, int CC_idP, frame_t frameP, sub_frame_t subframeP, int test_only); -boolean_t CCE_allocation_infeasible(int module_idP, - int CC_idP, - int common_flag, - int subframe, - int aggregation, int rnti); +bool CCE_allocation_infeasible(int module_idP, + int CC_idP, + int common_flag, + int subframe, + int aggregation, int rnti); /* tries to allocate a CCE. If it succeeds, reserves NFAPI DCI and DLSCH config */ int CCE_try_allocate_dlsch(int module_id, int CC_id, @@ -741,13 +741,12 @@ BSR_SHORT *get_bsr_short(module_id_t module_idP, uint8_t bsr_len); */ BSR_LONG *get_bsr_long(module_id_t module_idP, uint8_t bsr_len); -/*! \fn boolean_t update_bsr(module_id_t module_idP, frame_t frameP,sub_frame_t subframeP) +/*! \fn bool update_bsr(module_id_t module_idP, frame_t frameP,sub_frame_t subframeP) \brief get the rlc stats and update the bsr level for each lcid \param[in] Mod_id instance of the UE \param[in] frame Frame index */ -boolean_t update_bsr(module_id_t module_idP, frame_t frameP, - sub_frame_t subframeP, eNB_index_t eNB_index); +bool update_bsr(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, eNB_index_t eNB_index); /*! \fn locate_BsrIndexByBufferSize (int *table, int size, int value) \brief locate the BSR level in the table as defined in 36.321. This function requires that he values in table to be monotonic, either increasing or decreasing. The returned value is not less than 0, nor greater than n-1, where n is the size of table. diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index bb969668d6..db4d51a92f 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -638,7 +638,7 @@ dlsch_scheduler_pre_processor(module_id_t Mod_id, LOG_E(MAC, "UE %d has RNTI NOT_A_RNTI!\n", UE_id); continue; } - if (UE_info->active[UE_id] != TRUE) { + if (UE_info->active[UE_id] != true) { LOG_E(MAC, "UE %d RNTI %x is NOT active!\n", UE_id, rnti); continue; } diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c index 926c44381c..d7796d1d40 100644 --- a/openair2/LAYER2/MAC/ue_procedures.c +++ b/openair2/LAYER2/MAC/ue_procedures.c @@ -2325,8 +2325,8 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, uint8_t bsr_len = 0, bsr_ce_len = 0, bsr_header_len = 0; uint8_t phr_header_len = 0, phr_ce_len = 0, phr_len = 0; uint8_t lcid = 0, lcid_rlc_pdu_count = 0; - boolean_t is_lcid_processed = FALSE; - boolean_t is_all_lcid_processed = FALSE; + bool is_lcid_processed = false; + bool is_all_lcid_processed = false; uint16_t sdu_lengths[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; uint8_t sdu_lcids[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; uint8_t payload_offset = 0, num_sdus = 0; @@ -2444,11 +2444,11 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, // Check for DCCH first // TO DO: Multiplex in the order defined by the logical channel prioritization for (lcid = DCCH; - (lcid < MAX_NUM_LCID) && (is_all_lcid_processed == FALSE); lcid++) { + (lcid < MAX_NUM_LCID) && (is_all_lcid_processed == false); lcid++) { if (UE_mac_inst[module_idP].scheduling_info.LCID_status[lcid] == LCID_NOT_EMPTY) { lcid_rlc_pdu_count = 0; - is_lcid_processed = FALSE; + is_lcid_processed = false; lcid_buffer_occupancy_old = mac_rlc_get_buffer_occupancy_ind(module_idP, UE_mac_inst[module_idP]. @@ -2536,8 +2536,8 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, //No more remaining TBS after this PDU //exit the function rlc_pdu_header_len_last = 1; - is_lcid_processed = TRUE; - is_all_lcid_processed = TRUE; + is_lcid_processed = true; + is_all_lcid_processed = true; } else { rlc_pdu_header_len_last = (sdu_lengths[num_sdus] > 128) ? 3 : 2; @@ -2547,8 +2547,8 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, (bsr_len + phr_len + total_rlc_pdu_header_len + rlc_pdu_header_len_last + sdu_length_total)) { rlc_pdu_header_len_last = 1; - is_lcid_processed = TRUE; - is_all_lcid_processed = TRUE; + is_lcid_processed = true; + is_all_lcid_processed = true; } } @@ -2559,7 +2559,7 @@ ue_get_sdu(module_id_t module_idP, int CC_id, frame_t frameP, lcid_rlc_pdu_count++; } else { /* avoid infinite loop ... */ - is_lcid_processed = TRUE; + is_lcid_processed = true; } /* Get updated BO after multiplexing this PDU */ @@ -3164,7 +3164,7 @@ ue_scheduler(const module_id_t module_idP, } //Check whether Regular BSR is triggered - if (update_bsr(module_idP, txFrameP, txSubframeP, eNB_indexP) == TRUE) { + if (update_bsr(module_idP, txFrameP, txSubframeP, eNB_indexP) == true) { // call SR procedure to generate pending SR and BSR for next PUCCH/PUSCH TxOp. This should implement the procedures // outlined in Sections 5.4.4 an 5.4.5 of 36.321 UE_mac_inst[module_idP].scheduling_info.SR_pending = 1; @@ -3251,11 +3251,11 @@ ue_scheduler(const module_id_t module_idP, // to be improved -boolean_t +bool update_bsr(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, eNB_index_t eNB_index) { mac_rlc_status_resp_t rlc_status; - boolean_t bsr_regular_triggered = FALSE; + bool bsr_regular_triggered = false; uint8_t lcid; uint8_t lcgid; uint8_t num_lcid_with_data = 0; // for LCID with data only if LCGID is defined @@ -3352,7 +3352,7 @@ update_bsr(module_id_t module_idP, frame_t frameP, (lcgid_buffer_remain [UE_mac_inst[module_idP].scheduling_info.LCGID[lcid]] == 0)) { - bsr_regular_triggered = TRUE; + bsr_regular_triggered = true; LOG_D(MAC, "[UE %d] PDCCH Tick : MAC BSR Triggered LCID%d LCGID%d data become available at frame %d subframe %d\n", module_idP, lcid, @@ -3364,7 +3364,7 @@ update_bsr(module_id_t module_idP, frame_t frameP, // Trigger Regular BSR if ReTxBSR Timer has expired and UE has data for transmission if (UE_mac_inst[module_idP].scheduling_info.retxBSR_SF == 0) { - bsr_regular_triggered = TRUE; + bsr_regular_triggered = true; if ((UE_mac_inst[module_idP].BSR_reporting_active & BSR_TRIGGER_REGULAR) == 0) { diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h index 4b37c19dff..7bbe8d68a7 100644 --- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h +++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_extern.h @@ -74,7 +74,7 @@ extern uint8_t rb_table[34]; extern uint16_t pre_nb_rbs_required[2][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; extern uint8_t dlsch_ue_select_tbl_in_use; extern uint8_t new_dlsch_ue_select_tbl_in_use; -extern boolean_t pre_scd_activeUE[NUMBER_OF_UE_MAX]; +extern bool pre_scd_activeUE[NUMBER_OF_UE_MAX]; extern eNB_UE_STATS pre_scd_eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; #endif*/ diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 5ffccf28d3..072f0e58de 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -580,7 +580,7 @@ int nr_rrc_mac_config_req_ue_logicalChannelBearer( int cc_idP, uint8_t gNB_index, long logicalChannelIdentity, - boolean_t status){ + bool status){ NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); mac->logicalChannelBearer_exist[logicalChannelIdentity] = status; return 0; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 800e042464..05b6634655 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -415,7 +415,7 @@ typedef struct { uint8_t BSR_reporting_active; /// LogicalChannelConfig has bearer. - boolean_t logicalChannelBearer_exist[NR_MAX_NUM_LCID]; + bool logicalChannelBearer_exist[NR_MAX_NUM_LCID]; NR_UE_SCHEDULING_INFO scheduling_info; /// PHR @@ -546,7 +546,7 @@ typedef struct prach_association_pattern { // SSB details typedef struct ssb_info { - boolean_t transmitted; // True if the SSB index is transmitted according to the SSB positions map configuration + bool transmitted; // True if the SSB index is transmitted according to the SSB positions map configuration prach_occasion_info_t *mapped_ro[MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions to this SSB index uint16_t nb_mapped_ro; // Total number of mapped ROs to this SSB index } ssb_info_t; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index caa4af4144..38f774be76 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -85,14 +85,12 @@ int8_t nr_ue_decode_BCCH_DL_SCH(module_id_t module_id, \param cc_id component carrier id \param gNB_index gNB index \param long logicalChannelIdentity - \param boolean_t status*/ -int nr_rrc_mac_config_req_ue_logicalChannelBearer( - module_id_t module_id, - int cc_idP, - uint8_t gNB_index, - long logicalChannelIdentity, - boolean_t status -); + \param bool status*/ +int nr_rrc_mac_config_req_ue_logicalChannelBearer(module_id_t module_id, + int cc_idP, + uint8_t gNB_index, + long logicalChannelIdentity, + bool status); /**\brief primitive from RRC layer to MAC layer for configuration L1/L2, now supported 4 rrc messages: MIB, cell_group_config for MAC/PHY, spcell_config(serving cell config) \param module_id module id @@ -154,14 +152,14 @@ void fill_scheduled_response(nr_scheduled_response_t *scheduled_response, */ int8_t nr_ue_get_SR(module_id_t module_idP, frame_t frameP, slot_t slotP); -/*! \fn boolean_t update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t gNB_index) +/*! \fn bool update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t gNB_index) \brief get the rlc stats and update the bsr level for each lcid \param[in] Mod_id instance of the UE \param[in] frameP Frame index \param[in] slot slotP number \param[in] uint8_t gNB_index */ -boolean_t nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t gNB_index); +bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t gNB_index); /*! \fn nr_locate_BsrIndexByBufferSize (int *table, int size, int value) \brief locate the BSR level in the table as defined in 38.321. This function requires that he values in table to be monotonic, either increasing or decreasing. The returned value is not less than 0, nor greater than n-1, where n is the size of table. diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 735ff1bd54..507cdb2661 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -325,7 +325,7 @@ void ssb_rach_config(RA_config_t *ra, NR_PRACH_RESOURCES_t *prach_resources, NR_ // ======================================= NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; - boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB + bool multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB int total_preambles_per_ssb; uint8_t ssb_nb_in_ro; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 50ea7cdd34..6166fc7038 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -2002,7 +2002,7 @@ int find_pucch_resource_set(NR_UE_MAC_INST_t *mac, int uci_size) { * processing slots of reception/transmission * gNB_id identifier * -* RETURN : TRUE a valid resource has been found +* RETURN : true a valid resource has been found * * DESCRIPTION : return tx harq process identifier for given transmission slot * TS 38.213 9.2.1 PUCCH Resource Sets @@ -2132,7 +2132,7 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, int number_harq_feedback = 0; uint32_t dai_current = 0; uint32_t dai_max = 0; - bool two_transport_blocks = FALSE; + bool two_transport_blocks = false; int number_of_code_word = 1; int U_DAI_c = 0; int N_m_c_rx = 0; @@ -2154,7 +2154,7 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, bwpd->pdsch_Config->choice.setup && bwpd->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI && bwpd->pdsch_Config->choice.setup->maxNrofCodeWordsScheduledByDCI[0] == 2) { - two_transport_blocks = TRUE; + two_transport_blocks = true; number_of_code_word = 2; } @@ -2254,7 +2254,7 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, * For a monitoring occasion of a PDCCH with DCI format 1_0 or DCI format 1_1 in at least one serving cell, * when a UE receives a PDSCH with one transport block and the value of higher layer parameter maxNrofCodeWordsScheduledByDCI is 2, * the HARQ-ACK response is associated with the first transport block and the UE generates a NACK for the second transport block - * if spatial bundling is not applied (HARQ-ACK-spatial-bundling-PUCCH = FALSE) and generates HARQ-ACK value of ACK for the second + * if spatial bundling is not applied (HARQ-ACK-spatial-bundling-PUCCH = false) and generates HARQ-ACK value of ACK for the second * transport block if spatial bundling is applied. */ @@ -2265,7 +2265,7 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, ack_data[code_word][i] = 0; /* nack data transport block which has been missed */ number_harq_feedback++; } - if (two_transport_blocks == TRUE) { + if (two_transport_blocks == true) { dai_total[code_word][i] = dai[code_word][i]; /* for a single cell, dai_total is the same as dai of first cell */ } } @@ -2296,7 +2296,7 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, o_ACK = o_ACK | (ack_data[1][m] << O_bit_number_cw1); } - if (two_transport_blocks == TRUE) { + if (two_transport_blocks == true) { O_bit_number_cw0 = (8 * j) + 2*(V_temp - 1); } else { @@ -2311,7 +2311,7 @@ uint8_t get_downlink_ack(NR_UE_MAC_INST_t *mac, j = j + 1; } - if (two_transport_blocks == TRUE) { + if (two_transport_blocks == true) { O_ACK = 2 * ( 4 * j + V_temp2); /* for two transport blocks */ } else { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index ad6bf3cdc4..f6a42ccaab 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1247,7 +1247,7 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in } //Check whether Regular BSR is triggered - if (nr_update_bsr(mod_id, txFrameP, txSlotP, gNB_indexP) == TRUE) { + if (nr_update_bsr(mod_id, txFrameP, txSlotP, gNB_indexP) == true) { // call SR procedure to generate pending SR and BSR for next PUCCH/PUSCH TxOp. This should implement the procedures // outlined in Sections 5.4.4 an 5.4.5 of 38.321 mac->scheduling_info.SR_pending = 1; @@ -1260,10 +1260,10 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in } -boolean_t +bool nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t gNB_index) { mac_rlc_status_resp_t rlc_status; - boolean_t bsr_regular_triggered = FALSE; + bool bsr_regular_triggered = false; uint8_t lcid; uint8_t lcgid; uint8_t num_lcid_with_data = 0; // for LCID with data only if LCGID is defined @@ -1356,7 +1356,7 @@ nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t gNB_ which belong to any LCG and for which data is already available for transmission */ { - bsr_regular_triggered = TRUE; + bsr_regular_triggered = true; LOG_D(NR_MAC, "[UE %d] PDCCH Tick : MAC BSR Triggered LCID%d LCGID%d data become available at frame %d slot %d\n", module_idP, lcid, mac->scheduling_info.LCGID[lcid], @@ -1367,7 +1367,7 @@ nr_update_bsr(module_id_t module_idP, frame_t frameP, slot_t slotP, uint8_t gNB_ // Trigger Regular BSR if ReTxBSR Timer has expired and UE has data for transmission if (mac->scheduling_info.retxBSR_SF == 0) { - bsr_regular_triggered = TRUE; + bsr_regular_triggered = true; if ((mac->BSR_reporting_active & NR_BSR_TRIGGER_REGULAR) == 0) { LOG_I(NR_MAC, "[UE %d] PDCCH Tick : MAC BSR Triggered ReTxBSR Timer expiry at frame %d slot %d\n", @@ -1628,7 +1628,7 @@ static void build_ro_list(NR_UE_MAC_INST_t *mac) { int y2; // PRACH Configuration Index table additional variable used to compute the valid frame numbers uint8_t slot_shift_for_map; uint8_t map_shift; - boolean_t even_slot_invalid; + bool even_slot_invalid; int64_t s_map; uint8_t prach_conf_start_symbol; // Starting symbol of the PRACH occasions in the PRACH slot uint8_t N_t_slot; // Number of PRACH occasions in a 14-symbols PRACH slot @@ -1900,7 +1900,7 @@ static void map_ssb_to_ro(NR_UE_MAC_INST_t *mac) { mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.rach_ConfigCommon->choice.setup; NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present; - boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB + bool multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB uint16_t required_nb_of_prach_occasion; // Nb of RACH occasions required to map all the SSBs uint8_t required_nb_of_prach_conf_period; // Nb of PRACH configuration periods required to map all the SSBs diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 7658441aed..343b72d6a6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -673,7 +673,6 @@ typedef struct { } NR_UE_sched_ctrl_t; typedef struct { - boolean_t fiveG_connected; uicc_t *uicc; } NRUEcontext_t; diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c index 108a5dbe91..9adc6ecb5d 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c @@ -139,7 +139,7 @@ extern volatile int oai_exit; pthread_t pdcp_stats_thread_desc; // will be called when 4G F1 implementation will use GTP-U instead of protobuf -boolean_t cu_f1u_data_req( +bool cu_f1u_data_req( protocol_ctxt_t *ctxt_pP, const srb_flag_t srb_flagP, const rb_id_t rb_id, @@ -228,7 +228,7 @@ rlc_op_status_t cu_send_to_du(const protocol_ctxt_t *const ctxt, __func__, rb_id, size); extern instance_t CUuniqInstance; itti_send_msg_to_task(TASK_GTPV1_U, CUuniqInstance, message_p); - return TRUE; + return true; } //----------------------------------------------------------------------------- @@ -239,18 +239,16 @@ rlc_op_status_t cu_send_to_du(const protocol_ctxt_t *const ctxt, * this mem_block_t to be dissected for testing purposes. For further details see test * code at targets/TEST/PDCP/test_pdcp.c:test_pdcp_data_req() */ -boolean_t pdcp_data_req( - protocol_ctxt_t *ctxt_pP, - const srb_flag_t srb_flagP, - const rb_id_t rb_idP, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_sizeP, - unsigned char *const sdu_buffer_pP, - const pdcp_transmission_mode_t modeP, - const uint32_t *const sourceL2Id, - const uint32_t *const destinationL2Id -) +bool pdcp_data_req(protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_sizeP, + unsigned char *const sdu_buffer_pP, + const pdcp_transmission_mode_t modeP, + const uint32_t *const sourceL2Id, + const uint32_t *const destinationL2Id) //----------------------------------------------------------------------------- { pdcp_t *pdcp_p = NULL; @@ -261,7 +259,7 @@ boolean_t pdcp_data_req( uint16_t current_sn = 0; mem_block_t *pdcp_pdu_p = NULL; rlc_op_status_t rlc_status; - boolean_t ret = TRUE; + bool ret = true; hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE; hashtable_rc_t h_rc; uint8_t rb_offset= (srb_flagP == 0) ? DTCH -1 : 0; @@ -277,7 +275,7 @@ boolean_t pdcp_data_req( if (sdu_buffer_sizeP == 0) { LOG_W(PDCP, "Handed SDU is of size 0! Ignoring...\n"); - return FALSE; + return false; } /* @@ -287,12 +285,12 @@ boolean_t pdcp_data_req( sdu_buffer_sizeP, MAX_IP_PACKET_SIZE); if (modeP == PDCP_TRANSMISSION_MODE_TRANSPARENT) { - AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE, "RB id is too high (%ld/%d) %u %u!\n", rb_idP, NB_RB_MBMS_MAX, ctxt_pP->module_id, ctxt_pP->rnti); + AssertError (rb_idP < NB_RB_MBMS_MAX, return false, "RB id is too high (%ld/%d) %u %u!\n", rb_idP, NB_RB_MBMS_MAX, ctxt_pP->module_id, ctxt_pP->rnti); } else { if (srb_flagP) { - AssertError (rb_idP < 3, return FALSE, "RB id is too high (%ld/%d) %u %u!\n", rb_idP, 3, ctxt_pP->module_id, ctxt_pP->rnti); + AssertError (rb_idP < 3, return false, "RB id is too high (%ld/%d) %u %u!\n", rb_idP, 3, ctxt_pP->module_id, ctxt_pP->rnti); } else { - AssertError (rb_idP < LTE_maxDRB, return FALSE, "RB id is too high (%ld/%d) %u %u!\n", rb_idP, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti); + AssertError (rb_idP < LTE_maxDRB, return false, "RB id is too high (%ld/%d) %u %u!\n", rb_idP, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti); } } @@ -304,7 +302,7 @@ boolean_t pdcp_data_req( LOG_W(PDCP, PROTOCOL_CTXT_FMT" Instance is not configured for rb_id %ld Ignoring SDU...\n", PROTOCOL_CTXT_ARGS(ctxt_pP), rb_idP); - return FALSE; + return false; } } @@ -371,7 +369,7 @@ boolean_t pdcp_data_req( memset(&pdu_header.mac_i[0],0,PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE); memset(&pdcp_pdu_p->data[sdu_buffer_sizeP + pdcp_header_len],0,PDCP_CONTROL_PLANE_DATA_PDU_MAC_I_SIZE); - if (pdcp_serialize_control_plane_data_pdu_with_SRB_sn_buffer((unsigned char *)pdcp_pdu_p->data, &pdu_header) == FALSE) { + if (pdcp_serialize_control_plane_data_pdu_with_SRB_sn_buffer((unsigned char *)pdcp_pdu_p->data, &pdu_header) == false) { LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Cannot fill PDU buffer with relevant header fields!\n", PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p)); @@ -382,7 +380,7 @@ boolean_t pdcp_data_req( } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT); - return FALSE; + return false; } } else { pdcp_user_plane_data_pdu_header_with_long_sn pdu_header; @@ -390,7 +388,7 @@ boolean_t pdcp_data_req( pdu_header.sn = pdcp_get_next_tx_seq_number(pdcp_p); current_sn = pdu_header.sn ; - if (pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer((unsigned char *)pdcp_pdu_p->data, &pdu_header) == FALSE) { + if (pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer((unsigned char *)pdcp_pdu_p->data, &pdu_header) == false) { LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" Cannot fill PDU buffer with relevant header fields!\n", PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP,pdcp_p)); @@ -401,7 +399,7 @@ boolean_t pdcp_data_req( } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT); - return FALSE; + return false; } } @@ -422,7 +420,7 @@ boolean_t pdcp_data_req( } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT); - return FALSE; + return false; } LOG_D(PDCP, "Sequence number %d is assigned to current PDU\n", current_sn); @@ -481,7 +479,7 @@ boolean_t pdcp_data_req( ctxt_pP->module_id, rb_idP); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_REQ,VCD_FUNCTION_OUT); - return FALSE; + return false; } /* @@ -497,16 +495,16 @@ boolean_t pdcp_data_req( if (ctxt_pP->enb_flag == ENB_FLAG_YES && NODE_IS_DU(RC.rrc[ctxt_pP->module_id]->node_type)) { LOG_E(PDCP, "Can't be DU, bad node type %d \n", RC.rrc[ctxt_pP->module_id]->node_type); - ret=FALSE; + ret = false; } else { rlc_status = pdcp_params.send_rlc_data_req_func(ctxt_pP, srb_flagP, MBMS_FLAG_NO, rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p,sourceL2Id, destinationL2Id); - ret=FALSE; + ret = false; switch (rlc_status) { case RLC_OP_STATUS_OK: LOG_D(PDCP, "Data sending request over RLC succeeded!\n"); - ret=TRUE; + ret=true; break; case RLC_OP_STATUS_BAD_PARAMETER: @@ -544,7 +542,7 @@ boolean_t pdcp_data_req( itti_send_msg_to_task (TASK_CU_F1, ctxt_pP->module_id, message_p); //CU_send_DL_RRC_MESSAGE_TRANSFER(ctxt_pP->module_id, message_p); LOG_I(PDCP, "Send F1AP_DL_RRC_MESSAGE with ITTI\n"); - ret=TRUE; + ret=true; } else { rlc_status = rlc_data_req(ctxt_pP , srb_flagP @@ -561,27 +559,27 @@ boolean_t pdcp_data_req( switch (rlc_status) { case RLC_OP_STATUS_OK: LOG_D(PDCP, "Data sending request over RLC succeeded!\n"); - ret=TRUE; + ret=true; break; case RLC_OP_STATUS_BAD_PARAMETER: LOG_W(PDCP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n"); - ret= FALSE; + ret= false; break; case RLC_OP_STATUS_INTERNAL_ERROR: LOG_W(PDCP, "Data sending request over RLC failed with 'Internal Error' reason!\n"); - ret= FALSE; + ret= false; break; case RLC_OP_STATUS_OUT_OF_RESSOURCES: LOG_W(PDCP, "Data sending request over RLC failed with 'Out of Resources' reason!\n"); - ret= FALSE; + ret= false; break; default: LOG_W(PDCP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status); - ret= FALSE; + ret= false; break; } // switch case } @@ -596,7 +594,7 @@ boolean_t pdcp_data_req( /* * Control arrives here only if rlc_data_req() returns RLC_OP_STATUS_OK - * so we return TRUE afterwards + * so we return true afterwards */ for (pdcp_uid=0; pdcp_uid< MAX_MOBILES_PER_ENB; pdcp_uid++) { @@ -619,7 +617,7 @@ boolean_t pdcp_data_req( //----------------------------------------------------------------------------- -boolean_t +bool pdcp_data_ind( const protocol_ctxt_t *const ctxt_pP, const srb_flag_t srb_flagP, @@ -638,7 +636,7 @@ pdcp_data_ind( pdcp_sn_t sequence_number = 0; volatile sdu_size_t payload_offset = 0; rb_id_t rb_id = rb_idP; - boolean_t packet_forwarded = FALSE; + bool packet_forwarded = false; hash_key_t key = HASHTABLE_NOT_A_KEY_VALUE; hashtable_rc_t h_rc; uint8_t rb_offset= (srb_flagP == 0) ? DTCH -1 :0; @@ -654,7 +652,7 @@ pdcp_data_ind( "[MSG] PDCP UL %s PDU on rb_id %ld\n", (srb_flagP)? "CONTROL" : "DATA", rb_idP); if (MBMS_flagP) { - AssertError (rb_idP < NB_RB_MBMS_MAX, return FALSE, + AssertError (rb_idP < NB_RB_MBMS_MAX, return false, "RB id is too high (%ld/%d) %u rnti %x!\n", rb_idP, NB_RB_MBMS_MAX, @@ -680,12 +678,12 @@ pdcp_data_ind( } } else { rb_id = rb_idP % LTE_maxDRB; - AssertError (rb_id < LTE_maxDRB, return FALSE, "RB id is too high (%ld/%d) %u UE %x!\n", + AssertError (rb_id < LTE_maxDRB, return false, "RB id is too high (%ld/%d) %u UE %x!\n", rb_id, LTE_maxDRB, ctxt_pP->module_id, ctxt_pP->rnti); - AssertError (rb_id > 0, return FALSE, "RB id is too low (%ld/%d) %u UE %x!\n", + AssertError (rb_id > 0, return false, "RB id is too low (%ld/%d) %u UE %x!\n", rb_id, LTE_maxDRB, ctxt_pP->module_id, @@ -700,14 +698,14 @@ pdcp_data_ind( key); free_mem_block(sdu_buffer_pP, __func__); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT); - return FALSE; + return false; } } if (sdu_buffer_sizeP == 0) { LOG_W(PDCP, "SDU buffer size is zero! Ignoring this chunk!\n"); - return FALSE; + return false; } if (ctxt_pP->enb_flag) { @@ -764,13 +762,13 @@ pdcp_data_ind( } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT); - return FALSE; + return false; } #if 0 /* Removed by Cedric */ - if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p, srb_flagP) == TRUE) { + if (pdcp_is_rx_seq_number_valid(sequence_number, pdcp_p, srb_flagP) == true) { LOG_T(PDCP, "Incoming PDU has a sequence number (%d) in accordance with RX window\n", sequence_number); /* if (dc == PDCP_DATA_PDU ) LOG_D(PDCP, "Passing piggybacked SDU to NAS driver...\n"); @@ -788,7 +786,7 @@ pdcp_data_ind( */ LOG_W(PDCP, "Ignoring PDU...\n"); free_mem_block(sdu_buffer_pP, __func__); - return FALSE; + return false; } #endif @@ -837,7 +835,7 @@ pdcp_data_ind( LOG_W(PDCP, "Ignoring PDU...\n"); free_mem_block(sdu_buffer_pP, __func__); /* TODO: indicate integrity verification failure to upper layer */ - return FALSE; + return false; } if (sequence_number < pdcp_p->next_pdcp_rx_sn) @@ -864,7 +862,7 @@ pdcp_data_ind( } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT); - return TRUE; + return true; } /* if (srb_flagP) */ /* @@ -892,7 +890,7 @@ pdcp_data_ind( LOG_W(PDCP, "Ignoring PDU...\n"); free_mem_block(sdu_buffer_pP, __func__); /* TODO: indicate integrity verification failure to upper layer */ - return FALSE; + return false; } else if (pdcp_p->next_pdcp_rx_sn - sequence_number > reordering_window) { pdcp_p->rx_hfn++; rx_hfn_for_count = pdcp_p->rx_hfn; @@ -948,7 +946,7 @@ pdcp_data_ind( LOG_W(PDCP, "Ignoring PDU...\n"); free_mem_block(sdu_buffer_pP, __func__); /* TODO: indicate integrity verification failure to upper layer */ - return FALSE; + return false; } /* TODO: specs say we have to store this PDU in a list and then deliver @@ -1015,7 +1013,7 @@ pdcp_data_ind( LOG_W(PDCP, "Ignoring PDU...\n"); free_mem_block(sdu_buffer_pP, __func__); /* TODO: indicate integrity verification failure to upper layer */ - return FALSE; + return false; } break; @@ -1039,7 +1037,7 @@ pdcp_data_ind( } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT); - return TRUE; + return true; } // XXX Decompression would be done at this point @@ -1051,7 +1049,7 @@ pdcp_data_ind( */ if (LINK_ENB_PDCP_TO_GTPV1U) { - if ((TRUE == ctxt_pP->enb_flag) && (FALSE == srb_flagP)) { + if ((true == ctxt_pP->enb_flag) && (false == srb_flagP)) { LOG_D(PDCP, "Sending packet to GTP, Calling GTPV1U_ENB_TUNNEL_DATA_REQ ue %x rab %ld len %u\n", ctxt_pP->rnti, rb_id + 4, @@ -1069,10 +1067,10 @@ pdcp_data_ind( GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rnti = ctxt_pP->rnti; GTPV1U_ENB_TUNNEL_DATA_REQ(message_p).rab_id = rb_id + 4; itti_send_msg_to_task(TASK_GTPV1_U, INSTANCE_DEFAULT, message_p); - packet_forwarded = TRUE; + packet_forwarded = true; } } else { - packet_forwarded = FALSE; + packet_forwarded = false; } #ifdef MBMS_MULTICAST_OUT @@ -1086,13 +1084,13 @@ pdcp_data_ind( // dest_addr.sin_addr.s_addr = ip_header->daddr; // sendto(mbms_socket, &sdu_buffer_pP->data[payload_offset], sdu_buffer_sizeP - payload_offset, MSG_DONTWAIT, (struct sockaddr*)&dest_addr, sizeof(dest_addr)); - // //packet_forwarded = TRUE; + // //packet_forwarded = true; } #endif - if (FALSE == packet_forwarded) { + if (false == packet_forwarded) { notifiedFIFO_elt_t * new_sdu_p = newNotifiedFIFO_elt(sdu_buffer_sizeP - payload_offset + sizeof (pdcp_data_ind_header_t), 0, NULL, NULL); if ((MBMS_flagP == 0) && (pdcp_p->rlc_mode == RLC_MODE_AM)) { @@ -1185,7 +1183,7 @@ pdcp_data_ind( } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT); - return TRUE; + return true; } void pdcp_update_stats(const protocol_ctxt_t *const ctxt_pP) { @@ -1297,7 +1295,7 @@ pdcp_run ( NULL, NULL ); - if (result != TRUE) + if (result != true) LOG_E(PDCP, "PDCP data request failed!\n"); // Message buffer has been processed, free it now. @@ -1420,7 +1418,7 @@ pdcp_mbms_run ( // NULL, NULL // ); // -// if (result != TRUE) +// if (result != true) // LOG_E(PDCP, "PDCP data request failed!\n"); // // // Message buffer has been processed, free it now. @@ -1549,10 +1547,7 @@ void pdcp_add_UE(const protocol_ctxt_t *const ctxt_pP) { } //----------------------------------------------------------------------------- -boolean_t -pdcp_remove_UE( - const protocol_ctxt_t *const ctxt_pP -) +bool pdcp_remove_UE(const protocol_ctxt_t *const ctxt_pP) //----------------------------------------------------------------------------- { LTE_DRB_Identity_t srb_id = 0; @@ -1599,19 +1594,17 @@ pdcp_remove_UE( //----------------------------------------------------------------------------- -boolean_t -rrc_pdcp_config_asn1_req ( - const protocol_ctxt_t *const ctxt_pP, - LTE_SRB_ToAddModList_t *const srb2add_list_pP, - LTE_DRB_ToAddModList_t *const drb2add_list_pP, - LTE_DRB_ToReleaseList_t *const drb2release_list_pP, - const uint8_t security_modeP, - uint8_t *const kRRCenc_pP, - uint8_t *const kRRCint_pP, - uint8_t *const kUPenc_pP, - LTE_PMCH_InfoList_r9_t *const pmch_InfoList_r9_pP, - rb_id_t *const defaultDRB -) +bool +rrc_pdcp_config_asn1_req(const protocol_ctxt_t *const ctxt_pP, + LTE_SRB_ToAddModList_t *const srb2add_list_pP, + LTE_DRB_ToAddModList_t *const drb2add_list_pP, + LTE_DRB_ToReleaseList_t *const drb2release_list_pP, + const uint8_t security_modeP, + uint8_t *const kRRCenc_pP, + uint8_t *const kRRCint_pP, + uint8_t *const kUPenc_pP, + LTE_PMCH_InfoList_r9_t *const pmch_InfoList_r9_pP, + rb_id_t *const defaultDRB) //----------------------------------------------------------------------------- { long int lc_id = 0; @@ -1669,7 +1662,7 @@ rrc_pdcp_config_asn1_req ( PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p), key); free(pdcp_p); - return TRUE; + return true; } else { LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD key 0x%"PRIx64"\n", PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p), @@ -1784,13 +1777,13 @@ rrc_pdcp_config_asn1_req ( PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p), key_defaultDRB); free(pdcp_p); - return TRUE; + return true; } else if (h_rc != HASH_TABLE_OK) { LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD ADD key 0x%"PRIx64" FAILED\n", PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p), key); free(pdcp_p); - return TRUE; + return true; } else { LOG_D(PDCP, PROTOCOL_PDCP_CTXT_FMT" CONFIG_ACTION_ADD ADD key 0x%"PRIx64"\n", PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p), @@ -1944,7 +1937,7 @@ rrc_pdcp_config_asn1_req ( if (ctxt_pP->enb_flag) { drb_id = (mch_id * LTE_maxSessionPerPMCH ) + lc_id ;//+ (LTE_maxDRB + 3)*MAX_MOBILES_PER_ENB; // 1 - if (pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) { + if (pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == true) { action = CONFIG_ACTION_MBMS_MODIFY; } else { action = CONFIG_ACTION_MBMS_ADD; @@ -1952,7 +1945,7 @@ rrc_pdcp_config_asn1_req ( } else { drb_id = (mch_id * LTE_maxSessionPerPMCH ) + lc_id; // + (LTE_maxDRB + 3); // 15 - if (pdcp_mbms_array_ue[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == TRUE) { + if (pdcp_mbms_array_ue[ctxt_pP->module_id][mch_id][lc_id].instanciated_instance == true) { action = CONFIG_ACTION_MBMS_MODIFY; } else { action = CONFIG_ACTION_MBMS_ADD; @@ -1990,23 +1983,22 @@ rrc_pdcp_config_asn1_req ( } //----------------------------------------------------------------------------- -boolean_t -pdcp_config_req_asn1 ( - const protocol_ctxt_t *const ctxt_pP, - pdcp_t *const pdcp_pP, - const srb_flag_t srb_flagP, - const rlc_mode_t rlc_modeP, - const config_action_t actionP, - const uint16_t lc_idP, - const uint16_t mch_idP, - const rb_id_t rb_idP, - const uint8_t rb_snP, - const uint8_t rb_reportP, - const uint16_t header_compression_profileP, - const uint8_t security_modeP, - uint8_t *const kRRCenc_pP, - uint8_t *const kRRCint_pP, - uint8_t *const kUPenc_pP) +bool +pdcp_config_req_asn1(const protocol_ctxt_t *const ctxt_pP, + pdcp_t *const pdcp_pP, + const srb_flag_t srb_flagP, + const rlc_mode_t rlc_modeP, + const config_action_t actionP, + const uint16_t lc_idP, + const uint16_t mch_idP, + const rb_id_t rb_idP, + const uint8_t rb_snP, + const uint8_t rb_reportP, + const uint16_t header_compression_profileP, + const uint8_t security_modeP, + uint8_t *const kRRCenc_pP, + uint8_t *const kRRCint_pP, + uint8_t *const kUPenc_pP) //----------------------------------------------------------------------------- { @@ -2015,7 +2007,7 @@ pdcp_config_req_asn1 ( DevAssert(pdcp_pP != NULL); if (ctxt_pP->enb_flag == ENB_FLAG_YES) { - pdcp_pP->is_ue = FALSE; + pdcp_pP->is_ue = false; pdcp_add_UE(ctxt_pP); //pdcp_eNB_UE_instance_to_rnti[ctxtP->module_id] = ctxt_pP->rnti; @@ -2035,11 +2027,11 @@ pdcp_config_req_asn1 ( //pdcp_eNB_UE_instance_to_rnti_index = (pdcp_eNB_UE_instance_to_rnti_index + 1) % MAX_MOBILES_PER_ENB; } else { - pdcp_pP->is_ue = TRUE; + pdcp_pP->is_ue = true; pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti; } - pdcp_pP->is_srb = (srb_flagP == SRB_FLAG_YES) ? TRUE : FALSE; + pdcp_pP->is_srb = srb_flagP == SRB_FLAG_YES; pdcp_pP->lcid = lc_idP; pdcp_pP->rb_id = rb_idP; pdcp_pP->header_compression_profile = header_compression_profileP; @@ -2162,10 +2154,10 @@ pdcp_config_req_asn1 ( rb_idP); if (ctxt_pP->enb_flag == ENB_FLAG_YES) { - pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_idP][lc_idP].instanciated_instance = TRUE ; + pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_idP][lc_idP].instanciated_instance = true ; pdcp_mbms_array_eNB[ctxt_pP->module_id][mch_idP][lc_idP].rb_id = rb_idP; } else { - pdcp_mbms_array_ue[ctxt_pP->module_id][mch_idP][lc_idP].instanciated_instance = TRUE ; + pdcp_mbms_array_ue[ctxt_pP->module_id][mch_idP][lc_idP].instanciated_instance = true ; pdcp_mbms_array_ue[ctxt_pP->module_id][mch_idP][lc_idP].rb_id = rb_idP; } @@ -2245,10 +2237,10 @@ void rrc_pdcp_config_req ( pdcp_p->rb_id = rb_idP; if (ctxt_pP->enb_flag == ENB_FLAG_NO) { - pdcp_p->is_ue = TRUE; + pdcp_p->is_ue = true; pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti; } else { - pdcp_p->is_ue = FALSE; + pdcp_p->is_ue = false; } pdcp_p->next_pdcp_tx_sn = 0; @@ -2321,10 +2313,10 @@ void rrc_pdcp_config_req ( pdcp_p->rb_id = rb_idP; if (ctxt_pP->enb_flag == ENB_FLAG_NO) { - pdcp_p->is_ue = TRUE; + pdcp_p->is_ue = true; pdcp_UE_UE_module_id_to_rnti[ctxt_pP->module_id] = ctxt_pP->rnti; } else { - pdcp_p->is_ue = FALSE; + pdcp_p->is_ue = false; } pdcp_p->next_pdcp_tx_sn = 0; diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h index 332ee382d7..8cbc49d756 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h @@ -51,7 +51,7 @@ typedef rlc_op_status_t (*send_rlc_data_req_func_t)(const protocol_ctxt_t *cons const rb_id_t, const mui_t, confirm_t, sdu_size_t, mem_block_t *,const uint32_t *const, const uint32_t *const); -typedef boolean_t (pdcp_data_ind_t)( const protocol_ctxt_t *, const srb_flag_t, +typedef bool (pdcp_data_ind_t)( const protocol_ctxt_t *, const srb_flag_t, const MBMS_flag_t, const rb_id_t, const sdu_size_t, mem_block_t *,const uint32_t *const, const uint32_t *const); typedef pdcp_data_ind_t* pdcp_data_ind_func_t; @@ -153,14 +153,13 @@ typedef struct pdcp_stats_s { typedef struct pdcp_s { - //boolean_t instanciated_instance; uint16_t header_compression_profile; /* SR: added this flag to distinguish UE/eNB instance as pdcp_run for virtual * mode can receive data on NETLINK for eNB while eNB_flag = 0 and for UE when eNB_flag = 1 */ - boolean_t is_ue; - boolean_t is_srb; + bool is_ue; + bool is_srb; /* Configured security algorithms */ uint8_t cipheringAlgorithm; @@ -217,7 +216,7 @@ typedef struct pdcp_s { } pdcp_t; typedef struct pdcp_mbms_s { - boolean_t instanciated_instance; + bool instanciated_instance; rb_id_t rb_id; } pdcp_mbms_t; @@ -230,7 +229,7 @@ typedef struct pdcp_mbms_s { * under targets/TEST/PDCP/ */ -/*! \fn boolean_t pdcp_data_req(const protocol_ctxt_t* const , srb_flag_t , rb_id_t , mui_t , confirm_t ,sdu_size_t , unsigned char* , pdcp_transmission_mode_t ) +/*! \fn bool pdcp_data_req(const protocol_ctxt_t* const , srb_flag_t , rb_id_t , mui_t , confirm_t ,sdu_size_t , unsigned char* , pdcp_transmission_mode_t ) * \brief This functions handles data transfer requests coming either from RRC or from IP * \param[in] ctxt_pP Running context. * \param[in] rab_id Radio Bearer ID @@ -239,38 +238,34 @@ typedef struct pdcp_mbms_s { * \param[in] sdu_buffer_size Size of incoming SDU in bytes * \param[in] sdu_buffer Buffer carrying SDU * \param[in] mode flag to indicate whether the userplane data belong to the control plane or data plane or transparent -* \return TRUE on success, FALSE otherwise +* \return true on success, false otherwise * \note None * @ingroup _pdcp */ -boolean_t pdcp_data_req( - protocol_ctxt_t *ctxt_pP, - const srb_flag_t srb_flagP, - const rb_id_t rb_id, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_size, - unsigned char *const sdu_buffer, - const pdcp_transmission_mode_t mode, - const uint32_t * sourceL2Id, - const uint32_t * destinationL2Id -); +bool pdcp_data_req(protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t mode, + const uint32_t * sourceL2Id, + const uint32_t * destinationL2Id); -boolean_t cu_f1u_data_req( - protocol_ctxt_t *ctxt_pP, - const srb_flag_t srb_flagP, - const rb_id_t rb_id, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_size, - unsigned char *const sdu_buffer, - const pdcp_transmission_mode_t mode, - const uint32_t *const sourceL2Id, - const uint32_t *const destinationL2Id - ); +bool cu_f1u_data_req(protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t mode, + const uint32_t *const sourceL2Id, + const uint32_t *const destinationL2Id); -/*! \fn boolean_t pdcp_data_ind(const protocol_ctxt_t* const, srb_flag_t, MBMS_flag_t, rb_id_t, sdu_size_t, mem_block_t*, boolean_t) +/*! \fn bool pdcp_data_ind(const protocol_ctxt_t* const, srb_flag_t, MBMS_flag_t, rb_id_t, sdu_size_t, mem_block_t*, bool) * \brief This functions handles data transfer indications coming from RLC * \param[in] ctxt_pP Running context. * \param[in] Shows if rb is SRB @@ -279,7 +274,7 @@ boolean_t cu_f1u_data_req( * \param[in] sdu_buffer_size Size of incoming SDU in bytes * \param[in] sdu_buffer Buffer carrying SDU * \param[in] is_data_plane flag to indicate whether the userplane data belong to the control plane or data plane -* \return TRUE on success, FALSE otherwise +* \return TRUE on success, false otherwise * \note None * @ingroup _pdcp */ @@ -316,20 +311,18 @@ void rrc_pdcp_config_req ( * \param[in] defaultDRB Default DRB ID * \return A status about the processing, OK or error code. */ -boolean_t rrc_pdcp_config_asn1_req ( - const protocol_ctxt_t *const ctxt_pP, - LTE_SRB_ToAddModList_t *const srb2add_list, - LTE_DRB_ToAddModList_t *const drb2add_list, - LTE_DRB_ToReleaseList_t *const drb2release_list, - const uint8_t security_modeP, - uint8_t *const kRRCenc, - uint8_t *const kRRCint, - uint8_t *const kUPenc, - LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9, - rb_id_t *const defaultDRB -); +bool rrc_pdcp_config_asn1_req(const protocol_ctxt_t *const ctxt_pP, + LTE_SRB_ToAddModList_t *const srb2add_list, + LTE_DRB_ToAddModList_t *const drb2add_list, + LTE_DRB_ToReleaseList_t *const drb2release_list, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc, + LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9, + rb_id_t *const defaultDRB); -/*! \fn boolean_t pdcp_config_req_asn1 (const protocol_ctxt_t* const ctxt_pP, srb_flag_t srb_flagP, uint32_t action, rb_id_t rb_id, uint8_t rb_sn, uint8_t rb_report, uint16_t header_compression_profile, uint8_t security_mode) +/*! \fn bool pdcp_config_req_asn1 (const protocol_ctxt_t* const ctxt_pP, srb_flag_t srb_flagP, uint32_t action, rb_id_t rb_id, uint8_t rb_sn, uint8_t rb_report, uint16_t header_compression_profile, uint8_t security_mode) * \brief Function for RRC to configure a Radio Bearer. * \param[in] ctxt_pP Running context. * \param[in] pdcp_pP Pointer on PDCP structure. @@ -349,22 +342,21 @@ boolean_t rrc_pdcp_config_asn1_req ( * \param[in] kUPenc User-Plane encryption key * \return A status about the processing, OK or error code. */ -boolean_t pdcp_config_req_asn1 ( - const protocol_ctxt_t *const ctxt_pP, - pdcp_t *const pdcp_pP, - const srb_flag_t srb_flagP, - const rlc_mode_t rlc_mode, - const uint32_t action, - const uint16_t lc_id, - const uint16_t mch_id, - const rb_id_t rb_id, - const uint8_t rb_sn, - const uint8_t rb_report, - const uint16_t header_compression_profile, - const uint8_t security_mode, - uint8_t *const kRRCenc, - uint8_t *const kRRCint, - uint8_t *const kUPenc); +bool pdcp_config_req_asn1(const protocol_ctxt_t *const ctxt_pP, + pdcp_t *const pdcp_pP, + const srb_flag_t srb_flagP, + const rlc_mode_t rlc_mode, + const uint32_t action, + const uint16_t lc_id, + const uint16_t mch_id, + const rb_id_t rb_id, + const uint8_t rb_sn, + const uint8_t rb_report, + const uint16_t header_compression_profile, + const uint8_t security_mode, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc); /*! \fn void pdcp_add_UE(const protocol_ctxt_t* const ctxt_pP) * \brief Function (for RRC) to add a new UE in PDCP module @@ -373,13 +365,12 @@ boolean_t pdcp_config_req_asn1 ( */ void pdcp_add_UE(const protocol_ctxt_t *const ctxt_pP); -/*! \fn boolean_t pdcp_remove_UE(const protocol_ctxt_t* const ctxt_pP) +/*! \fn bool pdcp_remove_UE(const protocol_ctxt_t* const ctxt_pP) * \brief Function for RRC to remove UE from PDCP module hashtable * \param[in] ctxt_pP Running context. * \return A status about the processing, OK or error code. */ -boolean_t pdcp_remove_UE( - const protocol_ctxt_t *const ctxt_pP); +bool pdcp_remove_UE(const protocol_ctxt_t *const ctxt_pP); /*! \fn void rrc_pdcp_config_release( const protocol_ctxt_t* const, rb_id_t) * \brief This functions is unused diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_primitives.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_primitives.c index ef674132c4..77d3cf3857 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_primitives.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_primitives.c @@ -32,7 +32,7 @@ #include "pdcp.h" #include "pdcp_primitives.h" -extern boolean_t util_mark_nth_bit_of_octet(uint8_t* octet, uint8_t index); +extern bool util_mark_nth_bit_of_octet(uint8_t* octet, uint8_t index); /* * Parses data/control field out of buffer of User Plane PDCP Data PDU with @@ -123,13 +123,13 @@ uint8_t pdcp_get_sequence_number_of_pdu_with_SRB_sn(unsigned char* pdu_buffer) * Fills the incoming buffer with the fields of the header for srb sn * * @param pdu_buffer PDCP PDU buffer - * @return TRUE on success, FALSE otherwise + * @return true on success, false otherwise */ -boolean_t pdcp_serialize_control_plane_data_pdu_with_SRB_sn_buffer(unsigned char* pdu_buffer, \ - pdcp_control_plane_data_pdu_header* pdu) +bool pdcp_serialize_control_plane_data_pdu_with_SRB_sn_buffer(unsigned char* pdu_buffer, + pdcp_control_plane_data_pdu_header* pdu) { if (pdu_buffer == NULL || pdu == NULL) { - return FALSE; + return false; } /* @@ -138,20 +138,20 @@ boolean_t pdcp_serialize_control_plane_data_pdu_with_SRB_sn_buffer(unsigned char uint8_t sequence_number = pdu->sn; pdu_buffer[0] = sequence_number & 0x1F; // 5bit sn - return TRUE; + return true; } /* * Fills the incoming buffer with the fields of the header for long sn * * @param pdu_buffer PDCP PDU buffer - * @return TRUE on success, FALSE otherwise + * @return true on success, false otherwise */ -boolean_t pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer(unsigned char* pdu_buffer, \ - pdcp_user_plane_data_pdu_header_with_long_sn* pdu) +bool pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer(unsigned char* pdu_buffer, + pdcp_user_plane_data_pdu_header_with_long_sn* pdu) { if (pdu_buffer == NULL || pdu == NULL) { - return FALSE; + return false; } /* @@ -170,7 +170,7 @@ boolean_t pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer(unsigned char* pdu_buffer[0] |= 0x80; // set the first bit as 1 } - return TRUE; + return true; } /* @@ -178,13 +178,14 @@ boolean_t pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer(unsigned char* * * @param pdu_buffer The buffer that PDU will be serialized into * @param pdu A status report header - * @return TRUE on success, FALSE otherwise + * @return true on success, false otherwise */ -boolean_t pdcp_serialize_control_pdu_for_pdcp_status_report(unsigned char* pdu_buffer, \ - uint8_t bitmap[512], pdcp_control_pdu_for_pdcp_status_report* pdu) +bool pdcp_serialize_control_pdu_for_pdcp_status_report(unsigned char* pdu_buffer, + uint8_t bitmap[512], + pdcp_control_pdu_for_pdcp_status_report* pdu) { if (pdu_buffer == NULL || pdu == NULL) { - return FALSE; + return false; } /* @@ -205,6 +206,6 @@ boolean_t pdcp_serialize_control_pdu_for_pdcp_status_report(unsigned char* pdu_b */ memcpy(pdu_buffer + 2, bitmap, 512); - return TRUE; + return true; } diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_primitives.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp_primitives.h index 8b5ebe7287..423f69afc9 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_primitives.h +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_primitives.h @@ -142,18 +142,18 @@ uint8_t pdcp_get_sequence_number_of_pdu_with_SRB_sn(unsigned char* pdu_buffer); * Fills the incoming buffer with the fields of the header for SRB1 * * @param pdu_buffer PDCP PDU buffer - * @return TRUE on success, FALSE otherwise + * @return true on success, false otherwise */ -boolean_t pdcp_serialize_control_plane_data_pdu_with_SRB_sn_buffer(unsigned char* pdu_buffer, \ - pdcp_control_plane_data_pdu_header* pdu); +bool pdcp_serialize_control_plane_data_pdu_with_SRB_sn_buffer(unsigned char* pdu_buffer, + pdcp_control_plane_data_pdu_header* pdu); /* * Fills the incoming buffer with the fields of the header for long SN (RLC UM and AM) * * @param pdu_buffer PDCP PDU buffer - * @return TRUE on success, FALSE otherwise + * @return true on success, false otherwise */ -boolean_t pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer(unsigned char* pdu_buffer, \ - pdcp_user_plane_data_pdu_header_with_long_sn* pdu); +bool pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer(unsigned char* pdu_buffer, + pdcp_user_plane_data_pdu_header_with_long_sn* pdu); /* * Fills the incoming status report header with given value of bitmap @@ -162,10 +162,11 @@ boolean_t pdcp_serialize_user_plane_data_pdu_with_long_sn_buffer(unsigned char* * @param FMS First Missing PDCP SN * @param bitmap Received/Missing sequence number bitmap * @param pdu A status report header - * @return TRUE on success, FALSE otherwise + * @return true on success, false otherwise */ -boolean_t pdcp_serialize_control_pdu_for_pdcp_status_report(unsigned char* pdu_buffer, \ - uint8_t bitmap[512], pdcp_control_pdu_for_pdcp_status_report* pdu); +bool pdcp_serialize_control_pdu_for_pdcp_status_report(unsigned char* pdu_buffer, + uint8_t bitmap[512], + pdcp_control_pdu_for_pdcp_status_report* pdu); int pdcp_netlink_dequeue_element(const protocol_ctxt_t* const ctxt_pP, struct pdcp_netlink_element_s **data_ppP); diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_sequence_manager.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_sequence_manager.c index cdc583ef21..31beb3a9e0 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_sequence_manager.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_sequence_manager.c @@ -33,12 +33,12 @@ /* * Initializes sequence numbering state * @param pdcp_entity The PDCP entity to be initialized - * @return boolean_t TRUE on success, FALSE otherwise + * @return bool true on success, false otherwise */ -boolean_t pdcp_init_seq_numbers(pdcp_t* pdcp_entity) +bool pdcp_init_seq_numbers(pdcp_t* pdcp_entity) { if (pdcp_entity == NULL) { - return FALSE; + return false; } /* Sequence number state variables */ @@ -55,34 +55,34 @@ boolean_t pdcp_init_seq_numbers(pdcp_t* pdcp_entity) // Shall UE and eNB behave differently on initialization? (see 7.1.e) pdcp_entity->last_submitted_pdcp_rx_sn = 4095; - return TRUE; + return true; } -boolean_t pdcp_is_seq_num_size_valid(pdcp_t* pdcp_entity) +bool pdcp_is_seq_num_size_valid(pdcp_t* pdcp_entity) { if (pdcp_entity == NULL) { - return FALSE; + return false; } // Check if the size of SN is valid (see 3GPP TS 36.323 v10.1.0 item 6.3.2) if (pdcp_entity->seq_num_size != 5 && pdcp_entity->seq_num_size != 7 && pdcp_entity->seq_num_size != 12) { LOG_W(PDCP, "Incoming SN size is invalid! (Expected: {5 | 7 | 12}, Received: %d\n", pdcp_entity->seq_num_size); - return FALSE; + return false; } - return TRUE; + return true; } /** * Check if SN number is in the range according to SN size */ -boolean_t pdcp_is_seq_num_valid(uint16_t seq_num, uint8_t seq_num_size) +bool pdcp_is_seq_num_valid(uint16_t seq_num, uint8_t seq_num_size) { if (seq_num >= 0 && seq_num <= pdcp_calculate_max_seq_num_for_given_size(seq_num_size)) { - return TRUE; + return true; } - return FALSE; + return false; } uint16_t pdcp_calculate_max_seq_num_for_given_size(uint8_t seq_num_size) @@ -96,7 +96,7 @@ uint16_t pdcp_calculate_max_seq_num_for_given_size(uint8_t seq_num_size) uint16_t pdcp_get_next_tx_seq_number(pdcp_t* pdcp_entity) { - if (pdcp_is_seq_num_size_valid(pdcp_entity) == FALSE) { + if (pdcp_is_seq_num_size_valid(pdcp_entity) == false) { return -1; } @@ -118,10 +118,10 @@ uint16_t pdcp_get_next_tx_seq_number(pdcp_t* pdcp_entity) return pdcp_seq_num; } -boolean_t pdcp_advance_rx_window(pdcp_t* pdcp_entity) +bool pdcp_advance_rx_window(pdcp_t* pdcp_entity) { - if (pdcp_is_seq_num_size_valid(pdcp_entity) == FALSE) { - return FALSE; + if (pdcp_is_seq_num_size_valid(pdcp_entity) == false) { + return false; } /* @@ -137,10 +137,10 @@ boolean_t pdcp_advance_rx_window(pdcp_t* pdcp_entity) pdcp_entity->next_pdcp_rx_sn++; } - return TRUE; + return true; } -boolean_t pdcp_mark_current_pdu_as_received(uint16_t seq_num, pdcp_t* pdcp_entity) +bool pdcp_mark_current_pdu_as_received(uint16_t seq_num, pdcp_t* pdcp_entity) { /* * Incoming sequence number and PDCP entity were already @@ -158,5 +158,5 @@ boolean_t pdcp_mark_current_pdu_as_received(uint16_t seq_num, pdcp_t* pdcp_entit LOG_D(PDCP, "Marking %d. bit of %d. octet of status bitmap\n", (seq_num % 8) + 1, octet_index); util_mark_nth_bit_of_octet(&pdcp_entity->missing_pdu_bitmap[octet_index], seq_num % 8); util_print_binary_representation((uint8_t*)"Current state of relevant octet: ", pdcp_entity->missing_pdu_bitmap[octet_index]); - return TRUE; + return true; } diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_sequence_manager.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp_sequence_manager.h index 172c9810e6..bff98d1b00 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_sequence_manager.h +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_sequence_manager.h @@ -35,17 +35,17 @@ * @param pdcp_entity The PDCP entity to be initialized * @return none */ -boolean_t pdcp_init_seq_numbers(pdcp_t* pdcp_entity); +bool pdcp_init_seq_numbers(pdcp_t* pdcp_entity); /** * Checks if incoming PDCP entitiy pointer and relevant sequence number size is valid - * @return TRUE (0x01) if it is valid, FALSE (0x00) otherwise + * @return true (0x01) if it is valid, false (0x00) otherwise */ -boolean_t pdcp_is_seq_num_size_valid(pdcp_t* pdcp_entity); +bool pdcp_is_seq_num_size_valid(pdcp_t* pdcp_entity); /** * Check if SN number is in the range according to SN size - * @return TRUE if it is valid, FALSE otherwise + * @return true if it is valid, false otherwise */ -boolean_t pdcp_is_seq_num_valid(uint16_t seq_num, uint8_t seq_num_size); +bool pdcp_is_seq_num_valid(uint16_t seq_num, uint8_t seq_num_size); /** * Returns the maximum allowed sequence number value for given size of SN field * @return Max sequence number value @@ -58,11 +58,11 @@ uint16_t pdcp_get_next_tx_seq_number(pdcp_t* pdcp_entity); /** * Advances the RX window state of given PDCP entity upon successfull receipt of a SDU */ -boolean_t pdcp_advance_rx_window(pdcp_t* pdcp_entity); +bool pdcp_advance_rx_window(pdcp_t* pdcp_entity); /** * Updates missing PDU bitmap with incoming sequence number -* @return TRUE if successful, FALSE otherwise +* @return true if successful, false otherwise */ -boolean_t pdcp_mark_current_pdu_as_received(uint16_t seq_num, pdcp_t* pdcp_entity); +bool pdcp_mark_current_pdu_as_received(uint16_t seq_num, pdcp_t* pdcp_entity); #endif diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_util.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_util.c index cf8218829f..79f6d68820 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_util.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_util.c @@ -130,9 +130,9 @@ void util_print_binary_representation(unsigned char* message, uint8_t octet) * * @param octet 8-bit data * @param index Index of bit to be set - * @return TRUE on success, FALSE otherwise + * @return true on success, false otherwise */ -boolean_t util_mark_nth_bit_of_octet(uint8_t* octet, uint8_t index) +bool util_mark_nth_bit_of_octet(uint8_t* octet, uint8_t index) { uint8_t mask = 0x80; @@ -148,6 +148,6 @@ boolean_t util_mark_nth_bit_of_octet(uint8_t* octet, uint8_t index) */ *octet |= mask; - return TRUE; + return true; } diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_util.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp_util.h index 49846c7a9f..89b8ff672f 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_util.h +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_util.h @@ -66,8 +66,8 @@ void util_print_binary_representation(unsigned char* message, uint8_t octet); * * @param octet Octet * @param index Index - * @return TRUE on success, FALSE otherwise + * @return true on success, false otherwise */ -boolean_t util_mark_nth_bit_of_octet(uint8_t* octet, uint8_t index); +bool util_mark_nth_bit_of_octet(uint8_t* octet, uint8_t index); #endif // PDCP_UTIL_H diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c index 4eb0907046..ddc7bf85e8 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am.c @@ -52,7 +52,7 @@ rlc_am_get_status_pdu_buffer_occupancy( rlc_sn_t sn_cursor = rlc_pP->vr_r; rlc_sn_t sn_prev = rlc_pP->vr_r; rlc_sn_t sn_end = rlc_pP->vr_ms; - boolean_t segment_loop_end = false; + bool segment_loop_end = false; if (sn_prev != sn_end) { while ((RLC_AM_DIFF_SN(sn_prev,rlc_pP->vr_r) < RLC_AM_DIFF_SN(sn_end,rlc_pP->vr_r)) && (cursor_p != NULL)) { diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_entity.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_entity.h index 1b6d837565..95c47943a4 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_entity.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_entity.h @@ -54,7 +54,7 @@ typedef struct rlc_am_entity_s { rb_id_t rb_id; /*!< \brief Radio bearer identifier, for statistics and trace purpose. */ logical_chan_id_t channel_id; /*!< \brief Transport channel identifier. */ - boolean_t is_data_plane; /*!< \brief To know if the RLC belongs to a data radio bearer or a signalling radio bearer, for statistics and trace purpose. */ + bool is_data_plane; /*!< \brief To know if the RLC belongs to a data radio bearer or a signalling radio bearer, for statistics and trace purpose. */ rlc_buffer_occupancy_t sdu_buffer_occupancy; /*!< \brief Number of bytes of unsegmented SDUs. */ rlc_buffer_occupancy_t status_buffer_occupancy; /*!< \brief Number of bytes of control PDUs waiting for transmission. */ @@ -76,7 +76,7 @@ typedef struct rlc_am_entity_s { rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer; /*!< \brief Transmission PDU data buffer. Used also for retransmissions */ signed int retrans_num_pdus; /*!< \brief Number of PDUs in the retransmission buffer. */ signed int retrans_num_bytes_to_retransmit; /*!< \brief Number of bytes in the retransmission buffer to be retransmitted. Only payload is taken into account */ - boolean_t force_poll; /*!< \brief force poll due to t_poll_retransmit time-out. */ + bool force_poll; /*!< \brief force poll due to t_poll_retransmit time-out. */ //--------------------------------------------------------------------- // RX BUFFERS @@ -186,8 +186,8 @@ typedef struct rlc_am_entity_s { // note occupancy of other buffers is deducted from nb elements in lists rlc_buffer_occupancy_t buffer_occupancy_retransmission_buffer; /*!< \brief Number of PDUs. */ - boolean_t initialized; /*!< \brief Boolean for rlc_am_entity_t struct initialization. */ - boolean_t configured; /*!< \brief Boolean for rlc_am_entity_t struct configuration. */ + bool initialized; /*!< \brief Boolean for rlc_am_entity_t struct initialization. */ + bool configured; /*!< \brief Boolean for rlc_am_entity_t struct configuration. */ } rlc_am_entity_t; /** @} */ # endif diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c index cb09f24855..8ff29fa44b 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.c @@ -32,7 +32,7 @@ rlc_am_init( const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlc_pP) { - if (rlc_pP->initialized == TRUE) { + if (rlc_pP->initialized == true) { LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[AM INIT] INITIALIZATION ALREADY DONE, DOING NOTHING\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); } else { @@ -79,7 +79,7 @@ rlc_am_init( rlc_pP->last_absolute_subframe_status_indication = 0xFFFFFFFF; // any value > 1 - rlc_pP->initialized = TRUE; + rlc_pP->initialized = true; } } //----------------------------------------------------------------------------- @@ -134,7 +134,7 @@ rlc_am_reestablish( rlc_pP->last_absolute_subframe_status_indication = 0xFFFFFFFF; // any value > 1 - rlc_pP->initialized = TRUE; + rlc_pP->initialized = true; } @@ -197,7 +197,7 @@ rlc_am_configure( const uint32_t t_reorderingP, const uint32_t t_status_prohibitP) { - if (rlc_pP->configured == TRUE) { + if (rlc_pP->configured == true) { LOG_I(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RECONFIGURE] max_retx_threshold %d poll_pdu %d poll_byte %d t_poll_retransmit %d t_reordering %d t_status_prohibit %d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), max_retx_thresholdP, @@ -235,7 +235,7 @@ rlc_am_configure( rlc_am_init_timer_reordering (ctxt_pP, rlc_pP, t_reorderingP); rlc_am_init_timer_status_prohibit(ctxt_pP, rlc_pP, t_status_prohibitP); - rlc_pP->configured = TRUE; + rlc_pP->configured = true; } } diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.c index 0957c20bdf..a5f0b4f9ef 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.c @@ -183,12 +183,10 @@ rlc_am_send_sdu ( } } //----------------------------------------------------------------------------- -void -rlc_am_reassemble_pdu( - const protocol_ctxt_t *const ctxt_pP, - rlc_am_entity_t *const rlc_pP, - mem_block_t *const tb_pP, - boolean_t free_rlc_pdu) { +void rlc_am_reassemble_pdu(const protocol_ctxt_t *const ctxt_pP, + rlc_am_entity_t *const rlc_pP, + mem_block_t *const tb_pP, + bool free_rlc_pdu) { int i,j; rlc_am_pdu_info_t *pdu_info = &((rlc_am_rx_pdu_management_t *)(tb_pP->data))->pdu_info; LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[REASSEMBLY PDU] TRY REASSEMBLY PDU SN=%03d\n", diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.h index bf9bd58fb5..839e7d9304 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_reassembly.h @@ -57,14 +57,14 @@ void rlc_am_reassembly (const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * */ void rlc_am_send_sdu (const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP); -/*! \fn void rlc_am_reassemble_pdu(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, const mem_block_t* const tb_pP,boolean_t free_rlc_pdu) +/*! \fn void rlc_am_reassemble_pdu(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, const mem_block_t* const tb_pP, bool free_rlc_pdu) * \brief Reassembly a RLC AM PDU, depending of the content of this PDU, data will be reassemblied to the current output SDU, the current will be sent to higher layers or not, after or before the reassembly, or no send of SDU will be triggered, depending on FI field in PDU header. * \param[in] ctxtP Running context. * \param[in] rlc_pP RLC AM protocol instance pointer. * \param[in] tb_pP RLC AM PDU embedded in a mem_block_t. * \param[in] free_rlc_pdu Flag for freeing RLC AM PDU after reassembly. */ -void rlc_am_reassemble_pdu(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, mem_block_t* const tb_pP,boolean_t free_rlc_pdu); +void rlc_am_reassemble_pdu(const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP, mem_block_t* const tb_pP, bool free_rlc_pdu); /** @} */ #endif diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c index 916d1513b0..a749aa035e 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_receiver.c @@ -328,7 +328,7 @@ rlc_am_receive_process_data_pdu ( rlc_am_pdu_info_t* pdu_info_p = &((rlc_am_rx_pdu_management_t*)(tb_pP->data))->pdu_info; rlc_am_pdu_sn_10_t* rlc_am_pdu_sn_10_p = (rlc_am_pdu_sn_10_t*)first_byte_pP; rlc_am_rx_pdu_status_t pdu_status = RLC_AM_DATA_PDU_STATUS_OK; - boolean_t reassemble = false; + bool reassemble = false; if (rlc_am_get_data_pdu_infos(ctxt_pP,rlc_pP, rlc_am_pdu_sn_10_p, tb_size_in_bytesP, pdu_info_p) >= 0) { diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.c index 56b37e1e39..7129307739 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.c @@ -29,13 +29,12 @@ #include "LAYER2/MAC/mac_extern.h" #include "common/utils/LOG/log.h" //----------------------------------------------------------------------------- -boolean_t rlc_am_nack_pdu ( - const protocol_ctxt_t* const ctxt_pP, - rlc_am_entity_t *const rlc_pP, - const rlc_sn_t snP, - const rlc_sn_t prev_nack_snP, - sdu_size_t so_startP, - sdu_size_t so_endP) +bool rlc_am_nack_pdu(const protocol_ctxt_t* const ctxt_pP, + rlc_am_entity_t *const rlc_pP, + const rlc_sn_t snP, + const rlc_sn_t prev_nack_snP, + sdu_size_t so_startP, + sdu_size_t so_endP) { // 5.2.1 Retransmission // ... @@ -54,8 +53,8 @@ boolean_t rlc_am_nack_pdu ( rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer_p = &rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE]; //int pdu_sdu_index; //int sdu_index; - boolean_t status = TRUE; - boolean_t retx_count_increment = FALSE; + bool status = true; + bool retx_count_increment = false; sdu_size_t pdu_data_to_retx = 0; if (mb_p != NULL) { @@ -63,7 +62,7 @@ boolean_t rlc_am_nack_pdu ( if(so_startP > so_endP) { LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[NACK-PDU] ERROR NACK MISSING PDU, so_startP %d, so_endP %d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),so_startP, so_endP); - status = FALSE; + status = false; } // Handle full PDU NACK first else if ((so_startP == 0) && (so_endP == 0x7FFF)) { @@ -71,9 +70,7 @@ boolean_t rlc_am_nack_pdu ( pdu_data_to_retx = tx_data_pdu_buffer_p->payload_size; /* Increment VtReTxNext if this is the first NACK or if some segments have already been transmitted */ if ((tx_data_pdu_buffer_p->flags.retransmit == 0) || (tx_data_pdu_buffer_p->nack_so_start)) - { - retx_count_increment = TRUE; - } + retx_count_increment = true; tx_data_pdu_buffer_p->nack_so_start = 0; tx_data_pdu_buffer_p->num_holes = 0; @@ -89,11 +86,11 @@ boolean_t rlc_am_nack_pdu ( if(tx_data_pdu_buffer_p->nack_so_start >= tx_data_pdu_buffer_p->payload_size){ LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[NACK-PDU] ERROR NACK MISSING PDU, nack_so_start %d, payload_size %d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),tx_data_pdu_buffer_p->nack_so_start, tx_data_pdu_buffer_p->payload_size); - status = FALSE; + status = false; } } else { - status = FALSE; + status = false; } } else if (tx_data_pdu_buffer_p->flags.max_retransmit == 0) { @@ -107,9 +104,8 @@ boolean_t rlc_am_nack_pdu ( if (prev_nack_snP != snP) { /* New NACK_SN with SO */ /* check whether a new segment is to be placed in Retransmission Buffer, then increment vrReTx */ - if ((tx_data_pdu_buffer_p->flags.retransmit == 0) || (so_startP < tx_data_pdu_buffer_p->nack_so_start)) { - retx_count_increment = TRUE; - } + if ((tx_data_pdu_buffer_p->flags.retransmit == 0) || (so_startP < tx_data_pdu_buffer_p->nack_so_start)) + retx_count_increment = true; tx_data_pdu_buffer_p->num_holes = 1; tx_data_pdu_buffer_p->retx_hole_index = 0; @@ -129,21 +125,18 @@ boolean_t rlc_am_nack_pdu ( tx_data_pdu_buffer_p->nack_so_stop = so_endP; tx_data_pdu_buffer_p->num_holes ++; pdu_data_to_retx = so_endP - so_startP + 1; + } else { + status = false; } - else { - status = FALSE; - } - } - else { - status = FALSE; + } else { + status = false; } } else { - status = FALSE; + status = false; } - } - else { - status = FALSE; + } else { + status = false; } if (status) { @@ -175,17 +168,16 @@ boolean_t rlc_am_nack_pdu ( LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[NACK-PDU] ERROR NACK MISSING PDU SN %05d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), snP); - status = FALSE; + status = false; } return status; } //----------------------------------------------------------------------------- -void rlc_am_ack_pdu ( - const protocol_ctxt_t* const ctxt_pP, - rlc_am_entity_t *const rlc_pP, - const rlc_sn_t snP, - boolean_t free_pdu) +void rlc_am_ack_pdu(const protocol_ctxt_t* const ctxt_pP, + rlc_am_entity_t *const rlc_pP, + const rlc_sn_t snP, + bool free_pdu) { mem_block_t* mb_p = rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE].mem_block; rlc_am_tx_data_pdu_management_t *tx_data_pdu_buffer = &rlc_pP->tx_data_pdu_buffer[snP % RLC_AM_WINDOW_SIZE]; @@ -283,7 +275,7 @@ mem_block_t* rlc_am_retransmit_get_am_segment( sdu_size_t retx_so_start,retx_so_stop; //starting and ending SO for retransmission in this PDU rlc_sn_t sn = pdu_mngt->sn; uint16_t header_so_part; - boolean_t fi_start, fi_end; + bool fi_start, fi_end; uint8_t sdu_index = 0; uint8_t sdu_segment_index = 0; uint8_t num_LIs_pdu_segment = pdu_mngt->nb_sdus - 1; @@ -377,11 +369,11 @@ mem_block_t* rlc_am_retransmit_get_am_segment( /* Set FI part to false if SO Start and SO End are different from PDU boundaries */ if (retx_so_start) { - fi_start = FALSE; + fi_start = false; } if (retx_so_stop < pdu_mngt->payload_size - 1) { - fi_end = FALSE; + fi_end = false; } /* Header content is filled at the end */ @@ -423,7 +415,7 @@ mem_block_t* rlc_am_retransmit_get_am_segment( else { /* if retx_so_start is still not included then set data_size with full original PDU data size */ - /* Set fi_start to FALSE in this case */ + /* Set fi_start to false in this case */ data_size = pdu_mngt->payload_size; } sdu_index ++; @@ -432,7 +424,7 @@ mem_block_t* rlc_am_retransmit_get_am_segment( if (retx_so_start == data_size) { /* Set FI Start if retx_so_start = cumulated data size */ - fi_start = TRUE; + fi_start = true; /* there must be at least one SDU more */ //Assertion(eNB)_PRAN_DesignDocument_annex No.778 if(sdu_index >= pdu_mngt->nb_sdus) @@ -464,8 +456,8 @@ mem_block_t* rlc_am_retransmit_get_am_segment( } else if (retx_so_start != 0) { - /* in all other cases set fi_start to FALSE if it SO Start is not 0 */ - fi_start = FALSE; + /* in all other cases set fi_start to false if it SO Start is not 0 */ + fi_start = false; } /* Set first SDU portion of the segment */ @@ -582,10 +574,10 @@ mem_block_t* rlc_am_retransmit_get_am_segment( "RLC AM Tx PDU Segment Data Error: retx_so_stop=%d OriginalPDUDataLength=%d SOStart=%d SegmentLength=%d numLISegment=%d numLIPDU=%d sn=%d LcId=%d !\n", retx_so_stop,pdu_mngt->payload_size,retx_so_start,*payload_sizeP,num_LIs_pdu_segment,pdu_mngt->nb_sdus - 1,sn,rlc_pP->channel_id); */ - /* init FI End to FALSE if retx_so_stop is not end of PDU */ + /* init FI End to false if retx_so_stop is not end of PDU */ if (retx_so_stop != pdu_mngt->payload_size - 1) { - fi_end = FALSE; + fi_end = false; } /* Check consistency between sdus_segment_size and payload_sizeP */ @@ -596,7 +588,7 @@ mem_block_t* rlc_am_retransmit_get_am_segment( data_size += sdus_segment_size[i]; if ((retx_so_stop == data_size - 1) && (i < num_LIs_pdu_segment)) { - fi_end = TRUE; + fi_end = true; } } //Assertion(eNB)_PRAN_DesignDocument_annex No.782 @@ -665,7 +657,7 @@ mem_block_t* rlc_am_retransmit_get_am_segment( pdu_mngt->nack_so_start = pdu_mngt->hole_so_start[pdu_mngt->retx_hole_index]; } - /* Content is supposed to be init with 0 so with FIStart=FIEnd=TRUE */ + /* Content is supposed to be init with 0 so with FIStart=FIEnd=true */ RLC_AM_PDU_SET_D_C(*pdu_segment_header_p); RLC_AM_PDU_SET_RF(*pdu_segment_header_p); /* Change FI */ diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.h index fc52689314..c34d06337d 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_retransmit.h @@ -35,7 +35,7 @@ # ifndef __RLC_AM_RETRANSMIT_H__ # define __RLC_AM_RETRANSMIT_H__ //----------------------------------------------------------------------------- -/*! \fn boolean_t rlc_am_nack_pdu (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP, int16_t snP, int16_t prev_nack_snP,sdu_size_t so_startP, sdu_size_t so_endP) +/*! \fn bool rlc_am_nack_pdu (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP, int16_t snP, int16_t prev_nack_snP,sdu_size_t so_startP, sdu_size_t so_endP) * \brief The RLC AM PDU which have the sequence number snP is marked NACKed with segment offset fields. * \param[in] ctxtP Running context. * \param[in] rlcP RLC AM protocol instance pointer. @@ -46,13 +46,12 @@ * \return OK/KO * \note It may appear a new hole in the retransmission buffer depending on the segment offset informations. Depending on the state of the retransmission buffer, negative confirmation can be sent to higher layers about the drop by the RLC AM instance of a particular SDU. */ -boolean_t rlc_am_nack_pdu ( - const protocol_ctxt_t* const ctxt_pP, - rlc_am_entity_t *const rlcP, - const rlc_sn_t snP, - const rlc_sn_t prev_nack_snP, - sdu_size_t so_startP, - sdu_size_t so_endP); +bool rlc_am_nack_pdu(const protocol_ctxt_t* const ctxt_pP, + rlc_am_entity_t *const rlcP, + const rlc_sn_t snP, + const rlc_sn_t prev_nack_snP, + sdu_size_t so_startP, + sdu_size_t so_endP); /*! \fn void rlc_am_ack_pdu (const protocol_ctxt_t* const ctxt_pP,rlc_am_entity_t *rlcP, rlc_sn_t snP) * \brief The RLC AM PDU which have the sequence number snP is marked ACKed. @@ -62,11 +61,10 @@ boolean_t rlc_am_nack_pdu ( * \param[in] free_pdu Boolean indicating that the PDU can be freed because smaller than new vtA. * \note Depending on the state of the retransmission buffer, positive confirmation can be sent to higher layers about the receiving by the peer RLC AM instance of a particular SDU. */ -void rlc_am_ack_pdu ( - const protocol_ctxt_t* const ctxt_pP, - rlc_am_entity_t *const rlcP, - const rlc_sn_t snP, - boolean_t free_pdu); +void rlc_am_ack_pdu(const protocol_ctxt_t* const ctxt_pP, + rlc_am_entity_t *const rlcP, + const rlc_sn_t snP, + bool free_pdu); /*! \fn mem_block_t* rlc_am_retransmit_get_copy (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *rlcP, rlc_sn_t snP) * \brief The RLC AM PDU which have the sequence number snP is marked ACKed. diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c index 4a06553901..bd578abab2 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.c @@ -31,14 +31,13 @@ #include "common/utils/LOG/log.h" -boolean_t rlc_am_rx_check_vr_reassemble( - const protocol_ctxt_t* const ctxt_pP, - const rlc_am_entity_t* const rlc_pP) +bool rlc_am_rx_check_vr_reassemble(const protocol_ctxt_t* const ctxt_pP, + const rlc_am_entity_t* const rlc_pP) { mem_block_t* cursor_p = rlc_pP->receiver_buffer.head; rlc_am_rx_pdu_management_t * pdu_cursor_mgnt_p = NULL; sdu_size_t next_waited_so = 0; - boolean_t reassemble = FALSE; + bool reassemble = false; if (cursor_p != NULL) { @@ -48,7 +47,7 @@ boolean_t rlc_am_rx_check_vr_reassemble( if (sn_ref != rlc_pP->vr_r) { /* Case vrR has advanced from head : most likely case */ - reassemble = TRUE; + reassemble = true; /* Handle first SN if it is made of PDU segments : set them all to be reassembled */ if (pdu_info_p->rf) { pdu_cursor_mgnt_p = (rlc_am_rx_pdu_management_t *) (cursor_p->data); @@ -58,7 +57,7 @@ boolean_t rlc_am_rx_check_vr_reassemble( { LOG_E(RLC, "AM Rx Check Reassembly head SN=%d with PDU segments != vrR=%d should be fully received LCID=%d\n", sn_ref,rlc_pP->vr_r,rlc_pP->channel_id); - return FALSE; + return false; } /* AssertFatal(pdu_cursor_mgnt_p->all_segments_received > 0,"AM Rx Check Reassembly head SN=%d with PDU segments != vrR=%d should be fully received LCID=%d\n", @@ -94,7 +93,7 @@ boolean_t rlc_am_rx_check_vr_reassemble( { LOG_E(RLC, "AM Rx Check Reassembly vr=%d should be partly received SNHead=%d LCID=%d\n", rlc_pP->vr_r,sn_ref,rlc_pP->channel_id); - return FALSE; + return false; } /* AssertFatal(pdu_cursor_mgnt_p->all_segments_received == 0,"AM Rx Check Reassembly vr=%d should be partly received SNHead=%d LCID=%d\n", @@ -123,7 +122,7 @@ boolean_t rlc_am_rx_check_vr_reassemble( { LOG_E(RLC, "AM Rx Check Reassembly SNHead=vr=%d should be partly received LCID=%d\n", rlc_pP->vr_r,rlc_pP->channel_id); - return FALSE; + return false; } /* AssertFatal(pdu_cursor_mgnt_p->all_segments_received == 0,"AM Rx Check Reassembly SNHead=vr=%d should be partly received LCID=%d\n", @@ -132,7 +131,7 @@ boolean_t rlc_am_rx_check_vr_reassemble( while ((cursor_p != NULL) && (pdu_info_p->sn == rlc_pP->vr_r) && (pdu_info_p->so == next_waited_so)) { if (pdu_cursor_mgnt_p->segment_reassembled == RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_NO) { pdu_cursor_mgnt_p->segment_reassembled = RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_PENDING; - reassemble = TRUE; + reassemble = true; } next_waited_so += pdu_info_p->payload_size; cursor_p = cursor_p->next; @@ -157,7 +156,7 @@ mem_block_t * create_new_segment_from_pdu( int16_t new_li_list[RLC_AM_MAX_SDU_IN_PDU]; int16_t header_size = 0; uint8_t num_li = 0; - boolean_t fi_start, fi_end, lsf; + bool fi_start, fi_end, lsf; /* Init some PDU Segment header fixed parameters */ fi_start = !((pdu_rx_info_p->fi & 0x2) >> 1); @@ -170,11 +169,11 @@ mem_block_t * create_new_segment_from_pdu( header_size = RLC_AM_PDU_SEGMENT_HEADER_MIN_SIZE; if (so_offset) { - fi_start = FALSE; + fi_start = false; } if (so_offset + data_length_to_copy != pdu_rx_info_p->payload_size) { - fi_end = FALSE; - lsf = FALSE; + fi_end = false; + lsf = false; } } // end no LI in original segment else { @@ -185,7 +184,7 @@ mem_block_t * create_new_segment_from_pdu( /* set LSF to false if we know that end of the original segment will not be copied */ if (so_offset + data_length_to_copy != pdu_rx_info_p->payload_size) { - lsf = FALSE; + lsf = false; } /* catch the first LI containing so_offset */ @@ -223,7 +222,7 @@ mem_block_t * create_new_segment_from_pdu( num_li = j; /* set FI End if remaining size = 0 */ if (remaining_size == 0) { - fi_end = TRUE; + fi_end = true; } } } @@ -263,7 +262,7 @@ mem_block_t * create_new_segment_from_pdu( } /* Fill Header part in the buffer */ - /* Content is supposed to be init with 0 so with FIStart=FIEnd=TRUE */ + /* Content is supposed to be init with 0 so with FIStart=FIEnd=true */ /* copy first two bytes from original: D/C + RF + FI + E+ SN*/ memset(pdu_segment_header_p, 0, header_size); RLC_AM_PDU_SET_D_C(*pdu_segment_header_p); @@ -1106,7 +1105,7 @@ rlc_am_rx_list_reassemble_rlc_sdus( do { if (rlc_am_rx_pdu_management_p->all_segments_received > 0) { cursor_p = list2_remove_head(&rlc_pP->receiver_buffer); - rlc_am_reassemble_pdu(ctxt_pP, rlc_pP, cursor_p,TRUE); + rlc_am_reassemble_pdu(ctxt_pP, rlc_pP, cursor_p, true); rlc_am_rx_old_pdu_management = rlc_am_rx_pdu_management_p; cursor_p = list2_get_head(&rlc_pP->receiver_buffer); @@ -1123,7 +1122,7 @@ rlc_am_rx_list_reassemble_rlc_sdus( else if (rlc_am_rx_pdu_management_p->segment_reassembled == RLC_AM_RX_PDU_SEGMENT_REASSEMBLE_PENDING) { rlc_am_rx_pdu_management_p->segment_reassembled = RLC_AM_RX_PDU_SEGMENT_REASSEMBLED; - rlc_am_reassemble_pdu(ctxt_pP, rlc_pP, cursor_p,FALSE); + rlc_am_reassemble_pdu(ctxt_pP, rlc_pP, cursor_p, false); rlc_am_rx_old_pdu_management = rlc_am_rx_pdu_management_p; cursor_p = cursor_p->next; diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.h index fd8704964d..18e423312c 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_rx_list.h @@ -61,13 +61,13 @@ rlc_am_rx_pdu_status_t rlc_am_rx_list_check_duplicate_insert_pdu(const protocol_ */ signed int rlc_am_rx_list_insert_pdu(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlcP, mem_block_t* const tbP); -/*! \fn boolean_t rlc_am_rx_check_vr_reassemble(const protocol_ctxt_t* const ctxt_pP,const rlc_am_entity_t* const rlc_pP) +/*! \fn bool rlc_am_rx_check_vr_reassemble(const protocol_ctxt_t* const ctxt_pP,const rlc_am_entity_t* const rlc_pP) * \brief Check if reassembly taking into account potential new vrR value * \param[in] ctxt_pP Running context. * \param[in] rlcP RLC AM protocol instance pointer. -* \return TRUE if reassembly must be done, FALSE else +* \return true if reassembly must be done, false else */ -boolean_t rlc_am_rx_check_vr_reassemble(const protocol_ctxt_t* const ctxt_pP,const rlc_am_entity_t* const rlc_pP); +bool rlc_am_rx_check_vr_reassemble(const protocol_ctxt_t* const ctxt_pP,const rlc_am_entity_t* const rlc_pP); /*! \fn void rlc_am_rx_check_all_byte_segments(const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t* const rlcP, mem_block_t* const tbP) * \brief Check if all sub-segments of a PDU are received, if yes then call rlc_am_rx_mark_all_segments_received() procedure. diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.c index ed81e119ac..9e7c3338f8 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.c @@ -32,12 +32,11 @@ #include "common/utils/LOG/log.h" //----------------------------------------------------------------------------- -void rlc_am_pdu_polling ( - const protocol_ctxt_t* const ctxt_pP, - rlc_am_entity_t *const rlc_pP, - rlc_am_pdu_sn_10_t *const pdu_pP, - const int16_t payload_sizeP, - boolean_t is_new_pdu) +void rlc_am_pdu_polling(const protocol_ctxt_t* const ctxt_pP, + rlc_am_entity_t *const rlc_pP, + rlc_am_pdu_sn_10_t *const pdu_pP, + const int16_t payload_sizeP, + bool is_new_pdu) { // 5.2.2 Polling // An AM RLC entity can poll its peer AM RLC entity in order to trigger STATUS reporting at the peer AM RLC entity. diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.h index dc754d08e4..1e472302c8 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.h +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_segment.h @@ -36,14 +36,14 @@ # define __RLC_AM_SEGMENT_H__ //----------------------------------------------------------------------------- -/*! \fn void rlc_am_pdu_polling (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlcP, rlc_am_pdu_sn_10_t *pduP, int16_t payload_sizeP,boolean_t is_new_pdu) +/*! \fn void rlc_am_pdu_polling (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlcP, rlc_am_pdu_sn_10_t *pduP, int16_t payload_sizeP, bool is_new_pdu) * \brief Set or not the poll bit in the PDU header depending on RLC AM protocol variables. * \param[in] ctxt_pP Running context. * \param[in] rlcP RLC AM protocol instance pointer. * \param[in] pduP Pointer on the header of the PDU in order to be able to set the poll bit if necessary. * \param[in] payload_sizeP Size of the payload of the PDU. */ -void rlc_am_pdu_polling (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlcP, rlc_am_pdu_sn_10_t *pduP, int16_t payload_sizeP,boolean_t is_new_pdu); +void rlc_am_pdu_polling (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t *const rlcP, rlc_am_pdu_sn_10_t *pduP, int16_t payload_sizeP, bool is_new_pdu); /*! \fn void rlc_am_segment_10 (const protocol_ctxt_t* const ctxt_pP, rlc_am_entity_t * const rlcP) * \brief Segment a PDU with 10 bits sequence number, based on segmentation information given by MAC (size to transmit). diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_status_report.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_status_report.c index 02a0247a03..f1e6c961e7 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_status_report.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_status_report.c @@ -237,7 +237,7 @@ rlc_am_receive_process_control_pdu( rlc_sn_t nack_sn,prev_nack_sn; sdu_size_t data_cnf_so_stop = 0x7FFF; unsigned int nack_index; - boolean_t status = TRUE; + bool status = true; if (rlc_am_get_control_pdu_infos(rlc_am_pdu_sn_10_p, tb_size_in_bytes_pP, &rlc_pP->control_pdu_info) >= 0) { rlc_am_tx_buffer_display(ctxt_pP, rlc_pP, " TX BUFFER BEFORE PROCESS OF STATUS PDU"); @@ -282,7 +282,7 @@ rlc_am_receive_process_control_pdu( if (RLC_AM_DIFF_SN(rlc_pP->vt_s,rlc_pP->vt_a) >= RLC_AM_DIFF_SN(ack_sn,rlc_pP->vt_a)) { if (rlc_pP->control_pdu_info.num_nack == 0) { while (sn_cursor != ack_sn) { - rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor,TRUE); + rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor, true); sn_cursor = RLC_AM_NEXT_SN(sn_cursor); } @@ -294,7 +294,7 @@ rlc_am_receive_process_control_pdu( prev_nack_sn = 0x3FFF; while (sn_cursor != nack_sn) { - rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor,TRUE); + rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor, true); sn_cursor = RLC_AM_NEXT_SN(sn_cursor); } @@ -316,7 +316,7 @@ rlc_am_receive_process_control_pdu( rlc_am_ack_pdu(ctxt_pP, rlc_pP, sn_cursor, - FALSE); + false); } else { status = rlc_am_nack_pdu (ctxt_pP, rlc_pP, @@ -348,13 +348,13 @@ rlc_am_receive_process_control_pdu( LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" WARNING CONTROL PDU ACK SN %d OUT OF WINDOW vtA=%d vtS=%d\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),ack_sn,rlc_pP->vt_a,rlc_pP->vt_s); *tb_size_in_bytes_pP = 0; - status = FALSE; + status = false; } } else { LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" ERROR IN DECODING CONTROL PDU\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP)); *tb_size_in_bytes_pP = 0; - status = FALSE; + status = false; } if (status) { @@ -480,8 +480,8 @@ rlc_am_send_status_pdu( int waited_so = 0; mem_block_t *tb_p = NULL; sdu_size_t pdu_size = 0; - boolean_t status_report_completed = false; - boolean_t segment_loop_end = false; + bool status_report_completed = false; + bool segment_loop_end = false; memset(&control_pdu_info, 0, sizeof(rlc_am_control_pdu_info_t)); LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[SEND-STATUS] nb_bits_to_transmit %d (15 already allocated for header)\n", PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP), diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c index 7a95a62787..e898a601c2 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_test.c @@ -1170,7 +1170,7 @@ void rlc_am_v9_3_0_test(void) { // initscr(); // cbreak(); - // keypad(stdscr, TRUE); + // keypad(stdscr, true); // under test pool_buffer_init(); set_comp_log(RLC, LOG_ERR, LOG_MED, 1); diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_poll_retransmit.c b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_poll_retransmit.c index 969ed2d7a5..7aead2f30a 100644 --- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_poll_retransmit.c +++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_timer_poll_retransmit.c @@ -111,7 +111,7 @@ rlc_am_check_timer_poll_retransmit( } - rlc_pP->force_poll= TRUE; + rlc_pP->force_poll = true; //BugFix : new ms_time_out is computed when next poll is transmitter } } diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.c b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.c index 4e3fffe176..f079696aa9 100644 --- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.c +++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.c @@ -31,13 +31,11 @@ #include "list.h" #include "LAYER2/MAC/mac_extern.h" //----------------------------------------------------------------------------- -void -rlc_tm_send_sdu ( - const protocol_ctxt_t* const ctxt_pP, - rlc_tm_entity_t * const rlc_pP, - const boolean_t error_indicationP, - uint8_t * const srcP, - const sdu_size_t length_in_bitsP) +void rlc_tm_send_sdu(const protocol_ctxt_t* const ctxt_pP, + rlc_tm_entity_t * const rlc_pP, + const bool error_indicationP, + uint8_t * const srcP, + const sdu_size_t length_in_bitsP) { int length_in_bytes; #if DEBUG_RLC_TM_DISPLAY_ASCII_DATA diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h index d2bab33b1a..de7b9b8170 100644 --- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h +++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm.h @@ -51,7 +51,7 @@ /*! \fn void rlc_tm_send_sdu ( * const protocol_ctxt_t* const ctxt_pP, * rlc_tm_entity_t * const rlc_pP, -* const boolean_t error_indicationP, +* const bool error_indicationP, * uint8_t * const srcP, * const sdu_size_t length_in_bitsP) * \brief Send SDU if any reassemblied to upper layer. @@ -60,12 +60,11 @@ * \param[in] srcP SDU data pointer. * \param[in] length_in_bitsP Length of SDU in bits. */ -void rlc_tm_send_sdu ( - const protocol_ctxt_t* const ctxt_pP, - rlc_tm_entity_t * const rlc_pP, - const boolean_t error_indicationP, - uint8_t * const srcP, - const sdu_size_t length_in_bitsP); +void rlc_tm_send_sdu(const protocol_ctxt_t* const ctxt_pP, + rlc_tm_entity_t * const rlc_pP, + const bool error_indicationP, + uint8_t * const srcP, + const sdu_size_t length_in_bitsP); /*! \fn void rlc_tm_no_segment (const protocol_ctxt_t* const ctxt_pP, rlc_tm_entity_t * const rlcP) * \brief Schedule a SDU to be transmited by lower layers. diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_entity.h b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_entity.h index 1a13982df6..3c2f1804be 100644 --- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_entity.h +++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_entity.h @@ -40,14 +40,13 @@ * \brief Structure containing a RLC TM instance protocol variables, allocation variables, buffers and other miscellaneous variables. */ typedef struct rlc_tm_entity { - boolean_t allocation; /*!< \brief Boolean for rlc_tm_entity_t struct allocation. */ + bool allocation; /*!< \brief Boolean for rlc_tm_entity_t struct allocation. */ rlc_protocol_state_t protocol_state; /*!< \brief Protocol state, can be RLC_NULL_STATE, RLC_DATA_TRANSFER_READY_STATE, RLC_LOCAL_SUSPEND_STATE. */ - boolean_t is_uplink_downlink; /*!< \brief Is this instance is a transmitter, a receiver or both? */ - boolean_t is_data_plane; /*!< \brief To know if the RLC belongs to a data radio bearer or a signalling radio bearer, for statistics and trace purpose. */ + bool is_uplink_downlink; /*!< \brief Is this instance is a transmitter, a receiver or both? */ + bool is_data_plane; /*!< \brief To know if the RLC belongs to a data radio bearer or a signalling radio bearer, for statistics and trace purpose. */ // for stats and trace purpose : logical_chan_id_t channel_id; /*!< \brief Transport channel identifier. */ rb_id_t rb_id; /*!< \brief Radio bearer identifier, for statistics and trace purpose. */ - //boolean_t is_enb; /*!< \brief To know if the RLC belongs to a eNB or UE. */ //----------------------------- // tranmission //----------------------------- diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c index 22e6f4d78d..a838b2a006 100644 --- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c +++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.c @@ -133,10 +133,9 @@ rlc_tm_cleanup ( } //----------------------------------------------------------------------------- -void rlc_tm_configure( - const protocol_ctxt_t* const ctxt_pP, - rlc_tm_entity_t * const rlcP, - const boolean_t is_uplink_downlinkP) +void rlc_tm_configure(const protocol_ctxt_t* const ctxt_pP, + rlc_tm_entity_t * const rlcP, + const bool is_uplink_downlinkP) { rlcP->is_uplink_downlink = is_uplink_downlinkP; rlc_tm_reset_state_variables (ctxt_pP, rlcP); diff --git a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h index 57e2116a72..f315a0311a 100644 --- a/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h +++ b/openair2/LAYER2/RLC/TM_v9.3.0/rlc_tm_init.h @@ -78,27 +78,24 @@ void rlc_tm_init ( * \brief Reset protocol variables and state variables to initial values. * \param[in] rlcP RLC TM protocol instance pointer. */ -void rlc_tm_reset_state_variables ( - const protocol_ctxt_t* const ctxt_pP, - rlc_tm_entity_t * const rlcP); +void rlc_tm_reset_state_variables(const protocol_ctxt_t* const ctxt_pP, + rlc_tm_entity_t * const rlcP); /*! \fn void rlc_tm_cleanup(rlc_tm_entity_t * const rlcP) * \brief Free all allocated memory (lists and buffers) previously allocated by this RLC TM instance. * \param[in] rlcP RLC TM protocol instance pointer. */ -void rlc_tm_cleanup( - rlc_tm_entity_t * const rlcP); +void rlc_tm_cleanup(rlc_tm_entity_t * const rlcP); -/*! \fn void rlc_tm_configure(const protocol_ctxt_t* const ctxt_pP,rlc_tm_entity_t * const rlcP, const boolean_t is_uplink_downlinkP) +/*! \fn void rlc_tm_configure(const protocol_ctxt_t* const ctxt_pP,rlc_tm_entity_t * const rlcP, const bool is_uplink_downlinkP) * \brief Configure RLC TM protocol parameters. * \param[in] rlcP RLC TM protocol instance pointer. * \param[in] is_uplink_downlinkP Is this instance is TRANSMITTER_ONLY, RECEIVER_ONLY, or TRANSMITTER_AND_RECEIVER. */ -void rlc_tm_configure( - const protocol_ctxt_t* const ctxt_pP, - rlc_tm_entity_t * const rlcP, - const boolean_t is_uplink_downlinkP); +void rlc_tm_configure(const protocol_ctxt_t* const ctxt_pP, + rlc_tm_entity_t * const rlcP, + const bool is_uplink_downlinkP); /*! \fn void rlc_tm_set_debug_infos(const protocol_ctxt_t* const ctxt_pP, rlc_tm_entity_t * const rlcP, const rb_id_t rb_idP, const srb_flag_t srb_flagP) * \brief Set debug informations for a RLC TM protocol instance, these informations are only for trace purpose. diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c index bec815ac5d..f2cb4f09b1 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_control_primitives.c @@ -263,7 +263,7 @@ rlc_um_init ( } rlc_pP->first_pdu = 1; - rlc_pP->initialized = TRUE; + rlc_pP->initialized = true; } } //----------------------------------------------------------------------------- diff --git a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_entity.h b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_entity.h index 3250ac85b8..7bfa3d60ff 100644 --- a/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_entity.h +++ b/openair2/LAYER2/RLC/UM_v9.3.0/rlc_um_entity.h @@ -53,12 +53,11 @@ typedef struct rlc_um_timer_s { */ typedef struct rlc_um_entity_s { - boolean_t initialized; /*!< \brief Boolean for rlc_am_entity_t struct initialization. */ - boolean_t is_uplink_downlink; /*!< \brief Is this instance is a transmitter, a receiver or both? */ + bool initialized; /*!< \brief Boolean for rlc_am_entity_t struct initialization. */ + bool is_uplink_downlink; /*!< \brief Is this instance is a transmitter, a receiver or both? */ rlc_protocol_state_t protocol_state; /*!< \brief Protocol state, can be RLC_NULL_STATE, RLC_DATA_TRANSFER_READY_STATE, RLC_LOCAL_SUSPEND_STATE. */ - boolean_t is_data_plane; /*!< \brief To know if the RLC belongs to a data radio bearer or a signalling radio bearer, for statistics and trace purpose. */ - //boolean_t is_enb; /*!< \brief To know if the RLC belongs to a eNB or UE. */ - boolean_t is_mxch; /*!< \brief To know if the RLC belongs to a MBMS bearer. */ + bool is_data_plane; /*!< \brief To know if the RLC belongs to a data radio bearer or a signalling radio bearer, for statistics and trace purpose. */ + bool is_mxch; /*!< \brief To know if the RLC belongs to a MBMS bearer. */ //----------------------------- // PROTOCOL VARIABLES //----------------------------- @@ -114,7 +113,7 @@ typedef struct rlc_um_entity_s { //----------------------------- // STATISTICS //----------------------------- - boolean_t first_pdu; /*!< \brief Act as a boolean, tells if the next PDU is the first PDU to be received. */ + bool first_pdu; /*!< \brief Act as a boolean, tells if the next PDU is the first PDU to be received. */ unsigned int stat_tx_pdcp_sdu; /*!< \brief Number of SDUs received from upper layers. */ unsigned int stat_tx_pdcp_bytes; /*!< \brief Number of SDU bytes received from upper layers. */ diff --git a/openair2/LAYER2/RLC/rlc.c b/openair2/LAYER2/RLC/rlc.c index b9dcf0414b..ec90817500 100644 --- a/openair2/LAYER2/RLC/rlc.c +++ b/openair2/LAYER2/RLC/rlc.c @@ -41,13 +41,12 @@ #include "common/ran_context.h" extern RAN_CONTEXT_t RC; -extern boolean_t pdcp_data_ind( - const protocol_ctxt_t *const ctxt_pP, - const srb_flag_t srb_flagP, - const MBMS_flag_t MBMS_flagP, - const rb_id_t rb_idP, - const sdu_size_t sdu_buffer_sizeP, - mem_block_t *const sdu_buffer_pP); +extern bool pdcp_data_ind(const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_idP, + const sdu_size_t sdu_buffer_sizeP, + mem_block_t *const sdu_buffer_pP); #define DEBUG_RLC_PDCP_INTERFACE 1 //#define TRACE_RLC_PAYLOAD 1 @@ -397,7 +396,7 @@ rlc_op_status_t rlc_data_req (const protocol_ctxt_t *const ctxt_pP, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RLC_DATA_REQ,VCD_FUNCTION_IN); - if (MBMS_flagP == TRUE) { + if (MBMS_flagP == true) { if (ctxt_pP->enb_flag) { log_ch_id = rlc_mbms_enb_get_lcid_by_rb_id(ctxt_pP->module_id,rb_idP); mbms_id_p = &rlc_mbms_lcid2service_session_id_eNB[ctxt_pP->module_id][log_ch_id]; diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h index 1e5b7947d7..1e17ff96bf 100644 --- a/openair2/LAYER2/RLC/rlc.h +++ b/openair2/LAYER2/RLC/rlc.h @@ -107,7 +107,7 @@ typedef struct { rlc_buffer_occupancy_t pdus_in_buffer; /*!< \brief Number of PDUs buffered in RLC protocol instance (OBSOLETE). */ frame_t head_sdu_creation_time; /*!< \brief Head SDU creation time. */ sdu_size_t head_sdu_remaining_size_to_send; /*!< \brief remaining size of sdu: could be the total size or the remaining size of already segmented sdu */ - boolean_t head_sdu_is_segmented; /*!< \brief 0 if head SDU has not been segmented, 1 if already segmented */ + bool head_sdu_is_segmented; /*!< \brief 0 if head SDU has not been segmented, 1 if already segmented */ } mac_rlc_status_resp_t; diff --git a/openair2/LAYER2/RLC/rlc_mac.c b/openair2/LAYER2/RLC/rlc_mac.c index 89cbe4c406..0e1cb89fd7 100644 --- a/openair2/LAYER2/RLC/rlc_mac.c +++ b/openair2/LAYER2/RLC/rlc_mac.c @@ -425,8 +425,8 @@ rlc_buffer_occupancy_t mac_rlc_get_buffer_occupancy_ind( /* Assumptions : for UE only */ /* At each TTI, Buffer Occupancy is first computed in mac_rlc_status_ind called by MAC ue_scheduler() function */ /* Then this function is called during MAC multiplexing ue_get_sdu(), and it may be call several times for the same bearer if it is in AM mode and there are several PDU types to transmit */ - //AssertFatal(enb_flagP == FALSE,"RLC Tx mac_rlc_get_buffer_occupancy_ind function is not implemented for eNB LcId=%d\n", channel_idP); - if(enb_flagP != FALSE) { + //AssertFatal(enb_flagP == false,"RLC Tx mac_rlc_get_buffer_occupancy_ind function is not implemented for eNB LcId=%d\n", channel_idP); + if(enb_flagP != false) { LOG_E(RLC, "Tx mac_rlc_get_buffer_occupancy_ind function is not implemented for eNB LcId=%u\n", channel_idP); return 0; } diff --git a/openair2/LAYER2/RLC/rlc_rrc.c b/openair2/LAYER2/RLC/rlc_rrc.c index 4313f379fe..ed9af5efb2 100644 --- a/openair2/LAYER2/RLC/rlc_rrc.c +++ b/openair2/LAYER2/RLC/rlc_rrc.c @@ -480,7 +480,7 @@ rlc_op_status_t rrc_rlc_remove_rlc ( /* for no gcc warnings */ (void)lcid; - if (MBMS_flagP == TRUE) { + if (MBMS_flagP == true) { if (ctxt_pP->enb_flag) { lcid = rlc_mbms_enb_get_lcid_by_rb_id(ctxt_pP->module_id,rb_idP); mbms_id_p = &rlc_mbms_lcid2service_session_id_eNB[ctxt_pP->module_id][lcid]; @@ -581,7 +581,7 @@ rlc_union_t *rrc_rlc_add_rlc ( rlc_mbms_id_t *mbms_id_p = NULL; logical_chan_id_t lcid = 0; - if (MBMS_flagP == FALSE) { + if (MBMS_flagP == false) { //AssertFatal (rb_idP < NB_RB_MAX, "RB id is too high (%u/%d)!\n", rb_idP, NB_RB_MAX); //AssertFatal (chan_idP < RLC_MAX_LC, "LC id is too high (%u/%d)!\n", chan_idP, RLC_MAX_LC); if(rb_idP >= NB_RB_MAX) { @@ -595,7 +595,7 @@ rlc_union_t *rrc_rlc_add_rlc ( } } - if (MBMS_flagP == TRUE) { + if (MBMS_flagP == true) { if (ctxt_pP->enb_flag) { lcid = rlc_mbms_enb_get_lcid_by_rb_id(ctxt_pP->module_id,rb_idP); mbms_id_p = &rlc_mbms_lcid2service_session_id_eNB[ctxt_pP->module_id][lcid]; @@ -640,11 +640,11 @@ rlc_union_t *rrc_rlc_add_rlc ( } else if (h_rc == HASH_TABLE_KEY_NOT_EXISTS) { rlc_union_p = calloc(1, sizeof(rlc_union_t)); h_rc = hashtable_insert(rlc_coll_p, key, rlc_union_p); - if(MBMS_flagP != TRUE) + if(MBMS_flagP != true) h_lcid_rc = hashtable_insert(rlc_coll_p, key_lcid, rlc_union_p); if ((h_rc == HASH_TABLE_OK) && (h_lcid_rc == HASH_TABLE_OK)) { - if (MBMS_flagP == TRUE) { + if (MBMS_flagP == true) { LOG_I(RLC, PROTOCOL_CTXT_FMT" RLC service id %u session id %u rrc_rlc_add_rlc\n", PROTOCOL_CTXT_ARGS(ctxt_pP), mbms_id_p->service_id, diff --git a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c index fc794ad169..9598bf1ad6 100644 --- a/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c +++ b/openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.c @@ -359,15 +359,14 @@ static void enqueue_pdcp_data_ind( if (pthread_mutex_unlock(&pq.m) != 0) abort(); } -boolean_t pdcp_data_ind( - const protocol_ctxt_t *const ctxt_pP, - const srb_flag_t srb_flagP, - const MBMS_flag_t MBMS_flagP, - const rb_id_t rb_id, - const sdu_size_t sdu_buffer_size, - mem_block_t *const sdu_buffer, - const uint32_t *const srcID, - const uint32_t *const dstID) +bool pdcp_data_ind(const protocol_ctxt_t *const ctxt_pP, + const srb_flag_t srb_flagP, + const MBMS_flag_t MBMS_flagP, + const rb_id_t rb_id, + const sdu_size_t sdu_buffer_size, + mem_block_t *const sdu_buffer, + const uint32_t *const srcID, + const uint32_t *const dstID) { enqueue_pdcp_data_ind(ctxt_pP, srb_flagP, @@ -438,7 +437,7 @@ static void *enb_tun_read_thread(void *_) ctxt.rnti = rnti; uint8_t qfi = 7; - boolean_t rqi = 0; + bool rqi = 0; int pdusession_id = 10; sdap_data_req(&ctxt, SRB_FLAG_NO, rb_id, RLC_MUI_UNDEFINED, @@ -484,7 +483,7 @@ static void *ue_tun_read_thread(void *_) ctxt.rnti = rnti; - boolean_t dc = SDAP_HDR_UL_DATA_PDU; + bool dc = SDAP_HDR_UL_DATA_PDU; uint8_t qfi = 7; int pdusession_id = 10; @@ -858,7 +857,7 @@ void pdcp_run(const protocol_ctxt_t *const ctxt_pP) RRC_DCCH_DATA_REQ(msg_p).mode, NULL, NULL); - if (result != TRUE) + if (result != true) LOG_E(PDCP, "PDCP data request failed!\n"); result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_REQ(msg_p).sdu_p); AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); @@ -950,7 +949,7 @@ static void add_drb_am(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s, int has_sdap = 0; int has_sdapULheader=0; int has_sdapDLheader=0; - boolean_t is_sdap_DefaultDRB = false; + bool is_sdap_DefaultDRB = false; NR_QFI_t *mappedQFIs2Add = NULL; uint8_t mappedQFIs2AddCount=0; if (s->cnAssociation->present == NR_DRB_ToAddMod__cnAssociation_PR_eps_BearerIdentity) @@ -1033,20 +1032,18 @@ static void add_drb(int is_gnb, int rnti, struct NR_DRB_ToAddMod *s, LOG_I(PDCP, "%s:%s:%d: added DRB for UE RNTI %x\n", __FILE__, __FUNCTION__, __LINE__, rnti); } -boolean_t nr_rrc_pdcp_config_asn1_req( - const protocol_ctxt_t *const ctxt_pP, - NR_SRB_ToAddModList_t *const srb2add_list, - NR_DRB_ToAddModList_t *const drb2add_list, - NR_DRB_ToReleaseList_t *const drb2release_list, - const uint8_t security_modeP, - uint8_t *const kRRCenc, - uint8_t *const kRRCint, - uint8_t *const kUPenc, - uint8_t *const kUPint - ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 - ,rb_id_t *const defaultDRB, - struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list) - //struct NR_RLC_Config *rlc_Config) +bool nr_rrc_pdcp_config_asn1_req(const protocol_ctxt_t *const ctxt_pP, + NR_SRB_ToAddModList_t *const srb2add_list, + NR_DRB_ToAddModList_t *const drb2add_list, + NR_DRB_ToReleaseList_t *const drb2release_list, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc, + uint8_t *const kUPint, + LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9, + rb_id_t *const defaultDRB, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list) { int rnti = ctxt_pP->rnti; int i; @@ -1104,17 +1101,16 @@ boolean_t nr_rrc_pdcp_config_asn1_req( } /* Dummy function due to dependency from LTE libraries */ -boolean_t rrc_pdcp_config_asn1_req( - const protocol_ctxt_t *const ctxt_pP, - LTE_SRB_ToAddModList_t *const srb2add_list, - LTE_DRB_ToAddModList_t *const drb2add_list, - LTE_DRB_ToReleaseList_t *const drb2release_list, - const uint8_t security_modeP, - uint8_t *const kRRCenc, - uint8_t *const kRRCint, - uint8_t *const kUPenc - ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 - ,rb_id_t *const defaultDRB) +bool rrc_pdcp_config_asn1_req(const protocol_ctxt_t *const ctxt_pP, + LTE_SRB_ToAddModList_t *const srb2add_list, + LTE_DRB_ToAddModList_t *const drb2add_list, + LTE_DRB_ToReleaseList_t *const drb2release_list, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc, + LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9, + rb_id_t *const defaultDRB) { return 0; } @@ -1219,8 +1215,7 @@ uint64_t get_pdcp_optmask(void) return pdcp_optmask; } -boolean_t pdcp_remove_UE( - const protocol_ctxt_t *const ctxt_pP) +bool pdcp_remove_UE(const protocol_ctxt_t *const ctxt_pP) { int rnti = ctxt_pP->rnti; @@ -1275,13 +1270,12 @@ void pdcp_config_set_security( nr_pdcp_manager_unlock(nr_pdcp_ue_manager); } -static boolean_t pdcp_data_req_srb( - protocol_ctxt_t *ctxt_pP, - const rb_id_t rb_id, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_size, - unsigned char *const sdu_buffer) +static bool pdcp_data_req_srb(protocol_ctxt_t *ctxt_pP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer) { LOG_D(PDCP, "%s() called, size %d\n", __func__, sdu_buffer_size); nr_pdcp_ue_t *ue; @@ -1322,13 +1316,12 @@ static boolean_t pdcp_data_req_srb( } -static boolean_t pdcp_data_req_drb( - protocol_ctxt_t *ctxt_pP, - const rb_id_t rb_id, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_size, - unsigned char *const sdu_buffer) +static bool pdcp_data_req_drb(protocol_ctxt_t *ctxt_pP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer) { LOG_D(PDCP, "%s() called, size %d\n", __func__, sdu_buffer_size); nr_pdcp_ue_t *ue; @@ -1368,19 +1361,16 @@ static boolean_t pdcp_data_req_drb( return 1; } -boolean_t cu_f1u_data_req( - protocol_ctxt_t *ctxt_pP, - const srb_flag_t srb_flagP, - const rb_id_t rb_id, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_size, - unsigned char *const sdu_buffer, - const pdcp_transmission_mode_t mode - ,const uint32_t *const sourceL2Id - ,const uint32_t *const destinationL2Id - ) { - +bool cu_f1u_data_req(protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t mode, + const uint32_t *const sourceL2Id, + const uint32_t *const destinationL2Id) { //Force instance id to 0, OAI incoherent instance management ctxt_pP->instance=0; mem_block_t *memblock = get_free_mem_block(sdu_buffer_size, __func__); @@ -1397,18 +1387,16 @@ boolean_t cu_f1u_data_req( return ret; } -boolean_t pdcp_data_req( - protocol_ctxt_t *ctxt_pP, - const srb_flag_t srb_flagP, - const rb_id_t rb_id, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_size, - unsigned char *const sdu_buffer, - const pdcp_transmission_mode_t mode - ,const uint32_t *const sourceL2Id - ,const uint32_t *const destinationL2Id - ) +bool pdcp_data_req(protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_id, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t mode, + const uint32_t *const sourceL2Id, + const uint32_t *const destinationL2Id) { if (srb_flagP) { return pdcp_data_req_srb(ctxt_pP, rb_id, muiP, confirmP, sdu_buffer_size, sdu_buffer); diff --git a/openair2/M2AP/m2ap_common.h b/openair2/M2AP/m2ap_common.h index 95da064b4a..0a6895fcb7 100644 --- a/openair2/M2AP/m2ap_common.h +++ b/openair2/M2AP/m2ap_common.h @@ -55,11 +55,6 @@ # define M2AP_PORT 36423 #endif -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - extern int asn1_xer_print; #if defined(ENB_MODE) diff --git a/openair2/RRC/LITE/rrc_common.c b/openair2/RRC/LITE/rrc_common.c index a4239e857d..f0c4e94c99 100644 --- a/openair2/RRC/LITE/rrc_common.c +++ b/openair2/RRC/LITE/rrc_common.c @@ -306,7 +306,7 @@ rrc_rx_tx( LOG_D(RRC,"SFN.SN %d.%d => release timer %d/%d\n",ctxt_pP->frame,ctxt_pP->subframe, ue_context_p->ue_context.ue_release_timer,ue_context_p->ue_context.ue_release_timer_thres); if ((ctxt_pP->frame == 0) && (ctxt_pP->subframe==0)) { - if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) { + if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == true) { LOG_I(RRC,"UE rnti %x:S-TMSI %x failure timer %d/20000\n", ue_context_p->ue_context.rnti, ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi, diff --git a/openair2/RRC/LTE/L2_interface.c b/openair2/RRC/LTE/L2_interface.c index 0a63acc8fb..c12d2aa873 100644 --- a/openair2/RRC/LTE/L2_interface.c +++ b/openair2/RRC/LTE/L2_interface.c @@ -299,7 +299,7 @@ mac_rrc_data_ind( const uint8_t *sduP, const sdu_size_t sdu_lenP, const uint8_t mbsfn_sync_areaP, - const boolean_t brOption + const bool brOption ) //-------------------------------------------------------------------------- { diff --git a/openair2/RRC/LTE/L2_interface_common.c b/openair2/RRC/LTE/L2_interface_common.c index 1993fe7de0..660bd91dda 100644 --- a/openair2/RRC/LTE/L2_interface_common.c +++ b/openair2/RRC/LTE/L2_interface_common.c @@ -58,7 +58,7 @@ rrc_data_req( { if(sdu_sizeP == 255) { LOG_I(RRC,"sdu_sizeP == 255"); - return FALSE; + return false; } MessageDef *message_p; @@ -94,7 +94,7 @@ rrc_data_req( if (ctxt_pP->enb_flag && NODE_IS_CU(RC.rrc[ctxt_pP->module_id]->node_type)) pdcp_run(ctxt_pP); - return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. + return true; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. } //------------------------------------------------------------------------------ diff --git a/openair2/RRC/LTE/L2_interface_ue.c b/openair2/RRC/LTE/L2_interface_ue.c index 534030864a..850ecf1b58 100644 --- a/openair2/RRC/LTE/L2_interface_ue.c +++ b/openair2/RRC/LTE/L2_interface_ue.c @@ -298,7 +298,7 @@ rrc_data_req_ue( TASK_PDCP_UE, ctxt_pP->instance, message_p); - return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. + return true; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. } } diff --git a/openair2/RRC/LTE/MESSAGES/asn1_msg.c b/openair2/RRC/LTE/MESSAGES/asn1_msg.c index c34c65b195..e5024e3505 100644 --- a/openair2/RRC/LTE/MESSAGES/asn1_msg.c +++ b/openair2/RRC/LTE/MESSAGES/asn1_msg.c @@ -343,7 +343,7 @@ uint8_t do_MIB_SL(const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, if (in_coverage > 0 ) { //in coverage - mib_sl->inCoverage_r12 = TRUE; + mib_sl->inCoverage_r12 = true; mib_sl->sl_Bandwidth_r12 = *UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index]->freqInfo.ul_Bandwidth; if (UE_rrc_inst[ctxt_pP->module_id].sib1[eNB_index]->tdd_Config) { @@ -366,7 +366,7 @@ uint8_t do_MIB_SL(const protocol_ctxt_t *const ctxt_pP, const uint8_t eNB_index, } else { //Todo - out of coverage for V2X // Todo - UE has a selected SyncRef UE - mib_sl->inCoverage_r12 = FALSE; + mib_sl->inCoverage_r12 = false; //set sl-Bandwidth, subframeAssignmentSL and reserved from the pre-configured parameters } @@ -989,7 +989,7 @@ uint8_t do_SIB1(rrc_eNB_carrier_data_t *carrier, sib1_1250->nonCriticalExtension = NULL; ////Rel1310 if ((configuration->schedulingInfoSIB1_BR_r13[CC_id] != 0) && - (brOption==TRUE)) { + (brOption==true)) { sib1_1250->nonCriticalExtension = calloc(1, sizeof(LTE_SystemInformationBlockType1_v1310_IEs_t)); memset(sib1_1250->nonCriticalExtension, 0, sizeof(LTE_SystemInformationBlockType1_v1310_IEs_t)); LTE_SystemInformationBlockType1_v1310_IEs_t *sib1_1310 = sib1_1250->nonCriticalExtension; @@ -1279,7 +1279,7 @@ uint8_t do_SIB23(uint8_t Mod_id, *sib2 = &sib2_part->choice.sib2; *sib3 = &sib3_part->choice.sib3; - if ((configuration->eMBMS_configured > 0) && (brOption==FALSE)) { + if ((configuration->eMBMS_configured > 0) && (brOption==false)) { sib13_part = CALLOC(1,sizeof(struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member)); memset(sib13_part,0,sizeof(struct LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member)); sib13_part->present = LTE_SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib13_v920; @@ -2781,7 +2781,7 @@ do_RRCConnectionSetup( mac_MainConfig->ul_SCH_Config->maxHARQ_Tx = maxHARQ_Tx; // max number of UL HARQ transmission mac_MainConfig->ul_SCH_Config->periodicBSR_Timer = periodicBSR_Timer; mac_MainConfig->ul_SCH_Config->retxBSR_Timer = LTE_RetxBSR_Timer_r12_sf320; // LTE_RetxBSR_Timer_r12_sf5120 // regular BSR timer - mac_MainConfig->ul_SCH_Config->ttiBundling = 0; // FALSE + mac_MainConfig->ul_SCH_Config->ttiBundling = 0; // false //* timeAlignmentTimerDedicated *// mac_MainConfig->timeAlignmentTimerDedicated = LTE_TimeAlignmentTimer_infinity; //* DRX Config *// @@ -3135,7 +3135,7 @@ uint8_t do_RRCConnectionSetup_BR( //mac_MainConfig->ul_SCH_Config->maxHARQ_Tx = maxHARQ_Tx; mac_MainConfig->ul_SCH_Config->periodicBSR_Timer = periodicBSR_Timer; mac_MainConfig->ul_SCH_Config->retxBSR_Timer = LTE_RetxBSR_Timer_r12_sf320; - mac_MainConfig->ul_SCH_Config->ttiBundling = 0; // FALSE + mac_MainConfig->ul_SCH_Config->ttiBundling = 0; // false mac_MainConfig->timeAlignmentTimerDedicated = LTE_TimeAlignmentTimer_infinity; mac_MainConfig->drx_Config = NULL; mac_MainConfig->phr_Config = CALLOC(1, sizeof(*mac_MainConfig->phr_Config)); diff --git a/openair2/RRC/LTE/defs_NB_IoT.h b/openair2/RRC/LTE/defs_NB_IoT.h index c76bdea53f..b98dbe22cc 100644 --- a/openair2/RRC/LTE/defs_NB_IoT.h +++ b/openair2/RRC/LTE/defs_NB_IoT.h @@ -156,7 +156,7 @@ typedef struct UE_RRC_INFO_NB_IoT_s { #define RRC_TRANSACTION_IDENTIFIER_NUMBER 3 typedef struct UE_S_TMSI_NB_IoT_s { - boolean_t presence; + bool presence; mme_code_t mme_code; m_tmsi_t m_tmsi; } __attribute__ ((__packed__)) UE_S_TMSI_NB_IoT; diff --git a/openair2/RRC/LTE/rrc_UE.c b/openair2/RRC/LTE/rrc_UE.c index 9b37853ed2..577ee3effd 100644 --- a/openair2/RRC/LTE/rrc_UE.c +++ b/openair2/RRC/LTE/rrc_UE.c @@ -4351,8 +4351,8 @@ void rrc_ue_generate_nrMeasurementReport(protocol_ctxt_t *const ctxt_pP, uint8_t AssertFatal(size >= 0, "do_nrMeasurementReport failed \n"); LOG_I(RRC, "[UE %d] Frame %d : Generating Measurement Report for eNB %d\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index); - int result = pdcp_data_req(ctxt_pP, SRB_FLAG_YES, DCCH, rrc_mui++, 0, size, buffer, PDCP_TRANSMISSION_MODE_DATA,NULL, NULL); - AssertFatal (result == TRUE, "PDCP data request failed!\n"); + const bool result = pdcp_data_req(ctxt_pP, SRB_FLAG_YES, DCCH, rrc_mui++, 0, size, buffer, PDCP_TRANSMISSION_MODE_DATA,NULL, NULL); + AssertFatal (result == true, "PDCP data request failed!\n"); } } } @@ -4370,7 +4370,6 @@ void rrc_ue_generate_MeasurementReport(protocol_ctxt_t *const ctxt_pP, uint8_t e long nElem, nElem1; float rsrp_filtered, rsrq_filtered; static frame_t pframe=0; - int result; nElem = 98; nElem1 = 35; target_eNB_offset = UE_rrc_inst[ctxt_pP->module_id].Info[0].handoverTarget; // eNB_offset of target eNB: used to obtain the mod_id of target eNB @@ -4420,8 +4419,8 @@ void rrc_ue_generate_MeasurementReport(protocol_ctxt_t *const ctxt_pP, uint8_t e AssertFatal(size >= 0, "do_MeasurementReport failed \n"); LOG_I(RRC, "[UE %d] Frame %d : Generating Measurement Report for eNB %d. Size is %zu\n", ctxt_pP->module_id, ctxt_pP->frame, eNB_index, size); - result = pdcp_data_req(ctxt_pP, SRB_FLAG_YES, DCCH, rrc_mui++, 0, size, buffer, PDCP_TRANSMISSION_MODE_DATA,NULL, NULL); - AssertFatal (result == TRUE, "PDCP data request failed!\n"); + const bool result = pdcp_data_req(ctxt_pP, SRB_FLAG_YES, DCCH, rrc_mui++, 0, size, buffer, PDCP_TRANSMISSION_MODE_DATA,NULL, NULL); + AssertFatal (result == true, "PDCP data request failed!\n"); //LOG_D(RRC, "[UE %d] Frame %d Sending MeasReport (%d bytes) through DCCH%d to PDCP \n",ue_mod_idP,frameP, size, DCCH); } diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index 64baf5e2ac..22c8a14863 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -367,7 +367,7 @@ typedef struct UE_RRC_INFO_s { } __attribute__ ((__packed__)) UE_RRC_INFO; typedef struct UE_S_TMSI_s { - boolean_t presence; + bool presence; mme_code_t mme_code; m_tmsi_t m_tmsi; } __attribute__ ((__packed__)) UE_S_TMSI; @@ -931,7 +931,7 @@ typedef struct UE_RRC_INST_s { } UE_RRC_INST; typedef struct UE_PF_PO_s { - boolean_t enable_flag; /* flag indicate whether current object is used */ + bool enable_flag; /* flag indicate whether current object is used */ uint16_t ue_index_value; /* UE index value */ uint8_t PF_min; /* minimal value of Paging Frame (PF) */ uint8_t PO; /* Paging Occasion (PO) */ diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index ea98d3169d..a5d938cdf6 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -150,7 +150,7 @@ init_SI( LTE_SystemInformationBlockType1_v1310_IEs_t *sib1_v13ext=(LTE_SystemInformationBlockType1_v1310_IEs_t *)NULL; LOG_D(RRC,"%s()\n\n\n\n",__FUNCTION__); - if(configuration->radioresourceconfig[CC_id].mbms_dedicated_serving_cell == TRUE) { + if(configuration->radioresourceconfig[CC_id].mbms_dedicated_serving_cell == true) { LOG_A(RRC, "Configuring MIB FeMBMS (N_RB_DL %d)\n", (int)configuration->N_RB_DL[CC_id]); RC.rrc[ctxt_pP->module_id]->carrier[CC_id].MIB_FeMBMS = (uint8_t *) malloc16(4); @@ -266,7 +266,7 @@ init_SI( carrier->sizeof_SIB1 = do_SIB1(&rrc->carrier[CC_id], ctxt_pP->module_id, CC_id, - FALSE, + false, configuration ); AssertFatal(carrier->sizeof_SIB1 != 255,"FATAL, RC.rrc[enb_mod_idP].carrier[CC_id].sizeof_SIB1 == 255"); @@ -276,7 +276,7 @@ init_SI( RC.rrc[ctxt_pP->module_id]->carrier[CC_id].SIB1_BR = (uint8_t *) malloc16(32); RC.rrc[ctxt_pP->module_id]->carrier[CC_id].sizeof_SIB1_BR = do_SIB1(&RC.rrc[ctxt_pP->module_id]->carrier[CC_id], ctxt_pP->module_id, - CC_id, TRUE, configuration); + CC_id, true, configuration); } } @@ -285,7 +285,7 @@ init_SI( AssertFatal(carrier->SIB23!=NULL,"cannot allocate memory for SIB"); carrier->sizeof_SIB23 = do_SIB23(ctxt_pP->module_id, CC_id, - FALSE, + false, configuration ); LOG_I(RRC,"do_SIB23, size %d \n ", carrier->sizeof_SIB23); @@ -295,7 +295,7 @@ init_SI( if (configuration->schedulingInfoSIB1_BR_r13[CC_id]>0) { carrier->SIB23_BR = (uint8_t *) malloc16(64); AssertFatal(carrier->SIB23_BR!=NULL,"cannot allocate memory for SIB"); - carrier->sizeof_SIB23_BR = do_SIB23(ctxt_pP->module_id, CC_id, TRUE, configuration); + carrier->sizeof_SIB23_BR = do_SIB23(ctxt_pP->module_id, CC_id, true, configuration); } LOG_T(RRC, PROTOCOL_RRC_CTXT_FMT" SIB2/3 Contents (partial)\n", @@ -661,7 +661,7 @@ rrc_eNB_get_next_transaction_identifier( ////----------------------------------------------------------------------------- //{ // -// boolean_t reg = FALSE; +// bool reg = false; // module_id_t i; // // AssertFatal(enb_mod_idP < NB_eNB_INST, "eNB index invalid (%d/%d)!", enb_mod_idP, NB_eNB_INST); @@ -669,12 +669,12 @@ rrc_eNB_get_next_transaction_identifier( // for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { // if (RC.rrc[enb_mod_idP]->Info.UE_info[i] == UE_identity) { // // UE_identity already registered -// reg = TRUE; +// reg = true; // break; // } // } // -// if (reg == FALSE) { +// if (reg == false) { // return (UE_MODULE_INVALID); // } else // return (i); @@ -713,7 +713,7 @@ rrc_eNB_ue_context_stmsi_exist( m_tmsiP, mme_codeP, ue_context_p, ue_context_p->ue_context.rnti); - if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) { + if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == true) { printf("=> S-TMSI %x, MME %x\n", ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi, ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code); @@ -986,7 +986,7 @@ void remove_UE_from_freelist(module_id_t mod_id, rnti_t rnti) { pthread_mutex_unlock(&lock_ue_freelist); } -void put_UE_in_freelist(module_id_t mod_id, rnti_t rnti, boolean_t removeFlag) { +void put_UE_in_freelist(module_id_t mod_id, rnti_t rnti, bool removeFlag) { UE_free_list_t *free_list = NULL; eNB_MAC_INST *eNB_MAC = RC.mac[mod_id]; pthread_mutex_lock(&lock_ue_freelist); @@ -1013,7 +1013,7 @@ void release_UE_in_freeList(module_id_t mod_id) { PHY_VARS_eNB *eNB_PHY = NULL; struct rrc_eNB_ue_context_s *ue_context_pP = NULL; eNB_MAC_INST *eNB_MAC = RC.mac[mod_id]; - boolean_t remove_UEContext; + bool remove_UEContext; rnti_t rnti; int head, tail, ue_num; pthread_mutex_lock(&lock_ue_freelist); @@ -1678,7 +1678,7 @@ rrc_eNB_process_RRCConnectionReestablishmentComplete( ue_context_pP->ue_context.rnti = ctxt_pP->rnti; if (EPC_MODE_ENABLED) { - uint8_t send_security_mode_command = FALSE; + uint8_t send_security_mode_command = false; rrc_pdcp_config_security( ctxt_pP, ue_context_pP, @@ -2332,7 +2332,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t *co // PDCP PDCP_rlc_AM = CALLOC(1, sizeof(*PDCP_rlc_AM)); DRB_pdcp_config->rlc_AM = PDCP_rlc_AM; - PDCP_rlc_AM->statusReportRequired = FALSE; + PDCP_rlc_AM->statusReportRequired = false; break; default : @@ -2590,7 +2590,7 @@ rrc_eNB_modify_dedicatedRRCConnectionReconfiguration(const protocol_ctxt_t *cons PDCP_rlc_AM = CALLOC(1, sizeof(*PDCP_rlc_AM)); DRB_pdcp_config->rlc_AM = PDCP_rlc_AM; - PDCP_rlc_AM->statusReportRequired = FALSE; + PDCP_rlc_AM->statusReportRequired = false; break; default : @@ -2951,7 +2951,7 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t #ifdef RRC_DEFAULT_RAB_IS_AM // EXMIMO_IOT PDCP_rlc_AM = CALLOC(1, sizeof(*PDCP_rlc_AM)); DRB_pdcp_config->rlc_AM = PDCP_rlc_AM; - PDCP_rlc_AM->statusReportRequired = FALSE; + PDCP_rlc_AM->statusReportRequired = false; #else PDCP_rlc_UM = CALLOC(1, sizeof(*PDCP_rlc_UM)); DRB_pdcp_config->rlc_UM = PDCP_rlc_UM; @@ -3347,7 +3347,7 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.triggerType.choice.event.eventId.present = LTE_ReportConfigInterRAT__triggerType__event__eventId_PR_eventB1_NR_r15; ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.triggerType.choice.event.eventId.choice.eventB1_NR_r15.b1_ThresholdNR_r15.present = LTE_ThresholdNR_r15_PR_nr_RSRP_r15; ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.triggerType.choice.event.eventId.choice.eventB1_NR_r15.b1_ThresholdNR_r15.choice.nr_RSRP_r15 = 0; - ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.triggerType.choice.event.eventId.choice.eventB1_NR_r15.reportOnLeave_r15 = FALSE; + ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.triggerType.choice.event.eventId.choice.eventB1_NR_r15.reportOnLeave_r15 = false; ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.triggerType.choice.event.hysteresis = 2; ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.triggerType.choice.event.timeToTrigger = LTE_TimeToTrigger_ms80; ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.maxReportCells = 4; @@ -3361,9 +3361,9 @@ void rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt_t if (ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.ext7->reportQuantityCellNR_r15 == NULL) exit(1); - ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.ext7->reportQuantityCellNR_r15->ss_rsrp = TRUE; - ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.ext7->reportQuantityCellNR_r15->ss_rsrq = TRUE; - ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.ext7->reportQuantityCellNR_r15->ss_sinr = TRUE; + ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.ext7->reportQuantityCellNR_r15->ss_rsrp = true; + ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.ext7->reportQuantityCellNR_r15->ss_rsrq = true; + ReportConfig_NR->reportConfig.choice.reportConfigInterRAT.ext7->reportQuantityCellNR_r15->ss_sinr = true; ASN_SEQUENCE_ADD(&ReportConfig_list->list, ReportConfig_NR); LOG_A(RRC, "Generating RRCCConnectionReconfigurationRequest (NRUE Measurement Report Request).\n"); } @@ -3714,7 +3714,7 @@ flexran_rrc_eNB_generate_defaultRRCConnectionReconfiguration(const protocol_ctxt #ifdef RRC_DEFAULT_RAB_IS_AM // EXMIMO_IOT PDCP_rlc_AM = CALLOC(1, sizeof(*PDCP_rlc_AM)); DRB_pdcp_config->rlc_AM = PDCP_rlc_AM; - PDCP_rlc_AM->statusReportRequired = FALSE; + PDCP_rlc_AM->statusReportRequired = 0; // FALSE #else PDCP_rlc_UM = CALLOC(1, sizeof(*PDCP_rlc_UM)); DRB_pdcp_config->rlc_UM = PDCP_rlc_UM; @@ -5052,7 +5052,7 @@ check_handovers( && ue_context_p->ue_context.handover_info != NULL && ue_context_p->ue_context.handover_info->forwarding_state == FORWARDING_NO_EMPTY ) { MessageDef *msg_p; - int result; + bool result; protocol_ctxt_t ctxt; do { @@ -5090,7 +5090,7 @@ check_handovers( GTPV1U_ENB_DATA_FORWARDING_IND (msg_p).mode, NULL, NULL ); - if (result != TRUE) { + if (result != true) { LOG_E(RRC, "target enb send data forwarding buffer to PDCP request failed!\n"); } else { LOG_D(RRC, "target enb send data forwarding buffer to PDCP!\n"); @@ -5158,7 +5158,7 @@ check_handovers( GTPV1U_ENB_END_MARKER_IND (msg_p).mode, NULL, NULL ); - if (result != TRUE) { + if (result != true) { LOG_E(RRC, "target enb send spgw buffer to PDCP request failed!\n"); } else { LOG_D(RRC, "target enb send spgw buffer to PDCP!\n"); @@ -5390,7 +5390,7 @@ rrc_eNB_generate_HO_RRCConnectionReconfiguration(const protocol_ctxt_t *const ct #ifdef RRC_DEFAULT_RAB_IS_AM // EXMIMO_IOT PDCP_rlc_AM = CALLOC(1, sizeof(*PDCP_rlc_AM)); DRB_pdcp_config->rlc_AM = PDCP_rlc_AM; - PDCP_rlc_AM->statusReportRequired = FALSE; + PDCP_rlc_AM->statusReportRequired = 0; // FALSE #else PDCP_rlc_UM = CALLOC(1, sizeof(*PDCP_rlc_UM)); DRB_pdcp_config->rlc_UM = PDCP_rlc_UM; @@ -6280,10 +6280,7 @@ rrc_eNB_configure_rbs_handover(struct rrc_eNB_ue_context_s *ue_context_p, protoc ctxt_pP, ue_context_p, ue_context_p->ue_context.kenb); - rrc_pdcp_config_security( - ctxt_pP, - ue_context_p, - FALSE); + rrc_pdcp_config_security(ctxt_pP, ue_context_p, false); } // Add a new user (called during the HO procedure) @@ -6361,9 +6358,9 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete( UE_sched_ctrl_t *UE_scheduling_control = &(RC.mac[module_id]->UE_info.UE_sched_ctrl[UE_id_mac]); - if (UE_scheduling_control->cdrx_waiting_ack == TRUE) { - UE_scheduling_control->cdrx_waiting_ack = FALSE; - UE_scheduling_control->cdrx_configured = TRUE; // Set to TRUE when RRC Connection Reconfiguration is received + if (UE_scheduling_control->cdrx_waiting_ack == true) { + UE_scheduling_control->cdrx_waiting_ack = false; + UE_scheduling_control->cdrx_configured = true; // Set to TRUE when RRC Connection Reconfiguration is received LOG_I(RRC, "CDRX configuration activated after RRC Connection Reconfiguration Complete reception\n"); } } @@ -6627,7 +6624,7 @@ rrc_eNB_generate_RRCConnectionSetup( ) //----------------------------------------------------------------------------- { - boolean_t is_mtc = ctxt_pP->brOption; + bool is_mtc = ctxt_pP->brOption; LTE_LogicalChannelConfig_t *SRB1_logicalChannelConfig; //,*SRB2_logicalChannelConfig; LTE_SRB_ToAddModList_t **SRB_configList; LTE_SRB_ToAddMod_t *SRB1_config; @@ -7284,7 +7281,7 @@ rrc_eNB_decode_ccch( LOG_E(RRC, "%s:%d:%s: rrc_eNB_get_next_free_ue_context returned NULL\n", __FILE__, __LINE__, __FUNCTION__); if (ue_context_p != NULL) { - ue_context_p->ue_context.Initialue_identity_s_TMSI.presence = TRUE; + ue_context_p->ue_context.Initialue_identity_s_TMSI.presence = true; ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code = mme_code; ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi = m_tmsi; } else { @@ -8766,7 +8763,7 @@ void rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { if ((ctxt_pP->frame&127) == 0 && ctxt_pP->subframe ==0) { if (fd) { - if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) { + if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == true) { fprintf(fd,"RRC UE rnti %x: S-TMSI %x failure timer %d/8\n", ue_context_p->ue_context.rnti, ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi, diff --git a/openair2/RRC/LTE/rrc_eNB_GTPV1U.c b/openair2/RRC/LTE/rrc_eNB_GTPV1U.c index 575a38ee3d..64b5594dd9 100644 --- a/openair2/RRC/LTE/rrc_eNB_GTPV1U.c +++ b/openair2/RRC/LTE/rrc_eNB_GTPV1U.c @@ -84,23 +84,20 @@ rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP( } //------------------------------------------------------------------------------ -boolean_t -gtpv_data_req( - const protocol_ctxt_t* const ctxt_pP, - const rb_id_t rb_idP, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_sizeP, - uint8_t* const buffer_pP, - const pdcp_transmission_mode_t modeP, - uint32_t task_id -) +bool gtpv_data_req(const protocol_ctxt_t* const ctxt_pP, + const rb_id_t rb_idP, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_sizeP, + uint8_t* const buffer_pP, + const pdcp_transmission_mode_t modeP, + uint32_t task_id) //------------------------------------------------------------------------------ { if(sdu_sizeP == 0) { LOG_I(GTPU,"gtpv_data_req sdu_sizeP == 0"); - return FALSE; + return false; } LOG_D(GTPU,"gtpv_data_req ue rnti %x sdu_sizeP %d rb id %ld", ctxt_pP->rnti, sdu_sizeP, rb_idP); MessageDef *message_p; @@ -129,7 +126,7 @@ gtpv_data_req( GTPV1U_ENB_DATA_FORWARDING_IND (message_p).eNB_index = ctxt_pP->eNB_index; itti_send_msg_to_task (TASK_DATA_FORWARDING, ctxt_pP->instance, message_p); - return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. + return true; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. } else if (task_id == TASK_END_MARKER){ LOG_I(GTPU,"gtpv_data_req task_id = TASK_END_MARKER\n"); @@ -152,23 +149,22 @@ gtpv_data_req( GTPV1U_ENB_END_MARKER_IND (message_p).eNB_index = ctxt_pP->eNB_index; itti_send_msg_to_task (TASK_END_MARKER, ctxt_pP->instance, message_p); - return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. + return true; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. } LOG_E(RRC, "Impossible state\n"); - return FALSE; + return false; } -boolean_t gtpv_data_req_new ( - protocol_ctxt_t *ctxt, - const srb_flag_t srb_flagP, - const rb_id_t rb_idP, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_sizeP, - unsigned char *const sdu_buffer_pP, - const pdcp_transmission_mode_t modeP, - const uint32_t *sourceL2Id, - const uint32_t *destinationL2Id) { +bool gtpv_data_req_new(protocol_ctxt_t *ctxt, + const srb_flag_t srb_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_sizeP, + unsigned char *const sdu_buffer_pP, + const pdcp_transmission_mode_t modeP, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id) { int task; if (sdu_buffer_sizeP==0) diff --git a/openair2/RRC/LTE/rrc_eNB_GTPV1U.h b/openair2/RRC/LTE/rrc_eNB_GTPV1U.h index ab789099ca..f991cbd5f6 100644 --- a/openair2/RRC/LTE/rrc_eNB_GTPV1U.h +++ b/openair2/RRC/LTE/rrc_eNB_GTPV1U.h @@ -60,16 +60,13 @@ void rrc_eNB_send_GTPV1U_ENB_DELETE_TUNNEL_REQ( rrc_eNB_ue_context_t* ue_context_pP ); -boolean_t -gtpv_data_req( - const protocol_ctxt_t* const ctxt_pP, - const rb_id_t rb_idP, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_sizeP, - uint8_t* const buffer_pP, - const pdcp_transmission_mode_t modeP, - uint32_t task_id -); +bool gtpv_data_req(const protocol_ctxt_t* const ctxt_pP, + const rb_id_t rb_idP, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_sizeP, + uint8_t* const buffer_pP, + const pdcp_transmission_mode_t modeP, + uint32_t task_id); #endif /* RRC_ENB_GTPV1U_H_ */ diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c index f24c9ab1b6..aefbc01831 100644 --- a/openair2/RRC/LTE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c @@ -402,15 +402,13 @@ static e_LTE_SecurityAlgorithmConfig__integrityProtAlgorithm rrc_eNB_select_inte *\param mod_id Instance ID of eNB. *\param ue_index Instance ID of UE in the eNB. *\param security_capabilities The security capabilities received from S1AP. - *\return TRUE if at least one algorithm has been changed else FALSE. + *\return true if at least one algorithm has been changed else false. */ int -rrc_eNB_process_security( - const protocol_ctxt_t *const ctxt_pP, - rrc_eNB_ue_context_t *const ue_context_pP, - security_capabilities_t *security_capabilities_pP -) { - boolean_t changed = FALSE; +rrc_eNB_process_security(const protocol_ctxt_t *const ctxt_pP, + rrc_eNB_ue_context_t *const ue_context_pP, + security_capabilities_t *security_capabilities_pP) { + bool changed = false; LTE_CipheringAlgorithm_r12_t cipheringAlgorithm; e_LTE_SecurityAlgorithmConfig__integrityProtAlgorithm integrityProtAlgorithm; /* Save security parameters */ @@ -428,14 +426,14 @@ rrc_eNB_process_security( if (ue_context_pP->ue_context.ciphering_algorithm != cipheringAlgorithm) { ue_context_pP->ue_context.ciphering_algorithm = cipheringAlgorithm; - changed = TRUE; + changed = true; } integrityProtAlgorithm = rrc_eNB_select_integrity (ue_context_pP->ue_context.security_capabilities.integrity_algorithms); if (ue_context_pP->ue_context.integrity_algorithm != integrityProtAlgorithm) { ue_context_pP->ue_context.integrity_algorithm = integrityProtAlgorithm; - changed = TRUE; + changed = true; } LOG_I (RRC, "[eNB %d][UE %x] Selected security algorithms (%p): %lx, %x, %s\n", @@ -532,7 +530,7 @@ rrc_pdcp_config_security( pdcp_p, DCCH, DCCH+2, - (send_security_mode_command == TRUE) ? + (send_security_mode_command == true) ? 0 | (ue_context_pP->ue_context.integrity_algorithm << 4) : (ue_context_pP->ue_context.ciphering_algorithm ) | (ue_context_pP->ue_context.integrity_algorithm << 4), @@ -960,12 +958,12 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char ue_context_p, S1AP_INITIAL_CONTEXT_SETUP_REQ(msg_p).security_key); { - uint8_t send_security_mode_command = TRUE; + uint8_t send_security_mode_command = true; #ifndef EXMIMO_IOT if ((ue_context_p->ue_context.ciphering_algorithm == SecurityAlgorithmConfig__cipheringAlgorithm_eea0) && (ue_context_p->ue_context.integrity_algorithm == INTEGRITY_ALGORITHM_NONE)) { - send_security_mode_command = FALSE; + send_security_mode_command = false; } #endif @@ -978,7 +976,7 @@ int rrc_eNB_process_S1AP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, const char rrc_eNB_generate_SecurityModeCommand ( &ctxt, ue_context_p); - send_security_mode_command = FALSE; + send_security_mode_command = false; // apply ciphering after RRC security command mode rrc_pdcp_config_security( &ctxt, @@ -1414,19 +1412,19 @@ int rrc_eNB_process_S1AP_E_RAB_MODIFY_REQ(MessageDef *msg_p, const char *msg_nam /* Save e RAB information for later */ { int j; - boolean_t is_treated[S1AP_MAX_E_RAB] = {FALSE}; + bool is_treated[S1AP_MAX_E_RAB] = {false}; uint8_t nb_of_failed_e_rabs = 0; // keep the previous bearer // the index for the rec for (i = 0; i < S1AP_E_RAB_MODIFY_REQ (msg_p).nb_e_rabs_tomodify; i++) { - if (is_treated[i] == TRUE) { + if (is_treated[i] == true) { // already treated continue; } for (j = i+1; j < S1AP_E_RAB_MODIFY_REQ (msg_p).nb_e_rabs_tomodify; j++) { - if (is_treated[j] == FALSE && + if (is_treated[j] == false && S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[j].e_rab_id == S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[i].e_rab_id) { // handle multiple E-RAB ID ue_context_p->ue_context.modify_e_rab[j].status = E_RAB_STATUS_NEW; @@ -1434,12 +1432,12 @@ int rrc_eNB_process_S1AP_E_RAB_MODIFY_REQ(MessageDef *msg_p, const char *msg_nam ue_context_p->ue_context.modify_e_rab[j].cause = S1AP_CAUSE_RADIO_NETWORK; ue_context_p->ue_context.modify_e_rab[j].cause_value = 31;//S1ap_CauseRadioNetwork_multiple_E_RAB_ID_instances; nb_of_failed_e_rabs++; - is_treated[i] = TRUE; - is_treated[j] = TRUE; + is_treated[i] = true; + is_treated[j] = true; } } - if (is_treated[i] == TRUE) { + if (is_treated[i] == true) { // handle multiple E-RAB ID ue_context_p->ue_context.modify_e_rab[i].status = E_RAB_STATUS_NEW; ue_context_p->ue_context.modify_e_rab[i].param.e_rab_id = S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[i].e_rab_id; @@ -1456,7 +1454,7 @@ int rrc_eNB_process_S1AP_E_RAB_MODIFY_REQ(MessageDef *msg_p, const char *msg_nam ue_context_p->ue_context.modify_e_rab[i].cause = S1AP_CAUSE_NAS; ue_context_p->ue_context.modify_e_rab[i].cause_value = 3;//S1ap_CauseNas_unspecified; nb_of_failed_e_rabs++; - is_treated[i] = TRUE; + is_treated[i] = true; continue; } @@ -1474,19 +1472,19 @@ int rrc_eNB_process_S1AP_E_RAB_MODIFY_REQ(MessageDef *msg_p, const char *msg_nam ue_context_p->ue_context.modify_e_rab[i].param.nas_pdu.buffer = S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[i].nas_pdu.buffer; ue_context_p->ue_context.modify_e_rab[i].param.sgw_addr = ue_context_p->ue_context.e_rab[j].param.sgw_addr; ue_context_p->ue_context.modify_e_rab[i].param.gtp_teid = ue_context_p->ue_context.e_rab[j].param.gtp_teid; - is_treated[i] = TRUE; + is_treated[i] = true; break; } } - if (is_treated[i] == FALSE) { + if (is_treated[i] == false) { // handle Unknown E-RAB ID ue_context_p->ue_context.modify_e_rab[i].status = E_RAB_STATUS_NEW; ue_context_p->ue_context.modify_e_rab[i].param.e_rab_id = S1AP_E_RAB_MODIFY_REQ(msg_p).e_rab_modify_params[i].e_rab_id; ue_context_p->ue_context.modify_e_rab[i].cause = S1AP_CAUSE_RADIO_NETWORK; ue_context_p->ue_context.modify_e_rab[i].cause_value = 30;//S1ap_CauseRadioNetwork_unknown_E_RAB_ID; nb_of_failed_e_rabs++; - is_treated[i] = TRUE; + is_treated[i] = true; } } @@ -1824,8 +1822,8 @@ int rrc_eNB_process_PAGING_IND(MessageDef *msg_p, const char *msg_name, instance uint8_t i = 0; for (i = 0; i < MAX_MOBILES_PER_ENB; i++) { - if ((UE_PF_PO[CC_id][i].enable_flag == TRUE && UE_PF_PO[CC_id][i].ue_index_value == (uint16_t)(S1AP_PAGING_IND(msg_p).ue_index_value)) - || (UE_PF_PO[CC_id][i].enable_flag != TRUE)) { + if ((UE_PF_PO[CC_id][i].enable_flag == true && UE_PF_PO[CC_id][i].ue_index_value == (uint16_t)(S1AP_PAGING_IND(msg_p).ue_index_value)) + || (UE_PF_PO[CC_id][i].enable_flag != true)) { /* set T = min(Tc,Tue) */ UE_PF_PO[CC_id][i].T = T; /* set UE_ID */ @@ -1845,12 +1843,12 @@ int rrc_eNB_process_PAGING_IND(MessageDef *msg_p, const char *msg_name, instance UE_PF_PO[CC_id][i].PO = (frame_type==FDD) ? (4*(i_s&1)+(5*(i_s>>1))) : ((i_s&1)+(5*(i_s>>1))); } - if (UE_PF_PO[CC_id][i].enable_flag == TRUE) { + if (UE_PF_PO[CC_id][i].enable_flag == true) { //paging exist UE log LOG_D(RRC,"[eNB %ld] CC_id %d In S1AP_PAGING_IND: Update exist UE %d, T %d, PF %d, PO %d\n", instance, CC_id, UE_PF_PO[CC_id][i].ue_index_value, T, UE_PF_PO[CC_id][i].PF_min, UE_PF_PO[CC_id][i].PO); } else { /* set enable_flag */ - UE_PF_PO[CC_id][i].enable_flag = TRUE; + UE_PF_PO[CC_id][i].enable_flag = true; //paging new UE log LOG_D(RRC,"[eNB %ld] CC_id %d In S1AP_PAGING_IND: Insert a new UE %d, T %d, PF %d, PO %d\n", instance, CC_id, UE_PF_PO[CC_id][i].ue_index_value, T, UE_PF_PO[CC_id][i].PF_min, UE_PF_PO[CC_id][i].PO); } diff --git a/openair2/RRC/LTE/rrc_proto.h b/openair2/RRC/LTE/rrc_proto.h index f0456005f5..7bd3fbf758 100644 --- a/openair2/RRC/LTE/rrc_proto.h +++ b/openair2/RRC/LTE/rrc_proto.h @@ -457,7 +457,7 @@ mac_rrc_data_ind( const uint8_t *sduP, const sdu_size_t sdu_lenP, const uint8_t mbsfn_sync_areaP, - const boolean_t brOption + const bool brOption ); int8_t @@ -685,7 +685,7 @@ extern RRC_release_list_t rrc_release_info; extern pthread_mutex_t lock_ue_freelist; void remove_UE_from_freelist(module_id_t mod_id, rnti_t rnti); -void put_UE_in_freelist(module_id_t mod_id, rnti_t rnti, boolean_t removeFlag); +void put_UE_in_freelist(module_id_t mod_id, rnti_t rnti, bool removeFlag); void release_UE_in_freeList(module_id_t mod_id); /** @}*/ diff --git a/openair2/RRC/NR/L2_nr_interface.c b/openair2/RRC/NR/L2_nr_interface.c index 161d1cd847..6fc0566cbd 100644 --- a/openair2/RRC/NR/L2_nr_interface.c +++ b/openair2/RRC/NR/L2_nr_interface.c @@ -168,7 +168,7 @@ nr_rrc_data_req( { if(sdu_sizeP == 255) { LOG_D(RRC,"sdu_sizeP == 255"); - return FALSE; + return false; } MessageDef *message_p; @@ -204,7 +204,7 @@ nr_rrc_data_req( if (ctxt_pP->enb_flag && NODE_IS_CU(RC.nrrrc[ctxt_pP->module_id]->node_type)) pdcp_run(ctxt_pP); - return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. + return true; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. } uint16_t mac_rrc_nr_data_req(const module_id_t Mod_idP, @@ -315,7 +315,7 @@ int8_t nr_mac_rrc_data_ind(const module_id_t module_idP, const rb_id_t srb_idP, const uint8_t *sduP, const sdu_size_t sdu_lenP, - const boolean_t brOption) { + const bool brOption) { if (NODE_IS_DU(RC.nrrrc[module_idP]->node_type)) { LOG_W(RRC,"[DU %d][RAPROC] Received SDU for CCCH on SRB %ld length %d for UE id %d RNTI %x \n", diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 3488080f27..1b322ed925 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -173,7 +173,7 @@ typedef struct UE_RRC_INFO_NR_s { } __attribute__ ((__packed__)) NR_UE_RRC_INFO; typedef struct UE_S_TMSI_NR_s { - boolean_t presence; + bool presence; uint16_t amf_set_id; uint8_t amf_pointer; uint32_t fiveg_tmsi; diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index d569b91aa8..dc6e14215f 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -174,18 +174,16 @@ int8_t nr_mac_rrc_bwp_switch_req(const module_id_t module_idP, const int dl_bwp_id, const int ul_bwp_id); -int8_t nr_mac_rrc_data_ind( - const module_id_t module_idP, - const int CC_id, - const frame_t frameP, - const sub_frame_t sub_frameP, - const int UE_id, - const rnti_t rntiP, - const rb_id_t srb_idP, - const uint8_t *sduP, - const sdu_size_t sdu_lenP, - const boolean_t brOption -); +int8_t nr_mac_rrc_data_ind(const module_id_t module_idP, + const int CC_id, + const frame_t frameP, + const sub_frame_t sub_frameP, + const int UE_id, + const rnti_t rntiP, + const rb_id_t srb_idP, + const uint8_t *sduP, + const sdu_size_t sdu_lenP, + const bool brOption); int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP, protocol_ctxt_t *const ctxt_pP, @@ -219,16 +217,15 @@ rlc_op_status_t nr_rrc_rlc_config_asn1_req (const protocol_ctxt_t * const ctxt const LTE_PMCH_InfoList_r9_t * const pmch_InfoList_r9_pP, struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); -boolean_t nr_rrc_pdcp_config_asn1_req( - const protocol_ctxt_t *const ctxt_pP, - NR_SRB_ToAddModList_t *const srb2add_list, - NR_DRB_ToAddModList_t *const drb2add_list, - NR_DRB_ToReleaseList_t *const drb2release_list, - const uint8_t security_modeP, - uint8_t *const kRRCenc, - uint8_t *const kRRCint, - uint8_t *const kUPenc, - uint8_t *const kUPint - ,LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9 - ,rb_id_t *const defaultDRB, - struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); +bool nr_rrc_pdcp_config_asn1_req(const protocol_ctxt_t *const ctxt_pP, + NR_SRB_ToAddModList_t *const srb2add_list, + NR_DRB_ToAddModList_t *const drb2add_list, + NR_DRB_ToReleaseList_t *const drb2release_list, + const uint8_t security_modeP, + uint8_t *const kRRCenc, + uint8_t *const kRRCint, + uint8_t *const kUPenc, + uint8_t *const kUPint, + LTE_PMCH_InfoList_r9_t *pmch_InfoList_r9, + rb_id_t *const defaultDRB, + struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 3d95081336..43082003df 100755 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -116,16 +116,16 @@ uint8_t first_rrcreconfiguration = 0; ///---------------------------------------------------------------------------------------------------------------/// ///---------------------------------------------------------------------------------------------------------------/// -boolean_t DURecvCb( protocol_ctxt_t *ctxt_pP, - const srb_flag_t srb_flagP, - const rb_id_t rb_idP, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_sizeP, - unsigned char *const sdu_buffer_pP, - const pdcp_transmission_mode_t modeP, - const uint32_t *sourceL2Id, - const uint32_t *destinationL2Id) { +bool DURecvCb(protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_sizeP, + unsigned char *const sdu_buffer_pP, + const pdcp_transmission_mode_t modeP, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id) { // The buffer comes from the stack in gtp-u thread, we have a make a separate buffer to enqueue in a inter-thread message queue mem_block_t *sdu=get_free_mem_block(sdu_buffer_sizeP, __func__); memcpy(sdu->data, sdu_buffer_pP, sdu_buffer_sizeP); @@ -917,7 +917,7 @@ rrc_gNB_generate_dedicatedRRCReconfiguration( sdap_config->sdap_HeaderDL = NR_SDAP_Config__sdap_HeaderDL_absent; sdap_config->sdap_HeaderUL = NR_SDAP_Config__sdap_HeaderUL_absent; } - sdap_config->defaultDRB = TRUE; + sdap_config->defaultDRB = true; sdap_config->mappedQoS_FlowsToAdd = calloc(1, sizeof(struct NR_SDAP_Config__mappedQoS_FlowsToAdd)); memset(sdap_config->mappedQoS_FlowsToAdd, 0, sizeof(struct NR_SDAP_Config__mappedQoS_FlowsToAdd)); @@ -1826,7 +1826,7 @@ rrc_gNB_process_RRCConnectionReestablishmentComplete( ue_context_pP->ue_context.rnti = ctxt_pP->rnti; if (AMF_MODE_ENABLED) { - uint8_t send_security_mode_command = FALSE; + uint8_t send_security_mode_command = false; nr_rrc_pdcp_config_security( ctxt_pP, ue_context_pP, @@ -2113,7 +2113,7 @@ int nr_rrc_gNB_decode_ccch(protocol_ctxt_t *const ctxt_pP, } if (ue_context_p != NULL) { - ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.presence = TRUE; + ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.presence = true; ue_context_p->ue_context.ng_5G_S_TMSI_Part1 = s_tmsi_part1; } } @@ -2590,7 +2590,7 @@ rrc_gNB_decode_dcch( fiveg_s_TMSI, fiveg_s_TMSI >> 38, fiveg_s_TMSI >> 38, (fiveg_s_TMSI >> 32) & 0x3F, (fiveg_s_TMSI >> 32) & 0x3F, (uint32_t)fiveg_s_TMSI); - if (ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.presence == TRUE) { + if (ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.presence == true) { ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.amf_set_id = fiveg_s_TMSI >> 38; ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.amf_pointer = (fiveg_s_TMSI >> 32) & 0x3F; ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.fiveg_tmsi = (uint32_t)fiveg_s_TMSI; @@ -3235,7 +3235,6 @@ static int rrc_process_DU_DL(MessageDef *msg_p, const char *msg_name, instance_ LOG_I(F1AP, "Received DL RRC Transfer on srb_id %ld\n", req->srb_id); // rlc_op_status_t rlc_status; - // boolean_t ret = TRUE; //LOG_I(F1AP, "PRRCContainer size %lu:", ie->value.choice.RRCContainer.size); //for (int i = 0; i < ie->value.choice.RRCContainer.size; i++) @@ -3260,23 +3259,23 @@ static int rrc_process_DU_DL(MessageDef *msg_p, const char *msg_name, instance_ // switch (rlc_status) { // case RLC_OP_STATUS_OK: // //LOG_I(F1AP, "Data sending request over RLC succeeded!\n"); - // ret=TRUE; + // ret=true; // break; // case RLC_OP_STATUS_BAD_PARAMETER: // LOG_W(F1AP, "Data sending request over RLC failed with 'Bad Parameter' reason!\n"); - // ret= FALSE; + // ret= false; // break; // case RLC_OP_STATUS_INTERNAL_ERROR: // LOG_W(F1AP, "Data sending request over RLC failed with 'Internal Error' reason!\n"); - // ret= FALSE; + // ret= false; // break; // case RLC_OP_STATUS_OUT_OF_RESSOURCES: // LOG_W(F1AP, "Data sending request over RLC failed with 'Out of Resources' reason!\n"); - // ret= FALSE; + // ret= false; // break; // default: // LOG_W(F1AP, "RLC returned an unknown status code after PDCP placed the order to send some data (Status Code:%d)\n", rlc_status); - // ret= FALSE; + // ret= false; // break; // } // switch case // return ret; @@ -3940,7 +3939,7 @@ void nr_rrc_subframe_process(protocol_ctxt_t *const ctxt_pP, const int CC_id) { gNB_MAC_INST *nrmac=RC.nrmac[ctxt_pP->module_id]; //WHAT A BEAUTIFULL RACE CONDITION !!! if (fd) { - if (ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.presence == TRUE) { + if (ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.presence == true) { fprintf(fd,"NR RRC UE rnti %x: S-TMSI %x failure timer %d/8\n", ue_context_p->ue_id_rnti, ue_context_p->ue_context.Initialue_identity_5g_s_TMSI.fiveg_tmsi, diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 0dcd064663..6663ddea85 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -708,7 +708,7 @@ rrc_gNB_process_security( rrc_gNB_ue_context_t *const ue_context_pP, ngap_security_capabilities_t *security_capabilities_pP ) { - boolean_t changed = FALSE; + bool changed = false; NR_CipheringAlgorithm_t cipheringAlgorithm; e_NR_IntegrityProtAlgorithm integrityProtAlgorithm; /* Save security parameters */ @@ -726,14 +726,14 @@ rrc_gNB_process_security( if (ue_context_pP->ue_context.ciphering_algorithm != cipheringAlgorithm) { ue_context_pP->ue_context.ciphering_algorithm = cipheringAlgorithm; - changed = TRUE; + changed = true; } integrityProtAlgorithm = rrc_gNB_select_integrity(ctxt_pP, ue_context_pP->ue_context.security_capabilities.nRintegrity_algorithms); if (ue_context_pP->ue_context.integrity_algorithm != integrityProtAlgorithm) { ue_context_pP->ue_context.integrity_algorithm = integrityProtAlgorithm; - changed = TRUE; + changed = true; } LOG_I (NR_RRC, "[gNB %d][UE %x] Selected security algorithms (%p): %lx, %x, %s\n", @@ -1126,17 +1126,17 @@ rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ( ue_context_p->ue_context.gNB_ue_ngap_id = gNB_ue_ngap_id; { int j; - boolean_t is_treated[NGAP_MAX_PDUSESSION] = {FALSE}; + bool is_treated[NGAP_MAX_PDUSESSION] = {false}; uint8_t nb_of_failed_pdusessions = 0; for (i = 0; i < nb_pdusessions_tomodify; i++) { - if (is_treated[i] == TRUE) { + if (is_treated[i] == true) { continue; } //Check if same PDU session ID to handle multiple pdu sessions for (j = i+1; j < nb_pdusessions_tomodify; j++) { - if (is_treated[j] == FALSE && + if (is_treated[j] == false && NGAP_PDUSESSION_MODIFY_REQ(msg_p).pdusession_modify_params[j].pdusession_id == NGAP_PDUSESSION_MODIFY_REQ(msg_p).pdusession_modify_params[i].pdusession_id) { // handle multiple pdu session id @@ -1147,12 +1147,12 @@ rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ( ue_context_p->ue_context.modify_pdusession[j].cause = NGAP_CAUSE_RADIO_NETWORK; ue_context_p->ue_context.modify_pdusession[j].cause_value = NGAP_CauseRadioNetwork_multiple_PDU_session_ID_instances; nb_of_failed_pdusessions++; - is_treated[i] = TRUE; - is_treated[j] = TRUE; + is_treated[i] = true; + is_treated[j] = true; } } // handle multiple pdu session id case - if (is_treated[i] == TRUE) { + if (is_treated[i] == true) { LOG_D(NR_RRC, "handle multiple pdu session id \n"); ue_context_p->ue_context.modify_pdusession[i].status = PDU_SESSION_STATUS_NEW; ue_context_p->ue_context.modify_pdusession[i].param.pdusession_id = @@ -1195,13 +1195,13 @@ rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ( ue_context_p->ue_context.modify_pdusession[i].param.gtp_teid = ue_context_p->ue_context.pduSession[j].param.gtp_teid; - is_treated[i] = TRUE; + is_treated[i] = true; break; } } // handle Unknown pdu session ID - if (is_treated[i] == FALSE) { + if (is_treated[i] == false) { LOG_D(NR_RRC, "handle Unknown pdu session ID \n"); ue_context_p->ue_context.modify_pdusession[i].status = PDU_SESSION_STATUS_NEW; ue_context_p->ue_context.modify_pdusession[i].param.pdusession_id = @@ -1209,7 +1209,7 @@ rrc_gNB_process_NGAP_PDUSESSION_MODIFY_REQ( ue_context_p->ue_context.modify_pdusession[i].cause = NGAP_CAUSE_RADIO_NETWORK; ue_context_p->ue_context.modify_pdusession[i].cause_value = NGAP_CauseRadioNetwork_unknown_PDU_session_ID; nb_of_failed_pdusessions++; - is_treated[i] = TRUE; + is_treated[i] = true; } } diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index 6f0c7fc27f..b4508e2627 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -181,6 +181,6 @@ rrc_data_req_nr_ue( TASK_PDCP_UE, ctxt_pP->instance, message_p); - return TRUE; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. + return true; // TODO should be changed to a CNF message later, currently RRC lite does not used the returned value anyway. } diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 50ec32772d..078f7f51a1 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -2014,7 +2014,7 @@ nr_rrc_ue_establish_srb2( int i, cnt; if( radioBearerConfig->srb3_ToRelease != NULL){ - if( *radioBearerConfig->srb3_ToRelease == TRUE){ + if( *radioBearerConfig->srb3_ToRelease == true){ //TODO (release the PDCP entity and the srb-Identity of the SRB3.) } } diff --git a/openair2/SDAP/nr_sdap/nr_sdap.c b/openair2/SDAP/nr_sdap/nr_sdap.c index 74ef93aff7..dd7a76920d 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap.c +++ b/openair2/SDAP/nr_sdap/nr_sdap.c @@ -21,19 +21,19 @@ #include "nr_sdap.h" -boolean_t sdap_data_req(protocol_ctxt_t *ctxt_p, - const srb_flag_t srb_flag, - const rb_id_t rb_id, - const mui_t mui, - const confirm_t confirm, - const sdu_size_t sdu_buffer_size, - unsigned char *const sdu_buffer, - const pdcp_transmission_mode_t pt_mode, - const uint32_t *sourceL2Id, - const uint32_t *destinationL2Id, - const uint8_t qfi, - const boolean_t rqi, - const int pdusession_id) { +bool sdap_data_req(protocol_ctxt_t *ctxt_p, + const srb_flag_t srb_flag, + const rb_id_t rb_id, + const mui_t mui, + const confirm_t confirm, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t pt_mode, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id, + const uint8_t qfi, + const bool rqi, + const int pdusession_id) { nr_sdap_entity_t *sdap_entity; sdap_entity = nr_sdap_get_entity(ctxt_p->rnti, pdusession_id); @@ -42,19 +42,19 @@ boolean_t sdap_data_req(protocol_ctxt_t *ctxt_p, return 0; } - boolean_t ret = sdap_entity->tx_entity(sdap_entity, - ctxt_p, - srb_flag, - rb_id, - mui, - confirm, - sdu_buffer_size, - sdu_buffer, - pt_mode, - sourceL2Id, - destinationL2Id, - qfi, - rqi); + bool ret = sdap_entity->tx_entity(sdap_entity, + ctxt_p, + srb_flag, + rb_id, + mui, + confirm, + sdu_buffer_size, + sdu_buffer, + pt_mode, + sourceL2Id, + destinationL2Id, + qfi, + rqi); return ret; } diff --git a/openair2/SDAP/nr_sdap/nr_sdap.h b/openair2/SDAP/nr_sdap/nr_sdap.h index cd702cfd7f..5959ca1558 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap.h +++ b/openair2/SDAP/nr_sdap/nr_sdap.h @@ -32,20 +32,19 @@ * Downlink - gNB * Uplink - nrUE */ -boolean_t sdap_data_req(protocol_ctxt_t *ctxt_p, - const srb_flag_t srb_flag, - const rb_id_t rb_id, - const mui_t mui, - const confirm_t confirm, - const sdu_size_t sdu_buffer_size, - unsigned char *const sdu_buffer, - const pdcp_transmission_mode_t pt_mode, - const uint32_t *sourceL2Id, - const uint32_t *destinationL2Id, - const uint8_t qfi, - const boolean_t rqi, - const int pdusession_id - ); +bool sdap_data_req(protocol_ctxt_t *ctxt_p, + const srb_flag_t srb_flag, + const rb_id_t rb_id, + const mui_t mui, + const confirm_t confirm, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t pt_mode, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id, + const uint8_t qfi, + const bool rqi, + const int pdusession_id); /* * TS 37.324 4.4 Functions diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index 79532748d2..5e3627296c 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -46,23 +46,22 @@ void nr_pdcp_submit_sdap_ctrl_pdu(int rnti, rb_id_t sdap_ctrl_pdu_drb, nr_sdap_u return; } -static boolean_t nr_sdap_tx_entity(nr_sdap_entity_t *entity, - protocol_ctxt_t *ctxt_p, - const srb_flag_t srb_flag, - const rb_id_t rb_id, - const mui_t mui, - const confirm_t confirm, - const sdu_size_t sdu_buffer_size, - unsigned char *const sdu_buffer, - const pdcp_transmission_mode_t pt_mode, - const uint32_t *sourceL2Id, - const uint32_t *destinationL2Id, - const uint8_t qfi, - const boolean_t rqi - ) { +static bool nr_sdap_tx_entity(nr_sdap_entity_t *entity, + protocol_ctxt_t *ctxt_p, + const srb_flag_t srb_flag, + const rb_id_t rb_id, + const mui_t mui, + const confirm_t confirm, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t pt_mode, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id, + const uint8_t qfi, + const bool rqi) { /* The offset of the SDAP header, it might be 0 if the has_sdap is not true in the pdcp entity. */ int offset=0; - boolean_t ret=false; + bool ret = false; /*Hardcode DRB ID given from upper layer (ue/enb_tun_read_thread rb_id), it will change if we have SDAP*/ rb_id_t sdap_drb_id = rb_id; int pdcp_ent_has_sdap = 0; @@ -297,7 +296,7 @@ static void nr_sdap_rx_entity(nr_sdap_entity_t *entity, } } -void nr_sdap_qfi2drb_map_update(nr_sdap_entity_t *entity, uint8_t qfi, rb_id_t drb, boolean_t hasSdap){ +void nr_sdap_qfi2drb_map_update(nr_sdap_entity_t *entity, uint8_t qfi, rb_id_t drb, bool hasSdap) { if(qfi < SDAP_MAX_QFI && qfi > SDAP_MAP_RULE_EMPTY && drb > 0 && @@ -390,7 +389,7 @@ void nr_sdap_ue_qfi2drb_config(nr_sdap_entity_t *existing_sdap_entity, nr_sdap_entity_t *new_nr_sdap_entity(int has_sdap, uint16_t rnti, int pdusession_id, - boolean_t is_defaultDRB, + bool is_defaultDRB, uint8_t drb_identity, NR_QFI_t *mapped_qfi_2_add, uint8_t mappedQFIs2AddCount) diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.h b/openair2/SDAP/nr_sdap/nr_sdap_entity.h index b46e5bf4e3..635289d4d4 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.h +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.h @@ -64,7 +64,7 @@ typedef struct nr_sdap_ul_hdr_s { typedef struct qfi2drb_s { rb_id_t drb_id; - boolean_t hasSdap; + bool hasSdap; } qfi2drb_t; void nr_pdcp_submit_sdap_ctrl_pdu(int rnti, rb_id_t sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu); @@ -75,7 +75,7 @@ typedef struct nr_sdap_entity_s { int pdusession_id; qfi2drb_t qfi2drb_table[SDAP_MAX_QFI]; - void (*qfi2drb_map_update)(struct nr_sdap_entity_s *entity, uint8_t qfi, rb_id_t drb, boolean_t hasSdap); + void (*qfi2drb_map_update)(struct nr_sdap_entity_s *entity, uint8_t qfi, rb_id_t drb, bool hasSdap); void (*qfi2drb_map_delete)(struct nr_sdap_entity_s *entity, uint8_t qfi); rb_id_t (*qfi2drb_map)(struct nr_sdap_entity_s *entity, uint8_t qfi, rb_id_t upper_layer_rb_id); @@ -84,20 +84,19 @@ typedef struct nr_sdap_entity_s { void (*sdap_submit_ctrl_pdu)(int rnti, rb_id_t sdap_ctrl_pdu_drb, nr_sdap_ul_hdr_t ctrl_pdu); - boolean_t (*tx_entity)(struct nr_sdap_entity_s *entity, - protocol_ctxt_t *ctxt_p, - const srb_flag_t srb_flag, - const rb_id_t rb_id, - const mui_t mui, - const confirm_t confirm, - const sdu_size_t sdu_buffer_size, - unsigned char *const sdu_buffer, - const pdcp_transmission_mode_t pt_mode, - const uint32_t *sourceL2Id, - const uint32_t *destinationL2Id, - const uint8_t qfi, - const boolean_t rqi - ); + bool (*tx_entity)(struct nr_sdap_entity_s *entity, + protocol_ctxt_t *ctxt_p, + const srb_flag_t srb_flag, + const rb_id_t rb_id, + const mui_t mui, + const confirm_t confirm, + const sdu_size_t sdu_buffer_size, + unsigned char *const sdu_buffer, + const pdcp_transmission_mode_t pt_mode, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id, + const uint8_t qfi, + const bool rqi); void (*rx_entity)(struct nr_sdap_entity_s *entity, rb_id_t pdcp_entity, @@ -114,7 +113,7 @@ typedef struct nr_sdap_entity_s { } nr_sdap_entity_t; /* QFI to DRB Mapping Related Function */ -void nr_sdap_qfi2drb_map_update(nr_sdap_entity_t *entity, uint8_t qfi, rb_id_t drb, boolean_t hasSdap); +void nr_sdap_qfi2drb_map_update(nr_sdap_entity_t *entity, uint8_t qfi, rb_id_t drb, bool hasSdap); /* QFI to DRB Mapping Related Function */ void nr_sdap_qfi2drb_map_del(nr_sdap_entity_t *entity, uint8_t qfi); @@ -168,7 +167,7 @@ void nr_sdap_ue_qfi2drb_config(nr_sdap_entity_t *existing_sdap_entity, nr_sdap_entity_t *new_nr_sdap_entity(int has_sdap, uint16_t rnti, int pdusession_id, - boolean_t is_defaultDRB, + bool is_defaultDRB, uint8_t default_DRB, NR_QFI_t *mapped_qfi_2_add, uint8_t mappedQFIs2AddCount); diff --git a/openair2/X2AP/x2ap_common.h b/openair2/X2AP/x2ap_common.h index a2f903a737..7dd88ffa21 100644 --- a/openair2/X2AP/x2ap_common.h +++ b/openair2/X2AP/x2ap_common.h @@ -52,11 +52,6 @@ # define X2AP_PORT 36422 #endif -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - extern int asn1_xer_print; #if defined(ENB_MODE) diff --git a/openair3/M3AP/m3ap_common.h b/openair3/M3AP/m3ap_common.h index 7f68510314..c5f55bc70a 100644 --- a/openair3/M3AP/m3ap_common.h +++ b/openair3/M3AP/m3ap_common.h @@ -52,11 +52,6 @@ # define M3AP_PORT 36444 #endif -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - extern int asn1_xer_print; #if defined(ENB_MODE) diff --git a/openair3/NAS/COMMON/UTIL/nas_timer.c b/openair3/NAS/COMMON/UTIL/nas_timer.c index 8448d9a78c..b67a3bc232 100644 --- a/openair3/NAS/COMMON/UTIL/nas_timer.c +++ b/openair3/NAS/COMMON/UTIL/nas_timer.c @@ -121,7 +121,7 @@ static nas_timer_database_t _nas_timer_db = { static void _nas_timer_db_init(void); static int _nas_timer_db_get_id(void); -static int _nas_timer_db_is_active(int id); +static bool _nas_timer_db_is_active(int id); static nas_timer_entry_t *_nas_timer_db_create_entry(long sec, nas_timer_callback_t cb, void *args); static void _nas_timer_db_delete_entry(int id); @@ -130,7 +130,7 @@ static void _nas_timer_db_insert_entry(int id, nas_timer_entry_t *te); static int _nas_timer_db_insert(timer_queue_t *entry); static nas_timer_entry_t *_nas_timer_db_remove_entry(int id); -static int _nas_timer_db_remove(timer_queue_t *entry); +static bool _nas_timer_db_remove(timer_queue_t *entry); /* * ----------------------------------------------------------------------------- @@ -408,12 +408,12 @@ static int _nas_timer_db_get_id(void) ** Others: _nas_timer_db ** ** ** ** Outputs: None ** - ** Return: TRUE if the timer entry is active; FALSE ** + ** Return: true if the timer entry is active; false ** ** if it is not an active timer entry. ** ** Others: None ** ** ** ***************************************************************************/ -static int _nas_timer_db_is_active(int id) +static bool _nas_timer_db_is_active(int id) { return ( (id != NAS_TIMER_INACTIVE_ID) && (_nas_timer_db.tq[id].id != NAS_TIMER_INACTIVE_ID) ); @@ -562,11 +562,11 @@ static int _nas_timer_db_insert(timer_queue_t *entry) } else { /* The new entry is the first entry of the list */ _nas_timer_db.head = entry; - return TRUE; + return true; } /* The new entry is NOT the first entry of the list */ - return FALSE; + return false; } /**************************************************************************** @@ -588,7 +588,7 @@ static int _nas_timer_db_insert(timer_queue_t *entry) ***************************************************************************/ static nas_timer_entry_t *_nas_timer_db_remove_entry(int id) { - int restart; + bool restart; /* The identifier of the timer is valid within the timer queue */ assert(_nas_timer_db.tq[id].id == id); @@ -622,7 +622,7 @@ static nas_timer_entry_t *_nas_timer_db_remove_entry(int id) return (_nas_timer_db.tq[id].entry); } -static int _nas_timer_db_remove(timer_queue_t *entry) +static bool _nas_timer_db_remove(timer_queue_t *entry) { /* Update the pointer from the previous entry */ /* prev ---> entry ---> next */ @@ -644,12 +644,12 @@ static int _nas_timer_db_remove(timer_queue_t *entry) if (_nas_timer_db.head != NULL) { /* Other timers are scheduled to expire */ - return TRUE; + return true; } } /* The entry was NOT the first entry of the list */ - return FALSE; + return false; } /* diff --git a/openair3/NAS/COMMON/UTIL/socket.c b/openair3/NAS/COMMON/UTIL/socket.c index 53a6ec8823..20c071203d 100644 --- a/openair3/NAS/COMMON/UTIL/socket.c +++ b/openair3/NAS/COMMON/UTIL/socket.c @@ -397,7 +397,7 @@ static int _socket_set_option(int sfd) * and it will simply open another socket on the same port and * continue listening. */ - optval = TRUE; + optval = true; if (setsockopt (sfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) { return RETURNerror; @@ -405,12 +405,12 @@ static int _socket_set_option(int sfd) /* IPV6_V6ONLY socket option * ------------------------- - * When option is set to TRUE, the socket is restricted to sending and + * When option is set to true, the socket is restricted to sending and * receiving IPv6 packets only. - * When option is set to FALSE, the socket can be used to send and receive + * When option is set to false, the socket can be used to send and receive * packets to and from an IPv6 address or an IPv4-mapped IPv6 address. */ - optval = FALSE; + optval = false; if (setsockopt (sfd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)) < 0) { return RETURNerror; diff --git a/openair3/NAS/COMMON/UTIL/stty.c b/openair3/NAS/COMMON/UTIL/stty.c index eceb0b06b1..fe87a63e44 100644 --- a/openair3/NAS/COMMON/UTIL/stty.c +++ b/openair3/NAS/COMMON/UTIL/stty.c @@ -192,7 +192,7 @@ static sttyset_t stty_params[] = { { NULL, 0, 0, 0 } }; -static int _stty_set_this(struct termios *term, const sttyset_t *p, int turnon); +static int _stty_set_this(struct termios *term, const sttyset_t *p, bool turnon); /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ @@ -207,7 +207,7 @@ static int _stty_set_this(struct termios *term, const sttyset_t *p, int turnon); ** ** ** Inputs: p: The TTY parameters ** ** turnon: Indicate whether the parameter should be ** - ** turned on (TRUE) or turned off (FALSE) ** + ** turned on (true) or turned off (false) ** ** Others: None ** ** ** ** Outputs: term: The termios structure to fill ** @@ -223,7 +223,7 @@ int stty_set(int fd, const char *params) register char *s; struct termios term; register int i; - int mode; + bool mode; /* Get current tty attributes */ if ( tcgetattr(fd, &term) < 0 ) { @@ -234,10 +234,10 @@ int stty_set(int fd, const char *params) p = strtok(s," \t\n"); while (p && (rc != RETURNerror)) { - mode = 1; + mode = true; if ( *p == '-' ) { - mode = 0; + mode = false; p++; } @@ -275,7 +275,7 @@ int stty_set(int fd, const char *params) ** ** ** Inputs: p: The TTY parameters ** ** turnon: Indicate whether the parameter should be ** - ** turned on (TRUE) or turned off (FALSE) ** + ** turned on (true) or turned off (false) ** ** Others: None ** ** ** ** Outputs: term: The termios structure to fill ** @@ -283,7 +283,7 @@ int stty_set(int fd, const char *params) ** Others: None ** ** ** ***************************************************************************/ -static int _stty_set_this(struct termios *term, const sttyset_t *p, int turnon) +static int _stty_set_this(struct termios *term, const sttyset_t *p, bool turnon) { int rc = RETURNok; diff --git a/openair3/NAS/TEST/AS_SIMULATOR/as_simulator.c b/openair3/NAS/TEST/AS_SIMULATOR/as_simulator.c index bbc37d18a3..387c3de3a8 100644 --- a/openair3/NAS/TEST/AS_SIMULATOR/as_simulator.c +++ b/openair3/NAS/TEST/AS_SIMULATOR/as_simulator.c @@ -120,12 +120,12 @@ static socket_id_t * _as_simulator_mme_sid = NULL; /* * UE NAS process connection manager's running indicator */ -static int _as_simulator_ue_is_running = FALSE; +static bool _as_simulator_ue_is_running = false; /* * MME NAS process connection manager's running indicator */ -static int _as_simulator_mme_is_running = FALSE; +static bool _as_simulator_mme_is_running = false; static int _set_signal_handler(int signal, void (handler)(int)); static void _signal_handler(int signal_number); @@ -307,8 +307,8 @@ static void _signal_handler(int signal_number) { printf("\nWARNING\t: %s - Signal %d received\n", __FUNCTION__, signal_number); - _as_simulator_ue_is_running = FALSE; - _as_simulator_mme_is_running = FALSE; + _as_simulator_ue_is_running = false; + _as_simulator_mme_is_running = false; } /* @@ -321,7 +321,7 @@ static void* _as_simulator_ue_mngr(void* args) int msg_id; as_message_t msg; - _as_simulator_ue_is_running = TRUE; + _as_simulator_ue_is_running = true; printf("INFO\t: %s - UE connection manager started\n", __FUNCTION__); @@ -388,7 +388,7 @@ static void* _as_simulator_ue_mngr(void* args) } /* Close the connection to the network sublayer */ - _as_simulator_ue_is_running = FALSE; + _as_simulator_ue_is_running = false; printf("ERROR\t: The UE connection manager exited\n"); return (NULL); } @@ -403,7 +403,7 @@ static void* _as_simulator_mme_mngr(void* args) int msg_id; as_message_t msg; - _as_simulator_mme_is_running = TRUE; + _as_simulator_mme_is_running = true; printf("INFO\t: %s - MME connection manager started\n", __FUNCTION__); @@ -469,7 +469,7 @@ static void* _as_simulator_mme_mngr(void* args) } /* Close the connection to the network sublayer */ - _as_simulator_mme_is_running = FALSE; + _as_simulator_mme_is_running = false; printf("ERROR\t: %s - The MME connection manager exited\n", __FUNCTION__); return (NULL); } diff --git a/openair3/NAS/TEST/NETWORK/network_simulator.c b/openair3/NAS/TEST/NETWORK/network_simulator.c index 461f701f95..492a709463 100644 --- a/openair3/NAS/TEST/NETWORK/network_simulator.c +++ b/openair3/NAS/TEST/NETWORK/network_simulator.c @@ -208,7 +208,7 @@ static const OctetString* _network_simulator_pdn[NETWORK_IP_MAX][2] = { static int _set_signal_handler(int signal, void (handler)(int)); static void _signal_handler(int signal_number); static int _process_message(int msgID, const as_message_t* req); -static int _assign_pdn_address(int ue_pdn_type, int is_initial, int* pdn_type, OctetString* pdn); +static int _assign_pdn_address(int ue_pdn_type, bool is_initial, int* pdn_type, OctetString* pdn); /* Functions used to process messages received from the Access Stratum */ static int _process_cell_info_req(const cell_info_req_t* req, cell_info_cnf_t* rsp); @@ -283,7 +283,7 @@ int main (int argc, const char* argv[]) /* * Network simulator main loop */ - while (TRUE) { + while (true) { as_message_t msg; /* Receive message from the NAS */ @@ -1072,11 +1072,11 @@ static int _process_pdn_connectivity_request(const pdn_connectivity_request_msg* /* Assign PDN address */ if (apn.length > 0) { request->accesspointname.accesspointnamevalue = apn; - esm_cause = _assign_pdn_address(requested_pdn_type, FALSE, &pdn_type, + esm_cause = _assign_pdn_address(requested_pdn_type, false, &pdn_type, &request->pdnaddress.pdnaddressinformation); } else { request->accesspointname.accesspointnamevalue = EURECOM_APN; - esm_cause = _assign_pdn_address(requested_pdn_type, TRUE, &pdn_type, + esm_cause = _assign_pdn_address(requested_pdn_type, true, &pdn_type, &request->pdnaddress.pdnaddressinformation); } diff --git a/openair3/NAS/TEST/USER/user_simulator.c b/openair3/NAS/TEST/USER/user_simulator.c index 1c429c3b85..3050c16692 100644 --- a/openair3/NAS/TEST/USER/user_simulator.c +++ b/openair3/NAS/TEST/USER/user_simulator.c @@ -192,7 +192,7 @@ int main (int argc, const char* argv[]) /* * User simulator main loop */ - while (TRUE) { + while (true) { char c; int len; @@ -293,7 +293,7 @@ static void _signal_handler(int signal_number) */ static void* _receive_thread(void* arg) { - while (TRUE) { + while (true) { /* Receive AT response from the NAS sublayer */ int rbytes = USER_RECV(_user_simulator_recv_buffer, USER_SIMULATOR_BUFFER_SIZE); diff --git a/openair3/NAS/UE/API/USER/at_command.c b/openair3/NAS/UE/API/USER/at_command.c index ab85b2d2fa..a6591c6748 100644 --- a/openair3/NAS/UE/API/USER/at_command.c +++ b/openair3/NAS/UE/API/USER/at_command.c @@ -354,7 +354,7 @@ static int ParseString(char * at_str, at_command_t* at_command) char* terminal_character_index = NULL; int num_of_chars_to_compare = -1; int handler_index; - int handler_found = FALSE; + bool handler_found = false; int check_for_carriage_return_index = 0; /* @@ -415,7 +415,7 @@ static int ParseString(char * at_str, at_command_t* at_command) if (strncasecmp(at_str, _at_command_handler[handler_index].command, num_of_chars_to_compare) != 0) continue; - handler_found = TRUE; + handler_found = true; break; } @@ -681,7 +681,7 @@ static unsigned int NumberOfParameters(const unsigned char* str) ** Others: None ** ** ** ** Outputs: None ** - ** Return: TRUE, FALSE ** + ** Return: true, false ** ** Others: None ** ** ** ***************************************************************************/ @@ -689,11 +689,11 @@ static unsigned int IsNumeric(const char* str, size_t len) { while (len-- > 0) { if (!isdigit(str[len])) { - return FALSE; + return false; } } - return TRUE; + return true; } /****************************************************************************/ @@ -719,7 +719,7 @@ static int parse_e1(const char* string, int position, at_command_t* at_command) static int parse_q0(const char* string, int position, at_command_t* at_command) { /* Result code suppression Q0 */ - at_error_code_suppression_q1 = FALSE; + at_error_code_suppression_q1 = false; at_command->id = 0; at_command->mask = AT_COMMAND_NO_PARAM; return at_command->id; @@ -728,7 +728,7 @@ static int parse_q0(const char* string, int position, at_command_t* at_command) static int parse_q1(const char* string, int position, at_command_t* at_command) { /* Result code suppression Q1 */ - at_error_code_suppression_q1 = TRUE; + at_error_code_suppression_q1 = true; at_command->id = 0; at_command->mask = AT_COMMAND_NO_PARAM; return at_command->id; @@ -738,7 +738,7 @@ static int parse_v0(const char* string, int position, at_command_t* at_command) { /* Response format V0 (numeric result code + limited header) */ at_error_format = AT_ERROR_NUMERIC; - at_response_format_v1 = FALSE; + at_response_format_v1 = false; at_command->id = 0; at_command->mask = AT_COMMAND_NO_PARAM; return at_command->id; @@ -748,7 +748,7 @@ static int parse_v1(const char* string, int position, at_command_t* at_command) { /* Response format V1 (verbose result code + full header) */ at_error_format = AT_ERROR_VERBOSE; - at_response_format_v1 = TRUE; + at_response_format_v1 = true; at_command->id = 0; at_command->mask = AT_COMMAND_NO_PARAM; return at_command->id; diff --git a/openair3/NAS/UE/API/USER/at_error.c b/openair3/NAS/UE/API/USER/at_error.c index d004c89736..bad7127adc 100644 --- a/openair3/NAS/UE/API/USER/at_error.c +++ b/openair3/NAS/UE/API/USER/at_error.c @@ -55,10 +55,10 @@ extern int at_response_format_v1; /* * Result code suppression indicator (set by ATQ0 and ATQ1) * ------------------------------------------------------- - * FALSE - Result codes are transmitted to the user application - * TRUE - Result codes are suppressed and not transmitted + * false - Result codes are transmitted to the user application + * true - Result codes are suppressed and not transmitted */ -int at_error_code_suppression_q1 = FALSE; +bool at_error_code_suppression_q1 = false; /* * Verbose mode indicator (set by ATV0, ATV1 and AT+CMEE) diff --git a/openair3/NAS/UE/API/USER/at_response.c b/openair3/NAS/UE/API/USER/at_response.c index 859db90d7e..eef0385750 100644 --- a/openair3/NAS/UE/API/USER/at_response.c +++ b/openair3/NAS/UE/API/USER/at_response.c @@ -52,10 +52,10 @@ Description Defines structure of the AT command response returned after /* * Response format indicator (set by ATV0 and ATV1) * ----------------------------------------------- - * TRUE - , - * FALSE - , + * true - , + * false - , */ -int at_response_format_v1 = TRUE; +bool at_response_format_v1 = true; /****************************************************************************/ /******************* L O C A L D E F I N I T I O N S *******************/ diff --git a/openair3/NAS/UE/EMM/Attach.c b/openair3/NAS/UE/EMM/Attach.c index 5e7a1f578b..52f7ebce44 100644 --- a/openair3/NAS/UE/EMM/Attach.c +++ b/openair3/NAS/UE/EMM/Attach.c @@ -146,7 +146,7 @@ int emm_proc_attach(nas_user_t *user, emm_proc_attach_type_t type) /* Update the emergency bearer service indicator */ if (type == EMM_ATTACH_TYPE_EMERGENCY) { - user->emm_data->is_emergency = TRUE; + user->emm_data->is_emergency = true; } /* Setup initial NAS information message to transfer */ @@ -211,7 +211,7 @@ int emm_proc_attach(nas_user_t *user, emm_proc_attach_type_t type) } /* Setup EPS NAS security data */ - emm_as_set_security_data(&emm_as->sctx, user->emm_data->security, FALSE, FALSE); + emm_as_set_security_data(&emm_as->sctx, user->emm_data->security, false, false); emm_as->ksi = EMM_AS_NO_KEY_AVAILABLE; if (user->emm_data->security) { @@ -230,8 +230,8 @@ int emm_proc_attach(nas_user_t *user, emm_proc_attach_type_t type) * is requested to setup a default EPS bearer */ esm_sap.primitive = ESM_PDN_CONNECTIVITY_REQ; - esm_sap.is_standalone = FALSE; - esm_sap.data.pdn_connect.is_defined = TRUE; + esm_sap.is_standalone = false; + esm_sap.data.pdn_connect.is_defined = true; esm_sap.data.pdn_connect.cid = 1; /* TODO: PDN type should be set according to the IP capability of the UE */ esm_sap.data.pdn_connect.pdn_type = NET_PDN_TYPE_IPV4; @@ -387,7 +387,7 @@ int emm_proc_attach_accept(nas_user_t *user, long t3412, long t3402, long t3423, if (n_eplmns > 0) { for (i = 0; (i < n_eplmns) && (i < EMM_DATA_EPLMN_MAX); i++) { - int is_forbidden = FALSE; + bool is_forbidden = false; if (!user->emm_data->is_emergency) { /* If the attach procedure is not for emergency bearer @@ -395,7 +395,7 @@ int emm_proc_attach_accept(nas_user_t *user, long t3412, long t3402, long t3423, * code that is already in the list of forbidden PLMNs */ for (j = 0; j < user->emm_data->fplmn.n_plmns; j++) { if (PLMNS_ARE_EQUAL(eplmn[i], user->emm_data->fplmn.plmn[j])) { - is_forbidden = TRUE; + is_forbidden = true; break; } } @@ -418,7 +418,7 @@ int emm_proc_attach_accept(nas_user_t *user, long t3412, long t3402, long t3423, * Notify ESM that a default EPS bearer has to be activated */ esm_sap.primitive = ESM_DEFAULT_EPS_BEARER_CONTEXT_ACTIVATE_REQ; - esm_sap.is_standalone = FALSE; + esm_sap.is_standalone = false; esm_sap.recv = esm_msg_pP; rc = esm_sap_send(user, &esm_sap); @@ -445,7 +445,7 @@ int emm_proc_attach_accept(nas_user_t *user, long t3412, long t3402, long t3423, emm_sap.u.emm_as.u.data.ueid = user->ueid; /* Setup EPS NAS security data */ emm_as_set_security_data(&emm_sap.u.emm_as.u.data.sctx, - user->emm_data->security, FALSE, TRUE); + user->emm_data->security, false, true); /* Get the activate default EPS bearer context accept message * to be transfered within the ESM container of the attach * complete message */ @@ -546,7 +546,7 @@ int emm_proc_attach_reject(nas_user_t *user, int emm_cause, const OctetString *e case EMM_CAUSE_EPS_NOT_ALLOWED: case EMM_CAUSE_BOTH_NOT_ALLOWED: /* Consider the USIM as invalid for EPS services */ - user->emm_data->usim_is_valid = FALSE; + user->emm_data->usim_is_valid = false; /* Delete the list of equivalent PLMNs */ user->emm_data->nvdata.eplmn.n_plmns = 0; break; @@ -682,7 +682,7 @@ int emm_proc_attach_reject(nas_user_t *user, int emm_cause, const OctetString *e if (esm_msg_pP != NULL) { esm_sap_t esm_sap; esm_sap.primitive = ESM_PDN_CONNECTIVITY_REJ; - esm_sap.is_standalone = FALSE; + esm_sap.is_standalone = false; esm_sap.recv = esm_msg_pP; rc = esm_sap_send(user, &esm_sap); } @@ -731,7 +731,7 @@ int emm_proc_attach_complete(void *args) /* Set the EPS update status to EU1 UPDATED */ user->emm_data->status = EU1_UPDATED; - user->emm_data->is_attached = TRUE; + user->emm_data->is_attached = true; /* * Notify EMM that network attach complete message has been delivered @@ -747,7 +747,7 @@ int emm_proc_attach_complete(void *args) * Complete message */ esm_sap.primitive = ESM_DEFAULT_EPS_BEARER_CONTEXT_ACTIVATE_CNF; - esm_sap.is_standalone = FALSE; + esm_sap.is_standalone = false; rc = esm_sap_send(user, &esm_sap); } @@ -766,7 +766,7 @@ int emm_proc_attach_complete(void *args) ** The UE shall restart the attach procedure when timer ** ** T3411 expires. ** ** ** - ** Inputs: is_initial: TRUE if the NAS message that failed to be ** + ** Inputs: is_initial: true if the NAS message that failed to be ** ** transfered is an initial NAS message (ESM ** ** message embedded within an Attach Request ** ** message) ** @@ -778,7 +778,7 @@ int emm_proc_attach_complete(void *args) ** Others: T3410, T3411 ** ** ** ***************************************************************************/ -int emm_proc_attach_failure(int is_initial, void *args) +int emm_proc_attach_failure(bool is_initial, void *args) { LOG_FUNC_IN; int rc = RETURNok; @@ -804,7 +804,7 @@ int emm_proc_attach_failure(int is_initial, void *args) * to be transmitted */ esm_sap.primitive = ESM_PDN_CONNECTIVITY_REJ; - esm_sap.is_standalone = FALSE; + esm_sap.is_standalone = false; esm_sap.recv = NULL; } else { /* @@ -813,7 +813,7 @@ int emm_proc_attach_failure(int is_initial, void *args) * has failed to be transmitted */ esm_sap.primitive = ESM_DEFAULT_EPS_BEARER_CONTEXT_ACTIVATE_REJ; - esm_sap.is_standalone = FALSE; + esm_sap.is_standalone = false; esm_sap.recv = NULL; } @@ -919,7 +919,7 @@ int emm_proc_attach_set_emergency(emm_data_t *emm_data) LOG_TRACE(WARNING, "EMM-PROC - UE is now attached to the network for " "emergency bearer services only"); - emm_data->is_emergency = TRUE; + emm_data->is_emergency = true; LOG_FUNC_RETURN(RETURNok); } @@ -950,7 +950,7 @@ int emm_proc_attach_set_detach(void *nas_user) "EMM-PROC - UE is now locally detached from the network"); /* Reset the network attachment indicator */ - user->emm_data->is_attached = FALSE; + user->emm_data->is_attached = false; /* * Notify that the UE is locally detached from the network */ diff --git a/openair3/NAS/UE/EMM/Authentication.c b/openair3/NAS/UE/EMM/Authentication.c index a2762d08e8..a3b58f89f4 100644 --- a/openair3/NAS/UE/EMM/Authentication.c +++ b/openair3/NAS/UE/EMM/Authentication.c @@ -129,7 +129,7 @@ static int _authentication_kasme(const OctetString *autn, ** authentication challenge data and respond with an AUTHEN- ** ** TICATION RESPONSE message to the network. ** ** ** - ** Inputs: native_ksi: TRUE if the security context is of type ** + ** Inputs: native_ksi: true if the security context is of type ** ** native (for KSIASME) ** ** ksi: The NAS ket sey identifier ** ** rand: Authentication parameter RAND ** @@ -179,14 +179,14 @@ int emm_proc_authentication_request(nas_user_t *user, int native_ksi, int ksi, OctetString res = {AUTH_RES_SIZE, authentication_data->res}; if ((memcmp(authentication_data->rand, rand->value, AUTH_CK_SIZE) != 0) || - (authentication_data->auth_process_started == FALSE)) { + (authentication_data->auth_process_started == false)) { /* * There is no valid stored RAND in the ME or the stored RAND is * different from the new received value in the AUTHENTICATION * REQUEST message OR if this is first time UE starting the * Authentication process */ - authentication_data->auth_process_started = TRUE; + authentication_data->auth_process_started = true; OctetString auts; auts.length = 0; auts.value = (uint8_t *)malloc(AUTH_AUTS_SIZE); @@ -308,7 +308,7 @@ int emm_proc_authentication_request(nas_user_t *user, int native_ksi, int ksi, emm_sap.u.emm_as.u.security.res = &res; /* Setup EPS NAS security data */ emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx, - user->emm_data->security, FALSE, TRUE); + user->emm_data->security, false, true); rc = emm_sap_send(user, &emm_sap); if (rc != RETURNerror) { @@ -398,7 +398,7 @@ int emm_proc_authentication_reject(nas_user_t *user) } /* Consider the USIM invalid */ - user->emm_data->usim_is_valid = FALSE; + user->emm_data->usim_is_valid = false; /* Stop timer T3410 */ if (emm_timers->T3410.id != NAS_TIMER_INACTIVE_ID) { @@ -652,7 +652,7 @@ static int _authentication_abnormal_cases_cde(nas_user_t *user, int emm_cause, emm_sap.u.emm_as.u.security.auts = auts; /* Setup EPS NAS security data */ emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx, - user->emm_data->security, FALSE, TRUE); + user->emm_data->security, false, true); rc = emm_sap_send(user, &emm_sap); if (rc != RETURNerror) { diff --git a/openair3/NAS/UE/EMM/Detach.c b/openair3/NAS/UE/EMM/Detach.c index b61bcdc14d..654486226e 100644 --- a/openair3/NAS/UE/EMM/Detach.c +++ b/openair3/NAS/UE/EMM/Detach.c @@ -114,7 +114,7 @@ static int _emm_detach_abort(nas_user_t *user, emm_proc_detach_type_t type); ** Return: RETURNok, RETURNerror ** ** ** ***************************************************************************/ -int emm_proc_detach(nas_user_t *user, emm_proc_detach_type_t type, int switch_off) +int emm_proc_detach(nas_user_t *user, emm_proc_detach_type_t type, bool switch_off) { LOG_FUNC_IN; @@ -154,7 +154,7 @@ int emm_proc_detach(nas_user_t *user, emm_proc_detach_type_t type, int switch_of emm_as->guti = user->emm_data->guti; emm_as->ueid = user->ueid; /* Setup EPS NAS security data */ - emm_as_set_security_data(&emm_as->sctx, user->emm_data->security, FALSE, TRUE); + emm_as_set_security_data(&emm_as->sctx, user->emm_data->security, false, true); /* * Notify EMM-AS SAP that Detach Request message has to @@ -280,7 +280,7 @@ int emm_proc_detach_accept(void* args) ** Others: None ** ** ** ***************************************************************************/ -int emm_proc_detach_failure(int is_initial, void *args) +int emm_proc_detach_failure(bool is_initial, void *args) { LOG_FUNC_IN; @@ -405,8 +405,7 @@ void *emm_detach_t3421_handler(void *args) emm_as->guti = user->emm_data->guti; emm_as->ueid = user->ueid; /* Setup EPS NAS security data */ - emm_as_set_security_data(&emm_as->sctx, user->emm_data->security, - FALSE, TRUE); + emm_as_set_security_data(&emm_as->sctx, user->emm_data->security, false, true); /* * Notify EMM-AS SAP that Detach Request message has to diff --git a/openair3/NAS/UE/EMM/EmmStatusHdl.c b/openair3/NAS/UE/EMM/EmmStatusHdl.c index 367d0327f4..9ac2fc794b 100644 --- a/openair3/NAS/UE/EMM/EmmStatusHdl.c +++ b/openair3/NAS/UE/EMM/EmmStatusHdl.c @@ -137,8 +137,7 @@ int emm_proc_status(nas_user_t *user, int emm_cause) emm_sap.u.emm_as.u.status.guti = user->emm_data->guti; sctx = user->emm_data->security; /* Setup EPS NAS security data */ - emm_as_set_security_data(&emm_sap.u.emm_as.u.status.sctx, sctx, - FALSE, TRUE); + emm_as_set_security_data(&emm_sap.u.emm_as.u.status.sctx, sctx, false, true); rc = emm_sap_send(user, &emm_sap); diff --git a/openair3/NAS/UE/EMM/Identification.c b/openair3/NAS/UE/EMM/Identification.c index 0364c6d22f..d4fc85a931 100644 --- a/openair3/NAS/UE/EMM/Identification.c +++ b/openair3/NAS/UE/EMM/Identification.c @@ -199,8 +199,7 @@ int emm_proc_identification_request(nas_user_t *user, emm_proc_identity_type_t t emm_sap.u.emm_as.u.security.ueid = user->ueid; emm_sap.u.emm_as.u.security.msgType = EMM_AS_MSG_TYPE_IDENT; /* Setup EPS NAS security data */ - emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx, - user->emm_data->security, FALSE, TRUE); + emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx, user->emm_data->security, false, true); rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); diff --git a/openair3/NAS/UE/EMM/IdleMode.c b/openair3/NAS/UE/EMM/IdleMode.c index 362d5e5b4a..50a318355c 100644 --- a/openair3/NAS/UE/EMM/IdleMode.c +++ b/openair3/NAS/UE/EMM/IdleMode.c @@ -663,8 +663,8 @@ int emm_proc_plmn_selection(nas_user_t *user, int index) ** to camp on an acceptable cell, irrespective of its PLMN ** ** identity, so that only emergency calls can be made. ** ** ** - ** Inputs: found: TRUE if a suitable cell of the chosen ** - ** PLMN has been found; FALSE otherwise. ** + ** Inputs: found: true if a suitable cell of the chosen ** + ** PLMN has been found; false otherwise. ** ** tac: The code of the location/tracking area the ** ** chosen PLMN belongs to ** ** ci: The identifier of the cell ** @@ -685,7 +685,7 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci, emm_plmn_list_t *emm_plmn_list = user->emm_plmn_list; user_api_id_t *user_api_id = user->user_api_id; int index = emm_plmn_list->index; - int select_next_plmn = FALSE; + bool select_next_plmn = false; LOG_TRACE(INFO, "EMM-IDLE - %s cell found for PLMN %d in %s mode", (found)? "One" : "No", index, @@ -694,7 +694,7 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci, "Automatic/manual"); if (found) { - int is_forbidden = FALSE; + bool is_forbidden = false; /* Select the PLMN of which a suitable cell has been found */ emm_data->splmn = *emm_plmn_list->plmn[index]; @@ -721,7 +721,7 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci, /* Check if the selected PLMN is in the forbidden list */ for (i = 0; i < emm_data->fplmn.n_plmns; i++) { if (PLMNS_ARE_EQUAL(emm_data->splmn, emm_data->fplmn.plmn[i])) { - is_forbidden = TRUE; + is_forbidden = true; break; } } @@ -730,7 +730,7 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci, for (i = 0; i < emm_data->fplmn_gprs.n_plmns; i++) { if (PLMNS_ARE_EQUAL(emm_data->splmn, emm_data->fplmn_gprs.plmn[i])) { - is_forbidden = TRUE; + is_forbidden = true; break; } } @@ -745,7 +745,7 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci, if (!is_forbidden) { for (i = 0; i < emm_data->ftai.n_tais; i++) { if (TAIS_ARE_EQUAL(tai, emm_data->ftai.tai[i])) { - is_forbidden = TRUE; + is_forbidden = true; break; } } @@ -754,7 +754,7 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci, if (!is_forbidden) { for (i = 0; i < emm_data->ftai_roaming.n_tais; i++) { if (TAIS_ARE_EQUAL(tai, emm_data->ftai_roaming.tai[i])) { - is_forbidden = TRUE; + is_forbidden = true; break; } } @@ -793,7 +793,7 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci, * Try to select the next PLMN in the ordered list of available PLMNs */ index += 1; - select_next_plmn = TRUE; + select_next_plmn = true; /* Bypass the previously selected PLMN */ if (index == emm_plmn_list->splmn) { @@ -809,7 +809,7 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci, * registered or equivalent PLMNs is ongoing */ index += 1; - select_next_plmn = TRUE; + select_next_plmn = true; } else if (emm_data->plmn_mode == EMM_DATA_PLMN_MANUAL) { @@ -830,7 +830,7 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci, */ emm_data->plmn_mode = EMM_DATA_PLMN_AUTO; index = emm_plmn_list->hplmn; - select_next_plmn = TRUE; + select_next_plmn = true; } /* @@ -851,7 +851,7 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci, } else { /* No suitable cell of any PLMN within the ordered list * of available PLMNs has been found */ - select_next_plmn = FALSE; + select_next_plmn = false; emm_sap.primitive = EMMREG_NO_CELL; } } @@ -892,11 +892,11 @@ int emm_proc_plmn_selection_end(nas_user_t *user, int found, tac_t tac, ci_t ci, if (emm_plmn_list->splmn == emm_plmn_list->rplmn) { /* The selected PLMN is the registered PLMN */ LOG_TRACE(INFO, "EMM-IDLE - The selected PLMN is the registered PLMN"); - emm_data->is_rplmn = TRUE; + emm_data->is_rplmn = true; } else if (emm_plmn_list->splmn < emm_plmn_list->hplmn) { /* The selected PLMN is in the list of equivalent PLMNs */ LOG_TRACE(INFO, "EMM-IDLE - The selected PLMN is in the list of equivalent PLMNs"); - emm_data->is_eplmn = TRUE; + emm_data->is_eplmn = true; } /* diff --git a/openair3/NAS/UE/EMM/LowerLayer.c b/openair3/NAS/UE/EMM/LowerLayer.c index 01b07fc356..538ba21099 100644 --- a/openair3/NAS/UE/EMM/LowerLayer.c +++ b/openair3/NAS/UE/EMM/LowerLayer.c @@ -208,7 +208,7 @@ int lowerlayer_data_ind(nas_user_t *user, const OctetString *data) LOG_FUNC_IN; esm_sap.primitive = ESM_UNITDATA_IND; - esm_sap.is_standalone = TRUE; + esm_sap.is_standalone = true; esm_sap.ueid = user->ueid; esm_sap.recv = data; @@ -250,7 +250,7 @@ int lowerlayer_data_req(nas_user_t *user, const OctetString *data) emm_sap.u.emm_as.u.data.NASmsg.length = data->length; emm_sap.u.emm_as.u.data.NASmsg.value = data->value; /* Setup EPS NAS security data */ - emm_as_set_security_data(&emm_sap.u.emm_as.u.data.sctx, sctx, FALSE, TRUE); + emm_as_set_security_data(&emm_sap.u.emm_as.u.data.sctx, sctx, false, true); rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); @@ -336,7 +336,7 @@ int emm_proc_lowerlayer_success(lowerlayer_data_t *lowerlayer_data) ** Description: Handles EMM procedure to be executed upon receiving noti- ** ** fication that data failed to be delivered to the network. ** ** ** - ** Inputs: is_initial: TRUE if the NAS message that failed to be ** + ** Inputs: is_initial: true if the NAS message that failed to be ** ** transfered is an initial NAS message ** ** Others: None ** ** ** @@ -345,7 +345,7 @@ int emm_proc_lowerlayer_success(lowerlayer_data_t *lowerlayer_data) ** Others: None ** ** ** ***************************************************************************/ -int emm_proc_lowerlayer_failure(lowerlayer_data_t *lowerlayer_data, int is_initial) +int emm_proc_lowerlayer_failure(lowerlayer_data_t *lowerlayer_data, bool is_initial) { LOG_FUNC_IN; diff --git a/openair3/NAS/UE/EMM/LowerLayer.h b/openair3/NAS/UE/EMM/LowerLayer.h index 0d8eefc7f3..ed60e379bc 100644 --- a/openair3/NAS/UE/EMM/LowerLayer.h +++ b/openair3/NAS/UE/EMM/LowerLayer.h @@ -72,7 +72,7 @@ int emm_proc_lowerlayer_initialize(lowerlayer_data_t *lowerlayer_data, lowerlaye lowerlayer_release_callback_t release, void *args); int emm_proc_lowerlayer_success(lowerlayer_data_t *lowerlayer_data); -int emm_proc_lowerlayer_failure(lowerlayer_data_t *lowerlayer_data, int is_initial); +int emm_proc_lowerlayer_failure(lowerlayer_data_t *lowerlayer_data, bool is_initial); int emm_proc_lowerlayer_release(lowerlayer_data_t *lowerlayer_data); diff --git a/openair3/NAS/UE/EMM/LowerLayer_defs.h b/openair3/NAS/UE/EMM/LowerLayer_defs.h index 6035d4ed12..1a0ae7d656 100644 --- a/openair3/NAS/UE/EMM/LowerLayer_defs.h +++ b/openair3/NAS/UE/EMM/LowerLayer_defs.h @@ -11,7 +11,7 @@ typedef int (*lowerlayer_success_callback_t)(void *); * Type of EMM procedure callback function executed when data are not * delivered to the network because a lower layer failure occurred */ -typedef int (*lowerlayer_failure_callback_t)(int, void *); +typedef int (*lowerlayer_failure_callback_t)(bool, void *); /* * Type of EMM procedure callback function executed when NAS signalling diff --git a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredAttemptingToAttach.c b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredAttemptingToAttach.c index f58cf4b9e0..3fa47094c7 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredAttemptingToAttach.c +++ b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredAttemptingToAttach.c @@ -120,7 +120,7 @@ int EmmDeregisteredAttemptingToAttach(nas_user_t *user, const emm_reg_t *evt) /* * Data failed to be delivered to the network */ - rc = emm_proc_lowerlayer_failure(user->lowerlayer_data, FALSE); + rc = emm_proc_lowerlayer_failure(user->lowerlayer_data, false); break; default: diff --git a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredLimitedService.c b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredLimitedService.c index 4310f963cd..c0763009b8 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredLimitedService.c +++ b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredLimitedService.c @@ -133,7 +133,7 @@ int EmmDeregisteredLimitedService(nas_user_t *user, const emm_reg_t *evt) /* * Initial NAS message failed to be delivered to the network */ - rc = emm_proc_lowerlayer_failure(user->lowerlayer_data, TRUE); + rc = emm_proc_lowerlayer_failure(user->lowerlayer_data, true); break; case _EMMREG_LOWERLAYER_RELEASE: diff --git a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c index f77c2921a3..0925cb4e0f 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c +++ b/openair3/NAS/UE/EMM/SAP/EmmDeregisteredNormalService.c @@ -141,7 +141,7 @@ int EmmDeregisteredNormalService(nas_user_t *user, const emm_reg_t *evt) /* * Initial NAS message failed to be delivered to the network */ - rc = emm_proc_lowerlayer_failure(user->lowerlayer_data, TRUE); + rc = emm_proc_lowerlayer_failure(user->lowerlayer_data, true); break; case _EMMREG_LOWERLAYER_RELEASE: diff --git a/openair3/NAS/UE/EMM/SAP/EmmRegistered.c b/openair3/NAS/UE/EMM/SAP/EmmRegistered.c index fbd3e1ce63..2cd25f77d6 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmRegistered.c +++ b/openair3/NAS/UE/EMM/SAP/EmmRegistered.c @@ -143,7 +143,7 @@ int EmmRegistered(nas_user_t *user, const emm_reg_t *evt) /* * Data transfer message failed to be delivered */ - rc = emm_proc_lowerlayer_failure(user->lowerlayer_data, FALSE); + rc = emm_proc_lowerlayer_failure(user->lowerlayer_data, false); break; case _EMMREG_LOWERLAYER_RELEASE: diff --git a/openair3/NAS/UE/EMM/SAP/EmmRegisteredInitiated.c b/openair3/NAS/UE/EMM/SAP/EmmRegisteredInitiated.c index 36929fc4d7..a770e08bab 100644 --- a/openair3/NAS/UE/EMM/SAP/EmmRegisteredInitiated.c +++ b/openair3/NAS/UE/EMM/SAP/EmmRegisteredInitiated.c @@ -240,7 +240,7 @@ int EmmRegisteredInitiated(nas_user_t *user, const emm_reg_t *evt) * any message transfered by EMM common procedures requested * by the network. */ - rc = emm_proc_lowerlayer_failure(user->lowerlayer_data, FALSE); + rc = emm_proc_lowerlayer_failure(user->lowerlayer_data, false); break; case _EMMREG_LOWERLAYER_RELEASE: diff --git a/openair3/NAS/UE/EMM/SAP/emm_as.c b/openair3/NAS/UE/EMM/SAP/emm_as.c index ea4eefadeb..de6dee4a5e 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_as.c +++ b/openair3/NAS/UE/EMM/SAP/emm_as.c @@ -679,7 +679,7 @@ static int _emm_as_cell_info_res(nas_user_t *user, const emm_as_cell_info_t *msg int AcT = NET_ACCESS_EUTRAN; - if (msg->found == TRUE) { + if (msg->found == true) { /* Get the first supported access technology */ while (AcT != NET_ACCESS_UNAVAILABLE) { if (msg->rat & (1 << AcT)) { @@ -1081,7 +1081,7 @@ static int _emm_as_data_req(const emm_data_t *emm_data, const emm_as_data_t *msg LOG_FUNC_IN; ul_info_transfer_req_t *as_msg = (ul_info_transfer_req_t *)ul_info_transfer_req_unaligned; int size = 0; - int is_encoded = FALSE; + bool is_encoded = false; LOG_TRACE(INFO, "EMMAS-SAP - Send AS data transfer request"); @@ -1114,7 +1114,7 @@ static int _emm_as_data_req(const emm_data_t *emm_data, const emm_as_data_t *msg default: /* Send other NAS messages as already encoded ESM messages */ size = msg->NASmsg.length; - is_encoded = TRUE; + is_encoded = true; break; } diff --git a/openair3/NAS/UE/EMM/SAP/emm_asDef.h b/openair3/NAS/UE/EMM/SAP/emm_asDef.h index 7bd464ec04..4f6182a2c9 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_asDef.h +++ b/openair3/NAS/UE/EMM/SAP/emm_asDef.h @@ -150,7 +150,7 @@ typedef struct emm_as_establish_s { uint32_t ueid; /* UE lower layer identifier */ emm_as_EPS_identity_t UEid; /* UE's EPS mobile identity */ emm_as_security_data_t sctx;/* EPS NAS security context */ - int switch_off; /* TRUE if the UE is switched off */ + bool switch_off; /* true if the UE is switched off */ uint8_t type; /* Network attach/detach type */ uint8_t RRCcause; /* Connection establishment cause */ uint8_t RRCtype; /* Associated call type */ @@ -194,7 +194,7 @@ typedef struct emm_as_data_s { uint32_t ueid; /* UE lower layer identifier */ const GUTI_t *guti; /* GUTI temporary mobile identity */ emm_as_security_data_t sctx;/* EPS NAS security context */ - int switch_off; /* TRUE if the UE is switched off */ + bool switch_off; /* true if the UE is switched off */ uint8_t type; /* Network detach type */ uint8_t delivered; /* Data message delivery indicator */ #define EMM_AS_NAS_DATA_ATTACH 0x01 /* Attach complete */ diff --git a/openair3/NAS/UE/EMM/SAP/emm_esmDef.h b/openair3/NAS/UE/EMM/SAP/emm_esmDef.h index aac37b46bf..6e7065f913 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_esmDef.h +++ b/openair3/NAS/UE/EMM/SAP/emm_esmDef.h @@ -71,9 +71,9 @@ typedef enum { * --------------------------------------------- */ typedef struct { - int is_emergency; /* Indicates whether the PDN connection is established + bool is_emergency; /* Indicates whether the PDN connection is established * for emergency bearer services only */ - int is_attached; /* Indicates whether the UE remains attached to the + bool is_attached; /* Indicates whether the UE remains attached to the * network */ } emm_esm_establish_t; diff --git a/openair3/NAS/UE/EMM/SAP/emm_regDef.h b/openair3/NAS/UE/EMM/SAP/emm_regDef.h index b66c0565ea..752f328375 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_regDef.h +++ b/openair3/NAS/UE/EMM/SAP/emm_regDef.h @@ -100,7 +100,7 @@ typedef struct { * ------------------------------------- */ typedef struct { - int is_emergency; /* TRUE if the UE was attempting to register to + bool is_emergency; /* true if the UE was attempting to register to * the network for emergency services only */ } emm_reg_attach_t; @@ -109,7 +109,7 @@ typedef struct { * ------------------------------------- */ typedef struct { - int switch_off; /* TRUE if the UE is switched off */ + bool switch_off; /* true if the UE is switched off */ int type; /* Network detach type */ } emm_reg_detach_t; diff --git a/openair3/NAS/UE/EMM/SecurityModeControl.c b/openair3/NAS/UE/EMM/SecurityModeControl.c index f9a02b1a70..fd3332669b 100644 --- a/openair3/NAS/UE/EMM/SecurityModeControl.c +++ b/openair3/NAS/UE/EMM/SecurityModeControl.c @@ -124,7 +124,7 @@ static void _security_release(emm_security_context_t *ctx); ** grity algorithm and ciphered with the selected NAS ciphe- ** ** ring algorithm. ** ** ** - ** Inputs: native_ksi: TRUE if the security context is of type ** + ** Inputs: native_ksi: true if the security context is of type ** ** native (for KSIASME) ** ** ksi: The NAS ket sey identifier ** ** seea: Selected EPS cyphering algorithm ** @@ -145,7 +145,7 @@ int emm_proc_security_mode_command(nas_user_t *user, int native_ksi, int ksi, int rc = RETURNerror; int emm_cause = EMM_CAUSE_SUCCESS; - int security_context_is_new = FALSE; + int security_context_is_new = false; security_data_t *security_data = user->security_data; LOG_TRACE(INFO, "EMM-PROC - Security mode control requested (ksi=%d)", @@ -263,7 +263,7 @@ int emm_proc_security_mode_command(nas_user_t *user, int native_ksi, int ksi, user->emm_data->security->ul_count.overflow = 0; user->emm_data->security->ul_count.seq_num = 0; /* Set new security context indicator */ - security_context_is_new = TRUE; + security_context_is_new = true; } } @@ -328,7 +328,7 @@ int emm_proc_security_mode_command(nas_user_t *user, int native_ksi, int ksi, emm_sap.u.emm_as.u.security.emm_cause = emm_cause; /* Setup EPS NAS security data */ emm_as_set_security_data(&emm_sap.u.emm_as.u.security.sctx, - user->emm_data->security, security_context_is_new, TRUE); + user->emm_data->security, security_context_is_new, true); rc = emm_sap_send(user, &emm_sap); LOG_FUNC_RETURN (rc); diff --git a/openair3/NAS/UE/EMM/emmData.h b/openair3/NAS/UE/EMM/emmData.h index dfdfb34e77..50219b7883 100644 --- a/openair3/NAS/UE/EMM/emmData.h +++ b/openair3/NAS/UE/EMM/emmData.h @@ -112,7 +112,7 @@ typedef struct { #define EMM_DETACH_COUNTER_MAX 5 unsigned int count; /* Counter used to limit the number of * subsequently detach attempts */ - int switch_off; /* UE switch-off indicator */ + bool switch_off; /* UE switch-off indicator */ emm_proc_detach_type_t type; /* Type of the detach procedure * currently in progress */ } emm_detach_data_t; @@ -249,8 +249,8 @@ typedef struct emm_data_s { emm_eps_update_t status; /* The current EPS update status */ emm_ecm_state_t ecm_status; /* The EPS Connection Management status */ - int is_attached; /* Network attachment indicator */ - int is_emergency; /* Emergency bearer services indicator*/ + bool is_attached; /* Network attachment indicator */ + bool is_emergency; /* Emergency bearer services indicator*/ /* Tracking Areas list the UE is registered to * Contains the list of TAIs that identify the tracking areas that diff --git a/openair3/NAS/UE/EMM/emm_main.c b/openair3/NAS/UE/EMM/emm_main.c index 329b59fae6..74676c8b36 100644 --- a/openair3/NAS/UE/EMM/emm_main.c +++ b/openair3/NAS/UE/EMM/emm_main.c @@ -113,7 +113,7 @@ void _emm_attach_initialize(emm_attach_data_t *emm_attach_data) { void _emm_detach_initialize(emm_detach_data_t *emm_detach) { emm_detach->count = 0; - emm_detach->switch_off = FALSE; + emm_detach->switch_off = false; emm_detach->type = EMM_DETACH_TYPE_RESERVED; } @@ -137,7 +137,7 @@ void emm_main_initialize(nas_user_t *user, emm_indication_callback_t cb, const c LOG_FUNC_IN; user->emm_data = calloc_or_fail(sizeof(emm_data_t)); /* USIM validity indicator */ - user->emm_data->usim_is_valid = FALSE; + user->emm_data->usim_is_valid = false; /* The IMEI read from the UE's non-volatile memory */ user->emm_data->imei = (imei_t *)malloc(sizeof(imei_t)); user->emm_data->imei->length = _emm_main_get_imei(user->emm_data->imei, imei); @@ -157,14 +157,14 @@ void emm_main_initialize(nas_user_t *user, emm_indication_callback_t cb, const c user->emm_data->plmn_rat = NET_ACCESS_UNAVAILABLE; /* Selected PLMN */ memset(&user->emm_data->splmn, 0xFF, sizeof(plmn_t)); - user->emm_data->is_rplmn = FALSE; - user->emm_data->is_eplmn = FALSE; + user->emm_data->is_rplmn = false; + user->emm_data->is_eplmn = false; /* Radio Access Technology of the serving cell */ user->emm_data->rat = NET_ACCESS_UNAVAILABLE; /* Network registration status */ user->emm_data->stat = NET_REG_STATE_OFF; - user->emm_data->is_attached = FALSE; - user->emm_data->is_emergency = FALSE; + user->emm_data->is_attached = false; + user->emm_data->is_emergency = false; /* Location/Tracking area code */ user->emm_data->tac = 0; // two byte in hexadecimal format /* Identifier of the serving cell */ @@ -201,7 +201,7 @@ void emm_main_initialize(nas_user_t *user, emm_indication_callback_t cb, const c /* The USIM application is present and valid */ LOG_TRACE(INFO, "EMM-MAIN - USIM application data successfully read"); - user->emm_data->usim_is_valid = TRUE; + user->emm_data->usim_is_valid = true; /* print keys (for debugging) */ { @@ -844,12 +844,12 @@ AcT_t emm_main_get_plmn_rat(emm_data_t *emm_data) ** Others: user->emm_data-> ** ** ** ** Outputs: None ** - ** Return: TRUE if the UE is currently attached to ** - ** the network; FALSE otherwise. ** + ** Return: true if the UE is currently attached to ** + ** the network; false otherwise. ** ** Others: None ** ** ** ***************************************************************************/ -int emm_main_is_attached(emm_data_t *emm_data) +bool emm_main_is_attached(emm_data_t *emm_data) { LOG_FUNC_IN; LOG_FUNC_RETURN (emm_data->is_attached); @@ -866,13 +866,13 @@ int emm_main_is_attached(emm_data_t *emm_data) ** Others: user->emm_data-> ** ** ** ** Outputs: None ** - ** Return: TRUE if the UE is currently attached or is ** + ** Return: true if the UE is currently attached or is ** ** attempting to attach to the network for ** - ** emergency bearer services; FALSE otherwise ** + ** emergency bearer services; false otherwise ** ** Others: None ** ** ** ***************************************************************************/ -int emm_main_is_emergency(emm_data_t *emm_data) +bool emm_main_is_emergency(emm_data_t *emm_data) { LOG_FUNC_IN; LOG_FUNC_RETURN (emm_data->is_attached && emm_data->is_emergency); @@ -967,8 +967,8 @@ static int _emm_main_get_imei(imei_t *imei, const char *imei_str) ** Others: None ** ** ** ** Outputs: None ** - ** Return: TRUE if the first IMSI is found to match ** - ** the second; FALSE otherwise. ** + ** Return: true if the first IMSI is found to match ** + ** the second; false otherwise. ** ** Others: None ** ** ** ***************************************************************************/ @@ -977,16 +977,16 @@ static int _emm_main_imsi_cmp(imsi_t *imsi1, imsi_t *imsi2) int i; if (imsi1->length != imsi2->length) { - return FALSE; + return false; } for (i = 0; i < imsi1->length; i++) { if (imsi1->u.value[i] != imsi2->u.value[i]) { - return FALSE; + return false; } } - return TRUE; + return true; } /**************************************************************************** diff --git a/openair3/NAS/UE/EMM/emm_main.h b/openair3/NAS/UE/EMM/emm_main.h index d30f778e3b..d081024548 100644 --- a/openair3/NAS/UE/EMM/emm_main.h +++ b/openair3/NAS/UE/EMM/emm_main.h @@ -94,8 +94,8 @@ AcT_t emm_main_get_plmn_rat(emm_data_t *emm_data); const char *emm_main_get_registered_plmn(emm_plmn_list_t *emm_plmn_list, emm_data_t *emm_data, network_plmn_t *plmn, int format); /* User's getter for network attachment */ -int emm_main_is_attached(emm_data_t *emm_data); -int emm_main_is_emergency(emm_data_t *emm_data); +bool emm_main_is_attached(emm_data_t *emm_data); +bool emm_main_is_emergency(emm_data_t *emm_data); #endif /* __EMM_MAIN_H__*/ diff --git a/openair3/NAS/UE/EMM/emm_proc.h b/openair3/NAS/UE/EMM/emm_proc.h index 7d4024d9d6..b93bb33bf1 100644 --- a/openair3/NAS/UE/EMM/emm_proc.h +++ b/openair3/NAS/UE/EMM/emm_proc.h @@ -89,7 +89,7 @@ int emm_proc_attach_accept(nas_user_t *user, long T3412, long T3402, long T3423, const OctetString *esm_msg); int emm_proc_attach_reject(nas_user_t *user, int emm_cause, const OctetString *esm_msg); int emm_proc_attach_complete(void *args); -int emm_proc_attach_failure(int is_initial, void *args); +int emm_proc_attach_failure(bool is_initial, void *args); int emm_proc_attach_release(void *args); int emm_proc_attach_restart(nas_user_t *user); @@ -103,10 +103,10 @@ int emm_proc_attach_set_detach(void *user); * Detach procedure * -------------------------------------------------------------------------- */ -int emm_proc_detach(nas_user_t *user, emm_proc_detach_type_t type, int switch_off); +int emm_proc_detach(nas_user_t *user, emm_proc_detach_type_t type, bool switch_off); int emm_proc_detach_request(void *args); int emm_proc_detach_accept(void *args); -int emm_proc_detach_failure(int is_initial, void *args); +int emm_proc_detach_failure(bool is_initial, void *args); int emm_proc_detach_release(void *args); diff --git a/openair3/NAS/UE/ESM/DedicatedEpsBearerContextActivation.c b/openair3/NAS/UE/ESM/DedicatedEpsBearerContextActivation.c index 21c3da3f19..db95dd648f 100644 --- a/openair3/NAS/UE/ESM/DedicatedEpsBearerContextActivation.c +++ b/openair3/NAS/UE/ESM/DedicatedEpsBearerContextActivation.c @@ -131,7 +131,7 @@ int esm_proc_dedicated_eps_bearer_context_request(nas_user_t *user, int ebi, int } /* Assign dedicated EPS bearer context */ - int new_ebi = esm_ebr_assign(user->esm_ebr_data, ebi, pid+1, FALSE); + int new_ebi = esm_ebr_assign(user->esm_ebr_data, ebi, pid+1, false); if (new_ebi == ESM_EBI_UNASSIGNED) { /* 3GPP TS 24.301, section 6.4.2.5, abnormal cases a and b @@ -141,7 +141,7 @@ int esm_proc_dedicated_eps_bearer_context_request(nas_user_t *user, int ebi, int int old_pid, old_bid; /* Locally deactivate the existing EPS bearer context and proceed * with the requested dedicated EPS bearer context activation */ - rc = esm_proc_eps_bearer_context_deactivate(user, TRUE, ebi, + rc = esm_proc_eps_bearer_context_deactivate(user, true, ebi, &old_pid, &old_bid); if (rc != RETURNok) { @@ -149,7 +149,7 @@ int esm_proc_dedicated_eps_bearer_context_request(nas_user_t *user, int ebi, int *esm_cause = ESM_CAUSE_PROTOCOL_ERROR; } else { /* Assign new dedicated EPS bearer context */ - ebi = esm_ebr_assign(user->esm_ebr_data, ebi, pid+1, FALSE); + ebi = esm_ebr_assign(user->esm_ebr_data, ebi, pid+1, false); } } @@ -165,7 +165,7 @@ int esm_proc_dedicated_eps_bearer_context_request(nas_user_t *user, int ebi, int *esm_cause = ESM_CAUSE_SYNTACTICAL_ERROR_IN_PACKET_FILTER; } else { /* Create new dedicated EPS bearer context */ - default_ebi = esm_ebr_context_create(esm_data, user->ueid, pid, ebi, FALSE, qos, tft); + default_ebi = esm_ebr_context_create(esm_data, user->ueid, pid, ebi, false, qos, tft); if (default_ebi != ESM_EBI_UNASSIGNED) { /* Dedicated EPS bearer contextx successfully created */ @@ -197,7 +197,7 @@ int esm_proc_dedicated_eps_bearer_context_request(nas_user_t *user, int ebi, int ** Inputs: is_standalone: Not used ** ** ebi: EPS bearer identity ** ** msg: Encoded ESM message to be sent ** - ** ue_triggered: TRUE if the EPS bearer context procedure ** + ** ue_triggered: true if the EPS bearer context procedure ** ** was triggered by the UE ** ** Others: None ** ** ** @@ -206,8 +206,8 @@ int esm_proc_dedicated_eps_bearer_context_request(nas_user_t *user, int ebi, int ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_dedicated_eps_bearer_context_accept(nas_user_t *user, int is_standalone, int ebi, - OctetString *msg, int ue_triggered) +int esm_proc_dedicated_eps_bearer_context_accept(nas_user_t *user, bool is_standalone, int ebi, + OctetString *msg, bool ue_triggered) { LOG_FUNC_IN; @@ -268,8 +268,8 @@ int esm_proc_dedicated_eps_bearer_context_accept(nas_user_t *user, int is_standa ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_dedicated_eps_bearer_context_reject(nas_user_t *user, int is_standalone, int ebi, - OctetString *msg, int ue_triggered) +int esm_proc_dedicated_eps_bearer_context_reject(nas_user_t *user, bool is_standalone, int ebi, + OctetString *msg, bool ue_triggered) { LOG_FUNC_IN; diff --git a/openair3/NAS/UE/ESM/DefaultEpsBearerContextActivation.c b/openair3/NAS/UE/ESM/DefaultEpsBearerContextActivation.c index 7c528d7569..f61b149822 100644 --- a/openair3/NAS/UE/ESM/DefaultEpsBearerContextActivation.c +++ b/openair3/NAS/UE/ESM/DefaultEpsBearerContextActivation.c @@ -103,7 +103,7 @@ int esm_proc_default_eps_bearer_context_request(nas_user_t *user, int pid, int e "requested by the network (ebi=%d)", ebi); /* Assign default EPS bearer context */ - int new_ebi = esm_ebr_assign(user->esm_ebr_data, ebi, pid+1, TRUE); + int new_ebi = esm_ebr_assign(user->esm_ebr_data, ebi, pid+1, true); if (new_ebi == ESM_EBI_UNASSIGNED) { /* 3GPP TS 24.301, section 6.4.1.5, abnormal cases a and b @@ -113,7 +113,7 @@ int esm_proc_default_eps_bearer_context_request(nas_user_t *user, int pid, int e int old_pid, old_bid; /* Locally deactivate the existing EPS bearer context and proceed * with the requested default EPS bearer context activation */ - rc = esm_proc_eps_bearer_context_deactivate(user, TRUE, ebi, + rc = esm_proc_eps_bearer_context_deactivate(user, true, ebi, &old_pid, &old_bid); if (rc != RETURNok) { @@ -121,13 +121,13 @@ int esm_proc_default_eps_bearer_context_request(nas_user_t *user, int pid, int e *esm_cause = ESM_CAUSE_PROTOCOL_ERROR; } else { /* Assign new default EPS bearer context */ - ebi = esm_ebr_assign(user->esm_ebr_data, ebi, pid+1, TRUE); + ebi = esm_ebr_assign(user->esm_ebr_data, ebi, pid+1, true); } } if (ebi != ESM_EBI_UNASSIGNED) { /* Create new default EPS bearer context */ - ebi = esm_ebr_context_create(esm_data, user->ueid, pid, ebi, TRUE, qos, NULL); + ebi = esm_ebr_context_create(esm_data, user->ueid, pid, ebi, true, qos, NULL); if (ebi != ESM_EBI_UNASSIGNED) { /* Default EPS bearer contextx successfully created */ @@ -165,9 +165,9 @@ int esm_proc_default_eps_bearer_context_request(nas_user_t *user, int pid, int e ** te message ** ** ebi: EPS bearer identity ** ** msg: Encoded ESM message to be sent ** - ** ue_triggered: TRUE if the EPS bearer context procedure ** + ** ue_triggered: true if the EPS bearer context procedure ** ** was triggered by the UE (should be always ** - ** TRUE) ** + ** true) ** ** Others: None ** ** ** ** Outputs: None ** @@ -175,8 +175,8 @@ int esm_proc_default_eps_bearer_context_request(nas_user_t *user, int pid, int e ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_default_eps_bearer_context_accept(nas_user_t *user, int is_standalone, int ebi, - OctetString *msg, int ue_triggered) +int esm_proc_default_eps_bearer_context_accept(nas_user_t *user, bool is_standalone, int ebi, + OctetString *msg, bool ue_triggered) { LOG_FUNC_IN; @@ -245,8 +245,8 @@ int esm_proc_default_eps_bearer_context_accept(nas_user_t *user, int is_standalo ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_default_eps_bearer_context_reject(nas_user_t *user, int is_standalone, int ebi, - OctetString *msg, int ue_triggered) +int esm_proc_default_eps_bearer_context_reject(nas_user_t *user, bool is_standalone, int ebi, + OctetString *msg, bool ue_triggered) { LOG_FUNC_IN; @@ -344,7 +344,7 @@ int esm_proc_default_eps_bearer_context_failure(nas_user_t *user) "ESM-PROC - Default EPS bearer context activation failure"); /* Release the default EPS bearer context and enter state INACTIVE */ - int rc = esm_proc_eps_bearer_context_deactivate(user, TRUE, ebi, &pid, &bid); + int rc = esm_proc_eps_bearer_context_deactivate(user, true, ebi, &pid, &bid); if (rc != RETURNerror) { /* Reset default EPS bearer context internal data */ diff --git a/openair3/NAS/UE/ESM/EpsBearerContextDeactivation.c b/openair3/NAS/UE/ESM/EpsBearerContextDeactivation.c index 5adbae05c6..742e70cd4a 100644 --- a/openair3/NAS/UE/ESM/EpsBearerContextDeactivation.c +++ b/openair3/NAS/UE/ESM/EpsBearerContextDeactivation.c @@ -97,7 +97,7 @@ static int _eps_bearer_release(nas_user_t *user, int ebi, int *pid, int *bid); ** has an EPS bearer context with specified EPS bearer iden- ** ** tity activated. ** ** ** - ** Inputs: is local: TRUE if the EPS bearer context has to be ** + ** Inputs: is local: true if the EPS bearer context has to be ** ** locally released without peer-to-peer si- ** ** gnalling between the UE and the MME ** ** ebi: EPS bearer identity of the EPS bearer con- ** @@ -111,7 +111,7 @@ static int _eps_bearer_release(nas_user_t *user, int ebi, int *pid, int *bid); ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_eps_bearer_context_deactivate(nas_user_t *user, int is_local, int ebi, +int esm_proc_eps_bearer_context_deactivate(nas_user_t *user, bool is_local, int ebi, int *pid, int *bid) { LOG_FUNC_IN; @@ -213,7 +213,7 @@ int esm_proc_eps_bearer_context_deactivate_request(nas_user_t *user, int ebi, in * the PDN connection */ if (*esm_cause == ESM_CAUSE_REACTIVATION_REQUESTED) { esm_sap_t esm_sap; - int active = FALSE; + bool active = false; /* 3GPP TS 24.301, section 6.4.4.3 * The UE should re-initiate the UE requested PDN connectivity @@ -242,8 +242,8 @@ int esm_proc_eps_bearer_context_deactivate_request(nas_user_t *user, int ebi, in * Notify ESM to re-initiate PDN connectivity procedure */ esm_sap.primitive = ESM_PDN_CONNECTIVITY_REQ; - esm_sap.is_standalone = TRUE; - esm_sap.data.pdn_connect.is_defined = TRUE; + esm_sap.is_standalone = true; + esm_sap.data.pdn_connect.is_defined = true; esm_sap.data.pdn_connect.cid = pid + 1; rc = esm_sap_send(user, &esm_sap); } @@ -265,10 +265,10 @@ int esm_proc_eps_bearer_context_deactivate_request(nas_user_t *user, int ebi, in ** DEACTIVATE EPS BEARER CONTEXT ACCEPT message and entering ** ** the state BEARER CONTEXT INACTIVE. ** ** ** - ** Inputs: is_standalone: Should be always TRUE ** + ** Inputs: is_standalone: Should be always true ** ** ebi: EPS bearer identity ** ** msg: Encoded ESM message to be sent ** - ** ue_triggered: TRUE if the EPS bearer context procedure ** + ** ue_triggered: true if the EPS bearer context procedure ** ** was triggered by the UE ** ** Others: None ** ** ** @@ -277,8 +277,8 @@ int esm_proc_eps_bearer_context_deactivate_request(nas_user_t *user, int ebi, in ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_eps_bearer_context_deactivate_accept(nas_user_t *user, int is_standalone, int ebi, - OctetString *msg, int ue_triggered) +int esm_proc_eps_bearer_context_deactivate_accept(nas_user_t *user, bool is_standalone, int ebi, + OctetString *msg, bool ue_triggered) { LOG_FUNC_IN; @@ -371,7 +371,7 @@ static int _eps_bearer_release(nas_user_t *user, int ebi, int *pid, int *bid) LOG_TRACE(WARNING, "ESM-PROC - Failed to release EPS bearer context"); } else { /* Set the EPS bearer context state to INACTIVE */ - rc = esm_ebr_set_status(user_api_id, esm_ebr_data, ebi, ESM_EBR_INACTIVE, FALSE); + rc = esm_ebr_set_status(user_api_id, esm_ebr_data, ebi, ESM_EBR_INACTIVE, false); if (rc != RETURNok) { /* The EPS bearer context was already in INACTIVE state */ diff --git a/openair3/NAS/UE/ESM/EsmStatusHdl.c b/openair3/NAS/UE/ESM/EsmStatusHdl.c index def498a89b..88f6550251 100644 --- a/openair3/NAS/UE/ESM/EsmStatusHdl.c +++ b/openair3/NAS/UE/ESM/EsmStatusHdl.c @@ -149,7 +149,7 @@ int esm_proc_status_ind( ** ** ** Description: Initiates ESM status procedure. ** ** ** - ** Inputs: is_standalone: Not used - Always TRUE ** + ** Inputs: is_standalone: Not used - Always true ** ** ueid: UE lower layer identifier ** ** ebi: Not used ** ** msg: Encoded ESM status message to be sent ** @@ -161,9 +161,9 @@ int esm_proc_status_ind( ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_status(nas_user_t *user, int is_standalone, +int esm_proc_status(nas_user_t *user, bool is_standalone, int ebi, OctetString *msg, - int ue_triggered) + bool ue_triggered) { LOG_FUNC_IN; diff --git a/openair3/NAS/UE/ESM/PdnConnectivity.c b/openair3/NAS/UE/ESM/PdnConnectivity.c index d17b5fde3c..a79320cccb 100644 --- a/openair3/NAS/UE/ESM/PdnConnectivity.c +++ b/openair3/NAS/UE/ESM/PdnConnectivity.c @@ -80,7 +80,7 @@ Description Defines the PDN connectivity ESM procedure executed by the * PDN connection handlers */ static int _pdn_connectivity_create(esm_data_t *esm_data, int pid, const OctetString *apn, - esm_proc_pdn_type_t pdn_type, int is_emergency); + esm_proc_pdn_type_t pdn_type, bool is_emergency); static int _pdn_connectivity_update(esm_data_t *esm_data, int pid, const OctetString *apn, esm_proc_pdn_type_t pdn_type, const OctetString *pdn_addr, int esm_cause); static int _pdn_connectivity_delete(esm_data_t *esm_data, int pid); @@ -121,7 +121,7 @@ static void *_pdn_connectivity_t3482_handler(void *); ** to be defined or undefined ** ** pdn_type: PDN connection type (IPv4, IPv6, IPv4v6) ** ** apn: Access Point logical Name to be used ** - ** is_emergency: TRUE if the PDN connection has to be esta- ** + ** is_emergency: true if the PDN connection has to be esta- ** ** blished for emergency bearer services ** ** Others: None ** ** ** @@ -133,7 +133,7 @@ static void *_pdn_connectivity_t3482_handler(void *); ***************************************************************************/ int esm_proc_pdn_connectivity(nas_user_t *user, int cid, int is_to_define, esm_proc_pdn_type_t pdn_type, - const OctetString *apn, int is_emergency, + const OctetString *apn, bool is_emergency, unsigned int *pti) { LOG_FUNC_IN; @@ -270,7 +270,7 @@ int esm_proc_pdn_connectivity(nas_user_t *user, int cid, int is_to_define, ** pti: Procedure transaction identity ** ** msg: Encoded PDN connectivity request message ** ** to be sent ** - ** sent_by_ue: Not used - Always TRUE ** + ** sent_by_ue: Not used - Always true ** ** Others: None ** ** ** ** Outputs: None ** @@ -278,8 +278,8 @@ int esm_proc_pdn_connectivity(nas_user_t *user, int cid, int is_to_define, ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_pdn_connectivity_request(nas_user_t *user, int is_standalone, int pti, - OctetString *msg, int sent_by_ue) +int esm_proc_pdn_connectivity_request(nas_user_t *user, bool is_standalone, int pti, + OctetString *msg, bool sent_by_ue) { LOG_FUNC_IN; esm_pt_data_t *esm_pt_data = user->esm_pt_data; @@ -523,7 +523,7 @@ int esm_proc_pdn_connectivity_complete(nas_user_t *user) ** PDN connectivity procedure which is still pending in the ** ** PROCEDURE TRANSACTION INACTIVE or PENDING state. ** ** ** - ** Inputs: is_pending: TRUE if this PDN connectivity procedure ** + ** Inputs: is_pending: true if this PDN connectivity procedure ** ** transaction is in the PENDING state ** ** Others: None ** ** ** @@ -679,7 +679,7 @@ static void *_pdn_connectivity_t3482_handler(void *args) ** Inputs: pid: Identifier of the PDN connection entry ** ** apn: Access Point Name of the PDN connection ** ** pdn_type: PDN type (IPv4, IPv6, IPv4v6) ** - ** is_emergency: TRUE if the PDN connection has to be esta- ** + ** is_emergency: true if the PDN connection has to be esta- ** ** blished for emergency bearer services ** ** ** ** Outputs: None ** @@ -688,7 +688,7 @@ static void *_pdn_connectivity_t3482_handler(void *args) ***************************************************************************/ static int _pdn_connectivity_create(esm_data_t *esm_data, int pid, const OctetString *apn, esm_proc_pdn_type_t pdn_type, - int is_emergency) + bool is_emergency) { esm_pdn_t *pdn = NULL; @@ -720,7 +720,7 @@ static int _pdn_connectivity_create(esm_data_t *esm_data, int pid, const OctetSt /* Set the PDN connection identifier */ esm_data->pdn[pid].pid = pid; /* Reset the PDN connection active indicator */ - esm_data->pdn[pid].is_active = FALSE; + esm_data->pdn[pid].is_active = false; /* Setup the PDN connection data */ esm_data->pdn[pid].data = pdn; } @@ -744,7 +744,7 @@ static int _pdn_connectivity_create(esm_data_t *esm_data, int pid, const OctetSt } pdn->type = pdn_type; - pdn->addr_realloc = FALSE; + pdn->addr_realloc = false; return (RETURNok); } @@ -825,7 +825,7 @@ static int _pdn_connectivity_update(esm_data_t *esm_data, int pid, const OctetSt * the other IP version using the UE requested PDN connectivity * procedure to the same APN with a single address PDN type * (IPv4 or IPv6) other than the one already activated */ - pdn->addr_realloc = TRUE; + pdn->addr_realloc = true; } else if ( (esm_cause == ESM_CAUSE_PDN_TYPE_IPV4_ONLY_ALLOWED) || (esm_cause == ESM_CAUSE_PDN_TYPE_IPV6_ONLY_ALLOWED) ) { /* The UE requested IPv4 or IPv6 address and the network allows @@ -833,9 +833,9 @@ static int _pdn_connectivity_update(esm_data_t *esm_data, int pid, const OctetSt * The UE shall not subsequently initiate another UE requested * PDN connectivity procedure to the same APN to obtain a PDN * type different from the one allowed by the network */ - pdn->addr_realloc = FALSE; + pdn->addr_realloc = false; } else if (pdn_type != ESM_PDN_TYPE_IPV4V6) { - pdn->addr_realloc = TRUE; + pdn->addr_realloc = true; } return (RETURNok); diff --git a/openair3/NAS/UE/ESM/PdnDisconnect.c b/openair3/NAS/UE/ESM/PdnDisconnect.c index 6665126e40..cb7b3225bc 100644 --- a/openair3/NAS/UE/ESM/PdnDisconnect.c +++ b/openair3/NAS/UE/ESM/PdnDisconnect.c @@ -155,7 +155,7 @@ int esm_proc_pdn_disconnect(esm_data_t *esm_data, int cid, unsigned int *pti, un ** PDN DISCONNECT REQUEST message to the MME, starting timer ** ** T3492 and entering state PROCEDURE TRANSACTION PENDING. ** ** ** - ** Inputs: is_standalone: Should be always TRUE ** + ** Inputs: is_standalone: Should be always true ** ** pti: Procedure transaction identity ** ** msg: Encoded PDN disconnect request message to ** ** be sent ** @@ -167,8 +167,8 @@ int esm_proc_pdn_disconnect(esm_data_t *esm_data, int cid, unsigned int *pti, un ** Others: None ** ** ** ***************************************************************************/ -int esm_proc_pdn_disconnect_request(nas_user_t *user, int is_standalone, int pti, - OctetString *msg, int sent_by_ue) +int esm_proc_pdn_disconnect_request(nas_user_t *user, bool is_standalone, int pti, + OctetString *msg, bool sent_by_ue) { LOG_FUNC_IN; @@ -326,7 +326,7 @@ int esm_proc_pdn_disconnect_reject(nas_user_t *user, int pti, int *esm_cause) */ esm_sap_t esm_sap; esm_sap.primitive = ESM_EPS_BEARER_CONTEXT_DEACTIVATE_REQ; - esm_sap.is_standalone = TRUE; + esm_sap.is_standalone = true; esm_sap.recv = NULL; esm_sap.send.length = 0; esm_sap.data.eps_bearer_context_deactivate.ebi = ebi; @@ -444,7 +444,7 @@ static void *_pdn_disconnect_t3492_handler(void *args) */ esm_sap_t esm_sap; esm_sap.primitive = ESM_EPS_BEARER_CONTEXT_DEACTIVATE_REQ; - esm_sap.is_standalone = TRUE; + esm_sap.is_standalone = true; esm_sap.recv = NULL; esm_sap.send.length = 0; esm_sap.data.eps_bearer_context_deactivate.ebi = ebi; diff --git a/openair3/NAS/UE/ESM/SAP/esm_sap.c b/openair3/NAS/UE/ESM/SAP/esm_sap.c index e039f66a3a..f1663175d4 100644 --- a/openair3/NAS/UE/ESM/SAP/esm_sap.c +++ b/openair3/NAS/UE/ESM/SAP/esm_sap.c @@ -63,9 +63,9 @@ Description Defines the ESM Service Access Points at which the EPS /******************* L O C A L D E F I N I T I O N S *******************/ /****************************************************************************/ -static int _esm_sap_recv(nas_user_t *user, int msg_type, int is_standalone, +static int _esm_sap_recv(nas_user_t *user, int msg_type, bool is_standalone, const OctetString *req, OctetString *rsp, esm_sap_error_t *err); -static int _esm_sap_send(nas_user_t *user, int msg_type, int is_standalone, int pti, int ebi, +static int _esm_sap_send(nas_user_t *user, int msg_type, bool is_standalone, int pti, int ebi, const esm_sap_data_t *data, OctetString *rsp); @@ -171,7 +171,7 @@ int esm_sap_send(nas_user_t *user, esm_sap_t *msg) } /* Define new PDN context */ - rc = esm_proc_pdn_connectivity(user, pdn_connect->cid, TRUE, + rc = esm_proc_pdn_connectivity(user, pdn_connect->cid, true, pdn_connect->pdn_type, &apn, pdn_connect->is_emergency, NULL); @@ -183,7 +183,7 @@ int esm_sap_send(nas_user_t *user, esm_sap_t *msg) if (pdn_connect->is_defined) { unsigned int pti; /* Assign new procedure transaction identity */ - rc = esm_proc_pdn_connectivity(user, pdn_connect->cid, TRUE, + rc = esm_proc_pdn_connectivity(user, pdn_connect->cid, true, pdn_connect->pdn_type, NULL, pdn_connect->is_emergency, &pti); @@ -205,7 +205,7 @@ int esm_sap_send(nas_user_t *user, esm_sap_t *msg) if ( msg->is_standalone && pdn_connect->is_defined ) { /* Undefine the specified PDN context */ - rc = esm_proc_pdn_connectivity(user, pdn_connect->cid, FALSE, + rc = esm_proc_pdn_connectivity(user, pdn_connect->cid, false, pdn_connect->pdn_type, NULL, pdn_connect->is_emergency, NULL); } else if (msg->recv != NULL) { @@ -214,7 +214,7 @@ int esm_sap_send(nas_user_t *user, esm_sap_t *msg) msg->recv, &msg->send, &msg->err); } else { /* The PDN connectivity procedure locally failed */ - rc = esm_proc_pdn_connectivity_failure(user, TRUE); + rc = esm_proc_pdn_connectivity_failure(user, true); } } break; @@ -230,7 +230,7 @@ int esm_sap_send(nas_user_t *user, esm_sap_t *msg) if (rc != RETURNerror) { /* Send PDN disconnect request */ - rc = _esm_sap_send(user, PDN_DISCONNECT_REQUEST, TRUE, pti, ebi, + rc = _esm_sap_send(user, PDN_DISCONNECT_REQUEST, true, pti, ebi, &msg->data, &msg->send); } } @@ -278,7 +278,7 @@ int esm_sap_send(nas_user_t *user, esm_sap_t *msg) rc = esm_proc_default_eps_bearer_context_failure(user); if (rc != RETURNerror) { - rc = esm_proc_pdn_connectivity_failure(user, FALSE); + rc = esm_proc_pdn_connectivity_failure(user, false); } break; @@ -306,7 +306,7 @@ int esm_sap_send(nas_user_t *user, esm_sap_t *msg) /* * Locally deactivate EPS bearer context */ - rc = esm_proc_eps_bearer_context_deactivate(user, TRUE, + rc = esm_proc_eps_bearer_context_deactivate(user, true, msg->data.eps_bearer_context_deactivate.ebi, &pid, &bid); } break; @@ -359,7 +359,7 @@ int esm_sap_send(nas_user_t *user, esm_sap_t *msg) ** Return: RETURNok, RETURNerror ** ** ** ***************************************************************************/ -static int _esm_sap_recv(nas_user_t *user, int msg_type, int is_standalone, +static int _esm_sap_recv(nas_user_t *user, int msg_type, bool is_standalone, const OctetString *req, OctetString *rsp, esm_sap_error_t *err) { @@ -422,7 +422,7 @@ static int _esm_sap_recv(nas_user_t *user, int msg_type, int is_standalone, * was triggered network-internally */ int triggered_by_ue = (pti != PROCEDURE_TRANSACTION_IDENTITY_UNASSIGNED); /* Indicate whether the received message shall be ignored */ - int is_discarded = FALSE; + bool is_discarded = false; if (esm_cause != ESM_CAUSE_SUCCESS) { LOG_TRACE(ERROR, "ESM-SAP - Failed to decode expected ESM message " @@ -455,7 +455,7 @@ static int _esm_sap_recv(nas_user_t *user, int msg_type, int is_standalone, * of already accepted activate default EPS bearer context * request message */ - is_discarded = TRUE; + is_discarded = true; } } else { /* Return reject message */ @@ -493,7 +493,7 @@ static int _esm_sap_recv(nas_user_t *user, int msg_type, int is_standalone, * of already accepted activate dedicated EPS bearer context * request message */ - is_discarded = TRUE; + is_discarded = true; } } else { /* Return reject message */ @@ -525,7 +525,7 @@ static int _esm_sap_recv(nas_user_t *user, int msg_type, int is_standalone, * received with PTI reserved value, or assigned value * that does not match any PTI in use */ - is_discarded = TRUE; + is_discarded = true; } else if ( (esm_cause == ESM_CAUSE_SUCCESS) || (esm_cause == ESM_CAUSE_INVALID_EPS_BEARER_IDENTITY) ) { /* Return accept message */ @@ -541,7 +541,7 @@ static int _esm_sap_recv(nas_user_t *user, int msg_type, int is_standalone, * message with the EPS bearer identity set to the received * EPS bearer identity */ - is_discarded = TRUE; + is_discarded = true; } } @@ -565,7 +565,7 @@ static int _esm_sap_recv(nas_user_t *user, int msg_type, int is_standalone, * Ignore PDN connectivity reject message received with * reserved or unassigned EPS bearer identity value */ - is_discarded = TRUE; + is_discarded = true; } break; @@ -588,7 +588,7 @@ static int _esm_sap_recv(nas_user_t *user, int msg_type, int is_standalone, * Ignore PDN disconnect reject message received with * reserved or unassigned EPS bearer identity value */ - is_discarded = TRUE; + is_discarded = true; } break; @@ -629,7 +629,7 @@ static int _esm_sap_recv(nas_user_t *user, int msg_type, int is_standalone, * onto the network */ esm_procedure = esm_proc_status; /* Discard received ESM message */ - is_discarded = TRUE; + is_discarded = true; } } else { /* ESM message processing succeed */ @@ -687,7 +687,7 @@ static int _esm_sap_recv(nas_user_t *user, int msg_type, int is_standalone, ** Return: RETURNok, RETURNerror ** ** ** ***************************************************************************/ -static int _esm_sap_send(nas_user_t *user, int msg_type, int is_standalone, +static int _esm_sap_send(nas_user_t *user, int msg_type, bool is_standalone, int pti, int ebi, const esm_sap_data_t *data, OctetString *rsp) { @@ -697,7 +697,7 @@ static int _esm_sap_send(nas_user_t *user, int msg_type, int is_standalone, int rc = RETURNok; /* Indicate whether the message is sent by the UE or the MME */ - int sent_by_ue = TRUE; + bool sent_by_ue = true; ESM_msg esm_msg; memset(&esm_msg, 0 , sizeof(ESM_msg)); diff --git a/openair3/NAS/UE/ESM/SAP/esm_sapDef.h b/openair3/NAS/UE/ESM/SAP/esm_sapDef.h index 4ff7c7e9dd..2d3227ba75 100644 --- a/openair3/NAS/UE/ESM/SAP/esm_sapDef.h +++ b/openair3/NAS/UE/ESM/SAP/esm_sapDef.h @@ -109,11 +109,11 @@ typedef struct esm_activate_eps_default_bearer_context_s { */ typedef struct esm_pdn_connectivity_s { int cid; /* PDN connection local identifier */ - int is_defined; /* Indicates whether a PDN context has been defined + bool is_defined; /* Indicates whether a PDN context has been defined * for the specified APN */ int pdn_type; /* PDN address type (IPv4, IPv6, IPv4v6) */ const char *apn; /* PDN's Access Point Name */ - int is_emergency; /* Indicates whether the PDN context has been + bool is_emergency; /* Indicates whether the PDN context has been * defined to establish connection for emergency * bearer services */ } esm_pdn_connectivity_t; @@ -149,7 +149,7 @@ typedef union { typedef struct esm_sap_s { esm_primitive_t primitive; /* ESM-SAP primitive to process */ - int is_standalone; /* Indicates whether the ESM message handled + bool is_standalone; /* Indicates whether the ESM message handled * within this primitive has to be sent/received * standalone or together within an EMM related * message */ diff --git a/openair3/NAS/UE/ESM/SAP/esm_send.c b/openair3/NAS/UE/ESM/SAP/esm_send.c index 020d9d89e3..e710d745ad 100644 --- a/openair3/NAS/UE/ESM/SAP/esm_send.c +++ b/openair3/NAS/UE/ESM/SAP/esm_send.c @@ -132,7 +132,7 @@ int esm_send_status(int pti, int ebi, esm_status_msg *msg, int esm_cause) ** Others: None ** ** ** ***************************************************************************/ -int esm_send_pdn_connectivity_request(int pti, int is_emergency, int pdn_type, +int esm_send_pdn_connectivity_request(int pti, bool is_emergency, int pdn_type, const char *apn, pdn_connectivity_request_msg *msg) { diff --git a/openair3/NAS/UE/ESM/SAP/esm_send.h b/openair3/NAS/UE/ESM/SAP/esm_send.h index f97454027a..b9bcab0f39 100644 --- a/openair3/NAS/UE/ESM/SAP/esm_send.h +++ b/openair3/NAS/UE/ESM/SAP/esm_send.h @@ -40,6 +40,8 @@ Description Defines functions executed at the ESM Service Access #ifndef __ESM_SEND_H__ #define __ESM_SEND_H__ +#include + #include "EsmStatus.h" @@ -90,7 +92,7 @@ int esm_send_status(int pti, int ebi, esm_status_msg *msg, int esm_cause); * Transaction related messages * ---------------------------- */ -int esm_send_pdn_connectivity_request(int pti, int is_emergency, int pdn_type, +int esm_send_pdn_connectivity_request(int pti, bool is_emergency, int pdn_type, const char *apn, pdn_connectivity_request_msg *msg); int esm_send_pdn_disconnect_request(int pti, int ebi, pdn_disconnect_request_msg *msg); diff --git a/openair3/NAS/UE/ESM/esmData.h b/openair3/NAS/UE/ESM/esmData.h index 16f4707a37..525f4ec00a 100644 --- a/openair3/NAS/UE/ESM/esmData.h +++ b/openair3/NAS/UE/ESM/esmData.h @@ -37,6 +37,7 @@ Description Defines internal private data handled by EPS Session *****************************************************************************/ #include // sprintf +#include #include "networkDef.h" #include "OctetString.h" @@ -92,7 +93,7 @@ typedef enum { typedef struct esm_ebr_context_s { unsigned char ebi; /* EPS bearer identity */ esm_ebr_state status; /* EPS bearer context status */ - int is_default_ebr; /* TRUE if the bearer context is associated + bool is_default_ebr; /* bool if the bearer context is associated * to a default EPS bearer */ char cid; /* Identifier of the PDN context the EPS * bearer context has been assigned to */ @@ -137,7 +138,7 @@ typedef struct esm_bearer_s { typedef struct esm_pdn_s { unsigned int pti; /* Identity of the procedure transaction executed * to activate the PDN connection entry */ - int is_emergency; /* Emergency bearer services indicator */ + bool is_emergency; /* Emergency bearer services indicator */ OctetString apn; /* Access Point Name currently in used */ int ambr; /* Aggregate Maximum Bit Rate of this APN */ int type; /* Address PDN type (IPv4, IPv6, IPv4v6) */ @@ -147,7 +148,7 @@ typedef struct esm_pdn_s { ESM_DATA_IPV6_ADDRESS_SIZE) /* IPv4 PDN address and/or IPv6 prefix */ char ip_addr[ESM_DATA_IP_ADDRESS_SIZE+1]; - int addr_realloc; /* Indicates whether the UE is allowed to subsequently + bool addr_realloc; /* Indicates whether the UE is allowed to subsequently * request another PDN connectivity to the same APN * using an address PDN type (IPv4 or IPv6) other * than the one already activated */ @@ -175,7 +176,7 @@ typedef struct esm_data_context_s { #define ESM_DATA_PDN_MAX 4 struct { int pid; /* Identifier of the PDN connection */ - int is_active; /* TRUE/FALSE if the PDN connection is active/inactive + bool is_active; /* true/false if the PDN connection is active/inactive * or the process to activate/deactivate the PDN * connection is in progress */ esm_pdn_t *data; /* Active PDN connection data */ diff --git a/openair3/NAS/UE/ESM/esm_ebr.c b/openair3/NAS/UE/ESM/esm_ebr.c index 3a62812eca..4c6b56cec9 100644 --- a/openair3/NAS/UE/ESM/esm_ebr.c +++ b/openair3/NAS/UE/ESM/esm_ebr.c @@ -153,7 +153,7 @@ void esm_ebr_register_callback(esm_indication_callback_t cb) ** ebi: Identity of the new EPS bearer context ** ** cid: Identifier of the PDN context the EPS bea- ** ** rer context is associated to ** - ** default_ebr TRUE if the new bearer context is associa- ** + ** default_ebr bool if the new bearer context is associa- ** ** ted to a default EPS bearer ** ** Others: None ** ** ** @@ -163,7 +163,7 @@ void esm_ebr_register_callback(esm_indication_callback_t cb) ** the not assigned EBI (0) otherwise. ** ** ** ***************************************************************************/ -int esm_ebr_assign(esm_ebr_data_t *esm_ebr_data, int ebi, int cid, int default_ebr) +int esm_ebr_assign(esm_ebr_data_t *esm_ebr_data, int ebi, int cid, bool default_ebr) { esm_ebr_context_t *ebr_ctx = NULL; int i; @@ -284,7 +284,7 @@ int esm_ebr_release(esm_ebr_data_t *esm_ebr_data, ** ** ** ebi: The identity of the EPS bearer ** ** status: The new EPS bearer context status ** - ** ue_requested: TRUE/FALSE if the modification of the EPS ** + ** ue_requested: true/false if the modification of the EPS ** ** bearer context status was requested by the ** ** UE/network ** ** Others: None ** @@ -294,7 +294,7 @@ int esm_ebr_release(esm_ebr_data_t *esm_ebr_data, ** ** ***************************************************************************/ int esm_ebr_set_status(user_api_id_t *user_api_id, esm_ebr_data_t *esm_ebr_data, - int ebi, esm_ebr_state status, int ue_requested) + int ebi, esm_ebr_state status, bool ue_requested) { esm_ebr_context_t *ebr_ctx; esm_ebr_state old_status; @@ -385,11 +385,11 @@ esm_ebr_state esm_ebr_get_status(esm_ebr_data_t *esm_ebr_data, ** Others: None ** ** ** ** Outputs: None ** - ** Return: TRUE, FALSE ** + ** Return: true, false ** ** Others: None ** ** ** ***************************************************************************/ -int esm_ebr_is_reserved(esm_ebr_data_t *esm_ebr_data, int ebi) +bool esm_ebr_is_reserved(esm_ebr_data_t *esm_ebr_data, int ebi) { return ( (ebi != ESM_EBI_UNASSIGNED) && (ebi < ESM_EBI_MIN) ); } @@ -404,12 +404,11 @@ int esm_ebr_is_reserved(esm_ebr_data_t *esm_ebr_data, int ebi) ** ebi: The identity of the EPS bearer ** ** ** ** Outputs: None ** - ** Return: TRUE, FALSE ** + ** Return: true, false ** ** Others: None ** ** ** ***************************************************************************/ -int esm_ebr_is_not_in_use(esm_ebr_data_t *esm_ebr_data, - int ebi) +bool esm_ebr_is_not_in_use(esm_ebr_data_t *esm_ebr_data, int ebi) { return ( (ebi == ESM_EBI_UNASSIGNED) || diff --git a/openair3/NAS/UE/ESM/esm_ebr.h b/openair3/NAS/UE/ESM/esm_ebr.h index 6de4a048a4..4447a227ba 100644 --- a/openair3/NAS/UE/ESM/esm_ebr.h +++ b/openair3/NAS/UE/ESM/esm_ebr.h @@ -75,15 +75,15 @@ typedef int (*esm_indication_callback_t) (user_api_id_t *user_api_id, int, netwo void esm_ebr_register_callback(esm_indication_callback_t cb); -int esm_ebr_is_reserved(esm_ebr_data_t *esm_ebr_data, int ebi); +bool esm_ebr_is_reserved(esm_ebr_data_t *esm_ebr_data, int ebi); esm_ebr_data_t *esm_ebr_initialize(void); -int esm_ebr_assign(esm_ebr_data_t *esm_ebr_data, int ebi, int cid, int default_ebr); +int esm_ebr_assign(esm_ebr_data_t *esm_ebr_data, int ebi, int cid, bool default_ebr); int esm_ebr_release(esm_ebr_data_t *esm_ebr_data, int ebi); -int esm_ebr_set_status(user_api_id_t *user_api_id, esm_ebr_data_t *esm_ebr_data, int ebi, esm_ebr_state status, int ue_requested); +int esm_ebr_set_status(user_api_id_t *user_api_id, esm_ebr_data_t *esm_ebr_data, int ebi, esm_ebr_state status, bool ue_requested); esm_ebr_state esm_ebr_get_status(esm_ebr_data_t *esm_ebr_data, int ebi); -int esm_ebr_is_not_in_use(esm_ebr_data_t *esm_ebr_data, int ebi); +bool esm_ebr_is_not_in_use(esm_ebr_data_t *esm_ebr_data, int ebi); #endif /* __ESM_EBR_H__*/ diff --git a/openair3/NAS/UE/ESM/esm_ebr_context.c b/openair3/NAS/UE/ESM/esm_ebr_context.c index b801ca2ad5..ca69687abe 100644 --- a/openair3/NAS/UE/ESM/esm_ebr_context.c +++ b/openair3/NAS/UE/ESM/esm_ebr_context.c @@ -84,7 +84,7 @@ static int _esm_ebr_context_check_precedence(const network_tft_t *, ** Inputs: ** ** pid: PDN connection identifier ** ** ebi: EPS bearer identity ** - ** is_default: TRUE if the new bearer is a default EPS ** + ** is_default: true if the new bearer is a default EPS ** ** bearer context ** ** esm_qos: EPS bearer level QoS parameters ** ** tft: Traffic flow template parameters ** @@ -98,7 +98,7 @@ static int _esm_ebr_context_check_precedence(const network_tft_t *, ***************************************************************************/ int esm_ebr_context_create( esm_data_t *esm_data, int ueid, - int pid, int ebi, int is_default, + int pid, int ebi, bool is_default, const network_qos_t *qos, const network_tft_t *tft) { int bid = 0; esm_data_context_t *esm_ctx = NULL; @@ -185,11 +185,11 @@ int esm_ebr_context_create( if (is_default) { /* Set the PDN connection activation indicator */ - esm_ctx->pdn[pid].is_active = TRUE; + esm_ctx->pdn[pid].is_active = true; /* Update the emergency bearer services indicator */ if (pdn->is_emergency) { - esm_ctx->emergency = TRUE; + esm_ctx->emergency = true; } // LG ADD TEMP @@ -383,7 +383,7 @@ int esm_ebr_context_create( ***************************************************************************/ int esm_ebr_context_release(nas_user_t *user, int ebi, int *pid, int *bid) { - int found = FALSE; + bool found = false; esm_pdn_t *pdn = NULL; esm_data_context_t *esm_ctx; esm_ebr_data_t *esm_ebr_data = user->esm_ebr_data; @@ -416,7 +416,7 @@ int esm_ebr_context_release(nas_user_t *user, } /* The EPS bearer context entry is found */ - found = TRUE; + found = true; break; } } @@ -450,7 +450,7 @@ int esm_ebr_context_release(nas_user_t *user, if (pdn->bearer[*bid] != NULL) { ebi = pdn->bearer[*bid]->ebi; - found = TRUE; + found = true; } } } @@ -503,7 +503,7 @@ int esm_ebr_context_release(nas_user_t *user, /* Set the EPS bearer context state to INACTIVE */ esm_ebr_set_status(user_api_id, esm_ebr_data, pdn->bearer[i]->ebi, - ESM_EBR_INACTIVE, TRUE); + ESM_EBR_INACTIVE, true); /* Release EPS bearer data */ esm_ebr_release(esm_ebr_data, pdn->bearer[i]->ebi); // esm_ebr_release() @@ -519,11 +519,11 @@ int esm_ebr_context_release(nas_user_t *user, } /* Reset the PDN connection activation indicator */ - esm_ctx->pdn[*pid].is_active = FALSE; + esm_ctx->pdn[*pid].is_active = false; /* Update the emergency bearer services indicator */ if (pdn->is_emergency) { - esm_ctx->emergency = FALSE; + esm_ctx->emergency = false; } } @@ -534,7 +534,7 @@ int esm_ebr_context_release(nas_user_t *user, if (esm_ctx->n_ebrs == 0) { emm_sap_t emm_sap; emm_sap.primitive = EMMESM_ESTABLISH_CNF; - emm_sap.u.emm_esm.u.establish.is_attached = FALSE; + emm_sap.u.emm_esm.u.establish.is_attached = false; (void) emm_sap_send(user, &emm_sap); } /* 3GPP TS 24.301, section 6.4.4.3, 6.4.4.6 @@ -546,8 +546,8 @@ int esm_ebr_context_release(nas_user_t *user, else if (esm_ctx->emergency && (esm_ctx->n_ebrs == 1) ) { emm_sap_t emm_sap; emm_sap.primitive = EMMESM_ESTABLISH_CNF; - emm_sap.u.emm_esm.u.establish.is_attached = TRUE; - emm_sap.u.emm_esm.u.establish.is_emergency = TRUE; + emm_sap.u.emm_esm.u.establish.is_attached = true; + emm_sap.u.emm_esm.u.establish.is_emergency = true; (void) emm_sap_send(user, &emm_sap); } diff --git a/openair3/NAS/UE/ESM/esm_ebr_context.h b/openair3/NAS/UE/ESM/esm_ebr_context.h index d7dfb1da70..c72f3f0e8b 100644 --- a/openair3/NAS/UE/ESM/esm_ebr_context.h +++ b/openair3/NAS/UE/ESM/esm_ebr_context.h @@ -66,7 +66,7 @@ typedef enum { /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -int esm_ebr_context_create(esm_data_t *esm_data, int ueid, int pid, int ebi, int is_default, +int esm_ebr_context_create(esm_data_t *esm_data, int ueid, int pid, int ebi, bool is_default, const network_qos_t *qos, const network_tft_t *tft); int esm_ebr_context_release(nas_user_t *user, int ebi, int *pid, int *bid); diff --git a/openair3/NAS/UE/ESM/esm_main.c b/openair3/NAS/UE/ESM/esm_main.c index 288e748679..895e463726 100644 --- a/openair3/NAS/UE/ESM/esm_main.c +++ b/openair3/NAS/UE/ESM/esm_main.c @@ -96,12 +96,12 @@ void esm_main_initialize(nas_user_t *user, esm_indication_callback_t cb) for (i = 0; i < ESM_DATA_PDN_MAX + 1; i++) { esm_data->pdn[i].pid = -1; - esm_data->pdn[i].is_active = FALSE; + esm_data->pdn[i].is_active = false; esm_data->pdn[i].data = NULL; } /* Emergency bearer services indicator */ - esm_data->emergency = FALSE; + esm_data->emergency = false; /* Initialize the procedure transaction identity manager */ @@ -225,12 +225,12 @@ int esm_main_get_nb_pdns(esm_data_t *esm_data) ** Inputs: None ** ** ** ** Outputs: None ** - ** Return: TRUE if a PDN connection for emergency ** + ** Return: true if a PDN connection for emergency ** ** bearer services is established ** ** Others: None ** ** ** ***************************************************************************/ -int esm_main_has_emergency(esm_data_t *esm_data) +bool esm_main_has_emergency(esm_data_t *esm_data) { LOG_FUNC_IN; @@ -245,16 +245,16 @@ int esm_main_has_emergency(esm_data_t *esm_data) ** ** ** Inputs: cid: PDN connection identifier ** ** ** - ** Outputs: state: TRUE if the current state of the PDN con- ** - ** nection is ACTIVE; FALSE otherwise. ** - ** Return: TRUE if the specified PDN connection has a ** - ** PDN context defined; FALSE if no any PDN ** + ** Outputs: state: true if the current state of the PDN con- ** + ** nection is ACTIVE; false otherwise. ** + ** Return: true if the specified PDN connection has a ** + ** PDN context defined; false if no any PDN ** ** context has been defined for the specified ** ** connection. ** ** Others: None ** ** ** ***************************************************************************/ -int esm_main_get_pdn_status(nas_user_t *user, int cid, int *state) +bool esm_main_get_pdn_status(nas_user_t *user, int cid, bool *state) { LOG_FUNC_IN; @@ -263,14 +263,14 @@ int esm_main_get_pdn_status(nas_user_t *user, int cid, int *state) esm_ebr_data_t *esm_ebr_data = user-> esm_ebr_data; if (pid >= ESM_DATA_PDN_MAX) { - return (FALSE); + return (false); } else if (pid != esm_data->pdn[pid].pid) { LOG_TRACE(WARNING, "ESM-MAIN - PDN connection %d is not defined", cid); - return (FALSE); + return (false); } else if (esm_data->pdn[pid].data == NULL) { LOG_TRACE(ERROR, "ESM-MAIN - PDN connection %d has not been allocated", cid); - return (FALSE); + return (false); } if (esm_data->pdn[pid].data->bearer[0] != NULL) { @@ -281,7 +281,7 @@ int esm_main_get_pdn_status(nas_user_t *user, int cid, int *state) } /* The PDN connection has not been activated yet */ - LOG_FUNC_RETURN (TRUE); + LOG_FUNC_RETURN (true); } /**************************************************************************** @@ -301,7 +301,7 @@ int esm_main_get_pdn_status(nas_user_t *user, int cid, int *state) ** ** ***************************************************************************/ int esm_main_get_pdn(esm_data_t *esm_data, int cid, int *type, const char **apn, - int *is_emergency, int *is_active) + bool *is_emergency, bool *is_active) { LOG_FUNC_IN; diff --git a/openair3/NAS/UE/ESM/esm_main.h b/openair3/NAS/UE/ESM/esm_main.h index 6e6ecc0db4..ca8679c5b7 100644 --- a/openair3/NAS/UE/ESM/esm_main.h +++ b/openair3/NAS/UE/ESM/esm_main.h @@ -69,10 +69,9 @@ void esm_main_cleanup(esm_data_t *esm_data); /* User's getter for PDN connections and EPS bearer contexts */ int esm_main_get_nb_pdns_max(esm_data_t *esm_data); int esm_main_get_nb_pdns(esm_data_t *esm_data); -int esm_main_has_emergency(esm_data_t *esm_data); -int esm_main_get_pdn_status(nas_user_t *user, int cid, int *state); -int esm_main_get_pdn(esm_data_t *esm_data, int cid, int *type, const char **apn, int *is_emergency, - int *is_active); +bool esm_main_has_emergency(esm_data_t *esm_data); +bool esm_main_get_pdn_status(nas_user_t *user, int cid, bool *state); +int esm_main_get_pdn(esm_data_t *esm_data, int cid, int *type, const char **apn, bool *is_emergency, bool *is_active); int esm_main_get_pdn_addr(esm_data_t *esm_data, int cid, const char **ipv4addr, const char **ipv6addr); diff --git a/openair3/NAS/UE/ESM/esm_proc.h b/openair3/NAS/UE/ESM/esm_proc.h index 941cfa620d..42a925327e 100644 --- a/openair3/NAS/UE/ESM/esm_proc.h +++ b/openair3/NAS/UE/ESM/esm_proc.h @@ -79,7 +79,7 @@ typedef enum { * Type of the ESM procedure callback executed when requested by the UE * or initiated by the network */ -typedef int (*esm_proc_procedure_t) (nas_user_t *user, int, int, OctetString *, int); +typedef int (*esm_proc_procedure_t) (nas_user_t *user, bool, int, OctetString *, bool); /* EPS bearer level QoS parameters */ typedef network_qos_t esm_proc_qos_t; @@ -113,8 +113,7 @@ typedef struct { * -------------------------------------------------------------------------- */ int esm_proc_status_ind(int pti, int ebi, int *esm_cause); -int esm_proc_status(nas_user_t *user, int is_standalone, int pti, OctetString *msg, - int sent_by_ue); +int esm_proc_status(nas_user_t *user, bool is_standalone, int pti, OctetString *msg, bool sent_by_ue); /* @@ -123,10 +122,10 @@ int esm_proc_status(nas_user_t *user, int is_standalone, int pti, OctetString *m * -------------------------------------------------------------------------- */ int esm_proc_pdn_connectivity(nas_user_t *user, int cid, int to_define, - esm_proc_pdn_type_t pdn_type, const OctetString *apn, int is_emergency, + esm_proc_pdn_type_t pdn_type, const OctetString *apn, bool is_emergency, unsigned int *pti); -int esm_proc_pdn_connectivity_request(nas_user_t *user, int is_standalone, int pti, - OctetString *msg, int sent_by_ue); +int esm_proc_pdn_connectivity_request(nas_user_t *user, bool is_standalone, int pti, + OctetString *msg, bool sent_by_ue); int esm_proc_pdn_connectivity_accept(nas_user_t *user, int pti, esm_proc_pdn_type_t pdn_type, const OctetString *pdn_address, const OctetString *apn, int *esm_cause); int esm_proc_pdn_connectivity_reject(nas_user_t *user, int pti, int *esm_cause); @@ -140,8 +139,8 @@ int esm_proc_pdn_connectivity_failure(nas_user_t *user, int is_pending); * -------------------------------------------------------------------------- */ int esm_proc_pdn_disconnect(esm_data_t *esm_data, int cid, unsigned int *pti, unsigned int *ebi); -int esm_proc_pdn_disconnect_request(nas_user_t *user, int is_standalone, int pti, - OctetString *msg, int sent_by_ue); +int esm_proc_pdn_disconnect_request(nas_user_t *user, bool is_standalone, int pti, + OctetString *msg, bool sent_by_ue); int esm_proc_pdn_disconnect_accept(esm_pt_data_t *esm_pt_data, int pti, int *esm_cause); int esm_proc_pdn_disconnect_reject(nas_user_t *user, int pti, int *esm_cause); @@ -157,10 +156,10 @@ int esm_proc_default_eps_bearer_context_request(nas_user_t *user, int pid, int e int esm_proc_default_eps_bearer_context_complete(default_eps_bearer_context_data_t *default_eps_bearer_context_data); int esm_proc_default_eps_bearer_context_failure(nas_user_t *user); -int esm_proc_default_eps_bearer_context_accept(nas_user_t *user, int is_standalone, int ebi, - OctetString *msg, int ue_triggered); -int esm_proc_default_eps_bearer_context_reject(nas_user_t *user, int is_standalone, int ebi, - OctetString *msg, int ue_triggered); +int esm_proc_default_eps_bearer_context_accept(nas_user_t *user, bool is_standalone, int ebi, + OctetString *msg, bool ue_triggered); +int esm_proc_default_eps_bearer_context_reject(nas_user_t *user, bool is_standalone, int ebi, + OctetString *msg, bool ue_triggered); /* * -------------------------------------------------------------------------- @@ -171,10 +170,10 @@ int esm_proc_default_eps_bearer_context_reject(nas_user_t *user, int is_standalo int esm_proc_dedicated_eps_bearer_context_request(nas_user_t *user, int ebi, int default_ebi, const esm_proc_qos_t *qos, const esm_proc_tft_t *tft, int *esm_cause); -int esm_proc_dedicated_eps_bearer_context_accept(nas_user_t *user, int is_standalone, int ebi, - OctetString *msg, int ue_triggered); -int esm_proc_dedicated_eps_bearer_context_reject(nas_user_t *user, int is_standalone, int ebi, - OctetString *msg, int ue_triggered); +int esm_proc_dedicated_eps_bearer_context_accept(nas_user_t *user, bool is_standalone, int ebi, + OctetString *msg, bool ue_triggered); +int esm_proc_dedicated_eps_bearer_context_reject(nas_user_t *user, bool is_standalone, int ebi, + OctetString *msg, bool ue_triggered); /* * -------------------------------------------------------------------------- @@ -182,11 +181,11 @@ int esm_proc_dedicated_eps_bearer_context_reject(nas_user_t *user, int is_standa * -------------------------------------------------------------------------- */ -int esm_proc_eps_bearer_context_deactivate(nas_user_t *user, int is_local, int ebi, int *pid, +int esm_proc_eps_bearer_context_deactivate(nas_user_t *user, bool is_local, int ebi, int *pid, int *bid); int esm_proc_eps_bearer_context_deactivate_request(nas_user_t *user, int ebi, int *esm_cause); -int esm_proc_eps_bearer_context_deactivate_accept(nas_user_t *user, int is_standalone, int ebi, - OctetString *msg, int ue_triggered); +int esm_proc_eps_bearer_context_deactivate_accept(nas_user_t *user, bool is_standalone, int ebi, + OctetString *msg, bool ue_triggered); #endif /* __ESM_PROC_H__*/ diff --git a/openair3/NAS/UE/ESM/esm_pt.c b/openair3/NAS/UE/ESM/esm_pt.c index f253291fd9..d9f593fb57 100644 --- a/openair3/NAS/UE/ESM/esm_pt.c +++ b/openair3/NAS/UE/ESM/esm_pt.c @@ -482,11 +482,11 @@ int esm_pt_get_pending_pti(esm_pt_data_t *esm_pt_data, esm_pt_state status) ** Inputs: pti: The identity of the procedure transaction ** ** ** ** Outputs: None ** - ** Return: TRUE, FALSE ** + ** Return: true, false ** ** Others: None ** ** ** ***************************************************************************/ -int esm_pt_is_not_in_use(esm_pt_data_t *esm_pt_data, int pti) +bool esm_pt_is_not_in_use(esm_pt_data_t *esm_pt_data, int pti) { return ( (pti == ESM_PT_UNASSIGNED) || (esm_pt_data->context[pti - ESM_PTI_MIN] == NULL) || @@ -504,11 +504,11 @@ int esm_pt_is_not_in_use(esm_pt_data_t *esm_pt_data, int pti) ** Others: None ** ** ** ** Outputs: None ** - ** Return: TRUE, FALSE ** + ** Return: true, false ** ** Others: None ** ** ** ***************************************************************************/ -int esm_pt_is_reserved(int pti) +bool esm_pt_is_reserved(int pti) { return ( (pti != ESM_PT_UNASSIGNED) && (pti > ESM_PTI_MAX) ); } diff --git a/openair3/NAS/UE/ESM/esm_pt.h b/openair3/NAS/UE/ESM/esm_pt.h index 3179e0f47b..b0c62253ab 100644 --- a/openair3/NAS/UE/ESM/esm_pt.h +++ b/openair3/NAS/UE/ESM/esm_pt.h @@ -64,7 +64,7 @@ Description Defines functions used to handle ESM procedure transactions. /****************** E X P O R T E D F U N C T I O N S ******************/ /****************************************************************************/ -int esm_pt_is_reserved(int pti); +bool esm_pt_is_reserved(int pti); esm_pt_data_t *esm_pt_initialize(void); @@ -79,6 +79,6 @@ int esm_pt_set_status(esm_pt_data_t *esm_pt_data, int pti, esm_pt_state status); esm_pt_state esm_pt_get_status(esm_pt_data_t *esm_pt_data, int pti); int esm_pt_get_pending_pti(esm_pt_data_t *esm_pt_data, esm_pt_state status); -int esm_pt_is_not_in_use(esm_pt_data_t *esm_pt_data, int pti); +bool esm_pt_is_not_in_use(esm_pt_data_t *esm_pt_data, int pti); #endif /* __ESM_PT_H__*/ diff --git a/openair3/NAS/UE/UEprocess.c b/openair3/NAS/UE/UEprocess.c index 7b9a1be422..a3a1c9c79b 100644 --- a/openair3/NAS/UE/UEprocess.c +++ b/openair3/NAS/UE/UEprocess.c @@ -205,7 +205,7 @@ static void *_nas_user_mngr(void *args) LOG_FUNC_IN; pthread_setname_np( pthread_self(), "nas_user_mngr"); - int exit_loop = FALSE; + bool exit_loop = false; int *fd = (int *) args; @@ -251,7 +251,7 @@ static void *_nas_network_mngr(void *args) LOG_TRACE (INFO, "UE-MAIN - Network connection manager started (%d)", *fd); /* Network receiving loop */ - while (TRUE) { + while (true) { /* Read the network data message */ bytes = network_api_read_data (*fd); diff --git a/openair3/NAS/UE/nas_proc.c b/openair3/NAS/UE/nas_proc.c index 9350590788..41230696a4 100644 --- a/openair3/NAS/UE/nas_proc.c +++ b/openair3/NAS/UE/nas_proc.c @@ -64,8 +64,8 @@ Description NAS procedure call manager #define NAS_PROC_RSRP_UNKNOWN 255 -static int _nas_proc_activate(nas_user_t *user, int cid, int apply_to_all); -static int _nas_proc_deactivate(nas_user_t *user, int cid, int apply_to_all); +static int _nas_proc_activate(nas_user_t *user, int cid, bool apply_to_all); +static int _nas_proc_deactivate(nas_user_t *user, int cid, bool apply_to_all); /****************************************************************************/ /****************** E X P O R T E D F U N C T I O N S ******************/ @@ -93,7 +93,7 @@ void nas_proc_initialize(nas_user_t *user, emm_indication_callback_t emm_cb, LOG_FUNC_IN; /* Initialize local NAS data */ - user->proc.EPS_capability_status = FALSE; + user->proc.EPS_capability_status = false; user->proc.rsrq = NAS_PROC_RSRQ_UNKNOWN; user->proc.rsrp = NAS_PROC_RSRP_UNKNOWN; @@ -129,7 +129,7 @@ void nas_proc_cleanup(nas_user_t *user) LOG_FUNC_IN; /* Detach the UE from the EPS network */ - int rc = nas_proc_detach(user, TRUE); + int rc = nas_proc_detach(user, true); if (rc != RETURNok) { LOG_TRACE(ERROR, "NAS-PROC - Failed to detach from the network"); @@ -176,7 +176,7 @@ int nas_proc_enable_s1_mode(nas_user_t *user) * Notify the EMM procedure call manager that EPS capability * of the UE is enabled */ - user->proc.EPS_capability_status = TRUE; + user->proc.EPS_capability_status = true; emm_sap.primitive = EMMREG_S1_ENABLED; rc = emm_sap_send(user, &emm_sap); @@ -209,7 +209,7 @@ int nas_proc_disable_s1_mode(nas_user_t *user) * Notify the EMM procedure call manager that EPS capability * of the UE is disabled */ - user->proc.EPS_capability_status = FALSE; + user->proc.EPS_capability_status = false; emm_sap.primitive = EMMREG_S1_DISABLED; rc = emm_sap_send(user, &emm_sap); @@ -231,7 +231,7 @@ int nas_proc_disable_s1_mode(nas_user_t *user) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_eps(nas_user_t *user, int *stat) +int nas_proc_get_eps(nas_user_t *user, bool *stat) { LOG_FUNC_IN; @@ -449,7 +449,7 @@ int nas_proc_deregister(nas_user_t *user) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_reg_data(nas_user_t *user, int *mode, int *selected, int format, +int nas_proc_get_reg_data(nas_user_t *user, int *mode, bool *selected, int format, network_plmn_t *oper, int *AcT) { LOG_FUNC_IN; @@ -462,12 +462,12 @@ int nas_proc_get_reg_data(nas_user_t *user, int *mode, int *selected, int format if (oper_name != NULL) { /* An operator is currently selected */ - *selected = TRUE; + *selected = true; /* Get the supported Radio Access Technology */ *AcT = emm_main_get_plmn_rat(user->emm_data); } else { /* No any operator is selected */ - *selected = FALSE; + *selected = false; *AcT = NET_ACCESS_UNAVAILABLE; } @@ -558,7 +558,7 @@ int nas_proc_get_loc_info(nas_user_t *user, char *tac, char *ci, int *AcT) ** ** ** Description: Initiates a detach procedure ** ** ** - ** Inputs: switch_off: TRUE if the detach is due to UE switch-off ** + ** Inputs: switch_off: true if the detach is due to UE switch-off ** ** Others: None ** ** ** ** Outputs: None ** @@ -566,7 +566,7 @@ int nas_proc_get_loc_info(nas_user_t *user, char *tac, char *ci, int *AcT) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_detach(nas_user_t *user, int switch_off) +int nas_proc_detach(nas_user_t *user, bool switch_off) { LOG_FUNC_IN; @@ -607,7 +607,7 @@ int nas_proc_attach(nas_user_t *user) if ( !emm_main_is_attached(user->emm_data) ) { /* Initiate an Attach procedure */ emm_sap.primitive = EMMREG_ATTACH_INIT; - emm_sap.u.emm_reg.u.attach.is_emergency = FALSE; + emm_sap.u.emm_reg.u.attach.is_emergency = false; rc = emm_sap_send(user, &emm_sap); } @@ -624,16 +624,16 @@ int nas_proc_attach(nas_user_t *user) ** Others: None ** ** ** ** Outputs: None ** - ** Return: TRUE if the UE is currently attached to ** + ** Return: true if the UE is currently attached to ** ** the network ** ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_get_attach_status(nas_user_t *user) +bool nas_proc_get_attach_status(nas_user_t *user) { LOG_FUNC_IN; - int is_attached = emm_main_is_attached(user->emm_data); + bool is_attached = emm_main_is_attached(user->emm_data); LOG_FUNC_RETURN (is_attached); } @@ -690,10 +690,10 @@ int nas_proc_get_pdn_status(nas_user_t *user, int *cids, int *states, int n_pdn_ /* For all PDN contexts */ for (cid = 1; (cid < n_pdn+1) && (n_defined_pdn < n_pdn_max); cid++) { /* Get the status of this PDN */ - int state = FALSE; - int is_defined = esm_main_get_pdn_status(user, cid, &state); + bool state = false; + bool is_defined = esm_main_get_pdn_status(user, cid, &state); - if (is_defined != FALSE) { + if (is_defined != false) { /* This PDN has been defined */ *(cids++) = cid; *(states++) = state; @@ -734,7 +734,7 @@ int nas_proc_get_pdn_param(esm_data_t *esm_data, int *cids, int *types, const ch /* For all PDN contexts */ for (cid = 1; (cid < n_pdn+1) && (n_defined_pdn < n_pdn_max); cid++) { - int emergency, active; + bool emergency, active; /* Get PDN connection parameters */ int rc = esm_main_get_pdn(esm_data, cid, types, apns, &emergency, &active); @@ -845,8 +845,8 @@ int nas_proc_set_pdn(nas_user_t *user, int cid, int type, const char *apn, int i esm_sap_t esm_sap; esm_sap.primitive = ESM_PDN_CONNECTIVITY_REQ; - esm_sap.is_standalone = TRUE; - esm_sap.data.pdn_connect.is_defined = FALSE; + esm_sap.is_standalone = true; + esm_sap.data.pdn_connect.is_defined = false; esm_sap.data.pdn_connect.cid = cid; esm_sap.data.pdn_connect.pdn_type = type; esm_sap.data.pdn_connect.apn = apn; @@ -882,8 +882,8 @@ int nas_proc_reset_pdn(nas_user_t *user, int cid) esm_sap_t esm_sap; esm_sap.primitive = ESM_PDN_CONNECTIVITY_REJ; - esm_sap.is_standalone = TRUE; - esm_sap.data.pdn_connect.is_defined = TRUE; + esm_sap.is_standalone = true; + esm_sap.data.pdn_connect.is_defined = true; esm_sap.data.pdn_connect.cid = cid; /* * Notify ESM that the specified PDN context has to be undefined @@ -916,7 +916,7 @@ int nas_proc_deactivate_pdn(nas_user_t *user, int cid) if (cid > 0) { /* Deactivate only the specified PDN context */ - rc = _nas_proc_deactivate(user, cid, FALSE); + rc = _nas_proc_deactivate(user, cid, false); } else { /* Do not deactivate the PDN connection established during initial * network attachment (identifier 1) */ @@ -924,7 +924,7 @@ int nas_proc_deactivate_pdn(nas_user_t *user, int cid) /* Deactivate all active PDN contexts */ while ((rc != RETURNerror) && (cid < esm_main_get_nb_pdns_max(user->esm_data)+1)) { - rc = _nas_proc_deactivate(user, cid++, TRUE); + rc = _nas_proc_deactivate(user, cid++, true); } } @@ -970,13 +970,13 @@ int nas_proc_activate_pdn(nas_user_t *user, int cid) if (rc != RETURNerror) { if (cid > 0) { /* Activate only the specified PDN context */ - rc = _nas_proc_activate(user, cid, FALSE); + rc = _nas_proc_activate(user, cid, false); } else { cid = 1; /* Activate all defined PDN contexts */ while ((rc != RETURNerror) && (cid < esm_main_get_nb_pdns_max(user->esm_data)+1)) { - rc = _nas_proc_activate(user, cid++, TRUE); + rc = _nas_proc_activate(user, cid++, true); } } } @@ -1177,7 +1177,7 @@ int nas_proc_ul_transfer_cnf(nas_user_t *user) */ emm_sap.primitive = EMMAS_DATA_IND; emm_sap.u.emm_as.u.data.ueid = user->ueid; - emm_sap.u.emm_as.u.data.delivered = TRUE; + emm_sap.u.emm_as.u.data.delivered = true; emm_sap.u.emm_as.u.data.NASmsg.length = 0; rc = emm_sap_send(user, &emm_sap); @@ -1214,7 +1214,7 @@ int nas_proc_ul_transfer_rej(nas_user_t *user) */ emm_sap.primitive = EMMAS_DATA_IND; emm_sap.u.emm_as.u.data.ueid = user->ueid; - emm_sap.u.emm_as.u.data.delivered = FALSE; + emm_sap.u.emm_as.u.data.delivered = false; emm_sap.u.emm_as.u.data.NASmsg.length = 0; rc = emm_sap_send(user, &emm_sap); @@ -1251,7 +1251,7 @@ int nas_proc_dl_transfer_ind(nas_user_t *user, const Byte_t *data, uint32_t len) */ emm_sap.primitive = EMMAS_DATA_IND; emm_sap.u.emm_as.u.data.ueid = user->ueid; - emm_sap.u.emm_as.u.data.delivered = TRUE; + emm_sap.u.emm_as.u.data.delivered = true; emm_sap.u.emm_as.u.data.NASmsg.length = len; emm_sap.u.emm_as.u.data.NASmsg.value = (uint8_t *)data; rc = emm_sap_send(user, &emm_sap); @@ -1274,7 +1274,7 @@ int nas_proc_dl_transfer_ind(nas_user_t *user, const Byte_t *data, uint32_t len) ** ** ** Inputs: cid: Identifier of the PDN context used to es- ** ** tablished connectivity to specified PDN ** - ** apply_to_all: TRUE if the PDN connectivity procedure is ** + ** apply_to_all: true if the PDN connectivity procedure is ** ** initiated to establish connectivity to all ** ** defined PDNs ** ** Others: None ** @@ -1284,12 +1284,12 @@ int nas_proc_dl_transfer_ind(nas_user_t *user, const Byte_t *data, uint32_t len) ** Others: None ** ** ** ***************************************************************************/ -static int _nas_proc_activate(nas_user_t *user, int cid, int apply_to_all) +static int _nas_proc_activate(nas_user_t *user, int cid, bool apply_to_all) { LOG_FUNC_IN; int rc; - int active = FALSE; + bool active = false; esm_sap_t esm_sap; @@ -1332,8 +1332,8 @@ static int _nas_proc_activate(nas_user_t *user, int cid, int apply_to_all) * for the specified PDN */ esm_sap.primitive = ESM_PDN_CONNECTIVITY_REQ; - esm_sap.is_standalone = TRUE; - esm_sap.data.pdn_connect.is_defined = TRUE; + esm_sap.is_standalone = true; + esm_sap.data.pdn_connect.is_defined = true; esm_sap.data.pdn_connect.cid = cid; rc = esm_sap_send(user, &esm_sap); @@ -1347,7 +1347,7 @@ static int _nas_proc_activate(nas_user_t *user, int cid, int apply_to_all) ** Description: Initiates a PDN disconnect procedure ** ** ** ** Inputs: cid: Identifier of the PDN context ** - ** apply_to_all: TRUE if the PDN disconnect procedure is ** + ** apply_to_all: true if the PDN disconnect procedure is ** ** initiated to request disconnection from ** ** all active PDNs ** ** Others: None ** @@ -1357,15 +1357,15 @@ static int _nas_proc_activate(nas_user_t *user, int cid, int apply_to_all) ** Others: None ** ** ** ***************************************************************************/ -static int _nas_proc_deactivate(nas_user_t *user, int cid, int apply_to_all) +static int _nas_proc_deactivate(nas_user_t *user, int cid, bool apply_to_all) { LOG_FUNC_IN; int rc; int pdn_type; const char *apn; - int emergency = FALSE; - int active = FALSE; + bool emergency = false; + bool active = false; /* Get PDN context parameters */ rc = esm_main_get_pdn(user->esm_data, cid, &pdn_type, &apn, &emergency, &active); diff --git a/openair3/NAS/UE/nas_proc.h b/openair3/NAS/UE/nas_proc.h index 4e653549ae..bd88691de8 100644 --- a/openair3/NAS/UE/nas_proc.h +++ b/openair3/NAS/UE/nas_proc.h @@ -74,7 +74,7 @@ void nas_proc_cleanup(nas_user_t *user); int nas_proc_enable_s1_mode(nas_user_t *user); int nas_proc_disable_s1_mode(nas_user_t *user); -int nas_proc_get_eps(nas_user_t *user, int *stat); +int nas_proc_get_eps(nas_user_t *user, bool *stat); int nas_proc_get_imsi(emm_data_t *emm_data, char *imsi_str); int nas_proc_get_msisdn(nas_user_t *user, char *msisdn_str, int *ton_npi); @@ -83,16 +83,16 @@ int nas_proc_get_signal_quality(nas_user_t *user, int *rsrq, int *rsrp); int nas_proc_register(nas_user_t *user, int mode, int format, const network_plmn_t *oper, int AcT); int nas_proc_deregister(nas_user_t *user); -int nas_proc_get_reg_data(nas_user_t *user, int *mode, int *selected, int format, +int nas_proc_get_reg_data(nas_user_t *user, int *mode, bool *selected, int format, network_plmn_t *oper, int *AcT); int nas_proc_get_oper_list(nas_user_t *user, const char **oper_list); int nas_proc_get_reg_status(nas_user_t *user, int *stat); int nas_proc_get_loc_info(nas_user_t *user, char *tac, char *ci, int *AcT); -int nas_proc_detach(nas_user_t *user, int switch_off); +int nas_proc_detach(nas_user_t *user, bool switch_off); int nas_proc_attach(nas_user_t *user); -int nas_proc_get_attach_status(nas_user_t *user); +bool nas_proc_get_attach_status(nas_user_t *user); int nas_proc_reset_pdn(nas_user_t *user, int cid); int nas_proc_set_pdn(nas_user_t *user, int cid, int type, const char *apn, int ipv4_addr, diff --git a/openair3/NAS/UE/nas_proc_defs.h b/openair3/NAS/UE/nas_proc_defs.h index 1ce2bfd929..09cf8e834e 100644 --- a/openair3/NAS/UE/nas_proc_defs.h +++ b/openair3/NAS/UE/nas_proc_defs.h @@ -1,12 +1,14 @@ #ifndef _NAS_PROC_DEFS_H #define _NAS_PROC_DEFS_H +#include + /* * Local NAS data */ typedef struct { /* EPS capibility status */ - int EPS_capability_status; + bool EPS_capability_status; /* Reference signal received quality */ int rsrq; /* Reference signal received power */ diff --git a/openair3/NAS/UE/nas_ue_task.c b/openair3/NAS/UE/nas_ue_task.c index a94445349c..34bf6cb3ad 100644 --- a/openair3/NAS/UE/nas_ue_task.c +++ b/openair3/NAS/UE/nas_ue_task.c @@ -43,10 +43,10 @@ uint16_t ue_idx_standalone = 0xFFFF; char *make_port_str_from_ueid(const char *base_port_str, int ueid); -static int nas_ue_process_events(nas_user_container_t *users, struct epoll_event *events, int nb_events) +static bool nas_ue_process_events(nas_user_container_t *users, struct epoll_event *events, int nb_events) { int event; - int exit_loop = FALSE; + bool exit_loop = false; LOG_I(NAS, "[UE] Received %d events\n", nb_events); @@ -310,7 +310,7 @@ void *nas_ue_task(void *args_p) nb_events = itti_get_events(TASK_NAS_UE, &events); if ((nb_events > 0) && (events != NULL)) { - if (nas_ue_process_events(users, events, nb_events) == TRUE) { + if (nas_ue_process_events(users, events, nb_events) == true) { LOG_E(NAS, "[UE] Received exit loop\n"); } } diff --git a/openair3/NAS/UE/nas_user.c b/openair3/NAS/UE/nas_user.c index d3467eddd5..56e41e4610 100644 --- a/openair3/NAS/UE/nas_user.c +++ b/openair3/NAS/UE/nas_user.c @@ -187,10 +187,10 @@ void nas_user_initialize(nas_user_t *user, emm_indication_callback_t emm_cb, ** from which data have been received ** ** Others: None ** ** ** - ** Outputs: Return: FALSE, TRUE ** + ** Outputs: Return: false, true ** ** ** ***************************************************************************/ -int nas_user_receive_and_process(nas_user_t *user, char *message) +bool nas_user_receive_and_process(nas_user_t *user, char *message) { LOG_FUNC_IN; @@ -212,13 +212,13 @@ int nas_user_receive_and_process(nas_user_t *user, char *message) * exit from the receiving loop */ LOG_TRACE (ERROR, "UE-MAIN - " "Failed to read data from the user application layer"); - LOG_FUNC_RETURN(TRUE); + LOG_FUNC_RETURN(true); } } if (bytes == 0) { /* A signal was caught before any data were available */ - LOG_FUNC_RETURN(FALSE); + LOG_FUNC_RETURN(false); } /* Decode the user data message */ @@ -268,12 +268,12 @@ int nas_user_receive_and_process(nas_user_t *user, char *message) * exit from the receiving loop */ LOG_TRACE (ERROR, "UE-MAIN - " "Failed to send data to the user application layer"); - LOG_FUNC_RETURN(TRUE); + LOG_FUNC_RETURN(true); } } } - LOG_FUNC_RETURN(FALSE); + LOG_FUNC_RETURN(false); } /**************************************************************************** @@ -989,7 +989,7 @@ static int _nas_user_proc_cops(nas_user_t *user, const at_command_t *data) char oper_buffer[NET_FORMAT_MAX_SIZE], *oper = oper_buffer; memset(oper, 0, NET_FORMAT_MAX_SIZE); - int oper_is_selected; + bool oper_is_selected; at_response->id = data->id; at_response->type = data->type; @@ -1266,7 +1266,7 @@ static int _nas_user_proc_cgatt(nas_user_t *user, const at_command_t *data) if (data->command.cgatt.state == AT_CGATT_ATTACHED) { ret_code = nas_proc_attach(user); } else if (data->command.cgatt.state == AT_CGATT_DETACHED) { - ret_code = nas_proc_detach(user, FALSE); + ret_code = nas_proc_detach(user, false); } if (ret_code != RETURNok) { @@ -1284,7 +1284,7 @@ static int _nas_user_proc_cgatt(nas_user_t *user, const at_command_t *data) /* * Read command returns the current EPS service state. */ - if (nas_proc_get_attach_status(user) != TRUE) { + if (nas_proc_get_attach_status(user) != true) { cgatt->state = AT_CGATT_DETACHED; } else { cgatt->state = AT_CGATT_ATTACHED; @@ -1821,7 +1821,7 @@ static int _nas_user_proc_cgdcont(nas_user_t *user, const at_command_t *data) int emergency = AT_CGDCONT_EBS_DEFAULT; int p_cscf = AT_CGDCONT_PCSCF_DEFAULT; int im_cn_signalling = AT_CGDCONT_IM_CM_DEFAULT; - int reset_pdn = TRUE; + bool reset_pdn = true; at_response->id = data->id; at_response->type = data->type; @@ -1870,7 +1870,7 @@ static int _nas_user_proc_cgdcont(nas_user_t *user, const at_command_t *data) break; } - reset_pdn = FALSE; + reset_pdn = false; } if (data->mask & AT_CGDCONT_APN_MASK) { diff --git a/openair3/NAS/UE/nas_user.h b/openair3/NAS/UE/nas_user.h index 1ded438ddd..63920540d4 100644 --- a/openair3/NAS/UE/nas_user.h +++ b/openair3/NAS/UE/nas_user.h @@ -63,7 +63,7 @@ Description NAS procedure functions triggered by the user void nas_user_initialize(nas_user_t *user, emm_indication_callback_t emm_cb, esm_indication_callback_t esm_cb, const char *version); -int nas_user_receive_and_process(nas_user_t *user, char *message); +bool nas_user_receive_and_process(nas_user_t *user, char *message); int nas_user_process_data(nas_user_t *user, const void *data); diff --git a/openair3/NGAP/ngap_common.h b/openair3/NGAP/ngap_common.h index 60f7beacd0..a550b6e436 100644 --- a/openair3/NGAP/ngap_common.h +++ b/openair3/NGAP/ngap_common.h @@ -102,13 +102,6 @@ # error "You are compiling ngap with the wrong version of ASN1C" #endif -#ifndef FALSE -# define FALSE (0) -#endif -#ifndef TRUE -# define TRUE (!FALSE) -#endif - #define NGAP_UE_ID_FMT "0x%06"PRIX32 extern int asn_debug; diff --git a/openair3/S1AP/s1ap_common.h b/openair3/S1AP/s1ap_common.h index 3c07f92a7f..d383b622b6 100644 --- a/openair3/S1AP/s1ap_common.h +++ b/openair3/S1AP/s1ap_common.h @@ -61,13 +61,6 @@ # error "You are compiling s1ap with the wrong version of ASN1C" #endif -#ifndef FALSE -# define FALSE (0) -#endif -#ifndef TRUE -# define TRUE (!FALSE) -#endif - #define S1AP_UE_ID_FMT "0x%06"PRIX32 extern int asn_debug; diff --git a/openair3/S1AP/s1ap_eNB_trace.c b/openair3/S1AP/s1ap_eNB_trace.c index 695eeb4ef8..de84682ec1 100644 --- a/openair3/S1AP/s1ap_eNB_trace.c +++ b/openair3/S1AP/s1ap_eNB_trace.c @@ -115,7 +115,7 @@ int s1ap_eNB_handle_trace_start(uint32_t assoc_id, container = &pdu->choice.initiatingMessage.value.choice.TraceStart; S1AP_FIND_PROTOCOLIE_BY_ID(S1AP_TraceStartIEs_t, ie, container, - S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, TRUE); + S1AP_ProtocolIE_ID_id_eNB_UE_S1AP_ID, true); mme_ref_p = s1ap_eNB_get_MME(NULL, assoc_id, 0); DevAssert(mme_ref_p != NULL); if (ie != NULL) { diff --git a/openair3/ocp-gtpu/gtp_itf.cpp b/openair3/ocp-gtpu/gtp_itf.cpp index a6bda28b57..3626e0b8ed 100644 --- a/openair3/ocp-gtpu/gtp_itf.cpp +++ b/openair3/ocp-gtpu/gtp_itf.cpp @@ -21,7 +21,7 @@ extern "C" { #include "openair2/SDAP/nr_sdap/nr_sdap.h" //#include -static boolean_t is_gnb = false; +static bool is_gnb = false; #pragma pack(1) @@ -969,7 +969,7 @@ static int Gtpv1uHandleGpdu(int h, int offset = sizeof(Gtpv1uMsgHeaderT); uint8_t qfi = 0; - boolean_t rqi = FALSE; + bool rqi = false; uint32_t NR_PDCP_PDU_SN = 0; /* if E, S, or PN is set then there are 4 more bytes of header */ diff --git a/openair3/ocp-gtpu/gtp_itf.h b/openair3/ocp-gtpu/gtp_itf.h index dd52481729..51a47e8c82 100644 --- a/openair3/ocp-gtpu/gtp_itf.h +++ b/openair3/ocp-gtpu/gtp_itf.h @@ -8,32 +8,30 @@ extern "C" { #endif -typedef boolean_t (*gtpCallback)( - protocol_ctxt_t *ctxt_pP, - const srb_flag_t srb_flagP, - const rb_id_t rb_idP, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_sizeP, - unsigned char *const sdu_buffer_pP, - const pdcp_transmission_mode_t modeP, - const uint32_t *sourceL2Id, - const uint32_t *destinationL2Id); +typedef bool (*gtpCallback)(protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_sizeP, + unsigned char *const sdu_buffer_pP, + const pdcp_transmission_mode_t modeP, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id); -typedef boolean_t (*gtpCallbackSDAP)( - protocol_ctxt_t *ctxt_pP, - const srb_flag_t srb_flagP, - const rb_id_t rb_idP, - const mui_t muiP, - const confirm_t confirmP, - const sdu_size_t sdu_buffer_sizeP, - unsigned char *const sdu_buffer_pP, - const pdcp_transmission_mode_t modeP, - const uint32_t *sourceL2Id, - const uint32_t *destinationL2Id, - const uint8_t qfi, - const boolean_t rqi, - const int pdusession_id); +typedef bool (*gtpCallbackSDAP)(protocol_ctxt_t *ctxt_pP, + const srb_flag_t srb_flagP, + const rb_id_t rb_idP, + const mui_t muiP, + const confirm_t confirmP, + const sdu_size_t sdu_buffer_sizeP, + unsigned char *const sdu_buffer_pP, + const pdcp_transmission_mode_t modeP, + const uint32_t *sourceL2Id, + const uint32_t *destinationL2Id, + const uint8_t qfi, + const bool rqi, + const int pdusession_id); typedef struct openAddr_s { char originHost[HOST_NAME_MAX]; diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 78acc373ee..0f11447bf4 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -380,7 +380,7 @@ struct openair0_device_t { @param buff Buffer which holds the samples (2 dimensional) @param nsamps number of samples to be sent @param number of antennas - @param flags flags must be set to TRUE if timestamp parameter needs to be applied + @param flags flags must be set to true if timestamp parameter needs to be applied */ int (*trx_write_func)(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int antenna_id, int flags); @@ -390,7 +390,7 @@ struct openair0_device_t { @param buff Buffer which holds the samples (1 dimensional) @param nsamps number of samples to be sent @param antenna_id index of the antenna if the device has multiple anteannas - @param flags flags must be set to TRUE if timestamp parameter needs to be applied + @param flags flags must be set to true if timestamp parameter needs to be applied */ int (*trx_write_func2)(openair0_device *device, openair0_timestamp timestamp, void *buff, int nsamps,int antenna_id, int flags); diff --git a/targets/ARCH/IRIS/USERSPACE/LIB/iris_lib.cpp b/targets/ARCH/IRIS/USERSPACE/LIB/iris_lib.cpp index 1273097f3b..47bbadfe28 100644 --- a/targets/ARCH/IRIS/USERSPACE/LIB/iris_lib.cpp +++ b/targets/ARCH/IRIS/USERSPACE/LIB/iris_lib.cpp @@ -134,7 +134,7 @@ static void trx_iris_end(openair0_device *device) { @param buff Buffer which holds the samples @param nsamps number of samples to be sent @param antenna_id index of the antenna if the device has multiple anteannas - @param flags flags must be set to TRUE if timestamp parameter needs to be applied + @param flags flags must be set to true if timestamp parameter needs to be applied */ diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 8976284345..c68a36e799 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -331,7 +331,7 @@ static void trx_usrp_end(openair0_device *device) { @param buff Buffer which holds the samples @param nsamps number of samples to be sent @param antenna_id index of the antenna if the device has multiple antennas - @param flags flags must be set to TRUE if timestamp parameter needs to be applied + @param flags flags must be set to true if timestamp parameter needs to be applied */ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, @@ -352,7 +352,7 @@ static int trx_usrp_write(openair0_device *device, AssertFatal( MAX_WRITE_THREAD_BUFFER_SIZE >= cc,"Do not support more than %d cc number\n", MAX_WRITE_THREAD_BUFFER_SIZE); - boolean_t first_packet_state=false,last_packet_state=false; + bool first_packet_state=false,last_packet_state=false; if (flags_lsb == 2) { // start of burst // s->tx_md.start_of_burst = true; @@ -481,7 +481,7 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI @param buff Buffer which holds the samples @param nsamps number of samples to be sent @param antenna_id index of the antenna if the device has multiple antennas - @param flags flags must be set to TRUE if timestamp parameter needs to be applied + @param flags flags must be set to true if timestamp parameter needs to be applied */ void *trx_usrp_write_thread(void * arg){ int ret=0; diff --git a/targets/ARCH/iqplayer/iqplayer_lib.c b/targets/ARCH/iqplayer/iqplayer_lib.c index b62c1935d3..f6578d6e9a 100644 --- a/targets/ARCH/iqplayer/iqplayer_lib.c +++ b/targets/ARCH/iqplayer/iqplayer_lib.c @@ -158,7 +158,7 @@ static void trx_iqplayer_end(openair0_device *device) { @param buff Buffer which holds the samples @param nsamps number of samples to be sent @param antenna_id index of the antenna if the device has multiple antennas - @param flags flags must be set to TRUE if timestamp parameter needs to be applied + @param flags flags must be set to true if timestamp parameter needs to be applied */ static int trx_iqplayer_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { struct timespec req; diff --git a/targets/ARCH/rfsimulator/stored_node.c b/targets/ARCH/rfsimulator/stored_node.c index cf025680cd..17ab3cb734 100644 --- a/targets/ARCH/rfsimulator/stored_node.c +++ b/targets/ARCH/rfsimulator/stored_node.c @@ -187,7 +187,7 @@ int main(int argc, char *argv[]) { } uint64_t typeStamp=ENB_MAGICDL; - boolean_t raw=false; + bool raw = false; if ( argc == 5 ) { raw=true; diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index a3048995a5..3d62d5c19a 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -231,9 +231,9 @@ static inline int rxtx(PHY_VARS_eNB *eNB, dlsch_ue_select_tbl_in_use = !dlsch_ue_select_tbl_in_use; // L2-emulator can work only one eNB. // memcpy(&pre_scd_eNB_UE_stats,&RC.mac[ru->eNB_list[0]->Mod_id]->UE_info.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); - // memcpy(&pre_scd_activeUE, &RC.mac[ru->eNB_list[0]->Mod_id]->UE_info.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX); + // memcpy(&pre_scd_activeUE, &RC.mac[ru->eNB_list[0]->Mod_id]->UE_info.active, sizeof(bool)*NUMBER_OF_UE_MAX); memcpy(&pre_scd_eNB_UE_stats,&RC.mac[0]->UE_info.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); - memcpy(&pre_scd_activeUE, &RC.mac[0]->UE_info.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX); + memcpy(&pre_scd_activeUE, &RC.mac[0]->UE_info.active, sizeof(bool)*NUMBER_OF_UE_MAX); AssertFatal((ret= pthread_mutex_lock(&ru->proc.mutex_pre_scd))==0,"[eNB] error locking proc mutex for eNB pre scd, return %d\n",ret); ru->proc.instance_pre_scd++; diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c index 836709b473..a7a0d2de32 100644 --- a/targets/RT/USER/lte-ru.c +++ b/targets/RT/USER/lte-ru.c @@ -1834,7 +1834,7 @@ static void *ru_thread( void *param ) { new_dlsch_ue_select_tbl_in_use = dlsch_ue_select_tbl_in_use; dlsch_ue_select_tbl_in_use = !dlsch_ue_select_tbl_in_use; memcpy(&pre_scd_eNB_UE_stats,&RC.mac[ru->eNB_list[0]->Mod_id]->UE_info.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); - memcpy(&pre_scd_activeUE, &RC.mac[ru->eNB_list[0]->Mod_id]->UE_info.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX); + memcpy(&pre_scd_activeUE, &RC.mac[ru->eNB_list[0]->Mod_id]->UE_info.active, sizeof(bool)*NUMBER_OF_UE_MAX); AssertFatal((ret=pthread_mutex_lock(&ru->proc.mutex_pre_scd))==0,"[eNB] error locking proc mutex for eNB pre scd\n"); ru->proc.instance_pre_scd++; diff --git a/targets/TEST/PDCP/test_pdcp.c b/targets/TEST/PDCP/test_pdcp.c index b62edf1215..d6becf87c1 100644 --- a/targets/TEST/PDCP/test_pdcp.c +++ b/targets/TEST/PDCP/test_pdcp.c @@ -100,7 +100,7 @@ int main(int argc, char **argv) list_init(&test_pdu_rx_list, NULL); logInit(); - if (init_pdcp_entity(&pdcp_array[0]) == TRUE && init_pdcp_entity(&pdcp_array[1]) == TRUE) + if (init_pdcp_entity(&pdcp_array[0]) == true && init_pdcp_entity(&pdcp_array[1]) == true) msg("[TEST] PDCP entity initialization OK\n"); else { msg("[TEST] Cannot initialize PDCP entities!\n"); @@ -109,7 +109,7 @@ int main(int argc, char **argv) /* Initialize PDCP state variables */ for (index = 0; index < 2; ++index) { - if (pdcp_init_seq_numbers(&pdcp_array[index]) == FALSE) { + if (pdcp_init_seq_numbers(&pdcp_array[index]) == false) { msg("[TEST] Cannot initialize sequence numbers of PDCP entity %d!\n", index); exit(1); } else { @@ -120,11 +120,11 @@ int main(int argc, char **argv) #if TEST_RX_AND_TX_WINDOW /* Test TX window */ - if (test_tx_window() == FALSE) + if (test_tx_window() == false) test_result = 1; /* Test RX window */ - if (test_rx_window() == FALSE) + if (test_rx_window() == false) test_result = 1; #endif @@ -132,11 +132,11 @@ int main(int argc, char **argv) #if TEST_PDCP_DATA_REQUEST_AND_INDICATION /* Test pdcp_data_req() method in pdcp.c */ - if (test_pdcp_data_req() == FALSE) + if (test_pdcp_data_req() == false) test_result = 1; /* Test pdcp_data_ind() method in pdcp.c */ - if (test_pdcp_data_ind() == FALSE) + if (test_pdcp_data_ind() == false) test_result = 1; #endif @@ -150,10 +150,10 @@ int main(int argc, char **argv) return test_result; } -BOOL init_pdcp_entity(pdcp_t *pdcp_entity) +bool init_pdcp_entity(pdcp_t *pdcp_entity) { if (pdcp_entity == NULL) - return FALSE; + return false; /* * Initialize sequence number state variables of relevant PDCP entity @@ -171,10 +171,10 @@ BOOL init_pdcp_entity(pdcp_t *pdcp_entity) pdcp_entity->next_pdcp_rx_sn, pdcp_entity->tx_hfn, pdcp_entity->rx_hfn, \ pdcp_entity->last_submitted_pdcp_rx_sn, pdcp_entity->seq_num_size); - return TRUE; + return true; } -BOOL test_tx_window(void) +bool test_tx_window(void) { unsigned long index = 0; @@ -185,33 +185,33 @@ BOOL test_tx_window(void) msg("TX packet # %07lu seq # %04d hfn # %04d\n", index, pseudo_tx_sn, pdcp_array[0].tx_hfn); else { msg("TX packet is out-of-window!\n"); - return FALSE; + return false; } } - return TRUE; + return true; } -BOOL test_rx_window(void) +bool test_rx_window(void) { unsigned long index = 0; for (index = 0; index < NUMBER_OF_TEST_PACKETS; ++index) { u16 pseudo_rx_sn = (index == 0) ? 0 : index % WINDOW_SIZE; - if (pdcp_is_rx_seq_number_valid(pseudo_rx_sn, &pdcp_array[1]) == TRUE) { + if (pdcp_is_rx_seq_number_valid(pseudo_rx_sn, &pdcp_array[1]) == true) { msg("RX packet # %07lu seq # %04d last-submitted # %04d hfn # %04d\n", \ index, pdcp_array[1].next_pdcp_rx_sn, pdcp_array[1].last_submitted_pdcp_rx_sn, pdcp_array[1].rx_hfn); } else { msg("RX packet seq # %04lu is not valid!\n", index); - return FALSE; + return false; } } - return TRUE; + return true; } -BOOL test_pdcp_data_req(void) +bool test_pdcp_data_req(void) { unsigned char* pdcp_test_pdu_buffer = NULL; unsigned char pdcp_test_pdu_buffer_size = DUMMY_BUFFER_SIZE + PDCP_USER_PLANE_DATA_PDU_LONG_SN_HEADER_SIZE; @@ -224,7 +224,7 @@ BOOL test_pdcp_data_req(void) if (pdcp_test_pdu_buffer == NULL) { msg("Cannot allocate a buffer for test!\n"); - return FALSE; + return false; } /* @@ -241,7 +241,7 @@ BOOL test_pdcp_data_req(void) /* * Ask PDCP to create a PDU with given buffer and enqueue it to `test_pdu_tx_list` */ - if (pdcp_data_req(0, 0, 10, DUMMY_BUFFER, &pdcp_array[0], &test_pdu_tx_list) == TRUE) { + if (pdcp_data_req(0, 0, 10, DUMMY_BUFFER, &pdcp_array[0], &test_pdu_tx_list) == true) { msg("[TEST] Starting to dissect PDU created by PDCP...\n"); /* @@ -251,7 +251,7 @@ BOOL test_pdcp_data_req(void) if (pdcp_test_pdu_buffer_size == 0 ) { msg("[TEST] PDU created by pdcp_data_req() is invalid!\n"); - return FALSE; + return false; } /* @@ -269,7 +269,7 @@ BOOL test_pdcp_data_req(void) */ if (pdcp_test_pdu_buffer[0] & 0x80) { msg("[TEST] First bit is not 0, which means this is not a Data PDU!\n"); - return FALSE; + return false; } else { msg("[TEST] First bit is 0 so this is a Data PDU, OK\n"); } @@ -279,7 +279,7 @@ BOOL test_pdcp_data_req(void) */ if ((pdcp_test_pdu_buffer[0] & 0x70) != 0) { msg("[TEST] Reserved bits are not 0!\n"); - return FALSE; + return false; } else { msg("[TEST] Reserved bits are all 0, OK\n"); } @@ -292,21 +292,21 @@ BOOL test_pdcp_data_req(void) if (sequence_number != index % WINDOW_SIZE) { msg("[TEST] Sequence numbers are out-of-order!\n"); - return FALSE; + return false; } else { msg("[TEST] Sequence number is correct\n"); } } else { msg("[TEST] pdcp_data_req() returned FALSE!\n"); - return FALSE; + return false; } } - return TRUE; + return true; } -BOOL test_pdcp_data_ind(void) +bool test_pdcp_data_ind(void) { /* * This is the list that pdcp_data_ind() takes to put pdcp_data_ind_header_t @@ -341,9 +341,9 @@ BOOL test_pdcp_data_ind(void) test_sdu = list_remove_head(&test_pdu_rx_list); - if (pdcp_data_ind(0, 0, test_sdu_size, test_sdu, &pdcp_array[0], &test_pdu_indication_list) == FALSE) { + if (pdcp_data_ind(0, 0, test_sdu_size, test_sdu, &pdcp_array[0], &test_pdu_indication_list) == false) { msg("[TEST] pdcp_data_ind() failed to handle data indication!\n"); - return FALSE; + return false; } else { msg("[TEST] pdcp_data_ind() succcessfuly handled data indication\n"); } @@ -359,7 +359,7 @@ BOOL test_pdcp_data_ind(void) if (test_data_ind_header == NULL) { msg("[TEST] Data indication header is not valid!\n"); - return FALSE; + return false; } else { pdcp_data_ind_header_t* indication_header = (pdcp_data_ind_header_t*)test_data_ind_header->data; @@ -370,7 +370,7 @@ BOOL test_pdcp_data_ind(void) msg("[TEST] Radio bearer ID is correct\n"); } else { msg("[TEST] Radio bearer ID is not correct! (expected: 0, parsed: %d)\n", indication_header->rb_id); - return FALSE; + return false; } /* @@ -380,7 +380,7 @@ BOOL test_pdcp_data_ind(void) msg("[TEST] SDU size is correct\n"); } else { msg("[TEST] SDU size is not correct! (expected: %d, parsed: %d)\n", DUMMY_BUFFER_SIZE, indication_header->data_size); - return FALSE; + return false; } /* @@ -412,11 +412,11 @@ BOOL test_pdcp_data_ind(void) print_byte_stream("[TEST] TXed data: ", DUMMY_BUFFER, DUMMY_BUFFER_SIZE); print_byte_stream("[TEST] RXed data: ", (unsigned char*)&(test_data_ind_header->data[data_index]), DUMMY_BUFFER_SIZE); - return FALSE; + return false; } } - return TRUE; + return true; } diff --git a/targets/TEST/PDCP/test_pdcp.h b/targets/TEST/PDCP/test_pdcp.h index 0da174cc8c..629f6f2539 100644 --- a/targets/TEST/PDCP/test_pdcp.h +++ b/targets/TEST/PDCP/test_pdcp.h @@ -42,17 +42,17 @@ int pdcp_fifo_flush_sdus (void) { return 0; } int pdcp_fifo_read_input_sdus_remaining_bytes (void) { return 0; } int pdcp_fifo_read_input_sdus (void) { return 0; } -BOOL init_pdcp_entity(pdcp_t *pdcp_entity); -BOOL test_tx_window(void); -BOOL test_rx_window(void); -BOOL test_pdcp_data_req(void); -BOOL test_pdcp_data_ind(void); +bool init_pdcp_entity(pdcp_t *pdcp_entity); +bool test_tx_window(void); +bool test_rx_window(void); +bool test_pdcp_data_req(void); +bool test_pdcp_data_ind(void); /* * PDCP methods that are going to be utilised throughout the test */ -extern BOOL pdcp_init_seq_numbers(pdcp_t* pdcp_entity); +extern bool pdcp_init_seq_numbers(pdcp_t* pdcp_entity); extern u16 pdcp_get_next_tx_seq_number(pdcp_t* pdcp_entity); -extern BOOL pdcp_is_rx_seq_number_valid(u16 seq_num, pdcp_t* pdcp_entity); +extern bool pdcp_is_rx_seq_number_valid(u16 seq_num, pdcp_t* pdcp_entity); #endif diff --git a/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c b/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c index 378ee95c3b..7b80171724 100644 --- a/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c +++ b/targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c @@ -109,7 +109,7 @@ int pdcp_fifo_flush_sdus () {} int pdcp_fifo_read_input_sdus_remaining_bytes () {} int pdcp_fifo_read_input_sdus () {} -BOOL init_pdcp_entity(pdcp_t *pdcp_entity); +bool init_pdcp_entity(pdcp_t *pdcp_entity); //----------------------------------------------------------------------------- void pdcp_rlc_test_mac_rlc_loop (struct mac_data_ind *data_indP, struct mac_data_req *data_requestP, int* drop_countP, int *tx_packetsP, int* dropped_tx_packetsP) //----------------------------------------------------------------------------- @@ -230,7 +230,7 @@ int main(int argc, char **argv) pdcp_module_init(); logInit(); - if (init_pdcp_entity(&pdcp_array[0][1]) == TRUE && init_pdcp_entity(&pdcp_array[1][1]) == TRUE) + if (init_pdcp_entity(&pdcp_array[0][1]) == true && init_pdcp_entity(&pdcp_array[1][1]) == true) msg("PDCP entity initialization OK\n"); else { msg("Cannot initialize PDCP entities!\n"); @@ -239,7 +239,7 @@ int main(int argc, char **argv) /* Initialize PDCP state variables */ for (index = 0; index < 2; ++index) { - if (pdcp_init_seq_numbers(&pdcp_array[index][1]) == FALSE) { + if (pdcp_init_seq_numbers(&pdcp_array[index][1]) == false) { msg("Cannot initialize %s PDCP entity!\n", ((index == 0) ? "first" : "second")); exit(1); } @@ -275,11 +275,11 @@ int main(int argc, char **argv) } //----------------------------------------------------------------------------- -BOOL init_pdcp_entity(pdcp_t *pdcp_entity) +bool init_pdcp_entity(pdcp_t *pdcp_entity) //----------------------------------------------------------------------------- { if (pdcp_entity == NULL) - return FALSE; + return false; /* * Initialize sequence number state variables of relevant PDCP entity @@ -292,6 +292,6 @@ BOOL init_pdcp_entity(pdcp_t *pdcp_entity) pdcp_entity->last_submitted_pdcp_rx_sn = 4095; pdcp_entity->seq_num_size = 12; - return TRUE; + return true; } From bf219fc24fa75c5a057dc6f2bb6d0a3ae5baaa35 Mon Sep 17 00:00:00 2001 From: Laurent Thomas Date: Thu, 16 Jun 2022 14:41:23 +0200 Subject: [PATCH 32/60] avx2 and better simd algo --- openair1/PHY/TOOLS/cmult_sv.c | 224 +++++--------------------------- openair1/PHY/TOOLS/tools_defs.h | 12 +- 2 files changed, 31 insertions(+), 205 deletions(-) diff --git a/openair1/PHY/TOOLS/cmult_sv.c b/openair1/PHY/TOOLS/cmult_sv.c index dc57964ca5..720b5da7e8 100644 --- a/openair1/PHY/TOOLS/cmult_sv.c +++ b/openair1/PHY/TOOLS/cmult_sv.c @@ -144,205 +144,39 @@ void multadd_real_four_symbols_vector_complex_scalar(int16_t *x, _m_empty(); } - -/* -int rotate_cpx_vector(int16_t *x, +#ifdef __AVX2__ +void rotate_cpx_vector(int16_t *x, int16_t *alpha, int16_t *y, uint32_t N, - uint16_t output_shift, - uint8_t format) + uint16_t output_shift) { - // Multiply elementwise two complex vectors of N elements - // x - input 1 in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| - // We assume x1 with a dynamic of 15 bit maximum - // - // alpha - input 2 in the format |Re0 Im0| - // We assume x2 with a dynamic of 15 bit maximum - // - // y - output in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| - // - // N - the size f the vectors (this function does N cpx mpy. WARNING: N>=4; - // - // output_shift - shift at output to return in Q1.15 - // format - 0 means alpha is in shuffled format, 1 means x is in shuffled format - - uint32_t i; // loop counter - - register __m128i m0,m1; - - - - __m128i *x_128; - __m128i *y_128; - - - shift = _mm_cvtsi32_si128(output_shift); - x_128 = (__m128i *)&x[0]; - - if (format==0) { // alpha is in shuffled format for complex multiply - ((int16_t *)&alpha_128)[0] = alpha[0]; - ((int16_t *)&alpha_128)[1] = -alpha[1]; - ((int16_t *)&alpha_128)[2] = alpha[1]; - ((int16_t *)&alpha_128)[3] = alpha[0]; - ((int16_t *)&alpha_128)[4] = alpha[0]; - ((int16_t *)&alpha_128)[5] = -alpha[1]; - ((int16_t *)&alpha_128)[6] = alpha[1]; - ((int16_t *)&alpha_128)[7] = alpha[0]; - } else { // input is in shuffled format for complex multiply - ((int16_t *)&alpha_128)[0] = alpha[0]; - ((int16_t *)&alpha_128)[1] = alpha[1]; - ((int16_t *)&alpha_128)[2] = alpha[0]; - ((int16_t *)&alpha_128)[3] = alpha[1]; - ((int16_t *)&alpha_128)[4] = alpha[0]; - ((int16_t *)&alpha_128)[5] = alpha[1]; - ((int16_t *)&alpha_128)[6] = alpha[0]; - ((int16_t *)&alpha_128)[7] = alpha[1]; + // multiply a complex vector with a complex value (alpha) + // stores result in y + // N is the number of complex numbers + // output_shift reduces the result of the multiplication by this number of bits + AssertFatal(N%8==0, "To be developped"); + const c16_t for_re={alpha[0], -alpha[1]}; + __m256i const alpha_for_real = _mm256_set1_epi32(*(uint32_t*)&for_re); + const c16_t for_im={alpha[1], alpha[0]}; + __m256i const alpha_for_im= _mm256_set1_epi32(*(uint32_t*)&for_im); + __m256i const perm_mask = + _mm256_set_epi8(31,30,23,22,29,28,21,20,27,26,19,18,25,24,17,16, + 15,14,7,6,13,12,5,4,11,10,3,2,9,8,1,0); + __m256i* xd= (__m256i*)x; + const __m256i *end=xd+N/8; + for( __m256i* yd = (__m256i *)y; xd>3); i++) { - - m0 = _mm_madd_epi16(x_128[0],alpha_128); //pmaddwd_r2r(mm1,mm0); // 1- compute x1[0]*x2[0] - m0 = _mm_sra_epi32(m0,shift); // 1- shift right by shift in order to compensate for the input amplitude - m1=m0; - m0 = _mm_packs_epi32(m1,m0); // 1- pack in a 128 bit register [re im re im] - y_128[0] = _mm_unpacklo_epi32(m0,m0); // 1- pack in a 128 bit register [re im re im] - m0 = _mm_madd_epi16(x_128[1],alpha_128); //pmaddwd_r2r(mm1,mm0); // 1- compute x1[0]*x2[0] - m0 = _mm_sra_epi32(m0,shift); // 1- shift right by shift in order to compensate for the input amplitude - m1 = m0; - m1 = _mm_packs_epi32(m1,m0); // 1- pack in a 128 bit register [re im re im] - y_128[1] = _mm_unpacklo_epi32(m1,m1); // 1- pack in a 128 bit register [re im re im] - m0 = _mm_madd_epi16(x_128[2],alpha_128); //pmaddwd_r2r(mm1,mm0); // 1- compute x1[0]*x2[0] - m0 = _mm_sra_epi32(m0,shift); // 1- shift right by shift in order to compensate for the input amplitude - m1 = m0; - m1 = _mm_packs_epi32(m1,m0); // 1- pack in a 128 bit register [re im re im] - y_128[2] = _mm_unpacklo_epi32(m1,m1); // 1- pack in a 128 bit register [re im re im] - m0 = _mm_madd_epi16(x_128[3],alpha_128); //pmaddwd_r2r(mm1,mm0); // 1- compute x1[0]*x2[0] - m0 = _mm_sra_epi32(m0,shift); // 1- shift right by shift in order to compensate for the input amplitude - m1 = m0; - m1 = _mm_packs_epi32(m1,m0); // 1- pack in a 128 bit register [re im re im] - y_128[3] = _mm_unpacklo_epi32(m1,m1); // 1- pack in a 128 bit register [re im re im] - if (format==1) { // Put output in proper format (Re,-Im,Im,Re), shuffle = (0,1,3,2) = 0x1e - - y_128[0] = _mm_shufflelo_epi16(y_128[0],0x1e); - y_128[0] = _mm_shufflehi_epi16(y_128[0],0x1e); - ((int16_t*)&y_128[0])[1] = -((int16_t*)&y_128[0])[1]; - ((int16_t*)&y_128[0])[5] = -((int16_t*)&y_128[0])[5]; - y_128[1] = _mm_shufflelo_epi16(y_128[1],0x1e); - y_128[1] = _mm_shufflehi_epi16(y_128[1],0x1e); - ((int16_t*)&y_128[1])[1] = -((int16_t*)&y_128[1])[1]; - ((int16_t*)&y_128[1])[5] = -((int16_t*)&y_128[1])[5]; - y_128[2] = _mm_shufflelo_epi16(y_128[2],0x1e); - y_128[2] = _mm_shufflehi_epi16(y_128[2],0x1e); - ((int16_t*)&y_128[2])[1] = -((int16_t*)&y_128[2])[1]; - ((int16_t*)&y_128[2])[5] = -((int16_t*)&y_128[2])[5]; - y_128[3] = _mm_shufflelo_epi16(y_128[3],0x1e); - y_128[3] = _mm_shufflehi_epi16(y_128[3],0x1e); - ((int16_t*)&y_128[3])[1] = -((int16_t*)&y_128[3])[1]; - ((int16_t*)&y_128[3])[5] = -((int16_t*)&y_128[3])[5]; - } - - - x_128+=4; - y_128 +=4; - } - - - _mm_empty(); - _m_empty(); - - return(0); } - -int rotate_cpx_vector2(int16_t *x, - int16_t *alpha, - int16_t *y, - uint32_t N, - uint16_t output_shift, - uint8_t format) -{ - // Multiply elementwise two complex vectors of N elements - // x - input 1 in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| - // We assume x1 with a dynamic of 15 bit maximum - // - // alpha - input 2 in the format |Re0 Im0| - // We assume x2 with a dynamic of 15 bit maximum - // - // y - output in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| - // - // N - the size f the vectors (this function does N cpx mpy. WARNING: N>=4; - // - // log2_amp - increase the output amplitude by a factor 2^log2_amp (default is 0) - // WARNING: log2_amp>0 can cause overflow!! - - uint32_t i; // loop counter - - register __m128i m0,m1; - - - __m128i *x_128; - __m128i *y_128; - - - shift = _mm_cvtsi32_si128(output_shift); - x_128 = (__m128i *)&x[0]; - - if (format==0) { // alpha is in shuffled format for complex multiply - ((int16_t *)&alpha_128)[0] = alpha[0]; - ((int16_t *)&alpha_128)[1] = -alpha[1]; - ((int16_t *)&alpha_128)[2] = alpha[1]; - ((int16_t *)&alpha_128)[3] = alpha[0]; - ((int16_t *)&alpha_128)[4] = alpha[0]; - ((int16_t *)&alpha_128)[5] = -alpha[1]; - ((int16_t *)&alpha_128)[6] = alpha[1]; - ((int16_t *)&alpha_128)[7] = alpha[0]; - } else { // input is in shuffled format for complex multiply - ((int16_t *)&alpha_128)[0] = alpha[0]; - ((int16_t *)&alpha_128)[1] = alpha[1]; - ((int16_t *)&alpha_128)[2] = alpha[0]; - ((int16_t *)&alpha_128)[3] = alpha[1]; - ((int16_t *)&alpha_128)[4] = alpha[0]; - ((int16_t *)&alpha_128)[5] = alpha[1]; - ((int16_t *)&alpha_128)[6] = alpha[0]; - ((int16_t *)&alpha_128)[7] = alpha[1]; - } - - y_128 = (__m128i *)&y[0]; - - // we compute 4 cpx multiply for each loop - for(i=0; i<(N>>1); i++) { - - - m0 = _mm_madd_epi16(x_128[i],alpha_128); //pmaddwd_r2r(mm1,mm0); // 1- compute x1[0]*x2[0] - m0 = _mm_sra_epi32(m0,shift); // 1- shift right by shift in order to compensate for the input amplitude - m1=m0; - m1 = _mm_packs_epi32(m1,m0); // 1- pack in a 128 bit register [re im re im] - y_128[i] = _mm_unpacklo_epi32(m1,m1); // 1- pack in a 128 bit register [re im re im] - if (format==1) { // Put output in proper format (Re,-Im,Im,Re), shuffle = (0,1,3,2) = 0x1e - - y_128[i] = _mm_shufflelo_epi16(y_128[i],0x1e); - y_128[i] = _mm_shufflehi_epi16(y_128[i],0x1e); - ((int16_t*)&y_128[i])[1] = -((int16_t*)&y_128[i])[1]; - ((int16_t*)&y_128[i])[5] = -((int16_t*)&y_128[i])[5]; - } - } - - - _mm_empty(); - _m_empty(); - - - return(0); -} -*/ - -int rotate_cpx_vector(int16_t *x, +#else +void rotate_cpx_vector(int16_t *x, int16_t *alpha, int16_t *y, uint32_t N, @@ -439,9 +273,9 @@ int rotate_cpx_vector(int16_t *x, _mm_empty(); _m_empty(); - return(0); + return; } - +#endif /* int mult_vector32_scalar(int16_t *x1, int x2, diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 839beb3dc9..954301d938 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -37,6 +37,7 @@ extern "C" { #include #include #include "PHY/sse_intrin.h" +#include "common/utils/assertions.h" #define CEILIDIV(a,b) ((a+b-1)/b) #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) @@ -104,15 +105,6 @@ void multadd_complex_vector_real_scalar(int16_t *x, uint8_t zero_flag, uint32_t N); -int rotate_cpx_vector(int16_t *x, - int16_t *alpha, - int16_t *y, - uint32_t N, - uint16_t output_shift); - - - - /*!\fn void init_fft(uint16_t size,uint8_t logsize,uint16_t *rev) \brief Initialize the FFT engine for a given size @param size Size of the FFT @@ -471,7 +463,7 @@ This function performs componentwise multiplication of a vector with a complex s The function implemented is : \f$\mathbf{y} = \alpha\mathbf{x}\f$ */ -int32_t rotate_cpx_vector(int16_t *x, +void rotate_cpx_vector(int16_t *x, int16_t *alpha, int16_t *y, uint32_t N, From 980bb2420b7713c11fba117c68f35aa1d7e0628f Mon Sep 17 00:00:00 2001 From: Laurent Thomas Date: Fri, 24 Jun 2022 17:04:40 +0200 Subject: [PATCH 33/60] fix CI discovered bug in avx2 rotate --- .../lte_ul_channel_estimation.c | 34 ++++----- openair1/PHY/MODULATION/ofdm_mod.c | 6 +- openair1/PHY/MODULATION/slot_fep_nr.c | 36 ++++----- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 24 +++--- .../nr_dl_channel_estimation.c | 23 +++--- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 17 ++--- openair1/PHY/TOOLS/cmult_sv.c | 75 ++++++------------- openair1/PHY/TOOLS/tools_defs.h | 12 +-- 8 files changed, 97 insertions(+), 130 deletions(-) diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index c867292942..e42f5f787c 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -41,10 +41,10 @@ extern int16_t *ul_ref_sigs_rx[30][2][34]; int32_t lte_ul_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, L1_rxtx_proc_t *proc, - LTE_eNB_ULSCH_t * ulsch, - int32_t **ul_ch_estimates, - int32_t **ul_ch_estimates_time, - int32_t **rxdataF_ext, + LTE_eNB_ULSCH_t * ulsch, + int32_t **ul_ch_estimates, + int32_t **ul_ch_estimates_time, + int32_t **rxdataF_ext, module_id_t UE_id, unsigned char l, unsigned char Ns) { @@ -88,7 +88,7 @@ int32_t lte_ul_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, } uint16_t N_rb_alloc = ulsch->harq_processes[harq_pid]->nb_rb; - int32_t tmp_estimates[N_rb_alloc*12] __attribute__((aligned(16))); + int32_t tmp_estimates[N_rb_alloc*12] __attribute__((aligned(32))); Msc_RS = N_rb_alloc*12; cyclic_shift = (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift + ulsch->harq_processes[harq_pid]->n_DMRS2 + @@ -334,14 +334,14 @@ int32_t lte_ul_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, current_phase2 = cmin(abs(current_phase2),127); // msg("sym: %d, current_phase1: %d, ru: %d + j%d, current_phase2: %d, ru: %d + j%d\n",k,current_phase1,ru1[2*current_phase1],ru1[2*current_phase1+1],current_phase2,ru2[2*current_phase2],ru2[2*current_phase2+1]); // rotate channel estimates by estimated phase - rotate_cpx_vector((int16_t *) ul_ch1, - &ru1[2*current_phase1], - (int16_t *) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k], + rotate_cpx_vector((c16_t *) ul_ch1, + (c16_t *)&ru1[2*current_phase1], + (c16_t *) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k], Msc_RS, 15); - rotate_cpx_vector((int16_t *) ul_ch2, - &ru2[2*current_phase2], - (int16_t *) &tmp_estimates[0], + rotate_cpx_vector((c16_t *) ul_ch2, + (c16_t *)&ru2[2*current_phase2], + (c16_t *) &tmp_estimates[0], Msc_RS, 15); // Combine the two rotated estimates @@ -657,14 +657,14 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms, current_phase2 = cmin(abs(current_phase2),127); // msg("sym: %d, current_phase1: %d, ru: %d + j%d, current_phase2: %d, ru: %d + j%d\n",k,current_phase1,ru1[2*current_phase1],ru1[2*current_phase1+1],current_phase2,ru2[2*current_phase2],ru2[2*current_phase2+1]); // rotate channel estimates by estimated phase - rotate_cpx_vector((int16_t *) ul_ch1, - &ru1[2*current_phase1], - (int16_t *) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k], + rotate_cpx_vector((c16_t *) ul_ch1, + (c16_t *)&ru1[2*current_phase1], + (c16_t *) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k], Msc_RS, 15); - rotate_cpx_vector((int16_t *) ul_ch2, - &ru2[2*current_phase2], - (int16_t *) &tmp_estimates[0], + rotate_cpx_vector((c16_t *) ul_ch2, + (c16_t *)&ru2[2*current_phase2], + (c16_t *) &tmp_estimates[0], Msc_RS, 15); // Combine the two rotated estimates diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index 2f075e8218..678eac2f3a 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -360,9 +360,9 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp, symbol_rotation[2 * (sidx + first_symbol + symb_offset)], symbol_rotation[1 + 2 * (sidx + first_symbol + symb_offset)]); - rotate_cpx_vector(trxdata + (sidx * length * 2), - &symbol_rotation[2 * (sidx + first_symbol + symb_offset)], - trxdata + (sidx * length * 2), + rotate_cpx_vector((c16_t*)trxdata + (sidx * length * 2), + (c16_t*)&symbol_rotation[2 * (sidx + first_symbol + symb_offset)], + (c16_t*) trxdata + (sidx * length * 2), length, 15); } diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 139b730ce1..5b0c4dc23a 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -98,18 +98,18 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, stop_meas(&ue->rx_dft_stats); int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; - int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[0])[symbol+symb_offset]; - ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; + c16_t rot2 = ((c16_t*)frame_parms->symbol_rotation[0])[symbol+symb_offset]; + rot2.i=-rot2.i; #ifdef DEBUG_FEP // if (ue->frame <100) printf("slot_fep: slot %d, symbol %d rx_offset %u, rotation symbol %d %d.%d\n", Ns,symbol, rx_offset, - symbol+symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]); + symbol+symb_offset,rot2.r,rot2.i); #endif - rotate_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], - (int16_t*)&rot2, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + rotate_cpx_vector((c16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + &rot2, + (c16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], frame_parms->ofdm_symbol_size, 15); @@ -214,18 +214,18 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, stop_meas(&ue->rx_dft_stats); int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; - int32_t rot2 = ((uint32_t*)frame_parms->symbol_rotation[0])[symbol + symb_offset]; - ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; + c16_t rot2 = ((c16_t*)frame_parms->symbol_rotation[0])[symbol + symb_offset]; + rot2.i=-rot2.i; #ifdef DEBUG_FEP // if (ue->frame <100) printf("slot_fep: slot %d, symbol %d rx_offset %u, rotation symbol %d %d.%d\n", Ns,symbol, rx_offset, - symbol+symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]); + symbol+symb_offset,rot2.r,rot2.i); #endif - rotate_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], - (int16_t*)&rot2, - (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + rotate_cpx_vector((c16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], + &rot2, + (c16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], frame_parms->ofdm_symbol_size, 15); } @@ -310,12 +310,12 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, for (int symbol=first_symbol;symbolsymbol_rotation[1])[symbol + symb_offset]; - ((int16_t*)&rot2)[1]=-((int16_t*)&rot2)[1]; - LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n",slot,symb_offset,((int16_t*)&rot2)[0],((int16_t*)&rot2)[1]); - rotate_cpx_vector((int16_t *)&rxdataF[soffset+(frame_parms->ofdm_symbol_size*symbol)], - (int16_t*)&rot2, - (int16_t *)&rxdataF[soffset+(frame_parms->ofdm_symbol_size*symbol)], + c16_t rot2 = ((c16_t*)frame_parms->symbol_rotation[1])[symbol + symb_offset]; + rot2.i=-rot2.i; + LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n",slot,symb_offset,rot2.r,rot2.i); + rotate_cpx_vector((c16_t *)&rxdataF[soffset+(frame_parms->ofdm_symbol_size*symbol)], + &rot2, + (c16_t *)&rxdataF[soffset+(frame_parms->ofdm_symbol_size*symbol)], length, 15); diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index cd3b535b3f..5404afd432 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -854,7 +854,7 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, uint32_t nb_re_pusch) { //#define DEBUG_UL_PTRS 1 - int16_t *phase_per_symbol = NULL; + c16_t *phase_per_symbol = NULL; int32_t *ptrs_re_symbol = NULL; int8_t ret = 0; @@ -871,20 +871,20 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, uint8_t *ptrsReOffset = &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset; /* loop over antennas */ for (int aarx=0; aarxnb_antennas_rx; aarx++) { - phase_per_symbol = (int16_t*)gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx]; + phase_per_symbol = (c16_t*)gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx]; ptrs_re_symbol = &gNB->pusch_vars[ulsch_id]->ptrs_re_per_slot; *ptrs_re_symbol = 0; - phase_per_symbol[(2*symbol)+1] = 0; // Imag + phase_per_symbol[symbol].i = 0; /* set DMRS estimates to 0 angle with magnitude 1 */ if(is_dmrs_symbol(symbol,*dmrsSymbPos)) { /* set DMRS real estimation to 32767 */ - phase_per_symbol[2*symbol]=(int16_t)((1<<15)-1); // 32767 + phase_per_symbol[symbol].r=INT16_MAX; // 32767 #ifdef DEBUG_UL_PTRS - printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[2*symbol],phase_per_symbol[(2*symbol)+1]); + printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[symbol].r,phase_per_symbol[symbol].i); #endif } else {// real ptrs value is set to 0 - phase_per_symbol[2*symbol] = 0; // Real + phase_per_symbol[symbol].r = 0; } if(symbol == *startSymbIndex) { @@ -909,7 +909,7 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, symbol,frame_parms->ofdm_symbol_size, (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(symbol * nb_re_pusch)], gNB->nr_gold_pusch_dmrs[rel15_ul->scid][nr_tti_rx][symbol], - &phase_per_symbol[2* symbol], + (int16_t*)&phase_per_symbol[symbol], ptrs_re_symbol); } /* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/ @@ -919,7 +919,7 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, /*------------------------------------------------------------------------------------------------------- */ /* If L-PTRS is > 0 then we need interpolation */ if(*L_ptrs > 0) { - ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, phase_per_symbol, *startSymbIndex, *nbSymb); + ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, (int16_t*)phase_per_symbol, *startSymbIndex, *nbSymb); if(ret != 0) { LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n"); } @@ -938,11 +938,11 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, /* Skip rotation if the slot processing is wrong */ if((!is_dmrs_symbol(i,*dmrsSymbPos)) && (ret == 0)) { #ifdef DEBUG_UL_PTRS - printf("[PHY][UL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[2* i],phase_per_symbol[(2* i) +1]); + printf("[PHY][UL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r,phase_per_symbol[i].i); #endif - rotate_cpx_vector((int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], - &phase_per_symbol[2* i], - (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], + rotate_cpx_vector((c16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], + &phase_per_symbol[i], + (c16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)], ((*nb_rb) * NR_NB_SC_PER_RB), 15); }// if not DMRS Symbol }// symbol loop diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 8936a69e70..ba7e61afe6 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -1657,7 +1657,6 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue, RX_type_t rx_type) { //#define DEBUG_DL_PTRS 1 - int16_t *phase_per_symbol = NULL; int32_t *ptrs_re_symbol = NULL; int8_t ret = 0; /* harq specific variables */ @@ -1701,20 +1700,20 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue, } /* loop over antennas */ for (int aarx=0; aarxnb_antennas_rx; aarx++) { - phase_per_symbol = (int16_t*)pdsch_vars[gNB_id]->ptrs_phase_per_slot[aarx]; + c16_t *phase_per_symbol = (c16_t*)pdsch_vars[gNB_id]->ptrs_phase_per_slot[aarx]; ptrs_re_symbol = (int32_t*)pdsch_vars[gNB_id]->ptrs_re_per_slot[aarx]; ptrs_re_symbol[symbol] = 0; - phase_per_symbol[(2*symbol)+1] = 0; // Imag + phase_per_symbol[symbol].i = 0; // Imag /* set DMRS estimates to 0 angle with magnitude 1 */ if(is_dmrs_symbol(symbol,*dmrsSymbPos)) { /* set DMRS real estimation to 32767 */ - phase_per_symbol[2*symbol]=(int16_t)((1<<15)-1); // 32767 + phase_per_symbol[symbol].r=INT16_MAX; // 32767 #ifdef DEBUG_DL_PTRS - printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[2*symbol],phase_per_symbol[(2*symbol)+1]); + printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[symbol].r,phase_per_symbol[symbol].i); #endif } else { // real ptrs value is set to 0 - phase_per_symbol[2*symbol] = 0; // Real + phase_per_symbol[symbol].r = 0; // Real } if(dlsch0_harq->status == ACTIVE) { @@ -1740,7 +1739,7 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue, symbol,frame_parms->ofdm_symbol_size, (int16_t*)&pdsch_vars[gNB_id]->rxdataF_comp0[aarx][(symbol * nb_re_pdsch)], ue->nr_gold_pdsch[gNB_id][nr_slot_rx][symbol][0], - &phase_per_symbol[2* symbol], + (int16_t*)&phase_per_symbol[symbol], &ptrs_re_symbol[symbol]); } }// HARQ 0 @@ -1752,7 +1751,7 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue, /*------------------------------------------------------------------------------------------------------- */ /* If L-PTRS is > 0 then we need interpolation */ if(*L_ptrs > 0) { - ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, phase_per_symbol, *startSymbIndex, *nbSymb); + ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, (int16_t*)phase_per_symbol, *startSymbIndex, *nbSymb); if(ret != 0) { LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n"); } @@ -1771,11 +1770,11 @@ void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue, /* Skip rotation if the slot processing is wrong */ if((!is_dmrs_symbol(i,*dmrsSymbPos)) && (ret == 0)) { #ifdef DEBUG_DL_PTRS - printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[2* i],phase_per_symbol[(2* i) +1]); + printf("[PHY][DL][PTRS]: Rotate Symbol %2d with %d + j* %d\n", i, phase_per_symbol[i].r,phase_per_symbol[i].i); #endif - rotate_cpx_vector((int16_t*)&pdsch_vars[gNB_id]->rxdataF_comp0[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)], - &phase_per_symbol[2* i], - (int16_t*)&pdsch_vars[gNB_id]->rxdataF_comp0[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)], + rotate_cpx_vector((c16_t*)&pdsch_vars[gNB_id]->rxdataF_comp0[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)], + &phase_per_symbol[i], + (c16_t*)&pdsch_vars[gNB_id]->rxdataF_comp0[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)], ((*nb_rb) * NR_NB_SC_PER_RB), 15); }// if not DMRS Symbol }// symbol loop diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index a07a19d085..22d7d5689f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -597,17 +597,16 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, int symb_offset = (slot%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; for(ap = 0; ap < n_antenna_ports; ap++) { for (int s=0;ssymbol_rotation[1])[s + symb_offset]; LOG_D(PHY,"In %s: rotating txdataF symbol %d (%d) => (%d.%d)\n", - __FUNCTION__, - s, - s + symb_offset, - frame_parms->symbol_rotation[1][2 * (s + symb_offset)], - frame_parms->symbol_rotation[1][1 + (2 * (s + symb_offset))]); + __FUNCTION__, + s, + s + symb_offset, + rot.r, rot.i); - rotate_cpx_vector((int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size * s], - &frame_parms->symbol_rotation[1][2 * (s + symb_offset)], - (int16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size * s], + rotate_cpx_vector((c16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size * s], + &rot, + (c16_t *)&txdataF[ap][frame_parms->ofdm_symbol_size * s], frame_parms->ofdm_symbol_size, 15); } diff --git a/openair1/PHY/TOOLS/cmult_sv.c b/openair1/PHY/TOOLS/cmult_sv.c index 720b5da7e8..a9d502b9eb 100644 --- a/openair1/PHY/TOOLS/cmult_sv.c +++ b/openair1/PHY/TOOLS/cmult_sv.c @@ -145,40 +145,9 @@ void multadd_real_four_symbols_vector_complex_scalar(int16_t *x, } #ifdef __AVX2__ -void rotate_cpx_vector(int16_t *x, - int16_t *alpha, - int16_t *y, - uint32_t N, - uint16_t output_shift) -{ - // multiply a complex vector with a complex value (alpha) - // stores result in y - // N is the number of complex numbers - // output_shift reduces the result of the multiplication by this number of bits - AssertFatal(N%8==0, "To be developped"); - const c16_t for_re={alpha[0], -alpha[1]}; - __m256i const alpha_for_real = _mm256_set1_epi32(*(uint32_t*)&for_re); - const c16_t for_im={alpha[1], alpha[0]}; - __m256i const alpha_for_im= _mm256_set1_epi32(*(uint32_t*)&for_im); - __m256i const perm_mask = - _mm256_set_epi8(31,30,23,22,29,28,21,20,27,26,19,18,25,24,17,16, - 15,14,7,6,13,12,5,4,11,10,3,2,9,8,1,0); - __m256i* xd= (__m256i*)x; - const __m256i *end=xd+N/8; - for( __m256i* yd = (__m256i *)y; xdr; + ((int16_t *)&alpha_128)[1] = -alpha->i; + ((int16_t *)&alpha_128)[2] = alpha->i; + ((int16_t *)&alpha_128)[3] = alpha->r; + ((int16_t *)&alpha_128)[4] = alpha->r; + ((int16_t *)&alpha_128)[5] = -alpha->i; + ((int16_t *)&alpha_128)[6] = alpha->i; + ((int16_t *)&alpha_128)[7] = alpha->r; #elif defined(__arm__) int32x4_t shift; int32x4_t ab_re0,ab_re1,ab_im0,ab_im1,re32,im32; int16_t reflip[8] __attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1}; int32x4x2_t xtmp; - ((int16_t *)&alpha_128)[0] = alpha[0]; - ((int16_t *)&alpha_128)[1] = alpha[1]; - ((int16_t *)&alpha_128)[2] = alpha[0]; - ((int16_t *)&alpha_128)[3] = alpha[1]; - ((int16_t *)&alpha_128)[4] = alpha[0]; - ((int16_t *)&alpha_128)[5] = alpha[1]; - ((int16_t *)&alpha_128)[6] = alpha[0]; - ((int16_t *)&alpha_128)[7] = alpha[1]; + ((int16_t *)&alpha_128)[0] = alpha->r; + ((int16_t *)&alpha_128)[1] = alpha->i; + ((int16_t *)&alpha_128)[2] = alpha->r; + ((int16_t *)&alpha_128)[3] = alpha->i; + ((int16_t *)&alpha_128)[4] = alpha->r; + ((int16_t *)&alpha_128)[5] = alpha->i; + ((int16_t *)&alpha_128)[6] = alpha->r; + ((int16_t *)&alpha_128)[7] = alpha->i; int16x8_t bflip = vrev32q_s16(alpha_128); int16x8_t bconj = vmulq_s16(alpha_128,*(int16x8_t *)reflip); shift = vdupq_n_s32(-output_shift); @@ -370,7 +339,7 @@ main () int16_t input[256] __attribute__((aligned(16))); int16_t input2[256] __attribute__((aligned(16))); int16_t output[256] __attribute__((aligned(16))); - int16_t alpha[2]; + c16_t alpha; int i; @@ -408,8 +377,8 @@ main () input2[14] = 1000; input2[15] = 2000; - alpha[0]=32767; - alpha[1]=0; + alpha->r=32767; + alpha->i=0; //mult_cpx_vector(input,input2,output,L,0); rotate_cpx_vector_norep(input,alpha,input,L,15); diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 954301d938..18d1533166 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -453,7 +453,7 @@ idft_size_idx_t get_idft(int ofdm_symbol_size) } -/*!\fn int32_t rotate_cpx_vector(int16_t *x,int16_t *alpha,int16_t *y,uint32_t N,uint16_t output_shift) +/*!\fn int32_t rotate_cpx_vector(c16_t *x,c16_t *alpha,c16_t *y,uint32_t N,uint16_t output_shift) This function performs componentwise multiplication of a vector with a complex scalar. @param x Vector input (Q1.15) in the format |Re0 Im0|,......,|Re(N-1) Im(N-1)| @param alpha Scalar input (Q1.15) in the format |Re0 Im0| @@ -463,11 +463,11 @@ This function performs componentwise multiplication of a vector with a complex s The function implemented is : \f$\mathbf{y} = \alpha\mathbf{x}\f$ */ -void rotate_cpx_vector(int16_t *x, - int16_t *alpha, - int16_t *y, - uint32_t N, - uint16_t output_shift); +void rotate_cpx_vector(c16_t *x, + c16_t *alpha, + c16_t *y, + uint32_t N, + uint16_t output_shift); //cadd_sv.c From ef469b9b517828b1515e19618c1a58633711fc71 Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 27 Jun 2022 18:35:38 +0200 Subject: [PATCH 34/60] code review remarks --- openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c | 3 +-- openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c | 3 +-- openair1/PHY/TOOLS/tools_defs.h | 8 ++++---- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 5404afd432..fe23e1b56f 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -854,7 +854,6 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, uint32_t nb_re_pusch) { //#define DEBUG_UL_PTRS 1 - c16_t *phase_per_symbol = NULL; int32_t *ptrs_re_symbol = NULL; int8_t ret = 0; @@ -871,7 +870,7 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, uint8_t *ptrsReOffset = &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset; /* loop over antennas */ for (int aarx=0; aarxnb_antennas_rx; aarx++) { - phase_per_symbol = (c16_t*)gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx]; + c16_t *phase_per_symbol = (c16_t*)gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx]; ptrs_re_symbol = &gNB->pusch_vars[ulsch_id]->ptrs_re_per_slot; *ptrs_re_symbol = 0; phase_per_symbol[symbol].i = 0; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c index 22d7d5689f..eaeffd0809 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c @@ -598,8 +598,7 @@ uint8_t nr_ue_pusch_common_procedures(PHY_VARS_NR_UE *UE, for(ap = 0; ap < n_antenna_ports; ap++) { for (int s=0;ssymbol_rotation[1])[s + symb_offset]; - LOG_D(PHY,"In %s: rotating txdataF symbol %d (%d) => (%d.%d)\n", - __FUNCTION__, + LOG_D(PHY,"rotating txdataF symbol %d (%d) => (%d.%d)\n", s, s + symb_offset, rot.r, rot.i); diff --git a/openair1/PHY/TOOLS/tools_defs.h b/openair1/PHY/TOOLS/tools_defs.h index 18d1533166..c471978f46 100644 --- a/openair1/PHY/TOOLS/tools_defs.h +++ b/openair1/PHY/TOOLS/tools_defs.h @@ -464,10 +464,10 @@ This function performs componentwise multiplication of a vector with a complex s The function implemented is : \f$\mathbf{y} = \alpha\mathbf{x}\f$ */ void rotate_cpx_vector(c16_t *x, - c16_t *alpha, - c16_t *y, - uint32_t N, - uint16_t output_shift); + c16_t *alpha, + c16_t *y, + uint32_t N, + uint16_t output_shift); //cadd_sv.c From 5894bcac227d20ad6be47c7b0670bfbc98fc3f87 Mon Sep 17 00:00:00 2001 From: laurent Date: Mon, 27 Jun 2022 18:48:45 +0200 Subject: [PATCH 35/60] rebase develop --- openair1/PHY/MODULATION/ofdm_mod.c | 34 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index 678eac2f3a..609f0c75df 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -46,18 +46,18 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA PHY_ofdm_mod(txdataF, // input - txdata, // output - frame_parms->ofdm_symbol_size, + txdata, // output + frame_parms->ofdm_symbol_size, - 1, // number of symbols - frame_parms->nb_prefix_samples0, // number of prefix samples - CYCLIC_PREFIX); + 1, // number of symbols + frame_parms->nb_prefix_samples0, // number of prefix samples + CYCLIC_PREFIX); PHY_ofdm_mod(txdataF+frame_parms->ofdm_symbol_size, // input - txdata+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0, // output - frame_parms->ofdm_symbol_size, - nsymb-1, - frame_parms->nb_prefix_samples, // number of prefix samples - CYCLIC_PREFIX); + txdata+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0, // output + frame_parms->ofdm_symbol_size, + nsymb-1, + frame_parms->nb_prefix_samples, // number of prefix samples + CYCLIC_PREFIX); @@ -341,11 +341,11 @@ void do_OFDM_mod(int32_t **txdataF, int32_t **txdata, uint32_t frame,uint16_t ne } void apply_nr_rotation(NR_DL_FRAME_PARMS *fp, - int16_t* trxdata, - int slot, - int first_symbol, - int nsymb, - int length) { + int16_t* trxdata, + int slot, + int first_symbol, + int nsymb, + int length) { int symb_offset = (slot%fp->slots_per_subframe)*fp->symbols_per_slot; int16_t *symbol_rotation = fp->symbol_rotation[0]; @@ -362,9 +362,9 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp, rotate_cpx_vector((c16_t*)trxdata + (sidx * length * 2), (c16_t*)&symbol_rotation[2 * (sidx + first_symbol + symb_offset)], - (c16_t*) trxdata + (sidx * length * 2), + (c16_t*) trxdata + (sidx * length * 2), length, 15); } } - + From d6e58c94364aadfbf046f80d43e28fb1cc50f8e6 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Mon, 27 Jun 2022 23:18:06 +0100 Subject: [PATCH 36/60] Fix decoding multiple ULSCH in the same slot in the case of a ULSCH fails to be detected --- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 2c56e2e4b2..1428987d40 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -625,6 +625,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { /* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */ int pucch_decode_done = 0; int pusch_decode_done = 0; + int phy_procedures_errors = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,1); LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); @@ -764,7 +765,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { if (no_sig) { LOG_D(PHY, "PUSCH not detected in frame %d, slot %d\n", frame_rx, slot_rx); nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, harq_pid, 1,1); - return 1; + phy_procedures_errors++; + continue; } gNB->pusch_vars[ULSCH_id]->ulsch_power_tot=0; gNB->pusch_vars[ULSCH_id]->ulsch_noise_power_tot=0; @@ -788,7 +790,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { /* in case of phy_test mode, we still want to decode to measure execution time. Therefore, we don't yet call nr_fill_indication, it will be called later */ nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 1,1); - return 1; + phy_procedures_errors++; + continue; } } else { LOG_D(PHY, "PUSCH detected in %d.%d (%d,%d,%d)\n",frame_rx,slot_rx, @@ -855,5 +858,5 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0); - return 0; + return phy_procedures_errors; } From ff5ec94d339fab462e8f8cc1e64a993a58e11330 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 28 Jun 2022 09:38:48 +0200 Subject: [PATCH 37/60] Address review: drop bool defines --- openair2/RRC/NR/rrc_gNB_reconfig.c | 3 --- openair2/UTIL/OMG/defs.h | 6 ------ 2 files changed, 9 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c index 44212cbf7a..2ee3a26c4b 100644 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ b/openair2/RRC/NR/rrc_gNB_reconfig.c @@ -47,9 +47,6 @@ #include "LAYER2/nr_rlc/nr_rlc_oai_api.h" #include "nr_rrc_config.h" -#define false 0 -#define true 1 - void fix_servingcellconfigdedicated(NR_ServingCellConfig_t *scd) { int b = 0; diff --git a/openair2/UTIL/OMG/defs.h b/openair2/UTIL/OMG/defs.h index 06c9bf6e73..1102a69cc5 100644 --- a/openair2/UTIL/OMG/defs.h +++ b/openair2/UTIL/OMG/defs.h @@ -29,12 +29,6 @@ #include -// TYPEDEFS - -#define true 1 -#define false 0 - -//typedef char bool; #include #include "omg_constants.h" From df1cffbc7f3f323cfe8e674546673e9f9592588d Mon Sep 17 00:00:00 2001 From: laurent Date: Wed, 29 Jun 2022 16:52:47 +0200 Subject: [PATCH 38/60] fix bug introduced by avx2 rotate_cpx change to c16_t --- cmake_targets/tools/build_helper | 4 +-- .../lte_ul_channel_estimation.c | 6 ++--- openair1/PHY/MODULATION/nr_modulation.c | 26 +++++++++---------- openair1/PHY/MODULATION/ofdm_mod.c | 12 ++++----- openair1/PHY/MODULATION/slot_fep_nr.c | 14 +++++----- openair1/PHY/defs_nr_common.h | 4 +-- 6 files changed, 33 insertions(+), 33 deletions(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 95f237ab33..d35f90fcce 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -197,8 +197,8 @@ check_warnings() { #argument: # $1: log file check_errors() { - #we look for 'warning:' in the compilation log file - error_count=`grep "error:" "$1" | wc -l` + #we look for 'error:' in the compilation log file + error_count=`grep -c "error:" "$1"` if [ $error_count -gt 0 ]; then echo_error "ERROR: $error_count error. See $1" fi diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index e42f5f787c..9327fe9fe8 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -341,7 +341,7 @@ int32_t lte_ul_channel_estimation(LTE_DL_FRAME_PARMS *frame_parms, 15); rotate_cpx_vector((c16_t *) ul_ch2, (c16_t *)&ru2[2*current_phase2], - (c16_t *) &tmp_estimates[0], + (c16_t *) tmp_estimates, Msc_RS, 15); // Combine the two rotated estimates @@ -658,12 +658,12 @@ int32_t lte_ul_channel_estimation_RRU(LTE_DL_FRAME_PARMS *frame_parms, // msg("sym: %d, current_phase1: %d, ru: %d + j%d, current_phase2: %d, ru: %d + j%d\n",k,current_phase1,ru1[2*current_phase1],ru1[2*current_phase1+1],current_phase2,ru2[2*current_phase2],ru2[2*current_phase2+1]); // rotate channel estimates by estimated phase rotate_cpx_vector((c16_t *) ul_ch1, - (c16_t *)&ru1[2*current_phase1], + (c16_t *) &ru1[2*current_phase1], (c16_t *) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k], Msc_RS, 15); rotate_cpx_vector((c16_t *) ul_ch2, - (c16_t *)&ru2[2*current_phase2], + (c16_t *) &ru2[2*current_phase2], (c16_t *) &tmp_estimates[0], Msc_RS, 15); diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c index 8352a7f5a6..8ebd70fb92 100644 --- a/openair1/PHY/MODULATION/nr_modulation.c +++ b/openair1/PHY/MODULATION/nr_modulation.c @@ -618,20 +618,20 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) { double f0 = f[ll]; double Ncpm1 = Ncp0; - int16_t *symbol_rotation = fp->symbol_rotation[ll]; + c16_t *symbol_rotation = fp->symbol_rotation[ll]; double tl = 0; double poff = 2 * M_PI * ((Ncp0 * Tc)) * f0; double exp_re = cos(poff); double exp_im = sin(-poff); - symbol_rotation[0] = (int16_t)floor(exp_re * 32767); - symbol_rotation[1] = (int16_t)floor(exp_im * 32767); + symbol_rotation[0].r = (int16_t)floor(exp_re * 32767); + symbol_rotation[0].i = (int16_t)floor(exp_im * 32767); LOG_I(PHY, "Doing symbol rotation calculation for gNB TX/RX, f0 %f Hz, Nsymb %d\n", f0, nsymb); LOG_I(PHY, "Symbol rotation %d/%d => (%d,%d)\n", 0, nsymb, - symbol_rotation[0], - symbol_rotation[1]); + symbol_rotation[0].r, + symbol_rotation[0].i); for (int l = 1; l < nsymb; l++) { @@ -646,15 +646,15 @@ void init_symbol_rotation(NR_DL_FRAME_PARMS *fp) { poff = 2 * M_PI * (tl + (Ncp * Tc)) * f0; exp_re = cos(poff); exp_im = sin(-poff); - symbol_rotation[l<<1] = (int16_t)floor(exp_re * 32767); - symbol_rotation[1 + (l<<1)] = (int16_t)floor(exp_im * 32767); + symbol_rotation[l].r = (int16_t)floor(exp_re * 32767); + symbol_rotation[l].i = (int16_t)floor(exp_im * 32767); LOG_I(PHY, "Symbol rotation %d/%d => tl %f (%d,%d) (%f)\n", l, nsymb, tl, - symbol_rotation[l<<1], - symbol_rotation[1 + (l<<1)], + symbol_rotation[l].r, + symbol_rotation[l].i, (poff / 2 / M_PI) - floor(poff / 2 / M_PI)); Ncpm1 = Ncp; @@ -670,13 +670,13 @@ void init_timeshift_rotation(NR_DL_FRAME_PARMS *fp) double poff = -i * 2.0 * M_PI * sample_offset / fp->ofdm_symbol_size; double exp_re = cos(poff); double exp_im = sin(-poff); - fp->timeshift_symbol_rotation[i*2] = (int16_t)round(exp_re * 32767); - fp->timeshift_symbol_rotation[i*2+1] = (int16_t)round(exp_im * 32767); + fp->timeshift_symbol_rotation[i].r = (int16_t)round(exp_re * 32767); + fp->timeshift_symbol_rotation[i].i = (int16_t)round(exp_im * 32767); if (i < 10) LOG_I(PHY,"Timeshift symbol rotation %d => (%d,%d) %f\n",i, - fp->timeshift_symbol_rotation[i*2], - fp->timeshift_symbol_rotation[i*2+1], + fp->timeshift_symbol_rotation[i].r, + fp->timeshift_symbol_rotation[i].i, poff); } } diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index 609f0c75df..0b8f22a094 100644 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -348,7 +348,7 @@ void apply_nr_rotation(NR_DL_FRAME_PARMS *fp, int length) { int symb_offset = (slot%fp->slots_per_subframe)*fp->symbols_per_slot; - int16_t *symbol_rotation = fp->symbol_rotation[0]; + c16_t *symbol_rotation = fp->symbol_rotation[0]; for (int sidx=0;sidxrx_dft_stats); int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; - c16_t rot2 = ((c16_t*)frame_parms->symbol_rotation[0])[symbol+symb_offset]; + c16_t rot2 = frame_parms->symbol_rotation[0][symbol+symb_offset]; rot2.i=-rot2.i; #ifdef DEBUG_FEP @@ -113,10 +113,10 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, frame_parms->ofdm_symbol_size, 15); - int16_t *shift_rot = frame_parms->timeshift_symbol_rotation; + c16_t *shift_rot = frame_parms->timeshift_symbol_rotation; multadd_cpx_vector((int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], - shift_rot, + (int16_t *)shift_rot, (int16_t *)&common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], 1, frame_parms->ofdm_symbol_size, @@ -214,7 +214,7 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, stop_meas(&ue->rx_dft_stats); int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; - c16_t rot2 = ((c16_t*)frame_parms->symbol_rotation[0])[symbol + symb_offset]; + c16_t rot2 = frame_parms->symbol_rotation[0][symbol + symb_offset]; rot2.i=-rot2.i; #ifdef DEBUG_FEP @@ -310,7 +310,7 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, for (int symbol=first_symbol;symbolsymbol_rotation[1])[symbol + symb_offset]; + c16_t rot2 = frame_parms->symbol_rotation[1][symbol + symb_offset]; rot2.i=-rot2.i; LOG_D(PHY,"slot %d, symb_offset %d rotating by %d.%d\n",slot,symb_offset,rot2.r,rot2.i); rotate_cpx_vector((c16_t *)&rxdataF[soffset+(frame_parms->ofdm_symbol_size*symbol)], @@ -319,10 +319,10 @@ void apply_nr_rotation_ul(NR_DL_FRAME_PARMS *frame_parms, length, 15); - int16_t *shift_rot = frame_parms->timeshift_symbol_rotation; + c16_t *shift_rot = frame_parms->timeshift_symbol_rotation; multadd_cpx_vector((int16_t *)&rxdataF[soffset+(frame_parms->ofdm_symbol_size*symbol)], - shift_rot, + (int16_t *)shift_rot, (int16_t *)&rxdataF[soffset+(frame_parms->ofdm_symbol_size*symbol)], 1, length, diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 9c8e90a9c7..67345b1a53 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -359,10 +359,10 @@ struct NR_DL_FRAME_PARMS { lte_prefix_type_t Ncp; /// sequence which is computed based on carrier frequency and numerology to rotate/derotate each OFDM symbol according to Section 5.3 in 38.211 /// First dimension is for the direction of the link (0 DL, 1 UL) - int16_t symbol_rotation[2][224*2]; + c16_t symbol_rotation[2][224]; /// sequence used to compensate the phase rotation due to timeshifted OFDM symbols /// First dimenstion is for different CP lengths - int16_t timeshift_symbol_rotation[4096*2] __attribute__ ((aligned (16))); + c16_t timeshift_symbol_rotation[4096*2] __attribute__ ((aligned (16))); /// shift of pilot position in one RB uint8_t nushift; /// SRS configuration from TS 38.331 RRC From c2fee0520c1bf91b33f6b8429ebef14a7d2a6add Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Thu, 30 Jun 2022 17:59:11 +0100 Subject: [PATCH 39/60] Fix variable redefinition --- openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c | 1 - 1 file changed, 1 deletion(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index f28f68acbd..f802c5b869 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -1163,7 +1163,6 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB, *snr = dB_fixed((int32_t)((*signal_power<first_carrier_offset + srs_pdu->bwp_start*12; uint8_t R = srs_pdu->comb_size == 0 ? 2 : 4; for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) { From 253e037fb284239b56c05c4f7358478c86dbef03 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Tue, 5 Jul 2022 11:07:01 +0100 Subject: [PATCH 40/60] Remove some variables from nr_srs_info_t --- openair1/PHY/defs_nr_common.h | 5 ----- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 19 ++++++++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index fe895d1770..a5a0824166 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -249,11 +249,6 @@ typedef struct { int32_t **srs_estimated_channel_freq; int32_t **srs_estimated_channel_time; int32_t **srs_estimated_channel_time_shifted; - uint32_t signal_power; - uint32_t noise_power_per_rb[273]; - uint32_t noise_power; - int8_t snr_per_rb[273]; - int8_t snr; } nr_srs_info_t; typedef struct { diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 1635de7e81..f92190df56 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -848,6 +848,11 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { LOG_D(NR_PHY, "(%d.%d) gNB is waiting for SRS, id = %i\n", frame_rx, slot_rx, i); nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; + uint32_t noise_power_per_rb[srs_pdu->bwp_size]; + int8_t snr_per_rb[srs_pdu->bwp_size]; + uint32_t signal_power; + uint32_t noise_power; + int8_t snr; // At least currently, the configuration is constant, so it is enough to generate the sequence just once. if(gNB->nr_srs_info[i]->sc_list_length == 0) { @@ -867,11 +872,11 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { gNB->nr_srs_info[i]->srs_estimated_channel_freq, gNB->nr_srs_info[i]->srs_estimated_channel_time, gNB->nr_srs_info[i]->srs_estimated_channel_time_shifted, - &gNB->nr_srs_info[i]->signal_power, - gNB->nr_srs_info[i]->noise_power_per_rb, - &gNB->nr_srs_info[i]->noise_power, - gNB->nr_srs_info[i]->snr_per_rb, - &gNB->nr_srs_info[i]->snr); + &signal_power, + noise_power_per_rb, + &noise_power, + snr_per_rb, + &snr); } T(T_GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE, T_INT(0), T_INT(srs_pdu->rnti), T_INT(frame_rx), T_INT(0), T_INT(0), @@ -889,7 +894,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { gNB->srs_pdu_list[num_srs].timing_advance = srs_est >= 0 ? nr_est_timing_advance_srs(&gNB->frame_parms, (const int32_t **)gNB->nr_srs_info[i]->srs_estimated_channel_time) : 0xFFFF; gNB->srs_pdu_list[num_srs].num_symbols = 1<num_symbols; - gNB->srs_pdu_list[num_srs].wide_band_snr = srs_est >= 0 ? (gNB->nr_srs_info[i]->snr + 64)<<1 : 0xFF; // 0xFF will be set if this field is invalid + gNB->srs_pdu_list[num_srs].wide_band_snr = srs_est >= 0 ? (snr + 64)<<1 : 0xFF; // 0xFF will be set if this field is invalid gNB->srs_pdu_list[num_srs].num_reported_symbols = 1<num_symbols; if(!gNB->srs_pdu_list[num_srs].reported_symbol_list) { gNB->srs_pdu_list[num_srs].reported_symbol_list = (nfapi_nr_srs_indication_reported_symbol_t*) calloc(1, gNB->srs_pdu_list[num_srs].num_reported_symbols*sizeof(nfapi_nr_srs_indication_reported_symbol_t)); @@ -897,7 +902,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { fill_srs_reported_symbol_list(&gNB->srs_pdu_list[num_srs].reported_symbol_list[0], srs_pdu, gNB->frame_parms.N_RB_UL, - gNB->nr_srs_info[i]->snr_per_rb, + snr_per_rb, srs_est); gNB->UL_INFO.srs_ind.number_of_pdus += 1; From 52f6d38a3478fd6bb13bb2dd0527153003605145 Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Tue, 5 Jul 2022 12:58:53 +0100 Subject: [PATCH 41/60] Remove more variables from nr_srs_info_t --- openair1/PHY/INIT/nr_init.c | 24 --------------- openair1/PHY/INIT/nr_init_ue.c | 25 ---------------- .../PHY/NR_ESTIMATION/nr_measurements_gNB.c | 2 +- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 10 +++---- openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 11 +++---- .../PHY/NR_TRANSPORT/nr_transport_proto.h | 2 +- openair1/PHY/NR_TRANSPORT/srs_rx.c | 2 +- openair1/PHY/defs_nr_common.h | 5 ---- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 30 ++++++++++++------- 9 files changed, 33 insertions(+), 78 deletions(-) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index bd349d146a..4fe66a5cbf 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -613,18 +613,6 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB, for (int id=0; idnr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t)); - gNB->nr_srs_info[id]->srs_received_signal = (int32_t **)malloc16(Prx*sizeof(int32_t*)); - gNB->nr_srs_info[id]->srs_ls_estimated_channel = (int32_t **)malloc16(Prx*sizeof(int32_t*)); - gNB->nr_srs_info[id]->srs_estimated_channel_freq = (int32_t **)malloc16(Prx*sizeof(int32_t*)); - gNB->nr_srs_info[id]->srs_estimated_channel_time = (int32_t **)malloc16(Prx*sizeof(int32_t*)); - gNB->nr_srs_info[id]->srs_estimated_channel_time_shifted = (int32_t **)malloc16(Prx*sizeof(int32_t*)); - for (i=0;inr_srs_info[id]->srs_received_signal[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t)); - gNB->nr_srs_info[id]->srs_ls_estimated_channel[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t)); - gNB->nr_srs_info[id]->srs_estimated_channel_freq[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t)); - gNB->nr_srs_info[id]->srs_estimated_channel_time[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t)); - gNB->nr_srs_info[id]->srs_estimated_channel_time_shifted[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t)); - } } generate_ul_reference_signal_sequences(SHRT_MAX); @@ -782,18 +770,6 @@ void phy_free_nr_gNB(PHY_VARS_gNB *gNB) free_and_zero(gNB->nr_csi_rs_info); for (int id = 0; id < NUMBER_OF_NR_SRS_MAX; id++) { - for (int i = 0; i < Prx; i++) { - free_and_zero(gNB->nr_srs_info[id]->srs_received_signal[i]); - free_and_zero(gNB->nr_srs_info[id]->srs_ls_estimated_channel[i]); - free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_freq[i]); - free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_time[i]); - free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_time_shifted[i]); - } - free_and_zero(gNB->nr_srs_info[id]->srs_received_signal); - free_and_zero(gNB->nr_srs_info[id]->srs_ls_estimated_channel); - free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_freq); - free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_time); - free_and_zero(gNB->nr_srs_info[id]->srs_estimated_channel_time_shifted); free_and_zero(gNB->nr_srs_info[id]); } diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 254a25097c..a332c2067c 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -377,19 +377,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) } ue->nr_srs_info = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t)); - ue->nr_srs_info->srs_received_signal = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) ); - ue->nr_srs_info->srs_ls_estimated_channel = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) ); - ue->nr_srs_info->srs_estimated_channel_freq = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) ); - ue->nr_srs_info->srs_estimated_channel_time = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) ); - ue->nr_srs_info->srs_estimated_channel_time_shifted = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) ); - for (i=0; inb_antennas_rx; i++) { - ue->nr_srs_info->srs_received_signal[i] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t)); - ue->nr_srs_info->srs_ls_estimated_channel[i] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t)); - ue->nr_srs_info->srs_estimated_channel_freq[i] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t)); - ue->nr_srs_info->srs_estimated_channel_time[i] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t)); - ue->nr_srs_info->srs_estimated_channel_time_shifted[i] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t)); - } - // RACH prach_vars[gNB_id]->prachF = (int16_t *)malloc16_clear( sizeof(int)*(7*2*sizeof(int)*(fp->ofdm_symbol_size*12)) ); @@ -517,18 +504,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB) free_and_zero(ue->nr_csi_rs_info->csi_rs_estimated_channel_freq); free_and_zero(ue->nr_csi_rs_info); - for (int i = 0; i < fp->nb_antennas_rx; i++) { - free_and_zero(ue->nr_srs_info->srs_received_signal[i]); - free_and_zero(ue->nr_srs_info->srs_ls_estimated_channel[i]); - free_and_zero(ue->nr_srs_info->srs_estimated_channel_freq[i]); - free_and_zero(ue->nr_srs_info->srs_estimated_channel_time[i]); - free_and_zero(ue->nr_srs_info->srs_estimated_channel_time_shifted[i]); - } - free_and_zero(ue->nr_srs_info->srs_received_signal); - free_and_zero(ue->nr_srs_info->srs_ls_estimated_channel); - free_and_zero(ue->nr_srs_info->srs_estimated_channel_freq); - free_and_zero(ue->nr_srs_info->srs_estimated_channel_time); - free_and_zero(ue->nr_srs_info->srs_estimated_channel_time_shifted); free_and_zero(ue->nr_srs_info); free_and_zero(ue->csiim_vars[gNB_id]); diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index c1be11c468..1793a76fe1 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -68,7 +68,7 @@ int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) } int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms, - const int32_t **srs_estimated_channel_time) { + const int32_t srs_estimated_channel_time[][frame_parms->ofdm_symbol_size]) { int timing_advance = 0; int max_val = 0; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 84470be571..080b9b65d5 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -965,10 +965,11 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB, const nfapi_nr_srs_pdu_t *srs_pdu, const nr_srs_info_t *nr_srs_info, const int32_t *srs_generated_signal, - const int32_t **srs_received_signal, - int32_t **srs_estimated_channel_freq, - int32_t **srs_estimated_channel_time, - int32_t **srs_estimated_channel_time_shifted, + int32_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size*(1<num_symbols)], + int32_t srs_ls_estimated_channel[][gNB->frame_parms.ofdm_symbol_size*(1<num_symbols)], + int32_t srs_estimated_channel_freq[][gNB->frame_parms.ofdm_symbol_size*(1<num_symbols)], + int32_t srs_estimated_channel_time[][gNB->frame_parms.ofdm_symbol_size], + int32_t srs_estimated_channel_time_shifted[][gNB->frame_parms.ofdm_symbol_size], uint32_t *signal_power, uint32_t *noise_power_per_rb, uint32_t *noise_power, @@ -981,7 +982,6 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB, } const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - int32_t **srs_ls_estimated_channel = nr_srs_info->srs_ls_estimated_channel; int16_t ch_real[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length]; int16_t ch_imag[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length]; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 01af743473..b0ed3662ea 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -56,7 +56,7 @@ void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq int nr_est_timing_advance_pusch(PHY_VARS_gNB* phy_vars_gNB, int UE_id); int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms, - const int32_t **srs_estimated_channel_time); + const int32_t srs_estimated_channel_time[][frame_parms->ofdm_symbol_size]); void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, NR_DL_FRAME_PARMS *frame_parms, @@ -72,10 +72,11 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB, const nfapi_nr_srs_pdu_t *srs_pdu, const nr_srs_info_t *nr_srs_info, const int32_t *srs_generated_signal, - const int32_t **srs_received_signal, - int32_t **srs_estimated_channel_freq, - int32_t **srs_estimated_channel_time, - int32_t **srs_estimated_channel_time_shifted, + int32_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size*(1<num_symbols)], + int32_t srs_ls_estimated_channel[][gNB->frame_parms.ofdm_symbol_size*(1<num_symbols)], + int32_t srs_estimated_channel_freq[][gNB->frame_parms.ofdm_symbol_size*(1<num_symbols)], + int32_t srs_estimated_channel_time[][gNB->frame_parms.ofdm_symbol_size], + int32_t srs_estimated_channel_time_shifted[][gNB->frame_parms.ofdm_symbol_size], uint32_t *signal_power, uint32_t *noise_power_per_rb, uint32_t *noise_power, diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index e3b7efacfb..109fac7e2d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -330,7 +330,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, int slot, nfapi_nr_srs_pdu_t *srs_pdu, nr_srs_info_t *nr_srs_info, - int32_t **srs_received_signal); + int32_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size*(1<num_symbols)]); void init_prach_list(PHY_VARS_gNB *gNB); void init_prach_ru_list(RU_t *ru); diff --git a/openair1/PHY/NR_TRANSPORT/srs_rx.c b/openair1/PHY/NR_TRANSPORT/srs_rx.c index ffcd7362f3..39c3846db5 100644 --- a/openair1/PHY/NR_TRANSPORT/srs_rx.c +++ b/openair1/PHY/NR_TRANSPORT/srs_rx.c @@ -98,7 +98,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, int slot, nfapi_nr_srs_pdu_t *srs_pdu, nr_srs_info_t *nr_srs_info, - int32_t **srs_received_signal) { + int32_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size*(1<num_symbols)]) { if(nr_srs_info->sc_list_length == 0) { LOG_E(NR_PHY, "(%d.%d) nr_srs_info was not generated yet!\n", frame, slot); diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 93c419da6f..ebcf8361f6 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -244,11 +244,6 @@ typedef struct { uint16_t sc_list[6*273]; uint8_t srs_generated_signal_bits; int32_t srs_generated_signal[OFDM_SYMBOL_SIZE_SAMPLES_MAX * MAX_NUM_NR_SRS_SYMBOLS]; - int32_t **srs_received_signal; - int32_t **srs_ls_estimated_channel; - int32_t **srs_estimated_channel_freq; - int32_t **srs_estimated_channel_time; - int32_t **srs_estimated_channel_time_shifted; } nr_srs_info_t; typedef struct { diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 635a0d0f37..d2cf0f141f 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -850,7 +850,14 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { LOG_D(NR_PHY, "(%d.%d) gNB is waiting for SRS, id = %i\n", frame_rx, slot_rx, i); + NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; + uint8_t N_symb_SRS = 1<num_symbols; + int32_t srs_received_signal[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size*N_symb_SRS]; + int32_t srs_ls_estimated_channel[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size*N_symb_SRS]; + int32_t srs_estimated_channel_freq[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size*N_symb_SRS]; + int32_t srs_estimated_channel_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size]; + int32_t srs_estimated_channel_time_shifted[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size]; uint32_t noise_power_per_rb[srs_pdu->bwp_size]; int8_t snr_per_rb[srs_pdu->bwp_size]; uint32_t signal_power; @@ -859,10 +866,10 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { // At least currently, the configuration is constant, so it is enough to generate the sequence just once. if(gNB->nr_srs_info[i]->sc_list_length == 0) { - generate_srs_nr(srs_pdu, &gNB->frame_parms, gNB->nr_srs_info[i]->srs_generated_signal, gNB->nr_srs_info[i], AMP, frame_rx, slot_rx); + generate_srs_nr(srs_pdu, frame_parms, gNB->nr_srs_info[i]->srs_generated_signal, gNB->nr_srs_info[i], AMP, frame_rx, slot_rx); } - const int srs_est = nr_get_srs_signal(gNB,frame_rx,slot_rx,srs_pdu, gNB->nr_srs_info[i], gNB->nr_srs_info[i]->srs_received_signal); + const int srs_est = nr_get_srs_signal(gNB,frame_rx,slot_rx, srs_pdu, gNB->nr_srs_info[i], srs_received_signal); if (srs_est >= 0) { nr_srs_channel_estimation(gNB, @@ -871,10 +878,11 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { srs_pdu, gNB->nr_srs_info[i], gNB->nr_srs_info[i]->srs_generated_signal, - (const int32_t **)gNB->nr_srs_info[i]->srs_received_signal, - gNB->nr_srs_info[i]->srs_estimated_channel_freq, - gNB->nr_srs_info[i]->srs_estimated_channel_time, - gNB->nr_srs_info[i]->srs_estimated_channel_time_shifted, + srs_received_signal, + srs_ls_estimated_channel, + srs_estimated_channel_freq, + srs_estimated_channel_time, + srs_estimated_channel_time_shifted, &signal_power, noise_power_per_rb, &noise_power, @@ -883,10 +891,10 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { } T(T_GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE, T_INT(0), T_INT(srs_pdu->rnti), T_INT(frame_rx), T_INT(0), T_INT(0), - T_BUFFER(gNB->nr_srs_info[i]->srs_estimated_channel_freq[0], gNB->frame_parms.ofdm_symbol_size*sizeof(int32_t))); + T_BUFFER(srs_estimated_channel_freq[0], frame_parms->ofdm_symbol_size*sizeof(int32_t))); T(T_GNB_PHY_UL_TIME_CHANNEL_ESTIMATE, T_INT(0), T_INT(srs_pdu->rnti), T_INT(frame_rx), T_INT(0), T_INT(0), - T_BUFFER(gNB->nr_srs_info[i]->srs_estimated_channel_time_shifted[0], gNB->frame_parms.ofdm_symbol_size*sizeof(int32_t))); + T_BUFFER(srs_estimated_channel_time_shifted[0], frame_parms->ofdm_symbol_size*sizeof(int32_t))); const uint16_t num_srs = gNB->UL_INFO.srs_ind.number_of_pdus; gNB->UL_INFO.srs_ind.pdu_list = &gNB->srs_pdu_list[0]; @@ -894,8 +902,8 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { gNB->UL_INFO.srs_ind.slot = slot_rx; gNB->srs_pdu_list[num_srs].handle = srs_pdu->handle; gNB->srs_pdu_list[num_srs].rnti = srs_pdu->rnti; - gNB->srs_pdu_list[num_srs].timing_advance = srs_est >= 0 ? nr_est_timing_advance_srs(&gNB->frame_parms, - (const int32_t **)gNB->nr_srs_info[i]->srs_estimated_channel_time) : 0xFFFF; + gNB->srs_pdu_list[num_srs].timing_advance = srs_est >= 0 ? nr_est_timing_advance_srs(frame_parms, + srs_estimated_channel_time) : 0xFFFF; gNB->srs_pdu_list[num_srs].num_symbols = 1<num_symbols; gNB->srs_pdu_list[num_srs].wide_band_snr = srs_est >= 0 ? (snr + 64)<<1 : 0xFF; // 0xFF will be set if this field is invalid gNB->srs_pdu_list[num_srs].num_reported_symbols = 1<num_symbols; @@ -904,7 +912,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { } fill_srs_reported_symbol_list(&gNB->srs_pdu_list[num_srs].reported_symbol_list[0], srs_pdu, - gNB->frame_parms.N_RB_UL, + frame_parms->N_RB_UL, snr_per_rb, srs_est); From 805b35643f047857fe3604c5fd1c265753418855 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 24 Jun 2022 10:37:22 +0200 Subject: [PATCH 42/60] Updates in TESTBench documentation - Correct carabe name - NR freq bands with "nXX" - add amariue in figure - minor changes --- doc/TESTBenches.md | 12 ++++++------ .../4g-faraday-bench.pdf | Bin 53134 -> 53079 bytes .../4g-faraday-bench.png | Bin 92391 -> 92377 bytes .../5g-nsa-faraday-bench.pdf | Bin 337513 -> 337509 bytes .../5g-nsa-faraday-bench.png | Bin 89436 -> 89413 bytes .../5g-nsa-faraday-bench.tex | 2 +- .../5g-ota-bench.pdf | Bin 232494 -> 232400 bytes .../5g-ota-bench.png | Bin 90027 -> 96734 bytes .../5g-ota-bench.tex | 13 +++++++++---- 9 files changed, 16 insertions(+), 11 deletions(-) diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index 547fd5a23b..7951bb6a88 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -9,19 +9,19 @@ | Machine | IP address | Lockable Resource | Function | Connected devices | | ------------- | --------------- | --------------------- | ------------------ | ----------------------------------------------------- | -| asterix | 172.21.16.127 | CI-Asterix-Usage | gNB | 173.21.19.14 | -| obelix | 172.21.16.128 | CI-Obelix-Usage | eNB, UE (5G) | 172.21.19.13, X300 (192.168.60.2), B200mini (30C51EB) | +| asterix | 172.21.16.127 | CI-Asterix-Usage | gNB (n78) | 173.21.19.14 | +| obelix | 172.21.16.128 | CI-Obelix-Usage | eNB (n40, n78), nrUE | 172.21.19.13, X300 (192.168.60.2), B200mini (30C51EB) | | porcepix | 172.21.16.136 | CI-NSA-MiniBench | Executor, EPC, 5GC | -- | | nrmodule2 | 172.21.16.139 | CI-NSA-MiniBench | Quectel | Quectel module | -| nepes | 172.21.16.137 | CI-NSA-MiniBench | gNB | B200mini (30C51D4) | +| nepes | 172.21.16.137 | CI-NSA-MiniBench | gNB (n78) | B200mini (30C51D4) | | caracal | 172.21.16.132 | CI-Caracal | gNB/phytest | N300 (192.168.10.2) | | idefix | 172.21.16.135 | CI-NSA-MiniBench | Quectel | Quectel module | -| amariue | 172.21.16.144 | CI-Amarisoft-UE-Usage | TBD | Amarisoft UE simulator | +| amariue | 172.21.16.144 | CI-Amarisoft-UE-Usage | nrUE | Amarisoft UE simulator | | bellatrix | 192.168.117.115 | CI-RAN-VM-Deployment | Executor | -- | | nano | 192.168.12.62 | CI-Bench-1-Phones | EPC, adb | 2x COTS (adb) | | hutch | 192.168.12.19 | CI-Bench-1-Phones | eNB (B7) | B200mini (30C5239) | | starsky | 192.168.12.18 | CI-Bench-1-Phones | eNB (B40) | b200mini (30A3E3C) | -| carabe | 192.168.12.211 | CI-Bench-2-OAI-Phone | UE 4G (B) | B200mini (30AE8C9) | +| carabe | 192.168.12.211 | CI-Bench-2-OAI-Phone | UE (B7UE) | B200mini (30AE8C9) | Note: The available resources, and their current usage, is indicated here: - [Lockable resources of jenkins-oai](https://jenkins-oai.eurecom.fr/lockable-resources/): @@ -40,7 +40,7 @@ Note: The available resources, and their current usage, is indicated here: ### OTA Testbench -[Proper image to be followed up. TBD: add antennas/circulators] +**Purpose**: Over-the-air 4G/5G (NSA/SA) tests Note: obelix and porcepix are both used in the OTA testbench and the 5G NSA/Faraday Cage testbench! diff --git a/doc/testbenches_doc_resources/4g-faraday-bench.pdf b/doc/testbenches_doc_resources/4g-faraday-bench.pdf index 7e31789e9acb9a3cc05719d98304966708925ff9..f6f7b078e67c61044004c70a92c729b14079cafc 100644 GIT binary patch delta 8561 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 delta 8689 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

U^jvkQkX}oYqF9J@~lgByn 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 literal 92391 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

h0&06N?X9REx=xt1C&ZPLaVB>*KpD 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 diff --git a/doc/testbenches_doc_resources/5g-nsa-faraday-bench.pdf b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.pdf index f6d960c1a257651b538b404f8f019438d3014f15..1b921e64370954673e45ed70ff1643462f4774ed 100644 GIT binary patch delta 1414 zcmV;11$p}E%oOF!6p$tYHz1eLtpg{KPYnXF!I54he~5nMzTLNY0IkHGP~vK(j+~K? zN}wRJpp_R9!6*_p`_(tWpevD)D+M|REB+Db@+Keo^HC7Q5Q6T{pM?S?Zjb#{8Ujm- zNVHL~po}u64W4&m^;Zpte5WeEhvS>Q7*gHTPsgz)C<6o}VFD<0DZf`guzv!f0~4)~ zs3RB*f9WZg+ts`G&as9kTKHgrhwYvCkEy;(Ao9nyX z`t$a~>ep@4V)O(KvuQNCJY-8`He0k292sF8kPdIk_uGm)0hP{=IvA#&=mV4s?|$2( z_~mi6Nk1)ojV@dG1(q5VSrILerPEaL1QfU+e;6D%Yvx5Mpo+;x^)Q z`}D-FaZJsmM6CrEXrXHgs)D+%@soBLUBQO!Qpn1l?TfxCLz-!LF5_&`7k$%sHa+dR z9ZsyhM+iEZgNERie6zz8NUr#`Q(dlskN zA2dyq-0FyD7R>7`vptjD0vUflpTlI0Xu-!GE9XsC&bzEUYO{v76ub;euR&YGwu+JO zwG^|_25)h}XdQy)sUscZ6`g9en$10?Z7kR&pY0$S(M@(ArY?H`8unMA*;vlb9O64; z@I2sdq@QlFHGGS{z>*1YGL#JY#FFzSF%=v+qM`+d?JyORi~jWZe6xRhnr=;p&|&E- zUD^1SZccikVOKW%US+k7-3(1u$lo|Yp22L|v2<<2%Y_@{=#F9Gc;)g5gdUW7vx}?X znS2(v4YRmuyPdx1s15`+GXl#(p)r^f*rz$nb>pm}K22V&2#ia)qJWJFyUMI~w?JVDeuD0{T?6}0=-vk>iy!gD6NjH||TE=c6b zGZQ9)h(!5mf2*Ufx#-YN8_&KN&@L~}p%~GcgJ)v+KKz=BF=Nm z@yp|ClYUzG8eO*V3oNw)vLaeVmQGW}lcK-{f5G6Cvu0kD0;-s-$>W#Z*ZY6R#UCMu zwXb|-BRroMGG}LnH7Z7WYxOAvUWvK-?Xaspvg#p!4@Q}AAOp?GP-w`;W07u*yz)}t z#nWU!G)kl91J7mWs?X|BQ5BShxFi6%zkj$NYcWQT#3-y~qupo6bhNU;SuLDb=)ili ze@~~06vR}M{`A)alQ}GkCWY)-ycVOkZCn1bfiMC9M5q@9j2UhIw6qQ_airYvf|6$iff5@m0M?o zGu)>qc8z0dCM9aEa)B1Qrl2aQ>l#04UzZVV*e->v?AgBPn=+)8hUYTQ7Jbn-jc3!- zp4;KX+Iv(%Cv(s$xFz50Fa?t9{;+%6eV@4I05>(wM7D8#(KDrwN>ezyX*L=!dZsj9 z1;QURO_SW}h-Vhe>nyX~liLCrf8U?OWQ}OS#~v%^O;*mktUPM7Rv}=ju;&#)jt2<> zp5|iAPRlW)TX0&3$_L&>?h13N)v_ksSUkpZ@UY~x9jIW6(T1th4q(GB>$ozrT50etl0L^qdSt7%wn5!rPZQOvyxe> zFi1+iPOJ22Ps87tvTD(1vg*W&!xofB)M8iUtIW9`T(ZW0`N@@LP44uMH=casiO(&~ z12FRXWMhl$GYe0yimIS&Z1=ajPXIJ|c8$R!Un`_#W8J5QhLq!WqfDAPr#Y8w2>E+2 z6@MP`_SnBY{|Ddy4by|Z1c$x^0f)W>0*Af?1Bbo@1h>8f1uq&bH83_YGBGqVF)J`K zConK4DGD!5Z)8MabY&nYL^?7sGBPkVFg7tVF*GtUw;3M=A_h?~GDA5tLqtR|L^d=q zLoq@)IXFW#MK>}vG&nRfH%3A}AUrTKLpd`;L_{$}HZ(9pF+w;wI72l>H!?LeI5aai zMnXPa3NK7$ZfA68ATcvJmy9I^D}TEU!axv&;Ti9pdE006j3A)_%0QwWN` zPAGr`%0L3oCZG1#XaV4t0Yws(sEP0dQE#B^(2i%&Zfnm{G%HHaiD)w}?w(UYB2S)~ zFcCx~(x>^Y_P*w#MLVoKyP`)sy*&G3K)dcd3x@B*udx_1hOOsF%oyhvFbFQ+_ydl+ T5oMP=CIuk~GYTaoMNdWw2!WYd diff --git a/doc/testbenches_doc_resources/5g-nsa-faraday-bench.png b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.png index c677b598e9894a1bbf0e1e7321497e4c51e6fb17..006e6ab347d2dcd3283f5cdb59c65d1d1ba1ea8e 100644 GIT binary patch delta 49697 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 O+B%g@F&i!Ml>Y&OOLdk2 diff --git a/doc/testbenches_doc_resources/5g-nsa-faraday-bench.tex b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.tex index 66b52f7f69..a9f12fe3df 100644 --- a/doc/testbenches_doc_resources/5g-nsa-faraday-bench.tex +++ b/doc/testbenches_doc_resources/5g-nsa-faraday-bench.tex @@ -30,7 +30,7 @@ \draw (obelix) -- (b210o); \node[above right=0.35cm of faraday.south west] (antn) {\includegraphics[width=0.3cm]{antenna}}; - \draw (b210n) -| node [pos=0.2, duplexer] {B78} (antn); + \draw (b210n) -| node [pos=0.2, duplexer] {n78} (antn); \node[left=5cm of faraday, label=above:porcepix] (porcepix) {\includegraphics[width=1.2cm]{server}}; diff --git a/doc/testbenches_doc_resources/5g-ota-bench.pdf b/doc/testbenches_doc_resources/5g-ota-bench.pdf index e4d4c15e394ad4664d6eea6580db9952d8d7e341..121969030e64e03ac0e4fedc9ba4fc1c692de71c 100644 GIT binary patch delta 9332 zcmai(LsaJvpv7x`*>;o7U#`hEC)>99&6-@3Z8zDI-DG33t;zNN=e*6^y~SPJbME#o zKKIt9qs*kCBv69bxw+H8rXX5iNL$X4NCNHmRo$_v-?5^mx=iT-}KR$_rp}%NU}afT~}^SPR+^7>4W-1wK_ms#q8;^m*dnFjipPGokAhjSC!Sd zNduiBw+MfEZLVnWUNnACb-B_ryv`|MYX6N{!#fN;;SCu4$)|GKm1b7ljTG?XbtbkV^&hc2_9+~%sSgV zbL6SCa%n2A1vI-yNuA#f-fvI$-Ut4C?B#tLy!pIuUY?y3|U#-$@er?}D!}y+z&?k;EGCWD` zs87=9vo`gYBU0fJ_RDU-RH&5y zSdSO|r_zNJ{KG3Y(mjkHUlPd_)8V`RaRUQ7g>1N~8Mi)v44ykP$zQs9FJ4DTtI&MOEqJ*MvdFJZC00$O-#P()?lNQnx zp=sSPddSG<^!HG^iluh<(n^S>$Y=q2p>*LJx5C?@AG^bYj+pA`1ZEu=zMZ1qVO@|5 z>78hrkTd%itdd-{Oo!E|d{vrH0NS)6vjat){2y^bjN9j489H%{tX4M?K- z4YY{s%CH$l)h&2*`V7e~CaQwQ4bhVnhOuQi_AB~sB$Vr*SHFqh=)tvkIw@2*oKg0; zE`XMcV9i3YGKJBpD51IMdUdmk4c2M&MHz{3pXST$tN9pH2`(ph{}Q(61mAFIc&sLE zt=BWs+0Qc>Uxi_8{~OQG@#0vx1Ei}5t>t4KosxG-2YR`gx` z#;IVnr=t`2eD;`*Pj_&hNIHQz?+DJ5PdSbqAlmu*Jtw;n3ay*fI^XYRrt)56MKke~C zM4%%?pdtU$msSyIke)e+lb1Cu-v)&Jg`Fdf)f7YrxT|^cXRmiqi^nrZaz*0As1!XO zcRvc^4acyBs1$n6%E1+;MSg`ZOgn~k#Op;rAyQc9=ad`3P=FL3B;feN?{VPOVHgX z>I(W7*QX*X*y3+_WJtR~P*wCFj@L}$*W8Ctk`SRHUr50T5D@2(5U*?B?%oxx16^Q& zPm$ZtaC>8vppQ!@&%h$41wT6Ho{=rUbQrBC27(~~X!v0ppc69&?6X&h0Fpg;-VEFRxuZ4XG2OIgW{d6(-LI0QV z{KWlC6yk^^{NT%5XA%w(WIZg1=aVZ6S{l#oEPkEj6X2Zgx%pfa{hTZa4Hf-7&byl) zhHTC8h2((f@r_vX`H*U>A%u#4VS)X?w?g`uKl+T1qwmK-s80*w75U_(js(&$264~x zK_V;PKCNSfoW;@yNLWy+L65<20gVs_0mdJI6U-EvuO{Bg#MzQRplp;rAfzf7v^qdc z%1RR`xVr?jv*oUj0D(w;S&;U#UpU?mZ&W^QJK3`0!9nN)v8 zFy7RkmKK2~=VLsEAC=e5t!3?lmxkd1%Njv~i`XL>L{^$m?V*z97(k_a7je(FGCPG| zCm^Y^DCxk?xyb-1@mR5`Wilw5hHXX%dV*N11l zMKa_>nG0s&667WXnM!2+1P&O6=Qqa2aiE+{+FJ*{s-sQaJQ7BZqA4C0XCg4<2TLb$oG67v6@7H?qjmu~Wh*C@TfY6w-Y zT-_dj&;9o@&9Bv2iGdzsi`B~PjFYdPV%cOg?`U8vY;wqV0C;C`?BS{WQSRK~r~FL) z7!t{%m6Cq97UzaMU&#I-YbeWpf8|D;)=WAC;rblxoTF?os!`m_dEKhU9BU|tewE=$ zNgP-qJJbd*`TdT*om#Njc&@{HFF7724QZ&5pb>To@Z-QyA&bC~bXK5`omo<7cJoYt zYntPUWde7k0j!Mail^&E>1~1;9d`5&n2xtPB81I(0S6w_B~9VYzhZb!Rcq7M6Ok<) z=2R~Ee~5R#kg={dNGX6J7Ro!6w!nKNk;mn% zQd}KXQBy1SN@Qq$kIG%l?Ck%@Q4SG!y`)PzR^D}A)B6a z7Bq-hSt`M<41TYYwgnn(*kQzMJB7P+0gl}n`0pQtt@CB#|wR&G$Kmj5_Yf3c0Vd-SaKJPfx2GYkqqH|5m7T>dT4%8YP?hG z9;)FOPN!Xic_^5H_jIA|Kbz`a;wdLIS0fGoW2-;AdMA0CQt8(qy4j~yb$i1nrnJXN z^%%Ozf1Ok5=Fim4T?FfGO>(XSGsB1Y*0u` zQimp!AyOoE9>*+{9WvFGZ840822I7ZUAuYO3DqV`%~6cHn=%=biaSHwPg*DKXXvaz zXfn5l*0)dD$XG$Hnp^g%R~tRZ562R!fHTBuM??T=O+l{b- zd()jTccYn`9KQ1 zFlH4{?+on5vr1w}uLRgu&mdy*?@h5!yJBn(*%#@m#mA_!Y#OCDue=;ROhZ? z2nf!*;GIu1M_XbQF=>0*r?8T|hUQ4Wf|(EOWQ%O6ndq{8E`7W-1KHH50xzD}-=ieB z#r5C2(oOKjnH#Ji8=m%+8OuwxSB_=eqMf&>(e9u40Bj*Dm7d#*)mgm|rf+Kf zMTR^B=P*tk3DjXiU zA0Ye5z0La*nssohYr4j$od&;7piNQEW|ymjPt%6O0Nuf+w@%?%dSaMLBMFPbprH0jF%c~e4i zmT6W2euM^EtIRh;zH>ma6S)j7G&~jHwdUyasHxR4MdtW&>4jHMgz5%TBEN{TvJP-e zNsUHi6*iGa*FOG9pl0EJ1KtDE^qu~aj~5x{vW0`|7AmWVH_KBcA49wpsz%2Xa=sA* zcCTCxuUvU+7(|})7zr}k{qs-bNwAuLs8XGO=5bzM8Ip(Pxd5el9&SaWaTg)e!?Wm( zZx@xmUh8!2mnl!^v*b`)LhKWFkIAM~#D6YwRll4fzv12+&0#AV->2q2q+`0D3i-!) zuTV_A#Sfp&8zd=g)cu`nnoDITylS(`ZS;N`b+F;CGFh34W2f~ho;fYlZINsB9zCvg zem+>2Ku|`*76l=N>M~KJxibHih zJr9?>sHhO!-WrJCI+~#L6gaF#egrmh>ir&f6u3aLOEZxLhQaLRjNEL7YVfKtCBzR` zLZ%b4ey12-Pdv$5e{Z$iSx(BvXZ6A9(pxP$JTrXqmhA`0oLaVLVu!UHc^6--mwu$%5yOIrRhA&R z=5`!*{qhWIVpFnv6L7g|th^~7=4ETAx%D|BI9aq-yr(K~*;??szU{Yf#W+i!uAAX` zx0Vlr@dMzsOgoqIrI=FVLlu+_6R;N3BjYJIYsW*bo+vgv>MUTOq#W72;Xl|ET>1D z<`3WAM`z>gC`gqs{fYVB3>sO_Ve>8NTqe{js3o)DZU+Ifg9ZzUsw`dsy0{FQ$M6-& zS|E!~FWEom(HLW4-McQ!M%uzJ1^kOc6SwXbCEETX{PprD#1SX;+`vIdKx0>U4%KRc z&&HU%W?8OyeDY-5B;;60bnWJBvSLyM{lWR|3=)5~julFkg6JFw6F1Z-H%YQ{w}sv- znx`t++Hy;_Jw9|=nJmDd5&>=RR9n0)f$tJSR^}yHSyZ36-1xw%z#?H7^&_*l z0aSY`{xYZZF-U1QZi+9m5haWo3*0A9o>G;nM0MU*rnw2_yQA==Xt6xa&YI#jHO?M2 zyqd?(zsI#5BzaNjSDEU07;x0mD0}P-MR*MFCOtaot-(MNH`duBTugdq36d?Iw5*S1 z?Dt%bDx_#bvAT`<%pr+0src9Weu8C2)1Nk8tC?o1?+O|^o75bzXiS&N08NA6HI)S% z&SP}eFrg?EI8o^6|6PkTf6F*AbFiWJp*Ts#YzGnpNP-_+XW zx7?@@i850pm0yjOn`D3^K2M+)MpLrA2;fHq|!2m0aaCp-R-ySdvN zYzvjTDG8&z$djet0|yw?q#szVCkmW+mFSj81$zvAe`fXO{Z0V(R-56-TlKpJeqCAo z>m%X%{H~mTzEK$tXe>>Jvd{C>8Z|#qBfEs`zbSKhLKQ)AvYL*s zR!j)O2{AG;TYAL!E)rx4mh6Fc>a2hcQI*S+-jC~8-uSxI*{sm~am)Xnzfg5scBa98 zsqEt?wBA5V*nY?n-gm%YS?{(b`1pf}WN_SU4ayF52&jCDDyDfw#{tqkY*n4@&~kxsz!%-Dum zkZ5`sH?V#w+UV%pBKNLrd0s${-?#MGwmTR>zW3^KfW!Hl&ia)|as|=hA9uYsa$xF$ z4T6J>+FW1to0&YUWR+*KI4|#X4}s!hgGnezGfK+oy=G}?9233f*z$vVwgUdy%YX?L zr)jrUo1kY^XSu@KKVL9DCWyW;#w9zT=^aAn1HjuO=ss88N~%&S^6jAN#?dTinS~ec zNBWhG!O17Bk)=ocy_q^`ZNV13;gVi>&UlUlZ8ZnMW!C;rnd&?N0_*TD?JHB@8XPhP#liHlX(@c zfH0dJXaoI>q4O`g!9`M3oOpsz%xOns9Mub>2d<}?HnM)}zMO2ra&iH?=vqm4IbaQY z!Mh6wo*$3JUxJ!kzBG}q3&F*a&9Avu1c*FWX3o>Bu)w)9RHb&tsGTZcoI~u|8J%4#=w3 z5jBn0{oGB`*Aft{R-*qS;n}b>xsio>I&SOs=C`_zeTeE^G}62|oOFz!oQ0x( zqJ^tw)VNEz--0mR`d@K3mV6%(gn{_%M;Dbc9z^BW+*j|`xylELb?nPGs|8~%1c`9C zTUtUNW5)}5ooAiQ(BTfu(W5ULJ|k(Ze*~gY>Rk31KZR{-TD5Wg=AXnV)cDGcRf^!s zl7_LwE2}$j!TA}97qTXX&!aQdA^aDxahNp*K0>-dHvWi$34fQr3)N=54**l~AJTjK zoVcma=szSd?M!yP7%SXiN!EmZSX8{oq6&~e~;Pu)$hW9$AwN;Xj8pv;0x0OrMKk>}x4Yww^9@jb%@5NucsW0!O=(8vDPC^ZQ%#k9YE zOw79HctOHfZRO-5$a2~>4at4rn^P@jn;~~`jJZmF3J3mH(c_r6!zU5e{#N_u~uHGb4Nf_0~6<#@e41%DLqa8 zSyawr;1gDrAxQl^ea$@5NJ$q<(hKuR@fLSU?U~-aH9GE4^2#=#hhXPaBgy07po|M{{OVGYiF^MBS4f8NA0St@HE+5S6R@po`w#`*3HSx5(im%Q~$ z*Bj5FZ?-Jmj7KI%I*=pV6Sr|^FFaIPJvy@*XJ~n8erCl>4kx)Er+^ri3S@_;99ap`Sm3u|1KC7ihVBtD8GC{B0Rmy|oS{ z6$SUQ9h5>D9cLENMB#VzFZbw<^IIJk>o9oy@ji_eyFg(z7+~!j3O8_2(O{Ntjq!-* zViU?Ci>lN;SStcHC1RjnI9g##+z~jXwum0dSvluxzX`pbKi70ky5cGQTAHM5=2-K1)xCjq*mn6d zD*d~1ln3ggGvGGa8ktkhSf!DfL$e}R*l%qqOHXp6>8%=G%Q=)!JJ&l!d7L9>hUE#) z-n5Iqq-I@2d7IU$xugCLHJxRYdZcNudMTfDCx2>1qF*HEs~dnDU|vWd_4y0aW9Vm# zM2BbcF}Hku{S!Zu%=YWfRE&PvOFM!nemq7<4ZJj$4WKxMpQgbxWR41i9pfU6PZj~3 zw092@W*vwIYz2w|%Omv5BgT)%RqyS$S8_?^9AsaQTG32g>3I0ilvj++t8F&KtDmmE z1+t)Ox@NHXan(Y~E+|8}9|_>rt>7xFb(zBgMw@?ZB~w?enP*$71Vl;7QA?`LCA z@C$h-4ZsJRy<#zEJL=<|S7KX298EU*#C_B`mfK`lwyomJE2$cO1$qyZ5m3i_XM%Hbx38iDPdwTDgNMo!o2##qWx-9 z9tk(3iMN7d)dugX#006##xUkj(B3(hKZ3b~S+WE)YFb1nNDiKhjRVZe&dI@*wjK&1 z_&@d|6f_3O^}o;cAB|1NbuKjE(a_n^c4p`e;{gl>nbbBGT%w%{Wgp0a+91EaW+#)d z&$wyWv!#->*QC|?#h;cmx@*t>E{?xMIw@MZBJjH?b&RxJgHE!B*+BZQ=wdQ^I<7#` zXpqFX5dxerxfEY1RG=a$Wz?vVE^K%Vj5bDckdZAC-IyyNy%Lu%dS?dzG%C&Zixgom zQ6^vT3m>IDxpb(WZ67>OQuG&ANfA~)9=xda_@5NcKbbeAvr{C_qFaJ&o?HbmmTT#_ z-46+t&cKeFj7sqnG#!@WM!WT4V&iM|$RQEvP>Tt@nf%Y%`VRCSDFp*!bvKpFmRXaF z_m!D{95*+C-vqEO)dydZ%JtV$S0H^L?i$jIYl<|J4VxBpbnxk|K{;KiFEn((m(6vT zf1F9{d^Pmk6waBo1Z_U?$Wl7^c7m1atlT$lnmJLM+yj01qoA0UmoI{5KrjaXz*(Ch@>7CDd}~N2CA7 zY56wbr-T!X+52V$3ZPM*{-e&T43v0#>%e&wSEr|vrwpy3_3iu8O*E+rD|*5HbBdLq zjJ6Se*JaBQ3TH+8ZfD(7bH0fmVM-)_DjMm}vgrS8Am$bo{)yM{UUTa*QLUZt%J*eX zgFU1N&a^=@`C17IPoURBcx@g~s`ne}=)6K=J_gs0af zxR?I3GqH`XZHjAwMwRJ*@0C*4H4AA~N0><@B|g8IB!CzlFK^l+ z%$DKvVkX7{{mp=Ql8_d6PSq|D+4Xs;d20$FB~0)ao{vYE?>LeKcUZKr?bZLKY@(y) zj`MGZV(+s~GI45np)tNPKO+;BE*($m`Ec{Ku%3dV^X_GZIRU>4&HaqT^|KUZI&Ii#TERMJ1c1xUzP&M-B^2*#u-yMX3%pl(&;xxr>1o6OttO^uNxIj_L*J*hG zjC9@9>-#&`VPd(i9U9M!J%BY>3XM9)IDeA>fw&XKaoG+uZ=7ej^jQ%?gw-Q-ZA|RW zkNT|!lH}hYr*@7eZRzDT%RHy$>E`Q1h{= zdIT%Okx|ts7|MDW8Se$N4F>UO2GSZJ!2Q`|HKaP>@n16=?HQN;!KzBV7H<-5?o!Q` zid~|UK>T7ppLQwd(H{n9YUV**XSxrxf4Gaef}XkHX7^b(&}r}<1-TOH_!51H#m$|y7D}Ugsj={x>jV*B#Il|sn+b<)@hor*~QYaF5pwI z@D@zU&o2vHsF%qi(3oi@(I6dVHc2iHQC=EeIXKdSmLTZ>;t2tQK4rA99alDtPxAH;oc!6U`_uy2vQ`k5 zhY1MbCnxQ%;A19;NBKL!yUlMPh#siXh(a`~#J|F!*eUk6-jL6K17+G?beVT$#nt5G zts+W}z9)?S&W&Q7MWa*M*t7S(-;(DT8<}dP=-5BoTgCKm5cEZ{THGkBhikG&z2L=Q gUkiX-vyK%)*}yzagN^}_Ah5D>B2ZCDC`lsx4}3}~4FCWD delta 9435 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%0Df-%sBKKHZvL8?Bum$h#?LEP24qI0hr%B-N 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⁣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 literal 90027 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%0D%sqj=-Kn=?=3kz@z+nwCt^ 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

vh4ehB$&?ymC@{5J~(+oo1-;TWB{07$j*UR>Bk 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 Date: Tue, 5 Jul 2022 17:17:40 +0100 Subject: [PATCH 43/60] To use some casts to c16_t --- openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c | 4 ++-- .../PHY/NR_ESTIMATION/nr_ul_channel_estimation.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index 1793a76fe1..935798334f 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -75,8 +75,8 @@ int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms, for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) { int temp = 0; for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { - int Re = ((int16_t*)srs_estimated_channel_time[aa])[(i<<1)]; - int Im = ((int16_t*)srs_estimated_channel_time[aa])[1+(i<<1)]; + int Re = ((c16_t*)srs_estimated_channel_time[aa])[i].r; + int Im = ((c16_t*)srs_estimated_channel_time[aa])[i].i; temp += (Re*Re/2) + (Im*Im/2); } if (temp > max_val) { diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 080b9b65d5..00b053e3ff 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -999,11 +999,11 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB, for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) { - int16_t generated_real = srs_generated_signal[nr_srs_info->sc_list[sc_idx]] & 0xFFFF; - int16_t generated_imag = (srs_generated_signal[nr_srs_info->sc_list[sc_idx]] >> 16) & 0xFFFF; + int16_t generated_real = ((c16_t*)srs_generated_signal)[nr_srs_info->sc_list[sc_idx]].r; + int16_t generated_imag = ((c16_t*)srs_generated_signal)[nr_srs_info->sc_list[sc_idx]].i; - int16_t received_real = srs_received_signal[ant][nr_srs_info->sc_list[sc_idx]] & 0xFFFF; - int16_t received_imag = (srs_received_signal[ant][nr_srs_info->sc_list[sc_idx]] >> 16) & 0xFFFF; + int16_t received_real = ((c16_t*)srs_received_signal[ant])[nr_srs_info->sc_list[sc_idx]].r; + int16_t received_imag = ((c16_t*)srs_received_signal[ant])[nr_srs_info->sc_list[sc_idx]].i; // We know that nr_srs_info->srs_generated_signal_bits bits are enough to represent the generated_real and generated_imag. // So we only need a nr_srs_info->srs_generated_signal_bits shift to ensure that the result fits into 16 bits. @@ -1074,10 +1074,10 @@ int nr_srs_channel_estimation(const PHY_VARS_gNB *gNB, // Compute noise for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) { - ch_real[ant*nr_srs_info->sc_list_length + sc_idx] = (int16_t)(srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]] & 0xFFFF); - ch_imag[ant*nr_srs_info->sc_list_length + sc_idx] = (int16_t)((srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]] >> 16) & 0xFFFF); - noise_real[ant*nr_srs_info->sc_list_length + sc_idx] = abs((int16_t)(srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]] & 0xFFFF) - ch_real[ant*nr_srs_info->sc_list_length + sc_idx]); - noise_imag[ant*nr_srs_info->sc_list_length + sc_idx] = abs((int16_t)((srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]] >> 16) & 0xFFFF) - ch_imag[ant*nr_srs_info->sc_list_length + sc_idx]); + ch_real[ant*nr_srs_info->sc_list_length + sc_idx] = ((c16_t*)srs_estimated_channel_freq[ant])[nr_srs_info->sc_list[sc_idx]].r; + ch_imag[ant*nr_srs_info->sc_list_length + sc_idx] = ((c16_t*)srs_estimated_channel_freq[ant])[nr_srs_info->sc_list[sc_idx]].i; + noise_real[ant*nr_srs_info->sc_list_length + sc_idx] = abs(((c16_t*)srs_ls_estimated_channel[ant])[nr_srs_info->sc_list[sc_idx]].r - ch_real[ant*nr_srs_info->sc_list_length + sc_idx]); + noise_imag[ant*nr_srs_info->sc_list_length + sc_idx] = abs(((c16_t*)srs_ls_estimated_channel[ant])[nr_srs_info->sc_list[sc_idx]].i - ch_imag[ant*nr_srs_info->sc_list_length + sc_idx]); } // Convert to time domain From d68f7d6270df9806cc833fc98d45b5db693433ce Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Tue, 5 Jul 2022 17:50:58 +0100 Subject: [PATCH 44/60] Add help string --- openair2/GNB_APP/MACRLC_nr_paramdef.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/GNB_APP/MACRLC_nr_paramdef.h b/openair2/GNB_APP/MACRLC_nr_paramdef.h index 22b83f4064..4359cb0c86 100644 --- a/openair2/GNB_APP/MACRLC_nr_paramdef.h +++ b/openair2/GNB_APP/MACRLC_nr_paramdef.h @@ -97,7 +97,7 @@ {CONFIG_STRING_MACRLC_ULSCH_MAX_FRAME_INACTIVITY, NULL, 0, uptr:NULL, defintval:10, TYPE_UINT, 0}, \ {CONFIG_STRING_MACRLC_PUSCHTARGETSNRX10, NULL, 0, iptr:NULL, defintval:200, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_PUCCHTARGETSNRX10, NULL, 0, iptr:NULL, defintval:150, TYPE_INT, 0}, \ -{CONFIG_STRING_MACRLC_UL_PRBBLACK_SNR_THRESHOLD, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \ +{CONFIG_STRING_MACRLC_UL_PRBBLACK_SNR_THRESHOLD, "SNR threshold to decide whether a PRB will be blacklisted or not", 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_PUCCHFAILURETHRES, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_PUSCHFAILURETHRES, NULL, 0, iptr:NULL, defintval:10, TYPE_INT, 0}, \ {CONFIG_STRING_MACRLC_DL_BLER_TARGET_UPPER, "Upper threshold of BLER to decrease DL MCS", 0, dblptr:NULL, defdblval:0.15, TYPE_DOUBLE, 0}, \ From 24745eafca450f4f7fde10b2bf8986ab883a4a89 Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Wed, 6 Jul 2022 08:45:48 +0100 Subject: [PATCH 45/60] Rename variable from phy_procedures_errors to pusch_DTX --- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 1428987d40..8e1f2bbd4c 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -625,7 +625,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { /* those variables to log T_GNB_PHY_PUCCH_PUSCH_IQ only when we try to decode */ int pucch_decode_done = 0; int pusch_decode_done = 0; - int phy_procedures_errors = 0; + int pusch_DTX = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,1); LOG_D(PHY,"phy_procedures_gNB_uespec_RX frame %d, slot %d\n",frame_rx,slot_rx); @@ -765,7 +765,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { if (no_sig) { LOG_D(PHY, "PUSCH not detected in frame %d, slot %d\n", frame_rx, slot_rx); nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, harq_pid, 1,1); - phy_procedures_errors++; + pusch_DTX++; continue; } gNB->pusch_vars[ULSCH_id]->ulsch_power_tot=0; @@ -790,7 +790,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { /* in case of phy_test mode, we still want to decode to measure execution time. Therefore, we don't yet call nr_fill_indication, it will be called later */ nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 1,1); - phy_procedures_errors++; + pusch_DTX++; continue; } } else { @@ -858,5 +858,5 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) { } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_UESPEC_RX,0); - return phy_procedures_errors; + return pusch_DTX; } From 79586c03f401d9d874678856e16f9dfb640eacfc Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 5 Jul 2022 14:16:06 +0200 Subject: [PATCH 46/60] fix for pointa and ssboffset --- openair1/PHY/NR_TRANSPORT/nr_pbch.c | 6 +- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 7 +- openair1/SIMULATION/NR_PHY/pbchsim.c | 6 +- openair2/LAYER2/NR_MAC_gNB/config.c | 24 +++---- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 68 ++++--------------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 + openair2/RRC/NR/MESSAGES/asn1_msg.c | 14 ++-- 8 files changed, 44 insertions(+), 84 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_TRANSPORT/nr_pbch.c index fc7df46496..278c2dfd58 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pbch.c @@ -35,6 +35,7 @@ #include "PHY/NR_TRANSPORT/nr_transport_proto.h" #include "PHY/LTE_REFSIG/lte_refsig.h" #include "PHY/sse_intrin.h" +#include "executables/softmodem-common.h" //#define DEBUG_PBCH //#define DEBUG_PBCH_ENCODING @@ -248,6 +249,9 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu, for (int i=0; ipbch_a |= ((pbch_pdu[i>>3]>>(7-(i&7)))&1)<sa ? config->ssb_table.ssb_subcarrier_offset.value : 31; + #ifdef DEBUG_PBCH_ENCODING for (int i=0; i<3; i++) printf("pbch_pdu[%d]: 0x%02x\n", i, pbch_pdu[i]); @@ -265,7 +269,7 @@ int nr_generate_pbch(nfapi_nr_dl_tti_ssb_pdu *ssb_pdu, for (int i=0; i<3; i++) pbch->pbch_a |= ((ssb_index>>(5-i))&1)<<(29+i); // resp. 6th, 5th and 4th bits of ssb_index else - pbch->pbch_a |= ((config->ssb_table.ssb_subcarrier_offset.value>>4)&1)<<29; //MSB of k_SSB (bit index 4) + pbch->pbch_a |= ((ssb_sc_offset>>4)&1)<<29; //MSB of k_SSB (bit index 4) LOG_D(PHY,"After extra byte: pbch_a = 0x%08x\n",pbch->pbch_a); diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 1428987d40..4d511a2e95 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -72,8 +72,11 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame,int slot,nfapi_nr_ ssb_start_symbol = ssb_start_symbol_abs % fp->symbols_per_slot; // start symbol wrt slot // setting the first subcarrier - fp->ssb_start_subcarrier = (12 * cfg->ssb_table.ssb_offset_point_a.value + ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset); - LOG_D(PHY, "SSB first subcarrier %d (%d,%d)\n", fp->ssb_start_subcarrier,cfg->ssb_table.ssb_offset_point_a.value,ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset); + const int scs = cfg->ssb_config.scs_common.value; + const int prb_offset = (fp->freq_range == nr_FR1) ? ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA>>scs : ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA>>(scs-2); + const int sc_offset = (fp->freq_range == nr_FR1) ? ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset>>scs : ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset; + fp->ssb_start_subcarrier = (12 * prb_offset + sc_offset); + LOG_D(PHY, "SSB first subcarrier %d (%d,%d)\n", fp->ssb_start_subcarrier, prb_offset, sc_offset); LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n",frame,slot, ssb_start_symbol); nr_generate_pss(&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp); diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 07c5f118dc..b43cb6b00d 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -67,7 +67,10 @@ openair0_config_t openair0_cfg[MAX_CARDS]; uint8_t const nr_rv_round_map[4] = {0, 2, 3, 1}; uint64_t get_softmodem_optmask(void) {return 0;} -softmodem_params_t *get_softmodem_params(void) {return 0;} +static softmodem_params_t softmodem_params; +softmodem_params_t *get_softmodem_params(void) { + return &softmodem_params; +} void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {} @@ -174,6 +177,7 @@ int main(int argc, char **argv) int ssb_subcarrier_offset = 0; channel_desc_t *gNB2UE; + get_softmodem_params()->sa = 0; //uint8_t extended_prefix_flag=0; //int8_t interf1=-21,interf2=-21; diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 218b75b2e8..4daddbf03a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -335,22 +335,13 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, int pusch_AntennaPorts, cfg->num_tlv++; // SSB Table Configuration - int scs_scaling = 1<<(cfg->ssb_config.scs_common.value); - if (scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000) - scs_scaling = scs_scaling*3; - if (scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666) - scs_scaling = scs_scaling>>2; uint32_t absolute_diff = (*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); - - RC.nrmac[Mod_idP]->ssb_SubcarrierOffset = absolute_diff%(12*scs_scaling); - int sco = 31; // no SIB1 - if(get_softmodem_params()->sa) { - sco = RC.nrmac[Mod_idP]->ssb_SubcarrierOffset; - if(frequency_range == FR1) - sco <<= cfg->ssb_config.scs_common.value; // 38.211 section 7.4.3.1 in FR1 it is expresses in terms of 15kHz SCS - } - - cfg->ssb_table.ssb_offset_point_a.value = absolute_diff/(12*scs_scaling) - 10; //absoluteFrequencySSB is the central frequency of SSB which is made by 20RBs in total + const int scaling_5khz = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000 ? 3 : 1; + int sco = (absolute_diff*scaling_5khz) % 24; + if(frequency_range == FR2) + sco >>= 1; // this assumes 120kHz SCS for SSB and subCarrierSpacingCommon (only option supported by OAI for + const int scs_scaling = frequency_range == FR2 ? 1 << (*scc->ssbSubcarrierSpacing - 2) : 1 << *scc->ssbSubcarrierSpacing; + cfg->ssb_table.ssb_offset_point_a.value = absolute_diff/(12*scaling_5khz) - 10*scs_scaling; //absoluteFrequencySSB is the central frequency of SSB which is made by 20RBs in total cfg->ssb_table.ssb_offset_point_a.tl.tag = NFAPI_NR_CONFIG_SSB_OFFSET_POINT_A_TAG; cfg->num_tlv++; cfg->ssb_table.ssb_period.value = *scc->ssb_periodicityServingCell; @@ -360,6 +351,9 @@ void config_common(int Mod_idP, int pdsch_AntennaPorts, int pusch_AntennaPorts, cfg->ssb_table.ssb_subcarrier_offset.tl.tag = NFAPI_NR_CONFIG_SSB_SUBCARRIER_OFFSET_TAG; cfg->num_tlv++; + RC.nrmac[Mod_idP]->ssb_SubcarrierOffset = cfg->ssb_table.ssb_subcarrier_offset.value; + RC.nrmac[Mod_idP]->ssb_OffsetPointA = cfg->ssb_table.ssb_offset_point_a.value; + switch (scc->ssb_PositionsInBurst->present) { case 1 : cfg->ssb_table.ssb_mask_list[0].ssb_mask.value = scc->ssb_PositionsInBurst->choice.shortBitmap.buf[0]<<24; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index e2ceadb889..828cb2b880 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -54,52 +54,6 @@ extern RAN_CONTEXT_t RC; - -uint16_t get_ssboffset_pointa(NR_ServingCellConfigCommon_t *scc,const long band) { - - int ratio; - switch (*scc->ssbSubcarrierSpacing) { - case NR_SubcarrierSpacing_kHz15: - AssertFatal(band <= 95, - "Band %ld is not possible for SSB with 15 kHz SCS\n", - band); - // no band available above 3GHz using 15kHz - ratio = 3; // NRARFCN step is 5 kHz - break; - case NR_SubcarrierSpacing_kHz30: - AssertFatal(band <= 96, - "Band %ld is not possible for SSB with 30 kHz SCS\n", - band); - if (band == 46 || band == 48 || band == 77 || - band == 78 || band == 79 || band == 96) // above 3GHz - ratio = 2; // NRARFCN step is 15 kHz - else - ratio = 6; // NRARFCN step is 5 kHz - break; - case NR_SubcarrierSpacing_kHz120: - AssertFatal(band >= 257, - "Band %ld is not possible for SSB with 120 kHz SCS\n", - band); - ratio = 2; // NRARFCN step is 15 kHz - break; - case NR_SubcarrierSpacing_kHz240: - AssertFatal(band >= 257, - "Band %ld is not possible for SSB with 240 kHz SCS\n", - band); - ratio = 4; // NRARFCN step is 15 kHz - break; - default: - AssertFatal(1 == 0, "SCS %ld not allowed for SSB \n", - *scc->ssbSubcarrierSpacing); - } - - const uint32_t ssb_offset0 = *scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA; - - return (ssb_offset0/(ratio*12) - 10); // absoluteFrequencySSB is the center of SSB - -} - - void schedule_ssb(frame_t frame, sub_frame_t slot, NR_ServingCellConfigCommon_t *scc, nfapi_nr_dl_tti_request_body_t *dl_req, @@ -190,7 +144,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) NR_SubcarrierSpacing_t scs = *scc->ssbSubcarrierSpacing; const long band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; - uint16_t offset_pointa = get_ssboffset_pointa(scc,band); + const uint16_t offset_pointa = gNB->ssb_OffsetPointA; uint8_t ssbSubcarrierOffset = gNB->ssb_SubcarrierOffset; const BIT_STRING_t *shortBitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap; @@ -207,8 +161,9 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb); // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters if ((ssb_start_symbol/14) == rel_slot){ + const int prb_offset = offset_pointa >> scs; schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1)); - fill_ssb_vrb_map(cc, offset_pointa, ssb_start_symbol, CC_id); + fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id); if (get_softmodem_params()->sa == 1) { get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb], frameP, @@ -221,7 +176,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) band, i_ssb, ssb_frame_periodicity, - offset_pointa); + prb_offset); gNB->type0_PDCCH_CSS_config[i_ssb].active = true; } } @@ -235,8 +190,9 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb); // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters if ((ssb_start_symbol/14) == rel_slot){ + const int prb_offset = offset_pointa >> scs; schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1)); - fill_ssb_vrb_map(cc, offset_pointa, ssb_start_symbol, CC_id); + fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id); if (get_softmodem_params()->sa == 1) { get_type0_PDCCH_CSS_config_parameters(&gNB->type0_PDCCH_CSS_config[i_ssb], frameP, @@ -249,7 +205,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) band, i_ssb, ssb_frame_periodicity, - offset_pointa); + prb_offset); gNB->type0_PDCCH_CSS_config[i_ssb].active = true; } } @@ -264,8 +220,9 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) ssb_start_symbol = get_ssb_start_symbol(band,scs,i_ssb); // if start symbol is in current slot, schedule current SSB, fill VRB map and call get_type0_PDCCH_CSS_config_parameters if ((ssb_start_symbol/14) == rel_slot){ + const int prb_offset = offset_pointa >> (scs-2); // reference 60kHz schedule_ssb(frameP, slotP, scc, dl_req, i_ssb, ssbSubcarrierOffset, offset_pointa, (*(uint32_t*)cc->MIB_pdu.payload) & ((1<<24)-1)); - fill_ssb_vrb_map(cc, offset_pointa, ssb_start_symbol, CC_id); + fill_ssb_vrb_map(cc, prb_offset, ssbSubcarrierOffset, ssb_start_symbol, CC_id); const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; const int n_slots_frame = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; // FR2 is only TDD, to be fixed for flexible TDD @@ -286,7 +243,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) band, i_ssb, ssb_frame_periodicity, - offset_pointa); + prb_offset); gNB->type0_PDCCH_CSS_config[i_ssb].active = true; } } @@ -306,7 +263,7 @@ void schedule_nr_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframe //---------------------------------------- } -void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, uint16_t symStart, int CC_id) { +void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, int ssb_subcarrier_offset, uint16_t symStart, int CC_id) { AssertFatal(*cc->ServingCellConfigCommon->ssbSubcarrierSpacing != NR_SubcarrierSpacing_kHz240, @@ -314,7 +271,8 @@ void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, uint16_t symStart uint16_t *vrb_map = cc[CC_id].vrb_map; - for (int rb = 0; rb < 20; rb++) + const int extra_prb = ssb_subcarrier_offset > 0; + for (int rb = 0; rb < 20+extra_prb; rb++) vrb_map[rbStart + rb] = SL_to_bitmap(symStart, 4); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 3fd394abdb..364f0255d2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -434,7 +434,7 @@ int binomial(int n, int k); bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot); -void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, uint16_t symStart, int CC_id); +void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, int ssb_subcarrier_offset, uint16_t symStart, int CC_id); /* \brief Function to indicate a received SDU on ULSCH. diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 40d16f8e8d..49c1f5caf2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -765,6 +765,7 @@ typedef struct gNB_MAC_INST_s { int pusch_failure_thres; /// Subcarrier Offset int ssb_SubcarrierOffset; + int ssb_OffsetPointA; /// SIB1 Time domain allocation int sib1_tda; int minRXTXTIMEpdsch; diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index ea4e038ca0..d08f816cdb 100755 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -226,17 +226,13 @@ uint8_t do_MIB_NR(gNB_RRC_INST *rrc,uint32_t frame) { AssertFatal(scc->ssbSubcarrierSpacing != NULL, "scc->ssbSubcarrierSpacing is null\n"); int band = *scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]; frequency_range_t frequency_range = band<100?FR1:FR2; - int scs_scaling = 1<<*scc->ssbSubcarrierSpacing; - if (scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000) - scs_scaling = scs_scaling*3; - if (scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA > 2016666) - scs_scaling = scs_scaling>>2; - uint32_t absolute_diff = (*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); int ssb_subcarrier_offset = 31; // default value for NSA if (get_softmodem_params()->sa) { - ssb_subcarrier_offset = absolute_diff%(12*scs_scaling); - if(frequency_range == FR1) - ssb_subcarrier_offset <<= *scc->ssbSubcarrierSpacing; + uint32_t absolute_diff = (*scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencySSB - scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA); + int scs_scaling = scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA < 600000 ? 3 : 1; + ssb_subcarrier_offset = (absolute_diff*scs_scaling)%24; + if(frequency_range == FR2) + ssb_subcarrier_offset >>= 1; // this assumes 120kHz SCS for SSB and subCarrierSpacingCommon (only option supported by OAI for now) } mib->message.choice.mib->ssb_SubcarrierOffset = ssb_subcarrier_offset&15; From edcb1b2bf578ed980935d5774c4ef80d4ff8cd10 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 5 Jul 2022 18:30:02 +0200 Subject: [PATCH 47/60] workaround for pbchsim --- openair1/SIMULATION/NR_PHY/pbchsim.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index b43cb6b00d..0e648c945f 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -177,7 +177,7 @@ int main(int argc, char **argv) int ssb_subcarrier_offset = 0; channel_desc_t *gNB2UE; - get_softmodem_params()->sa = 0; + get_softmodem_params()->sa = 1; //uint8_t extended_prefix_flag=0; //int8_t interf1=-21,interf2=-21; @@ -464,6 +464,7 @@ int main(int argc, char **argv) frame_parms->Nid_cell = Nid_cell; frame_parms->nushift = Nid_cell%4; frame_parms->ssb_type = nr_ssb_type_C; + frame_parms->freq_range = mu<2 ? nr_FR1 : nr_FR2; nr_phy_config_request_sim_pbchsim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions); phy_init_nr_gNB(gNB,0,1); @@ -588,9 +589,12 @@ int main(int argc, char **argv) for (i=0; iLmax; i++) { if((SSB_positions >> i) & 0x01) { + const int sc_offset = frame_parms->freq_range == nr_FR1 ? ssb_subcarrier_offset<freq_range == nr_FR1 ? gNB->gNB_config.ssb_table.ssb_offset_point_a.value<gNB_config.ssb_table.ssb_offset_point_a.value << (mu - 2); msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.bchPayload = 0x55dd33; msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbBlockIndex = i; - msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = ssb_subcarrier_offset; + msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.SsbSubcarrierOffset = sc_offset; + msgDataTx.ssb[i].ssb_pdu.ssb_pdu_rel15.ssbOffsetPointA = prb_offset; start_symbol = nr_get_ssb_start_symbol(frame_parms,i); int slot = start_symbol/14; From 43c980d36bf277e49e3f22ea545e309af7099239 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Jul 2022 09:24:31 +0200 Subject: [PATCH 48/60] CI: NSA-B200-Container: no Qlog --- ci-scripts/xml_files/container_nsa_b200_quectel.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/ci-scripts/xml_files/container_nsa_b200_quectel.xml b/ci-scripts/xml_files/container_nsa_b200_quectel.xml index 8d04be3efd..51e6668cf0 100644 --- a/ci-scripts/xml_files/container_nsa_b200_quectel.xml +++ b/ci-scripts/xml_files/container_nsa_b200_quectel.xml @@ -53,7 +53,6 @@ Initialize_UE Initialize Quectel idefix - yes From f1e3f7fb1f0fc8acc69d096987c2f6324f362e50 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Jul 2022 17:59:33 +0200 Subject: [PATCH 49/60] CI: Abort pipeline if DeployObject fails --- ci-scripts/cls_containerize.py | 2 ++ ci-scripts/main.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 259db7bffe..49aeeeed55 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -567,8 +567,10 @@ class Containerize(): if status: HTML.CreateHtmlTestRow('N/A', 'OK', CONST.ALL_PROCESSES_OK) else: + self.exitStatus = 1 HTML.CreateHtmlTestRow('N/A', 'KO', CONST.ALL_PROCESSES_OK) + def UndeployObject(self, HTML, RAN): if self.eNB_serverId[self.eNB_instance] == '0': lIpAddr = self.eNBIPAddress diff --git a/ci-scripts/main.py b/ci-scripts/main.py index adef885942..448f2636e3 100644 --- a/ci-scripts/main.py +++ b/ci-scripts/main.py @@ -919,6 +919,8 @@ elif re.match('^TesteNB$', mode, re.IGNORECASE) or re.match('^TestUE$', mode, re CONTAINERS.Copy_Image_to_Test_Server(HTML) elif action == 'Deploy_Object': CONTAINERS.DeployObject(HTML, EPC) + if CONTAINERS.exitStatus==1: + RAN.prematureExit = True elif action == 'Undeploy_Object': CONTAINERS.UndeployObject(HTML, RAN) elif action == 'Cppcheck_Analysis': From 5928d571e7c82040bf8e04f8fc9f1f29a9db7014 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 8 Jul 2022 11:14:04 +0200 Subject: [PATCH 50/60] CI: Fix log message typo in UndeployObject() --- ci-scripts/cls_containerize.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/cls_containerize.py b/ci-scripts/cls_containerize.py index 49aeeeed55..6abf444a0d 100644 --- a/ci-scripts/cls_containerize.py +++ b/ci-scripts/cls_containerize.py @@ -590,7 +590,7 @@ class Containerize(): if lIpAddr == '' or lUserName == '' or lPassWord == '' or lSourcePath == '': HELP.GenericHelp(CONST.Version) sys.exit('Insufficient Parameter') - logging.debug('\u001B[1m Deploying OAI Object on server: ' + lIpAddr + '\u001B[0m') + logging.debug('\u001B[1m Undeploying OAI Object from server: ' + lIpAddr + '\u001B[0m') mySSH = SSH.SSHConnection() mySSH.open(lIpAddr, lUserName, lPassWord) mySSH.command('cd ' + lSourcePath + '/' + self.yamlPath[self.eNB_instance], '\$', 5) From 87d1a53ca39585246131a5e6af32929e09b89f7b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 14 Jul 2022 17:08:59 +0200 Subject: [PATCH 51/60] CI: Allow publickey authentication in SSHConnection For pubkey, checks that we are on the right machine --- ci-scripts/sshconnection.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py index dca3daa817..d9ab3c5011 100644 --- a/ci-scripts/sshconnection.py +++ b/ci-scripts/sshconnection.py @@ -60,7 +60,7 @@ class SSHConnection(): count = 0 connect_status = False while count < 4: - self.ssh = pexpect.spawn('ssh -o PubkeyAuthentication=no {}@{}'.format(username,ipaddress)) + self.ssh = pexpect.spawn('ssh -o PubkeyAuthentication=yes {}@{}'.format(username,ipaddress)) # Longer timeout at connection due to asterix slowness self.ssh.timeout = 25 self.sshresponse = self.ssh.expect(['Are you sure you want to continue connecting (yes/no)?', 'password:', 'Last login', pexpect.EOF, pexpect.TIMEOUT]) @@ -85,13 +85,15 @@ class SSHConnection(): logging.debug('self.sshresponse = ' + str(self.sshresponse)) elif self.sshresponse == 2: # Checking if we are really on the remote client defined by its IP address - self.command('stdbuf -o0 ifconfig | egrep --color=never "inet addr:|inet "', prompt, 5) - result = re.search(str(ipaddress), str(self.ssh.before)) - if result is None: - self.close() - else: + self.ssh.sendline('stdbuf -o0 ifconfig | egrep --color=never "inet addr:|inet "') + self.sshresponse = self.ssh.expect([ipaddress, pexpect.EOF, pexpect.TIMEOUT]) + if self.sshresponse == 0: count = 10 connect_status = True + # this expect seems to be necessary to advance the read buffer until the prompt, or getBefore() will not return the last command + self.sshresponse = self.ssh.expect([prompt]) + else: + logging.error('logged in to ' + ipaddress + ' without password but IP is not found via ifconfig on remote host, aborting') else: # debug output logging.debug(str(self.ssh.before)) From 4b50e4b1f684f958f3bdcd604a4a10de64fa94db Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 14 Jul 2022 22:18:01 +0200 Subject: [PATCH 52/60] CI: decode in getBefore() --- ci-scripts/sshconnection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py index d9ab3c5011..52d799ebe3 100644 --- a/ci-scripts/sshconnection.py +++ b/ci-scripts/sshconnection.py @@ -274,4 +274,4 @@ class SSHConnection(): sys.exit('SCP failed') def getBefore(self): - return str(self.ssh.before) + return self.ssh.before.decode('utf-8') From b308cbe1019002a1f51dedde0c1cb84fd62a62f2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 7 Jul 2022 09:07:58 +0200 Subject: [PATCH 53/60] Add RAN-SA-B200-Module-SABOX-Container test --- .../gnb.sa.band78.fr1.106PRB.usrpb210.conf | 344 ++++++++++++++++++ .../xml_files/container_sa_b200_quectel.xml | 169 +++++++++ .../xml_files/container_sa_b200_terminate.xml | 42 +++ ci-scripts/xml_files/fr1_5gc_closure.xml | 37 ++ ci-scripts/xml_files/fr1_5gc_start.xml | 38 ++ .../yaml_files/sa_b200_gnb/docker-compose.yml | 44 +++ doc/TESTBenches.md | 5 +- docker/scripts/generateTemplate.py | 1 + docker/scripts/gnb_entrypoint.sh | 1 + docker/scripts/gnb_parameters.yaml | 30 ++ 10 files changed, 710 insertions(+), 1 deletion(-) create mode 100644 ci-scripts/conf_files/gnb.sa.band78.fr1.106PRB.usrpb210.conf create mode 100644 ci-scripts/xml_files/container_sa_b200_quectel.xml create mode 100644 ci-scripts/xml_files/container_sa_b200_terminate.xml create mode 100644 ci-scripts/xml_files/fr1_5gc_closure.xml create mode 100644 ci-scripts/xml_files/fr1_5gc_start.xml create mode 100644 ci-scripts/yaml_files/sa_b200_gnb/docker-compose.yml diff --git a/ci-scripts/conf_files/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.sa.band78.fr1.106PRB.usrpb210.conf new file mode 100644 index 0000000000..2a6053ab46 --- /dev/null +++ b/ci-scripts/conf_files/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -0,0 +1,344 @@ +Active_gNBs = ( "gNB-OAI"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( + { + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ + mcc = 222; + mnc = 01; + mnc_length = 2; + snssaiList = ( + { + sst = 1; + #sd = 0x1; // 0 false, else true + } + ); + + }); + + nr_cellid = 12345678L; + + ////////// Physical parameters: + + min_rxtxtime = 2; + do_CSIRS = 1; + do_SRS = 1; + + pdcch_ConfigSIB1 = ( + { + controlResourceSetZero = 12; + searchSpaceZero = 0; + } + ); + + servingCellConfigCommon = ( + { + #spCellConfigCommon + + physCellId = 0; + +# downlinkConfigCommon + #frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641280; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640008; + #scs-SpecificCarrierList + dl_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + #initialDownlinkBWP + #genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; # 6366 12925 12956 28875 12952 +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + #pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + #uplinkConfigCommon + #frequencyInfoUL + ul_frequencyBand = 78; + #scs-SpecificCarrierList + ul_offstToCarrier = 0; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + #initialUplinkBWP + #genericParameters + initialULBWPlocationAndBandwidth = 28875; +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + #rach-ConfigCommon + #rach-ConfigGeneric + prach_ConfigurationIndex = 98; +#prach_msg1_FDM +#0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; +#preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; +#powerRampingStep +# 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; +#ra_ReponseWindow +#1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; +#ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR +#1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; +#oneHalf (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; +#ra_ContentionResolutionTimer +#(0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; +#prach-RootSequenceIndex_PR +#1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precendence over the one derived from prach-ConfigIndex + # + msg1_SubcarrierSpacing = 1, +# restrictedSetConfig +# 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0, + + msg3_DeltaPreamble = 1; + p0_NominalWithGrant =-90; + +# pucch-ConfigCommon setup : +# pucchGroupHopping +# 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; +# ssb_PositionsInBurs_BitmapPR +# 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + +# ssb_periodicityServingCell +# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + +# dmrs_TypeA_position +# 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + + #tdd-UL-DL-ConfigurationCommon +# subcarrierSpacing +# 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + dl_UL_TransmissionPeriodicity = 6; + nrofDownlinkSlots = 7; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + ssPBCH_BlockPower = -25; + } + + ); + +# Dedicated Serving Cell Configuration +servingCellConfigDedicated = ({ + # BWP-Downlink + # BWP 1 Configuration + dl_bwp-Id_1 = 1; + dl_bwp1_locationAndBandwidth = 28875; // RBstart=0, L=106 (40 MHz BW) + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_bwp1_subcarrierSpacing = 1; + + # BWP 2 Configuration + dl_bwp-Id_2 = 2; + dl_bwp2_locationAndBandwidth = 13750; // RBstart=0, L=51 (20 MHz BW) + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_bwp2_subcarrierSpacing = 1; + + # BWP 3 Configuration + dl_bwp-Id_3 = 3; + dl_bwp3_locationAndBandwidth = 6325; // RBstart=0, L=24 (10 MHz BW) + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_bwp3_subcarrierSpacing = 1; + + firstActiveDownlinkBWP-Id = 1; #BWP-Id + defaultDownlinkBWP-Id = 1; #BWP-Id + + # bwp-InactivityTimer ENUMERATED {ms2, ms3, ms4, ms5, ms6, ms8, ms10, ms20, ms30, + # ms40,ms50, ms60, ms80,ms100, ms200,ms300, ms500, + # ms750, ms1280, ms1920, ms2560, spare10, spare9, spare8, + # spare7, spare6, spare5, spare4, spare3, spare2, spare1 } + + # UplinkConfig + # BWP-Uplink + # BWP 1 Configuration + ul_bwp-Id_1 = 1; + ul_bwp1_locationAndBandwidth = 28875; // RBstart=0, L=106 (40 MHz BW) + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_bwp1_subcarrierSpacing = 1; + + # BWP 2 Configuration + ul_bwp-Id_2 = 2; + ul_bwp2_locationAndBandwidth = 13750; // RBstart=0, L=51 (20 MHz BW) + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_bwp2_subcarrierSpacing = 1; + + # BWP 3 Configuration + ul_bwp-Id_3 = 3; + ul_bwp3_locationAndBandwidth = 6325; // RBstart=0, L=24 (10 MHz BW) + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_bwp3_subcarrierSpacing = 1; + + firstActiveUplinkBWP-Id = 1; #BWP-Id + } +); + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// AMF parameters: + amf_ip_address = ( { ipv4 = "172.21.16.136"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + + NETWORK_INTERFACES : + { + GNB_INTERFACE_NAME_FOR_NG_AMF = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "172.21.16.137/24"; + GNB_INTERFACE_NAME_FOR_NGU = "demo-oai"; + GNB_IPV4_ADDRESS_FOR_NGU = "172.21.16.137/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 200; + pucch_TargetSNRx10 = 200; + ulsch_max_frame_inactivity = 0; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 100; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 +} +); + +RUs = ( +{ + local_rf = "yes" + nb_tx = 1 + nb_rx = 1 + att_tx = 10; + att_rx = 10; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + #beamforming 1x4 matrix: + bf_weights = [0x00007fff, 0x0000, 0x0000, 0x0000]; + clock_src = "internal"; +} +); + +THREAD_STRUCT = ( +{ + #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT" + parallel_config = "PARALLEL_SINGLE_THREAD"; + #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE" + worker_config = "WORKER_ENABLE"; +} +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = "4043"; + options = (); #("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that an UE supports in chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that an UE supports in chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level ="info"; + hw_log_level ="info"; + phy_log_level ="info"; + mac_log_level ="info"; + rlc_log_level ="info"; + pdcp_log_level ="info"; + rrc_log_level ="info"; + ngap_log_level ="debug"; + f1ap_log_level ="debug"; +}; + diff --git a/ci-scripts/xml_files/container_sa_b200_quectel.xml b/ci-scripts/xml_files/container_sa_b200_quectel.xml new file mode 100644 index 0000000000..971fd1deed --- /dev/null +++ b/ci-scripts/xml_files/container_sa_b200_quectel.xml @@ -0,0 +1,169 @@ + + + TEST-SA-FR1-B200 + SA SanityCheck with QUECTEL + tasks + 1 + + 000001 + 010002 + 030000 + 030101 + 000001 + 010000 + 000001 + 050000 + 050001 + 010002 + 000001 + 030201 + + + + + + Initialize_UE + Initialize Quectel + idefix + + + + + Terminate_UE + Terminate Quectel + idefix + + + + Copy_Image_to_Test + Copy gNB image to test server + oai-gnb + 1 + 0 + + + + Deploy_Object + Deploy gNB (TDD/Band78/40MHz/B200) in a container + ci-scripts/yaml_files/sa_b200_gnb + 0 + 0 + + + + IdleSleep + Sleep + 5 + + + + IdleSleep + Sleep + 20 + + + + + Ping + Ping: 20pings in 20sec + idefix + -c 20 + 1 + 15 + + + + Ping + Ping: 100pings in 20sec + idefix + -c 100 -i 0.2 + 1 + 15 + + + + Ping + Ping: 20pings in 20sec + idefix + -c 20 + 1 + 15 + + + + Ping + Ping: 100pings in 20sec + idefix + -c 100 -i 0.2 + 1 + 15 + + + + Iperf + iperf (DL/125Mbps/UDP)(60 sec)(single-ue profile) + -u -b 125M -t 60 -i 1 -fm + DL + idefix + 25 + 80 + single-ue + + + + Iperf + iperf (UL/8Mbps/UDP)(60 sec)(single-ue profile) + -u -b 8M -t 60 -i 1 -fm + UL + idefix + 1 + 95 + single-ue + + + + Iperf + iperf (BIDIR TCP)(10 sec)(single-ue profile) + -t 10 --bidir + BIDIR + idefix + single-ue + + + + Undeploy_Object + Undeploy gNB + ci-scripts/yaml_files/sa_b200_gnb + 0 + 0 + + + + diff --git a/ci-scripts/xml_files/container_sa_b200_terminate.xml b/ci-scripts/xml_files/container_sa_b200_terminate.xml new file mode 100644 index 0000000000..5a2b6bd454 --- /dev/null +++ b/ci-scripts/xml_files/container_sa_b200_terminate.xml @@ -0,0 +1,42 @@ + + + TEST-SA-FR1-B200-terminate + SA tear-down in case of problem + tasks + 1 + + 030201 + + + + + Undeploy_Object + Undeploy gNB + ci-scripts/yaml_files/sa_b200_gnb + 1 + 1 + sa-test + + + diff --git a/ci-scripts/xml_files/fr1_5gc_closure.xml b/ci-scripts/xml_files/fr1_5gc_closure.xml new file mode 100644 index 0000000000..e5e57fa694 --- /dev/null +++ b/ci-scripts/xml_files/fr1_5gc_closure.xml @@ -0,0 +1,37 @@ + + + 5gc-closure + 5GC-Closure + log-out + +060000 + + + + + Terminate_5GCN + Terminate 5GC + + + diff --git a/ci-scripts/xml_files/fr1_5gc_start.xml b/ci-scripts/xml_files/fr1_5gc_start.xml new file mode 100644 index 0000000000..8758b761cd --- /dev/null +++ b/ci-scripts/xml_files/fr1_5gc_start.xml @@ -0,0 +1,38 @@ + + + 5gc-start-tab + 5GC-Start + log-in + + 000100 + + + + + + Initialize_5GCN + Initialize 5GC + + + diff --git a/ci-scripts/yaml_files/sa_b200_gnb/docker-compose.yml b/ci-scripts/yaml_files/sa_b200_gnb/docker-compose.yml new file mode 100644 index 0000000000..9ea52c1247 --- /dev/null +++ b/ci-scripts/yaml_files/sa_b200_gnb/docker-compose.yml @@ -0,0 +1,44 @@ +version: '3.8' + +services: + gnb_mono_tdd: + image: oai-gnb:latest + privileged: true + container_name: sa-b200-gnb + environment: + USE_SA_TDD_MONO_B2XX: 'yes' + USE_B2XX: 'yes' + GNB_NAME: gNB-in-docker + MCC: '222' + MNC: '01' + MNC_LENGTH: 2 + TAC: 1 + NSSAI_SST: 1 + NSSAI_SD0: 1 + AMF_IP_ADDRESS: 172.21.16.136 + GNB_NGA_IF_NAME: eth0 + GNB_NGA_IP_ADDRESS: 192.168.68.194 + GNB_NGU_IF_NAME: eth0 + GNB_NGU_IP_ADDRESS: 192.168.68.194 + USE_ADDITIONAL_OPTIONS: --sa -E -q --RUs.[0].sdr_addrs serial=30C51D4 --continuous-tx --log_config.global_log_options level,nocolor,time,line_num,function + volumes: + - /dev:/dev + networks: + public_net: + ipv4_address: 192.168.68.194 + #entrypoint: /bin/bash -c "sleep infinity" + healthcheck: + # pgrep does NOT work + test: /bin/bash -c "ps aux | grep -v grep | grep -c softmodem" + interval: 10s + timeout: 5s + retries: 5 + +networks: + public_net: + name: sa-b200-gnb-net + ipam: + config: + - subnet: 192.168.68.192/26 + driver_opts: + com.docker.network.bridge.name: "sa-gnb-net" diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index 547fd5a23b..24e649ccc0 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -89,7 +89,10 @@ Webhook currently only ping - [RAN-NSA-B200-Module-LTEBOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-NSA-B200-Module-LTEBOX-Container/) - obelix + B200, nepes + B200, idefix + Quectel, porcepix w/ ltebox - - basic NSA test, known to be instable + - basic NSA test +- [RAN-SA-B200-Module-SABOX-Container](https://jenkins-oai.eurecom.fr/job/RAN-SA-B200-Module-SABOX-Container/) + - obelix + B200, nepes + B200, idefix + Quectel, porcepix w/ sabox + - basic SA test (40 MHz TDD) - [RAN-PhySim-Cluster](https://jenkins-oai.eurecom.fr/job/RAN-PhySim-Cluster/) - asterix (`Asterix-OC-oaicicd-session` resource), tests in OpenShift Cluster - unitary simulators (`nr_dlsim`, etc.) diff --git a/docker/scripts/generateTemplate.py b/docker/scripts/generateTemplate.py index 850bb535a5..ec8f32ec6e 100644 --- a/docker/scripts/generateTemplate.py +++ b/docker/scripts/generateTemplate.py @@ -60,6 +60,7 @@ def main(): "rcc.band40.tm1.25PRB": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "gnb.band78.tm1.fr1.106PRB.usrpb210.conf": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "gnb.band78.sa.fr1.106PRB.usrpn310.conf": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', + "gnb.sa.band78.fr1.106PRB.usrpb210.conf": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "gnb.sa.band66.fr1.106PRB.usrpn300.conf": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "gNB_SA_CU.conf": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', "gNB_SA_DU.conf": f'{data[0]["paths"]["dest_dir"]}/{outputfilename}', diff --git a/docker/scripts/gnb_entrypoint.sh b/docker/scripts/gnb_entrypoint.sh index dd6256609c..ac0e0d4c88 100755 --- a/docker/scripts/gnb_entrypoint.sh +++ b/docker/scripts/gnb_entrypoint.sh @@ -10,6 +10,7 @@ THREAD_PARALLEL_CONFIG=${THREAD_PARALLEL_CONFIG:-PARALLEL_SINGLE_THREAD} if [[ -v USE_NSA_TDD_MONO ]]; then cp $PREFIX/etc/gnb.nsa.tdd.conf $PREFIX/etc/gnb.conf; fi if [[ -v USE_SA_TDD_MONO ]]; then cp $PREFIX/etc/gnb.sa.tdd.conf $PREFIX/etc/gnb.conf; fi +if [[ -v USE_SA_TDD_MONO_B2XX ]]; then cp $PREFIX/etc/gnb.sa.tdd.b2xx.conf $PREFIX/etc/gnb.conf; fi if [[ -v USE_SA_FDD_MONO ]]; then cp $PREFIX/etc/gnb.sa.fdd.conf $PREFIX/etc/gnb.conf; fi if [[ -v USE_SA_CU ]]; then cp $PREFIX/etc/gnb.sa.cu.conf $PREFIX/etc/gnb.conf; fi if [[ -v USE_SA_TDD_CU ]]; then cp $PREFIX/etc/gnb.sa.du.tdd.conf $PREFIX/etc/gnb.conf; fi diff --git a/docker/scripts/gnb_parameters.yaml b/docker/scripts/gnb_parameters.yaml index d5942f2c9b..420559ff3f 100644 --- a/docker/scripts/gnb_parameters.yaml +++ b/docker/scripts/gnb_parameters.yaml @@ -94,6 +94,36 @@ - key: parallel_config env: "@THREAD_PARALLEL_CONFIG@" + - filePrefix: gnb.sa.band78.fr1.106PRB.usrpb210.conf + outputfilename: "gnb.sa.tdd.b2xx.conf" + config: + - key: Active_gNBs + env: "@GNB_NAME@" + - key: gNB_name + env: "@GNB_NAME@" + - key: mcc + env: "@MCC@" + - key: mnc + env: "@MNC@" + - key: mnc_length + env: "@MNC_LENGTH@" + - key: tracking_area_code + env: "@TAC@" + - key: sst + env: "@NSSAI_SST@" + - key: ipv4 + env: "@AMF_IP_ADDRESS@" + - key: GNB_INTERFACE_NAME_FOR_NG_AMF + env: "@GNB_NGA_IF_NAME@" + - key: GNB_IPV4_ADDRESS_FOR_NG_AMF + env: "@GNB_NGA_IP_ADDRESS@" + - key: GNB_INTERFACE_NAME_FOR_NGU + env: "@GNB_NGU_IF_NAME@" + - key: GNB_IPV4_ADDRESS_FOR_NGU + env: "@GNB_NGU_IP_ADDRESS@" + - key: parallel_config + env: "@THREAD_PARALLEL_CONFIG@" + - filePrefix: gnb.sa.band66.fr1.106PRB.usrpn300.conf outputfilename: "gnb.sa.fdd.conf" config: From 0c4aa33939cf0b6cb9142a37019b8fc58bf97cde Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 14 Jul 2022 23:57:52 +0200 Subject: [PATCH 54/60] Trigger SA-B200 test from RAN-Container-Parent --- ci-scripts/Jenkinsfile-GitLab-Container | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index c22e6fabec..b37c9d4f4b 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -278,6 +278,26 @@ pipeline { } } } + stage ("SA B200 Sanity Check") { + when { expression {doMandatoryTests} } + steps { + script { + triggerSlaveJob ('RAN-SA-B200-Module-SABOX-Container', 'Test-SA-B200') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-SA-B200-Module-SABOX-Container') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } stage ("Test OAI NR UE - OAI gNB - TDD - Band 78 - N300") { when { expression {doMandatoryTests} } steps { From 63daf5793b414a92fb87e6f77845fb9c68c22752 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 15 Jul 2022 11:01:26 +0200 Subject: [PATCH 55/60] Remove useless SA test sleep --- ci-scripts/xml_files/container_sa_b200_quectel.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/ci-scripts/xml_files/container_sa_b200_quectel.xml b/ci-scripts/xml_files/container_sa_b200_quectel.xml index 971fd1deed..7f0475629d 100644 --- a/ci-scripts/xml_files/container_sa_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_b200_quectel.xml @@ -26,7 +26,6 @@ tasks 1 - 000001 010002 030000 030101 From 52168e5201c9b93a2632ec6c40f8de210491e351 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 15 Jul 2022 11:00:18 +0200 Subject: [PATCH 56/60] Shut off quectel before running SA tests --- ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml | 1 + ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml | 1 + ci-scripts/xml_files/fr1_nsa_quectel.xml | 1 + ci-scripts/xml_files/fr1_sa_quectel.xml | 1 + ci-scripts/xml_files/fr1_sa_quectel_162prb.xml | 1 + ci-scripts/xml_files/fr1_sa_quectel_stages.xml | 1 + ci-scripts/xml_files/lte_2x2_tm1_quectel.xml | 1 + ci-scripts/xml_files/lte_2x2_tm2_quectel.xml | 1 + 8 files changed, 8 insertions(+) diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml index 2ef2b7d7ce..459a16c323 100644 --- a/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel.xml @@ -26,6 +26,7 @@ tasks 1 + 010002 030000 040000 000002 diff --git a/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml index 335fe873a1..c8e0659330 100644 --- a/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml +++ b/ci-scripts/xml_files/fr1_nsa_2x2_quectel_attach_detach.xml @@ -26,6 +26,7 @@ tasks 1 + 010002 031000 041000 000002 diff --git a/ci-scripts/xml_files/fr1_nsa_quectel.xml b/ci-scripts/xml_files/fr1_nsa_quectel.xml index a7fd0fc0d7..c72c61c0a2 100644 --- a/ci-scripts/xml_files/fr1_nsa_quectel.xml +++ b/ci-scripts/xml_files/fr1_nsa_quectel.xml @@ -26,6 +26,7 @@ tasks 1 + 010002 030000 040000 000002 diff --git a/ci-scripts/xml_files/fr1_sa_quectel.xml b/ci-scripts/xml_files/fr1_sa_quectel.xml index 2b215479c2..fd983d8835 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel.xml @@ -26,6 +26,7 @@ tasks 1 + 010002 040000 000002 010000 diff --git a/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml index 23eaccfcfd..f426bd6035 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel_162prb.xml @@ -26,6 +26,7 @@ tasks 1 + 010002 042000 000002 010000 diff --git a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml index 603f3f919b..48a9b60e7d 100644 --- a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml +++ b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml @@ -26,6 +26,7 @@ tasks 1 + 011002 041000 000002 011000 diff --git a/ci-scripts/xml_files/lte_2x2_tm1_quectel.xml b/ci-scripts/xml_files/lte_2x2_tm1_quectel.xml index 0d18a52839..b6388eede2 100644 --- a/ci-scripts/xml_files/lte_2x2_tm1_quectel.xml +++ b/ci-scripts/xml_files/lte_2x2_tm1_quectel.xml @@ -26,6 +26,7 @@ tasks 1 + 010002 030000 000002 010000 diff --git a/ci-scripts/xml_files/lte_2x2_tm2_quectel.xml b/ci-scripts/xml_files/lte_2x2_tm2_quectel.xml index f84691ab48..99c8f75e06 100644 --- a/ci-scripts/xml_files/lte_2x2_tm2_quectel.xml +++ b/ci-scripts/xml_files/lte_2x2_tm2_quectel.xml @@ -26,6 +26,7 @@ tasks 1 + 010002 030001 000002 010000 From ae05420c84ccbdc04843db1d5b318176998220b4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 15 Jul 2022 13:35:19 +0200 Subject: [PATCH 57/60] CI: log error if oai-amf container is not present for AMF IP addr retrieval --- ci-scripts/epc.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci-scripts/epc.py b/ci-scripts/epc.py index 0e0afefaaf..9113d29ac9 100644 --- a/ci-scripts/epc.py +++ b/ci-scripts/epc.py @@ -311,6 +311,8 @@ class EPCManagement(): tmp = str(response[0],'utf-8') self.MmeIPAddress = tmp.rstrip() logging.debug('AMF IP Address ' + self.MmeIPAddress) + else: + logging.error('no container with name oai-amf found, could not retrieve AMF IP address') mySSH.close() def CheckHSSProcess(self, status_queue): From 16c758ae0972a35bef28af38c82122232926f563 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 15 Jul 2022 16:00:52 +0200 Subject: [PATCH 58/60] CI: Drop IP check when connectiong via SSH and pubkey --- ci-scripts/sshconnection.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/ci-scripts/sshconnection.py b/ci-scripts/sshconnection.py index 52d799ebe3..035da71426 100644 --- a/ci-scripts/sshconnection.py +++ b/ci-scripts/sshconnection.py @@ -84,16 +84,11 @@ class SSHConnection(): else: logging.debug('self.sshresponse = ' + str(self.sshresponse)) elif self.sshresponse == 2: - # Checking if we are really on the remote client defined by its IP address - self.ssh.sendline('stdbuf -o0 ifconfig | egrep --color=never "inet addr:|inet "') - self.sshresponse = self.ssh.expect([ipaddress, pexpect.EOF, pexpect.TIMEOUT]) - if self.sshresponse == 0: - count = 10 - connect_status = True - # this expect seems to be necessary to advance the read buffer until the prompt, or getBefore() will not return the last command - self.sshresponse = self.ssh.expect([prompt]) - else: - logging.error('logged in to ' + ipaddress + ' without password but IP is not found via ifconfig on remote host, aborting') + # We directly ended up on the remote server because of pubkey auth + count = 10 + connect_status = True + # this expect() seems to be necessary to advance the read buffer until the prompt, or getBefore() will not return the last command + self.sshresponse = self.ssh.expect([prompt]) else: # debug output logging.debug(str(self.ssh.before)) From 04251d5b06f4ab5abbe560905efac74e496a101c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 18 Jul 2022 17:39:52 +0200 Subject: [PATCH 59/60] Correctly initialize protocol_ctxt in F1 code In the previous version, not all fields, and in particular the `eNB_index`, were not initialized, leading to errors when they were used (e.g., the PDCP code checks that eNB_index == 0). --- openair2/RRC/NR/rrc_gNB.c | 63 ++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 43082003df..400be0bd4d 100755 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -197,7 +197,7 @@ static void init_NR_SI(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *configuration } char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigurationReq *configuration) { - protocol_ctxt_t ctxt; + protocol_ctxt_t ctxt = { 0 }; gNB_RRC_INST *rrc=RC.nrrrc[gnb_mod_idP]; PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, gnb_mod_idP, GNB_FLAG_YES, NOT_A_RNTI, 0, 0,gnb_mod_idP); LOG_I(NR_RRC, @@ -3030,11 +3030,13 @@ void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC static int rrc_process_DU_DL(MessageDef *msg_p, const char *msg_name, instance_t instance) { NRDuDlReq_t * req=&NRDuDlReq(msg_p); - protocol_ctxt_t ctxt; - ctxt.rnti = req->rnti; - ctxt.module_id = instance; - ctxt.instance = instance; - ctxt.enb_flag = 1; + protocol_ctxt_t ctxt = { + .rnti = req->rnti, + .module_id = instance, + .instance = instance, + .enb_flag = 1, + .eNB_index = instance + }; gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_get_ue_context(rrc, ctxt.rnti); @@ -3285,11 +3287,13 @@ return 0; static void rrc_DU_process_ue_context_setup_request(MessageDef *msg_p, const char *msg_name, instance_t instance){ f1ap_ue_context_setup_t * req=&F1AP_UE_CONTEXT_SETUP_REQ(msg_p); - protocol_ctxt_t ctxt; - ctxt.rnti = req->rnti; - ctxt.module_id = instance; - ctxt.instance = instance; - ctxt.enb_flag = 1; + protocol_ctxt_t ctxt = { + .rnti = req->rnti, + .module_id = instance, + .instance = instance, + .enb_flag = 1, + .eNB_index = instance + }; gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; gNB_MAC_INST *mac = RC.nrmac[ctxt.module_id]; struct rrc_gNB_ue_context_s *ue_context_p = @@ -3515,11 +3519,13 @@ static void rrc_DU_process_ue_context_setup_request(MessageDef *msg_p, const cha static void rrc_DU_process_ue_context_modification_request(MessageDef *msg_p, const char *msg_name, instance_t instance){ f1ap_ue_context_setup_t * req=&F1AP_UE_CONTEXT_MODIFICATION_REQ(msg_p); - protocol_ctxt_t ctxt; - ctxt.rnti = req->rnti; - ctxt.module_id = instance; - ctxt.instance = instance; - ctxt.enb_flag = 1; + protocol_ctxt_t ctxt = { + .rnti = req->rnti, + .module_id = instance, + .instance = instance, + .enb_flag = 1, + .eNB_index = instance + }; gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; gNB_MAC_INST *mac = RC.nrmac[ctxt.module_id]; struct rrc_gNB_ue_context_s *ue_context_p = @@ -3664,11 +3670,13 @@ static void rrc_DU_process_ue_context_modification_request(MessageDef *msg_p, co static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, const char *msg_name, instance_t instance){ f1ap_ue_context_setup_t * resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p); - protocol_ctxt_t ctxt; - ctxt.rnti = resp->rnti; - ctxt.module_id = instance; - ctxt.instance = instance; - ctxt.enb_flag = 1; + protocol_ctxt_t ctxt = { + .rnti = resp->rnti, + .module_id = instance, + .instance = instance, + .enb_flag = 1, + .eNB_index = instance + }; gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_get_ue_context(rrc, ctxt.rnti); NR_CellGroupConfig_t *cellGroupConfig = NULL; @@ -3721,12 +3729,13 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, const ch static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, const char *msg_name, instance_t instance){ f1ap_ue_context_setup_t * resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p); - protocol_ctxt_t ctxt; - ctxt.rnti = resp->rnti; - ctxt.module_id = instance; - ctxt.instance = instance; - ctxt.enb_flag = 1; - ctxt.eNB_index = instance; + protocol_ctxt_t ctxt = { + .rnti = resp->rnti, + .module_id = instance, + .instance = instance, + .enb_flag = 1, + .eNB_index = instance + }; gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_get_ue_context(rrc, ctxt.rnti); NR_CellGroupConfig_t *cellGroupConfig = NULL; From b1a3cbb068eeeac04a0c14ccbba7d6c28cc491bc Mon Sep 17 00:00:00 2001 From: luis_pereira87 Date: Wed, 20 Jul 2022 12:55:17 +0100 Subject: [PATCH 60/60] Fix segmentation fault when changing BWP --- openair2/RRC/NR/rrc_gNB.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 400be0bd4d..648df1a306 100755 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1949,7 +1949,7 @@ int nr_rrc_reconfiguration_req(rrc_gNB_ue_context_t *const ue_context_pP NULL, NULL, NULL, - NULL, + ue_context_pP, NULL, NULL, NULL,