diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index 21e2f5ca8db8b6f4626f0c7287e97f85e555b90f..454faf1a1ec1677f515e3c961f5d14409d551520 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -136,7 +136,6 @@ These modes of operation are supported: - evalution of RSRP report - evaluation of CQI report - MAC scheduling of SR reception -- Support of up to 16 UEs (can be increased to 32) - Intra-frequency handover ## gNB RLC @@ -247,6 +246,11 @@ These modes of operation are supported: - Interfaces with PDCP and RLC for data send/receive at the CU and DU respectively (F1-U interface) - Interface with SDAP for data send/receive, capture of GTP-U Optional Header, GTP-U Extension Header and PDU Session Container. +## Number of supported UEs + +* 16 by default (as defined in `MAX_MOBILES_PER_GNB`) +* up to 64 if the configured bandwidth is sufficient (at leat 40 MHz) + # OpenAirInterface 5G-NR UE Feature Set # ## NR UE PHY Layer ## diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 798ec5ce4e8851f49a3e95731fcb5031382288de..e70d7b66ebaa1a39dd2fb8da5d4a7ee36e111d6b 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -56,6 +56,7 @@ #include "utils.h" #include "xer_encoder.h" +#define PUCCH2_SIZE 8 const uint8_t slotsperframe[5] = {10, 20, 40, 80, 160}; static NR_BWP_t clone_generic_parameters(const NR_BWP_t *gp) @@ -187,6 +188,24 @@ static NR_PUSCH_Config_t *clone_pusch_config(const NR_PUSCH_Config_t *pc) return clone; } +static int get_nb_pucch2_per_slot(const NR_ServingCellConfigCommon_t *scc, int bwp_size) +{ + const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; + const int n_slots_frame = slotsperframe[*scc->ssbSubcarrierSpacing]; + int ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0) : n_slots_frame; + int n_slots_period = tdd ? n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; + int max_meas_report_period = 320; // slots + int max_csi_reports = MAX_MOBILES_PER_GNB << 1; // 2 reports per UE (RSRP and RI-PMI-CQI) + int available_report_occasions = max_meas_report_period * ul_slots_period / n_slots_period; + int nb_pucch2 = (max_csi_reports / (available_report_occasions + 1)) + 1; + // in current implementation we need (nb_pucch2 * PUCCH2_SIZE) prbs for PUCCH2 + // and MAX_MOBILES_PER_GNB prbs for PUCCH1 + AssertFatal((nb_pucch2 * PUCCH2_SIZE) + MAX_MOBILES_PER_GNB <= bwp_size, + "Cannot allocate all required PUCCH resources for max number of %d UEs in BWP with %d PRBs\n", + MAX_MOBILES_PER_GNB, bwp_size); + return nb_pucch2; +} + NR_SearchSpace_t *rrc_searchspace_config(bool is_common, int searchspaceid, int coresetid) { @@ -295,7 +314,7 @@ static uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc) static int set_ideal_period(const int n_slots_period, const int n_ul_slots_period) { - return MAX_MOBILES_PER_GNB * 2 * n_slots_period / n_ul_slots_period; // 2 reports per UE + return MAX_MOBILES_PER_GNB * 2 * n_slots_period / n_ul_slots_period; // 2 reports per UE (RSRP and RI-PMI-CQI) } static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0, @@ -307,7 +326,6 @@ static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0, nzpcsi0->periodicityAndOffset = calloc(1,sizeof(*nzpcsi0->periodicityAndOffset)); // TODO ideal period to be set according to estimation by the gNB on how fast the channel changes const int offset = nb_slots_per_period * id; - if (ideal_period < 5) { nzpcsi0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots4; nzpcsi0->periodicityAndOffset->choice.slots4 = offset; @@ -974,7 +992,11 @@ static void set_dl_DataToUL_ACK(NR_PUCCH_Config_t *pucch_Config, int min_feedbac } // PUCCH resource set 0 for configuration with O_uci <= 2 bits and/or a positive or negative SR (section 9.2.1 of 38.213) -static void config_pucch_resset0(NR_PUCCH_Config_t *pucch_Config, int uid, int curr_bwp, const NR_UE_NR_Capability_t *uecap) +static void config_pucch_resset0(NR_PUCCH_Config_t *pucch_Config, + int uid, + int curr_bwp, + int num_pucch2, + const NR_UE_NR_Capability_t *uecap) { NR_PUCCH_ResourceSet_t *pucchresset = calloc(1,sizeof(*pucchresset)); pucchresset->pucch_ResourceSetId = 0; @@ -990,7 +1012,7 @@ static void config_pucch_resset0(NR_PUCCH_Config_t *pucch_Config, int uid, int c NR_PUCCH_Resource_t *pucchres0 = calloc(1,sizeof(*pucchres0)); pucchres0->pucch_ResourceId = *pucchid; - pucchres0->startingPRB = 8 + uid; + pucchres0->startingPRB = (PUCCH2_SIZE * num_pucch2) + uid; AssertFatal(pucchres0->startingPRB < curr_bwp, "Not enough resources in current BWP (size %d) to allocate uid %d\n", curr_bwp, uid); pucchres0->intraSlotFrequencyHopping = NULL; pucchres0->secondHopPRB = NULL; @@ -1006,7 +1028,10 @@ static void config_pucch_resset0(NR_PUCCH_Config_t *pucch_Config, int uid, int c // PUCCH resource set 1 for configuration with O_uci > 2 bits (currently format2) -static void config_pucch_resset1(NR_PUCCH_Config_t *pucch_Config, const NR_UE_NR_Capability_t *uecap) +static void config_pucch_resset1(NR_PUCCH_Config_t *pucch_Config, + int uid, + int num_pucch2, + const NR_UE_NR_Capability_t *uecap) { NR_PUCCH_ResourceSet_t *pucchresset=calloc(1,sizeof(*pucchresset)); pucchresset->pucch_ResourceSetId = 1; @@ -1022,12 +1047,12 @@ static void config_pucch_resset1(NR_PUCCH_Config_t *pucch_Config, const NR_UE_NR NR_PUCCH_Resource_t *pucchres2 = calloc(1,sizeof(*pucchres2)); pucchres2->pucch_ResourceId = *pucchressetid; - pucchres2->startingPRB = 0; + pucchres2->startingPRB = PUCCH2_SIZE * (uid % num_pucch2); pucchres2->intraSlotFrequencyHopping = NULL; pucchres2->secondHopPRB = NULL; pucchres2->format.present = NR_PUCCH_Resource__format_PR_format2; pucchres2->format.choice.format2 = calloc(1,sizeof(*pucchres2->format.choice.format2)); - pucchres2->format.choice.format2->nrofPRBs = 8; + pucchres2->format.choice.format2->nrofPRBs = PUCCH2_SIZE; pucchres2->format.choice.format2->nrofSymbols = 1; pucchres2->format.choice.format2->startingSymbolIndex = 13; asn1cSeqAdd(&pucch_Config->resourceToAddModList->list,pucchres2); @@ -1501,8 +1526,9 @@ static void config_uplinkBWP(NR_BWP_Uplink_t *ubwp, pucch_Config->resourceSetToReleaseList = NULL; pucch_Config->resourceToAddModList = calloc(1,sizeof(*pucch_Config->resourceToAddModList)); pucch_Config->resourceToReleaseList = NULL; - config_pucch_resset0(pucch_Config, uid, curr_bwp, uecap); - config_pucch_resset1(pucch_Config, uecap); + int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp); + config_pucch_resset0(pucch_Config, uid, curr_bwp, num_pucch2, uecap); + config_pucch_resset1(pucch_Config, uid, num_pucch2, uecap); set_pucch_power_config(pucch_Config, configuration->do_CSIRS); scheduling_request_config(scc, pucch_Config, ubwp->bwp_Common->genericParameters.subcarrierSpacing); set_dl_DataToUL_ACK(pucch_Config, configuration->minRXTXTIME, ubwp->bwp_Common->genericParameters.subcarrierSpacing); @@ -1545,7 +1571,11 @@ static void set_phr_config(NR_MAC_CellGroupConfig_t *mac_CellGroupConfig) mac_CellGroupConfig->phr_Config->choice.setup->phr_Tx_PowerFactorChange = NR_PHR_Config__phr_Tx_PowerFactorChange_dB1; } -static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc, NR_CSI_ReportConfig_t *csirep, int uid, bool is_rsrp) +static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc, + NR_CSI_ReportConfig_t *csirep, + int uid, + int curr_bwp, + bool is_rsrp) { const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; const int n_slots_frame = slotsperframe[*scc->ssbSubcarrierSpacing]; @@ -1553,7 +1583,8 @@ static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc, NR const int n_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; const int ideal_period = set_ideal_period(n_slots_period, n_ul_slots_period); const int first_ul_slot_period = tdd ? get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols) : 0; - const int idx = (uid << 1) + is_rsrp; + const int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp); + const int idx = (uid * 2 / num_pucch2) + is_rsrp; const int offset = first_ul_slot_period + idx % n_ul_slots_period + (idx / n_ul_slots_period) * n_slots_period; AssertFatal(offset < 320, "Not enough UL slots to accomodate all possible UEs. Need to rework the implementation\n"); @@ -1703,7 +1734,8 @@ static void config_csi_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig, const nr_pdsch_AntennaPorts_t *antennaports, const int max_layers, int rep_id, - int uid) + int uid, + int curr_bwp) { int resource_id = -1; int im_id = -1; @@ -1732,7 +1764,7 @@ static void config_csi_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig, csirep->nzp_CSI_RS_ResourcesForInterference = NULL; csirep->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic; csirep->reportConfigType.choice.periodic = calloc(1, sizeof(*csirep->reportConfigType.choice.periodic)); - set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, false); + set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, curr_bwp, false); asn1cSeqAdd(&csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list, pucchcsires); csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_cri_RI_PMI_CQI; csirep->reportQuantity.choice.cri_RI_PMI_CQI = (NULL_t)0; @@ -1767,6 +1799,7 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig, int do_csi, // if rsrp is based on CSI or SSB int rep_id, int uid, + int curr_bwp, int num_antenna_ports) { int resource_id = -1; @@ -1793,7 +1826,7 @@ static void config_rsrp_meas_report(NR_CSI_MeasConfig_t *csi_MeasConfig, csirep->nzp_CSI_RS_ResourcesForInterference = NULL; csirep->reportConfigType.present = NR_CSI_ReportConfig__reportConfigType_PR_periodic; csirep->reportConfigType.choice.periodic = calloc(1, sizeof(*csirep->reportConfigType.choice.periodic)); - set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, true); + set_csi_meas_periodicity(servingcellconfigcommon, csirep, uid, curr_bwp, true); asn1cSeqAdd(&csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list, pucchcsires); if (do_csi && num_antenna_ports < 4) { csirep->reportQuantity.present = NR_CSI_ReportConfig__reportQuantity_PR_cri_RSRP; @@ -2848,8 +2881,9 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, pucch_Config->resourceSetToReleaseList = NULL; pucch_Config->resourceToAddModList = calloc(1, sizeof(*pucch_Config->resourceToAddModList)); pucch_Config->resourceToReleaseList = NULL; - config_pucch_resset0(pucch_Config, uid, curr_bwp, NULL); - config_pucch_resset1(pucch_Config, NULL); + int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp); + config_pucch_resset0(pucch_Config, uid, curr_bwp, num_pucch2, NULL); + config_pucch_resset1(pucch_Config, uid, num_pucch2, NULL); set_pucch_power_config(pucch_Config, configuration->do_CSIRS); initialUplinkBWP->pusch_Config = config_pusch(NULL, configuration->use_deltaMCS, scc, NULL); @@ -3060,12 +3094,13 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, &configuration->pdsch_AntennaPorts, *pdsch_servingcellconfig->ext1->maxMIMO_Layers, bwp_id, - uid); + uid, + curr_bwp); } NR_PUCCH_CSI_Resource_t *pucchrsrp = calloc(1, sizeof(*pucchrsrp)); pucchrsrp->uplinkBandwidthPartId = bwp_id; pucchrsrp->pucch_Resource = pucch_Resource; - config_rsrp_meas_report(csi_MeasConfig, scc, pucchrsrp, configuration->do_CSIRS, bwp_id + 10, uid, pdsch_AntennaPorts); + config_rsrp_meas_report(csi_MeasConfig, scc, pucchrsrp, configuration->do_CSIRS, bwp_id + 10, uid, curr_bwp, pdsch_AntennaPorts); } fill_harq_IEs(SpCellConfig->spCellConfigDedicated, configuration->num_dlharq, configuration->num_ulharq); @@ -3561,8 +3596,23 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC pucchcsires1->uplinkBandwidthPartId = bwp->bwp_Id; pucchcsires1->pucch_Resource = 2; - config_csi_meas_report(csi_MeasConfig, servingcellconfigcommon, pucchcsires1, bwp->bwp_Dedicated->pdsch_Config, pdschap, *pdsch_servingcellconfig->ext1->maxMIMO_Layers, bwp->bwp_Id, uid); - config_rsrp_meas_report(csi_MeasConfig, servingcellconfigcommon, pucchcsires1, do_csirs, bwp->bwp_Id + 10, uid, dl_antenna_ports); + config_csi_meas_report(csi_MeasConfig, + servingcellconfigcommon, + pucchcsires1, + bwp->bwp_Dedicated->pdsch_Config, + pdschap, + *pdsch_servingcellconfig->ext1->maxMIMO_Layers, + bwp->bwp_Id, + uid, + curr_bwp); + config_rsrp_meas_report(csi_MeasConfig, + servingcellconfigcommon, + pucchcsires1, + do_csirs, + bwp->bwp_Id + 10, + uid, + curr_bwp, + dl_antenna_ports); } secondaryCellGroup->spCellConfig->spCellConfigDedicated->sCellDeactivationTimer = NULL; secondaryCellGroup->spCellConfig->spCellConfigDedicated->crossCarrierSchedulingConfig = NULL;