diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index d064b522b9..ef04daaad1 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -38,6 +38,7 @@ #include "assertions.h" #include "common/utils/utils.h" +#define MAX_SI_GROUPS 3 #define NR_MAX_PDSCH_TBS 3824 #define MAX_NUM_BEAM_PERIODS 4 #define MAX_BWP_SIZE 275 diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 1b5518f0bc..46e126ed97 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -936,10 +936,7 @@ static void update_mib_conf(NR_MIB_t *target, NR_MIB_t *source) target->intraFreqReselection = source->intraFreqReselection; } -void nr_rrc_mac_config_req_mib(module_id_t module_id, - int cc_idP, - NR_MIB_t *mib, - int sched_sib) +void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib, int sched_sib) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); int ret = pthread_mutex_lock(&mac->if_mutex); @@ -952,8 +949,8 @@ void nr_rrc_mac_config_req_mib(module_id_t module_id, mac->phy_config.CC_id = cc_idP; if (sched_sib == 1) mac->get_sib1 = true; - else if (sched_sib == 2) - mac->get_otherSI = true; + else if (sched_sib > 1) + mac->get_otherSI[sched_sib - 2] = true; nr_ue_decode_mib(mac, cc_idP); ret = pthread_mutex_unlock(&mac->if_mutex); AssertFatal(!ret, "mutex failed %d\n", ret); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 838d1989f0..3241235bd3 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -539,7 +539,7 @@ typedef struct NR_UE_MAC_INST_s { int servCellIndex; long physCellId; bool get_sib1; - bool get_otherSI; + bool get_otherSI[MAX_SI_GROUPS]; NR_MIB_t *mib; si_schedInfo_t si_SchedInfo; diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 6c744e8275..1ca4168b6f 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -56,7 +56,8 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) LOG_I(NR_MAC, "[UE%d] Initializing MAC\n", mac->ue_id); nr_ue_reset_sync_state(mac); mac->get_sib1 = false; - mac->get_otherSI = false; + for (int i = 0; i < MAX_SI_GROUPS; i++) + mac->get_otherSI[i] = false; memset(&mac->phy_config, 0, sizeof(mac->phy_config)); mac->si_SchedInfo.si_window_start = -1; mac->servCellIndex = 0; diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c index 1a816c64f6..34ef533884 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -375,7 +375,6 @@ bool search_space_monitoring_ocasion_other_si(NR_UE_MAC_INST_t *mac, if (((frame * slots_per_frame + slot - offset - i) % period) == 0) { int N = mac->ssb_list.nb_tx_ssb; int K = mac->ssb_list.nb_ssb_per_index[mac->mib_ssb]; - // numbering current frame and slot in terms of monitoring occasions in window int rel_slot = abs_slot - mac->si_SchedInfo.si_window_start; int current_monitor_occasion = (rel_slot % period) + (duration * rel_slot / period); @@ -399,43 +398,41 @@ bool is_window_valid(NR_UE_MAC_INST_t *mac, int window_slots, int abs_slot) return true; } -bool monitor_dci_for_other_SI(NR_UE_MAC_INST_t *mac, - const NR_SearchSpace_t *ss, - const int slots_per_frame, - const int frame, - const int slot) +static bool monitor_dci_for_other_SI(NR_UE_MAC_INST_t *mac, + const NR_SearchSpace_t *ss, + const int si_idx, + const int slots_per_frame, + const int frame, + const int slot) { // according to 5.2.2.3.2 in 331 const int abs_slot = frame * slots_per_frame + slot; - for (int i = 0; i < mac->si_SchedInfo.si_SchedInfo_list.count; i++) { - si_schedinfo_config_t *config = mac->si_SchedInfo.si_SchedInfo_list.array[i]; - int window_slots = 5 << mac->si_SchedInfo.si_WindowLength; - int x = (config->si_WindowPosition - 1) * window_slots; - int T = 8 << config->si_Periodicity; // radio frame periodicity - bool check_valid; - switch (config->type) { - case NR_SI_INFO : - if (mac->si_SchedInfo.si_window_start == -1) { - if ((frame % T) == (x / slots_per_frame) && (x % slots_per_frame == 0)) - mac->si_SchedInfo.si_window_start = abs_slot; // in terms of absolute slot number - } - check_valid = is_window_valid(mac, window_slots, abs_slot); - if (check_valid && search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame)) - return true; - break; - case NR_SI_INFO_v1700 : - if (mac->si_SchedInfo.si_window_start == -1) { - if ((frame % T == floor(x / slots_per_frame)) && (slot == x % slots_per_frame)) - mac->si_SchedInfo.si_window_start = abs_slot; - } - check_valid = is_window_valid(mac, window_slots, abs_slot); - if (check_valid && (config->si_WindowPosition - 1) == slot) - return search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame); - break; - default : - AssertFatal(false, "Invalid SI-SchedulingInfo case\n"); - } + si_schedinfo_config_t *config = mac->si_SchedInfo.si_SchedInfo_list.array[si_idx]; + int window_slots = 5 << mac->si_SchedInfo.si_WindowLength; + int x = (config->si_WindowPosition - 1) * window_slots; + int T = 8 << config->si_Periodicity; // radio frame periodicity + bool check_valid; + switch (config->type) { + case NR_SI_INFO : + if (mac->si_SchedInfo.si_window_start == -1) { + if ((frame % T) == (x / slots_per_frame) && (x % slots_per_frame == 0)) + mac->si_SchedInfo.si_window_start = abs_slot; // in terms of absolute slot number + } + check_valid = is_window_valid(mac, window_slots, abs_slot); + if (check_valid && search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame)) + return true; + break; + case NR_SI_INFO_v1700 : + if (mac->si_SchedInfo.si_window_start == -1) { + if ((frame % T == floor(x / slots_per_frame)) && (slot == x % slots_per_frame)) + mac->si_SchedInfo.si_window_start = abs_slot; + } + if (is_window_valid(mac, window_slots, abs_slot)) + return search_space_monitoring_ocasion_other_si(mac, ss, abs_slot, frame, slot, slots_per_frame); + break; + default : + AssertFatal(false, "Invalid SI-SchedulingInfo case\n"); } return false; } @@ -478,13 +475,15 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl config_dci_pdu(mac, dl_config, TYPE_SI_RNTI_, slot, mac->search_space_zero); } } - if (mac->get_otherSI) { + for (int i = 0; i < MAX_SI_GROUPS; i++) { + if (!mac->get_otherSI[i]) + continue; // If searchSpaceOtherSystemInformation is set to zero, // PDCCH monitoring occasions for SI message reception in SI-window // are same as PDCCH monitoring occasions for SIB1 const NR_SearchSpace_t *ss = pdcch_config->otherSI_SS ? pdcch_config->otherSI_SS : mac->search_space_zero; // TODO configure SI-window - if (monitor_dci_for_other_SI(mac, ss, slots_per_frame, frame, slot)) { + if (monitor_dci_for_other_SI(mac, ss, i, slots_per_frame, frame, slot)) { LOG_D(NR_MAC_DCI, "Monitoring DCI for other SIs in frame %d slot %d\n", frame, slot); config_dci_pdu(mac, dl_config, TYPE_SI_RNTI_, slot, ss); } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 995d987304..9d2f702a16 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -310,8 +310,12 @@ int8_t nr_ue_decode_BCCH_DL_SCH(NR_UE_MAC_INST_t *mac, if(ack_nack) { LOG_D(NR_MAC, "Decoding NR-BCCH-DL-SCH-Message (SIB1 or SI)\n"); nr_mac_rrc_data_ind_ue(mac->ue_id, cc_id, gNB_index, 0, 0, 0, mac->physCellId, 0, NR_BCCH_DL_SCH, (uint8_t *) pduP, pdu_len); - mac->get_sib1 = false; - mac->get_otherSI = false; + if (mac->get_sib1) + mac->get_sib1 = false; + for (int i = 0; i < MAX_SI_GROUPS; i++) { + if (mac->get_otherSI[i]) + mac->get_otherSI[i] = false; + } T(T_NRUE_MAC_DL_PDU_WITH_DATA, T_INT(SI_RNTI), T_INT(-1 /* frame, unavailable here */), @@ -742,8 +746,16 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac, LOG_W(MAC, "[%d.%d] Invalid frequency_domain_assignment. Possibly due to false DCI. Ignoring DCI!\n", frame, slot); return -1; } + dlsch_pdu->rb_offset = dlsch_pdu->start_rb + dlsch_pdu->BWPStart; - if (mac->get_sib1 || mac->get_otherSI) + bool otherSI = false; + for (int i = 0; i < MAX_SI_GROUPS; i++) { + if (mac->get_otherSI[i]) { + otherSI = true; + break; + } + } + if (mac->get_sib1 || otherSI) dlsch_pdu->rb_offset -= dlsch_pdu->BWPStart; /* TIME_DOM_RESOURCE_ASSIGNMENT */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index a00db6585c..39cb665c21 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -342,7 +342,7 @@ static uint32_t get_tbs_bch(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, return TBS; } -static uint32_t schedule_control_sib1(module_id_t module_id, +static uint32_t schedule_control_sib1(gNB_MAC_INST *gNB_mac, int CC_id, NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, int time_domain_allocation, @@ -352,7 +352,6 @@ static uint32_t schedule_control_sib1(module_id_t module_id, int beam, uint16_t num_total_bytes) { - gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; AssertFatal(gNB_mac->sched_ctrlCommon, "sched_ctrlCommon is NULL\n"); NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id]; uint16_t *vrb_map = cc->vrb_map[beam]; @@ -625,7 +624,8 @@ void schedule_nr_sib1(module_id_t module_idP, NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0]; // Configure sched_ctrlCommon for SIB1 - uint32_t TBS = schedule_control_sib1(module_idP, CC_id, + uint32_t TBS = schedule_control_sib1(gNB_mac, + CC_id, type0_PDCCH_CSS_config, time_domain_allocation, &dmrs_parms, @@ -709,8 +709,11 @@ static void other_sib_sched_control(module_id_t module_idP, int n_slots_frame = gNB_mac->frame_structure.numb_slots_frame; NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frame, slot, beam_index, n_slots_frame); AssertFatal(beam.idx >= 0, "Cannot allocate otherSIB corresponding for SSB number %d in any available beam\n", beam_index); - LOG_D(NR_MAC, "(%d.%d) otherSIB transmission for ssb number %d\n", frame, slot, beam_index); + LOG_D(NR_MAC, "(%d.%d) otherSIB payload %d transmission for ssb number %d\n", frame, slot, payload_idx, beam_index); + NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0]; + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[cc->ssb_index[beam_index]]; + AssertFatal(gNB_mac->sched_ctrlCommon, "sched_ctrlCommon is NULL\n"); NR_PDSCH_ConfigCommon_t *pdsch_ConfigCommon = scc->downlinkConfigCommon->initialDownlinkBWP->pdsch_ConfigCommon->choice.setup; int time_domain_allocation = 1; NR_tda_info_t tda_info = set_tda_info_from_list(pdsch_ConfigCommon->pdsch_TimeDomainAllocationList, time_domain_allocation); @@ -728,8 +731,6 @@ static void other_sib_sched_control(module_id_t module_idP, AssertFatal(nr_of_candidates > 0, "nr_of_candidates is 0\n"); NR_ControlResourceSet_t *coreset = get_coreset(gNB_mac, scc, NULL, ss, NR_SearchSpace__searchSpaceType_PR_common); - NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0]; - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[cc->ssb_index[beam_index]]; if (!gNB_mac->sched_pdcch_otherSI) { gNB_mac->sched_pdcch_otherSI = calloc(1, sizeof(*gNB_mac->sched_pdcch_otherSI)); *gNB_mac->sched_pdcch_otherSI = set_pdcch_structure(gNB_mac, ss, coreset, scc, NULL, type0_PDCCH_CSS_config); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index e321c1dd5b..30c0e548a7 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -282,28 +282,34 @@ static void nr_rrc_ue_prepare_RRCSetupRequest(NR_UE_RRC_INST_t *rrc) } static void nr_rrc_configure_default_SI(NR_UE_RRC_SI_INFO *SI_info, - struct NR_SI_SchedulingInfo *si_SchedulingInfo, - struct NR_SI_SchedulingInfo_v1700 *si_SchedulingInfo_v1700) + NR_SI_SchedulingInfo_t *si_SchedulingInfo, + NR_SI_SchedulingInfo_v1700_t *si_SchedulingInfo_v1700) { + for (int i = 0; i < MAX_SI_GROUPS; i++) + SI_info->default_otherSI_map[i] = 0; + int nb_groups = 0; if (si_SchedulingInfo) { - SI_info->default_otherSI_map = 0; - for (int i = 0; i < si_SchedulingInfo->schedulingInfoList.list.count; i++) { - struct NR_SchedulingInfo *schedulingInfo = si_SchedulingInfo->schedulingInfoList.list.array[i]; + nb_groups = si_SchedulingInfo->schedulingInfoList.list.count; + AssertFatal(nb_groups <= MAX_SI_GROUPS, "Exceeding max number of SI groups configured\n"); + for (int i = 0; i < nb_groups; i++) { + NR_SchedulingInfo_t *schedulingInfo = si_SchedulingInfo->schedulingInfoList.list.array[i]; for (int j = 0; j < schedulingInfo->sib_MappingInfo.list.count; j++) { - struct NR_SIB_TypeInfo *sib_Type = schedulingInfo->sib_MappingInfo.list.array[j]; - SI_info->default_otherSI_map |= 1 << sib_Type->type; + NR_SIB_TypeInfo_t *sib_Type = schedulingInfo->sib_MappingInfo.list.array[j]; + SI_info->default_otherSI_map[i] |= 1 << sib_Type->type; } } } if (si_SchedulingInfo_v1700) { - SI_info->SInfo_r17.default_otherSI_map_r17 = 0; + int start_idx = nb_groups; + nb_groups += si_SchedulingInfo_v1700->schedulingInfoList2_r17.list.count; + AssertFatal(nb_groups <= MAX_SI_GROUPS, "Exceeding max number of SI groups configured\n"); for (int i = 0; i < si_SchedulingInfo_v1700->schedulingInfoList2_r17.list.count; i++) { - struct NR_SchedulingInfo2_r17 *schedulingInfo2 = si_SchedulingInfo_v1700->schedulingInfoList2_r17.list.array[i]; + NR_SchedulingInfo2_r17_t *schedulingInfo2 = si_SchedulingInfo_v1700->schedulingInfoList2_r17.list.array[i]; for (int j = 0; j < schedulingInfo2->sib_MappingInfo_r17.list.count; j++) { - struct NR_SIB_TypeInfo_v1700 *sib_TypeInfo_v1700 = schedulingInfo2->sib_MappingInfo_r17.list.array[j]; + NR_SIB_TypeInfo_v1700_t *sib_TypeInfo_v1700 = schedulingInfo2->sib_MappingInfo_r17.list.array[j]; if (sib_TypeInfo_v1700->sibType_r17.present == NR_SIB_TypeInfo_v1700__sibType_r17_PR_type1_r17) { - SI_info->SInfo_r17.default_otherSI_map_r17 |= 1 << sib_TypeInfo_v1700->sibType_r17.choice.type1_r17; + SI_info->default_otherSI_map[start_idx + i] |= 1 << (sib_TypeInfo_v1700->sibType_r17.choice.type1_r17 + 13); } } } @@ -318,11 +324,14 @@ static bool verify_NTN_access(const NR_UE_RRC_SI_INFO *SI_info, const NR_SIB1_v1 && *sib1_v1700->cellBarredNTN_r17 == NR_SIB1_v1700_IEs__cellBarredNTN_r17_notBarred) ntn_access = true; - uint32_t sib19_mask = 1 << NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType19; - int sib19_present = SI_info->SInfo_r17.default_otherSI_map_r17 & sib19_mask; - + uint32_t sib19_mask = 1 << (NR_SIB_TypeInfo_v1700__sibType_r17__type1_r17_sibType19 + 13); + int sib19_present = false; + for (int i = 0; i < MAX_SI_GROUPS; i++) { + sib19_present = SI_info->default_otherSI_map[i] & sib19_mask; + if (sib19_present) + break; + } AssertFatal(!ntn_access || sib19_present, "NTN cell, but SIB19 not configured.\n"); - return ntn_access && sib19_present; } @@ -783,7 +792,7 @@ bool check_si_validity_r17(NR_UE_RRC_SI_INFO_r17 *SI_info, int si_type) return true; } -int check_si_status(NR_UE_RRC_SI_INFO *SI_info) +static int check_si_status(NR_UE_RRC_SI_INFO *SI_info) { // schedule reception of SIB1 if RRC doesn't have it if (SI_info->sib1_validity == SIB_NOT_VALID) { @@ -791,31 +800,22 @@ int check_si_status(NR_UE_RRC_SI_INFO *SI_info) return 1; } else { - if (SI_info->default_otherSI_map) { + for (int j = 0; j < MAX_SI_GROUPS; j++) { + if (!SI_info->default_otherSI_map[j]) + continue; // Check if RRC has configured default SI - // from SIB2 to SIB14 as current ASN1 version // TODO can be used for on demand SI when (if) implemented - for (int i = 2; i < 15; i++) { - int si_index = i - 2; - if ((SI_info->default_otherSI_map >> si_index) & 0x01) { - // if RRC has no valid version of one of the default configured SI - // Then schedule reception of otherSI - if (!check_si_validity(SI_info, si_index)) - return 2; - } - } - } - - // Check if RRC has configured default SI - // from SIB15 to SIB21 as current r17 version - if (SI_info->SInfo_r17.default_otherSI_map_r17) { - for (int i = 15; i < 22; i++) { - int si_index = i - 15; - if ((SI_info->SInfo_r17.default_otherSI_map_r17 >> si_index) & 0x01) { - // if RRC has no valid version of one of the default configured SI - // Then schedule reception of otherSI - if (!check_si_validity_r17(&SI_info->SInfo_r17, si_index)) - return 2; + for (int i = 2; i < 22; i++) { + if (!((SI_info->default_otherSI_map[j] >> (i - 2)) & 0x01)) + continue; + // if RRC has no valid version of one of the default configured SI + // Then schedule reception of otherSI + if (i < 15) { + if (!check_si_validity(SI_info, i - 2)) + return 2 + j; + } else { + if (!check_si_validity_r17(&SI_info->SInfo_r17, i - 15)) + return 2 + j; } } } @@ -862,8 +862,10 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc, } int get_sib = 0; - if (IS_SA_MODE(get_softmodem_params()) && bcch_message->message.present == NR_BCCH_BCH_MessageType_PR_mib - && bcch_message->message.choice.mib->cellBarred == NR_MIB__cellBarred_notBarred && rrc->nrRrcState != RRC_STATE_DETACH_NR) { + if (IS_SA_MODE(get_softmodem_params()) + && bcch_message->message.present == NR_BCCH_BCH_MessageType_PR_mib + && bcch_message->message.choice.mib->cellBarred == NR_MIB__cellBarred_notBarred + && rrc->nrRrcState != RRC_STATE_DETACH_NR) { NR_UE_RRC_SI_INFO *SI_info = &rrc->perNB[gNB_index].SInfo; // to schedule MAC to get SI if required get_sib = check_si_status(SI_info); diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index ee46a343d7..c9b14b3ae5 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -111,7 +111,6 @@ typedef enum { } SIB_validity_t; typedef struct UE_RRC_SI_INFO_NR_r17_s { - uint32_t default_otherSI_map_r17; SIB_validity_t sib15_validity; NR_timer_t sib15_timer; SIB_validity_t sib16_validity; @@ -129,7 +128,7 @@ typedef struct UE_RRC_SI_INFO_NR_r17_s { } NR_UE_RRC_SI_INFO_r17; typedef struct UE_RRC_SI_INFO_NR_s { - uint32_t default_otherSI_map; + uint32_t default_otherSI_map[MAX_SI_GROUPS]; SIB_validity_t sib1_validity; NR_timer_t sib1_timer; SIB_validity_t sib2_validity;