From 90bb405e0d0de3fee71e1d3d851f6419b34b28fe Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 24 Oct 2023 10:51:27 +0200 Subject: [PATCH] Deep-copy PDCCH ConfigCommon for SIB1 Until this commit, the SIB1's PDCCH_configCommon was set (via a pointer, i.e., an indirection) to the one of the ServingCellConfigCommon (SCC). Afterwards, the SIB1 code further populated this PDCCH configCommon, indirectly populating the one of the the SCC, on which code later depends. Not only did this create possibilities for double-frees (since freeing the memory of SIB1, then SCC would free the PDCCH configcommon twice), but also it makes it harder to track where certain structures are populated. Hence, this commit solves both issues: - The SCC is correctly populated on initialization of the SCC - The SIB1 makes a deep copy of the SCC' PDCCH configCommon This resolves the two issues above. --- openair2/GNB_APP/gnb_config.c | 22 +++++++++++++++ openair2/RRC/NR/nr_rrc_config.c | 48 ++++++++++++++++++++------------- openair2/RRC/NR/nr_rrc_config.h | 1 + 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index e190b21748..b2ae0039b7 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -970,6 +970,28 @@ static NR_ServingCellConfigCommon_t *get_scc_config(int minRXTXTIME) fix_scc(scc, ssb_bitmap); } nr_rrc_config_ul_tda(scc, minRXTXTIME); + + // the gNB uses the servingCellConfigCommon everywhere, even when it should use the servingCellConfigCommonSIB. + // previously (before this commit), the following fields were indirectly populated through get_SIB1_NR(). + // since this might lead to memory problems (e.g., double frees), it has been moved here. + // note that the "right solution" would be to not populate the servingCellConfigCommon here, and use + // an "abstraction struct" that contains the corresponding values, from which SCC/SIB1/... is generated. + NR_PDCCH_ConfigCommon_t *pcc = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup; + AssertFatal(pcc != NULL && pcc->commonSearchSpaceList == NULL, "memory leak\n"); + pcc->commonSearchSpaceList = calloc_or_fail(1, sizeof(*pcc->commonSearchSpaceList)); + + NR_SearchSpace_t *ss1 = rrc_searchspace_config(true, 1, 0); + asn1cSeqAdd(&pcc->commonSearchSpaceList->list, ss1); + NR_SearchSpace_t *ss2 = rrc_searchspace_config(true, 2, 0); + asn1cSeqAdd(&pcc->commonSearchSpaceList->list, ss2); + NR_SearchSpace_t *ss3 = rrc_searchspace_config(true, 3, 0); + asn1cSeqAdd(&pcc->commonSearchSpaceList->list, ss3); + + asn1cCallocOne(pcc->searchSpaceSIB1, 0); + asn1cCallocOne(pcc->ra_SearchSpace, 1); + asn1cCallocOne(pcc->pagingSearchSpace, 2); + asn1cCallocOne(pcc->searchSpaceOtherSystemInformation, 3); + return scc; } diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 831ebd097d..6c940fb21a 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -103,6 +103,23 @@ static NR_SetupRelease_PUCCH_ConfigCommon_t *clone_pucch_configcommon(const NR_S return clone; } +static NR_SetupRelease_PDCCH_ConfigCommon_t *clone_pdcch_configcommon(const NR_SetupRelease_PDCCH_ConfigCommon_t *pcc) +{ + if (pcc == NULL || pcc->present == NR_SetupRelease_PDCCH_ConfigCommon_PR_NOTHING) + return NULL; + NR_SetupRelease_PDCCH_ConfigCommon_t *clone = calloc(1, sizeof(*clone)); + clone->present = pcc->present; + if (clone->present == NR_SetupRelease_PDCCH_ConfigCommon_PR_release) + return clone; + + uint8_t buf[1024]; + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_PDCCH_ConfigCommon, NULL, pcc->choice.setup, buf, sizeof(buf)); + AssertFatal(enc_rval.encoded > 0 && enc_rval.encoded < sizeof(buf), "could not clone NR_PDCCH_ConfigCommon: problem while encoding\n"); + asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_PDCCH_ConfigCommon, (void **)&clone->choice.setup, buf, enc_rval.encoded, 0, 0); + AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed == enc_rval.encoded, "could not clone NR_PDCCH_ConfigCommon: problem while decoding\n"); + return clone; +} + static NR_SetupRelease_PDSCH_ConfigCommon_t *clone_pdsch_configcommon(const NR_SetupRelease_PDSCH_ConfigCommon_t *pcc) { if (pcc == NULL || pcc->present == NR_SetupRelease_PDSCH_ConfigCommon_PR_NOTHING) @@ -120,7 +137,7 @@ static NR_SetupRelease_PDSCH_ConfigCommon_t *clone_pdsch_configcommon(const NR_S return clone; } -static NR_SearchSpace_t *rrc_searchspace_config(bool is_common, int searchspaceid, int coresetid) +NR_SearchSpace_t *rrc_searchspace_config(bool is_common, int searchspaceid, int coresetid) { NR_SearchSpace_t *ss = calloc(1,sizeof(*ss)); @@ -1916,25 +1933,18 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, c frequencyInfoDL->scs_SpecificCarrierList.list.array[i]); } - initialDownlinkBWP->pdcch_ConfigCommon = scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon; - initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList = - CALLOC(1, sizeof(struct NR_PDCCH_ConfigCommon__commonSearchSpaceList)); - AssertFatal(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList != NULL, "out of memory\n"); + initialDownlinkBWP->pdcch_ConfigCommon = clone_pdcch_configcommon(scc->downlinkConfigCommon->initialDownlinkBWP->pdcch_ConfigCommon); + AssertFatal(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList != NULL, + "expected commonSearchSpaceList to be populated through SCC\n"); + AssertFatal(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1 != NULL, + "expected searchSpaceSIB1 to be populated through SCC\n"); + AssertFatal(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->ra_SearchSpace != NULL, + "expected ra_SearchSpace to be populated through SCC\n"); + AssertFatal(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->pagingSearchSpace != NULL, + "expected pagingSearchSpace to be populated through SCC\n"); + AssertFatal(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation != NULL, + "expected searchSpaceOtherSystemInformation to be populated through SCC\n"); - NR_SearchSpace_t *ss1 = rrc_searchspace_config(true, 1, 0); - asn1cSeqAdd(&initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list, ss1); - - NR_SearchSpace_t *ss2 = rrc_searchspace_config(true, 2, 0); - asn1cSeqAdd(&initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list, ss2); - - NR_SearchSpace_t *ss3 = rrc_searchspace_config(true, 3, 0); - asn1cSeqAdd(&initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList->list, ss3); - - asn1cCallocOne(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1, 0); - asn1cCallocOne(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceOtherSystemInformation, 3); - asn1cCallocOne(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->pagingSearchSpace, 2); - asn1cCallocOne(initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->ra_SearchSpace, 1); - initialDownlinkBWP->pdsch_ConfigCommon = clone_pdsch_configcommon(scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon); ServCellCom->downlinkConfigCommon.bcch_Config.modificationPeriodCoeff = NR_BCCH_Config__modificationPeriodCoeff_n2; ServCellCom->downlinkConfigCommon.pcch_Config.defaultPagingCycle = NR_PagingCycle_rf256; diff --git a/openair2/RRC/NR/nr_rrc_config.h b/openair2/RRC/NR/nr_rrc_config.h index 802d57428c..1db2d4a2f1 100644 --- a/openair2/RRC/NR/nr_rrc_config.h +++ b/openair2/RRC/NR/nr_rrc_config.h @@ -43,6 +43,7 @@ void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsc NR_TDD_UL_DL_ConfigCommon_t *tdd_UL_DL_ConfigurationCommon, int curr_bwp); void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay); +NR_SearchSpace_t *rrc_searchspace_config(bool is_common, int searchspaceid, int coresetid); void prepare_sim_uecap(NR_UE_NR_Capability_t *cap, NR_ServingCellConfigCommon_t *scc,