From 2e80700d788d640182ea46da78cd550909244d06 Mon Sep 17 00:00:00 2001 From: alexjiao Date: Wed, 3 Sep 2025 19:32:14 +0800 Subject: [PATCH 1/7] Fix for servedRadioBearer to be NULL in RLC Bearer Config --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index f592423c5a..8951ef65e5 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -886,7 +886,8 @@ static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac, nr_lcid_rb_t rb) { NR_LC_SCHEDULING_INFO *lc_sched_info = get_scheduling_info_from_lcid(mac, lc_info->lcid); - lc_info->rb = rb; + if (rb.type != NR_LCID_NONE) + lc_info->rb = rb; lc_info->rb_suspended = false; if (rb.type == NR_LCID_SRB && !mac_lc_config->ul_SpecificParameters) { // release configuration and reset to default @@ -914,6 +915,12 @@ static void nr_configure_lc_config(NR_UE_MAC_INST_t *mac, static nr_lcid_rb_t configure_lcid_rb(NR_RLC_BearerConfig_t *rlc_bearer) { nr_lcid_rb_t rb; + if (!rlc_bearer->servedRadioBearer) { + LOG_W(NR_MAC, "RLC bearer config does not contain servedRadioBearer.\n"); + rb.type = NR_LCID_NONE; + return rb; + } + if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity) { rb.type = NR_LCID_SRB; rb.choice.srb_id = rlc_bearer->servedRadioBearer->choice.srb_Identity; @@ -953,8 +960,6 @@ static void configure_logicalChannelBearer(NR_UE_MAC_INST_t *mac, for (int i = 0; i < rlc_toadd_list->list.count; i++) { NR_RLC_BearerConfig_t *rlc_bearer = rlc_toadd_list->list.array[i]; nr_lcid_rb_t rb = configure_lcid_rb(rlc_bearer); - if (rb.type == NR_LCID_NONE) - continue; int lc_identity = rlc_bearer->logicalChannelIdentity; NR_LogicalChannelConfig_t *mac_lc_config = rlc_bearer->mac_LogicalChannelConfig; int j; From e454fc41d1e375bf5906c91a59c42a6cadd0840f Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 8 Sep 2025 10:59:11 +0200 Subject: [PATCH 2/7] Trigger MSG3 with C-RNTI in MAC CE if CBRA with newUE-Identity (handover) --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 8951ef65e5..729f0b4763 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1978,12 +1978,23 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac, LOG_I(NR_MAC, "Configuring CRNTI %x\n", mac->crnti); RA_config_t *ra = &mac->ra; + bool is_cfra = false; if (reconfWithSync->rach_ConfigDedicated) { AssertFatal(reconfWithSync->rach_ConfigDedicated->present == NR_ReconfigurationWithSync__rach_ConfigDedicated_PR_uplink, "RACH on supplementaryUplink not supported\n"); + NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = reconfWithSync->rach_ConfigDedicated->choice.uplink; + if (rach_ConfigDedicated->cfra) + is_cfra = true; + if (rach_ConfigDedicated->ext1 && rach_ConfigDedicated->ext1->cfra_TwoStep_r16) + is_cfra = true; UPDATE_IE(ra->rach_ConfigDedicated, reconfWithSync->rach_ConfigDedicated->choice.uplink, NR_RACH_ConfigDedicated_t); } + // in case of CBRA and reconfiguration with sync (handover) + // the UE sends MSG3 with C-RNTI to identify itself + if (!is_cfra) + mac->msg3_C_RNTI = true; + if (reconfWithSync->spCellConfigCommon) { NR_ServingCellConfigCommon_t *scc = reconfWithSync->spCellConfigCommon; if (scc->physCellId) From d56945e45ede4aca697b6616bdb81c09ef649f2a Mon Sep 17 00:00:00 2001 From: alexjiao Date: Fri, 5 Sep 2025 22:30:10 +0800 Subject: [PATCH 3/7] Monitor dedicated search spaces for DCIs after C-RNTI MAC-CE in Msg3 is sent --- openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c | 9 +++++++++ 1 file changed, 9 insertions(+) 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 8a2074422e..421720d1c7 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c @@ -483,6 +483,15 @@ void ue_dci_configuration(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_request_t *dl } config_dci_pdu(mac, dl_config, rnti_type, slot, ra_SS); } + // If Msg3 has C-RNTI MAC CE, also monitor dedicated search spaces during contention resolution + // according to TS 38.321 section 5.1.5 + if (ra->ra_state == nrRA_WAIT_CONTENTION_RESOLUTION && mac->msg3_C_RNTI) { + for (int i = 0; i < pdcch_config->list_SS.count; i++) { + NR_SearchSpace_t *ss = pdcch_config->list_SS.array[i]; + if (is_ss_monitor_occasion(frame, slot, slots_per_frame, ss)) + config_dci_pdu(mac, dl_config, TYPE_C_RNTI_, slot, ss); + } + } } else if (mac->state == UE_CONNECTED) { /* In RRC Connected state, the UE monitors for fallback DCI with C-RNTI in common and UE-specific SS. From 56f20d49bcf069c20720ad4da2903e24db866359 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 8 Sep 2025 15:03:53 +0200 Subject: [PATCH 4/7] improve handling of ssb_perRACH_OccasionAndCB_PreamblesPerSSB according to need code (also removing unused FAPI element ssb_per_rach) --- .../nfapi/public_inc/fapi_nr_ue_interface.h | 1 - openair2/LAYER2/NR_MAC_UE/config_ue.c | 14 +++++++------- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 2 ++ openair2/LAYER2/NR_MAC_UE/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c | 8 +++----- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index faebaffc6f..79d281c769 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -697,7 +697,6 @@ typedef struct uint8_t restricted_set_config;//PRACH restricted set config Value: 0: unrestricted 1: restricted set type A 2: restricted set type B uint8_t num_prach_fd_occasions;//Corresponds to the parameter 𝑀 in [38.211, sec 6.3.3.2] which equals the higher layer parameter msg1FDM Value: 1,2,4,8 fapi_nr_num_prach_fd_occasions_t* num_prach_fd_occasions_list; - uint8_t ssb_per_rach;//SSB-per-RACH-occasion Value: 0: 1/8 1:1/4, 2:1/2 3:1 4:2 5:4, 6:8 7:16 uint8_t prach_multiple_carriers_in_a_band;//0 = disabled 1 = enabled uint8_t root_seq_computed; // flag set and used only in PHY to indicate if table is computed with this config diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 729f0b4763..192b0a5111 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -262,8 +262,6 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo mac->frequency_range); //prach_fd_occasion->num_unused_root_sequences = ??? } - cfg->prach_config.ssb_per_rach = rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present-1; - } // computes round-trip-time between ue and sat based on SIB19 ephemeris data @@ -547,7 +545,6 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t prach_fd_occasion->num_root_sequences = compute_nr_root_seq(rach_ConfigCommon, nb_preambles, frame_type, mac->frequency_range); - cfg->prach_config.ssb_per_rach = rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present - 1; // prach_fd_occasion->num_unused_root_sequences = ??? } } @@ -1718,10 +1715,13 @@ static void configure_common_BWP_ul(NR_UE_MAC_INST_t *mac, int bwp_id, NR_BWP_Up mac->sc_info.initial_ul_BWPStart = bwp->BWPStart; } if (ul_common->rach_ConfigCommon) { - HANDLE_SETUPRELEASE_DIRECT(bwp->rach_ConfigCommon, - ul_common->rach_ConfigCommon, - NR_RACH_ConfigCommon_t, - asn_DEF_NR_RACH_ConfigCommon); + // ssb_perRACH_OccasionAndCB_PreamblesPerSSB is need M + // if NULL we need to maintain the information + NR_SetupRelease_RACH_ConfigCommon_t *rachcommon = ul_common->rach_ConfigCommon; + if (rachcommon->present == NR_SetupRelease_RACH_ConfigCommon_PR_setup + && rachcommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB) + mac->ssb_ro_preambles = get_ssb_ro_preambles_4step(rachcommon->choice.setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB); + HANDLE_SETUPRELEASE_DIRECT(bwp->rach_ConfigCommon, rachcommon, NR_RACH_ConfigCommon_t, asn_DEF_NR_RACH_ConfigCommon); } if (ul_common->ext1 && ul_common->ext1->msgA_ConfigCommon_r16) { HANDLE_SETUPRELEASE_DIRECT(bwp->msgA_ConfigCommon_r16, diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index b43937d362..fd917c5295 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -148,6 +148,7 @@ // Define the UE L2 states with X-Macro #define NR_UE_L2_STATES \ UE_STATE(UE_NOT_SYNC) \ + UE_STATE(UE_NOT_SYNC_RECONF) \ UE_STATE(UE_BARRED) \ UE_STATE(UE_RECEIVING_SIB) \ UE_STATE(UE_PERFORMING_RA) \ @@ -639,6 +640,7 @@ typedef struct NR_UE_MAC_INST_s { NR_SSB_meas_t ssb_measurements[MAX_NB_SSB]; NR_CSIRS_meas_t csirs_measurements; + ssb_ro_preambles_t ssb_ro_preambles; dci_pdu_rel15_t def_dci_pdu_rel15[NR_MAX_SLOTS_PER_FRAME][8]; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 4897a8fab8..aee55e4883 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -360,5 +360,5 @@ int sl_nr_ue_slot_select(const sl_nr_phy_config_request_t *cfg, int nr_slot, uin void nr_ue_sidelink_scheduler(nr_sidelink_indication_t *sl_ind, NR_UE_MAC_INST_t *mac); NR_SearchSpace_t *get_common_search_space(const NR_UE_MAC_INST_t *mac, const NR_SearchSpaceId_t ss_id); - +ssb_ro_preambles_t get_ssb_ro_preambles_4step(struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *config); #endif diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 0dae34eda7..13288a9c8d 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -190,7 +190,7 @@ static void select_preamble_group(NR_UE_MAC_INST_t *mac) // else if Msg3 is being retransmitted, we keep what used in first transmission of Msg3 } -static ssb_ro_preambles_t get_ssb_ro_preambles_4step(struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *config) +ssb_ro_preambles_t get_ssb_ro_preambles_4step(struct NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB *config) { ssb_ro_preambles_t ret = {0}; switch (config->present) { @@ -293,9 +293,7 @@ static void config_preamble_index(NR_UE_MAC_INST_t *mac) bool groupBconfigured = false; int preamb_ga = 0; if (ra->ra_type == RA_4_STEP) { - AssertFatal(nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB, - "Not expeting ssb_perRACH_OccasionAndCB_PreamblesPerSSB to be NULL here\n"); - ra->ssb_ro_config = get_ssb_ro_preambles_4step(nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB); + ra->ssb_ro_config = mac->ssb_ro_preambles; if (nr_rach_ConfigCommon->totalNumberOfRA_Preambles) nb_of_preambles = *nr_rach_ConfigCommon->totalNumberOfRA_Preambles; // Amongst the contention-based Random Access Preambles associated with an SSB the first numberOfRA-PreamblesGroupA @@ -321,7 +319,7 @@ static void config_preamble_index(NR_UE_MAC_INST_t *mac) if (twostep->msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16) ra->ssb_ro_config = get_ssb_ro_preambles_2step(twostep->msgA_SSB_PerRACH_OccasionAndCB_PreamblesPerSSB_r16); else - ra->ssb_ro_config = get_ssb_ro_preambles_4step(nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB); + ra->ssb_ro_config = mac->ssb_ro_preambles; if (twostep->msgA_TotalNumberOfRA_Preambles_r16) nb_of_preambles = *twostep->msgA_TotalNumberOfRA_Preambles_r16; } From 9c8274f6bd186f39fd3c7019354612af18ac3b58 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 12 Sep 2025 15:51:14 +0200 Subject: [PATCH 5/7] separate RRC to MAC message to trigger SIB scheduling --- openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- openair2/COMMON/rrc_messages_types.h | 7 +++++- openair2/LAYER2/NR_MAC_UE/config_ue.c | 32 ++++++++++++++------------- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 4 ++-- openair2/RRC/NR_UE/L2_interface_ue.c | 4 +++- openair2/RRC/NR_UE/rrc_UE.c | 10 ++++++--- 6 files changed, 36 insertions(+), 23 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 82984657d3..16ff94dd47 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -955,7 +955,7 @@ int main(int argc, char **argv) //Configure UE NR_BCCH_BCH_Message_t *mib = get_new_MIB_NR(scc); - nr_rrc_mac_config_req_mib(0, 0, mib->message.choice.mib, false, false); + nr_rrc_mac_config_req_mib(0, 0, mib->message.choice.mib, false); nr_rrc_mac_config_req_cg(0, 0, UE_CellGroup, UE_Capability_nr); asn1cFreeStruc(asn_DEF_NR_CellGroupConfig, UE_CellGroup); diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h index 255da9f189..233d3f1a80 100644 --- a/openair2/COMMON/rrc_messages_types.h +++ b/openair2/COMMON/rrc_messages_types.h @@ -478,7 +478,6 @@ typedef struct { } nr_mac_rrc_config_cg_t; typedef struct { NR_BCCH_BCH_Message_t *bcch; - int get_sib; bool access_barred; } nr_mac_rrc_config_mib_t; typedef struct { @@ -489,6 +488,10 @@ typedef struct { NR_SIB19_r17_t *sib19; bool can_start_ra; } nr_mac_rrc_config_other_sib_t; +typedef struct { + int get_sib; +} nr_mac_rrc_sched_sib_t; + enum payload_type { NR_MAC_RRC_CONFIG_RESET, @@ -496,6 +499,7 @@ enum payload_type { NR_MAC_RRC_CONFIG_MIB, NR_MAC_RRC_CONFIG_SIB1, NR_MAC_RRC_CONFIG_OTHER_SIB, + NR_MAC_RRC_SCHED_SIB, NR_MAC_RRC_RESUME_RB }; @@ -506,6 +510,7 @@ typedef struct { nr_mac_rrc_config_cg_t config_cg; nr_mac_rrc_config_mib_t config_mib; nr_mac_rrc_config_sib1_t config_sib1; + nr_mac_rrc_sched_sib_t sched_sib; nr_mac_rrc_config_other_sib_t config_other_sib; nr_mac_rrc_resume_rb_t resume_rb; } payload; diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 192b0a5111..05d2f87eb8 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1024,7 +1024,21 @@ static bool is_cset0_present(frequency_range_t const fr, uint8_t const kssb) return (fr == FR1) ? (kssb < 24) : (kssb < 12); } -void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib, int sched_sib, bool barred) +void nr_rrc_mac_sched_sib(module_id_t module_id, int sched_sib) +{ + NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); + if (sched_sib == 1) { + bool const is_c0 = is_cset0_present(mac->frequency_range, mac->ssb_subcarrier_offset); + mac->get_sib1 = is_c0; + AssertFatal(is_c0, "RRC scheduling SIB1 reception but MIB indicates no SIB1 present in current cell\n"); + } else if (sched_sib > 1) + mac->get_otherSI[sched_sib - 2] = true; + + if (mac->state == UE_NOT_SYNC && mac->get_sib1) + mac->state = UE_RECEIVING_SIB; +} + +void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib, bool barred) { NR_UE_MAC_INST_t *mac = get_mac_inst(module_id); int ret = pthread_mutex_lock(&mac->if_mutex); @@ -1044,22 +1058,10 @@ void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib, mac->phy_config.CC_id = cc_idP; nr_ue_decode_mib(mac, cc_idP); - - if (sched_sib == 1) { - bool const is_c0 = is_cset0_present(mac->frequency_range, mac->ssb_subcarrier_offset); - mac->get_sib1 = is_c0; - AssertFatal(is_c0, "RRC scheduling SIB1 reception but MIB indicates no SIB1 present in current cell\n"); - } else if (sched_sib > 1) - mac->get_otherSI[sched_sib - 2] = true; - if (get_softmodem_params()->phy_test) mac->state = UE_CONNECTED; - else if (mac->state == UE_NOT_SYNC) { - if (IS_SA_MODE(get_softmodem_params()) && mac->get_sib1) - mac->state = UE_RECEIVING_SIB; - else - mac->state = UE_PERFORMING_RA; - } + else if (mac->state == UE_NOT_SYNC && !IS_SA_MODE(get_softmodem_params())) + mac->state = UE_PERFORMING_RA; ret = pthread_mutex_unlock(&mac->if_mutex); AssertFatal(!ret, "mutex failed %d\n", ret); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index aee55e4883..981048f7b0 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -85,8 +85,8 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id, NR_CellGroupConfig_t *cell_group_config, NR_UE_NR_Capability_t *ue_Capability); -void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mibP, int sched_sib1, bool barred); - +void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mibP, bool barred); +void nr_rrc_mac_sched_sib(module_id_t module_id, int sched_sib); void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *sib1, bool can_start_ra); struct position; /* forward declaration */ diff --git a/openair2/RRC/NR_UE/L2_interface_ue.c b/openair2/RRC/NR_UE/L2_interface_ue.c index bae8915916..668f2981fb 100644 --- a/openair2/RRC/NR_UE/L2_interface_ue.c +++ b/openair2/RRC/NR_UE/L2_interface_ue.c @@ -146,7 +146,6 @@ void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id) nr_rrc_mac_config_req_mib(instance_id, 0, msg->payload.config_mib.bcch->message.choice.mib, - msg->payload.config_mib.get_sib, msg->payload.config_mib.access_barred); ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, msg->payload.config_mib.bcch); break; @@ -160,6 +159,9 @@ void process_msg_rcc_to_mac(nr_mac_rrc_message_t *msg, int instance_id) bool can_start_ra = msg->payload.config_other_sib.can_start_ra; nr_rrc_mac_config_other_sib(instance_id, msg->payload.config_other_sib.sib19, can_start_ra); } break; + case NR_MAC_RRC_SCHED_SIB: + nr_rrc_mac_sched_sib(instance_id, msg->payload.sched_sib.get_sib); + break; case NR_MAC_RRC_RESUME_RB: nr_rrc_mac_resume_rb(instance_id, msg->payload.resume_rb.is_srb, msg->payload.resume_rb.rb_id); break; diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 27e1dc0bb1..90c9c40ade 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1507,17 +1507,21 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc, && rrc->nrRrcState != RRC_STATE_DETACH_NR) { // to schedule MAC to get SI if required get_sib = check_si_status(SI_info); - if (get_sib) - SI_info->sib_pending = true; } if (bcch_message->message.present == NR_BCCH_BCH_MessageType_PR_mib) { nr_mac_rrc_message_t rrc_msg = {0}; rrc_msg.payload_type = NR_MAC_RRC_CONFIG_MIB; nr_mac_rrc_config_mib_t *config_mib = &rrc_msg.payload.config_mib; config_mib->bcch = bcch_message; - config_mib->get_sib = get_sib; config_mib->access_barred = barred; nr_rrc_send_msg_to_mac(rrc, &rrc_msg); + if (get_sib) { + SI_info->sib_pending = true; + nr_mac_rrc_message_t sib_msg = {0}; + sib_msg.payload_type = NR_MAC_RRC_SCHED_SIB; + sib_msg.payload.sched_sib.get_sib = get_sib; + nr_rrc_send_msg_to_mac(rrc, &sib_msg); + } } else { LOG_E(NR_RRC, "RRC-received BCCH message is not a MIB\n"); ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, bcch_message); From e3b0def6dcc1220d9e8cf542262465f9e68500cf Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 12 Sep 2025 18:34:29 +0200 Subject: [PATCH 6/7] conditional scheduling of SIB1 reception when receiving reconfigurationwSync --- openair2/COMMON/mac_messages_types.h | 1 + openair2/RRC/NR_UE/rrc_UE.c | 376 ++++++++++++++++----------- openair2/RRC/NR_UE/rrc_defs.h | 2 +- openair2/RRC/NR_UE/rrc_proto.h | 3 - 4 files changed, 221 insertions(+), 161 deletions(-) diff --git a/openair2/COMMON/mac_messages_types.h b/openair2/COMMON/mac_messages_types.h index c5c18a12f2..f505041fe8 100644 --- a/openair2/COMMON/mac_messages_types.h +++ b/openair2/COMMON/mac_messages_types.h @@ -78,6 +78,7 @@ typedef struct NRRrcMacRaInd_s { bool RA_succeeded; + int gnb_index; } NRRrcMacRaInd; typedef struct NRRrcMacMsg3Ind_s { diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 90c9c40ade..00d0ea204c 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -748,6 +748,189 @@ static void nr_rrc_ue_process_RadioBearerConfig(NR_UE_RRC_INST_t *ue_rrc, NR_Rad LOG_I(NR_RRC, "State = NR_RRC_CONNECTED\n"); } +static void nr_rrc_signal_maxrtxindication(int ue_id) +{ + MessageDef *msg = itti_alloc_new_message(TASK_RLC_UE, ue_id, NR_RRC_RLC_MAXRTX); + NR_RRC_RLC_MAXRTX(msg).ue_id = ue_id; + itti_send_msg_to_task(TASK_RRC_NRUE, ue_id, msg); +} + +/** @brief Release all active RLC entities for a UE and set to inactive. + * This is typically used when tearing down all DRBs at UE side, + * such as after a PDU session release or full reconfiguration. + * @param rrc Pointer to NR_UE_RRC_INST_t structure + * @param id Logical Channel ID (must be in range [0, NR_MAX_NUM_LCID-1]) */ +static void nr_rrc_release_rlc_entity(NR_UE_RRC_INST_t *rrc, int id) +{ + DevAssert(rrc); + DevAssert(id >= 0 && id < NR_MAX_NUM_LCID); + if (rrc->active_RLC_entity[id]) { + rrc->active_RLC_entity[id] = false; + nr_rlc_release_entity(rrc->ue_id, id); + LOG_I(RLC, "Released RLC entity: ue_id=%ld, lc_id=%d\n", rrc->ue_id, id); + } +} + +static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, const NR_CellGroupConfig_t *cellGroupConfig) +{ + if (cellGroupConfig->rlc_BearerToReleaseList != NULL) { + for (int i = 0; i < cellGroupConfig->rlc_BearerToReleaseList->list.count; i++) { + NR_LogicalChannelIdentity_t *lcid = cellGroupConfig->rlc_BearerToReleaseList->list.array[i]; + AssertFatal(lcid, "LogicalChannelIdentity shouldn't be null here\n"); + nr_rrc_release_rlc_entity(rrc, *lcid); + } + } + + if (cellGroupConfig->rlc_BearerToAddModList != NULL) { + for (int i = 0; i < cellGroupConfig->rlc_BearerToAddModList->list.count; i++) { + NR_RLC_BearerConfig_t *rlc_bearer = cellGroupConfig->rlc_BearerToAddModList->list.array[i]; + NR_LogicalChannelIdentity_t lcid = rlc_bearer->logicalChannelIdentity; + if (rrc->active_RLC_entity[lcid]) { + if (rlc_bearer->reestablishRLC) + nr_rlc_reestablish_entity(rrc->ue_id, lcid); + if (rlc_bearer->rlc_Config) + nr_rlc_reconfigure_entity(rrc->ue_id, lcid, rlc_bearer->rlc_Config); + } else { + rrc->active_RLC_entity[lcid] = true; + AssertFatal(rlc_bearer->servedRadioBearer, "servedRadioBearer mandatory in case of setup\n"); + AssertFatal(rlc_bearer->servedRadioBearer->present != NR_RLC_BearerConfig__servedRadioBearer_PR_NOTHING, + "Invalid RB for RLC configuration\n"); + if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity) { + NR_SRB_Identity_t srb_id = rlc_bearer->servedRadioBearer->choice.srb_Identity; + nr_rlc_add_srb(rrc->ue_id, srb_id, rlc_bearer); + nr_rlc_set_rlf_handler(rrc->ue_id, nr_rrc_signal_maxrtxindication); + } else { // DRB + NR_DRB_Identity_t drb_id = rlc_bearer->servedRadioBearer->choice.drb_Identity; + if (!rlc_bearer->rlc_Config) { + LOG_E(RLC, "RLC-Config not present but is mandatory for setup\n"); + rrc->active_RLC_entity[lcid] = false; + } else { + nr_rlc_add_drb(rrc->ue_id, drb_id, rlc_bearer); + nr_rlc_set_rlf_handler(rrc->ue_id, nr_rrc_signal_maxrtxindication); + } + } + } + } + } +} + +static void nr_rrc_process_reconfigurationWithSync(NR_UE_RRC_INST_t *rrc, + NR_ReconfigurationWithSync_t *reconfigurationWithSync, + int gNB_index) +{ + // perform Reconfiguration with sync according to 5.3.5.5.2 + if (!rrc->as_security_activated && !(get_softmodem_params()->phy_test || get_softmodem_params()->do_ra)) { + // if the AS security is not activated, perform the actions upon going to RRC_IDLE as specified in 5.3.11 + // with the release cause 'other' upon which the procedure ends + NR_Release_Cause_t release_cause = OTHER; + nr_rrc_going_to_IDLE(rrc, release_cause, NULL); + return; + } + + if (reconfigurationWithSync->spCellConfigCommon) { + /* if the frequencyInfoDL is included, consider the target SpCell + to be one on the SSB frequency indicated by the frequencyInfoDL */ + const NR_DownlinkConfigCommon_t *dcc = reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon; + if (dcc && dcc->frequencyInfoDL && dcc->frequencyInfoDL->absoluteFrequencySSB) + rrc->arfcn_ssb = *dcc->frequencyInfoDL->absoluteFrequencySSB; + + // consider the target SpCell to be one with a physical cell identity indicated by the physCellId + if (!reconfigurationWithSync->spCellConfigCommon->physCellId) + LOG_E(NR_RRC, "physCellId absent but should be mandatory present upon cell change and cell addition\n"); + else + rrc->phyCellID = *reconfigurationWithSync->spCellConfigCommon->physCellId; + } + + NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants; + nr_timer_stop(&tac->T310); + if (!get_softmodem_params()->phy_test) { + // T304 is stopped upon completion of RA procedure which is not done in phy-test mode + int t304_value = nr_rrc_get_T304(reconfigurationWithSync->t304); + nr_timer_setup(&tac->T304, t304_value, 10); // 10ms step + nr_timer_start(&tac->T304); + } + rrc->rnti = reconfigurationWithSync->newUE_Identity; + // reset the MAC entity of this cell group (done at MAC in handle_reconfiguration_with_sync) + + // 3GPP TS38.331 section 5.3.5.5.2 + nr_timer_stop(&tac->T430); + + if (rrc->target_ntncfg) { + ASN_STRUCT_FREE(asn_DEF_NR_NTN_Config_r17, rrc->target_ntncfg); + rrc->target_ntncfg = NULL; + rrc->process_target_ntncfg = false; + } + if (reconfigurationWithSync->spCellConfigCommon && + reconfigurationWithSync->spCellConfigCommon->ext2 && + reconfigurationWithSync->spCellConfigCommon->ext2->ntn_Config_r17) { + NR_NTN_Config_r17_t *ntncfg = reconfigurationWithSync->spCellConfigCommon->ext2->ntn_Config_r17; + // EPOCH time is always sent if NTN config is sent through DCCH + AssertFatal(ntncfg->epochTime_r17, "NTN-CONFIG sent in dedicated mode should have EPOCHTIME\n"); + const int copy_result = asn_copy(&asn_DEF_NR_NTN_Config_r17, (void **)&rrc->target_ntncfg, ntncfg); + AssertFatal(copy_result == 0, "unable to copy NR_NTN_Config_r17_t\n"); + } +} + +static void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t *cgConfig, int gNB_index, bool dedicatedsib1) +{ + NR_SpCellConfig_t *spCellConfig = cgConfig->spCellConfig; + if(spCellConfig) { + NR_ServingCellConfig_t *spCellConfigDedicated = spCellConfig->spCellConfigDedicated; + if (spCellConfigDedicated) { + if (spCellConfigDedicated->firstActiveDownlinkBWP_Id) + rrc->dl_bwp_id = *spCellConfigDedicated->firstActiveDownlinkBWP_Id; + if (spCellConfigDedicated->uplinkConfig && spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id) + rrc->ul_bwp_id = *spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id; + } + NR_ReconfigurationWithSync_t *reconfigurationWithSync = spCellConfig->reconfigurationWithSync; + if (reconfigurationWithSync) { + LOG_I(NR_RRC, "Processing reconfigurationWithSync\n"); + nr_rrc_process_reconfigurationWithSync(rrc, reconfigurationWithSync, gNB_index); + // if RRCReconfiguration does not include dedicatedSIB1-Delivery + // if the active downlink BWP, which is indicated by the firstActiveDownlinkBWP-Id for the target SpCell of the MCG, + // has a common search space configured by searchSpaceSIB1 + // acquire the SIB1, which is scheduled as specified in TS 38.213 [13], of the target SpCell of the MCG + if (!dedicatedsib1 && IS_SA_MODE(get_softmodem_params())) { + if (rrc->dl_bwp_id == 0) { + // Check initial DL BWP for searchSpaceSIB1 + NR_ServingCellConfigCommon_t *spCellConfigCommon = reconfigurationWithSync->spCellConfigCommon; + if (spCellConfigCommon) { + NR_DownlinkConfigCommon_t *downlinkConfig = spCellConfigCommon->downlinkConfigCommon; + if (downlinkConfig + && downlinkConfig->initialDownlinkBWP + && downlinkConfig->initialDownlinkBWP->pdcch_ConfigCommon + && downlinkConfig->initialDownlinkBWP->pdcch_ConfigCommon->present == NR_SetupRelease_PDCCH_ConfigCommon_PR_setup + && downlinkConfig->initialDownlinkBWP->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1) { + rrc->sched_reconfsync_sib1 = true; + } + } + } else { + // Check dedicated DL BWP for searchSpaceSIB1 + if (spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList) { + for (int i = 0; i < spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count; i++) { + NR_BWP_Downlink_t *bwp = spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[i]; + if (bwp->bwp_Id == rrc->dl_bwp_id && bwp->bwp_Common && bwp->bwp_Common->pdcch_ConfigCommon + && bwp->bwp_Common->pdcch_ConfigCommon->present == NR_SetupRelease_PDCCH_ConfigCommon_PR_setup + && bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceSIB1) { + rrc->sched_reconfsync_sib1 = true; + break; + } + } + } + } + } + } + nr_rrc_handle_SetupRelease_RLF_TimersAndConstants(rrc, spCellConfig->rlf_TimersAndConstants); + } + + nr_rrc_manage_rlc_bearers(rrc, cgConfig); + + if (cgConfig->ext1) + AssertFatal(cgConfig->ext1->reportUplinkTxDirectCurrent == NULL, "Reporting of UplinkTxDirectCurrent not implemented\n"); + AssertFatal(cgConfig->sCellToReleaseList == NULL, "Secondary serving cell release not implemented\n"); + AssertFatal(cgConfig->sCellToAddModList == NULL, "Secondary serving cell addition not implemented\n"); +} + static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, OCTET_STRING_t *masterCellGroup, long *fullConfig, @@ -768,7 +951,7 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); } - nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index); + nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index, false); LOG_D(RRC, "Sending CellGroupConfig to MAC the pointer will be managed by mac\n"); nr_mac_rrc_message_t rrc_msg = {0}; @@ -779,7 +962,7 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc, nr_rrc_send_msg_to_mac(rrc, &rrc_msg); } -static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCReconfiguration_v1530_IEs_t *rec_1530, int gNB_index) +static bool nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCReconfiguration_v1530_IEs_t *rec_1530, int gNB_index) { if (rec_1530->fullConfig) { // TODO perform the full configuration procedure as specified in 5.3.5.11 of 331 @@ -793,7 +976,9 @@ static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCRe nr_pdcp_config_set_security(rrc->ue_id, 1, true, &sp); } NR_UE_RRC_SI_INFO *SI_info = &rrc->perNB[gNB_index].SInfo; + bool dedicatedsib1 = false; if (rec_1530->dedicatedSIB1_Delivery) { + dedicatedsib1 = true; NR_SIB1_t *sib1 = NULL; asn_dec_rval_t dec_rval = uper_decode(NULL, &asn_DEF_NR_SIB1, @@ -860,6 +1045,7 @@ static void nr_rrc_process_reconfiguration_v1530(NR_UE_RRC_INST_t *rrc, NR_RRCRe } } } + return dedicatedsib1; } static void handle_meas_reporting_remove(rrcPerNB_t *rrc, int id, NR_UE_Timers_Constants_t *timers) @@ -1138,8 +1324,9 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_ case NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration: { NR_RRCReconfiguration_IEs_t *ie = reconfiguration->criticalExtensions.choice.rrcReconfiguration; + bool dedicatedsib1 = false; if (ie->nonCriticalExtension) - nr_rrc_process_reconfiguration_v1530(rrc, ie->nonCriticalExtension, gNB_index); + dedicatedsib1 = nr_rrc_process_reconfiguration_v1530(rrc, ie->nonCriticalExtension, gNB_index); if (ie->radioBearerConfig) { LOG_I(NR_RRC, "RRCReconfiguration includes radio Bearer Configuration\n"); @@ -1175,7 +1362,7 @@ static void nr_rrc_ue_process_rrcReconfiguration(NR_UE_RRC_INST_t *rrc, int gNB_ if (LOG_DEBUGFLAG(DEBUG_ASN1)) xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *) cellGroupConfig); - nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index); + nr_rrc_cellgroup_configuration(rrc, cellGroupConfig, gNB_index, dedicatedsib1); AssertFatal(!IS_SA_MODE(get_softmodem_params()), "secondaryCellGroup only used in NSA for now\n"); nr_mac_rrc_message_t rrc_msg = {0}; rrc_msg.payload_type = NR_MAC_RRC_CONFIG_CG; @@ -1278,6 +1465,7 @@ NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int instance_id, int num_ant_ rrc->dl_bwp_id = 0; rrc->ul_bwp_id = 0; rrc->as_security_activated = false; + rrc->sched_reconfsync_sib1 = false; rrc->detach_after_release = false; rrc->reconfig_after_reestab = false; /* 5G-S-TMSI */ @@ -1665,155 +1853,6 @@ static void nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_BCCH, VCD_FUNCTION_OUT ); } -static void nr_rrc_signal_maxrtxindication(int ue_id) -{ - MessageDef *msg = itti_alloc_new_message(TASK_RLC_UE, ue_id, NR_RRC_RLC_MAXRTX); - NR_RRC_RLC_MAXRTX(msg).ue_id = ue_id; - itti_send_msg_to_task(TASK_RRC_NRUE, ue_id, msg); -} - -/** @brief Release all active RLC entities for a UE and set to inactive. - * This is typically used when tearing down all DRBs at UE side, - * such as after a PDU session release or full reconfiguration. - * @param rrc Pointer to NR_UE_RRC_INST_t structure - * @param id Logical Channel ID (must be in range [0, NR_MAX_NUM_LCID-1]) */ -static void nr_rrc_release_rlc_entity(NR_UE_RRC_INST_t *rrc, int id) -{ - DevAssert(rrc); - DevAssert(id >= 0 && id < NR_MAX_NUM_LCID); - if (rrc->active_RLC_entity[id]) { - rrc->active_RLC_entity[id] = false; - nr_rlc_release_entity(rrc->ue_id, id); - LOG_I(RLC, "Released RLC entity: ue_id=%ld, lc_id=%d\n", rrc->ue_id, id); - } -} - -static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc, const NR_CellGroupConfig_t *cellGroupConfig) -{ - if (cellGroupConfig->rlc_BearerToReleaseList != NULL) { - for (int i = 0; i < cellGroupConfig->rlc_BearerToReleaseList->list.count; i++) { - NR_LogicalChannelIdentity_t *lcid = cellGroupConfig->rlc_BearerToReleaseList->list.array[i]; - AssertFatal(lcid, "LogicalChannelIdentity shouldn't be null here\n"); - nr_rrc_release_rlc_entity(rrc, *lcid); - } - } - - if (cellGroupConfig->rlc_BearerToAddModList != NULL) { - for (int i = 0; i < cellGroupConfig->rlc_BearerToAddModList->list.count; i++) { - NR_RLC_BearerConfig_t *rlc_bearer = cellGroupConfig->rlc_BearerToAddModList->list.array[i]; - NR_LogicalChannelIdentity_t lcid = rlc_bearer->logicalChannelIdentity; - if (rrc->active_RLC_entity[lcid]) { - if (rlc_bearer->reestablishRLC) - nr_rlc_reestablish_entity(rrc->ue_id, lcid); - if (rlc_bearer->rlc_Config) - nr_rlc_reconfigure_entity(rrc->ue_id, lcid, rlc_bearer->rlc_Config); - } else { - rrc->active_RLC_entity[lcid] = true; - AssertFatal(rlc_bearer->servedRadioBearer, "servedRadioBearer mandatory in case of setup\n"); - AssertFatal(rlc_bearer->servedRadioBearer->present != NR_RLC_BearerConfig__servedRadioBearer_PR_NOTHING, - "Invalid RB for RLC configuration\n"); - if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity) { - NR_SRB_Identity_t srb_id = rlc_bearer->servedRadioBearer->choice.srb_Identity; - nr_rlc_add_srb(rrc->ue_id, srb_id, rlc_bearer); - nr_rlc_set_rlf_handler(rrc->ue_id, nr_rrc_signal_maxrtxindication); - } else { // DRB - NR_DRB_Identity_t drb_id = rlc_bearer->servedRadioBearer->choice.drb_Identity; - if (!rlc_bearer->rlc_Config) { - LOG_E(RLC, "RLC-Config not present but is mandatory for setup\n"); - rrc->active_RLC_entity[lcid] = false; - } else { - nr_rlc_add_drb(rrc->ue_id, drb_id, rlc_bearer); - nr_rlc_set_rlf_handler(rrc->ue_id, nr_rrc_signal_maxrtxindication); - } - } - } - } - } -} - -static void nr_rrc_process_reconfigurationWithSync(NR_UE_RRC_INST_t *rrc, - NR_ReconfigurationWithSync_t *reconfigurationWithSync, - int gNB_index) -{ - // perform Reconfiguration with sync according to 5.3.5.5.2 - if (!rrc->as_security_activated && !(get_softmodem_params()->phy_test || get_softmodem_params()->do_ra)) { - // if the AS security is not activated, perform the actions upon going to RRC_IDLE as specified in 5.3.11 - // with the release cause 'other' upon which the procedure ends - NR_Release_Cause_t release_cause = OTHER; - nr_rrc_going_to_IDLE(rrc, release_cause, NULL); - return; - } - - if (reconfigurationWithSync->spCellConfigCommon) { - /* if the frequencyInfoDL is included, consider the target SpCell - to be one on the SSB frequency indicated by the frequencyInfoDL */ - const NR_DownlinkConfigCommon_t *dcc = reconfigurationWithSync->spCellConfigCommon->downlinkConfigCommon; - if (dcc && dcc->frequencyInfoDL && dcc->frequencyInfoDL->absoluteFrequencySSB) - rrc->arfcn_ssb = *dcc->frequencyInfoDL->absoluteFrequencySSB; - - // consider the target SpCell to be one with a physical cell identity indicated by the physCellId - if (!reconfigurationWithSync->spCellConfigCommon->physCellId) - LOG_E(NR_RRC, "physCellId absent but should be mandatory present upon cell change and cell addition\n"); - else - rrc->phyCellID = *reconfigurationWithSync->spCellConfigCommon->physCellId; - } - - NR_UE_Timers_Constants_t *tac = &rrc->timers_and_constants; - nr_timer_stop(&tac->T310); - if (!get_softmodem_params()->phy_test) { - // T304 is stopped upon completion of RA procedure which is not done in phy-test mode - int t304_value = nr_rrc_get_T304(reconfigurationWithSync->t304); - nr_timer_setup(&tac->T304, t304_value, 10); // 10ms step - nr_timer_start(&tac->T304); - } - rrc->rnti = reconfigurationWithSync->newUE_Identity; - // reset the MAC entity of this cell group (done at MAC in handle_reconfiguration_with_sync) - - // 3GPP TS38.331 section 5.3.5.5.2 - nr_timer_stop(&tac->T430); - - if (rrc->target_ntncfg) { - ASN_STRUCT_FREE(asn_DEF_NR_NTN_Config_r17, rrc->target_ntncfg); - rrc->target_ntncfg = NULL; - rrc->process_target_ntncfg = false; - } - if (reconfigurationWithSync->spCellConfigCommon && - reconfigurationWithSync->spCellConfigCommon->ext2 && - reconfigurationWithSync->spCellConfigCommon->ext2->ntn_Config_r17) { - NR_NTN_Config_r17_t *ntncfg = reconfigurationWithSync->spCellConfigCommon->ext2->ntn_Config_r17; - // EPOCH time is always sent if NTN config is sent through DCCH - AssertFatal(ntncfg->epochTime_r17, "NTN-CONFIG sent in dedicated mode should have EPOCHTIME\n"); - const int copy_result = asn_copy(&asn_DEF_NR_NTN_Config_r17, (void **)&rrc->target_ntncfg, ntncfg); - AssertFatal(copy_result == 0, "unable to copy NR_NTN_Config_r17_t\n"); - } -} - -void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t *cellGroupConfig, int gNB_index) -{ - NR_SpCellConfig_t *spCellConfig = cellGroupConfig->spCellConfig; - if(spCellConfig) { - if (spCellConfig->reconfigurationWithSync) { - LOG_I(NR_RRC, "Processing reconfigurationWithSync\n"); - nr_rrc_process_reconfigurationWithSync(rrc, spCellConfig->reconfigurationWithSync, gNB_index); - } - nr_rrc_handle_SetupRelease_RLF_TimersAndConstants(rrc, spCellConfig->rlf_TimersAndConstants); - if (spCellConfig->spCellConfigDedicated) { - if (spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id) - rrc->dl_bwp_id = *spCellConfig->spCellConfigDedicated->firstActiveDownlinkBWP_Id; - if (spCellConfig->spCellConfigDedicated->uplinkConfig && - spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id) - rrc->dl_bwp_id = *spCellConfig->spCellConfigDedicated->uplinkConfig->firstActiveUplinkBWP_Id; - } - } - - nr_rrc_manage_rlc_bearers(rrc, cellGroupConfig); - - if (cellGroupConfig->ext1) - AssertFatal(cellGroupConfig->ext1->reportUplinkTxDirectCurrent == NULL, "Reporting of UplinkTxDirectCurrent not implemented\n"); - AssertFatal(cellGroupConfig->sCellToReleaseList == NULL, "Secondary serving cell release not implemented\n"); - AssertFatal(cellGroupConfig->sCellToAddModList == NULL, "Secondary serving cell addition not implemented\n"); -} - static void rrc_ue_generate_RRCSetupComplete(const NR_UE_RRC_INST_t *rrc, const uint8_t Transaction_id) { uint8_t buffer[100]; @@ -2589,14 +2628,37 @@ static void nr_ue_check_meas_report(NR_UE_RRC_INST_t *rrc, const uint8_t gnb_ind } } -void nr_rrc_handle_ra_indication(NR_UE_RRC_INST_t *rrc, bool ra_succeeded) +static void nr_rrc_handle_ra_indication(NR_UE_RRC_INST_t *rrc, bool ra_succeeded, int gNB_index) { NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants; if (ra_succeeded && nr_timer_is_active(&timers->T304)) { // successful Random Access procedure triggered by reconfigurationWithSync - nr_timer_stop(&timers->T304); - // TODO handle the rest of procedures as described in 5.3.5.3 for when + // procedures described in 5.3.5.3 of 38.331 when // reconfigurationWithSync is included in spCellConfig + nr_timer_stop(&timers->T304); + + // TODO apply the parts of the CQI reporting configuration, + // the scheduling request configuration and the sounding RS + // configuration that do not require the UE to know the SFN of the respective target SpCell + // TODO apply the parts of the measurement and the radio resource configuration + // that require the UE to know the SFN of the respective target SpCell + // (not sure what to do for these two points, probably not relevant for our implementation) + + // if T390 is running stop timer T390 for all access categories + if (nr_timer_is_active(&timers->T390)) { + nr_timer_stop(&timers->T390); + // TODO perform the actions as specified in 5.3.14.4. + } + + if (rrc->sched_reconfsync_sib1) { + rrc->sched_reconfsync_sib1 = false; + NR_UE_RRC_SI_INFO *SI_info = &rrc->perNB[gNB_index].SInfo; + SI_info->sib_pending = true; + nr_mac_rrc_message_t sib_msg = {0}; + sib_msg.payload_type = NR_MAC_RRC_SCHED_SIB; + sib_msg.payload.sched_sib.get_sib = 1; + nr_rrc_send_msg_to_mac(rrc, &sib_msg); + } } else if (!ra_succeeded) { // upon random access problem indication from MCG MAC // while neither T300, T301, T304, T311 nor T319 are running @@ -2687,7 +2749,7 @@ void *rrc_nrue(void *notUsed) rrc->ue_id, ITTI_MSG_NAME(msg_p), NR_RRC_MAC_RA_IND(msg_p).RA_succeeded ? "successful" : "failed"); - nr_rrc_handle_ra_indication(rrc, NR_RRC_MAC_RA_IND(msg_p).RA_succeeded); + nr_rrc_handle_ra_indication(rrc, NR_RRC_MAC_RA_IND(msg_p).RA_succeeded, NR_RRC_MAC_RA_IND(msg_p).gnb_index); break; case NR_RRC_MAC_BCCH_DATA_IND: diff --git a/openair2/RRC/NR_UE/rrc_defs.h b/openair2/RRC/NR_UE/rrc_defs.h index 0672af7741..943c5a8d58 100644 --- a/openair2/RRC/NR_UE/rrc_defs.h +++ b/openair2/RRC/NR_UE/rrc_defs.h @@ -263,7 +263,7 @@ typedef struct NR_UE_RRC_INST_s { uint64_t fiveG_S_TMSI; // Frame timing received from MAC int current_frame; - + bool sched_reconfsync_sib1; //Sidelink params NR_SL_PreconfigurationNR_r16_t *sl_preconfig; // NTN params diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h index 1ebb728884..e6960e154b 100644 --- a/openair2/RRC/NR_UE/rrc_proto.h +++ b/openair2/RRC/NR_UE/rrc_proto.h @@ -46,9 +46,6 @@ NR_UE_RRC_INST_t* get_NR_UE_rrc_inst(int instance); void init_nsa_message (NR_UE_RRC_INST_t *rrc, char* reconfig_file, char* rbconfig_file); void process_nsa_message(NR_UE_RRC_INST_t *rrc, nsa_message_t nsa_message_type, void *message, int msg_len); - -void nr_rrc_cellgroup_configuration(NR_UE_RRC_INST_t *rrc, NR_CellGroupConfig_t *cellGroupConfig, int gNB_index); - void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc, NR_Release_Cause_t release_cause, NR_RRCRelease_t *RRCRelease); From 7da7dda71b19f8b059f8040cc0fe639b0796dbda Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 15 Sep 2025 15:46:18 +0200 Subject: [PATCH 7/7] new UE state to trigger RA after reconfiguration with sync --- openair2/LAYER2/NR_MAC_UE/config_ue.c | 12 +++++------- openair2/LAYER2/NR_MAC_UE/mac_proto.h | 2 +- openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 6 +++--- openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 2 +- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 05d2f87eb8..8f36c6cf43 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1060,7 +1060,7 @@ void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib, nr_ue_decode_mib(mac, cc_idP); if (get_softmodem_params()->phy_test) mac->state = UE_CONNECTED; - else if (mac->state == UE_NOT_SYNC && !IS_SA_MODE(get_softmodem_params())) + else if (mac->state == UE_NOT_SYNC_RECONF) mac->state = UE_PERFORMING_RA; ret = pthread_mutex_unlock(&mac->if_mutex); @@ -1811,7 +1811,7 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t LOG_A(NR_MAC, "Received detach indication\n"); reset_ra(mac, true); reset_mac_inst(mac); - nr_ue_reset_sync_state(mac); + nr_ue_reset_sync_state(mac, false); release_mac_configuration(mac, cause); mac->state = UE_DETACHING; break; @@ -1828,7 +1828,7 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t case RE_ESTABLISHMENT: reset_mac_inst(mac); nr_ue_mac_default_configs(mac); - nr_ue_reset_sync_state(mac); + nr_ue_reset_sync_state(mac, true); release_mac_configuration(mac, cause); // suspend all RBs except SRB0 for (int j = 0; j < mac->lc_ordered_list.count; j++) { @@ -1971,9 +1971,7 @@ void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19, b AssertFatal(!ret, "mutex failed %d\n", ret); } -static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac, - int cc_idP, - const NR_ReconfigurationWithSync_t *reconfWithSync) +static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac, int cc_idP, const NR_ReconfigurationWithSync_t *reconfWithSync) { reset_mac_inst(mac); mac->crnti = reconfWithSync->newUE_Identity; @@ -2015,7 +2013,7 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac, configure_common_BWP_ul(mac, bwp_id, scc->uplinkConfigCommon->initialUplinkBWP); } - mac->state = UE_NOT_SYNC; + mac->state = UE_NOT_SYNC_RECONF; ra->ra_state = nrRA_UE_IDLE; nr_ue_mac_default_configs(mac); diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h index 981048f7b0..7bb3861e48 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h @@ -252,7 +252,7 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac); void prepare_msg4_msgb_feedback(NR_UE_MAC_INST_t *mac, int pid, int ack_nack); void configure_initial_pucch(PUCCH_sched_t *pucch, int res_ind); void release_PUCCH_SRS(NR_UE_MAC_INST_t *mac); -void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac); +void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac, bool reconf); void nr_ue_send_synch_request(NR_UE_MAC_INST_t *mac, module_id_t module_id, int cc_id, const fapi_nr_synch_request_t *sync_req); bool is_ss_monitor_occasion(const int frame, const int slot, const int slots_per_frame, const NR_SearchSpace_t *ss); diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index c78d2217b4..4cf96b46bc 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -54,7 +54,7 @@ void send_srb0_rrc(int ue_id, const uint8_t *sdu, sdu_size_t sdu_len, void *data 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); + nr_ue_reset_sync_state(mac, false); mac->get_sib1 = false; for (int i = 0; i < MAX_SI_GROUPS; i++) mac->get_otherSI[i] = false; @@ -117,10 +117,10 @@ void nr_ue_send_synch_request(NR_UE_MAC_INST_t *mac, module_id_t module_id, int mac->if_module->synch_request(&mac->synch_request); } -void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac) +void nr_ue_reset_sync_state(NR_UE_MAC_INST_t *mac, bool reconf) { // reset synchornization status - mac->state = UE_NOT_SYNC; + mac->state = reconf ? UE_NOT_SYNC_RECONF : UE_NOT_SYNC; mac->ra.ra_state = nrRA_UE_IDLE; } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index bd9ea09041..419663d568 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -1146,7 +1146,7 @@ void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info dl_config->slot = rx_slot; dl_config->number_pdus = 0; - if (mac->state == UE_NOT_SYNC || mac->state == UE_DETACHING) + if (mac->state == UE_NOT_SYNC || mac->state == UE_NOT_SYNC_RECONF || mac->state == UE_DETACHING) return; if (mac->state == UE_CONNECTED) {