From b88efd74b8ba4c377751577ab8bfa0b31c5ddd37 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 28 Feb 2025 16:14:08 +0100 Subject: [PATCH 01/25] fix in determining the num of cdm groups with no data for ULSCH --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 4 ++-- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 808afc8d86..0b8bf3c03b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -278,7 +278,7 @@ static void schedule_nr_MsgA_pusch(NR_UplinkConfigCommon_t *uplinkConfigCommon, pusch_pdu->nr_of_symbols = L; pusch_pdu->pusch_data.new_data_indicator = 1; pusch_pdu->nrOfLayers = 1; - pusch_pdu->num_dmrs_cdm_grps_no_data = 2; // no data in dmrs symbols as in 6.2.2 in 38.214 + pusch_pdu->num_dmrs_cdm_grps_no_data = L <= 2 ? 1 : 2; // no data in dmrs symbols as in 6.2.2 in 38.214 pusch_pdu->ul_dmrs_symb_pos = get_l_prime(3, 0, pusch_dmrs_pos2, pusch_len1, 10, dmrs_TypeA_Position); pusch_pdu->transform_precoding = *uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup->msgA_PUSCH_Config_r16->msgA_TransformPrecoder_r16; pusch_pdu->rb_bitmap[0] = 0; @@ -1132,7 +1132,7 @@ static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, pusch_pdu->pusch_identity = *scc->physCellId; //If provided and the PUSCH is not a msg3 PUSCH, otherwise, L2 should set this to physical cell id. pusch_pdu->scid = 0; //DMRS sequence initialization [TS38.211, sec 6.4.1.1.1]. Should match what is sent in DCI 0_1, otherwise set to 0. pusch_pdu->dmrs_ports = 1; // 6.2.2 in 38.214 only port 0 to be used - pusch_pdu->num_dmrs_cdm_grps_no_data = 2; // no data in dmrs symbols as in 6.2.2 in 38.214 + pusch_pdu->num_dmrs_cdm_grps_no_data = nr_of_symbols <= 2 ? 1 : 2; // no data in dmrs symbols as in 6.2.2 in 38.214 pusch_pdu->resource_alloc = 1; //type 1 memset(pusch_pdu->rb_bitmap, 0, sizeof(pusch_pdu->rb_bitmap)); pusch_pdu->rb_start = ra->msg3_first_rb; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index c294d2966a..b9f6a193b7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -292,7 +292,7 @@ NR_pdsch_dmrs_t get_dl_dmrs_params(const NR_ServingCellConfigCommon_t *scc, int frontloaded_symb = 1; // default value nr_dci_format_t dci_format = dl_bwp ? dl_bwp->dci_format : NR_DL_DCI_FORMAT_1_0; if (dci_format == NR_DL_DCI_FORMAT_1_0) { - dmrs.numDmrsCdmGrpsNoData = tda_info->nrOfSymbols == 2 ? 1 : 2; + dmrs.numDmrsCdmGrpsNoData = tda_info->nrOfSymbols <= 2 ? 1 : 2; dmrs.dmrs_ports_id = 0; } else { @@ -696,7 +696,7 @@ NR_pusch_dmrs_t get_ul_dmrs_params(const NR_ServingCellConfigCommon_t *scc, dmrs.num_dmrs_cdm_grps_no_data = 2; } else { if (ul_bwp->transform_precoding && Layers < 3) - dmrs.num_dmrs_cdm_grps_no_data = ul_bwp->dci_format == NR_UL_DCI_FORMAT_0_1 || tda_info->nrOfSymbols == 2 ? 1 : 2; + dmrs.num_dmrs_cdm_grps_no_data = ul_bwp->dci_format == NR_UL_DCI_FORMAT_0_1 || tda_info->nrOfSymbols <= 2 ? 1 : 2; else dmrs.num_dmrs_cdm_grps_no_data = 2; } From a1e1405ee6f46cf87bc2eb4a35b6834e4956862c Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 17 Apr 2025 09:57:44 +0200 Subject: [PATCH 02/25] Start E1 before gNB_app In phy-test and do-ra modes, we will trigger a UE context creation after F1 Setup (because the DU is ready), in a later commit. However, before this commit, E1 is started after the gnb_app (which triggers F1 Setup). E1 starts an (integrated) CU-UP; if the E1 Setup arrives after the F1 setup (which creates a UE context), then the E1 setup handler will drop the newly created RRC context for a do-ra/phy-test mode. Avoid/minimize this by starting E1 first, so that E1 setup is done before F1 Setup is completed (this does not make sure the problem does not happen, but lowers the risk of the above problem). --- executables/nr-softmodem.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index 5a8464b60c..b9302392ab 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -305,11 +305,6 @@ static int create_gNB_tasks(ngran_node_t node_type, configmodule_interface_t *cf } if (gnb_nb > 0) { - if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) { - LOG_E(GNB_APP, "Create task for gNB APP failed\n"); - return -1; - } - if (!NODE_IS_DU(node_type)) { if (itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL) < 0) { LOG_E(NR_RRC, "Create task for NR RRC gNB failed\n"); @@ -333,6 +328,11 @@ static int create_gNB_tasks(ngran_node_t node_type, configmodule_interface_t *cf itti_free(TASK_UNKNOWN, msg); } + if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) { + LOG_E(GNB_APP, "Create task for gNB APP failed\n"); + return -1; + } + //Use check on x2ap to consider the NSA scenario if((is_x2ap_enabled() || IS_SA_MODE(get_softmodem_params())) && (node_type != ngran_gNB_CUCP)) { if (itti_create_task (TASK_GTPV1_U, >pv1uTask, NULL) < 0) { From a33735458873a77f03f833a89b3105065e863811 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 4 Mar 2025 16:41:58 +0100 Subject: [PATCH 03/25] Add function to compute slot for RA-RNTI --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 66 +++++++++++-------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 0b8bf3c03b..14b7951de3 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -681,6 +681,27 @@ static uint8_t nr_get_msg3_tpc(uint32_t preamble_power) return 3; // it means 0dB } +static unsigned int get_slot_RA(const NR_ServingCellConfigCommon_t *scc, + const NR_RACH_ConfigCommon_t *rach_ConfigCommon, + const NR_MsgA_ConfigCommon_r16_t *msgacc, + frame_type_t frame_type, + int slot) +{ + uint8_t index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; + uint16_t prach_format = + get_nr_prach_format_from_index(index, scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, frame_type); + unsigned int slot_RA; + if ((prach_format & 0xff) < 4) { + const int ul_mu = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + const int mu = nr_get_prach_or_ul_mu(msgacc, rach_ConfigCommon, ul_mu); + unsigned int slots_per_sf = (1 << mu); + slot_RA = slot / slots_per_sf; + } else { + slot_RA = slot; + } + return slot_RA; +} + void nr_initiate_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, @@ -723,35 +744,22 @@ void nr_initiate_ra_proc(module_id_t module_idP, ra->msg3_TPC = nr_get_msg3_tpc(preamble_power); NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - { - // 3GPP TS 38.321 Section 5.1.3(a) says t_id for RA-RNTI depends on mu as specified in clause 5.3.2 in TS 38.211 - // so mu = 0 for prach format < 4. - NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; - NR_MsgA_ConfigCommon_r16_t *msgacc = NULL; - if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) - msgacc = scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup; - const int ul_mu = scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; - const int mu = nr_get_prach_or_ul_mu(msgacc, rach_ConfigCommon, ul_mu); - uint8_t index = rach_ConfigCommon->rach_ConfigGeneric.prach_ConfigurationIndex; - uint16_t prach_format = - get_nr_prach_format_from_index(index, scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA, cc->frame_type); - unsigned int slot_RA; - if ((prach_format & 0xff) < 4) { - unsigned int slots_per_sf = (1 << mu); - slot_RA = slotP / slots_per_sf; - } else { - slot_RA = slotP; - } - uint8_t ul_carrier_id = 0; // 0 for NUL 1 for SUL - ra->RA_rnti = nr_get_ra_rnti(symbol, slot_RA, freq_index, ul_carrier_id); - if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) { - ra->ra_type = RA_2_STEP; - ra->ra_state = nrRA_WAIT_MsgA_PUSCH; - ra->MsgB_rnti = nr_get_MsgB_rnti(symbol, slot_RA, freq_index, ul_carrier_id); - } else { - ra->ra_type = RA_4_STEP; - ra->ra_state = nrRA_Msg2; - } + // 3GPP TS 38.321 Section 5.1.3(a) says t_id for RA-RNTI depends on mu as specified in clause 5.3.2 in TS 38.211 + // so mu = 0 for prach format < 4. + NR_RACH_ConfigCommon_t *rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; + NR_MsgA_ConfigCommon_r16_t *msgacc = NULL; + if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) + msgacc = scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup; + uint32_t slot_RA = get_slot_RA(scc, rach_ConfigCommon, msgacc, cc->frame_type, slotP); + uint8_t ul_carrier_id = 0; // 0 for NUL 1 for SUL + ra->RA_rnti = nr_get_ra_rnti(symbol, slot_RA, freq_index, ul_carrier_id); + if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) { + ra->ra_type = RA_2_STEP; + ra->ra_state = nrRA_WAIT_MsgA_PUSCH; + ra->MsgB_rnti = nr_get_MsgB_rnti(symbol, slot_RA, freq_index, ul_carrier_id); + } else { + ra->ra_type = RA_4_STEP; + ra->ra_state = nrRA_Msg2; } int index = ra - cc->ra; From a7c199cabf1fc7ee4c80e00b6f30a4bf8096c271 Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 2 Mar 2025 16:19:11 +0100 Subject: [PATCH 04/25] new name for UE list --- common/utils/telnetsrv/telnetsrv_ci.c | 2 +- common/utils/telnetsrv/telnetsrv_o1.c | 4 +-- openair1/SIMULATION/NR_PHY/dlsim.c | 6 ++--- .../RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c | 4 +-- .../RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c | 6 ++--- .../E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c | 2 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 8 +++--- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 6 ++--- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 26 +++++++++---------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 6 ++--- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 8 +++--- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 4 +-- openair2/LAYER2/NR_MAC_gNB/main.c | 10 +++---- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 2 +- 16 files changed, 49 insertions(+), 49 deletions(-) diff --git a/common/utils/telnetsrv/telnetsrv_ci.c b/common/utils/telnetsrv/telnetsrv_ci.c index bea421a995..fff1423c16 100644 --- a/common/utils/telnetsrv/telnetsrv_ci.c +++ b/common/utils/telnetsrv/telnetsrv_ci.c @@ -47,7 +47,7 @@ static int get_single_ue_rnti_mac(void) { NR_UE_info_t *ue = NULL; - UE_iterator(RC.nrmac[0]->UE_info.list, it) { + UE_iterator(RC.nrmac[0]->UE_info.connected_ue_list, it) { if (it && ue) return -1; if (it) diff --git a/common/utils/telnetsrv/telnetsrv_o1.c b/common/utils/telnetsrv/telnetsrv_o1.c index dc48a477d3..7136f5a1b7 100644 --- a/common/utils/telnetsrv/telnetsrv_o1.c +++ b/common/utils/telnetsrv/telnetsrv_o1.c @@ -123,7 +123,7 @@ static int get_stats(char *buf, int debug, telnet_printfunc_t prnt) static b_t last_total[MAX_MOBILES_PER_GNB] = {0}; // TODO: hash table? ue_stat_t ue_stat[MAX_MOBILES_PER_GNB] = {0}; int num_ues = 0; - UE_iterator((NR_UE_info_t **)mac->UE_info.list, it) { + UE_iterator((NR_UE_info_t **)mac->UE_info.connected_ue_list, it) { nr_rlc_statistics_t rlc = {0}; nr_rlc_get_statistics(it->rnti, srb_flag, rb_id, &rlc); b_t *lt = &last_total[num_ues]; @@ -369,7 +369,7 @@ static int stop_modem(char *buf, int debug, telnet_printfunc_t prnt) * scheduler, which has many PUCCH structures filled with expected frame/slot * combinations that won't happen. */ const gNB_MAC_INST *mac = RC.nrmac[0]; - UE_iterator((NR_UE_info_t **)mac->UE_info.list, it) { + UE_iterator((NR_UE_info_t **)mac->UE_info.connected_ue_list, it) { nr_mac_trigger_ul_failure(&it->UE_sched_ctrl, 1); } usleep(50000); diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index f767734e5f..708bb9e831 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -184,8 +184,8 @@ int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1, g_nrOfLay void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) { - NR_UE_info_t *UE_info = RC.nrmac[module_id]->UE_info.list[0]; - AssertFatal(RC.nrmac[module_id]->UE_info.list[1]==NULL, "can have only a single UE\n"); + NR_UE_info_t *UE_info = RC.nrmac[module_id]->UE_info.connected_ue_list[0]; + AssertFatal(RC.nrmac[module_id]->UE_info.connected_ue_list[1] == NULL, "can have only a single UE\n"); NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl; NR_UE_DL_BWP_t *current_BWP = &UE_info->current_DL_BWP; NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon; @@ -802,7 +802,7 @@ printf("%d\n", slot); gNB_mac->pre_processor_dl = nr_dlsim_preprocessor; phy_init_nr_gNB(gNB); N_RB_DL = gNB->frame_parms.N_RB_DL; - NR_UE_info_t *UE_info = RC.nrmac[0]->UE_info.list[0]; + NR_UE_info_t *UE_info = RC.nrmac[0]->UE_info.connected_ue_list[0]; configure_UE_BWP(RC.nrmac[0], scc, &UE_info->UE_sched_ctrl, NULL, UE_info, -1, -1); diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c index 854ef57d15..5a451cff01 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c @@ -37,7 +37,7 @@ bool read_mac_sm(void* data) NR_UEs_t *UE_info = &RC.nrmac[mod_id]->UE_info; size_t num_ues = 0; - UE_iterator(UE_info->list, ue) { + UE_iterator(UE_info->connected_ue_list, ue) { if (ue) num_ues += 1; } @@ -49,7 +49,7 @@ bool read_mac_sm(void* data) } size_t i = 0; //TODO - UE_iterator(UE_info->list, UE) { + UE_iterator(UE_info->connected_ue_list, UE) { const NR_UE_sched_ctrl_t* sched_ctrl = &UE->UE_sched_ctrl; mac_ue_stats_impl_t* rd = &mac->msg.ue_stats[i]; diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c index 08b070eb8d..d98fe35e88 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_rlc.c @@ -38,7 +38,7 @@ uint32_t num_act_rb(NR_UEs_t* const UE_info) assert(UE_info!= NULL); uint32_t act_rb = 0; - UE_iterator(UE_info->list, UE) { + UE_iterator(UE_info->connected_ue_list, UE) { uint16_t const rnti = UE->rnti; for(int rb_id = 1; rb_id < 6; ++rb_id ){ nr_rlc_statistics_t rlc = {0}; @@ -55,7 +55,7 @@ void active_avg_to_tx(NR_UEs_t* const UE_info) { assert(UE_info!= NULL); - UE_iterator(UE_info->list, UE) { + UE_iterator(UE_info->connected_ue_list, UE) { uint16_t const rnti = UE->rnti; for(int rb_id = 1; rb_id < 6; ++rb_id ){ nr_rlc_statistics_t rlc = {0}; @@ -91,7 +91,7 @@ bool read_rlc_sm(void* data) rlc->msg.tstamp = time_now_us(); uint32_t i = 0; - UE_iterator(UE_info->list, UE) { + UE_iterator(UE_info->connected_ue_list, UE) { uint16_t const rnti = UE->rnti; //for every LC ID for(int rb_id = 1; rb_id < 6; ++rb_id ){ diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index c9620e871f..aaf46797ac 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -282,7 +282,7 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst const ngran_node_t node_type = get_e2_node_type(); // Take MAC info - UE_iterator (RC.nrmac[0]->UE_info.list, ue) { + UE_iterator(RC.nrmac[0]->UE_info.connected_ue_list, ue) { NR_UE_sched_ctrl_t *sched_ctrl = &ue->UE_sched_ctrl; // UE matches if any of its DRBs matches for (size_t l = 0; l < seq_arr_size(&sched_ctrl->lc_config); ++l) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 14b7951de3..2c4ef67e3e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -522,7 +522,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP) } if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) { - if (gNB->UE_info.list[0] == NULL) + if (gNB->UE_info.connected_ue_list[0] == NULL) schedule_nr_MsgA_pusch(scc->uplinkConfigCommon, gNB, module_idP, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index b69490fbc9..c6054eeefd 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -323,7 +323,7 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, slot_t slot) { - UE_iterator(RC.nrmac[module_id]->UE_info.list, UE) { + UE_iterator(RC.nrmac[module_id]->UE_info.connected_ue_list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; sched_ctrl->num_total_bytes = 0; sched_ctrl->dl_pdus_total = 0; @@ -865,7 +865,7 @@ static void nr_dlsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s gNB_MAC_INST *mac = RC.nrmac[module_id]; NR_UEs_t *UE_info = &mac->UE_info; - if (UE_info->list[0] == NULL) + if (UE_info->connected_ue_list[0] == NULL) return; NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; @@ -885,7 +885,7 @@ static void nr_dlsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s max_sched_ues = min(max_sched_ues, MAX_DCI_CORESET); /* proportional fair scheduling algorithm */ - pf_dl(module_id, frame, slot, UE_info->list, max_sched_ues, num_beams, n_rb_sched); + pf_dl(module_id, frame, slot, UE_info->connected_ue_list, max_sched_ues, num_beams, n_rb_sched); } nr_pp_impl_dl nr_init_dlsch_preprocessor(int CC_id) { @@ -940,7 +940,7 @@ void nr_schedule_ue_spec(module_id_t module_id, const NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters; gNB_mac->mac_stats.total_prb_aggregate += NRRIV2BW(initialDL->locationAndBandwidth, MAX_BWP_SIZE); - UE_iterator(UE_info->list, UE) { + UE_iterator(UE_info->connected_ue_list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 55d9738938..bc7b40937f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -62,7 +62,7 @@ void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot) int slot_period = slot % mac->frame_structure.numb_slots_period; if (!is_xlsch_in_slot(dlsch_slot_bitmap, slot_period)) return; - NR_UE_info_t *UE = mac->UE_info.list[0]; + NR_UE_info_t *UE = mac->UE_info.connected_ue_list[0]; NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; @@ -214,9 +214,9 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ NR_COMMON_channels_t *cc = nr_mac->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_UE_info_t *UE = nr_mac->UE_info.list[0]; + NR_UE_info_t *UE = nr_mac->UE_info.connected_ue_list[0]; - AssertFatal(nr_mac->UE_info.list[1] == NULL, + AssertFatal(nr_mac->UE_info.connected_ue_list[1] == NULL, "cannot handle more than one UE\n"); if (UE == NULL) return false; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index b9f6a193b7..68d27be46a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2061,7 +2061,7 @@ void remove_front_nr_list(NR_list_t *listP) NR_UE_info_t *find_nr_UE(NR_UEs_t *UEs, rnti_t rntiP) { - UE_iterator(UEs->list, UE) { + UE_iterator(UEs->connected_ue_list, UE) { if (UE->rnti == rntiP) { LOG_D(NR_MAC,"Search and found rnti: %04x\n", rntiP); return UE; @@ -2508,7 +2508,7 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon; NR_UEs_t *UE_info = &nr_mac->UE_info; LOG_I(NR_MAC, "Adding new UE context with RNTI 0x%04x\n", rntiP); - dump_nr_list(UE_info->list); + dump_nr_list(UE_info->connected_ue_list); // We will attach at the end, to mitigate race conditions // This is not good, but we will fix it progressively @@ -2563,8 +2563,8 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf NR_SCHED_LOCK(&UE_info->mutex); int i; for(i=0; ilist[i] == NULL) { - UE_info->list[i] = UE; + if (UE_info->connected_ue_list[i] == NULL) { + UE_info->connected_ue_list[i] = UE; break; } } @@ -2577,7 +2577,7 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf NR_SCHED_UNLOCK(&UE_info->mutex); LOG_D(NR_MAC, "Add NR rnti %x\n", rntiP); - dump_nr_list(UE_info->list); + dump_nr_list(UE_info->connected_ue_list); return (UE); } @@ -2686,7 +2686,7 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti) NR_UEs_t *UE_info = &nr_mac->UE_info; NR_SCHED_LOCK(&UE_info->mutex); - UE_iterator(UE_info->list, UE) { + UE_iterator(UE_info->connected_ue_list, UE) { if (UE->rnti==rnti) break; } @@ -2698,11 +2698,11 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti) } NR_UE_info_t * newUEs[MAX_MOBILES_PER_GNB+1]={0}; - int newListIdx=0; - for (int i=0; ilist[i] && UE_info->list[i]->rnti != rnti) - newUEs[newListIdx++]=UE_info->list[i]; - memcpy(UE_info->list, newUEs, sizeof(UE_info->list)); + int newListIdx = 0; + for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) + if(UE_info->connected_ue_list[i] && UE_info->connected_ue_list[i]->rnti != rnti) + newUEs[newListIdx++] = UE_info->connected_ue_list[i]; + memcpy(UE_info->connected_ue_list, newUEs, sizeof(UE_info->connected_ue_list)); NR_SCHED_UNLOCK(&UE_info->mutex); const int CC_id = 0; @@ -2799,7 +2799,7 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, slot_t slot, nfapi_nr_dl_tt UE_info->sched_csirs = 0; - UE_iterator(UE_info->list, UE) { + UE_iterator(UE_info->connected_ue_list, UE) { NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; // CSI-RS is common to all UEs in a given BWP @@ -3161,7 +3161,7 @@ void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot) NR_SCHED_ENSURE_LOCKED(&mac->sched_lock); NR_UEs_t *UE_info = &mac->UE_info; - UE_iterator(UE_info->list, UE) { + UE_iterator(UE_info->connected_ue_list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; if (nr_mac_check_release(sched_ctrl, UE->rnti)) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index 2f6313de96..c3ebb5ab9b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -521,7 +521,7 @@ void nr_schedule_srs(int module_id, frame_t frame, int slot) NR_UEs_t *UE_info = &nrmac->UE_info; - UE_iterator(UE_info->list, UE) { + UE_iterator(UE_info->connected_ue_list, UE) { const int CC_id = 0; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index ddb5ba9ead..5254ff5b59 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -179,7 +179,7 @@ void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, slot_t slotP) if (!is_ul_slot(slotP, &nrmac->frame_structure)) return; - UE_iterator(nrmac->UE_info.list, UE) { + UE_iterator(nrmac->UE_info.connected_ue_list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; const int pucch_index = get_pucch_index(frameP, slotP, &nrmac->frame_structure, sched_ctrl->sched_pucch_size); NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[pucch_index]; @@ -217,7 +217,7 @@ void nr_csi_meas_reporting(int Mod_idP,frame_t frame, slot_t slot) /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); - UE_iterator(nrmac->UE_info.list, UE ) { + UE_iterator(nrmac->UE_info.connected_ue_list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; const int n_slots_frame = nrmac->frame_structure.numb_slots_frame; @@ -1219,7 +1219,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, slot_t slot) if (!is_ul_slot(slot, &nrmac->frame_structure)) return; const int CC_id = 0; - UE_iterator(nrmac->UE_info.list, UE) { + UE_iterator(nrmac->UE_info.connected_ue_list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; const int n_slots_frame = nrmac->frame_structure.numb_slots_frame; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index c4cfd4181e..cbbcbd00a9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -56,7 +56,7 @@ int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot) } // Avoid slots with the SRS - UE_iterator(nrmac->UE_info.list, UE) { + UE_iterator(nrmac->UE_info.connected_ue_list, UE) { NR_sched_srs_t sched_srs = UE->UE_sched_ctrl.sched_srs; if(sched_srs.srs_scheduled && sched_srs.frame == frame && sched_srs.slot == slot) return 1; @@ -2279,7 +2279,7 @@ static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s { gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; // no UEs - if (nr_mac->UE_info.list[0] == NULL) + if (nr_mac->UE_info.connected_ue_list[0] == NULL) return false; NR_COMMON_channels_t *cc = nr_mac->common_channels; @@ -2308,7 +2308,7 @@ static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s max_sched_ues = min(max_sched_ues, MAX_DCI_CORESET); /* proportional fair scheduling algorithm */ - pf_ul(module_id, frame, slot, sched_frame, sched_slot, nr_mac->UE_info.list, max_sched_ues, num_beams, len); + pf_ul(module_id, frame, slot, sched_frame, sched_slot, nr_mac->UE_info.connected_ue_list, max_sched_ues, num_beams, len); return true; } @@ -2369,7 +2369,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_ NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon; NR_UEs_t *UE_info = &nr_mac->UE_info; - UE_iterator( UE_info->list, UE) { + UE_iterator(UE_info->connected_ue_list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; if (sched_ctrl->ul_failure && !get_softmodem_params()->phy_test) continue; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 32943097ba..51357e2978 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -105,7 +105,7 @@ void du_clear_all_ue_states() gNB_MAC_INST *mac = RC.nrmac[0]; NR_SCHED_LOCK(&mac->sched_lock); - NR_UE_info_t *UE = *mac->UE_info.list; + NR_UE_info_t *UE = *mac->UE_info.connected_ue_list; instance_t f1inst = get_f1_gtp_instance(); @@ -116,7 +116,7 @@ void du_clear_all_ue_states() if (du_exists_f1_ue_data(rnti)) du_remove_f1_ue_data(rnti); newGtpuDeleteAllTunnels(f1inst, rnti); - UE = *mac->UE_info.list; + UE = *mac->UE_info.connected_ue_list; } NR_SCHED_UNLOCK(&mac->sched_lock); } diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 4d732bb3eb..13da756d56 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -106,7 +106,7 @@ void *nrmac_stats_thread(void *arg) { } void clear_mac_stats(gNB_MAC_INST *gNB) { - UE_iterator(gNB->UE_info.list, UE) { + UE_iterator(gNB->UE_info.connected_ue_list, UE) { memset(&UE->mac_stats,0,sizeof(UE->mac_stats)); } } @@ -121,7 +121,7 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset NR_SCHED_ENSURE_LOCKED(&gNB->sched_lock); NR_SCHED_LOCK(&gNB->UE_info.mutex); - UE_iterator(gNB->UE_info.list, UE) { + UE_iterator(gNB->UE_info.connected_ue_list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_mac_stats_t *stats = &UE->mac_stats; const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0; @@ -359,9 +359,9 @@ void mac_top_destroy_gNB(gNB_MAC_INST *mac) ASN_STRUCT_FREE(asn_DEF_NR_ServingCellConfig, cc->pre_ServingCellConfig); ASN_STRUCT_FREE(asn_DEF_NR_ServingCellConfigCommon, cc->ServingCellConfigCommon); NR_UEs_t *UE_info = &mac->UE_info; - for (int i = 0; i < sizeofArray(UE_info->list); ++i) - if (UE_info->list[i]) - delete_nr_ue_data(UE_info->list[i], cc, &UE_info->uid_allocator); + for (int i = 0; i < sizeofArray(UE_info->connected_ue_list); ++i) + if (UE_info->connected_ue_list[i]) + delete_nr_ue_data(UE_info->connected_ue_list[i], cc, &UE_info->uid_allocator); } void nr_mac_send_f1_setup_req(void) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 83802182e0..5d14bd9007 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -781,7 +781,7 @@ typedef struct { /// scheduling control info // last element always NULL pthread_mutex_t mutex; - NR_UE_info_t *list[MAX_MOBILES_PER_GNB+1]; + NR_UE_info_t *connected_ue_list[MAX_MOBILES_PER_GNB + 1]; // bitmap of CSI-RS already scheduled in current slot int sched_csirs; uid_allocator_t uid_allocator; From 8f62baefa61e770635cb931ae587eb8c80350ca8 Mon Sep 17 00:00:00 2001 From: francescomani Date: Mon, 3 Mar 2025 09:52:21 +0100 Subject: [PATCH 05/25] Use list of UEs during RA instead of array of RA processes - rewrite add_UE_to_list() and rewrite remove_UE_from_list() to simplify list handling - return pointer from get_new_nr_ue_inst(); it's completely freed by delete_nr_ue_data() - have add_new_UE_RA() add UE context to access list; remove with nr_release_ra_UE() - have add_connected_nr_ue() only add UE to connected list; to move from access to connected use transition_ra_connected_nr_ue(); remove with mac_remove_nr_ue() as previously - free memory on problems during RA - add some documentation - in NSA/HO: check for pre-configured RA process - there are asserts in all functions to clarify when a UE has RA --- openair1/SIMULATION/NR_PHY/dlsim.c | 4 +- openair2/LAYER2/NR_MAC_gNB/config.c | 50 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 487 +++++++++--------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 3 - .../NR_MAC_gNB/gNB_scheduler_primitives.c | 285 +++++----- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 92 ++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 237 ++++----- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 33 +- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 25 +- openair2/LAYER2/NR_MAC_gNB/main.c | 3 + openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 21 +- openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 2 +- openair2/RRC/NR/rrc_gNB_nsa.c | 14 +- 13 files changed, 584 insertions(+), 672 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 708bb9e831..8408d6ecb0 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -185,7 +185,7 @@ int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1, g_nrOfLay void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot) { NR_UE_info_t *UE_info = RC.nrmac[module_id]->UE_info.connected_ue_list[0]; - AssertFatal(RC.nrmac[module_id]->UE_info.connected_ue_list[1] == NULL, "can have only a single UE\n"); + AssertFatal(RC.nrmac[module_id]->UE_info.connected_ue_list[1] == NULL, "Only single UE allowed in dlsim\n"); NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl; NR_UE_DL_BWP_t *current_BWP = &UE_info->current_DL_BWP; NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon; @@ -804,7 +804,7 @@ printf("%d\n", slot); N_RB_DL = gNB->frame_parms.N_RB_DL; NR_UE_info_t *UE_info = RC.nrmac[0]->UE_info.connected_ue_list[0]; - configure_UE_BWP(RC.nrmac[0], scc, &UE_info->UE_sched_ctrl, NULL, UE_info, -1, -1); + configure_UE_BWP(RC.nrmac[0], scc, UE_info, false, -1, -1); // stub to configure frame_parms // nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions); diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 90891919db..dcd5fa220f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -858,14 +858,6 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c find_SSB_and_RO_available(nrmac); - NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; - NR_SCHED_LOCK(&nrmac->sched_lock); - for (int n = 0; n < NR_NB_RA_PROC_MAX; n++) { - NR_RA_t *ra = &cc->ra[n]; - nr_clear_ra_proc(ra); - } - NR_SCHED_UNLOCK(&nrmac->sched_lock); - if (IS_SA_MODE(get_softmodem_params())) config_sched_ctrlCommon(nrmac); } @@ -979,18 +971,17 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t DevAssert(get_softmodem_params()->phy_test); NR_SCHED_LOCK(&nrmac->sched_lock); - NR_UE_info_t *UE = add_new_nr_ue(nrmac, rnti, CellGroup); - if (!UE) { + NR_UE_info_t *UE = get_new_nr_ue_inst(&nrmac->UE_info.uid_allocator, rnti, CellGroup); + DevAssert(UE != NULL); // test-mode: we assume we can always create a UE + free_and_zero(UE->ra); // test-mode (sims, phy-test): UE will not do RA + bool res = add_connected_nr_ue(nrmac, UE); + if (!res) { LOG_E(NR_MAC, "Error adding UE %04x\n", rnti); + delete_nr_ue_data(UE, NULL, &nrmac->UE_info.uid_allocator); NR_SCHED_UNLOCK(&nrmac->sched_lock); return false; } - - if (CellGroup->spCellConfig && CellGroup->spCellConfig->reconfigurationWithSync - && CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated - && CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra) { - nr_mac_prepare_ra_ue(RC.nrmac[0], UE->rnti, CellGroup); - } + configure_UE_BWP(nrmac, nrmac->common_channels[0].ServingCellConfigCommon, UE, false, -1, -1); process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, CellGroup->rlc_BearerToAddModList); AssertFatal(CellGroup->rlc_BearerToReleaseList == NULL, "cannot release bearers while adding new UEs\n"); NR_SCHED_UNLOCK(&nrmac->sched_lock); @@ -998,32 +989,18 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t return true; } -bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup) +void nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, NR_UE_info_t *UE) { DevAssert(nrmac != NULL); - DevAssert(CellGroup != NULL); NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); - - // NSA case: need to pre-configure CFRA - const int CC_id = 0; - NR_COMMON_channels_t *cc = &nrmac->common_channels[CC_id]; - uint8_t ra_index = 0; - /* checking for free RA process */ - for(; ra_index < NR_NB_RA_PROC_MAX; ra_index++) { - if ((cc->ra[ra_index].ra_state == nrRA_gNB_IDLE) && (!cc->ra[ra_index].cfra)) - break; - } - if (ra_index == NR_NB_RA_PROC_MAX) { - LOG_E(NR_MAC, "RA processes are not available for CFRA RNTI %04x\n", rnti); - return false; - } - NR_RA_t *ra = &cc->ra[ra_index]; + NR_RA_t *ra = UE->ra; ra->cfra = true; - ra->rnti = rnti; - ra->CellGroup = CellGroup; + NR_CellGroupConfig_t *CellGroup = UE->CellGroup; + DevAssert(CellGroup != NULL); struct NR_CFRA *cfra = CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra; uint8_t num_preamble = cfra->resources.choice.ssb->ssb_ResourceList.list.count; ra->preambles.num_preambles = num_preamble; + NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; for (int i = 0; i < cc->num_active_ssb; i++) { for (int j = 0; j < num_preamble; j++) { if (cc->ssb_index[i] == cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ssb) { @@ -1033,8 +1010,7 @@ bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig } } } - LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup\n", ra->cfra ? "CFRA" : "CBRA", rnti); - return true; + LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup\n", ra->cfra ? "CFRA" : "CBRA", UE->rnti); } /* Prepare a new CellGroupConfig to be applied for this UE. We cannot diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 2c4ef67e3e..beb66aa6b7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -49,14 +49,14 @@ // forward declaration of functions used in this file static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, NR_ServingCellConfigCommon_t *scc, - const NR_RA_t *ra, + NR_UE_info_t *UE, int startSymbolAndLength, int scs, int bwp_size, int bwp_start, int mappingtype, int fh); -static void nr_fill_rar(uint8_t Mod_idP, NR_RA_t *ra, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu); +static void nr_fill_rar(uint8_t Mod_idP, NR_UE_info_t *UE, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu); static const uint8_t DELTA[4] = {2, 3, 4, 6}; @@ -636,39 +636,26 @@ int nr_fill_successrar(const NR_UE_sched_ctrl_t *ue_sched_ctl, return mac_pdu_length; } -static bool ra_contains_preamble(const NR_RA_t *ra, uint16_t preamble_index) +/** @brief find UE with RA process for given preamble */ +static NR_UE_info_t *get_existing_ra(gNB_MAC_INST *nr_mac, uint16_t preamble_index) { - for (int j = 0; j < ra->preambles.num_preambles; j++) { - // check if the preamble received correspond to one of the listed or configured preambles - if (preamble_index == ra->preambles.preamble_list[j]) { - if (ra->rnti == 0 && get_softmodem_params()->nsa) - continue; - return true; + UE_iterator(nr_mac->UE_info.access_ue_list, UE) { + NR_RA_t *ra = UE->ra; + for (int i = 0; i < ra->preambles.num_preambles; ++i) { + if (ra->preambles.preamble_list[i] == preamble_index) + return UE; } } - return false; + return NULL; } -static NR_RA_t *find_free_nr_RA(NR_RA_t *ra_base, int ra_count, uint16_t preamble_index) +/** @brief add UE to list of UEs doing RA. + * + * Remove with nr_release_ra_UE(). */ +bool add_new_UE_RA(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) { - // for posteriority: in the past we checked the beam index, but only in CFRA - //if (ra->cfra && preamble_index != ra->preamble.preamble_list[beam_index]]) - // // then is not right RA - // - // that seems strange because: - // - we check preamble_index already - // - why only CFRA? - - for (int i = 0; i < ra_count; ++i) { - NR_RA_t *ra = &ra_base[i]; - if (ra->ra_state != nrRA_gNB_IDLE) - continue; - if (!ra_contains_preamble(ra, preamble_index)) - continue; - - return ra; - } - return NULL; + DevAssert(UE->ra); // a UE in the acess_ue_list needs to have an RA process + return add_UE_to_list(NR_NB_RA_PROC_MAX, nr_mac->UE_info.access_ue_list, UE); } static uint8_t nr_get_msg3_tpc(uint32_t preamble_power) @@ -704,8 +691,8 @@ static unsigned int get_slot_RA(const NR_ServingCellConfigCommon_t *scc, void nr_initiate_ra_proc(module_id_t module_idP, int CC_id, - frame_t frameP, - int slotP, + frame_t frame, + int slot, uint16_t preamble_index, uint8_t freq_index, uint8_t symbol, @@ -717,32 +704,48 @@ void nr_initiate_ra_proc(module_id_t module_idP, gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_SCHED_LOCK(&nr_mac->sched_lock); - NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; - - NR_RA_t *ra = find_free_nr_RA(cc->ra, sizeofArray(cc->ra), preamble_index); - if (ra == NULL) { - LOG_E(NR_MAC, "FAILURE: %4d.%2d initiating RA procedure for preamble index %d: no free RA process\n", frameP, slotP, preamble_index); + /* check if preamble exists (NSA, HO cases) */ + NR_UE_info_t *UE = get_existing_ra(nr_mac, preamble_index); + if ((get_softmodem_params()->nsa || get_softmodem_params()->do_ra) && !UE) { + /* we are in NSA, but no UE has been configured => we ignore it */ + LOG_W(NR_MAC, "random access with preamble %d: no pre-configured RA process found\n", preamble_index); NR_SCHED_UNLOCK(&nr_mac->sched_lock); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0); return; } - if (ra->rnti == 0) { // This condition allows for the usage of a preconfigured rnti for the CFRA - bool rnti_found = nr_mac_get_new_rnti(&nr_mac->UE_info, cc->ra, sizeofArray(cc->ra), &ra->rnti); + if (!UE) { + /* in CBRA: we don't know this UE yet. There might be CFRA (e.g., HO IN SA) + * where we know the UE */ + rnti_t rnti; + bool rnti_found = nr_mac_get_new_rnti(&nr_mac->UE_info, &rnti); if (!rnti_found) { LOG_E(NR_MAC, "initialisation random access: no more available RNTIs for new UE\n"); - nr_clear_ra_proc(ra); + NR_SCHED_UNLOCK(&nr_mac->sched_lock); + return; + } + + UE = get_new_nr_ue_inst(&nr_mac->UE_info.uid_allocator, rnti, NULL); + if (!UE) { + LOG_E(NR_MAC, "FAILURE: %4d.%2d cannot create UE context, ignoring RA because RRC Reject not implemented yet\n", frame, slot); + NR_SCHED_UNLOCK(&nr_mac->sched_lock); + return; + } + if (!add_new_UE_RA(nr_mac, UE)) { + LOG_E(NR_MAC, "FAILURE: %4d.%2d initiating RA procedure for preamble index %d: no free RA process\n", frame, slot, preamble_index); + delete_nr_ue_data(UE, NULL, &nr_mac->UE_info.uid_allocator); NR_SCHED_UNLOCK(&nr_mac->sched_lock); return; } } - ra->preamble_frame = frameP; - ra->preamble_slot = slotP; + NR_RA_t *ra = UE->ra; + ra->preamble_frame = frame; + ra->preamble_slot = slot; ra->preamble_index = preamble_index; ra->timing_offset = timing_offset; ra->msg3_TPC = nr_get_msg3_tpc(preamble_power); + NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; // 3GPP TS 38.321 Section 5.1.3(a) says t_id for RA-RNTI depends on mu as specified in clause 5.3.2 in TS 38.211 // so mu = 0 for prach format < 4. @@ -750,10 +753,10 @@ void nr_initiate_ra_proc(module_id_t module_idP, NR_MsgA_ConfigCommon_r16_t *msgacc = NULL; if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) msgacc = scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16->choice.setup; - uint32_t slot_RA = get_slot_RA(scc, rach_ConfigCommon, msgacc, cc->frame_type, slotP); uint8_t ul_carrier_id = 0; // 0 for NUL 1 for SUL + uint32_t slot_RA = get_slot_RA(scc, rach_ConfigCommon, msgacc, cc->frame_type, slot); ra->RA_rnti = nr_get_ra_rnti(symbol, slot_RA, freq_index, ul_carrier_id); - if (scc->uplinkConfigCommon->initialUplinkBWP->ext1 && scc->uplinkConfigCommon->initialUplinkBWP->ext1->msgA_ConfigCommon_r16) { + if (msgacc) { ra->ra_type = RA_2_STEP; ra->ra_state = nrRA_WAIT_MsgA_PUSCH; ra->MsgB_rnti = nr_get_MsgB_rnti(symbol, slot_RA, freq_index, ul_carrier_id); @@ -762,18 +765,15 @@ void nr_initiate_ra_proc(module_id_t module_idP, ra->ra_state = nrRA_Msg2; } - int index = ra - cc->ra; - LOG_A(NR_MAC, "%d.%d UE RA-RNTI %04x TC-RNTI %04x: Activating RA process index %d\n", frameP, slotP, ra->RA_rnti, ra->rnti, index); + LOG_A(NR_MAC, "%d.%d UE RA-RNTI %04x TC-RNTI %04x: initiating RA procedure\n", frame, slot, ra->RA_rnti, UE->rnti); // Configure RA BWP - configure_UE_BWP(nr_mac, scc, NULL, ra, NULL, -1, -1); - + configure_UE_BWP(nr_mac, scc, UE, true, -1, -1); // return current SSB order in the list of tranmitted SSBs - int n_ssb = ssb_index_from_prach(module_idP, frameP, slotP, preamble_index, freq_index, symbol); - ra->beam_id = get_fapi_beamforming_index(nr_mac, cc->ssb_index[n_ssb]); + int n_ssb = ssb_index_from_prach(module_idP, frame, slot, preamble_index, freq_index, symbol); + UE->UE_beam_index = get_fapi_beamforming_index(nr_mac, cc->ssb_index[n_ssb]); NR_SCHED_UNLOCK(&nr_mac->sched_lock); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0); } @@ -796,14 +796,15 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, int CC_id, frame_t frame, slot_t slot, - NR_RA_t *ra, + NR_UE_info_t *UE, nfapi_nr_ul_dci_request_t *ul_dci_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; + NR_RA_t *ra = UE->ra; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP; - NR_UE_ServingCell_Info_t *sc_info = &ra->sc_info; + NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; + NR_UE_ServingCell_Info_t *sc_info = &UE->sc_info; NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = ul_bwp->tdaList_Common; int mu = ul_bwp->scs; @@ -813,12 +814,12 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, const int sched_slot = (slot + K2) % slots_frame; if (is_ul_slot(sched_slot, &nr_mac->frame_structure)) { - NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info, sched_frame, sched_slot, ra->beam_id, slots_frame); + NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame); if (beam_ul.idx < 0) return; - NR_beam_alloc_t beam_dci = beam_allocation_procedure(&nr_mac->beam_info, frame, slot, ra->beam_id, slots_frame); + NR_beam_alloc_t beam_dci = beam_allocation_procedure(&nr_mac->beam_info, frame, slot, UE->UE_beam_index, slots_frame); if (beam_dci.idx < 0) { - reset_beam_status(&nr_mac->beam_info, sched_frame, sched_slot, ra->beam_id, slots_frame, beam_ul.new_beam); + reset_beam_status(&nr_mac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, slots_frame, beam_ul.new_beam); return; } int fh = 0; @@ -849,7 +850,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, "%4d%2d: RA RNTI %04x CC_id %d Scheduling retransmission of Msg3 in (%d,%d)\n", frame, slot, - ra->rnti, + UE->rnti, CC_id, sched_frame, sched_slot); @@ -871,12 +872,12 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, nfapi_nr_pusch_pdu_t *pusch_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pusch_pdu; memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t)); - fill_msg3_pusch_pdu(pusch_pdu, scc, ra, startSymbolAndLength, mu, BWPSize, BWPStart, mappingtype, fh); + fill_msg3_pusch_pdu(pusch_pdu, scc, UE, startSymbolAndLength, mu, BWPSize, BWPStart, mappingtype, fh); future_ul_tti_req->n_pdus += 1; // generation of DCI 0_0 to schedule msg3 retransmission - NR_SearchSpace_t *ss = ra->ra_ss; - NR_ControlResourceSet_t *coreset = ra->coreset; + NR_SearchSpace_t *ss = UE->UE_sched_ctrl.search_space; + NR_ControlResourceSet_t *coreset = UE->UE_sched_ctrl.coreset; AssertFatal(coreset, "Coreset cannot be null for RA-Msg3 retransmission\n"); const int coresetid = coreset->controlResourceSetId; @@ -888,7 +889,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, ul_dci_request_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu)); pdcch_pdu_rel15 = &ul_dci_request_pdu->pdcch_pdu.pdcch_pdu_rel15; ul_dci_req->numPdus += 1; - nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch); + nr_configure_pdcch(pdcch_pdu_rel15, coreset, &UE->UE_sched_ctrl.sched_pdcch); nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15; } @@ -899,18 +900,18 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, beam_dci.idx, ss, coreset, - &ra->sched_pdcch, + &UE->UE_sched_ctrl.sched_pdcch, true, 0); if (CCEIndex < 0) { - LOG_E(NR_MAC, "UE %04x cannot find free CCE!\n", ra->rnti); + LOG_E(NR_MAC, "UE %04x cannot find free CCE!\n", UE->rnti); return; } // Fill PDCCH DL DCI PDU nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; pdcch_pdu_rel15->numDlDci++; - dci_pdu->RNTI = ra->rnti; + dci_pdu->RNTI = UE->rnti; dci_pdu->ScramblingId = *scc->physCellId; dci_pdu->ScramblingRNTI = 0; dci_pdu->AggregationLevel = aggregation_level; @@ -922,7 +923,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, dci_pdu->precodingAndBeamforming.prg_size = 0; dci_pdu->precodingAndBeamforming.dig_bf_interfaces = 1; dci_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = 0; - dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = ra->beam_id; + dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; dci_pdu_rel15_t uldci_payload={0}; @@ -940,7 +941,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, ra->msg3_TPC = 1; fill_dci_pdu_rel15(sc_info, - &ra->DL_BWP, + &UE->current_DL_BWP, ul_bwp, dci_pdu, &uldci_payload, @@ -956,7 +957,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, fill_pdcch_vrb_map(nr_mac, CC_id, - &ra->sched_pdcch, + &UE->UE_sched_ctrl.sched_pdcch, CCEIndex, aggregation_level, beam_dci.idx); @@ -971,7 +972,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, ra, scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer, K2, - ra->UL_BWP.scs); + ul_bwp->scs); // reset state to wait msg3 ra->ra_state = nrRA_WAIT_Msg3; @@ -987,6 +988,7 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc, int slot, NR_RA_t *ra, NR_beam_info_t *beam_info, + int ue_beam_idx, const frame_structure_t *fs) { DevAssert(tda_list != NULL); @@ -1025,7 +1027,7 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc, continue; // check if it is possible to allocate MSG3 in a beam in this slot - NR_beam_alloc_t beam = beam_allocation_procedure(beam_info, temp_frame, temp_slot, ra->beam_id, slots_per_frame); + NR_beam_alloc_t beam = beam_allocation_procedure(beam_info, temp_frame, temp_slot, ue_beam_idx, slots_per_frame); if (beam.idx < 0) continue; @@ -1040,14 +1042,15 @@ static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc, return false; } -static bool nr_get_Msg3alloc(gNB_MAC_INST *mac, int CC_id, int current_slot, frame_t current_frame, NR_RA_t *ra) +static bool nr_get_Msg3alloc(gNB_MAC_INST *mac, int CC_id, int current_slot, frame_t current_frame, NR_UE_info_t *UE) { + NR_RA_t *ra = UE->ra; DevAssert(ra->Msg3_tda_id >= 0 && ra->Msg3_tda_id < 16); uint16_t msg3_nb_rb = 8; // sdu has 6 or 8 bytes - NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP; - NR_UE_ServingCell_Info_t *sc_info = &ra->sc_info; + NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; + NR_UE_ServingCell_Info_t *sc_info = &UE->sc_info; const NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = ul_bwp->tdaList_Common; @@ -1056,7 +1059,7 @@ static bool nr_get_Msg3alloc(gNB_MAC_INST *mac, int CC_id, int current_slot, fra LOG_I(NR_MAC, "UE %04x: Msg3 scheduled at %d.%d (%d.%d TDA %u)\n", - ra->rnti, + UE->rnti, ra->Msg3_frame, ra->Msg3_slot, current_frame, @@ -1101,7 +1104,7 @@ static bool nr_get_Msg3alloc(gNB_MAC_INST *mac, int CC_id, int current_slot, fra static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, NR_ServingCellConfigCommon_t *scc, - const NR_RA_t *ra, + NR_UE_info_t *UE, int startSymbolAndLength, int scs, int bwp_size, @@ -1110,12 +1113,11 @@ static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, int fh) { int start_symbol_index,nr_of_symbols; - SLIV2SL(startSymbolAndLength, &start_symbol_index, &nr_of_symbols); int mcsindex = -1; // init value - + const NR_RA_t *ra = UE->ra; pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA; - pusch_pdu->rnti = ra->rnti; + pusch_pdu->rnti = UE->rnti; pusch_pdu->handle = 0; pusch_pdu->bwp_start = bwp_start; pusch_pdu->bwp_size = bwp_size; @@ -1169,7 +1171,7 @@ static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, pusch_pdu->beamforming.num_prgs = 0; pusch_pdu->beamforming.prg_size = 0; // bwp_size; pusch_pdu->beamforming.dig_bf_interface = 1; - pusch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = ra->beam_id; + pusch_pdu->beamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; int num_dmrs_symb = 0; for(int i = start_symbol_index; i < start_symbol_index+nr_of_symbols; i++) @@ -1196,16 +1198,16 @@ static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, } } -static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_t slotP, NR_RA_t *ra, uint8_t *RAR_pdu) +static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_t slotP, NR_UE_info_t *UE, uint8_t *RAR_pdu) { gNB_MAC_INST *mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP; - NR_UE_ServingCell_Info_t *sc_info = &ra->sc_info; - + NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; + NR_UE_ServingCell_Info_t *sc_info = &UE->sc_info; + NR_RA_t *ra = UE->ra; if (ra->ra_state == nrRA_gNB_IDLE) { - LOG_W(NR_MAC,"RA is not active for RA %X. skipping msg3 scheduling\n", ra->rnti); + LOG_W(NR_MAC,"RA is not active for RA %X. skipping msg3 scheduling\n", UE->rnti); return; } @@ -1222,7 +1224,7 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ vrb_map_UL[i + ra->msg3_first_rb + ra->msg3_bwp_start] |= mask; } - LOG_D(NR_MAC, "UE %04x: %d.%d RA is active, Msg3 in (%d,%d)\n", ra->rnti, frameP, slotP, ra->Msg3_frame, ra->Msg3_slot); + LOG_D(NR_MAC, "UE %04x: %d.%d RA is active, Msg3 in (%d,%d)\n", UE->rnti, frameP, slotP, ra->Msg3_frame, ra->Msg3_slot); buffer_index = ul_buffer_index(ra->Msg3_frame, ra->Msg3_slot, slots_frame, mac->UL_tti_req_ahead_size); nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[CC_id][buffer_index]; AssertFatal(future_ul_tti_req->SFN == ra->Msg3_frame @@ -1244,7 +1246,7 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ LOG_D(NR_MAC, "UE %04x: %d.%d Adding Msg3 UL Config Request for (%d,%d) : (%d,%d,%d)\n", - ra->rnti, + UE->rnti, frameP, slotP, ra->Msg3_frame, @@ -1253,18 +1255,18 @@ static void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, slot_ ra->msg3_first_rb, ra->msg3_round); - fill_msg3_pusch_pdu(pusch_pdu, scc, ra, startSymbolAndLength, ul_bwp->scs, ibwp_size, ra->msg3_bwp_start, mappingtype, fh); + fill_msg3_pusch_pdu(pusch_pdu, scc, UE, startSymbolAndLength, ul_bwp->scs, ibwp_size, ra->msg3_bwp_start, mappingtype, fh); future_ul_tti_req->n_pdus += 1; // calling function to fill rar message - nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu); + nr_fill_rar(module_idP, UE, RAR_pdu, pusch_pdu); } -static bool check_msg2_monitoring(const NR_RA_t *ra, int slots_per_frame, int current_frame, int current_slot) +static bool check_msg2_monitoring(const NR_SearchSpace_t *ss, int slots_per_frame, int current_frame, int current_slot) { // check if the slot is not among the PDCCH monitored ones (38.213 10.1) int monitoring_slot_period, monitoring_offset; - get_monitoring_period_offset(ra->ra_ss, &monitoring_slot_period, &monitoring_offset); + get_monitoring_period_offset(ss, &monitoring_slot_period, &monitoring_offset); if ((current_frame * slots_per_frame + current_slot - monitoring_offset) % monitoring_slot_period != 0) return false; return true; @@ -1334,8 +1336,7 @@ static bool msg2_in_response_window(int rach_frame, } static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, - NR_RA_t *ra, - NR_UE_DL_BWP_t *dl_bwp, + NR_UE_info_t *UE, nfapi_nr_dl_tti_request_body_t *dl_req, NR_sched_pucch_t *pucch, NR_pdsch_dmrs_t dmrs_info, @@ -1362,7 +1363,8 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, { // look up the PDCCH PDU for this CC, BWP, and CORESET. If it does not exist, create it. This is especially // important if we have multiple RAs, and the DLSCH has to reuse them, so we need to mark them - NR_ControlResourceSet_t *coreset = ra->coreset; + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + NR_ControlResourceSet_t *coreset = sched_ctrl->coreset; const int coresetid = coreset->controlResourceSetId; nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = nr_mac->pdcch_pdu_idx[CC_id][coresetid]; if (!pdcch_pdu_rel15) { @@ -1372,7 +1374,7 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2 + sizeof(nfapi_nr_dl_tti_pdcch_pdu)); dl_req->nPDUs += 1; pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15; - nr_configure_pdcch(pdcch_pdu_rel15, coreset, &ra->sched_pdcch); + nr_configure_pdcch(pdcch_pdu_rel15, coreset, &sched_ctrl->sched_pdcch); nr_mac->pdcch_pdu_idx[CC_id][coresetid] = pdcch_pdu_rel15; } @@ -1385,7 +1387,7 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - + NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; int mcsTableIdx = dl_bwp->mcsTableIdx; pdsch_pdu_rel15->pduBitmap = 0; @@ -1420,14 +1422,14 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, pdsch_pdu_rel15->StartSymbolIndex = tda.startSymbolIndex; pdsch_pdu_rel15->NrOfSymbols = tda.nrOfSymbols; pdsch_pdu_rel15->dlDmrsSymbPos = dmrs_info.dl_dmrs_symb_pos; - pdsch_pdu_rel15->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(mcsTableIdx, ra->sc_info.dl_bw_tbslbrm, 1); + pdsch_pdu_rel15->maintenance_parms_v3.tbSizeLbrmBytes = nr_compute_tbslbrm(mcsTableIdx, UE->sc_info.dl_bw_tbslbrm, 1); pdsch_pdu_rel15->maintenance_parms_v3.ldpcBaseGraph = get_BG(tb_size << 3, R); pdsch_pdu_rel15->precodingAndBeamforming.num_prgs = 1; pdsch_pdu_rel15->precodingAndBeamforming.prg_size = 275; pdsch_pdu_rel15->precodingAndBeamforming.dig_bf_interfaces = 1; pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].pm_idx = 0; - pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = ra->beam_id; + pdsch_pdu_rel15->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; /* Fill PDCCH DL DCI PDU */ nfapi_nr_dl_dci_pdu_t *dci_pdu = &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci]; @@ -1444,7 +1446,7 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, dci_pdu->precodingAndBeamforming.prg_size = 0; dci_pdu->precodingAndBeamforming.dig_bf_interfaces = 1; dci_pdu->precodingAndBeamforming.prgs_list[0].pm_idx = 0; - dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = ra->beam_id; + dci_pdu->precodingAndBeamforming.prgs_list[0].dig_bf_interface_list[0].beam_idx = UE->UE_beam_index; dci_pdu_rel15_t dci_payload; dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize, @@ -1490,15 +1492,15 @@ static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, pdcch_pdu_rel15->DurationSymbols, pdsch_pdu_rel15->BWPSize); - fill_dci_pdu_rel15(&ra->sc_info, + fill_dci_pdu_rel15(&UE->sc_info, dl_bwp, - &ra->UL_BWP, + &UE->current_UL_BWP, &pdcch_pdu_rel15->dci_pdu[pdcch_pdu_rel15->numDlDci - 1], &dci_payload, NR_DL_DCI_FORMAT_1_0, rnti_type, dl_bwp->bwp_id, - ra->ra_ss, + sched_ctrl->search_space, coreset, 0, // parameter not needed for DCI 1_0 nr_mac->cset0_bwp_size); @@ -1524,7 +1526,7 @@ static void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, slot_t slotP, - NR_RA_t *ra, + NR_UE_info_t *UE, nfapi_nr_dl_tti_request_t *DL_req, nfapi_nr_tx_data_request_t *TX_req) { @@ -1536,28 +1538,30 @@ static void nr_generate_Msg2(module_id_t module_idP, } NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; - NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP; - NR_UE_ServingCell_Info_t *sc_info = &ra->sc_info; + NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; + NR_UE_ServingCell_Info_t *sc_info = &UE->sc_info; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - + NR_RA_t *ra = UE->ra; long rrc_ra_ResponseWindow = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow; const int n_slots_frame = nr_mac->frame_structure.numb_slots_frame; if (!msg2_in_response_window(ra->preamble_frame, ra->preamble_slot, n_slots_frame, rrc_ra_ResponseWindow, frameP, slotP)) { - LOG_E(NR_MAC, "UE RA-RNTI %04x TC-RNTI %04x: exceeded RA window, cannot schedule Msg2\n", ra->RA_rnti, ra->rnti); - nr_clear_ra_proc(ra); + LOG_E(NR_MAC, "UE RA-RNTI %04x TC-RNTI %04x: exceeded RA window, cannot schedule Msg2\n", ra->RA_rnti, UE->rnti); + nr_release_ra_UE(nr_mac, UE->rnti); return; } - if (!check_msg2_monitoring(ra, n_slots_frame, frameP, slotP)) { - LOG_E(NR_MAC, "UE RA-RNTI %04x TC-RNTI %04x: Msg2 not monitored by UE\n", ra->RA_rnti, ra->rnti); + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + NR_SearchSpace_t *ss = sched_ctrl->search_space; + if (!check_msg2_monitoring(ss, n_slots_frame, frameP, slotP)) { + LOG_E(NR_MAC, "UE RA-RNTI %04x TC-RNTI %04x: Msg2 not monitored by UE\n", ra->RA_rnti, UE->rnti); return; } - NR_beam_alloc_t beam = beam_allocation_procedure(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame); + NR_beam_alloc_t beam = beam_allocation_procedure(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame); if (beam.idx < 0) return; - const NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP; + const NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; bool ret = get_feasible_msg3_tda(scc, DELTA[ul_bwp->scs], ul_bwp->tdaList_Common, @@ -1565,19 +1569,17 @@ static void nr_generate_Msg2(module_id_t module_idP, slotP, ra, &nr_mac->beam_info, + UE->UE_beam_index, &nr_mac->frame_structure); if (!ret || ra->Msg3_tda_id > 15) { - LOG_D(NR_MAC, "UE RNTI %04x %d.%d: infeasible Msg3 TDA\n", ra->rnti, frameP, slotP); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + LOG_D(NR_MAC, "UE RNTI %04x %d.%d: infeasible Msg3 TDA\n", UE->rnti, frameP, slotP); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } int mcsIndex = -1; // initialization value int rbStart = 0; int rbSize = 8; - - NR_SearchSpace_t *ss = ra->ra_ss; - long BWPStart = 0; long BWPSize = 0; NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = NULL; @@ -1585,12 +1587,12 @@ static void nr_generate_Msg2(module_id_t module_idP, BWPStart = dl_bwp->BWPStart; BWPSize = sc_info->initial_dl_BWPSize; } else { - type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[cc->ssb_index[ra->beam_id]]; + type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[cc->ssb_index[UE->UE_beam_index]]; BWPStart = type0_PDCCH_CSS_config->cset_start_rb; BWPSize = type0_PDCCH_CSS_config->num_rbs; } - NR_ControlResourceSet_t *coreset = ra->coreset; + NR_ControlResourceSet_t *coreset = sched_ctrl->coreset; AssertFatal(coreset, "Coreset cannot be null for RA-Msg2\n"); const int coresetid = coreset->controlResourceSetId; // Calculate number of symbols @@ -1617,34 +1619,34 @@ static void nr_generate_Msg2(module_id_t module_idP, if (rbStart > (BWPSize - rbSize)) { LOG_W(NR_MAC, "Cannot find free vrb_map for RA RNTI %04x!\n", ra->RA_rnti); - reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, UE->UE_beam_index, n_slots_frame, ra->Msg3_beam.new_beam); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } // Checking if the DCI allocation is feasible in current subframe nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { - LOG_W(NR_MAC, "UE %04x: %d.%d FAPI DL structure is full\n", ra->rnti, frameP, slotP); - reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + LOG_W(NR_MAC, "UE %04x: %d.%d FAPI DL structure is full\n", UE->rnti, frameP, slotP); + reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, UE->UE_beam_index, n_slots_frame, ra->Msg3_beam.new_beam); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } uint8_t aggregation_level; - int CCEIndex = get_cce_index(nr_mac, CC_id, slotP, 0, &aggregation_level, beam.idx, ss, coreset, &ra->sched_pdcch, true, 0); + int CCEIndex = get_cce_index(nr_mac, CC_id, slotP, 0, &aggregation_level, beam.idx, ss, coreset, &sched_ctrl->sched_pdcch, true, 0); if (CCEIndex < 0) { - LOG_W(NR_MAC, "UE %04x: %d.%d cannot find free CCE for Msg2!\n", ra->rnti, frameP, slotP); - reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + LOG_W(NR_MAC, "UE %04x: %d.%d cannot find free CCE for Msg2!\n", UE->rnti, frameP, slotP); + reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, UE->UE_beam_index, n_slots_frame, ra->Msg3_beam.new_beam); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } - bool msg3_ret = nr_get_Msg3alloc(nr_mac, CC_id, slotP, frameP, ra); + bool msg3_ret = nr_get_Msg3alloc(nr_mac, CC_id, slotP, frameP, UE); if (!msg3_ret) { - reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, ra->beam_id, n_slots_frame, ra->Msg3_beam.new_beam); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + reset_beam_status(&nr_mac->beam_info, ra->Msg3_frame, ra->Msg3_slot, UE->UE_beam_index, n_slots_frame, ra->Msg3_beam.new_beam); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } @@ -1653,14 +1655,14 @@ static void nr_generate_Msg2(module_id_t module_idP, // Distance calculation according to SCF222.10.02 RACH.indication (table 3-74) and 38.213 4.2/38.211 4.3.1 // T_c according to 38.211 4.1 float T_c_ns = 0.509; - int numerology = ra->UL_BWP.scs; + int numerology = ul_bwp->scs; float rtt_ns = T_c_ns * 16 * 64 / (1 << numerology) * ra->timing_offset; float speed_of_light_in_meters_per_second = 299792458.0f; float distance_in_meters = speed_of_light_in_meters_per_second * rtt_ns / 1000 / 1000 / 1000 / 2; LOG_A(NR_MAC, "UE %04x: %d.%d Generating RA-Msg2 DCI, RA RNTI 0x%x, state %d, preamble_index(RAPID) %d, " "timing_offset = %d (estimated distance %.1f [m])\n", - ra->rnti, + UE->rnti, frameP, slotP, ra->RA_rnti, @@ -1697,8 +1699,7 @@ static void nr_generate_Msg2(module_id_t module_idP, } prepare_dl_pdus(nr_mac, - ra, - dl_bwp, + UE, dl_req, NULL, dmrs_parms, @@ -1727,28 +1728,25 @@ static void nr_generate_Msg2(module_id_t module_idP, nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[TX_req->Number_of_PDUs]; // Program UL processing for Msg3 - nr_add_msg3(module_idP, CC_id, frameP, slotP, ra, (uint8_t *)&tx_req->TLVs[0].value.direct[0]); + nr_add_msg3(module_idP, CC_id, frameP, slotP, UE, (uint8_t *)&tx_req->TLVs[0].value.direct[0]); // Start RA contention resolution timer in Msg3 transmission slot (current slot + K2) // 3GPP TS 38.321 Section 5.1.5 Contention Resolution start_ra_contention_resolution_timer( ra, scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->ra_ContentionResolutionTimer, - *ra->UL_BWP.tdaList_Common->list.array[ra->Msg3_tda_id]->k2 + get_NTN_Koffset(scc), - ra->UL_BWP.scs); + *ul_bwp->tdaList_Common->list.array[ra->Msg3_tda_id]->k2 + get_NTN_Koffset(scc), + ul_bwp->scs); if (ra->cfra) { - NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_idP]->UE_info, ra->rnti); - if (UE) { - int delay = nr_mac_get_reconfig_delay_slots(ra->DL_BWP.scs); - interrupt_followup_action_t action = UE->reconfigCellGroup ? FOLLOW_INSYNC_RECONFIG : FOLLOW_INSYNC; - nr_mac_interrupt_ue_transmission(RC.nrmac[module_idP], UE, action, delay); - } + int delay = nr_mac_get_reconfig_delay_slots(dl_bwp->scs); + interrupt_followup_action_t action = UE->reconfigCellGroup ? FOLLOW_INSYNC_RECONFIG : FOLLOW_INSYNC; + nr_mac_interrupt_ue_transmission(RC.nrmac[module_idP], UE, action, delay); } LOG_D(NR_MAC, "UE %04x: %d.%d: Setting RA-Msg3 reception (%s) for SFN.Slot %d.%d\n", - ra->rnti, + UE->rnti, frameP, slotP, ra->cfra ? "CFRA" : "CBRA", @@ -1775,7 +1773,7 @@ static void nr_generate_Msg2(module_id_t module_idP, T_BUFFER(&tx_req->TLVs[0].value.direct[0], tx_req->TLVs[0].length)); // Mark the corresponding symbols RBs as used - fill_pdcch_vrb_map(nr_mac, CC_id, &ra->sched_pdcch, CCEIndex, aggregation_level, beam.idx); + fill_pdcch_vrb_map(nr_mac, CC_id, &sched_ctrl->sched_pdcch, CCEIndex, aggregation_level, beam.idx); for (int rb = 0; rb < rbSize; rb++) { vrb_map[BWPStart + rb + rbStart] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols); } @@ -1787,44 +1785,37 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, int CC_id, frame_t frameP, slot_t slotP, - NR_RA_t *ra, + NR_UE_info_t *UE, nfapi_nr_dl_tti_request_t *DL_req, nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; - NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP; + NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; // if it is a DL slot, if the RA is in MSG4 state if (is_dl_slot(slotP, &nr_mac->frame_structure)) { NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_SearchSpace_t *ss = ra->ra_ss; + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + NR_SearchSpace_t *ss = sched_ctrl->search_space; + NR_RA_t *ra = UE->ra; const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4"; - NR_ControlResourceSet_t *coreset = ra->coreset; + NR_ControlResourceSet_t *coreset = sched_ctrl->coreset; AssertFatal(coreset != NULL, "Coreset cannot be null for RA %s\n", ra_type_str); uint16_t mac_sdu_length = 0; - - NR_UE_info_t *UE = find_nr_UE(&nr_mac->UE_info, ra->rnti); - if (!UE) { - LOG_E(NR_MAC, "want to generate %s, but rnti %04x not in the table. Abort RA\n", ra_type_str, ra->rnti); - nr_clear_ra_proc(ra); - return; - } - - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */ int current_harq_pid = sched_ctrl->retrans_dl_harq.head; logical_chan_id_t lcid = DL_SCH_LCID_CCCH; if (current_harq_pid < 0) { // Check for data on SRB0 (RRCSetup) - mac_rlc_status_resp_t srb_status = nr_mac_rlc_status_ind(ra->rnti, frameP, lcid); + mac_rlc_status_resp_t srb_status = nr_mac_rlc_status_ind(UE->rnti, frameP, lcid); if (srb_status.bytes_in_buffer == 0) { lcid = DL_SCH_LCID_DCCH; // Check for data on SRB1 (RRCReestablishment, RRCReconfiguration) - srb_status = nr_mac_rlc_status_ind(ra->rnti, frameP, lcid); + srb_status = nr_mac_rlc_status_ind(UE->rnti, frameP, lcid); } // Need to wait until data for Msg4 is ready @@ -1834,7 +1825,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, } const int n_slots_frame = nr_mac->frame_structure.numb_slots_frame; - NR_beam_alloc_t beam = beam_allocation_procedure(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame); + NR_beam_alloc_t beam = beam_allocation_procedure(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame); if (beam.idx < 0) return; @@ -1845,7 +1836,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, BWPStart = dl_bwp->BWPStart; BWPSize = dl_bwp->BWPSize; } else { - type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[cc->ssb_index[ra->beam_id]]; + type0_PDCCH_CSS_config = &nr_mac->type0_PDCCH_CSS_config[cc->ssb_index[UE->UE_beam_index]]; BWPStart = type0_PDCCH_CSS_config->cset_start_rb; BWPSize = type0_PDCCH_CSS_config->num_rbs; } @@ -1858,21 +1849,21 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, beam.idx, ss, coreset, - &ra->sched_pdcch, + &sched_ctrl->sched_pdcch, true, 0); if (CCEIndex < 0) { - LOG_E(NR_MAC, "Cannot find free CCE for RA RNTI 0x%04x!\n", ra->rnti); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + LOG_E(NR_MAC, "Cannot find free CCE for RA RNTI 0x%04x!\n", UE->rnti); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } // Checking if the DCI allocation is feasible in current subframe nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body; if (dl_req->nPDUs > NFAPI_NR_MAX_DL_TTI_PDUS - 2) { - LOG_I(NR_MAC, "UE %04x: %d.%d FAPI DL structure is full\n", ra->rnti, frameP, slotP); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + LOG_I(NR_MAC, "UE %04x: %d.%d FAPI DL structure is full\n", UE->rnti, frameP, slotP); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } @@ -1935,18 +1926,18 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, } if (rbStart > (BWPSize - rbSize)) { - LOG_E(NR_MAC, "Cannot find free vrb_map for RNTI %04x!\n", ra->rnti); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + LOG_E(NR_MAC, "Cannot find free vrb_map for RNTI %04x!\n", UE->rnti); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } const int delta_PRI = 0; - int r_pucch = nr_get_pucch_resource(coreset, ra->UL_BWP.pucch_Config, CCEIndex); + int r_pucch = nr_get_pucch_resource(coreset, UE->current_UL_BWP.pucch_Config, CCEIndex); LOG_D(NR_MAC, "Msg4 r_pucch %d (CCEIndex %d, delta_PRI %d)\n", r_pucch, CCEIndex, delta_PRI); - int alloc = nr_acknack_scheduling(nr_mac, UE, frameP, slotP, ra->beam_id, r_pucch, 1); + int alloc = nr_acknack_scheduling(nr_mac, UE, frameP, slotP, UE->UE_beam_index, r_pucch, 1); if (alloc < 0) { LOG_D(NR_MAC,"Couldn't find a pucch allocation for ack nack (msg4) in frame %d slot %d\n", frameP, slotP); - reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); + reset_beam_status(&nr_mac->beam_info, frameP, slotP, UE->UE_beam_index, n_slots_frame, beam.new_beam); return; } @@ -1974,10 +1965,10 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, uint16_t mac_pdu_length = 0; if (ra->ra_type == RA_4_STEP) { // UE Contention Resolution Identity MAC CE - mac_pdu_length = nr_write_ce_dlsch_pdu(module_idP, nr_mac->sched_ctrlCommon, buf, 255, ra->cont_res_id); + mac_pdu_length = nr_write_ce_dlsch_pdu(module_idP, sched_ctrl, buf, 255, ra->cont_res_id); } else if (ra->ra_type == RA_2_STEP) { - mac_pdu_length = nr_fill_successrar(nr_mac->sched_ctrlCommon, - ra->rnti, + mac_pdu_length = nr_fill_successrar(sched_ctrl, + UE->rnti, ra->cont_res_id, pucch->resource_indicator, pucch->timing_indicator, @@ -1990,7 +1981,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, uint8_t buffer[CCCH_SDU_SIZE]; uint8_t mac_subheader_len = sizeof(NR_MAC_SUBHEADER_SHORT); // Get RLC data on the SRB (RRCSetup, RRCReestablishment) - mac_sdu_length = nr_mac_rlc_data_req(module_idP, ra->rnti, true, lcid, CCCH_SDU_SIZE, (char *)buffer); + mac_sdu_length = nr_mac_rlc_data_req(module_idP, UE->rnti, true, lcid, CCCH_SDU_SIZE, (char *)buffer); if (mac_sdu_length < 256) { ((NR_MAC_SUBHEADER_SHORT *)&buf[mac_pdu_length])->R = 0; @@ -2009,12 +2000,11 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, memcpy(&buf[mac_pdu_length + mac_subheader_len], buffer, mac_sdu_length); } - rnti_t rnti = ra->ra_type == RA_4_STEP ? ra->rnti : ra->MsgB_rnti; + rnti_t rnti = ra->ra_type == RA_4_STEP ? UE->rnti : ra->MsgB_rnti; const int pduindex = nr_mac->pdu_index[CC_id]++; prepare_dl_pdus(nr_mac, - ra, - dl_bwp, + UE, dl_req, pucch, dmrs_info, @@ -2052,7 +2042,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, } } - T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(ra->rnti), + T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id), T_INT(UE->rnti), T_INT(frameP), T_INT(slotP), T_INT(current_harq_pid), T_BUFFER(harq->transportBlock.buf, harq->tb_size)); // DL TX request @@ -2069,7 +2059,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, // Mark the corresponding symbols and RBs as used fill_pdcch_vrb_map(nr_mac, CC_id, - &ra->sched_pdcch, + &sched_ctrl->sched_pdcch, CCEIndex, aggregation_level, beam.idx); @@ -2080,7 +2070,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, ra->ra_state = nrRA_WAIT_Msg4_MsgB_ACK; LOG_I(NR_MAC, "UE %04x Generate %s: feedback at %4d.%2d, payload %d bytes, next state nrRA_WAIT_Msg4_MsgB_ACK\n", - ra->rnti, + UE->rnti, ra_type_str, pucch->frame, pucch->ul_slot, @@ -2088,67 +2078,47 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, } } -static void nr_check_Msg4_MsgB_Ack(module_id_t module_id, int CC_id, frame_t frame, slot_t slot, NR_RA_t *ra) +void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, NR_UE_info_t *UE, bool success) { + NR_RA_t *ra = UE->ra; const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4"; - NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, ra->rnti); - if (!UE) { - LOG_E(NR_MAC, "Cannot check %s ACK/NACK, rnti %04x not in the table\n", ra_type_str, ra->rnti); - return; - } const int current_harq_pid = ra->harq_pid; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_harq_t *harq = &sched_ctrl->harq_processes[current_harq_pid]; - LOG_D(NR_MAC, "ue rnti 0x%04x, harq is waiting %d, round %d, frame %d %d, harq id %d\n", ra->rnti, harq->is_waiting, harq->round, frame, slot, current_harq_pid); + LOG_D(NR_MAC, "ue rnti 0x%04x, round %d, frame %d %d, harq id %d\n", UE->rnti, harq->round, frame, slot, current_harq_pid); - if (harq->is_waiting == 0) { - if (harq->round == 0) { - if (UE->Msg4_MsgB_ACKed) { - LOG_A(NR_MAC, - "%4d.%2d UE %04x: Received Ack of %s. CBRA procedure succeeded!\n", - frame, slot, ra->rnti, ra_type_str); - } else { - LOG_I(NR_MAC, - "%4d.%2d UE %04x: RA Procedure failed at %s!\n", - frame, slot, ra->rnti, ra_type_str); - nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs); - } - - // Pause scheduling according to: - // 3GPP TS 38.331 Section 12 Table 12.1-1: UE performance requirements for RRC procedures for UEs - // Msg4 may transmit a RRCReconfiguration, for example when UE sends RRCReestablishmentComplete and MAC CE for C-RNTI in Msg3. - // In that case, gNB will generate a RRCReconfiguration that will be transmitted in Msg4, so we need to apply CellGroup after the Ack, - // UE->reconfigCellGroup already set when processing RRCReestablishment message - int delay = nr_mac_get_reconfig_delay_slots(UE->current_UL_BWP.scs); - nr_mac_interrupt_ue_transmission(RC.nrmac[module_id], UE, UE->interrupt_action, delay); - - nr_clear_ra_proc(ra); - if (sched_ctrl->retrans_dl_harq.head >= 0) { - remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); - } + if (harq->round == 0) { + if (success) { + LOG_A(NR_MAC, "%4d.%2d UE %04x: Received Ack of %s. CBRA procedure succeeded!\n", frame, slot, UE->rnti, ra_type_str); } else { - LOG_I(NR_MAC, "(UE %04x) Received Nack in %s, preparing retransmission!\n", ra->rnti, ra_type_str); - ra->ra_state = ra->ra_type == RA_4_STEP ? nrRA_Msg4 : nrRA_MsgB; + LOG_I(NR_MAC, "%4d.%2d UE %04x: RA Procedure failed at %s!\n", frame, slot, UE->rnti, ra_type_str); + nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs); } + + // Pause scheduling according to: + // 3GPP TS 38.331 Section 12 Table 12.1-1: UE performance requirements for RRC procedures for UEs + // Msg4 may transmit a RRCReconfiguration, for example when UE sends RRCReestablishmentComplete and MAC CE for C-RNTI in Msg3. + // In that case, gNB will generate a RRCReconfiguration that will be transmitted in Msg4, so we need to apply CellGroup after the Ack, + // UE->reconfigCellGroup already set when processing RRCReestablishment message + int delay = nr_mac_get_reconfig_delay_slots(UE->current_UL_BWP.scs); + gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + nr_mac_interrupt_ue_transmission(nr_mac, UE, UE->interrupt_action, delay); + if (!transition_ra_connected_nr_ue(nr_mac, UE)) { + LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti); + delete_nr_ue_data(UE, NULL, &nr_mac->UE_info.uid_allocator); + return; + } + if (sched_ctrl->retrans_dl_harq.head >= 0) { + remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); + } + } else { + LOG_I(NR_MAC, "(UE %04x) Received Nack in %s, preparing retransmission!\n", UE->rnti, ra_type_str); + ra->ra_state = ra->ra_type == RA_4_STEP ? nrRA_Msg4 : nrRA_MsgB; } } -void nr_clear_ra_proc(NR_RA_t *ra) -{ - /* we assume that this function is mutex-protected from outside */ - NR_SCHED_ENSURE_LOCKED(&RC.nrmac[0]->sched_lock); - memset(ra, 0, sizeof(*ra)); - ra->ra_state = nrRA_gNB_IDLE; - if (IS_SA_MODE(get_softmodem_params())) { // in SA, prefill with allowed preambles - ra->preambles.num_preambles = MAX_NUM_NR_PRACH_PREAMBLES; - for (int i = 0; i < MAX_NUM_NR_PRACH_PREAMBLES; i++) - ra->preambles.preamble_list[i] = i; - } -} - - ///////////////////////////////////// // Random Access Response PDU // // TS 38.213 ch 8.2 // @@ -2179,9 +2149,15 @@ void nr_clear_ra_proc(NR_RA_t *ra) // - sending only 1 RAR subPDU // - UL Grant: hardcoded CSI, TPC, time alloc // - padding -static void nr_fill_rar(uint8_t Mod_idP, NR_RA_t *ra, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu) +static void nr_fill_rar(uint8_t Mod_idP, NR_UE_info_t *UE, uint8_t *dlsch_buffer, nfapi_nr_pusch_pdu_t *pusch_pdu) { - LOG_D(NR_MAC, "[gNB] Generate RAR MAC PDU frame %d slot %d preamble index %u TA command %d \n", ra->Msg2_frame, ra-> Msg2_slot, ra->preamble_index, ra->timing_offset); + NR_RA_t *ra = UE->ra; + LOG_D(NR_MAC, + "[gNB] Generate RAR MAC PDU frame %d slot %d preamble index %u TA command %d \n", + ra->Msg2_frame, + ra->Msg2_slot, + ra->preamble_index, + ra->timing_offset); NR_RA_HEADER_BI *rarbi = (NR_RA_HEADER_BI *) dlsch_buffer; NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) (dlsch_buffer + 1); NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 2); @@ -2212,8 +2188,8 @@ static void nr_fill_rar(uint8_t Mod_idP, NR_RA_t *ra, uint8_t *dlsch_buffer, nfa rar->TA2 = (uint8_t) (ra->timing_offset & 0x1f); // 5 LSBs of timing advance // TC-RNTI - rar->TCRNTI_1 = (uint8_t) (ra->rnti >> 8); // 8 MSBs of rnti - rar->TCRNTI_2 = (uint8_t) (ra->rnti & 0xff); // 8 LSBs of rnti + rar->TCRNTI_1 = (uint8_t) (UE->rnti >> 8); // 8 MSBs of rnti + rar->TCRNTI_2 = (uint8_t) (UE->rnti & 0xff); // 8 LSBs of rnti // UL grant @@ -2263,6 +2239,22 @@ static void nr_fill_rar(uint8_t Mod_idP, NR_RA_t *ra, uint8_t *dlsch_buffer, nfa ra->msg3_TPC = 1; } +/** @brief remove the UE with RNTI rnti from list of UEs doing RA. + * + * The corresponding function to add is add_new_UE_RA(). */ +void nr_release_ra_UE(gNB_MAC_INST *mac, rnti_t rnti) +{ + NR_UEs_t *UE_info = &mac->UE_info; + NR_SCHED_LOCK(&UE_info->mutex); + NR_UE_info_t *UE = remove_UE_from_list(NR_NB_RA_PROC_MAX, UE_info->access_ue_list, rnti); + NR_SCHED_UNLOCK(&UE_info->mutex); + if (UE) { + delete_nr_ue_data(UE, mac->common_channels, &UE_info->uid_allocator); + } else { + LOG_W(NR_MAC,"Call to del rnti %04x, but not existing\n", rnti); + } +} + void nr_schedule_RA(module_id_t module_idP, frame_t frameP, slot_t slotP, @@ -2276,38 +2268,33 @@ void nr_schedule_RA(module_id_t module_idP, start_meas(&mac->schedule_ra); for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { - NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - NR_RA_t *ra = &cc->ra[i]; + UE_iterator(mac->UE_info.access_ue_list, UE) { + NR_RA_t *ra = UE->ra; if (ra->ra_state != nrRA_gNB_IDLE) - LOG_D(NR_MAC, "RA[%d] frame.slot %d.%d state: %d\n", i, frameP, slotP, ra->ra_state); + LOG_D(NR_MAC, "UE %04x frame.slot %d.%d RA state: %d\n", UE->rnti, frameP, slotP, ra->ra_state); - // Check RA Contention Resolution timer - if (ra->ra_type == RA_4_STEP && ra->ra_state >= nrRA_WAIT_Msg3) { + // Check RA Contention Resolution timer (TODO check this procedure) + if (ra->ra_type == RA_4_STEP && ra->ra_state > nrRA_WAIT_Msg3) { ra->contention_resolution_timer--; if (ra->contention_resolution_timer < 0) { - LOG_W(NR_MAC, "(%d.%d) RA Contention Resolution timer expired for UE 0x%04x, RA procedure failed...\n", frameP, slotP, ra->rnti); - bool requested = nr_mac_request_release_ue(mac, ra->rnti); + LOG_W(NR_MAC, "(%d.%d) RA Contention Resolution timer expired for UE 0x%04x, RA procedure failed...\n", frameP, slotP, UE->rnti); + bool requested = nr_mac_request_release_ue(mac, UE->rnti); if (!requested) - nr_mac_release_ue(mac, ra->rnti); - nr_clear_ra_proc(ra); + nr_release_ra_UE(mac, UE->rnti); continue; } } switch (ra->ra_state) { case nrRA_Msg2: - nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); + nr_generate_Msg2(module_idP, CC_id, frameP, slotP, UE, DL_req, TX_req); break; case nrRA_Msg3_retransmission: - nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req); + nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, UE, ul_dci_req); break; case nrRA_Msg4: case nrRA_MsgB: - nr_generate_Msg4_MsgB(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); - break; - case nrRA_WAIT_Msg4_MsgB_ACK: - nr_check_Msg4_MsgB_Ack(module_idP, CC_id, frameP, slotP, ra); + nr_generate_Msg4_MsgB(module_idP, CC_id, frameP, slotP, UE, DL_req, TX_req); break; default: break; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index c6054eeefd..226fe80dbb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -609,9 +609,6 @@ static void pf_dl(module_id_t module_id, /* Loop UE_info->list to check retransmission */ UE_iterator(UE_list, UE) { - if (!UE->Msg4_MsgB_ACKed) - continue; - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 68d27be46a..cb4592b4eb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2060,7 +2060,6 @@ void remove_front_nr_list(NR_list_t *listP) NR_UE_info_t *find_nr_UE(NR_UEs_t *UEs, rnti_t rntiP) { - UE_iterator(UEs->connected_ue_list, UE) { if (UE->rnti == rntiP) { LOG_D(NR_MAC,"Search and found rnti: %04x\n", rntiP); @@ -2070,6 +2069,17 @@ NR_UE_info_t *find_nr_UE(NR_UEs_t *UEs, rnti_t rntiP) return NULL; } +NR_UE_info_t *find_ra_UE(NR_UEs_t *UEs, rnti_t rntiP) +{ + UE_iterator(UEs->access_ue_list, UE) { + if (UE->rnti == rntiP) { + LOG_D(NR_MAC,"Search and found rnti: %04x\n", rntiP); + return UE; + } + } + return NULL; +} + void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_allocator_t *uia) { ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); @@ -2088,6 +2098,7 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca free_sched_pucch_list(sched_ctrl); uid_linear_allocator_free(uia, UE->uid); LOG_I(NR_MAC, "Remove NR rnti 0x%04x\n", UE->rnti); + free(UE->ra); free(UE); } @@ -2195,31 +2206,16 @@ static void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl, // main function to configure parameters of current BWP void configure_UE_BWP(gNB_MAC_INST *nr_mac, NR_ServingCellConfigCommon_t *scc, - NR_UE_sched_ctrl_t *sched_ctrl, - NR_RA_t *ra, NR_UE_info_t *UE, + bool is_RA, int dl_bwp_switch, int ul_bwp_switch) { - AssertFatal((ra != NULL && UE == NULL) || (ra == NULL && UE != NULL), "RA and UE structures are mutually exlusive in BWP configuration\n"); + NR_CellGroupConfig_t *CellGroup = UE->CellGroup; + NR_UE_ServingCell_Info_t *sc_info = &UE->sc_info; + NR_UE_DL_BWP_t *DL_BWP = &UE->current_DL_BWP; + NR_UE_UL_BWP_t *UL_BWP = &UE->current_UL_BWP; - NR_CellGroupConfig_t *CellGroup; - NR_UE_ServingCell_Info_t *sc_info; - NR_UE_DL_BWP_t *DL_BWP; - NR_UE_UL_BWP_t *UL_BWP; - - if (ra) { - DL_BWP = &ra->DL_BWP; - UL_BWP = &ra->UL_BWP; - CellGroup = ra->CellGroup; - sc_info = &ra->sc_info; - } - else { - DL_BWP = &UE->current_DL_BWP; - UL_BWP = &UE->current_UL_BWP; - CellGroup = UE->CellGroup; - sc_info = &UE->sc_info; - } NR_BWP_Downlink_t *dl_bwp = NULL; NR_BWP_Uplink_t *ul_bwp = NULL; NR_BWP_DownlinkDedicated_t *bwpd = NULL; @@ -2229,13 +2225,10 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, sc_info->n_ul_bwp = 0; int old_dl_bwp_id = DL_BWP->bwp_id; int old_ul_bwp_id = UL_BWP->bwp_id; - int target_ss; NR_ServingCellConfig_t *servingCellConfig = NULL; - if (CellGroup && - CellGroup->spCellConfig && - CellGroup->spCellConfig->spCellConfigDedicated) { + if (CellGroup && CellGroup->spCellConfig && CellGroup->spCellConfig->spCellConfigDedicated) { servingCellConfig = CellGroup->spCellConfig->spCellConfigDedicated; target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; @@ -2359,7 +2352,10 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, UL_BWP->rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup; } - if(UE) { + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + // Reset required fields in sched_ctrl (e.g. ul_ri and tpmi) + reset_sched_ctrl(sched_ctrl); + if(!is_RA) { if (servingCellConfig) { if (servingCellConfig->csi_MeasConfig) { sc_info->csi_MeasConfig = servingCellConfig->csi_MeasConfig->choice.setup; @@ -2403,18 +2399,9 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, if (CellGroup && CellGroup->physicalCellGroupConfig) UE->pdsch_HARQ_ACK_Codebook = CellGroup->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook; - // Reset required fields in sched_ctrl (e.g. ul_ri and tpmi) - reset_sched_ctrl(sched_ctrl); - // setting PDCCH related structures for sched_ctrl - sched_ctrl->search_space = get_searchspace(scc, - bwpd, - target_ss); - sched_ctrl->coreset = get_coreset(nr_mac, - scc, - bwpd, - sched_ctrl->search_space, - target_ss); + sched_ctrl->search_space = get_searchspace(scc, bwpd, target_ss); + sched_ctrl->coreset = get_coreset(nr_mac, scc, bwpd, sched_ctrl->search_space, target_ss); sched_ctrl->sched_pdcch = set_pdcch_structure(nr_mac, sched_ctrl->search_space, @@ -2436,11 +2423,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0) : NR_UL_DCI_FORMAT_0_0; - set_max_fb_time(UL_BWP, DL_BWP); - set_sched_pucch_list(sched_ctrl, UL_BWP, scc, &nr_mac->frame_structure); - } - - if(ra) { + } else { // setting PDCCH related structures for RA struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = NULL; NR_SearchSpaceId_t ra_SearchSpace = 0; @@ -2453,26 +2436,29 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, } AssertFatal(commonSearchSpaceList->list.count > 0, "common SearchSpace list has 0 elements\n"); for (int i = 0; i < commonSearchSpaceList->list.count; i++) { - NR_SearchSpace_t * ss = commonSearchSpaceList->list.array[i]; + NR_SearchSpace_t *ss = commonSearchSpaceList->list.array[i]; if (ss->searchSpaceId == ra_SearchSpace) - ra->ra_ss = ss; + sched_ctrl->search_space = ss; } - AssertFatal(ra->ra_ss!=NULL,"SearchSpace cannot be null for RA\n"); + AssertFatal(sched_ctrl->search_space != NULL, "SearchSpace cannot be null for RA\n"); - ra->coreset = get_coreset(nr_mac, scc, dl_bwp, ra->ra_ss, NR_SearchSpace__searchSpaceType_PR_common); + sched_ctrl->coreset = get_coreset(nr_mac, scc, dl_bwp, sched_ctrl->search_space, NR_SearchSpace__searchSpaceType_PR_common); NR_COMMON_channels_t *cc = &nr_mac->common_channels[0]; - int ssb_index = cc->ssb_index[ra->beam_id]; - ra->sched_pdcch = set_pdcch_structure(nr_mac, - ra->ra_ss, - ra->coreset, - scc, - &dl_genericParameters, - &nr_mac->type0_PDCCH_CSS_config[ssb_index]); + int ssb_index = cc->ssb_index[UE->UE_beam_index]; + sched_ctrl->sched_pdcch = set_pdcch_structure(nr_mac, + sched_ctrl->search_space, + sched_ctrl->coreset, + scc, + &dl_genericParameters, + &nr_mac->type0_PDCCH_CSS_config[ssb_index]); UL_BWP->dci_format = NR_UL_DCI_FORMAT_0_0; DL_BWP->dci_format = NR_DL_DCI_FORMAT_1_0; } + set_max_fb_time(UL_BWP, DL_BWP); + set_sched_pucch_list(sched_ctrl, UL_BWP, scc, &nr_mac->frame_structure); + // Set MCS tables long *dl_mcs_Table = DL_BWP->pdsch_Config ? DL_BWP->pdsch_Config->mcs_Table : NULL; DL_BWP->mcsTableIdx = get_pdsch_mcs_table(dl_mcs_Table, DL_BWP->dci_format, TYPE_C_RNTI_, target_ss); @@ -2482,9 +2468,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, // Set uplink MCS table long *mcs_Table = NULL; if (UL_BWP->pusch_Config) - mcs_Table = UL_BWP->transform_precoding ? - UL_BWP->pusch_Config->mcs_Table : - UL_BWP->pusch_Config->mcs_TableTransformPrecoder; + mcs_Table = UL_BWP->transform_precoding ? UL_BWP->pusch_Config->mcs_Table : UL_BWP->pusch_Config->mcs_TableTransformPrecoder; UL_BWP->mcs_table = get_pusch_mcs_table(mcs_Table, !UL_BWP->transform_precoding, UL_BWP->dci_format, TYPE_C_RNTI_, target_ss, false); } @@ -2502,49 +2486,29 @@ static void init_bler_stats(const NR_bler_options_t *bler_options, NR_bler_stats bler_stats->bler = (float)(bler_options->lower + bler_options->upper) / 2.0f; } -//------------------------------------------------------------------------------ -NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup) +/* @brief returns a new UE allocated instance. + * + * It will be typically added to the access_ue_list, but not always (e.g., + * phytest mode), so this is not done in this function (and also, to allow + * error handling). Remove with delete_nr_ue_data(). */ +NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup) { - NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon; - NR_UEs_t *UE_info = &nr_mac->UE_info; - LOG_I(NR_MAC, "Adding new UE context with RNTI 0x%04x\n", rntiP); - dump_nr_list(UE_info->connected_ue_list); - - // We will attach at the end, to mitigate race conditions - // This is not good, but we will fix it progressively - NR_UE_info_t *UE = calloc(1, sizeof(NR_UE_info_t)); - if(!UE) { - LOG_E(NR_MAC,"want to add UE %04x but the fixed allocated size is full\n",rntiP); + uid_t uid = uid_linear_allocator_new(uia); + /* if the UE list is full, we should reject the UE with an RRC reject + * message, but we do not have this functionality. To keep it simple, do not + * create a UE context here, so we can print an error message. */ + if (uid >= MAX_MOBILES_PER_GNB) { + uid_linear_allocator_free(uia, uid); return NULL; } - UE->rnti = rntiP; - UE->uid = uid_linear_allocator_new(&UE_info->uid_allocator); + NR_UE_info_t *UE = calloc_or_fail(1, sizeof(NR_UE_info_t)); + UE->rnti = rnti; UE->CellGroup = CellGroup; - - UE->Msg4_MsgB_ACKed = CellGroup != NULL; - + UE->uid = uid; + UE->ra = calloc(1, sizeof(*UE->ra)); NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - memset(sched_ctrl, 0, sizeof(*sched_ctrl)); - sched_ctrl->dl_max_mcs = 28; /* do not limit MCS for individual UEs */ sched_ctrl->ta_update = 31; - sched_ctrl->sched_srs.frame = -1; - sched_ctrl->sched_srs.slot = -1; - sched_ctrl->pdcch_cl_adjust = 0; - - // Initialize bler_stats - init_bler_stats(&nr_mac->dl_bler, &sched_ctrl->dl_bler_stats, nr_mac->frame); - init_bler_stats(&nr_mac->ul_bler, &sched_ctrl->ul_bler_stats, nr_mac->frame); - - // initialize LCID structure - seq_arr_init(&sched_ctrl->lc_config, sizeof(nr_lc_config_t)); - - // initialize UE BWP information - NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; - memset(dl_bwp, 0, sizeof(*dl_bwp)); - NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; - memset(ul_bwp, 0, sizeof(*ul_bwp)); - configure_UE_BWP(nr_mac, scc, sched_ctrl, NULL, UE, -1, -1); /* set illegal time domain allocation to force recomputation of all fields */ sched_ctrl->sched_pdsch.time_domain_allocation = -1; @@ -2558,27 +2522,87 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf create_dl_harq_list(sched_ctrl, &UE->sc_info); create_ul_harq_list(sched_ctrl, &UE->sc_info); - reset_srs_stats(UE); + // initialize LCID structure + seq_arr_init(&sched_ctrl->lc_config, sizeof(nr_lc_config_t)); + return UE; +} - NR_SCHED_LOCK(&UE_info->mutex); - int i; - for(i=0; iconnected_ue_list[i] == NULL) { - UE_info->connected_ue_list[i] = UE; - break; +bool add_UE_to_list(int list_size, NR_UE_info_t *list[list_size], NR_UE_info_t *UE) +{ + for (int i = 0; i < list_size; i++) { + if (!list[i]) { + list[i] = UE; + return true; } } - if (i == MAX_MOBILES_PER_GNB) { - LOG_E(NR_MAC,"Try to add UE %04x but the list is full\n", rntiP); - delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator); - NR_SCHED_UNLOCK(&UE_info->mutex); - return NULL; - } - NR_SCHED_UNLOCK(&UE_info->mutex); + return false; +} - LOG_D(NR_MAC, "Add NR rnti %x\n", rntiP); +NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], rnti_t rnti) +{ + for (int i = 0; i < list_size; i++) { + NR_UE_info_t *curr_UE = list[i]; + if (curr_UE->rnti != rnti) + continue; + + /* remove this UE from the list, return the pointer */ + memmove(&list[i], &list[i+1], sizeof(list[0]) * (list_size - i - 1)); + list[list_size - 1] = NULL; + return curr_UE; + } + LOG_E(NR_MAC, "UE %04x to be removed not found in list\n", rnti); + return NULL; +} + +/** @brief Transitions a UE from access list to connected list (i.e., the RA + * list to the "normal" UE context list. */ +bool transition_ra_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) +{ + NR_UEs_t *UE_info = &nr_mac->UE_info; + + // remove UE from initial access list (moved to connected mode) + NR_UE_info_t *r = remove_UE_from_list(NR_NB_RA_PROC_MAX, UE_info->access_ue_list, UE->rnti); + DevAssert(r == UE); /* sanity check: we should have removed the current UE ptr from list */ + + free_and_zero(UE->ra); + + return add_connected_nr_ue(nr_mac, UE); +} + +/** @brief Add a UE to the list of UEs in * connected mode. + * + * To remove the UE, use mac_remove_nr_ue(). */ +bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE) +{ + LOG_I(NR_MAC, "Adding new UE context with RNTI 0x%04x\n", UE->rnti); + NR_UEs_t *UE_info = &nr_mac->UE_info; dump_nr_list(UE_info->connected_ue_list); - return (UE); + AssertFatal(!UE->ra, "UE in connected cannot have RA process\n"); + + NR_SCHED_LOCK(&UE_info->mutex); + + bool success = add_UE_to_list(MAX_MOBILES_PER_GNB, UE_info->connected_ue_list, UE); + if (!success) { + LOG_E(NR_MAC,"Try to add UE %04x but the list is full\n", UE->rnti); + delete_nr_ue_data(UE, NULL, &UE_info->uid_allocator); + NR_SCHED_UNLOCK(&UE_info->mutex); + return false; + } + + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + sched_ctrl->dl_max_mcs = 28; /* do not limit MCS for individual UEs */ + sched_ctrl->sched_srs.frame = -1; + sched_ctrl->sched_srs.slot = -1; + sched_ctrl->pdcch_cl_adjust = 0; + reset_srs_stats(UE); + + // Initialize bler_stats + init_bler_stats(&nr_mac->dl_bler, &sched_ctrl->dl_bler_stats, nr_mac->frame); + init_bler_stats(&nr_mac->ul_bler, &sched_ctrl->ul_bler_stats, nr_mac->frame); + + NR_SCHED_UNLOCK(&UE_info->mutex); + dump_nr_list(UE_info->connected_ue_list); + return true; } void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl) @@ -2683,38 +2707,11 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti) { /* already mutex protected */ NR_SCHED_ENSURE_LOCKED(&nr_mac->sched_lock); - NR_UEs_t *UE_info = &nr_mac->UE_info; NR_SCHED_LOCK(&UE_info->mutex); - UE_iterator(UE_info->connected_ue_list, UE) { - if (UE->rnti==rnti) - break; - } - - if (!UE) { - LOG_W(NR_MAC,"Call to del rnti %04x, but not existing\n", rnti); - NR_SCHED_UNLOCK(&UE_info->mutex); - return; - } - - NR_UE_info_t * newUEs[MAX_MOBILES_PER_GNB+1]={0}; - int newListIdx = 0; - for (int i = 0; i < MAX_MOBILES_PER_GNB; i++) - if(UE_info->connected_ue_list[i] && UE_info->connected_ue_list[i]->rnti != rnti) - newUEs[newListIdx++] = UE_info->connected_ue_list[i]; - memcpy(UE_info->connected_ue_list, newUEs, sizeof(UE_info->connected_ue_list)); + NR_UE_info_t *UE = remove_UE_from_list(MAX_MOBILES_PER_GNB + 1, UE_info->connected_ue_list, rnti); NR_SCHED_UNLOCK(&UE_info->mutex); - const int CC_id = 0; - NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - NR_RA_t *ra = &cc->ra[i]; - if (ra->rnti == UE->rnti) { - nr_clear_ra_proc(ra); - ra->cfra = 0; - } - } - delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator); } @@ -3071,7 +3068,7 @@ static void nr_mac_apply_cellgroup(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - configure_UE_BWP(mac, scc, sched_ctrl, NULL, UE, -1, -1); + configure_UE_BWP(mac, scc, UE, false, -1, -1); reset_srs_stats(UE); @@ -3519,24 +3516,14 @@ bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid) return true; } -static const NR_RA_t *find_nr_RA_rnti(const NR_RA_t *ra_base, int ra_count, rnti_t rnti) -{ - for (int i = 0; i < ra_count; ++i) { - const NR_RA_t *ra = &ra_base[i]; - if (ra->ra_state != nrRA_gNB_IDLE && ra->rnti == rnti) - return ra; - } - return NULL; -} - -bool nr_mac_get_new_rnti(NR_UEs_t *UEs, const NR_RA_t *ra_base, int ra_count, rnti_t *rnti) +bool nr_mac_get_new_rnti(NR_UEs_t *UEs, rnti_t *rnti) { int loop = 0; bool exist_connected_ue, exist_in_pending_ra_ue; do { *rnti = (taus() % 0xffef) + 1; exist_connected_ue = find_nr_UE(UEs, *rnti) != NULL; - exist_in_pending_ra_ue = find_nr_RA_rnti(ra_base, ra_count, *rnti) != NULL; + exist_in_pending_ra_ue = find_ra_UE(UEs, *rnti) != NULL; loop++; } while (loop < 100 && (exist_connected_ue || exist_in_pending_ra_ue)); return loop < 100; // nothing found: loop count 100 diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 5254ff5b59..29ff27d38e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -171,39 +171,54 @@ static int get_pucch_index(int frame, int slot, const frame_structure_t *fs, int return (frame_start + ul_period_start + ul_period_slot) % sched_pucch_size; } -void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, slot_t slotP) +static void schedule_pucch_core(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, frame_t frame, slot_t slot) +{ + NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + const int pucch_index = get_pucch_index(frame, slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size); + NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[pucch_index]; + if (!curr_pucch->active) + return; + if (frame != curr_pucch->frame || slot != curr_pucch->ul_slot) { + LOG_E(NR_MAC, + "PUCCH frame/slot mismatch: current %4d.%2d vs. request %4d.%2d: not scheduling PUCCH\n", + curr_pucch->frame, + curr_pucch->ul_slot, + frame, + slot); + memset(curr_pucch, 0, sizeof(*curr_pucch));; + return; + } + + const uint16_t O_ack = curr_pucch->dai_c; + const uint16_t O_csi = curr_pucch->csi_bits; + const uint8_t O_sr = curr_pucch->sr_flag; + LOG_D(NR_MAC, + "Scheduling PUCCH[%d] RX for UE %04x in %4d.%2d O_ack %d, O_sr %d, O_csi %d\n", + pucch_index, + UE->rnti, + curr_pucch->frame, + curr_pucch->ul_slot, + O_ack,O_sr, + O_csi); + nr_fill_nfapi_pucch(nrmac, frame, slot, curr_pucch, UE); + memset(curr_pucch, 0, sizeof(*curr_pucch)); +} + +void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frame, slot_t slot) { /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); - if (!is_ul_slot(slotP, &nrmac->frame_structure)) + if (!is_ul_slot(slot, &nrmac->frame_structure)) return; + UE_iterator(nrmac->UE_info.access_ue_list, init_UE) { + if (init_UE->ra->ra_state == nrRA_WAIT_Msg4_MsgB_ACK) + schedule_pucch_core(nrmac, init_UE, frame, slot); + } + UE_iterator(nrmac->UE_info.connected_ue_list, UE) { - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - const int pucch_index = get_pucch_index(frameP, slotP, &nrmac->frame_structure, sched_ctrl->sched_pucch_size); - NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[pucch_index]; - if (!curr_pucch->active) - continue; - if (frameP != curr_pucch->frame || slotP != curr_pucch->ul_slot) { - LOG_E(NR_MAC, - "PUCCH frame/slot mismatch: current %4d.%2d vs. request %4d.%2d: not scheduling PUCCH\n", - curr_pucch->frame, - curr_pucch->ul_slot, - frameP, - slotP); - memset(curr_pucch, 0, sizeof(*curr_pucch));; - continue; - } - - const uint16_t O_ack = curr_pucch->dai_c; - const uint16_t O_csi = curr_pucch->csi_bits; - const uint8_t O_sr = curr_pucch->sr_flag; - LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %04x in %4d.%2d O_ack %d, O_sr %d, O_csi %d\n", - pucch_index,UE->rnti,curr_pucch->frame,curr_pucch->ul_slot,O_ack,O_sr,O_csi); - nr_fill_nfapi_pucch(nrmac, frameP, slotP, curr_pucch, UE); - memset(curr_pucch, 0, sizeof(*curr_pucch)); - + schedule_pucch_core(nrmac, UE, frame, slot); } } @@ -854,14 +869,19 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, slot_t slot, con gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; int rssi_threshold = nrmac->pucch_rssi_threshold; NR_SCHED_LOCK(&nrmac->sched_lock); - NR_UE_info_t * UE = find_nr_UE(&nrmac->UE_info, uci_01->rnti); + NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, uci_01->rnti); + bool is_ra = false; if (!UE) { - LOG_E(NR_MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_01->rnti); - NR_SCHED_UNLOCK(&nrmac->sched_lock); - return; + UE = find_ra_UE(&nrmac->UE_info, uci_01->rnti); + if (UE) + is_ra = true; + else { + LOG_E(NR_MAC, "Unknown RNTI %04x in PUCCH UCI\n", uci_01->rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); + return; + } } NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - if (((uci_01->pduBitmap >> 1) & 0x01)) { // iterate over received harq bits for (int harq_bit = 0; harq_bit < uci_01->harq.num_harq; harq_bit++) { @@ -877,10 +897,12 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, slot_t slot, con remove_front_nr_list(&sched_ctrl->feedback_dl_harq); LOG_D(NR_MAC,"%4d.%2d bit %d pid %d ack/nack %d\n",frame, slot, harq_bit,pid,harq_value); nr_mac_update_pdcch_closed_loop_adjust(sched_ctrl, harq_confidence != 0); - handle_dl_harq(UE, pid, harq_value == 0 && harq_confidence == 0, nrmac->dl_bler.harq_round_max); - if (!UE->Msg4_MsgB_ACKed && harq_value == 0 && harq_confidence == 0) - UE->Msg4_MsgB_ACKed = true; - if (harq_confidence == 1) UE->mac_stats.pucch0_DTX++; + bool success = harq_value == 0 && harq_confidence == 0; + handle_dl_harq(UE, pid, success, nrmac->dl_bler.harq_round_max); + if (is_ra) + nr_check_Msg4_MsgB_Ack(mod_id, frame, slot, UE, success); + if (harq_confidence == 1) + UE->mac_stats.pucch0_DTX++; } // tpc (power control) only if we received AckNack diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index cbbcbd00a9..5ca2b69151 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -461,17 +461,13 @@ static int nr_process_mac_pdu(instance_t module_idP, break; case UL_SCH_LCID_C_RNTI: - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i]; - if (ra->ra_state == nrRA_gNB_IDLE && ra->rnti == UE->rnti) { - // Extract C-RNTI value - rnti_t crnti = ((pduP[1] & 0xFF) << 8) | (pduP[2] & 0xFF); - AssertFatal(false, - "Received MAC CE for C-RNTI %04x without RA running, procedure exists? Or is it a bug while decoding the " - "MAC PDU?\n", - crnti); - break; - } + if (UE->ra && UE->ra->ra_state == nrRA_gNB_IDLE) { + // Extract C-RNTI value + rnti_t crnti = ((pduP[1] & 0xFF) << 8) | (pduP[2] & 0xFF); + AssertFatal(false, + "Received MAC CE for C-RNTI %04x without RA running, procedure exists? Or is it a bug while decoding the " + "MAC PDU?\n", + crnti); } break; @@ -547,24 +543,7 @@ static void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid) sched_ctrl->sched_ul_bytes = 0; } -static bool get_UE_waiting_CFRA_msg3(const gNB_MAC_INST *gNB_mac, - const int CC_id, - const frame_t frame, - const slot_t slot, - rnti_t rnti) -{ - bool UE_waiting_CFRA_msg3 = false; - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - const NR_RA_t *ra = &gNB_mac->common_channels[CC_id].ra[i]; - if (ra->cfra && ra->ra_state == nrRA_WAIT_Msg3 && frame == ra->Msg3_frame && slot == ra->Msg3_slot && rnti == ra->rnti) { - UE_waiting_CFRA_msg3 = true; - break; - } - } - return UE_waiting_CFRA_msg3; -} - -void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, slot_t slot, const nfapi_nr_crc_t *crc_pdu) +void handle_nr_ul_harq(module_id_t mod_id, frame_t frame, slot_t slot, const nfapi_nr_crc_t *crc_pdu) { gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; if (nrmac->radio_config.disable_harq) { @@ -573,12 +552,13 @@ void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, slot } NR_SCHED_LOCK(&nrmac->sched_lock); - for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { - NR_RA_t *ra = &nrmac->common_channels[CC_idP].ra[i]; + NR_UEs_t *UE_info = &nrmac->UE_info; + UE_iterator(UE_info->access_ue_list, ra_UE) { + const NR_RA_t *ra = ra_UE->ra; // if we find any ongoing RA that has already scheduled MSG3 // and it is expecting its reception in current frame and slot with matching RNTI // we can exit the function (no HARQ involved) - if (ra->ra_state >= nrRA_WAIT_Msg3 && ra->rnti == crc_pdu->rnti && frame == ra->Msg3_frame && slot == ra->Msg3_slot) { + if (ra->ra_state >= nrRA_WAIT_Msg3 && ra_UE->rnti == crc_pdu->rnti && frame == ra->Msg3_frame && slot == ra->Msg3_slot) { LOG_D(NR_MAC, "UL for rnti %04x in RA (MSG3), no need to process HARQ\n", crc_pdu->rnti); NR_SCHED_UNLOCK(&nrmac->sched_lock); return; @@ -586,6 +566,7 @@ void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, slot } NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, crc_pdu->rnti); + UE = UE ? UE : find_ra_UE(&nrmac->UE_info, crc_pdu->rnti); if (!UE) { NR_SCHED_UNLOCK(&nrmac->sched_lock); LOG_E(NR_MAC, "Couldn't identify UE connected with current UL HARQ process\n"); @@ -641,29 +622,56 @@ void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, slot NR_SCHED_UNLOCK(&nrmac->sched_lock); } -static void handle_msg3_failed_rx(NR_RA_t *ra, int i, int harq_round_max) +static void handle_msg3_failed_rx(gNB_MAC_INST *mac, NR_RA_t *ra, rnti_t rnti, int harq_round_max) { // for CFRA (NSA) do not schedule retransmission of msg3 if (ra->cfra) { - LOG_D(NR_MAC, "Random Access %i failed at state %s (NSA msg3 reception failed)\n", i, nrra_text[ra->ra_state]); - nr_clear_ra_proc(ra); + LOG_W(NR_MAC, "UE %04x RA failed at state %s (NSA msg3 reception failed)\n", rnti, nrra_text[ra->ra_state]); + nr_release_ra_UE(mac, rnti); return; } if (ra->msg3_round >= harq_round_max - 1) { - LOG_W(NR_MAC, "Random Access %i failed at state %s (Reached msg3 max harq rounds)\n", i, nrra_text[ra->ra_state]); - nr_clear_ra_proc(ra); + LOG_W(NR_MAC, "UE %04x RA failed at state %s (Reached msg3 max harq rounds)\n", rnti, nrra_text[ra->ra_state]); + nr_release_ra_UE(mac, rnti); return; } - LOG_D(NR_MAC, "Random Access %i Msg3 CRC did not pass\n", i); + LOG_D(NR_MAC, "UE %04x Msg3 CRC did not pass\n", rnti); ra->msg3_round++; ra->ra_state = nrRA_Msg3_retransmission; } -/* -* When data are received on PHY and transmitted to MAC -*/ +static NR_UE_info_t *configure_UE_crnti_msg3(gNB_MAC_INST *mac, NR_UE_info_t *old_UE, NR_UE_info_t *new_UE) +{ + // in case UE beam has changed + old_UE->UE_beam_index = new_UE->UE_beam_index; + // Reset UL failure for old UE + nr_mac_reset_ul_failure(&old_UE->UE_sched_ctrl); + // Reset HARQ processes + reset_dl_harq_list(&old_UE->UE_sched_ctrl); + reset_ul_harq_list(&old_UE->UE_sched_ctrl); + // old UE need to complete RA by sending DL + free_and_zero(old_UE->ra); + old_UE->ra = new_UE->ra; + new_UE->ra = NULL; + NR_UE_sched_ctrl_t *sched_ctrl = &old_UE->UE_sched_ctrl; + sched_ctrl->search_space = new_UE->UE_sched_ctrl.search_space; + sched_ctrl->coreset = new_UE->UE_sched_ctrl.coreset; + memcpy(&sched_ctrl->sched_pdcch, &new_UE->UE_sched_ctrl.sched_pdcch, sizeof(NR_sched_pdcch_t)); + old_UE->current_DL_BWP.dci_format = NR_DL_DCI_FORMAT_1_0; + // replace new UE with old UE in the access list + for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { + if (mac->UE_info.access_ue_list[i] && mac->UE_info.access_ue_list[i]->rnti == new_UE->rnti) { + mac->UE_info.access_ue_list[i] = old_UE; + break; + } + } + // remove new UE + delete_nr_ue_data(new_UE, mac->common_channels, &mac->UE_info.uid_allocator); + return old_UE; +} + static void _nr_rx_sdu(const module_id_t gnb_mod_idP, const int CC_idP, const frame_t frameP, @@ -685,9 +693,8 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, const int pusch_failure_thres = gNB_mac->pusch_failure_thres; NR_UE_info_t *UE = find_nr_UE(&gNB_mac->UE_info, current_rnti); - bool UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(gNB_mac, CC_idP, frameP, slotP, current_rnti); - if (UE && UE_waiting_CFRA_msg3 == false) { + if (UE) { NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl; @@ -791,74 +798,45 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs); } } - } else if (sduP) { - - bool no_sig = true; - for (uint32_t k = 0; k < sdu_lenP; k++) { - if (sduP[k] != 0) { - no_sig = false; - break; - } + } else { + UE = find_ra_UE(&gNB_mac->UE_info, current_rnti); + if (!UE) { + LOG_E(NR_MAC, "UL SDU discarded. Couldn't finde UE with RNTI %04x \n", current_rnti); + return; } + NR_RA_t *ra = UE->ra; + if (ra->ra_type == RA_4_STEP && ra->ra_state != nrRA_WAIT_Msg3) { + LOG_W(NR_MAC, "UL SDU discarded for RNTI %04x RA state not waiting for PUSCH\n", UE->rnti); + return; + } + if (sduP) { + bool no_sig = true; + for (uint32_t k = 0; k < sdu_lenP; k++) { + if (sduP[k] != 0) { + no_sig = false; + break; + } + } - T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP), - T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */, - T_BUFFER(sduP, sdu_lenP)); + T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP), + T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */, + T_BUFFER(sduP, sdu_lenP)); - /* we don't know this UE (yet). Check whether there is a ongoing RA (Msg 3) - * and check the corresponding UE's RNTI match, in which case we activate - * it. */ - for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { - NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i]; - if (ra->ra_type == RA_4_STEP && ra->ra_state != nrRA_WAIT_Msg3) - continue; if (no_sig) { - LOG_W(NR_MAC, "Random Access %i ULSCH with no signal\n", i); - handle_msg3_failed_rx(ra, i, gNB_mac->ul_bler.harq_round_max); - continue; + LOG_W(NR_MAC, "MSG3 ULSCH with no signal\n"); + handle_msg3_failed_rx(gNB_mac, ra, current_rnti, gNB_mac->ul_bler.harq_round_max); + return; } if (ra->ra_type == RA_2_STEP) { // random access pusch with RA-RNTI if (ra->RA_rnti != current_rnti) { LOG_E(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->RA_rnti, current_rnti); - continue; - } - } else { - // random access pusch with TC-RNTI - if (ra->rnti != current_rnti) { - LOG_E(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->rnti, current_rnti); - - if ((frameP == ra->Msg3_frame) && (slotP == ra->Msg3_slot)) { - LOG_W(NR_MAC, - "Random Access %i failed at state %s (TC_RNTI %04x RNTI %04x)\n", - i, - nrra_text[ra->ra_state], - ra->rnti, - current_rnti); - nr_clear_ra_proc(ra); - } - - continue; + return; } } - UE = UE ? UE : add_new_nr_ue(gNB_mac, ra->rnti, ra->CellGroup); - if (!UE) { - LOG_W(NR_MAC, - "Random Access %i discarded at state %s (TC_RNTI %04x RNTI %04x): max number of users achieved!\n", - i, - nrra_text[ra->ra_state], - ra->rnti, - current_rnti); - - nr_clear_ra_proc(ra); - return; - } - - UE->UE_beam_index = ra->beam_id; - - // re-initialize ta update variables after RA procedure completion + // re-initialize ta update variables after RA procedure completion UE->UE_sched_ctrl.ta_frame = frameP; LOG_A(NR_MAC, "%4d.%2d PUSCH with TC_RNTI 0x%04x received correctly\n", frameP, slotP, current_rnti); @@ -873,12 +851,16 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, UE_scheduling_control->raw_rssi = rssi; LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update); if (ra->cfra) { - LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", ra->rnti); + LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", UE->rnti); nr_mac_reset_ul_failure(UE_scheduling_control); reset_dl_harq_list(UE_scheduling_control); reset_ul_harq_list(UE_scheduling_control); - process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, ra->CellGroup->rlc_BearerToAddModList); - nr_clear_ra_proc(ra); + process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, UE->CellGroup->rlc_BearerToAddModList); + if (!transition_ra_connected_nr_ue(gNB_mac, UE)) { + LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti); + delete_nr_ue_data(UE, NULL, &gNB_mac->UE_info.uid_allocator); + return; + } } else { LOG_D(NR_MAC, "[RAPROC] Received %s:\n", ra->ra_type == RA_2_STEP ? "MsgA-PUSCH" : "Msg3"); for (uint32_t k = 0; k < sdu_lenP; k++) { @@ -892,40 +874,20 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, // Search for MAC CE for C-RNTI rnti_t crnti = lcid_crnti_lookahead(sduP, sdu_lenP); if (crnti != 0) { // 3GPP TS 38.321 Table 7.1-1: RNTI values, RNTI 0x0000: N/A - // this UE is the one identified by the RNTI in sduP - ra->rnti = crnti; - // Remove UE context just created after Msg.3 in some milliseconds as the UE is one already known (not now, as the UE - // context is still needed for the moment) - nr_mac_trigger_release_timer(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs); - // Replace the current UE by the UE identified by C-RNTI - UE = find_nr_UE(&gNB_mac->UE_info, crnti); - if (!UE) { + NR_UE_info_t *old_UE = find_nr_UE(&gNB_mac->UE_info, crnti); + if (!old_UE) { // The UE identified by C-RNTI no longer exists at the gNB // Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better // solution may be implemented - LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg3 to have UE come back with new RA attempt\n", ra->rnti); - mac_remove_nr_ue(gNB_mac, ra->rnti); - nr_clear_ra_proc(ra); + LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg3 to have UE come back with new RA attempt\n", UE->rnti); + nr_release_ra_UE(gNB_mac, current_rnti); return; } - - // The UE identified by C-RNTI still exists at the gNB - // Reset Msg4_ACKed to not schedule ULSCH and DLSCH before RRC Reconfiguration - UE->Msg4_MsgB_ACKed = false; - nr_mac_reset_ul_failure(&UE->UE_sched_ctrl); - // Reset HARQ processes - reset_dl_harq_list(&UE->UE_sched_ctrl); - reset_ul_harq_list(&UE->UE_sched_ctrl); - - // Switch to BWP where RA is configured, typically in the InitialBWP - // At this point, UE already switched and triggered RA in that BWP, need to do BWP switching also at gNB for C-RNTI - if (ra->DL_BWP.bwp_id != UE->current_DL_BWP.bwp_id || ra->UL_BWP.bwp_id != UE->current_UL_BWP.bwp_id) { - LOG_D(NR_MAC, "UE %04x Switch BWP from %ld to BWP id %ld\n", UE->rnti, UE->current_DL_BWP.bwp_id, ra->DL_BWP.bwp_id); - NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_idP].ServingCellConfigCommon; - configure_UE_BWP(gNB_mac, scc, &UE->UE_sched_ctrl, NULL, UE, ra->DL_BWP.bwp_id, ra->UL_BWP.bwp_id); - } - + // remove old UE from connected UEs + remove_UE_from_list(MAX_MOBILES_PER_GNB + 1, gNB_mac->UE_info.connected_ue_list, crnti); + UE = configure_UE_crnti_msg3(gNB_mac, old_UE, UE); + ra = UE->ra; if (UE->reconfigCellGroup) { // Nothing to do // A RRCReconfiguration message should be already pending (for example, an ongoing RRCReestablishment), and it will be @@ -950,26 +912,23 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, LOG_I(NR_MAC, "Activating scheduling %s for TC_RNTI 0x%04x (state %s)\n", ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4", - ra->rnti, + UE->rnti, nrra_text[ra->ra_state]); ra->ra_state = ra->ra_type == RA_2_STEP ? nrRA_MsgB : nrRA_Msg4; - LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", ra->rnti, nrra_text[ra->ra_state]); + LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", UE->rnti, nrra_text[ra->ra_state]); return; } - } - } else { - for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { - NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i]; + } else { if (ra->ra_state != nrRA_WAIT_Msg3) - continue; + return; if((frameP!=ra->Msg3_frame) || (slotP!=ra->Msg3_slot)) - continue; + return; if (ul_cqi != 0xff) ra->msg3_TPC = nr_get_tpc(target_snrx10, ul_cqi, 30, 0); - handle_msg3_failed_rx(ra, i, gNB_mac->ul_bler.harq_round_max); + handle_msg3_failed_rx(gNB_mac, ra, current_rnti, gNB_mac->ul_bler.harq_round_max); } } } @@ -1891,7 +1850,7 @@ static void pf_ul(module_id_t module_id, UE_iterator(UE_list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - if (!UE->Msg4_MsgB_ACKed || sched_ctrl->ul_failure) + if (sched_ctrl->ul_failure) continue; LOG_D(NR_MAC,"pf_ul: preparing UL scheduling for UE %04x\n",UE->rnti); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 8b403f9e86..5bb9f902ef 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -60,8 +60,8 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const plmn_id_t *plmn, uint64_t cellID, int tac); bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_sib_msg_t cu_sib[num_cu_sib]); bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); -bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); - +void nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, NR_UE_info_t *UE); +bool add_new_UE_RA(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE); int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs); bool nr_mac_prepare_cellgroup_update(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, NR_CellGroupConfig_t *CellGroup); @@ -135,8 +135,6 @@ void nr_initiate_ra_proc(module_id_t module_idP, int16_t timing_offset, uint32_t preamble_power); -void nr_clear_ra_proc(NR_RA_t *ra); - int nr_allocate_CCEs(int module_idP, int CC_idP, frame_t frameP, slot_t slotP, int test_only); void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP); @@ -310,21 +308,22 @@ void remove_nr_list(NR_list_t *listP, int id); void add_tail_nr_list(NR_list_t *listP, int id); void add_front_nr_list(NR_list_t *listP, int id); void remove_front_nr_list(NR_list_t *listP); - +void nr_release_ra_UE(gNB_MAC_INST *mac, rnti_t rnti); NR_UE_info_t * find_nr_UE(NR_UEs_t* UEs, rnti_t rntiP); - +NR_UE_info_t *find_ra_UE(NR_UEs_t *UEs, rnti_t rntiP); +void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_allocator_t *uia); void configure_UE_BWP(gNB_MAC_INST *nr_mac, NR_ServingCellConfigCommon_t *scc, - NR_UE_sched_ctrl_t *sched_ctrl, - NR_RA_t *ra, NR_UE_info_t *UE, + bool is_RA, int dl_bwp_switch, int ul_bwp_switch); -NR_UE_info_t* add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup); - +bool transition_ra_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE); +bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE); +void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, NR_UE_info_t *UE, bool success); void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti); - +NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup); int nr_get_default_pucch_res(int pucch_ResourceCommon); int nr_write_ce_dlsch_pdu(module_id_t module_idP, @@ -362,11 +361,7 @@ void reset_dl_harq_list(NR_UE_sched_ctrl_t *sched_ctrl); void reset_ul_harq_list(NR_UE_sched_ctrl_t *sched_ctrl); -void handle_nr_ul_harq(const int CC_idP, - module_id_t mod_id, - frame_t frame, - slot_t slot, - const nfapi_nr_crc_t *crc_pdu); +void handle_nr_ul_harq(module_id_t mod_id, frame_t frame, slot_t slot, const nfapi_nr_crc_t *crc_pdu); uint8_t *allocate_transportBlock_buffer(byte_array_t *tb, uint32_t needed); void free_transportBlock_buffer(byte_array_t *tb); @@ -394,7 +389,8 @@ uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx); uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format); void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl); - +bool add_UE_to_list(int list_size, NR_UE_info_t *list[list_size], NR_UE_info_t *UE); +NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], rnti_t rnti); int get_dl_tda(const gNB_MAC_INST *nrmac, int slot); int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot); @@ -430,7 +426,6 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options, int ul_buffer_index(int frame, int slot, int slots_per_frame, int size); void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t frameP, int slotP); - void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, gNB_MAC_INST *mac); int get_fapi_beamforming_index(gNB_MAC_INST *mac, int ssb_idx); NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame); @@ -467,7 +462,7 @@ void process_addmod_bearers_cellGroupConfig(NR_UE_sched_ctrl_t *sched_ctrl, bool nr_mac_add_lcid(NR_UE_sched_ctrl_t *sched_ctrl, const nr_lc_config_t *c); bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid); -bool nr_mac_get_new_rnti(NR_UEs_t *UEs, const NR_RA_t *ra_base, int ra_count, rnti_t *rnti); +bool nr_mac_get_new_rnti(NR_UEs_t *UEs, rnti_t *rnti); void nr_mac_update_pdcch_closed_loop_adjust(NR_UE_sched_ctrl_t *sched_ctrl, bool feedback_not_detected); void prepare_du_configuration_update(gNB_MAC_INST *mac, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 51357e2978..bc0a53a645 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -476,15 +476,18 @@ NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig) static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id) { int CC_id = 0; - const NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; rnti_t rnti; - bool found = nr_mac_get_new_rnti(&mac->UE_info, cc->ra, sizeofArray(cc->ra), &rnti); + bool found = nr_mac_get_new_rnti(&mac->UE_info, &rnti); if (!found) return NULL; - NR_UE_info_t* UE = add_new_nr_ue(mac, rnti, NULL); - if (!UE) + NR_UE_info_t *UE = get_new_nr_ue_inst(&mac->UE_info.uid_allocator, rnti, NULL); + AssertFatal(UE != NULL, "cannot create UE context, UE context setup failure not implemented\n"); + if (!add_new_UE_RA(mac, UE)) { + delete_nr_ue_data(UE, /*not used*/ NULL, &mac->UE_info.uid_allocator); + LOG_E(NR_MAC, "UE list full while creating new UE\n"); return NULL; + } f1_ue_data_t new_ue_data = {.secondary_ue = cu_id}; bool success = du_add_f1_ue_data(rnti, &new_ue_data); @@ -499,11 +502,10 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id) // by add_new_nr_ue(); it's a kind of chicken-and-egg problem), so below we // complete the UE context with the information that add_new_nr_ue() would // have added - UE->Msg4_MsgB_ACKed = true; UE->CellGroup = cellGroupConfig; nr_rlc_activate_srb0(UE->rnti, UE, NULL); - nr_mac_prepare_ra_ue(mac, rnti, UE->CellGroup); + nr_mac_prepare_ra_ue(mac, UE); /* SRB1 is added to RLC and MAC in the handler later */ return UE; } @@ -759,13 +761,6 @@ void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse return; } - const int CC_id = 0; - NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - NR_RA_t *ra = &cc->ra[i]; - if (ra->rnti == UE->rnti) - nr_clear_ra_proc(ra); - } NR_SCHED_UNLOCK(&mac->sched_lock); f1ap_ue_context_release_req_t request = { @@ -822,6 +817,7 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) pthread_mutex_lock(&mac->sched_lock); /* check first that the scheduler knows such UE */ NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, dl_rrc->gNB_DU_ue_id); + UE = UE ? UE : find_ra_UE(&mac->UE_info, dl_rrc->gNB_DU_ue_id); if (UE == NULL) { LOG_E(MAC, "ERROR: unknown UE with RNTI %04x, ignoring DL RRC Message Transfer\n", dl_rrc->gNB_DU_ue_id); pthread_mutex_unlock(&mac->sched_lock); @@ -870,12 +866,11 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) * from the current configuration. Also, expect the reconfiguration from * the CU, so save the old UE's CellGroup for the new UE */ UE->CellGroup->spCellConfig = NULL; - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; uid_t temp_uid = UE->uid; UE->uid = oldUE->uid; oldUE->uid = temp_uid; - configure_UE_BWP(mac, scc, sched_ctrl, NULL, UE, -1, -1); + configure_UE_BWP(mac, scc, UE, false, -1, -1); for (int i = 1; i < seq_arr_size(&oldUE->UE_sched_ctrl.lc_config); ++i) { const nr_lc_config_t *c = seq_arr_at(&oldUE->UE_sched_ctrl.lc_config, i); nr_mac_add_lcid(&UE->UE_sched_ctrl, c); diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 13da756d56..20602b8641 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -362,6 +362,9 @@ void mac_top_destroy_gNB(gNB_MAC_INST *mac) for (int i = 0; i < sizeofArray(UE_info->connected_ue_list); ++i) if (UE_info->connected_ue_list[i]) delete_nr_ue_data(UE_info->connected_ue_list[i], cc, &UE_info->uid_allocator); + for (int i = 0; i < sizeofArray(UE_info->access_ue_list); ++i) + if (UE_info->access_ue_list[i]) + delete_nr_ue_data(UE_info->access_ue_list[i], cc, &UE_info->uid_allocator); } void nr_mac_send_f1_setup_req(void) diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 5d14bd9007..6002c5756f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -229,8 +229,6 @@ typedef struct { NR_beam_alloc_t Msg3_beam; /// harq_pid used for Msg4 transmission uint8_t harq_pid; - /// UE RNTI allocated during RAR - rnti_t rnti; /// RA RNTI allocated from received PRACH uint16_t RA_rnti; /// MsgB RNTI allocated from received MsgA @@ -251,25 +249,12 @@ typedef struct { int msg3_nbSymb; /// MAC PDU length for Msg4 int mac_pdu_length; - /// RA search space - NR_SearchSpace_t *ra_ss; - /// RA Coreset - NR_ControlResourceSet_t *coreset; - NR_sched_pdcch_t sched_pdcch; - // Beam index - uint8_t beam_id; - /// CellGroup for UE that is to come (NSA is non-null, null for SA) - NR_CellGroupConfig_t *CellGroup; /// Preambles for contention-free access NR_preamble_ue_t preambles; int contention_resolution_timer; nr_ra_type_t ra_type; /// CFRA flag bool cfra; - // BWP for RA - NR_UE_DL_BWP_t DL_BWP; - NR_UE_UL_BWP_t UL_BWP; - NR_UE_ServingCell_Info_t sc_info; } NR_RA_t; /*! \brief gNB common channels */ @@ -289,8 +274,6 @@ typedef struct { /// used for otherSIB data uint8_t other_sib_bcch_pdu[2][NR_MAX_SIB_LENGTH / 8]; int other_sib_bcch_length[2]; - /// Template for RA computations - NR_RA_t ra[NR_NB_RA_PROC_MAX]; /// VRB map for common channels uint16_t vrb_map[MAX_NUM_BEAM_PERIODS][275]; /// VRB map for common channels and PUSCH, dynamically allocated because @@ -654,7 +637,6 @@ typedef struct { int pusch_snrx10; int pucch_snrx10; uint16_t ul_rssi; - uint8_t current_harq_pid; int pusch_consecutive_dtx_cnt; int pucch_consecutive_dtx_cnt; bool ul_failure; @@ -770,11 +752,11 @@ typedef struct { NR_UE_NR_Capability_t *capability; // UE selected beam index uint8_t UE_beam_index; - bool Msg4_MsgB_ACKed; float ul_thr_ue; float dl_thr_ue; long pdsch_HARQ_ACK_Codebook; bool is_redcap; + NR_RA_t *ra; } NR_UE_info_t; typedef struct { @@ -782,6 +764,7 @@ typedef struct { // last element always NULL pthread_mutex_t mutex; NR_UE_info_t *connected_ue_list[MAX_MOBILES_PER_GNB + 1]; + NR_UE_info_t *access_ue_list[NR_NB_RA_PROC_MAX]; // bitmap of CSI-RS already scheduled in current slot int sched_csirs; uid_allocator_t uid_allocator; diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index e82a185ba8..47fad165cd 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -203,7 +203,7 @@ static void handle_nr_ulsch(NR_UL_IND_t *UL_info) crc->timing_advance, crc->ul_cqi, crc->rssi); - handle_nr_ul_harq(UL_info->CC_id, UL_info->module_id, UL_info->frame, UL_info->slot, crc); + handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); } UL_info->rx_ind.number_of_pdus = 0; UL_info->crc_ind.number_crcs = 0; diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index e41875027e..714ac5b067 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -371,9 +371,17 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a && secondaryCellGroup->spCellConfig->reconfigurationWithSync && secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated && secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra); - NR_SCHED_LOCK(&RC.nrmac[rrc->module_id]->sched_lock); - ret = nr_mac_prepare_ra_ue(RC.nrmac[rrc->module_id], du_ue_id, secondaryCellGroup); - NR_SCHED_UNLOCK(&RC.nrmac[rrc->module_id]->sched_lock); + gNB_MAC_INST *nrmac = RC.nrmac[rrc->module_id]; + NR_SCHED_LOCK(&nrmac->sched_lock); + NR_UE_info_t *UE_info = get_new_nr_ue_inst(&nrmac->UE_info.uid_allocator, UE->rnti, secondaryCellGroup); + AssertFatal(UE_info != NULL, "cannot create UE context: list is full?\n"); + if (add_new_UE_RA(nrmac, UE_info)) { + ret = true; + nr_mac_prepare_ra_ue(nrmac, UE_info); + } else { + delete_nr_ue_data(UE_info, /* not used */ NULL, &nrmac->UE_info.uid_allocator); + } + NR_SCHED_UNLOCK(&nrmac->sched_lock); } AssertFatal(ret, "cannot add NSA UE in MAC, aborting\n"); From bf37994f78fa15f89accbd372be7ed7bab77174a Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 28 Mar 2025 17:47:54 +0100 Subject: [PATCH 06/25] separate function for RA ULSCH SDU --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 282 ++++++++++-------- 1 file changed, 151 insertions(+), 131 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 5ca2b69151..654b044654 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -672,6 +672,156 @@ static NR_UE_info_t *configure_UE_crnti_msg3(gNB_MAC_INST *mac, NR_UE_info_t *ol return old_UE; } +static void nr_rx_ra_sdu(const module_id_t mod_id, + const int CC_id, + const frame_t frame, + const sub_frame_t slot, + rnti_t rnti, + uint8_t *sdu, + const uint32_t sdu_len, + const uint16_t timing_advance, + const uint8_t ul_cqi, + const uint16_t rssi) +{ + gNB_MAC_INST *mac = RC.nrmac[mod_id]; + NR_UE_info_t *UE = find_ra_UE(&mac->UE_info, rnti); + if (!UE) { + LOG_E(NR_MAC, "UL SDU discarded. Couldn't finde UE with RNTI %04x \n", rnti); + return; + } + + NR_RA_t *ra = UE->ra; + if (ra->ra_type == RA_4_STEP && ra->ra_state != nrRA_WAIT_Msg3) { + LOG_W(NR_MAC, "UL SDU discarded for RNTI %04x RA state not waiting for PUSCH\n", UE->rnti); + return; + } + + const int target_snrx10 = mac->pusch_target_snrx10; + if (!sdu) { // NACK + if (ra->ra_state != nrRA_WAIT_Msg3) + return; + + if((frame!=ra->Msg3_frame) || (slot!=ra->Msg3_slot)) + return; + + if (ul_cqi != 0xff) + ra->msg3_TPC = nr_get_tpc(target_snrx10, ul_cqi, 30, 0); + + handle_msg3_failed_rx(mac, ra, rnti, mac->ul_bler.harq_round_max); + return; + } + + + bool no_sig = true; + for (uint32_t k = 0; k < sdu_len; k++) { + if (sdu[k] != 0) { + no_sig = false; + break; + } + } + + T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(mod_id), T_INT(CC_id), + T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(-1) /* harq_pid */, + T_BUFFER(sdu, sdu_len)); + + + if (no_sig) { + LOG_W(NR_MAC, "MSG3 ULSCH with no signal\n"); + handle_msg3_failed_rx(mac, ra, rnti, mac->ul_bler.harq_round_max); + return; + } + if (ra->ra_type == RA_2_STEP) { + // random access pusch with RA-RNTI + if (ra->RA_rnti != rnti) { + LOG_E(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->RA_rnti, rnti); + return; + } + } + + // re-initialize ta update variables after RA procedure completion + UE->UE_sched_ctrl.ta_frame = frame; + + LOG_A(NR_MAC, "%4d.%2d PUSCH with TC_RNTI 0x%04x received correctly\n", frame, slot, rnti); + + NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl; + if (ul_cqi != 0xff) { + UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10, ul_cqi, 30, UE_scheduling_control->sched_pusch.phr_txpower_calc); + UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640 - UE_scheduling_control->sched_pusch.phr_txpower_calc * 10; + } + if (timing_advance != 0xffff) + UE_scheduling_control->ta_update = timing_advance; + UE_scheduling_control->raw_rssi = rssi; + LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update); + if (ra->cfra) { + LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", UE->rnti); + nr_mac_reset_ul_failure(UE_scheduling_control); + reset_dl_harq_list(UE_scheduling_control); + reset_ul_harq_list(UE_scheduling_control); + process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, UE->CellGroup->rlc_BearerToAddModList); + if (!transition_ra_connected_nr_ue(mac, UE)) { + LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti); + delete_nr_ue_data(UE, NULL, &mac->UE_info.uid_allocator); + return; + } + } else { + LOG_D(NR_MAC, "[RAPROC] Received %s:\n", ra->ra_type == RA_2_STEP ? "MsgA-PUSCH" : "Msg3"); + for (uint32_t k = 0; k < sdu_len; k++) { + LOG_D(NR_MAC, "(%i): 0x%x\n", k, sdu[k]); + } + + // 3GPP TS 38.321 Section 5.4.3 Multiplexing and assembly + // Logical channels shall be prioritised in accordance with the following order (highest priority listed first): + // - MAC CE for C-RNTI, or data from UL-CCCH; + // This way, we need to process MAC CE for C-RNTI if RA is active and it is present in the MAC PDU + // Search for MAC CE for C-RNTI + rnti_t crnti = lcid_crnti_lookahead(sdu, sdu_len); + if (crnti != 0) { // 3GPP TS 38.321 Table 7.1-1: RNTI values, RNTI 0x0000: N/A + // Replace the current UE by the UE identified by C-RNTI + NR_UE_info_t *old_UE = find_nr_UE(&mac->UE_info, crnti); + if (!old_UE) { + // The UE identified by C-RNTI no longer exists at the gNB + // Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better + // solution may be implemented + LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg3 to have UE come back with new RA attempt\n", UE->rnti); + nr_release_ra_UE(mac, rnti); + return; + } + // remove old UE from connected UEs + remove_UE_from_list(MAX_MOBILES_PER_GNB + 1, mac->UE_info.connected_ue_list, crnti); + UE = configure_UE_crnti_msg3(mac, old_UE, UE); + ra = UE->ra; + if (UE->reconfigCellGroup) { + // Nothing to do + // A RRCReconfiguration message should be already pending (for example, an ongoing RRCReestablishment), and it will be + // transmitted in Msg4 + } else { + // Trigger RRC Reconfiguration + LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", UE->rnti); + nr_mac_trigger_reconfiguration(mac, UE); + } + } else { + // UE Contention Resolution Identity + // Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to fill in Msg4 + // First byte corresponds to R/LCID MAC sub-header + memcpy(ra->cont_res_id, &sdu[1], sizeof(uint8_t) * 6); + } + + // Decode MAC PDU for the correct UE, after checking for MAC CE for C-RNTI + // harq_pid set a non valid value because it is not used in this call + // the function is only called to decode the contention resolution sub-header + nr_process_mac_pdu(mod_id, UE, CC_id, frame, slot, sdu, sdu_len, -1); + + LOG_I(NR_MAC, + "Activating scheduling %s for TC_RNTI 0x%04x (state %s)\n", + ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4", + UE->rnti, + nrra_text[ra->ra_state]); + ra->ra_state = ra->ra_type == RA_2_STEP ? nrRA_MsgB : nrRA_Msg4; + LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", UE->rnti, nrra_text[ra->ra_state]); + return; + } +} + static void _nr_rx_sdu(const module_id_t gnb_mod_idP, const int CC_idP, const frame_t frameP, @@ -799,137 +949,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, } } } else { - UE = find_ra_UE(&gNB_mac->UE_info, current_rnti); - if (!UE) { - LOG_E(NR_MAC, "UL SDU discarded. Couldn't finde UE with RNTI %04x \n", current_rnti); - return; - } - NR_RA_t *ra = UE->ra; - if (ra->ra_type == RA_4_STEP && ra->ra_state != nrRA_WAIT_Msg3) { - LOG_W(NR_MAC, "UL SDU discarded for RNTI %04x RA state not waiting for PUSCH\n", UE->rnti); - return; - } - if (sduP) { - bool no_sig = true; - for (uint32_t k = 0; k < sdu_lenP; k++) { - if (sduP[k] != 0) { - no_sig = false; - break; - } - } - - T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP), - T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */, - T_BUFFER(sduP, sdu_lenP)); - - - if (no_sig) { - LOG_W(NR_MAC, "MSG3 ULSCH with no signal\n"); - handle_msg3_failed_rx(gNB_mac, ra, current_rnti, gNB_mac->ul_bler.harq_round_max); - return; - } - if (ra->ra_type == RA_2_STEP) { - // random access pusch with RA-RNTI - if (ra->RA_rnti != current_rnti) { - LOG_E(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->RA_rnti, current_rnti); - return; - } - } - - // re-initialize ta update variables after RA procedure completion - UE->UE_sched_ctrl.ta_frame = frameP; - - LOG_A(NR_MAC, "%4d.%2d PUSCH with TC_RNTI 0x%04x received correctly\n", frameP, slotP, current_rnti); - - NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl; - if (ul_cqi != 0xff) { - UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10, ul_cqi, 30, UE_scheduling_control->sched_pusch.phr_txpower_calc); - UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640 - UE_scheduling_control->sched_pusch.phr_txpower_calc * 10; - } - if (timing_advance != 0xffff) - UE_scheduling_control->ta_update = timing_advance; - UE_scheduling_control->raw_rssi = rssi; - LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update); - if (ra->cfra) { - LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", UE->rnti); - nr_mac_reset_ul_failure(UE_scheduling_control); - reset_dl_harq_list(UE_scheduling_control); - reset_ul_harq_list(UE_scheduling_control); - process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, UE->CellGroup->rlc_BearerToAddModList); - if (!transition_ra_connected_nr_ue(gNB_mac, UE)) { - LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti); - delete_nr_ue_data(UE, NULL, &gNB_mac->UE_info.uid_allocator); - return; - } - } else { - LOG_D(NR_MAC, "[RAPROC] Received %s:\n", ra->ra_type == RA_2_STEP ? "MsgA-PUSCH" : "Msg3"); - for (uint32_t k = 0; k < sdu_lenP; k++) { - LOG_D(NR_MAC, "(%i): 0x%x\n", k, sduP[k]); - } - - // 3GPP TS 38.321 Section 5.4.3 Multiplexing and assembly - // Logical channels shall be prioritised in accordance with the following order (highest priority listed first): - // - MAC CE for C-RNTI, or data from UL-CCCH; - // This way, we need to process MAC CE for C-RNTI if RA is active and it is present in the MAC PDU - // Search for MAC CE for C-RNTI - rnti_t crnti = lcid_crnti_lookahead(sduP, sdu_lenP); - if (crnti != 0) { // 3GPP TS 38.321 Table 7.1-1: RNTI values, RNTI 0x0000: N/A - // Replace the current UE by the UE identified by C-RNTI - NR_UE_info_t *old_UE = find_nr_UE(&gNB_mac->UE_info, crnti); - if (!old_UE) { - // The UE identified by C-RNTI no longer exists at the gNB - // Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better - // solution may be implemented - LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg3 to have UE come back with new RA attempt\n", UE->rnti); - nr_release_ra_UE(gNB_mac, current_rnti); - return; - } - // remove old UE from connected UEs - remove_UE_from_list(MAX_MOBILES_PER_GNB + 1, gNB_mac->UE_info.connected_ue_list, crnti); - UE = configure_UE_crnti_msg3(gNB_mac, old_UE, UE); - ra = UE->ra; - if (UE->reconfigCellGroup) { - // Nothing to do - // A RRCReconfiguration message should be already pending (for example, an ongoing RRCReestablishment), and it will be - // transmitted in Msg4 - } else { - // Trigger RRC Reconfiguration - LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", UE->rnti); - nr_mac_trigger_reconfiguration(gNB_mac, UE); - } - } else { - // UE Contention Resolution Identity - // Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to fill in Msg4 - // First byte corresponds to R/LCID MAC sub-header - memcpy(ra->cont_res_id, &sduP[1], sizeof(uint8_t) * 6); - } - - // Decode MAC PDU for the correct UE, after checking for MAC CE for C-RNTI - // harq_pid set a non valid value because it is not used in this call - // the function is only called to decode the contention resolution sub-header - nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP, -1); - - LOG_I(NR_MAC, - "Activating scheduling %s for TC_RNTI 0x%04x (state %s)\n", - ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4", - UE->rnti, - nrra_text[ra->ra_state]); - ra->ra_state = ra->ra_type == RA_2_STEP ? nrRA_MsgB : nrRA_Msg4; - LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", UE->rnti, nrra_text[ra->ra_state]); - return; - } - } else { - if (ra->ra_state != nrRA_WAIT_Msg3) - return; - - if((frameP!=ra->Msg3_frame) || (slotP!=ra->Msg3_slot)) - return; - - if (ul_cqi != 0xff) - ra->msg3_TPC = nr_get_tpc(target_snrx10, ul_cqi, 30, 0); - - handle_msg3_failed_rx(gNB_mac, ra, current_rnti, gNB_mac->ul_bler.harq_round_max); - } + nr_rx_ra_sdu(gnb_mod_idP, CC_idP, frameP, slotP, current_rnti, sduP, sdu_lenP, timing_advance, ul_cqi, rssi); } } From 356a27aad10711e3a77066922243fcef3d90fab7 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 4 Mar 2025 17:26:52 +0100 Subject: [PATCH 07/25] handle ul harq inside rx sdu function --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 67 ++++++------------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 2 - openair2/NR_PHY_INTERFACE/NR_IF_Module.c | 1 - 3 files changed, 20 insertions(+), 50 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 654b044654..9fcf8a8e9c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -543,50 +543,31 @@ static void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid) sched_ctrl->sched_ul_bytes = 0; } -void handle_nr_ul_harq(module_id_t mod_id, frame_t frame, slot_t slot, const nfapi_nr_crc_t *crc_pdu) +static void handle_nr_ul_harq(gNB_MAC_INST *nrmac, + NR_UE_info_t *UE, + frame_t frame, + slot_t slot, + rnti_t rnti, + int crc_harq_id, + bool crc_status) { - gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; if (nrmac->radio_config.disable_harq) { LOG_D(NR_MAC, "skipping UL feedback handling as HARQ is disabled\n"); return; } - NR_SCHED_LOCK(&nrmac->sched_lock); - NR_UEs_t *UE_info = &nrmac->UE_info; - UE_iterator(UE_info->access_ue_list, ra_UE) { - const NR_RA_t *ra = ra_UE->ra; - // if we find any ongoing RA that has already scheduled MSG3 - // and it is expecting its reception in current frame and slot with matching RNTI - // we can exit the function (no HARQ involved) - if (ra->ra_state >= nrRA_WAIT_Msg3 && ra_UE->rnti == crc_pdu->rnti && frame == ra->Msg3_frame && slot == ra->Msg3_slot) { - LOG_D(NR_MAC, "UL for rnti %04x in RA (MSG3), no need to process HARQ\n", crc_pdu->rnti); - NR_SCHED_UNLOCK(&nrmac->sched_lock); - return; - } - } - - NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, crc_pdu->rnti); - UE = UE ? UE : find_ra_UE(&nrmac->UE_info, crc_pdu->rnti); - if (!UE) { - NR_SCHED_UNLOCK(&nrmac->sched_lock); - LOG_E(NR_MAC, "Couldn't identify UE connected with current UL HARQ process\n"); - return; - } - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; int8_t harq_pid = sched_ctrl->feedback_ul_harq.head; - LOG_D(NR_MAC, "Comparing crc_pdu->harq_id vs feedback harq_pid = %d %d\n",crc_pdu->harq_id, harq_pid); - while (crc_pdu->harq_id != harq_pid || harq_pid < 0) { - LOG_W(NR_MAC, "Unexpected ULSCH HARQ PID %d (have %d) for RNTI 0x%04x\n", crc_pdu->harq_id, harq_pid, crc_pdu->rnti); - if (harq_pid < 0) { - NR_SCHED_UNLOCK(&nrmac->sched_lock); + LOG_D(NR_MAC, "Comparing crc harq_id vs feedback harq_pid = %d %d\n", crc_harq_id, harq_pid); + while (crc_harq_id != harq_pid || harq_pid < 0) { + LOG_W(NR_MAC, "Unexpected ULSCH HARQ PID %d (have %d) for RNTI 0x%04x\n", crc_harq_id, harq_pid, rnti); + if (harq_pid < 0) return; - } remove_front_nr_list(&sched_ctrl->feedback_ul_harq); sched_ctrl->ul_harq_processes[harq_pid].is_waiting = false; - if(sched_ctrl->ul_harq_processes[harq_pid].round >= RC.nrmac[mod_id]->ul_bler.harq_round_max - 1) { + if(sched_ctrl->ul_harq_processes[harq_pid].round >= nrmac->ul_bler.harq_round_max - 1) { abort_nr_ul_harq(UE, harq_pid); } else { sched_ctrl->ul_harq_processes[harq_pid].round++; @@ -599,27 +580,26 @@ void handle_nr_ul_harq(module_id_t mod_id, frame_t frame, slot_t slot, const nfa DevAssert(harq->is_waiting); harq->feedback_slot = -1; harq->is_waiting = false; - if (!crc_pdu->tb_crc_status) { + if (!crc_status) { finish_nr_ul_harq(sched_ctrl, harq_pid); LOG_D(NR_MAC, "Ulharq id %d crc passed for RNTI %04x\n", harq_pid, - crc_pdu->rnti); - } else if (harq->round >= RC.nrmac[mod_id]->ul_bler.harq_round_max - 1) { + rnti); + } else if (harq->round >= nrmac->ul_bler.harq_round_max - 1) { abort_nr_ul_harq(UE, harq_pid); LOG_D(NR_MAC, "RNTI %04x: Ulharq id %d crc failed in all rounds\n", - crc_pdu->rnti, + rnti, harq_pid); } else { harq->round++; LOG_D(NR_MAC, "Ulharq id %d crc failed for RNTI %04x\n", harq_pid, - crc_pdu->rnti); + rnti); add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid); } - NR_SCHED_UNLOCK(&nrmac->sched_lock); } static void handle_msg3_failed_rx(gNB_MAC_INST *mac, NR_RA_t *ra, rnti_t rnti, int harq_round_max) @@ -835,19 +815,14 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, const uint16_t rssi) { gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP]; - const int current_rnti = rntiP; LOG_D(NR_MAC, "rx_sdu for rnti %04x\n", current_rnti); const int target_snrx10 = gNB_mac->pusch_target_snrx10; const int rssi_threshold = gNB_mac->pusch_rssi_threshold; const int pusch_failure_thres = gNB_mac->pusch_failure_thres; - NR_UE_info_t *UE = find_nr_UE(&gNB_mac->UE_info, current_rnti); - if (UE) { - NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl; - if (sduP) T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP), T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(harq_pid), @@ -886,7 +861,6 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, UE_scheduling_control->ta_update = timing_advance; UE_scheduling_control->raw_rssi = rssi; UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640 - (txpower_calc * 10); - if (UE_scheduling_control->tpc0 > 1) LOG_D(NR_MAC, "[UE %04x] %d.%d. PUSCH TPC %d and TA %d pusch_snrx10 %d rssi %d phrx_tx_power %d PHR (1PRB) %d mcs %d, nb_rb %d\n", @@ -904,7 +878,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, NR_UE_ul_harq_t *cur_harq = &UE_scheduling_control->ul_harq_processes[harq_pid]; if (cur_harq->round == 0) - UE->mac_stats.pusch_snrx10 = UE_scheduling_control->pusch_snrx10; + UE->mac_stats.pusch_snrx10 = UE_scheduling_control->pusch_snrx10; LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n",UE->rnti,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update); } else{ @@ -926,15 +900,13 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, if (sduP != NULL) { LOG_D(NR_MAC, "Received PDU at MAC gNB \n"); - UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt = 0; UE_scheduling_control->sched_ul_bytes -= sdu_lenP; if (UE_scheduling_control->sched_ul_bytes < 0) UE_scheduling_control->sched_ul_bytes = 0; nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP, harq_pid); - } - else { + } else { if (ul_cqi == 0xff || ul_cqi <= 128) { UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt++; UE->mac_stats.ulsch_DTX++; @@ -948,6 +920,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs); } } + handle_nr_ul_harq(gNB_mac, UE, frameP, slotP, current_rnti, harq_pid, sduP == NULL); } else { nr_rx_ra_sdu(gnb_mod_idP, CC_idP, frameP, slotP, current_rnti, sduP, sdu_lenP, timing_advance, ul_cqi, rssi); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 5bb9f902ef..aebc53f8f4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -361,8 +361,6 @@ void reset_dl_harq_list(NR_UE_sched_ctrl_t *sched_ctrl); void reset_ul_harq_list(NR_UE_sched_ctrl_t *sched_ctrl); -void handle_nr_ul_harq(module_id_t mod_id, frame_t frame, slot_t slot, const nfapi_nr_crc_t *crc_pdu); - uint8_t *allocate_transportBlock_buffer(byte_array_t *tb, uint32_t needed); void free_transportBlock_buffer(byte_array_t *tb); diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index 47fad165cd..2352870ace 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -203,7 +203,6 @@ static void handle_nr_ulsch(NR_UL_IND_t *UL_info) crc->timing_advance, crc->ul_cqi, crc->rssi); - handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc); } UL_info->rx_ind.number_of_pdus = 0; UL_info->crc_ind.number_crcs = 0; From 5729b638a53f0787b4ebecdd4309121cc9286a48 Mon Sep 17 00:00:00 2001 From: francescomani Date: Fri, 7 Mar 2025 14:38:46 +0100 Subject: [PATCH 08/25] add dci 10 to config --- openair2/RRC/NR/nr_rrc_config.c | 11 ++++++++++- openair2/RRC/NR_UE/rrc_UE.c | 3 +-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 32f0ccae40..df7cabf804 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -3128,7 +3128,15 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, asn1cSeqAdd(&bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list, coreset); - int searchspaceid = 5; + int css_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; + css_num_agg_level_candidates[PDCCH_AGG_LEVEL1] = NR_SearchSpace__nrofCandidates__aggregationLevel1_n0; + css_num_agg_level_candidates[PDCCH_AGG_LEVEL2] = NR_SearchSpace__nrofCandidates__aggregationLevel2_n0; + css_num_agg_level_candidates[PDCCH_AGG_LEVEL4] = NR_SearchSpace__nrofCandidates__aggregationLevel4_n1; + css_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; + css_num_agg_level_candidates[PDCCH_AGG_LEVEL16] = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; + int searchspaceid = 4; + NR_SearchSpace_t *ss = rrc_searchspace_config(true, searchspaceid, coreset->controlResourceSetId, css_num_agg_level_candidates); + searchspaceid = 5; int rrc_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; int num_cces = get_coreset_num_cces(coreset->frequencyDomainResources.buf, coreset->duration); verify_agg_levels(num_cces, @@ -3137,6 +3145,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, searchspaceid, rrc_num_agg_level_candidates); NR_SearchSpace_t *ss2 = rrc_searchspace_config(false, searchspaceid, coreset->controlResourceSetId, rrc_num_agg_level_candidates); + asn1cSeqAdd(&bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss); asn1cSeqAdd(&bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list, ss2); bwp_Dedicated->pdsch_Config = config_pdsch(bitmap, 0, pdsch_AntennaPorts); diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index f7aa232c71..b36c2d676d 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1138,8 +1138,7 @@ static void rrc_ue_generate_RRCSetupComplete(const NR_UE_RRC_INST_t *rrc, const nr_pdcp_data_req_srb(rrc->ue_id, srb_id, 0, size, buffer, deliver_pdu_srb_rlc, NULL); } -static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, - const NR_RRCSetup_t *rrcSetup) +static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, const NR_RRCSetup_t *rrcSetup) { // if the RRCSetup is received in response to an RRCReestablishmentRequest // or RRCResumeRequest or RRCResumeRequest1 From c494c631d162f1fe3589fe6a0aa76e13e1626fc7 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 11 Mar 2025 15:53:47 +0100 Subject: [PATCH 09/25] target search space as input of function to configure UE BWP --- openair1/SIMULATION/NR_PHY/dlsim.c | 2 +- openair2/LAYER2/NR_MAC_gNB/config.c | 3 ++- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 +- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 19 +++++++++++-------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 6 +----- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 8408d6ecb0..f675256b0b 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -804,7 +804,7 @@ printf("%d\n", slot); N_RB_DL = gNB->frame_parms.N_RB_DL; NR_UE_info_t *UE_info = RC.nrmac[0]->UE_info.connected_ue_list[0]; - configure_UE_BWP(RC.nrmac[0], scc, UE_info, false, -1, -1); + configure_UE_BWP(RC.nrmac[0], scc, UE_info, false, NR_SearchSpace__searchSpaceType_PR_ue_Specific, -1, -1); // stub to configure frame_parms // nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions); diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index dcd5fa220f..9b9b5b54ce 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -981,7 +981,8 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t NR_SCHED_UNLOCK(&nrmac->sched_lock); return false; } - configure_UE_BWP(nrmac, nrmac->common_channels[0].ServingCellConfigCommon, UE, false, -1, -1); + int ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + configure_UE_BWP(nrmac, nrmac->common_channels[0].ServingCellConfigCommon, UE, false, ss_type, -1, -1); process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, CellGroup->rlc_BearerToAddModList); AssertFatal(CellGroup->rlc_BearerToReleaseList == NULL, "cannot release bearers while adding new UEs\n"); NR_SCHED_UNLOCK(&nrmac->sched_lock); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index beb66aa6b7..595d849cc4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -768,7 +768,7 @@ void nr_initiate_ra_proc(module_id_t module_idP, LOG_A(NR_MAC, "%d.%d UE RA-RNTI %04x TC-RNTI %04x: initiating RA procedure\n", frame, slot, ra->RA_rnti, UE->rnti); // Configure RA BWP - configure_UE_BWP(nr_mac, scc, UE, true, -1, -1); + configure_UE_BWP(nr_mac, scc, UE, true, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); // return current SSB order in the list of tranmitted SSBs int n_ssb = ssb_index_from_prach(module_idP, frame, slot, preamble_index, freq_index, symbol); UE->UE_beam_index = get_fapi_beamforming_index(nr_mac, cc->ssb_index[n_ssb]); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index cb4592b4eb..727cf63cd6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -394,10 +394,10 @@ NR_ControlResourceSet_t *get_coreset(gNB_MAC_INST *nrmac, } } -NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc, - NR_BWP_DownlinkDedicated_t *bwp_Dedicated, - NR_SearchSpace__searchSpaceType_PR target_ss) { - +static NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc, + NR_BWP_DownlinkDedicated_t *bwp_Dedicated, + NR_SearchSpace__searchSpaceType_PR target_ss) +{ int n = 0; if(bwp_Dedicated) n = bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count; @@ -2208,6 +2208,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, NR_ServingCellConfigCommon_t *scc, NR_UE_info_t *UE, bool is_RA, + int target_ss, int dl_bwp_switch, int ul_bwp_switch) { @@ -2225,13 +2226,11 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, sc_info->n_ul_bwp = 0; int old_dl_bwp_id = DL_BWP->bwp_id; int old_ul_bwp_id = UL_BWP->bwp_id; - int target_ss; NR_ServingCellConfig_t *servingCellConfig = NULL; if (CellGroup && CellGroup->spCellConfig && CellGroup->spCellConfig->spCellConfigDedicated) { servingCellConfig = CellGroup->spCellConfig->spCellConfigDedicated; - target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific; if(dl_bwp_switch >= 0 && ul_bwp_switch >= 0) { AssertFatal(dl_bwp_switch == ul_bwp_switch, "Different UL and DL BWP not supported\n"); @@ -2291,7 +2290,6 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, else { DL_BWP->bwp_id = 0; UL_BWP->bwp_id = 0; - target_ss = NR_SearchSpace__searchSpaceType_PR_common; DL_BWP->pdsch_Config = NULL; UL_BWP->pusch_Config = NULL; UL_BWP->pucch_Config = NULL; @@ -3068,7 +3066,12 @@ static void nr_mac_apply_cellgroup(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - configure_UE_BWP(mac, scc, UE, false, -1, -1); + int ss_type; + if (UE->CellGroup && UE->CellGroup->spCellConfig) + ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + else + ss_type = NR_SearchSpace__searchSpaceType_PR_common; + configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1); reset_srs_stats(UE); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index aebc53f8f4..66baea3427 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -271,11 +271,6 @@ NR_ControlResourceSet_t *get_coreset(gNB_MAC_INST *nrmac, NR_SearchSpace_t *ss, NR_SearchSpace__searchSpaceType_PR ss_type); -/* find a search space within a BWP */ -NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc, - NR_BWP_DownlinkDedicated_t *bwp_Dedicated, - NR_SearchSpace__searchSpaceType_PR target_ss); - long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList, int time_domain_assignment, int mu, @@ -316,6 +311,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, NR_ServingCellConfigCommon_t *scc, NR_UE_info_t *UE, bool is_RA, + int target_ss, int dl_bwp_switch, int ul_bwp_switch); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index bc0a53a645..d3d63fb0df 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -870,7 +870,7 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) uid_t temp_uid = UE->uid; UE->uid = oldUE->uid; oldUE->uid = temp_uid; - configure_UE_BWP(mac, scc, UE, false, -1, -1); + configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); for (int i = 1; i < seq_arr_size(&oldUE->UE_sched_ctrl.lc_config); ++i) { const nr_lc_config_t *c = seq_arr_at(&oldUE->UE_sched_ctrl.lc_config, i); nr_mac_add_lcid(&UE->UE_sched_ctrl, c); From a4357b74c5a5e0da1b2603b47127832e649e1e2f Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 13 Mar 2025 19:12:36 +0100 Subject: [PATCH 10/25] use DCIX0 in commmon search space in any scenario before reconfiguration complete this allows to remove a lot of complicated procedures relying on flags and timers --- openair2/LAYER2/NR_MAC_gNB/config.c | 21 ------ openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 24 ++----- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 48 ++----------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 69 +++++++------------ openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 3 +- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 54 +++++++-------- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 3 - openair2/RRC/NR/nr_rrc_config.c | 2 +- openair2/RRC/NR/nr_rrc_defs.h | 2 +- openair2/RRC/NR/rrc_gNB.c | 15 +++- openair2/RRC/NR/rrc_gNB_mobility.c | 1 - 11 files changed, 81 insertions(+), 161 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 9b9b5b54ce..6f41db3764 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -1013,24 +1013,3 @@ void nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, NR_UE_info_t *UE) } LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup\n", ra->cfra ? "CFRA" : "CBRA", UE->rnti); } - -/* Prepare a new CellGroupConfig to be applied for this UE. We cannot - * immediatly apply it, as we have to wait for the reconfiguration through RRC. - * This function sets up everything to apply the reconfiguration. Later, we - * will trigger the UE inactivity with nr_mac_interrupt_ue_transmission(); upon - * expiry, nr_mac_apply_cellgroup() will apply the CellGroupConfig (radio - * config etc). */ -bool nr_mac_prepare_cellgroup_update(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, NR_CellGroupConfig_t *CellGroup) -{ - DevAssert(nrmac != NULL); - DevAssert(UE != NULL); - DevAssert(CellGroup != NULL); - - /* we assume that this function is mutex-protected from outside */ - NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); - - UE->reconfigCellGroup = CellGroup; - UE->expect_reconfiguration = true; - - return true; -} diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 595d849cc4..0c5a2c759c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -1738,12 +1738,6 @@ static void nr_generate_Msg2(module_id_t module_idP, *ul_bwp->tdaList_Common->list.array[ra->Msg3_tda_id]->k2 + get_NTN_Koffset(scc), ul_bwp->scs); - if (ra->cfra) { - int delay = nr_mac_get_reconfig_delay_slots(dl_bwp->scs); - interrupt_followup_action_t action = UE->reconfigCellGroup ? FOLLOW_INSYNC_RECONFIG : FOLLOW_INSYNC; - nr_mac_interrupt_ue_transmission(RC.nrmac[module_idP], UE, action, delay); - } - LOG_D(NR_MAC, "UE %04x: %d.%d: Setting RA-Msg3 reception (%s) for SFN.Slot %d.%d\n", UE->rnti, @@ -2091,25 +2085,17 @@ void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, N if (harq->round == 0) { if (success) { + gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon; + // we configure the UE using common search space with DCIX0 while waiting for a reconfiguration + configure_UE_BWP(nr_mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); + transition_ra_connected_nr_ue(nr_mac, UE); LOG_A(NR_MAC, "%4d.%2d UE %04x: Received Ack of %s. CBRA procedure succeeded!\n", frame, slot, UE->rnti, ra_type_str); } else { LOG_I(NR_MAC, "%4d.%2d UE %04x: RA Procedure failed at %s!\n", frame, slot, UE->rnti, ra_type_str); nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs); } - // Pause scheduling according to: - // 3GPP TS 38.331 Section 12 Table 12.1-1: UE performance requirements for RRC procedures for UEs - // Msg4 may transmit a RRCReconfiguration, for example when UE sends RRCReestablishmentComplete and MAC CE for C-RNTI in Msg3. - // In that case, gNB will generate a RRCReconfiguration that will be transmitted in Msg4, so we need to apply CellGroup after the Ack, - // UE->reconfigCellGroup already set when processing RRCReestablishment message - int delay = nr_mac_get_reconfig_delay_slots(UE->current_UL_BWP.scs); - gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; - nr_mac_interrupt_ue_transmission(nr_mac, UE, UE->interrupt_action, delay); - if (!transition_ra_connected_nr_ue(nr_mac, UE)) { - LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti); - delete_nr_ue_data(UE, NULL, &nr_mac->UE_info.uid_allocator); - return; - } if (sched_ctrl->retrans_dl_harq.head >= 0) { remove_nr_list(&sched_ctrl->retrans_dl_harq, current_harq_pid); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 727cf63cd6..17a6ae53bd 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2083,7 +2083,6 @@ NR_UE_info_t *find_ra_UE(NR_UEs_t *UEs, rnti_t rntiP) void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_allocator_t *uia) { ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); - ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->reconfigCellGroup); ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->capability); NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; seq_arr_free(&sched_ctrl->lc_config, NULL); @@ -2098,7 +2097,7 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca free_sched_pucch_list(sched_ctrl); uid_linear_allocator_free(uia, UE->uid); LOG_I(NR_MAC, "Remove NR rnti 0x%04x\n", UE->rnti); - free(UE->ra); + free_and_zero(UE->ra); free(UE); } @@ -2392,6 +2391,8 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, sc_info->nrofHARQ_ProcessesForPUSCH_r17 = pusch_servingcellconfig->ext3->nrofHARQ_ProcessesForPUSCH_r17; } } + create_dl_harq_list(sched_ctrl, sc_info); + create_ul_harq_list(sched_ctrl, sc_info); } if (CellGroup && CellGroup->physicalCellGroupConfig) @@ -3025,7 +3026,7 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, slot_t slot, nfapi_nr_dl_tt } } -static void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group) +void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group) { DevAssert(cell_group != NULL); /* remove a reconfigurationWithSync, we don't need it anymore */ @@ -3045,43 +3046,6 @@ static void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group) free_and_zero(cell_group->rlc_BearerToAddModList->list.array[i]->reestablishRLC); } -static void nr_mac_apply_cellgroup(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t frame, slot_t slot) -{ - LOG_D(NR_MAC, "%4d.%2d RNTI %04x: UE inactivity timer expired\n", frame, slot, UE->rnti); - - /* check if there is a new CellGroupConfig to be applied */ - if (UE->interrupt_action == FOLLOW_INSYNC_RECONFIG && UE->reconfigCellGroup != NULL) { - LOG_D(NR_MAC, "%4d.%2d RNTI %04x: Apply CellGroupConfig after UE inactivity\n", frame, slot, UE->rnti); - ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); - UE->CellGroup = UE->reconfigCellGroup; - UE->reconfigCellGroup = NULL; - UE->interrupt_action = FOLLOW_INSYNC; - - if (LOG_DEBUGFLAG(DEBUG_ASN1)) - xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *)UE->CellGroup); - - nr_mac_clean_cellgroup(UE->CellGroup); - } - - NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; - - NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - int ss_type; - if (UE->CellGroup && UE->CellGroup->spCellConfig) - ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific; - else - ss_type = NR_SearchSpace__searchSpaceType_PR_common; - configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1); - - reset_srs_stats(UE); - - if (IS_SA_MODE(get_softmodem_params())) { - // add all available DL,UL HARQ processes for this UE in SA - create_dl_harq_list(sched_ctrl, &UE->sc_info); - create_ul_harq_list(sched_ctrl, &UE->sc_info); - } -} - int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs) { /* we previously assumed a specific "slot ahead" value for the PHY processing @@ -3109,7 +3073,7 @@ int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, interr // frames, after the inactivity of the UE. UE->UE_sched_ctrl.ta_frame = (mac->frame - 1 + 1024) % 1024; - LOG_D(NR_MAC, "UE %04x: Interrupt UE transmission (%d slots) action %d reconfigCellGroup %p\n", UE->rnti, slots, UE->interrupt_action, UE->reconfigCellGroup); + LOG_D(NR_MAC, "UE %04x: Interrupt UE transmission (%d slots) action %d\n", UE->rnti, slots, UE->interrupt_action); return 0; } @@ -3182,8 +3146,6 @@ void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot) nr_timer_stop(&sched_ctrl->transm_interrupt); if (UE->interrupt_action == FOLLOW_OUTOFSYNC) nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs); - else - nr_mac_apply_cellgroup(mac, UE, frame, slot); } } } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 9fcf8a8e9c..49fe0fca5e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -622,36 +622,6 @@ static void handle_msg3_failed_rx(gNB_MAC_INST *mac, NR_RA_t *ra, rnti_t rnti, i ra->ra_state = nrRA_Msg3_retransmission; } -static NR_UE_info_t *configure_UE_crnti_msg3(gNB_MAC_INST *mac, NR_UE_info_t *old_UE, NR_UE_info_t *new_UE) -{ - // in case UE beam has changed - old_UE->UE_beam_index = new_UE->UE_beam_index; - // Reset UL failure for old UE - nr_mac_reset_ul_failure(&old_UE->UE_sched_ctrl); - // Reset HARQ processes - reset_dl_harq_list(&old_UE->UE_sched_ctrl); - reset_ul_harq_list(&old_UE->UE_sched_ctrl); - // old UE need to complete RA by sending DL - free_and_zero(old_UE->ra); - old_UE->ra = new_UE->ra; - new_UE->ra = NULL; - NR_UE_sched_ctrl_t *sched_ctrl = &old_UE->UE_sched_ctrl; - sched_ctrl->search_space = new_UE->UE_sched_ctrl.search_space; - sched_ctrl->coreset = new_UE->UE_sched_ctrl.coreset; - memcpy(&sched_ctrl->sched_pdcch, &new_UE->UE_sched_ctrl.sched_pdcch, sizeof(NR_sched_pdcch_t)); - old_UE->current_DL_BWP.dci_format = NR_DL_DCI_FORMAT_1_0; - // replace new UE with old UE in the access list - for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { - if (mac->UE_info.access_ue_list[i] && mac->UE_info.access_ue_list[i]->rnti == new_UE->rnti) { - mac->UE_info.access_ue_list[i] = old_UE; - break; - } - } - // remove new UE - delete_nr_ue_data(new_UE, mac->common_channels, &mac->UE_info.uid_allocator); - return old_UE; -} - static void nr_rx_ra_sdu(const module_id_t mod_id, const int CC_id, const frame_t frame, @@ -732,12 +702,21 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, UE_scheduling_control->ta_update = timing_advance; UE_scheduling_control->raw_rssi = rssi; LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update); + NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; if (ra->cfra) { LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", UE->rnti); nr_mac_reset_ul_failure(UE_scheduling_control); reset_dl_harq_list(UE_scheduling_control); reset_ul_harq_list(UE_scheduling_control); process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, UE->CellGroup->rlc_BearerToAddModList); + int ss_type; + // we configure the UE using common search space with DCIX0 while waiting for a reconfiguration in SA + // in NSA (or do-ra) there is no reconfiguration in NR + if (IS_SA_MODE(get_softmodem_params())) + ss_type = NR_SearchSpace__searchSpaceType_PR_common; + else + ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific; + configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1); if (!transition_ra_connected_nr_ue(mac, UE)) { LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti); delete_nr_ue_data(UE, NULL, &mac->UE_info.uid_allocator); @@ -766,19 +745,23 @@ static void nr_rx_ra_sdu(const module_id_t mod_id, nr_release_ra_UE(mac, rnti); return; } - // remove old UE from connected UEs - remove_UE_from_list(MAX_MOBILES_PER_GNB + 1, mac->UE_info.connected_ue_list, crnti); - UE = configure_UE_crnti_msg3(mac, old_UE, UE); - ra = UE->ra; - if (UE->reconfigCellGroup) { - // Nothing to do - // A RRCReconfiguration message should be already pending (for example, an ongoing RRCReestablishment), and it will be - // transmitted in Msg4 - } else { - // Trigger RRC Reconfiguration - LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", UE->rnti); - nr_mac_trigger_reconfiguration(mac, UE); - } + // in case UE beam has changed + old_UE->UE_beam_index = UE->UE_beam_index; + // Reset UL failure for old UE + nr_mac_reset_ul_failure(&old_UE->UE_sched_ctrl); + // Reset HARQ processes + reset_dl_harq_list(&old_UE->UE_sched_ctrl); + reset_ul_harq_list(&old_UE->UE_sched_ctrl); + // Trigger RRC Reconfiguration + LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", crnti); + nr_mac_trigger_reconfiguration(mac, old_UE); + nr_release_ra_UE(mac, rnti); + LOG_A(NR_MAC, "%4d.%2d UE %04x: RA with C-RNTI complete\n", frame, slot, crnti); + // we configure the UE using common search space with DCIX0 while waiting for a reconfiguration + configure_UE_BWP(mac, scc, old_UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); + // TODO do we actually need to still process the PDU? + nr_process_mac_pdu(mod_id, old_UE, CC_id, frame, slot, sdu, sdu_len, -1); + return; } else { // UE Contention Resolution Identity // Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to fill in Msg4 diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 66baea3427..563cfd19b2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -64,7 +64,6 @@ void nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, NR_UE_info_t *UE); bool add_new_UE_RA(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE); int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs); -bool nr_mac_prepare_cellgroup_update(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, NR_CellGroupConfig_t *CellGroup); int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, interrupt_followup_action_t action, int slots); int nr_transmission_action_indicator_stop(gNB_MAC_INST *mac, NR_UE_info_t *UE_info); @@ -463,4 +462,6 @@ void prepare_du_configuration_update(gNB_MAC_INST *mac, f1ap_served_cell_info_t *info, NR_BCCH_BCH_Message_t *mib, const NR_BCCH_DL_SCH_Message_t *sib1); + +void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group); #endif /*__LAYER2_NR_MAC_PROTO_H__*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index d3d63fb0df..8ba63890ca 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -571,10 +571,10 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container, req->rrc_container_length); } + NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; UE->capability = ue_cap; if (ue_cap != NULL) { // store the new UE capabilities, and update the cellGroupConfig - NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc); } @@ -583,6 +583,10 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) struct NR_CellGroupConfig__rlc_BearerToAddModList *addmod = new_CellGroup->rlc_BearerToAddModList; for (int i = 0; i < addmod->list.count; ++i) { asn1cCallocOne(addmod->list.array[i]->reestablishRLC, NR_RLC_BearerConfig__reestablishRLC_true); + for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) { + nr_lc_config_t *lc_config = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i); + nr_rlc_reestablish_entity(UE->rnti, lc_config->lcid); + } } } @@ -595,7 +599,9 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name); resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3; - nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup); + ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); + UE->CellGroup = new_CellGroup; + configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); NR_SCHED_UNLOCK(&mac->sched_lock); @@ -666,9 +672,15 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container, req->rrc_container_length); } + NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; if (req->ReconfigComplOutcome != RRCreconf_info_not_present && req->ReconfigComplOutcome != RRCreconf_success) { LOG_E(NR_MAC, "RRC reconfiguration outcome unsuccessful, but no rollback mechanism implemented to come back to old configuration\n"); + } else if (req->ReconfigComplOutcome == RRCreconf_success) { + LOG_I(NR_MAC, "DU received confirmation of successful RRC Reconfiguration\n"); + // we re-configure the BWP to apply the CellGroup and to use UE specific Search Space with DCIX1 + nr_mac_clean_cellgroup(UE->CellGroup); + configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_ue_Specific, -1, -1); } if (ue_cap != NULL) { @@ -676,7 +688,6 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->capability); UE->capability = ue_cap; LOG_I(NR_MAC, "UE %04x: received capabilities, updating CellGroupConfig\n", UE->rnti); - NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc); } @@ -694,7 +705,9 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name); resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3; - nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup); + ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); + UE->CellGroup = new_CellGroup; + configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); } else { ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, new_CellGroup); // we actually don't need it } @@ -832,24 +845,13 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) DevAssert(success); } - if (UE->expect_reconfiguration && dl_rrc->srb_id == 1) { - /* we expected a reconfiguration, and this is on DCCH. We assume this is - * the reconfiguration: nr_mac_prepare_cellgroup_update() already stored - * the CellGroupConfig. Below, we trigger a timer, and the CellGroupConfig - * will be applied after its expiry in nr_mac_apply_cellgroup().*/ - NR_SCHED_LOCK(&mac->sched_lock); - int delay = nr_mac_get_reconfig_delay_slots(UE->current_UL_BWP.scs); - nr_mac_interrupt_ue_transmission(mac, UE, FOLLOW_INSYNC_RECONFIG, delay); - NR_SCHED_UNLOCK(&mac->sched_lock); - UE->expect_reconfiguration = false; - /* Re-establish RLC for all remaining bearers */ - if (UE->reestablish_rlc) { - for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) { - nr_lc_config_t *lc_config = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i); - nr_rlc_reestablish_entity(dl_rrc->gNB_DU_ue_id, lc_config->lcid); - } - UE->reestablish_rlc = false; + if (UE->reestablish_rlc && dl_rrc->srb_id == 1) { + // we expected a reconfiguration to re-establish RLC, and this is on DCCH. We assume this is the reconfiguration. + for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) { + nr_lc_config_t *lc_config = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i); + nr_rlc_reestablish_entity(dl_rrc->gNB_DU_ue_id, lc_config->lcid); } + UE->reestablish_rlc = false; } if (dl_rrc->old_gNB_DU_ue_id != NULL) { @@ -866,27 +868,25 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) * from the current configuration. Also, expect the reconfiguration from * the CU, so save the old UE's CellGroup for the new UE */ UE->CellGroup->spCellConfig = NULL; - NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; uid_t temp_uid = UE->uid; UE->uid = oldUE->uid; oldUE->uid = temp_uid; - configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); for (int i = 1; i < seq_arr_size(&oldUE->UE_sched_ctrl.lc_config); ++i) { const nr_lc_config_t *c = seq_arr_at(&oldUE->UE_sched_ctrl.lc_config, i); nr_mac_add_lcid(&UE->UE_sched_ctrl, c); } - - nr_mac_prepare_cellgroup_update(mac, UE, oldUE->CellGroup); + ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); + UE->CellGroup = oldUE->CellGroup; oldUE->CellGroup = NULL; mac_remove_nr_ue(mac, *dl_rrc->old_gNB_DU_ue_id); pthread_mutex_unlock(&mac->sched_lock); nr_rlc_remove_ue(dl_rrc->gNB_DU_ue_id); nr_rlc_update_id(*dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id); + /* 38.331 clause 5.3.7.4: apply the specified configuration defined in 9.2.1 for SRB1 */ + nr_rlc_reconfigure_entity(dl_rrc->gNB_DU_ue_id, 1, NULL); /* Set flag to trigger RLC re-establishment * for remaining RBs in next RRCReconfiguration */ UE->reestablish_rlc = true; - /* 38.331 clause 5.3.7.4: apply the specified configuration defined in 9.2.1 for SRB1 */ - nr_rlc_reconfigure_entity(dl_rrc->gNB_DU_ue_id, 1, NULL); instance_t f1inst = get_f1_gtp_instance(); if (f1inst >= 0) // we actually use F1-U gtpv1u_update_ue_id(f1inst, *dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 6002c5756f..43dcbab20d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -743,11 +743,8 @@ typedef struct { NR_mac_stats_t mac_stats; /// currently active CellGroupConfig NR_CellGroupConfig_t *CellGroup; - /// CellGroupConfig that is to be activated after the next reconfiguration - bool expect_reconfiguration; /// reestablishRLC has to be signaled in RRCreconfiguration bool reestablish_rlc; - NR_CellGroupConfig_t *reconfigCellGroup; interrupt_followup_action_t interrupt_action; NR_UE_NR_Capability_t *capability; // UE selected beam index diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index df7cabf804..4c95b435c6 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -3135,7 +3135,7 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid, css_num_agg_level_candidates[PDCCH_AGG_LEVEL8] = NR_SearchSpace__nrofCandidates__aggregationLevel8_n0; css_num_agg_level_candidates[PDCCH_AGG_LEVEL16] = NR_SearchSpace__nrofCandidates__aggregationLevel16_n0; int searchspaceid = 4; - NR_SearchSpace_t *ss = rrc_searchspace_config(true, searchspaceid, coreset->controlResourceSetId, css_num_agg_level_candidates); + NR_SearchSpace_t *ss = rrc_searchspace_config(true, searchspaceid, 0, css_num_agg_level_candidates); searchspaceid = 5; int rrc_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS]; int num_cces = get_coreset_num_cces(coreset->frequencyDomainResources.buf, coreset->duration); diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 79d102f9e3..a3029cefd2 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -238,7 +238,7 @@ typedef struct gNB_RRC_UE_s { uint32_t ue_rrc_inactivity_timer; uint32_t ue_reestablishment_counter; uint32_t ue_reconfiguration_counter; - + bool ongoing_reconfiguration; bool an_release; // flag if core requested UE release /* NGUEContextSetup might come with PDU sessions, but setup needs to be diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index a110e4af53..c8cec12375 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -1145,6 +1145,7 @@ int nr_rrc_reconfiguration_req(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p, const int { uint8_t xid = rrc_gNB_get_next_transaction_identifier(rrc->module_id); ue_p->xids[xid] = RRC_DEDICATED_RECONF; + ue_p->ongoing_reconfiguration = true; NR_CellGroupConfig_t *masterCellGroup = ue_p->masterCellGroup; if (dl_bwp_id > 0) { @@ -1237,6 +1238,7 @@ static void rrc_handle_RRCSetupRequest(gNB_RRC_INST *rrc, UE->establishment_cause = rrcSetupRequest->establishmentCause; UE->nr_cellid = msg->nr_cellid; UE->masterCellGroup = cellGroupConfig; + UE->ongoing_reconfiguration = false; activate_srb(UE, 1); rrc_gNB_generate_RRCSetup(0, msg->crnti, ue_context_p, msg->du2cu_rrc_container, msg->du2cu_rrc_container_length); } @@ -1804,6 +1806,7 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U { uint8_t xid = reconfig_complete->rrc_TransactionIdentifier; UE->ue_reconfiguration_counter++; + UE->ongoing_reconfiguration = false; switch (UE->xids[xid]) { case RRC_PDUSESSION_RELEASE: { @@ -1854,6 +1857,15 @@ static void handle_rrcReconfigurationComplete(gNB_RRC_INST *rrc, gNB_RRC_UE_t *U UE->ho_context->target->ho_success(rrc, UE); nr_rrc_finalize_ho(UE); } + + f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); + RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); + f1ap_ue_context_modif_req_t ue_context_modif_req = { + .gNB_CU_ue_id = UE->rrc_ue_id, + .gNB_DU_ue_id = ue_data.secondary_ue, + .ReconfigComplOutcome = RRCreconf_success, + }; + rrc->mac_rrc.ue_context_modification_request(ue_data.du_assoc_id, &ue_context_modif_req); } static void rrc_gNB_generate_UECapabilityEnquiry(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue) @@ -2417,7 +2429,8 @@ static void rrc_CU_process_ue_modification_required(MessageDef *msg_p, instance_ xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); /* trigger reconfiguration */ - nr_rrc_reconfiguration_req(rrc, UE, 0, 0); + if (!UE->ongoing_reconfiguration) + nr_rrc_reconfiguration_req(rrc, UE, 0, 0); return; } LOG_W(RRC, diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 477be84800..e6e50ffbf1 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -231,7 +231,6 @@ static void rrc_gNB_trigger_reconfiguration_for_handover(gNB_RRC_INST *rrc, gNB_ .plmn = rrc->configuration.plmn[0], .nr_cellid = rrc->nr_cellid, // TODO target cell ID .servCellId = 0, // TODO: correct value? - .ReconfigComplOutcome = RRCreconf_success, .transm_action_ind = &transmission_action_indicator, }; deliver_ue_ctxt_modification_data_t data = {.rrc = rrc, From 3ec14152a156a533a677b7c0e051f7d3dde28c92 Mon Sep 17 00:00:00 2001 From: francescomani Date: Tue, 1 Apr 2025 09:53:24 +0200 Subject: [PATCH 11/25] fix for ULSCH number of layers in case of DCI00 --- .../LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c | 14 ++++++++++---- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 4 ++-- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 1 + 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 17a6ae53bd..7b9ad1ed3b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -125,16 +125,22 @@ static const uint16_t cqi_table3[16][2] = {{0, 0}, static void determine_aggregation_level_search_order(int agg_level_search_order[NUM_PDCCH_AGG_LEVELS], float pdcch_cl_adjust); -uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, - const nr_dci_format_t dci_format) { - +uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format) +{ // TODO check this but it should be enough for now // if there is not csi report activated RI is 0 from initialization if(dci_format == NR_DL_DCI_FORMAT_1_0) return 1; else - return (sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.ri + 1); + return sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.ri + 1; +} +int get_ul_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format) +{ + if(dci_format == NR_UL_DCI_FORMAT_0_0) + return 1; + else + return sched_ctrl->srs_feedback.ul_ri + 1; } // Table 5.2.2.2.1-3 and Table 5.2.2.2.1-4 in 38.214 diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index 49fe0fca5e..258f3c8c76 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -1947,7 +1947,7 @@ static void pf_ul(module_id_t module_id, continue; } - sched_pusch->nrOfLayers = sched_ctrl->srs_feedback.ul_ri + 1; + sched_pusch->nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format); sched_pusch->time_domain_allocation = get_ul_tda(nrmac, sched_frame, sched_slot); sched_pusch->tda_info = get_ul_tda_info(current_BWP, sched_ctrl->coreset->controlResourceSetId, @@ -2097,7 +2097,7 @@ static void pf_ul(module_id_t module_id, - sched_pusch->nrOfLayers = sched_ctrl->srs_feedback.ul_ri + 1; + sched_pusch->nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format); sched_pusch->time_domain_allocation = get_ul_tda(nrmac, sched_frame, sched_slot); sched_pusch->tda_info = get_ul_tda_info(current_BWP, sched_ctrl->coreset->controlResourceSetId, diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 563cfd19b2..3ac09ce98a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -380,6 +380,7 @@ uint16_t get_pm_index(const gNB_MAC_INST *nrmac, uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx); uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format); +int get_ul_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format); void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl); bool add_UE_to_list(int list_size, NR_UE_info_t *list[list_size], NR_UE_info_t *UE); From 953a5ed33ee6863177092370ac311600883a37af Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 17 Apr 2025 11:59:55 +0200 Subject: [PATCH 12/25] Trigger release request on RA timeout only once Checking for < 0 makes the contention resolution timer trigger on each iteration once it is < 0. Instead, use == 0, which will trigger only once. --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 0c5a2c759c..edddd535b0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -2262,7 +2262,7 @@ void nr_schedule_RA(module_id_t module_idP, // Check RA Contention Resolution timer (TODO check this procedure) if (ra->ra_type == RA_4_STEP && ra->ra_state > nrRA_WAIT_Msg3) { ra->contention_resolution_timer--; - if (ra->contention_resolution_timer < 0) { + if (ra->contention_resolution_timer == 0) { LOG_W(NR_MAC, "(%d.%d) RA Contention Resolution timer expired for UE 0x%04x, RA procedure failed...\n", frameP, slotP, UE->rnti); bool requested = nr_mac_request_release_ue(mac, UE->rnti); if (!requested) From 6c5514d5c922e76f4cfa30b2b2fa43d22cbedcad Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 3 Apr 2025 15:06:27 +0200 Subject: [PATCH 13/25] Refactor out useless function --- CMakeLists.txt | 1 - doc/Doxyfile | 2 - openair2/RRC/NR/rrc_gNB_GTPV1U.c | 65 -------------------------------- openair2/RRC/NR/rrc_gNB_GTPV1U.h | 41 -------------------- openair2/RRC/NR/rrc_gNB_nsa.c | 11 ++---- 5 files changed, 4 insertions(+), 116 deletions(-) delete mode 100644 openair2/RRC/NR/rrc_gNB_GTPV1U.c delete mode 100644 openair2/RRC/NR/rrc_gNB_GTPV1U.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f7e7828285..0f77734be1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1366,7 +1366,6 @@ include_directories("${OPENAIR1_DIR}/SCHED_NR_UE") ########################## add_library (GTPV1U - ${NR_RRC_DIR}/rrc_gNB_GTPV1U.c ${RRC_DIR}/rrc_eNB_GTPV1U.c ${OPENAIR3_DIR}/ocp-gtpu/gtp_itf.cpp ) diff --git a/doc/Doxyfile b/doc/Doxyfile index 6399f7107c..991a0bf734 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1849,7 +1849,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/cucp_cuup_if.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/cucp_cuup_direct.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/nr_rrc_config.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_GTPV1U.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/mac_rrc_dl_direct.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_radio_bearers.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_NGAP.h \ @@ -1865,7 +1864,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_reconfig.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_NGAP.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/mac_rrc_dl_f1ap.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_GTPV1U.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/mac_rrc_dl.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_nsa.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/LTE/rrc_eNB_GTPV1U.c \ diff --git a/openair2/RRC/NR/rrc_gNB_GTPV1U.c b/openair2/RRC/NR/rrc_gNB_GTPV1U.c deleted file mode 100644 index 79882d58f3..0000000000 --- a/openair2/RRC/NR/rrc_gNB_GTPV1U.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file rrc_gNB_GTPV1U.c - * \brief rrc GTPV1U procedures for gNB - * \author Lionel GAUTHIER, Panos MATZAKOS - * \version 1.0 - * \company Eurecom - * \email: lionel.gauthier@eurecom.fr, panagiotis.matzakos@eurecom.fr - */ - -#include "openair2/RRC/NR/rrc_gNB_GTPV1U.h" -#include "LOG/log.h" -#include "RRC/NR/nr_rrc_defs.h" -#include "common/ran_context.h" -#include "openair2/RRC/NR/rrc_gNB_UE_context.h" -#include "rrc_defs.h" -#include "rrc_eNB_GTPV1U.h" -#include "s1ap_messages_types.h" - -int rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(gNB_RRC_UE_t *ue, - const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list) -{ - if (!create_tunnel_resp_pP) { - LOG_E(NR_RRC, "create_tunnel_resp_pP error\n"); - return -1; - } - - for (int i = 0; i < create_tunnel_resp_pP->num_tunnels; i++) { - ue->nsa_gtp_teid[inde_list[i]] = create_tunnel_resp_pP->enb_S1u_teid[i]; - ue->nsa_gtp_addrs[inde_list[i]] = create_tunnel_resp_pP->enb_addr; - ue->nsa_gtp_ebi[inde_list[i]] = create_tunnel_resp_pP->eps_bearer_id[i]; - LOG_I(RRC, - "UE %d: rrc_eNB_process_GTPV1U_CREATE_TUNNEL_RESP tunnel (%u, %u) bearer UE context index %u, msg index %u, id %u, gtp " - "addr len %d \n", - ue->rrc_ue_id, - create_tunnel_resp_pP->enb_S1u_teid[i], - ue->nsa_gtp_teid[inde_list[i]], - inde_list[i], - i, - create_tunnel_resp_pP->eps_bearer_id[i], - create_tunnel_resp_pP->enb_addr.length); - } - - return 0; -} diff --git a/openair2/RRC/NR/rrc_gNB_GTPV1U.h b/openair2/RRC/NR/rrc_gNB_GTPV1U.h deleted file mode 100644 index 60a6c0c5b5..0000000000 --- a/openair2/RRC/NR/rrc_gNB_GTPV1U.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file rrc_gNB_GTPV1U.h - * \brief rrc GTPV1U procedures for gNB - * \author Lionel GAUTHIER, Panos MATZAKOS - * \version 1.0 - * \company Eurecom - * \email: lionel.gauthier@eurecom.fr, panagiotis.matzakos@eurecom.fr - */ - -#ifndef RRC_GNB_GTPV1U_H_ -#define RRC_GNB_GTPV1U_H_ - -#include -#include "openair2/RRC/NR/nr_rrc_defs.h" -#include "gtpv1_u_messages_types.h" - -int rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(gNB_RRC_UE_t *ue, - const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP, - uint8_t *inde_list); - -#endif diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 714ac5b067..eaab13796f 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -60,7 +60,6 @@ #include "openair2/F1AP/f1ap_ids.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h" -#include "openair2/RRC/NR/rrc_gNB_GTPV1U.h" #include "openair3/SECU/key_nas_deriver.h" #include "rlc.h" #include "s1ap_messages_types.h" @@ -272,9 +271,6 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a NR_CG_Config_t *CG_Config = generate_CG_Config(reconfig, UE->rb_config); if(m!=NULL) { - uint8_t inde_list[m->nb_e_rabs_tobeadded]; - memset(inde_list, 0, m->nb_e_rabs_tobeadded*sizeof(uint8_t)); - if (m->nb_e_rabs_tobeadded>0) { for (int i=0; inb_e_rabs_tobeadded; i++) { // Add the new E-RABs at the corresponding rrc ue context of the gNB @@ -286,7 +282,6 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a create_tunnel_req.eps_bearer_id[i] = UE->e_rab[i].param.e_rab_id; create_tunnel_req.sgw_S1u_teid[i] = UE->e_rab[i].param.gtp_teid; memcpy(&create_tunnel_req.sgw_addr[i], &UE->e_rab[i].param.sgw_addr, sizeof(transport_layer_addr_t)); - inde_list[i] = i; LOG_I(RRC,"S1-U tunnel: index %d target sgw ip %d.%d.%d.%d length %d gtp teid %u\n", i, create_tunnel_req.sgw_addr[i].buffer[0], @@ -302,9 +297,11 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a RB_INSERT(rrc_nr_ue_tree_s, &RC.nrrrc[rrc->module_id]->rrc_ue_head, ue_context_p); memset(&create_tunnel_resp, 0, sizeof(create_tunnel_resp)); if (!IS_SOFTMODEM_NOS1) { - LOG_D(RRC, "Calling gtpv1u_create_s1u_tunnel()\n"); gtpv1u_create_s1u_tunnel(rrc->module_id, &create_tunnel_req, &create_tunnel_resp, nr_pdcp_data_req_drb); - rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(&ue_context_p->ue_context, &create_tunnel_resp, &inde_list[0]); + DevAssert(create_tunnel_resp.num_tunnels == 1); + UE->nsa_gtp_teid[0] = create_tunnel_resp.enb_S1u_teid[0]; + UE->nsa_gtp_addrs[0] = create_tunnel_resp.enb_addr; + UE->nsa_gtp_ebi[0] = create_tunnel_resp.eps_bearer_id[0]; } X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).nb_e_rabs_admitted_tobeadded = m->nb_e_rabs_tobeadded; X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).target_assoc_id = m->target_assoc_id; From 7b9442f58da9455ece3380fa1aecee19b0922c3e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 3 Apr 2025 12:47:32 +0200 Subject: [PATCH 14/25] DU-level changes to handle F1 UE Context Setup in NSA/phy-test/do-ra Co-authored-by: Francesco Mani --- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 135 +++++++++++++++--- openair2/LAYER2/NR_MAC_gNB/main.c | 1 - openair2/RRC/NR/nr_rrc_config.c | 6 +- 3 files changed, 113 insertions(+), 29 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 8ba63890ca..9d3850586b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -27,6 +27,7 @@ #include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h" #include "F1AP_CauseRadioNetwork.h" #include "NR_HandoverPreparationInformation.h" +#include "NR_CG-ConfigInfo.h" #include "openair3/ocp-gtpu/gtp_itf.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" #include "lib/f1ap_interface_management.h" @@ -342,6 +343,8 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, resp_drb->up_dl_tnl[0].teid = resp_f1.gnb_NGu_teid[0]; } + if (!cellGroupConfig->rlc_BearerToAddModList) + cellGroupConfig->rlc_BearerToAddModList = calloc_or_fail(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList)); int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig); DevAssert(ret == 0); } @@ -461,6 +464,52 @@ static NR_UE_NR_Capability_t *get_ue_nr_cap_from_ho_prep_info(uint8_t *buf, uint return cap; } +static NR_CG_ConfigInfo_t *get_cg_config_info(uint8_t *buf, uint32_t len) +{ + struct NR_CG_ConfigInfo *cg_configinfo = NULL; + asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_CG_ConfigInfo, (void **)&cg_configinfo, buf, len); + if (dec_rval.code != RC_OK) { + LOG_W(NR_MAC, "cannot decode CG-ConfigInfo, ignoring it\n"); + return NULL; + } + //xer_fprint(stdout, &asn_DEF_NR_CG_ConfigInfo, cg_configinfo); + return cg_configinfo; +} + +static NR_UE_NR_Capability_t *get_ue_nr_cap_from_cg_config_info(const NR_CG_ConfigInfo_t *cgci) +{ + /* INTO DU handler */ + if (cgci->criticalExtensions.present != NR_CG_ConfigInfo__criticalExtensions_PR_c1) + return NULL; + if (!cgci->criticalExtensions.choice.c1 + || cgci->criticalExtensions.choice.c1->present != NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo) + return NULL; + + const NR_CG_ConfigInfo_IEs_t *cgci_ie = cgci->criticalExtensions.choice.c1->choice.cg_ConfigInfo; + if (!cgci_ie->ue_CapabilityInfo) + return NULL; + + // Decode UE-CapabilityRAT-ContainerList + const OCTET_STRING_t *cap_buf = cgci_ie->ue_CapabilityInfo; + NR_UE_CapabilityRAT_ContainerList_t *clist = NULL; + asn_dec_rval_t dec_rval = uper_decode_complete(NULL, + &asn_DEF_NR_UE_CapabilityRAT_ContainerList, + (void **)&clist, + cap_buf->buf, + cap_buf->size); + + if (dec_rval.code != RC_OK) { + LOG_W(NR_MAC, + "Failed to decode NR_UE_CapabilityRAT_ContainerList (%zu bits), size of OCTET_STRING %lu\n", + dec_rval.consumed, + cap_buf->size); + return NULL; + } + NR_UE_NR_Capability_t *cap = get_nr_cap(clist); + ASN_STRUCT_FREE(asn_DEF_NR_UE_CapabilityRAT_ContainerList, clist); + return cap; +} + NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig) { uint8_t buf[16636]; @@ -473,45 +522,75 @@ NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig) return cloned; } -static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id) +static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_CG_ConfigInfo_t *cgci) { + const bool is_SA = IS_SA_MODE(get_softmodem_params()); int CC_id = 0; rnti_t rnti; - bool found = nr_mac_get_new_rnti(&mac->UE_info, &rnti); - if (!found) - return NULL; - - NR_UE_info_t *UE = get_new_nr_ue_inst(&mac->UE_info.uid_allocator, rnti, NULL); - AssertFatal(UE != NULL, "cannot create UE context, UE context setup failure not implemented\n"); - if (!add_new_UE_RA(mac, UE)) { - delete_nr_ue_data(UE, /*not used*/ NULL, &mac->UE_info.uid_allocator); - LOG_E(NR_MAC, "UE list full while creating new UE\n"); - return NULL; + if (get_softmodem_params()->phy_test) { + AssertFatal(mac->UE_info.connected_ue_list[0] == NULL, "phytest: UE already present\n"); + rnti = 0x1234; + } else { + bool found = nr_mac_get_new_rnti(&mac->UE_info, &rnti); + if (!found) + return NULL; } f1_ue_data_t new_ue_data = {.secondary_ue = cu_id}; bool success = du_add_f1_ue_data(rnti, &new_ue_data); DevAssert(success); - const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon; - const NR_ServingCellConfig_t *sccd = mac->common_channels[CC_id].pre_ServingCellConfig; - NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config); - cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc); + NR_UE_info_t *UE = get_new_nr_ue_inst(&mac->UE_info.uid_allocator, rnti, NULL); + AssertFatal(UE != NULL, "cannot create UE context, UE context setup failure not implemented\n"); + + NR_CellGroupConfig_t *cellGroupConfig = NULL; + NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; + const NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + const NR_ServingCellConfig_t *sccd = cc->pre_ServingCellConfig; + const nr_mac_config_t *configuration = &mac->radio_config; + if (is_SA) { + cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config); + cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc); + } else { + NR_UE_NR_Capability_t *cap = get_ue_nr_cap_from_cg_config_info(cgci); + cellGroupConfig = get_default_secondaryCellGroup(scc, sccd, cap, 1, 1, configuration, UE->uid); + // TODO: fixme: gives a new random RNTI + UE->rnti = cellGroupConfig->spCellConfig->reconfigurationWithSync->newUE_Identity; + // TODO: in NSA we assign capabilities here, otherwise outside => not logic + UE->capability = cap; + } // note: we don't pass the cellGroupConfig to add_new_nr_ue() because we need // the uid to create the CellGroupConfig (which is in the UE context created // by add_new_nr_ue(); it's a kind of chicken-and-egg problem), so below we // complete the UE context with the information that add_new_nr_ue() would // have added + AssertFatal(cellGroupConfig != NULL, "out of memory\n"); UE->CellGroup = cellGroupConfig; - nr_rlc_activate_srb0(UE->rnti, UE, NULL); - nr_mac_prepare_ra_ue(mac, UE); - /* SRB1 is added to RLC and MAC in the handler later */ + if (get_softmodem_params()->phy_test) { + // phytest mode: we don't set up RA, etc + free_and_zero(UE->ra); // test-mode: UE will not do RA + bool res = add_connected_nr_ue(mac, UE); + DevAssert(res); + } else { + if (!add_new_UE_RA(mac, UE)) { + delete_nr_ue_data(UE, /*not used*/ NULL, &mac->UE_info.uid_allocator); + LOG_E(NR_MAC, "UE list full while creating new UE\n"); + return NULL; + } + nr_mac_prepare_ra_ue(mac, UE); + + if (is_SA) { + /* SRB1 is added to RLC and MAC in the handler later */ + nr_rlc_activate_srb0(UE->rnti, UE, NULL); + } + } return UE; } void ue_context_setup_request(const f1ap_ue_context_setup_t *req) { + const bool is_SA = IS_SA_MODE(get_softmodem_params()); gNB_MAC_INST *mac = RC.nrmac[0]; /* response has same type as request... */ f1ap_ue_context_setup_t resp = { @@ -525,9 +604,11 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) bool ue_id_provided = resp.gNB_DU_ue_id > 0 && resp.gNB_DU_ue_id < 0xffff; NR_UE_NR_Capability_t *ue_cap = NULL; + NR_CG_ConfigInfo_t *cg_configinfo = NULL; if (req->cu_to_du_rrc_information != NULL) { const cu_to_du_rrc_information_t *cu2du = req->cu_to_du_rrc_information; - AssertFatal(cu2du->cG_ConfigInfo == NULL, "CG-ConfigInfo not handled\n"); + if (cu2du->cG_ConfigInfo != NULL) + cg_configinfo = get_cg_config_info(cu2du->cG_ConfigInfo, cu2du->cG_ConfigInfo_length); if (cu2du->handoverPreparationInfo != NULL) { ue_cap = get_ue_nr_cap_from_ho_prep_info(cu2du->handoverPreparationInfo, cu2du->handoverPreparationInfo_length); } else if (cu2du->uE_CapabilityRAT_ContainerList != NULL) { @@ -535,15 +616,21 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) } AssertFatal(cu2du->measConfig == NULL, "MeasConfig not handled\n"); } + /* 38.473: "For DC operation, the CG-ConfigInfo IE shall be included in the CU + * to DU RRC Information IE at the gNB acting as secondary node" As of now, + * we only handle NSA => we check we have CG-ConfigInfo if not SA or have SA + * and no CG-ConfigInfo */ + AssertFatal(is_SA ^ (cg_configinfo != NULL), "cannot have SA and CG-ConfigInfo: NR-DC not supported xor need CG-ConfigInfo for NSA/phy-test/do-ra\n"); NR_SCHED_LOCK(&mac->sched_lock); NR_UE_info_t *UE = NULL; if (!ue_id_provided) { - UE = create_new_UE(mac, req->gNB_CU_ue_id); + UE = create_new_UE(mac, req->gNB_CU_ue_id, cg_configinfo); resp.gNB_DU_ue_id = UE->rnti; resp.crnti = &UE->rnti; } else { + DevAssert(is_SA); UE = find_nr_UE(&mac->UE_info, req->gNB_DU_ue_id); } AssertFatal(UE, "no UE found or could not be created, but UE Context Setup Failed not implemented\n"); @@ -573,12 +660,13 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; UE->capability = ue_cap; - if (ue_cap != NULL) { + if (ue_cap != NULL && cg_configinfo == NULL) { // store the new UE capabilities, and update the cellGroupConfig + // only to be done if we did not already update through the cg_configinfo update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc); } - if (!ue_id_provided) { + if (!ue_id_provided && cg_configinfo == NULL) { /* new UE: tell the UE to reestablish RLC */ struct NR_CellGroupConfig__rlc_BearerToAddModList *addmod = new_CellGroup->rlc_BearerToAddModList; for (int i = 0; i < addmod->list.count; ++i) { @@ -601,7 +689,8 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup); UE->CellGroup = new_CellGroup; - configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1); + int ss_type = cg_configinfo ? NR_SearchSpace__searchSpaceType_PR_ue_Specific: NR_SearchSpace__searchSpaceType_PR_common; + configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1); NR_SCHED_UNLOCK(&mac->sched_lock); diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 20602b8641..1ca1da1dc2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -329,7 +329,6 @@ void mac_top_init_gNB(ngran_node_t node_type, // setup PDCP, RLC nr_pdcp_entity_security_keys_and_algos_t null_security_parameters = {0}; nr_pdcp_add_drbs(ENB_FLAG_NO, 0x1234, rbconfig->drb_ToAddModList, &null_security_parameters); - nr_rlc_add_drb(0x1234, rbconfig->drb_ToAddModList->list.array[0]->drb_Identity, rlc_rbconfig); // free memory free_nr_noS1_bearer_config(&rbconfig, &rlc_rbconfig); diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 4c95b435c6..1938f4b9bc 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -3559,12 +3559,8 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC NR_CellGroupConfig_t *secondaryCellGroup = calloc(1, sizeof(*secondaryCellGroup)); secondaryCellGroup->cellGroupId = scg_id; - /* LCID is 4 because the RLC layer requires it to be 3+rb_id; the rb_id is 1 - * for first RB. We pre-configure RLC UM Bi-directional, priority is 1 */ - NR_RLC_BearerConfig_t *RLC_BearerConfig = get_DRB_RLC_BearerConfig(4, 1, NR_RLC_Config_PR_um_Bi_Directional, 1); - secondaryCellGroup->rlc_BearerToAddModList = calloc(1, sizeof(*secondaryCellGroup->rlc_BearerToAddModList)); - asn1cSeqAdd(&secondaryCellGroup->rlc_BearerToAddModList->list, RLC_BearerConfig); + /* rlc_BearerToAddModList is handled outside */ secondaryCellGroup->mac_CellGroupConfig = configure_mac_cellgroup(&configuration->timer_config); secondaryCellGroup->physicalCellGroupConfig = configure_phy_cellgroup(); From 031be0666508784b492ddb5e48f9b676d41ee322 Mon Sep 17 00:00:00 2001 From: francescomani Date: Thu, 17 Apr 2025 18:50:03 +0200 Subject: [PATCH 15/25] use already generated RNTI when creating a new NSA US and take get_reconfiguration_with_sync out of get_default_secondaryCellGroup --- openair1/SIMULATION/NR_PHY/dlsim.c | 8 +++++--- openair1/SIMULATION/NR_PHY/ulsim.c | 11 ++++++----- openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 3 +-- openair2/RRC/NR/nr_rrc_config.c | 5 ----- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index f675256b0b..8babb7598d 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -780,8 +780,10 @@ printf("%d\n", slot); NR_UE_NR_Capability_t *UE_Capability_nr = CALLOC(1,sizeof(NR_UE_NR_Capability_t)); prepare_sim_uecap(UE_Capability_nr, scc, mu, N_RB_DL, g_mcsTableIdx, 0); - - NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, scd, UE_Capability_nr, 0, 1, &conf, 0); + rnti_t rnti = 0x1234; + int uid = 0; + NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, scd, UE_Capability_nr, 0, 1, &conf, uid); + secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc); /* -U option modify DMRS */ if(modify_dmrs) { @@ -796,7 +798,7 @@ printf("%d\n", slot); //xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup); // UE dedicated configuration - nr_mac_add_test_ue(RC.nrmac[0], secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity, secondaryCellGroup); + nr_mac_add_test_ue(RC.nrmac[0], rnti, secondaryCellGroup); // reset preprocessor to the one of DLSIM after it has been set during // nr_mac_config_scc() gNB_mac->pre_processor_dl = nr_dlsim_preprocessor; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index a23320ee10..83c1c31826 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -672,15 +672,16 @@ int main(int argc, char *argv[]) fix_scd(scd); NR_UE_NR_Capability_t* UE_Capability_nr = CALLOC(1,sizeof(NR_UE_NR_Capability_t)); - prepare_sim_uecap(UE_Capability_nr,scc,mu, - N_RB_UL,0,mcs_table); - - NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, scd, UE_Capability_nr, 0, 1, &conf, 0); + prepare_sim_uecap(UE_Capability_nr, scc, mu, N_RB_UL, 0, mcs_table); + rnti_t rnti = 0x1234; + int uid = 0; + NR_CellGroupConfig_t *secondaryCellGroup = get_default_secondaryCellGroup(scc, scd, UE_Capability_nr, 0, 1, &conf, uid); + secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, scc); NR_BCCH_BCH_Message_t *mib = get_new_MIB_NR(scc); // UE dedicated configuration - nr_mac_add_test_ue(RC.nrmac[0], secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity, secondaryCellGroup); + nr_mac_add_test_ue(RC.nrmac[0], rnti, secondaryCellGroup); frame_parms->nb_antennas_tx = 1; frame_parms->nb_antennas_rx = n_rx; nfapi_nr_config_request_scf_t *cfg = &gNB->gNB_config; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 9d3850586b..317b030e4a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -554,8 +554,7 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C } else { NR_UE_NR_Capability_t *cap = get_ue_nr_cap_from_cg_config_info(cgci); cellGroupConfig = get_default_secondaryCellGroup(scc, sccd, cap, 1, 1, configuration, UE->uid); - // TODO: fixme: gives a new random RNTI - UE->rnti = cellGroupConfig->spCellConfig->reconfigurationWithSync->newUE_Identity; + cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc); // TODO: in NSA we assign capabilities here, otherwise outside => not logic UE->capability = cap; } diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 1938f4b9bc..ac4f25109e 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -3567,11 +3567,6 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC secondaryCellGroup->spCellConfig = calloc(1, sizeof(*secondaryCellGroup->spCellConfig)); secondaryCellGroup->spCellConfig->servCellIndex = calloc(1, sizeof(*secondaryCellGroup->spCellConfig->servCellIndex)); *secondaryCellGroup->spCellConfig->servCellIndex = servCellIndex; - secondaryCellGroup->spCellConfig->reconfigurationWithSync = - calloc(1, sizeof(*secondaryCellGroup->spCellConfig->reconfigurationWithSync)); - - rnti_t rnti = get_softmodem_params()->phy_test == 1 ? 0x1234 : (taus() & 0xffff); - secondaryCellGroup->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(rnti, uid, servingcellconfigcommon); secondaryCellGroup->spCellConfig->rlf_TimersAndConstants = calloc(1, sizeof(*secondaryCellGroup->spCellConfig->rlf_TimersAndConstants)); From 67f04d828a13114c4d0613b4a914be0e1b560be4 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 3 Apr 2025 13:13:57 +0200 Subject: [PATCH 16/25] Implement UE context addition in CU through F1 in do-ra/phy-test Add functionality to trigger the addition of a new RRC UE context (in the CU) for NSA modes, using F1. This commit makes do-ra and phy-test modes work. "True" NSA will work in the next commit, which also sends the X2 addition request answer message. --- openair2/LAYER2/NR_MAC_gNB/main.c | 22 --- openair2/RRC/NR/MESSAGES/asn1_msg.c | 26 --- openair2/RRC/NR/MESSAGES/asn1_msg.h | 5 - openair2/RRC/NR/nr_rrc_proto.h | 5 +- openair2/RRC/NR/rrc_gNB.c | 39 +--- openair2/RRC/NR/rrc_gNB_du.c | 4 + openair2/RRC/NR/rrc_gNB_internode.c | 38 ---- openair2/RRC/NR/rrc_gNB_nsa.c | 288 ++++++++++++---------------- 8 files changed, 132 insertions(+), 295 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 1ca1da1dc2..3137ce0902 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -312,28 +312,6 @@ void mac_top_init_gNB(ngran_node_t node_type, // These should be out of here later if (get_softmodem_params()->usim_test == 0 ) nr_pdcp_layer_init(); - - if(IS_SOFTMODEM_NOS1 && get_softmodem_params()->phy_test) { - // get default noS1 configuration - NR_RadioBearerConfig_t *rbconfig = NULL; - NR_RLC_BearerConfig_t *rlc_rbconfig = NULL; - fill_nr_noS1_bearer_config(&rbconfig, &rlc_rbconfig); - - /* Note! previously, in nr_DRB_preconfiguration(), we passed ENB_FLAG_NO - * if ENB_NAS_USE_TUN was *not* set. It seems to me that we could not set - * this flag anywhere in the code, hence we would always configure PDCP - * with ENB_FLAG_NO in nr_DRB_preconfiguration(). This makes sense for - * noS1, because the result of passing ENB_FLAG_NO to PDCP is that PDCP - * will output the packets at a local interface, which is in line with - * the noS1 mode. Hence, below, we simply hardcode ENB_FLAG_NO */ - // setup PDCP, RLC - nr_pdcp_entity_security_keys_and_algos_t null_security_parameters = {0}; - nr_pdcp_add_drbs(ENB_FLAG_NO, 0x1234, rbconfig->drb_ToAddModList, &null_security_parameters); - - // free memory - free_nr_noS1_bearer_config(&rbconfig, &rlc_rbconfig); - } - } else { RC.nrmac = NULL; } diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 131b2694b6..586e2e7628 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -425,32 +425,6 @@ NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id, return rbconfig; } -void fill_nr_noS1_bearer_config(NR_RadioBearerConfig_t **rbconfig, - NR_RLC_BearerConfig_t **rlc_rbconfig) -{ - /* the EPS bearer ID is arbitrary; the rb_id is 1/the first DRB, it needs to - * match the one in get_DRB_RLC_BearerConfig(). No ciphering is to be - * configured */ - *rbconfig = get_default_rbconfig(10, 1, NR_CipheringAlgorithm_nea0, NR_SecurityConfig__keyToUse_master); - AssertFatal(*rbconfig != NULL, "get_default_rbconfig() failed\n"); - /* LCID is 4 because the RLC layer requires it to be 3+rb_id; the rb_id 1 is - * common with get_default_rbconfig() (first RB). We pre-configure RLC UM - * Bi-directional, priority is 1 */ - *rlc_rbconfig = get_DRB_RLC_BearerConfig(4, 1, NR_RLC_Config_PR_um_Bi_Directional, 1); - AssertFatal(*rlc_rbconfig != NULL, "get_DRB_RLC_BearerConfig() failed\n"); -} - -void free_nr_noS1_bearer_config(NR_RadioBearerConfig_t **rbconfig, - NR_RLC_BearerConfig_t **rlc_rbconfig) -{ - ASN_STRUCT_FREE(asn_DEF_NR_RadioBearerConfig, *rbconfig); - *rbconfig = NULL; - if (rlc_rbconfig != NULL) { - ASN_STRUCT_FREE(asn_DEF_NR_RLC_BearerConfig, *rlc_rbconfig); - *rlc_rbconfig = NULL; - } -} - //------------------------------------------------------------------------------ int do_RRCSetup(uint8_t *const buffer, size_t buffer_size, diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h index 3d09a65bd0..344659afbb 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.h +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h @@ -80,11 +80,6 @@ NR_RadioBearerConfig_t *get_default_rbconfig(int eps_bearer_id, e_NR_CipheringAlgorithm ciphering_algorithm, e_NR_SecurityConfig__keyToUse key_to_use); -void fill_nr_noS1_bearer_config(NR_RadioBearerConfig_t **rbconfig, - NR_RLC_BearerConfig_t **rlc_rbconfig); -void free_nr_noS1_bearer_config(NR_RadioBearerConfig_t **rbconfig, - NR_RLC_BearerConfig_t **rlc_rbconfig); - int do_RRCSetup(uint8_t *const buffer, size_t buffer_size, const uint8_t transaction_id, diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index dc5e77bbc5..dbe1202e8c 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -41,9 +41,8 @@ #define NR_MAX_SUPPORTED_DL_LAYERS 4 -void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc,NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t * cg_config_info); - -void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2ap_ENDC_sgnb_addition_req_t *m); +void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m); +void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp); void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti); void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index c8cec12375..aecf702f8d 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -255,41 +255,13 @@ void openair_rrc_gNB_configuration(gNB_RRC_INST *rrc, gNB_RrcConfigurationReq *c RB_INIT(&rrc->cuups); RB_INIT(&rrc->dus); rrc->configuration = *configuration; - - if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) { - AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "phy_test and do_ra only work in monolithic\n"); - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_allocate_new_ue_context(rrc); - LOG_I(NR_RRC,"Adding new user (%p)\n",ue_context_p); - if (!NODE_IS_CU(rrc->node_type)) { - rrc_add_nsa_user(rrc,ue_context_p,NULL); - } - } } static void rrc_gNB_process_AdditionRequestInformation(const module_id_t gnb_mod_idP, x2ap_ENDC_sgnb_addition_req_t *m) { - struct NR_CG_ConfigInfo *cg_configinfo = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete(NULL, - &asn_DEF_NR_CG_ConfigInfo, - (void **)&cg_configinfo, - (uint8_t *)m->rrc_buffer, - (int) m->rrc_buffer_size);//m->rrc_buffer_size); - gNB_RRC_INST *rrc=RC.nrrrc[gnb_mod_idP]; - - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - AssertFatal(1==0,"NR_UL_DCCH_MESSAGE decode error\n"); - // free the memory - SEQUENCE_free(&asn_DEF_NR_CG_ConfigInfo, cg_configinfo, 1); - return; - } - - xer_fprint(stdout,&asn_DEF_NR_CG_ConfigInfo, cg_configinfo); - // recreate enough of X2 EN-DC Container - AssertFatal(cg_configinfo->criticalExtensions.choice.c1->present == NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo, - "ueCapabilityInformation not present\n"); - parse_CG_ConfigInfo(rrc,cg_configinfo,m); - LOG_I(NR_RRC, "Successfully parsed CG_ConfigInfo of size %zu bits. (%zu bytes)\n", - dec_rval.consumed, (dec_rval.consumed +7/8)); + gNB_RRC_INST *rrc = RC.nrrrc[gnb_mod_idP]; + AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "NSA, phy_test, and do_ra only work in monolithic\n"); + rrc_add_nsa_user(rrc, m); } //----------------------------------------------------------------------------- @@ -2183,6 +2155,11 @@ static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance if (LOG_DEBUGFLAG(DEBUG_ASN1)) xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); + if (!IS_SA_MODE(get_softmodem_params())) { + rrc_add_nsa_user_resp(rrc, UE, resp); + return; + } + if (resp->drbs_to_be_setup_length > 0) { int num_drb = get_number_active_drbs(UE); DevAssert(num_drb == 0 || num_drb == resp->drbs_to_be_setup_length); diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index d6e025309a..aff74fc984 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -437,6 +437,10 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) if (rrc->node_name != NULL) resp.gNB_CU_name = strdup(rrc->node_name); rrc->mac_rrc.f1_setup_response(assoc_id, &resp); + + /* we need to setup one default UE for phy-test and do-ra modes in the MAC */ + if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) + rrc_add_nsa_user(rrc, NULL); } static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id) diff --git a/openair2/RRC/NR/rrc_gNB_internode.c b/openair2/RRC/NR/rrc_gNB_internode.c index 843eaca250..0fa7b92a90 100644 --- a/openair2/RRC/NR/rrc_gNB_internode.c +++ b/openair2/RRC/NR/rrc_gNB_internode.c @@ -46,44 +46,6 @@ #include "uper_encoder.h" #include "x2ap_messages_types.h" -int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m) { - if (CG_ConfigInfo->criticalExtensions.present == NR_CG_ConfigInfo__criticalExtensions_PR_c1) { - if (CG_ConfigInfo->criticalExtensions.choice.c1) { - if (CG_ConfigInfo->criticalExtensions.choice.c1->present == NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo) { - NR_CG_ConfigInfo_IEs_t *cg_ConfigInfo = CG_ConfigInfo->criticalExtensions.choice.c1->choice.cg_ConfigInfo; - - if (cg_ConfigInfo->ue_CapabilityInfo) { - // Decode UE-CapabilityRAT-ContainerList - NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList=NULL; - UE_CapabilityRAT_ContainerList = calloc(1,sizeof(NR_UE_CapabilityRAT_ContainerList_t)); - asn_dec_rval_t dec_rval = uper_decode(NULL, - &asn_DEF_NR_UE_CapabilityRAT_ContainerList, - (void **)&UE_CapabilityRAT_ContainerList, - cg_ConfigInfo->ue_CapabilityInfo->buf, - cg_ConfigInfo->ue_CapabilityInfo->size, 0, 0); - - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - AssertFatal(1==0,"[InterNode] Failed to decode NR_UE_CapabilityRAT_ContainerList (%zu bits), size of OCTET_STRING %lu\n", - dec_rval.consumed, cg_ConfigInfo->ue_CapabilityInfo->size); - } - - rrc_parse_ue_capabilities(rrc,UE_CapabilityRAT_ContainerList, m,cg_ConfigInfo); - } - - if (cg_ConfigInfo->candidateCellInfoListMN) AssertFatal(1==0,"Can't handle candidateCellInfoListMN yet\n"); - } else AssertFatal(1==0,"c1 extension is not cg_ConfigInfo, returning\n"); - } else { - LOG_E(RRC,"c1 extension not found, returning\n"); - return(-1); - } - } else { - LOG_E(RRC,"Ignoring unknown CG_ConfigInfo extensions\n"); - return(-1); - } - - return(0); -} - NR_CG_Config_t *generate_CG_Config(const NR_RRCReconfiguration_t *reconfig, const NR_RadioBearerConfig_t *rbconfig) { NR_CG_Config_t *cg_Config = calloc(1, sizeof(*cg_Config)); diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index eaab13796f..1248176535 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -61,6 +61,7 @@ #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h" #include "openair3/SECU/key_nas_deriver.h" +#include "rrc_gNB_du.h" #include "rlc.h" #include "s1ap_messages_types.h" #include "tree.h" @@ -70,114 +71,79 @@ #include "xer_decoder.h" #include "xer_encoder.h" -void rrc_parse_ue_capabilities(gNB_RRC_INST *rrc, NR_UE_CapabilityRAT_ContainerList_t *UE_CapabilityRAT_ContainerList, x2ap_ENDC_sgnb_addition_req_t *m, NR_CG_ConfigInfo_IEs_t *cg_config_info) +// In case of phy-test and do-ra mode, read UE capabilities directly from file +// and put it into a CG-ConfigInfo field +static int cg_config_info_from_ue_cap_file(uint32_t maxlen, uint8_t buf[maxlen]) { - OCTET_STRING_t *ueCapabilityRAT_Container_nr=NULL; - OCTET_STRING_t *ueCapabilityRAT_Container_MRDC=NULL; - asn_dec_rval_t dec_rval; - int list_size=0; + NR_CG_ConfigInfo_t *cgci = calloc_or_fail(1, sizeof(*cgci)); + cgci->criticalExtensions.present = NR_CG_ConfigInfo__criticalExtensions_PR_c1; + cgci->criticalExtensions.choice.c1 = calloc_or_fail(1, sizeof(*cgci->criticalExtensions.choice.c1)); + cgci->criticalExtensions.choice.c1->present = NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo; + NR_CG_ConfigInfo_IEs_t *cgci_ies = calloc_or_fail(1, sizeof(*cgci_ies)); + cgci->criticalExtensions.choice.c1->choice.cg_ConfigInfo = cgci_ies; - AssertFatal(UE_CapabilityRAT_ContainerList!=NULL,"UE_CapabilityRAT_ContainerList is null\n"); - AssertFatal((list_size=UE_CapabilityRAT_ContainerList->list.count) >= 2, "UE_CapabilityRAT_ContainerList->list.size %d < 2\n",UE_CapabilityRAT_ContainerList->list.count); + if (uecap_file != NULL) { + LOG_I(NR_RRC, "creating CG-ConfigInfo from UE capability file %s\n", uecap_file); - for (int i=0; ilist.array[i]->rat_Type == NR_RAT_Type_nr) ueCapabilityRAT_Container_nr = &UE_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container; - else if (UE_CapabilityRAT_ContainerList->list.array[i]->rat_Type == NR_RAT_Type_eutra_nr) ueCapabilityRAT_Container_MRDC = &UE_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container; - } - - // decode and store capabilities - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_allocate_new_ue_context(rrc); - gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - - if (ueCapabilityRAT_Container_nr != NULL) { - dec_rval = uper_decode(NULL, &asn_DEF_NR_UE_NR_Capability, (void **)&UE->UE_Capability_nr, ueCapabilityRAT_Container_nr->buf, ueCapabilityRAT_Container_nr->size, 0, 0); - - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - LOG_E(RRC, "Failed to decode UE NR capabilities (%zu bytes) container size %lu\n", dec_rval.consumed,ueCapabilityRAT_Container_nr->size); - ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); - UE->UE_Capability_nr = 0; - AssertFatal(1==0,"exiting\n"); + FILE *f = fopen(uecap_file, "r"); + if (!f) { + LOG_E(NR_RRC, "cannot open file %s, cannot read UE capabilities\n", uecap_file); + return 0; } - } - - if (ueCapabilityRAT_Container_MRDC != NULL) { - dec_rval = uper_decode(NULL, &asn_DEF_NR_UE_MRDC_Capability, (void **)&UE->UE_Capability_MRDC, ueCapabilityRAT_Container_MRDC->buf, ueCapabilityRAT_Container_MRDC->size, 0, 0); - - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - LOG_E(RRC, "Failed to decode UE MRDC capabilities (%zu bytes)\n", dec_rval.consumed); - ASN_STRUCT_FREE(asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC); - UE->UE_Capability_MRDC = 0; - AssertFatal(1==0,"exiting\n"); + char UE_NR_Capability_xer[65536]; + size_t size = fread(UE_NR_Capability_xer, 1, sizeof UE_NR_Capability_xer, f); + fclose(f); + if (size == 0 || size == sizeof UE_NR_Capability_xer) { + LOG_E(NR_RRC, "UE Capabilities XER file %s could not be read (read %ld bytes)\n", uecap_file, size); + return 0; } + NR_UE_NR_Capability_t *cap = calloc_or_fail(1, sizeof(*cap)); + asn_dec_rval_t dec_rval = xer_decode(0, &asn_DEF_NR_UE_NR_Capability, (void *)&cap, UE_NR_Capability_xer, size); + DevAssert(dec_rval.code == RC_OK); + //xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, cap); + + OCTET_STRING_t *os_cap = calloc_or_fail(1, sizeof(*os_cap)); + os_cap->size = uper_encode_to_new_buffer(&asn_DEF_NR_UE_NR_Capability, NULL, cap, (void **)&os_cap->buf); + cgci_ies->ue_CapabilityInfo = os_cap; } - // dump ue_capabilities - - if ( LOG_DEBUGFLAG(DEBUG_ASN1) && ueCapabilityRAT_Container_nr != NULL ) { - xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); - } - - if ( LOG_DEBUGFLAG(DEBUG_ASN1) && ueCapabilityRAT_Container_MRDC != NULL ) { - xer_fprint(stdout, &asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC); - } - LOG_A(NR_RRC, "Successfully decoded UE NR capabilities (NR and MRDC)\n"); - - AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "phy_test and do_ra only work in monolithic\n"); - LOG_I(NR_RRC,"Adding new NSA user (%p)\n",ue_context_p); - rrc_add_nsa_user(rrc,ue_context_p, m); + //xer_fprint(stdout, &asn_DEF_NR_CG_ConfigInfo, cgci); + asn_enc_rval_t rval = uper_encode_to_buffer(&asn_DEF_NR_CG_ConfigInfo, NULL, cgci, buf, maxlen); + DevAssert(rval.encoded > 0); + return (rval.encoded + 7) >> 3; } /* generate prototypes for the tree management functions (RB_INSERT used in rrc_add_nsa_user) */ RB_PROTOTYPE(rrc_nr_ue_tree_s, rrc_gNB_ue_context_s, entries, rrc_gNB_compare_ue_rnti_id); -void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2ap_ENDC_sgnb_addition_req_t *m) +void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m) { AssertFatal(!IS_SA_MODE(get_softmodem_params()), "%s() cannot be called in SA mode, it is intrinsically for NSA\n", __func__); - // generate nr-Config-r15 containers for LTE RRC : inside message for X2 EN-DC (CG-Config Message from 38.331) - const nr_mac_config_t *configuration = &RC.nrmac[0]->radio_config; - MessageDef *msg; - msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ_ACK); - gtpv1u_enb_create_tunnel_req_t create_tunnel_req; - gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp; - protocol_ctxt_t ctxt={0}; - nr_pdcp_entity_security_keys_and_algos_t security_parameters = {0}; - int i; + AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "NSA, phy_test and do_ra only work in monolithic\n"); + + sctp_assoc_t assoc_id = -1; /* integrated DU, hardcoded: if multiple we would not know what to do? */ + /* all the 0 are DU-related info that we will fill later, see rrc_add_nsa_user_resp() below */ + rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_create_ue_context(assoc_id, 0, rrc, 0, 0); gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - // In case of phy-test and do-ra mode, read UE capabilities directly from file - if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1) { - NR_UE_NR_Capability_t* UE_Capability_nr = NULL; - char UE_NR_Capability_xer[65536]; - FILE *f = NULL; - if (uecap_file) - f = fopen(uecap_file, "r"); - if (f) { - size_t size = fread(UE_NR_Capability_xer, 1, sizeof UE_NR_Capability_xer, f); - if (size == 0 || size == sizeof UE_NR_Capability_xer) - LOG_E(NR_RRC,"UE Capabilities XER file %s is too large (%ld)\n", uecap_file, size); - else { - UE_Capability_nr = CALLOC(1,sizeof(NR_UE_NR_Capability_t)); - asn_dec_rval_t dec_rval = xer_decode(0, &asn_DEF_NR_UE_NR_Capability, (void *)&UE_Capability_nr, UE_NR_Capability_xer, size); - assert(dec_rval.code == RC_OK); - xer_fprint(stdout,&asn_DEF_NR_UE_NR_Capability,(void *)UE_Capability_nr); - } - fclose(f); - } - else - LOG_E(NR_RRC,"Could not open UE Capabilities input file. Not handling OAI UE Capabilities.\n"); - UE->UE_Capability_nr = UE_Capability_nr; - } + nr_pdcp_entity_security_keys_and_algos_t security_parameters = {0}; - // NR RRCReconfiguration + uint8_t tmp[1024]; + uint8_t *cgci_buf = NULL; + uint32_t cgci_len = 0; if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra == 1) { + DevAssert(m == NULL); UE->rb_config = get_default_rbconfig(10 /* EPS bearer ID */, 1 /* drb ID */, NR_CipheringAlgorithm_nea0, NR_SecurityConfig__keyToUse_master); + cgci_len = cg_config_info_from_ue_cap_file(sizeof tmp, tmp); + DevAssert(cgci_len > 0); + cgci_buf = tmp; } else { + DevAssert(m != NULL); + cgci_buf = m->rrc_buffer; + cgci_len = m->rrc_buffer_size; + /* TODO: handle more than one bearer */ - if (m == NULL) { - LOG_E(RRC, "fatal: m==NULL\n"); - exit(1); - } if (m->nb_e_rabs_tobeadded != 1) { LOG_E(RRC, "fatal: m->nb_e_rabs_tobeadded = %d, should be 1\n", m->nb_e_rabs_tobeadded); exit(1); @@ -195,7 +161,7 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a */ /* preset nea0 as fallback */ UE->ciphering_algorithm = 0; - for (i = 0; i < rrc->security.ciphering_algorithms_count; i++) { + for (int i = 0; i < rrc->security.ciphering_algorithms_count; i++) { int nea_mask[4] = { 0, 0x8000, /* nea1 */ @@ -253,24 +219,10 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a UE->rb_config = get_default_rbconfig(m->e_rabs_tobeadded[0].e_rab_id, m->e_rabs_tobeadded[0].drb_ID, cipher_algo, NR_SecurityConfig__keyToUse_secondary); } - NR_ServingCellConfig_t *scc = RC.nrmac[0]->common_channels[0].pre_ServingCellConfig; - // The MAC has the ServingCellConfigCommon; the below code is incorrect: the - // CU should send a UE Context Setup Request to request the creating of the - // MAC Context - NR_ServingCellConfigCommon_t *sccc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon; - NR_CellGroupConfig_t *secondaryCellGroup = - get_default_secondaryCellGroup(sccc, scc, UE->UE_Capability_nr, 1, 1, configuration, ue_context_p->ue_context.rrc_ue_id); - AssertFatal(secondaryCellGroup != NULL, "out of memory\n"); - - NR_RRCReconfiguration_t *reconfig = calloc(1, sizeof(NR_RRCReconfiguration_t)); - reconfig->rrc_TransactionIdentifier = 0; - reconfig->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration; - reconfig->criticalExtensions.choice.rrcReconfiguration = get_default_reconfig(secondaryCellGroup); - UE->rnti = secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity; - - NR_CG_Config_t *CG_Config = generate_CG_Config(reconfig, UE->rb_config); - if(m!=NULL) { + + gtpv1u_enb_create_tunnel_req_t create_tunnel_req = {0}; + gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp = {0}; if (m->nb_e_rabs_tobeadded>0) { for (int i=0; inb_e_rabs_tobeadded; i++) { // Add the new E-RABs at the corresponding rrc ue context of the gNB @@ -295,7 +247,6 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a create_tunnel_req.rnti = ue_context_p->ue_context.rrc_ue_id; create_tunnel_req.num_tunnels = m->nb_e_rabs_tobeadded; RB_INSERT(rrc_nr_ue_tree_s, &RC.nrrrc[rrc->module_id]->rrc_ue_head, ue_context_p); - memset(&create_tunnel_resp, 0, sizeof(create_tunnel_resp)); if (!IS_SOFTMODEM_NOS1) { gtpv1u_create_s1u_tunnel(rrc->module_id, &create_tunnel_req, &create_tunnel_resp, nr_pdcp_data_req_drb); DevAssert(create_tunnel_resp.num_tunnels == 1); @@ -303,6 +254,67 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a UE->nsa_gtp_addrs[0] = create_tunnel_resp.enb_addr; UE->nsa_gtp_ebi[0] = create_tunnel_resp.eps_bearer_id[0]; } + } + } + + DevAssert(UE->rb_config != NULL); + nr_pdcp_add_drbs(GNB_FLAG_YES, + UE->rrc_ue_id, + UE->rb_config->drb_ToAddModList, + &security_parameters); + + cu_to_du_rrc_information_t cu2du = { + .cG_ConfigInfo = cgci_buf, + .cG_ConfigInfo_length = cgci_len, + }; + /* assumption: only a single bearer, see above */ + NR_DRB_ToAddModList_t *rb_list = UE->rb_config->drb_ToAddModList; + AssertFatal(rb_list->list.count == 1, "can only handle one bearer for NSA/phy-test/do-ra, but has %d\n", rb_list->list.count); + f1ap_drb_to_be_setup_t drbs = { + .drb_id = rb_list->list.array[0]->drb_Identity, + .rlc_mode = F1AP_RLC_MODE_UM_BIDIR, // hardcoded keep it backwards compatible for now + // rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM, + .up_ul_tnl_length = 1, + }; + f1ap_ue_context_setup_t req = { + .gNB_CU_ue_id = UE->rrc_ue_id, + .gNB_DU_ue_id = 0xffffffff, /* not known yet */ + .plmn.mcc = rrc->configuration.plmn[0].mcc, + .plmn.mnc = rrc->configuration.plmn[0].mnc, + .plmn.mnc_digit_length = rrc->configuration.plmn[0].mnc_digit_length, + .nr_cellid = rrc->nr_cellid, + .servCellId = 0, + .drbs_to_be_setup_length = 1, + .drbs_to_be_setup = &drbs, + .cu_to_du_rrc_information = &cu2du, + }; + f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); + RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); + rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &req); +} + +void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp) +{ + DevAssert(resp->crnti != NULL); + /* we did not fill any DU-related ID info in rrc_add_nsa_user() */ + UE->rnti = *resp->crnti; + DevAssert(cu_exists_f1_ue_data(UE->rrc_ue_id)); + f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); + ue_data.secondary_ue = resp->gNB_DU_ue_id; + bool success = cu_update_f1_ue_data(UE->rrc_ue_id, &ue_data); + DevAssert(success); + + NR_RRCReconfiguration_t *reconfig = calloc(1, sizeof(NR_RRCReconfiguration_t)); + reconfig->rrc_TransactionIdentifier = 0; + reconfig->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration; + reconfig->criticalExtensions.choice.rrcReconfiguration = get_default_reconfig(UE->masterCellGroup); + + /*NR_CG_Config_t *CG_Config =*/ generate_CG_Config(reconfig, UE->rb_config); + + + /* + MessageDef *msg; + msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ_ACK); X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).nb_e_rabs_admitted_tobeadded = m->nb_e_rabs_tobeadded; X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).target_assoc_id = m->target_assoc_id; @@ -343,72 +355,8 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a sizeof(X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer)); X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = (enc_rval.encoded+7)>>3; itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); //Check right id instead of hardcoding - } + */ - // below we configure the stack. In SA, we fully adopted F1, meaning that - // layers use different IDs (MAC/RLC use RNTI as DU UE ID, above use NGAP ID - // as CU UE ID. - uint32_t du_ue_id = ue_context_p->ue_context.rnti; - uint32_t rrc_ue_id = ue_context_p->ue_context.rrc_ue_id; - f1_ue_data_t du_ue_data = {.secondary_ue = rrc_ue_id}; - bool success = du_add_f1_ue_data(du_ue_id, &du_ue_data); - DevAssert(success); - f1_ue_data_t cu_ue_data = {.secondary_ue = du_ue_id}; - success = cu_add_f1_ue_data(rrc_ue_id, &cu_ue_data); - DevAssert(success); - LOG_I(RRC, "Assign CU UE ID %d and DU UE ID %d to UE RNTI %04x\n", rrc_ue_id, du_ue_id, ue_context_p->ue_context.rnti); - - // configure MAC and RLC - bool ret = false; - if (get_softmodem_params()->phy_test) { - // phytest mode: we don't set up RA, etc - ret = nr_mac_add_test_ue(RC.nrmac[rrc->module_id], du_ue_id, secondaryCellGroup); - } else { - DevAssert(secondaryCellGroup->spCellConfig - && secondaryCellGroup->spCellConfig->reconfigurationWithSync - && secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated - && secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra); - gNB_MAC_INST *nrmac = RC.nrmac[rrc->module_id]; - NR_SCHED_LOCK(&nrmac->sched_lock); - NR_UE_info_t *UE_info = get_new_nr_ue_inst(&nrmac->UE_info.uid_allocator, UE->rnti, secondaryCellGroup); - AssertFatal(UE_info != NULL, "cannot create UE context: list is full?\n"); - if (add_new_UE_RA(nrmac, UE_info)) { - ret = true; - nr_mac_prepare_ra_ue(nrmac, UE_info); - } else { - delete_nr_ue_data(UE_info, /* not used */ NULL, &nrmac->UE_info.uid_allocator); - } - NR_SCHED_UNLOCK(&nrmac->sched_lock); - } - AssertFatal(ret, "cannot add NSA UE in MAC, aborting\n"); - - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, rrc->module_id, GNB_FLAG_YES, rrc_ue_id, 0, 0, rrc->module_id); - LOG_W(RRC, - "Calling RRC PDCP/RLC ASN1 request functions for protocol context %p with module_id %d, rnti %lx, frame %d, subframe %d eNB_index %d \n", - &ctxt, - ctxt.module_id, - ctxt.rntiMaybeUEid, - ctxt.frame, - ctxt.subframe, - ctxt.eNB_index); - - nr_pdcp_add_drbs(ctxt.enb_flag, - rrc_ue_id, - ue_context_p->ue_context.rb_config->drb_ToAddModList, - &security_parameters); - - ctxt.rntiMaybeUEid = du_ue_id; - // assume only a single bearer - const NR_DRB_ToAddModList_t *drb_list = ue_context_p->ue_context.rb_config->drb_ToAddModList; - DevAssert(drb_list->list.count == 1); - const NR_DRB_ToAddMod_t *drb = drb_list->list.array[0]; - const struct NR_CellGroupConfig__rlc_BearerToAddModList *bearer_list = secondaryCellGroup->rlc_BearerToAddModList; - const NR_RLC_BearerConfig_t *bearer = bearer_list->list.array[0]; - DevAssert(bearer_list->list.count == 1); - DevAssert(drb->drb_Identity == bearer->servedRadioBearer->choice.drb_Identity); - nr_rlc_add_drb(ctxt.rntiMaybeUEid, drb->drb_Identity, bearer); - - LOG_D(RRC, "%s:%d: done RRC PDCP/RLC ASN1 request for UE rnti %lx\n", __FUNCTION__, __LINE__, ctxt.rntiMaybeUEid); } void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti) { From fddcb2a5e870f6aad674fd96933487a5b67a744f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 3 Apr 2025 15:01:33 +0200 Subject: [PATCH 17/25] Reply X2 Addition Request after F1 UE context setup in NSA --- openair2/RRC/NR/nr_rrc_defs.h | 4 +- openair2/RRC/NR/rrc_gNB_nsa.c | 71 ++++++++++++++--------------------- 2 files changed, 30 insertions(+), 45 deletions(-) diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index a3029cefd2..6cee7e6fa4 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -221,9 +221,9 @@ typedef struct gNB_RRC_UE_s { ngap_security_capabilities_t security_capabilities; //NSA block - /* Number of NSA e_rab */ + sctp_assoc_t x2_target_assoc; + int MeNB_ue_x2_id; int nb_of_e_rabs; - /* list of pdu session to be setup by RRC layers */ nr_e_rab_param_t e_rab[NB_RB_MAX];//[S1AP_MAX_E_RAB]; uint32_t nsa_gtp_teid[S1AP_MAX_E_RAB]; transport_layer_addr_t nsa_gtp_addrs[S1AP_MAX_E_RAB]; diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 1248176535..ea70d9f8f5 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -221,6 +221,8 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m) if(m!=NULL) { + UE->x2_target_assoc = m->target_assoc_id; + UE->MeNB_ue_x2_id = m->ue_x2_id; gtpv1u_enb_create_tunnel_req_t create_tunnel_req = {0}; gtpv1u_enb_create_tunnel_resp_t create_tunnel_resp = {0}; if (m->nb_e_rabs_tobeadded>0) { @@ -309,54 +311,37 @@ void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_co reconfig->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration; reconfig->criticalExtensions.choice.rrcReconfiguration = get_default_reconfig(UE->masterCellGroup); - /*NR_CG_Config_t *CG_Config =*/ generate_CG_Config(reconfig, UE->rb_config); + NR_CG_Config_t *CG_Config = generate_CG_Config(reconfig, UE->rb_config); + if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) { + /* we are done, no X2 answer necessary */ + ASN_STRUCT_FREE(asn_DEF_NR_CG_Config, CG_Config); + return; + } - /* - MessageDef *msg; - msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ_ACK); - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).nb_e_rabs_admitted_tobeadded = m->nb_e_rabs_tobeadded; - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).target_assoc_id = m->target_assoc_id; + MessageDef *msg = itti_alloc_new_message(TASK_RRC_ENB, 0, X2AP_ENDC_SGNB_ADDITION_REQ_ACK); + x2ap_ENDC_sgnb_addition_req_ACK_t *ack = &X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg); - for (int i = 0; i < UE->nb_of_e_rabs; i++) { - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].e_rab_id = UE->e_rab[i].param.e_rab_id; - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gtp_teid = create_tunnel_resp.enb_S1u_teid[i]; - memcpy(&X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gnb_addr, &create_tunnel_resp.enb_addr, sizeof(transport_layer_addr_t)); - //The length field in the X2AP targetting structure is expected in bits but the create_tunnel_resp returns the address length in bytes - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gnb_addr.length = create_tunnel_resp.enb_addr.length*8; - LOG_I(RRC,"S1-U create_tunnel_resp tunnel: index %d target gNB ip %d.%d.%d.%d length %d gtp teid %u\n", - i, - create_tunnel_resp.enb_addr.buffer[0], - create_tunnel_resp.enb_addr.buffer[1], - create_tunnel_resp.enb_addr.buffer[2], - create_tunnel_resp.enb_addr.buffer[3], - create_tunnel_resp.enb_addr.length, - create_tunnel_resp.enb_S1u_teid[i]); - LOG_I(RRC,"X2AP sGNB Addition Request: index %d target gNB ip %d.%d.%d.%d length %d gtp teid %u\n", - i, - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gnb_addr.buffer[0], - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gnb_addr.buffer[1], - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gnb_addr.buffer[2], - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gnb_addr.buffer[3], - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gnb_addr.length, - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).e_rabs_admitted_tobeadded[i].gtp_teid); - } - } else - LOG_W(RRC, "No E-RAB to be added received from SgNB Addition Request message \n"); + ack->nb_e_rabs_admitted_tobeadded = UE->nb_of_e_rabs; + DevAssert(UE->x2_target_assoc > 0); + ack->target_assoc_id = UE->x2_target_assoc; - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).MeNB_ue_x2_id = m->ue_x2_id; - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).SgNB_ue_x2_id = secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity; - //X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = CG_Config_size; //Need to verify correct value for the buffer_size - // Send to X2 entity to transport to MeNB - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CG_Config, - NULL, - (void *)CG_Config, - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer, - sizeof(X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer)); - X2AP_ENDC_SGNB_ADDITION_REQ_ACK(msg).rrc_buffer_size = (enc_rval.encoded+7)>>3; - itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); //Check right id instead of hardcoding - */ + for (int i = 0; i < UE->nb_of_e_rabs; i++) { + ack->e_rabs_admitted_tobeadded[i].e_rab_id = UE->e_rab[i].param.e_rab_id; + ack->e_rabs_admitted_tobeadded[i].gtp_teid = UE->nsa_gtp_teid[0]; + memcpy(&ack->e_rabs_admitted_tobeadded[i].gnb_addr, &UE->nsa_gtp_addrs[0], sizeof(transport_layer_addr_t)); + ack->e_rabs_admitted_tobeadded[i].gnb_addr.length = 32; // bits, IPv4 only + } + ack->MeNB_ue_x2_id = UE->MeNB_ue_x2_id; + ack->SgNB_ue_x2_id = UE->rrc_ue_id; + + // Send to X2 entity to transport to MeNB + asn_enc_rval_t enc_rval = + uper_encode_to_buffer(&asn_DEF_NR_CG_Config, NULL, (void *)CG_Config, ack->rrc_buffer, sizeof(ack->rrc_buffer)); + ack->rrc_buffer_size = (enc_rval.encoded + 7) >> 3; + itti_send_msg_to_task(TASK_X2AP, ENB_MODULE_ID_TO_INSTANCE(0), msg); + ASN_STRUCT_FREE(asn_DEF_NR_CG_Config, CG_Config); } void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti) { From efbdd92694edcccaae042f492d861655b900791a Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 24 Apr 2025 09:25:19 +0200 Subject: [PATCH 18/25] Move get_default_reconfig() to rrc_gNB_nsa.c --- CMakeLists.txt | 1 - doc/Doxyfile | 1 - openair2/RRC/NR/nr_rrc_proto.h | 2 - openair2/RRC/NR/rrc_gNB_nsa.c | 18 ++++++++ openair2/RRC/NR/rrc_gNB_reconfig.c | 66 ------------------------------ 5 files changed, 18 insertions(+), 70 deletions(-) delete mode 100644 openair2/RRC/NR/rrc_gNB_reconfig.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f77734be1..25d8d29bde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1139,7 +1139,6 @@ set(L2_NR_SRC ${NR_RRC_DIR}/nr_rrc_config.c ${NR_RRC_DIR}/rrc_gNB_nsa.c ${NR_RRC_DIR}/rrc_gNB_internode.c - ${NR_RRC_DIR}/rrc_gNB_reconfig.c ${NR_RRC_DIR}/rrc_gNB_UE_context.c ${NR_RRC_DIR}/rrc_gNB_NGAP.c ${NR_RRC_DIR}/rrc_gNB_radio_bearers.c diff --git a/doc/Doxyfile b/doc/Doxyfile index 991a0bf734..5b20232c20 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1861,7 +1861,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/nr_rrc_config.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_radio_bearers.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_reconfig.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_NGAP.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/mac_rrc_dl_f1ap.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/mac_rrc_dl.h \ diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index dbe1202e8c..fe544b7767 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -47,8 +47,6 @@ void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_co void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti); void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p); -NR_RRCReconfiguration_IEs_t *get_default_reconfig(const NR_CellGroupConfig_t *secondaryCellGroup); - NR_CG_Config_t *generate_CG_Config(const NR_RRCReconfiguration_t *reconfig, const NR_RadioBearerConfig_t *rbconfig); int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m); diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index ea70d9f8f5..1f89fe818d 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -295,6 +295,24 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m) rrc->mac_rrc.ue_context_setup_request(ue_data.du_assoc_id, &req); } +static NR_RRCReconfiguration_IEs_t *get_default_reconfig(const NR_CellGroupConfig_t *secondaryCellGroup) +{ + NR_RRCReconfiguration_IEs_t *reconfig = calloc(1, sizeof(NR_RRCReconfiguration_IEs_t)); + AssertFatal(reconfig != NULL, "out of memory\n"); + AssertFatal(secondaryCellGroup != NULL, "secondaryCellGroup is null\n"); + reconfig->radioBearerConfig = NULL; + + char scg_buffer[1024]; + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, (void *)secondaryCellGroup, scg_buffer, 1024); + AssertFatal(enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded); + reconfig->secondaryCellGroup = calloc(1, sizeof(*reconfig->secondaryCellGroup)); + OCTET_STRING_fromBuf(reconfig->secondaryCellGroup, (const char *)scg_buffer, (enc_rval.encoded + 7) >> 3); + reconfig->measConfig = NULL; + reconfig->lateNonCriticalExtension = NULL; + reconfig->nonCriticalExtension = NULL; + return reconfig; +} + void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp) { DevAssert(resp->crnti != NULL); diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c deleted file mode 100644 index 57e9b28dc6..0000000000 --- a/openair2/RRC/NR/rrc_gNB_reconfig.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file rrc_gNB_reconfig.c - * \brief rrc gNB RRCreconfiguration support routines - * \author Raymond Knopp - * \date 2019 - * \version 1.0 - * \company Eurecom - * \email: raymond.knopp@eurecom.fr - */ -#ifndef RRC_GNB_NSA_C -#define RRC_GNB_NSA_C - -#include - -#include "OCTET_STRING.h" -#include "RRC/NR/nr_rrc_proto.h" -#include "asn_codecs.h" -#include "assertions.h" -#include "constr_TYPE.h" -#include "oai_asn1.h" -#include "uper_encoder.h" - -NR_RRCReconfiguration_IEs_t *get_default_reconfig(const NR_CellGroupConfig_t *secondaryCellGroup) -{ - NR_RRCReconfiguration_IEs_t *reconfig = calloc(1, sizeof(NR_RRCReconfiguration_IEs_t)); - AssertFatal(reconfig != NULL, "out of memory\n"); - AssertFatal(secondaryCellGroup!=NULL,"secondaryCellGroup is null\n"); - // radioBearerConfig - reconfig->radioBearerConfig=NULL; - - char scg_buffer[1024]; - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, (void *)secondaryCellGroup, scg_buffer, 1024); - AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", enc_rval.failed_type->name, enc_rval.encoded); - reconfig->secondaryCellGroup = calloc(1,sizeof(*reconfig->secondaryCellGroup)); - OCTET_STRING_fromBuf(reconfig->secondaryCellGroup, - (const char *)scg_buffer, - (enc_rval.encoded+7)>>3); - // measConfig - reconfig->measConfig=NULL; - // lateNonCriticalExtension - reconfig->lateNonCriticalExtension = NULL; - // nonCriticalExtension - reconfig->nonCriticalExtension = NULL; - return reconfig; -} -#endif From 958b2f3fac15dc63b21512e78b3b2c59d4efe342 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 17 Apr 2025 17:21:47 +0200 Subject: [PATCH 19/25] Move generate_CG_Config() to rrc_gNB_nsa.c Remove the (now) unused rrc_gNB_internode.c. generate_CG_Config() is only used in NSA, so can be static. --- CMakeLists.txt | 1 - doc/Doxyfile | 1 - openair2/RRC/NR/nr_rrc_proto.h | 2 - openair2/RRC/NR/rrc_gNB_internode.c | 109 ---------------------------- openair2/RRC/NR/rrc_gNB_nsa.c | 38 ++++++++++ 5 files changed, 38 insertions(+), 113 deletions(-) delete mode 100644 openair2/RRC/NR/rrc_gNB_internode.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 25d8d29bde..feb7e41a4f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1138,7 +1138,6 @@ set(L2_NR_SRC ${NR_RRC_DIR}/mac_rrc_dl_f1ap.c ${NR_RRC_DIR}/nr_rrc_config.c ${NR_RRC_DIR}/rrc_gNB_nsa.c - ${NR_RRC_DIR}/rrc_gNB_internode.c ${NR_RRC_DIR}/rrc_gNB_UE_context.c ${NR_RRC_DIR}/rrc_gNB_NGAP.c ${NR_RRC_DIR}/rrc_gNB_radio_bearers.c diff --git a/doc/Doxyfile b/doc/Doxyfile index 5b20232c20..a154051692 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1844,7 +1844,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR_UE/rrc_defs.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR_UE/L2_interface_ue.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/L2_INTERFACE/openair_rrc_L2_interface.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/rrc_gNB_internode.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/nr_rrc_defs.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/cucp_cuup_if.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/RRC/NR/cucp_cuup_direct.c \ diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index fe544b7767..a06ef76581 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -47,8 +47,6 @@ void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_co void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti); void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p); -NR_CG_Config_t *generate_CG_Config(const NR_RRCReconfiguration_t *reconfig, const NR_RadioBearerConfig_t *rbconfig); - int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m); void rrc_gNB_generate_SecurityModeCommand(gNB_RRC_INST *rrc, gNB_RRC_UE_t *ue_p); diff --git a/openair2/RRC/NR/rrc_gNB_internode.c b/openair2/RRC/NR/rrc_gNB_internode.c deleted file mode 100644 index 0fa7b92a90..0000000000 --- a/openair2/RRC/NR/rrc_gNB_internode.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file rrc_gNB_internode.c - * \brief rrc internode procedures for gNB - * \author Raymond Knopp - * \date 2019 - * \version 1.0 - * \company Eurecom - * \email: raymond.knopp@eurecom.fr - */ -#ifndef RRC_GNB_INTERNODE_C -#define RRC_GNB_INTERNODE_C - -#include -#include -#include -#include "OCTET_STRING.h" -#include "RRC/NR/nr_rrc_proto.h" -#include "T.h" -#include "asn_codecs.h" -#include "assertions.h" -#include "common/utils/T/T.h" -#include "constr_TYPE.h" -#include "executables/softmodem-common.h" -#include "nr_rrc_defs.h" -#include "uper_decoder.h" -#include "uper_encoder.h" -#include "x2ap_messages_types.h" - -NR_CG_Config_t *generate_CG_Config(const NR_RRCReconfiguration_t *reconfig, const NR_RadioBearerConfig_t *rbconfig) -{ - NR_CG_Config_t *cg_Config = calloc(1, sizeof(*cg_Config)); - cg_Config->criticalExtensions.present = NR_CG_Config__criticalExtensions_PR_c1; - cg_Config->criticalExtensions.choice.c1 = calloc(1,sizeof(*cg_Config->criticalExtensions.choice.c1)); - cg_Config->criticalExtensions.choice.c1->present = NR_CG_Config__criticalExtensions__c1_PR_cg_Config; - cg_Config->criticalExtensions.choice.c1->choice.cg_Config = calloc(1,sizeof(NR_CG_Config_IEs_t)); - char buffer[1024]; - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_RRCReconfiguration, NULL, (void *)reconfig, buffer, 1024); - AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - cg_Config->criticalExtensions.choice.c1->choice.cg_Config->scg_CellGroupConfig = calloc(1,sizeof(OCTET_STRING_t)); - OCTET_STRING_fromBuf(cg_Config->criticalExtensions.choice.c1->choice.cg_Config->scg_CellGroupConfig, - (const char *)buffer, - (enc_rval.encoded+7)>>3); - - FILE *fd; // file to be generated for nr-ue - if (get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra > 0) { - // This is for phytest only, emulate first X2 message if uecap.raw file is present - LOG_I(RRC,"Dumping NR_RRCReconfiguration message (%jd bytes)\n",(enc_rval.encoded+7)>>3); - for (int i=0; i<(enc_rval.encoded+7)>>3; i++) { - printf("%02x",((uint8_t *)buffer)[i]); - } - printf("\n"); - fd = fopen("reconfig.raw","w"); - if (fd != NULL) { - fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd); - fclose(fd); - } - } - - enc_rval = uper_encode_to_buffer(&asn_DEF_NR_RadioBearerConfig, NULL, (void *)rbconfig, buffer, 1024); - AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - cg_Config->criticalExtensions.choice.c1->choice.cg_Config->scg_RB_Config = calloc(1,sizeof(OCTET_STRING_t)); - - OCTET_STRING_fromBuf(cg_Config->criticalExtensions.choice.c1->choice.cg_Config->scg_RB_Config, - (const char *)buffer, - (enc_rval.encoded+7)>>3); - - - - if (get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra > 0) { - - LOG_I(RRC,"Dumping scg_RB_Config message (%jd bytes)\n",(enc_rval.encoded+7)>>3); - for (int i=0; i<(enc_rval.encoded+7)>>3; i++) { - printf("%02x",((uint8_t *)buffer)[i]); - } - - printf("\n"); - fd = fopen("rbconfig.raw","w"); - if (fd != NULL) { - fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd); - fclose(fd); - } - } - - return cg_Config; -} - -#endif diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 1f89fe818d..b2f0991da3 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -313,6 +313,44 @@ static NR_RRCReconfiguration_IEs_t *get_default_reconfig(const NR_CellGroupConfi return reconfig; } +static NR_CG_Config_t *generate_CG_Config(const NR_RRCReconfiguration_t *reconfig, const NR_RadioBearerConfig_t *rbconfig) +{ + NR_CG_Config_t *cg_Config = calloc_or_fail(1, sizeof(*cg_Config)); + cg_Config->criticalExtensions.present = NR_CG_Config__criticalExtensions_PR_c1; + cg_Config->criticalExtensions.choice.c1 = calloc_or_fail(1, sizeof(*cg_Config->criticalExtensions.choice.c1)); + cg_Config->criticalExtensions.choice.c1->present = NR_CG_Config__criticalExtensions__c1_PR_cg_Config; + NR_CG_Config_IEs_t *cgc_ie = calloc_or_fail(1, sizeof(*cgc_ie)); + cg_Config->criticalExtensions.choice.c1->choice.cg_Config = cgc_ie; + cgc_ie->scg_CellGroupConfig = calloc_or_fail(1, sizeof(*cgc_ie->scg_CellGroupConfig)); + cgc_ie->scg_CellGroupConfig->size = + uper_encode_to_new_buffer(&asn_DEF_NR_RRCReconfiguration, NULL, reconfig, (void **)&cgc_ie->scg_CellGroupConfig->buf); + AssertFatal(cgc_ie->scg_CellGroupConfig->size > 0, + "ASN1 message encoding of RRCReconfiguration failed (%ld)!\n", + cgc_ie->scg_CellGroupConfig->size); + + cgc_ie->scg_RB_Config = calloc_or_fail(1, sizeof(*cgc_ie->scg_RB_Config)); + cgc_ie->scg_RB_Config->size = + uper_encode_to_new_buffer(&asn_DEF_NR_RadioBearerConfig, NULL, rbconfig, (void **)&cgc_ie->scg_RB_Config->buf); + AssertFatal(cgc_ie->scg_RB_Config->size > 0, "ASN1 message encoding failed (%ld)!\n", cgc_ie->scg_RB_Config->size); + + if (get_softmodem_params()->phy_test == 1 || get_softmodem_params()->do_ra > 0) { + // This is for phytest only, emulate first X2 message if uecap.raw file is present + LOG_I(RRC, "Dumping NR_RRCReconfiguration message (%jd bytes) to reconfig.raw\n", cgc_ie->scg_CellGroupConfig->size); + FILE *fd = fopen("reconfig.raw", "w"); + AssertFatal(fd != NULL, "could not open reconig.raw for writing: %d, %s\n", errno, strerror(errno)); + fwrite(cgc_ie->scg_CellGroupConfig->buf, cgc_ie->scg_CellGroupConfig->size, 1, fd); + fclose(fd); + + LOG_I(RRC, "Dumping scg_RB_Config message (%jd bytes) to reconfig.raw\n", cgc_ie->scg_RB_Config->size); + fd = fopen("rbconfig.raw", "w"); + AssertFatal(fd != NULL, "could not open rbconig.raw for writing: %d, %s\n", errno, strerror(errno)); + fwrite(cgc_ie->scg_RB_Config->buf, cgc_ie->scg_RB_Config->size, 1, fd); + fclose(fd); + } + + return cg_Config; +} + void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp) { DevAssert(resp->crnti != NULL); From 94443aefdeaa4dff1d8b87984bc5df2be71b623d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 24 Apr 2025 16:09:17 +0200 Subject: [PATCH 20/25] Save in SDAP context if is UE or gNB sdap_tun_read_thread needs to know if we are gNB/UE. Previously, we passed this into the thread, but the next commit also needs to for interface termination, where this info is not available. So, for noS1 mode, pass this in. --- openair2/SDAP/nr_sdap/nr_sdap.c | 35 +++++++++++--------------- openair2/SDAP/nr_sdap/nr_sdap_entity.c | 5 ++-- openair2/SDAP/nr_sdap/nr_sdap_entity.h | 5 +++- 3 files changed, 21 insertions(+), 24 deletions(-) diff --git a/openair2/SDAP/nr_sdap/nr_sdap.c b/openair2/SDAP/nr_sdap/nr_sdap.c index 1fe8e925a7..44b8fa2cb0 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap.c +++ b/openair2/SDAP/nr_sdap/nr_sdap.c @@ -107,17 +107,10 @@ void sdap_data_ind(rb_id_t pdcp_entity, size); } -struct thread_args { - nr_sdap_entity_t *entity; - bool is_gnb; -}; static void *sdap_tun_read_thread(void *arg) { DevAssert(arg != NULL); - struct thread_args *ta = arg; - nr_sdap_entity_t *entity = ta->entity; - bool is_gnb = ta->is_gnb; - free(ta); + nr_sdap_entity_t *entity = arg; char rx_buf[NL_MAX_PAYLOAD]; int len; @@ -134,9 +127,9 @@ static void *sdap_tun_read_thread(void *arg) LOG_D(SDAP, "read data of size %d\n", len); - protocol_ctxt_t ctxt = {.enb_flag = is_gnb, .rntiMaybeUEid = entity->ue_id}; + protocol_ctxt_t ctxt = {.enb_flag = entity->is_gnb, .rntiMaybeUEid = entity->ue_id}; - bool dc = is_gnb ? false : SDAP_HDR_UL_DATA_PDU; + bool dc = entity->is_gnb ? false : SDAP_HDR_UL_DATA_PDU; DevAssert(entity != NULL); entity->tx_entity(entity, @@ -161,30 +154,25 @@ void start_sdap_tun_gnb_first_ue_default_pdu_session(ue_id_t ue_id) { nr_sdap_entity_t *entity = nr_sdap_get_entity(ue_id, get_softmodem_params()->default_pdu_session_id); DevAssert(entity != NULL); + DevAssert(entity->is_gnb); char *ifprefix = get_softmodem_params()->nsa ? "oaitun_gnb" : "oaitun_enb"; char ifname[IFNAMSIZ]; tun_generate_ifname(ifname, ifprefix, ue_id - 1); entity->pdusession_sock = tun_alloc(ifname); tun_config(ifname, "10.0.1.1", NULL); - struct thread_args *ta = calloc_or_fail(1, sizeof(*ta)); - ta->entity = entity; - ta->is_gnb = true; - - threadCreate(&entity->pdusession_thread, sdap_tun_read_thread, ta, "gnb_tun_read_thread", -1, OAI_PRIORITY_RT_LOW); + threadCreate(&entity->pdusession_thread, sdap_tun_read_thread, entity, "gnb_tun_read_thread", -1, OAI_PRIORITY_RT_LOW); } void start_sdap_tun_ue(ue_id_t ue_id, int pdu_session_id, int sock) { nr_sdap_entity_t *entity = nr_sdap_get_entity(ue_id, pdu_session_id); DevAssert(entity != NULL); + DevAssert(!entity->is_gnb); entity->pdusession_sock = sock; entity->stop_thread = false; char thread_name[64]; snprintf(thread_name, sizeof(thread_name), "ue_tun_read_%ld_p%d", ue_id, pdu_session_id); - struct thread_args *ta = calloc_or_fail(1, sizeof(*ta)); - ta->entity = entity; - ta->is_gnb = false; - threadCreate(&entity->pdusession_thread, sdap_tun_read_thread, ta, thread_name, -1, OAI_PRIORITY_RT_LOW); + threadCreate(&entity->pdusession_thread, sdap_tun_read_thread, entity, thread_name, -1, OAI_PRIORITY_RT_LOW); } @@ -201,7 +189,7 @@ void create_ue_ip_if(const char *ipv4, const char *ipv6, int ue_id, int pdu_sess start_sdap_tun_ue(ue_id, pdu_session_id, sock); // interface name suffix is ue_id+1 } -void remove_ue_ip_if(nr_sdap_entity_t *entity) +void remove_ip_if(nr_sdap_entity_t *entity) { DevAssert(entity != NULL); // Stop the read thread @@ -211,6 +199,11 @@ void remove_ue_ip_if(nr_sdap_entity_t *entity) // Bring down the IP interface int default_pdu = get_softmodem_params()->default_pdu_session_id; char ifname[IFNAMSIZ]; - tun_generate_ue_ifname(ifname, entity->ue_id, entity->pdusession_id != default_pdu ? entity->pdusession_id : -1); + if (entity->is_gnb) { + char *ifprefix = get_softmodem_params()->nsa ? "oaitun_gnb" : "oaitun_enb"; + tun_generate_ifname(ifname, ifprefix, entity->ue_id - 1); + } else { + tun_generate_ue_ifname(ifname, entity->ue_id, entity->pdusession_id != default_pdu ? entity->pdusession_id : -1); + } tun_destroy(ifname, entity->pdusession_sock); } diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index aa6ee95b47..67238e7001 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -502,6 +502,7 @@ nr_sdap_entity_t *new_nr_sdap_entity(int is_gnb, sdap_entity->ue_id = ue_id; sdap_entity->pdusession_id = pdusession_id; + sdap_entity->is_gnb = is_gnb; sdap_entity->tx_entity = nr_sdap_tx_entity; sdap_entity->rx_entity = nr_sdap_rx_entity; @@ -600,8 +601,8 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) if (entityPtr->ue_id == ue_id && entityPtr->pdusession_id == pdusession_id) { entityPrev->next_entity = entityPtr->next_entity; - if (entityPrev->pdusession_sock != -1) { - remove_ue_ip_if(entityPrev); + if (entityPtr->pdusession_sock != -1) { + remove_ip_if(entityPtr); } free(entityPtr); LOG_D(SDAP, "Successfully deleted Entity.\n"); diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.h b/openair2/SDAP/nr_sdap/nr_sdap_entity.h index adfc48e663..3a42c6c076 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.h +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.h @@ -80,6 +80,9 @@ void nr_pdcp_submit_sdap_ctrl_pdu(ue_id_t ue_id, rb_id_t sdap_ctrl_pdu_drb, nr_s typedef struct nr_sdap_entity_s { ue_id_t ue_id; rb_id_t default_drb; + /// sdap_tun_read_thread needs to know if we are gNB/UE, so for noS1 mode, + /// store which one we are + bool is_gnb; int pdusession_id; int pdusession_sock; pthread_t pdusession_thread; @@ -218,5 +221,5 @@ bool is_sdap_tx(bool is_gnb, NR_SDAP_Config_t *sdap_config); void nr_reconfigure_sdap_entity(NR_SDAP_Config_t *sdap_config, ue_id_t ue_id, int pdusession_id, int drb_id); void set_qfi(uint8_t qfi, uint8_t pduid, ue_id_t ue_id); -void remove_ue_ip_if(nr_sdap_entity_t *entity); +void remove_ip_if(nr_sdap_entity_t *entity); #endif From 8a7987812a08bb773bf428db6a38d05523b63bb7 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 24 Apr 2025 16:10:24 +0200 Subject: [PATCH 21/25] Stop SDAP/noS1 interface in all cases reliably --- openair2/SDAP/nr_sdap/nr_sdap_entity.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/openair2/SDAP/nr_sdap/nr_sdap_entity.c b/openair2/SDAP/nr_sdap/nr_sdap_entity.c index 67238e7001..d93a508c33 100644 --- a/openair2/SDAP/nr_sdap/nr_sdap_entity.c +++ b/openair2/SDAP/nr_sdap/nr_sdap_entity.c @@ -588,6 +588,8 @@ bool nr_sdap_delete_entity(ue_id_t ue_id, int pdusession_id) if (entityPtr->ue_id == ue_id && entityPtr->pdusession_id == pdusession_id) { sdap_info.sdap_entity_llist = sdap_info.sdap_entity_llist->next_entity; + if (entityPtr->pdusession_sock != -1) + remove_ip_if(entityPtr); free(entityPtr); LOG_D(SDAP, "Successfully deleted Entity.\n"); ret = true; @@ -628,6 +630,8 @@ bool nr_sdap_delete_ue_entities(ue_id_t ue_id) /* Handle scenario where ue_id matches the head of the list */ while (entityPtr != NULL && entityPtr->ue_id == ue_id && upperBound < MAX_DRBS_PER_UE) { sdap_info.sdap_entity_llist = entityPtr->next_entity; + if (entityPtr->pdusession_sock != -1) + remove_ip_if(entityPtr); free(entityPtr); entityPtr = sdap_info.sdap_entity_llist; ret = true; @@ -639,6 +643,8 @@ bool nr_sdap_delete_ue_entities(ue_id_t ue_id) entityPtr = entityPtr->next_entity; } else { entityPrev->next_entity = entityPtr->next_entity; + if (entityPtr->pdusession_sock != -1) + remove_ip_if(entityPtr); free(entityPtr); entityPtr = entityPrev->next_entity; LOG_I(SDAP, "Successfully deleted SDAP entity for UE %ld\n", ue_id); From b9edba2186104beba90a156c926f7917c3a2ff8d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 17 Apr 2025 17:21:58 +0200 Subject: [PATCH 22/25] Reimplement NSA release using F1 The RLC function is not used, this is handled at the DU. --- openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c | 6 --- openair2/RRC/NR/nr_rrc_proto.h | 3 +- openair2/RRC/NR/rrc_gNB.c | 19 +++++++-- openair2/RRC/NR/rrc_gNB_nsa.c | 57 ++++++++++--------------- 4 files changed, 39 insertions(+), 46 deletions(-) diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 94079dada8..f1f06b2d56 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -899,12 +899,6 @@ void nr_rlc_remove_ue(int ue_id) nr_rlc_manager_unlock(nr_rlc_ue_manager); } -rlc_op_status_t rrc_rlc_remove_ue (const protocol_ctxt_t* const x) -{ - nr_rlc_remove_ue(x->rntiMaybeUEid); - return RLC_OP_STATUS_OK; -} - bool nr_rlc_update_id(int from_id, int to_id) { nr_rlc_manager_lock(nr_rlc_ue_manager); diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index a06ef76581..b8aab08edb 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -43,8 +43,9 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m); void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp); +void rrc_release_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context); +void rrc_remove_nsa_user_context(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context); -void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti); void rrc_remove_ue(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p); int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index aecf702f8d..b7e452fd73 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2028,16 +2028,27 @@ void rrc_gNB_process_initial_ul_rrc_message(sctp_assoc_t assoc_id, const f1ap_in ASN_STRUCT_FREE(asn_DEF_NR_UL_CCCH_Message, ul_ccch_msg); } +static void rrc_gNB_trigger_nsa_release(module_id_t mod_id, int ue_id) +{ + gNB_RRC_INST *rrc = RC.nrrrc[mod_id]; + rrc_gNB_ue_context_t *ue_context = rrc_gNB_get_ue_context(rrc, ue_id); + if (!ue_context) { + LOG_E(NR_RRC, "could not find UE for ID %d\n", ue_id); + return; + } + rrc_release_nsa_user(rrc, ue_context); +} + void rrc_gNB_process_release_request(const module_id_t gnb_mod_idP, x2ap_ENDC_sgnb_release_request_t *m) { - gNB_RRC_INST *rrc = RC.nrrrc[gnb_mod_idP]; - rrc_remove_nsa_user(rrc, m->rnti); + /* it's not the RNTI, it's the UE ID ... */ + rrc_gNB_trigger_nsa_release(gnb_mod_idP, m->rnti); } void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC_dc_overall_timeout_t *m) { - gNB_RRC_INST *rrc = RC.nrrrc[gnb_mod_idP]; - rrc_remove_nsa_user(rrc, m->rnti); + /* it's not the RNTI, it's the UE ID ... */ + rrc_gNB_trigger_nsa_release(gnb_mod_idP, m->rnti); } /* \brief fill E1 bearer modification's DRB from F1 DRB diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index b2f0991da3..2683f10a41 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -61,6 +61,7 @@ #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h" #include "openair3/SECU/key_nas_deriver.h" +#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h" #include "rrc_gNB_du.h" #include "rlc.h" #include "s1ap_messages_types.h" @@ -400,40 +401,26 @@ void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_co ASN_STRUCT_FREE(asn_DEF_NR_CG_Config, CG_Config); } -void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti) { - protocol_ctxt_t ctxt; - rrc_gNB_ue_context_t *ue_context; - int e_rab; +void rrc_remove_nsa_user_context(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context) +{ + if (!IS_SOFTMODEM_NOS1) + gtpv1u_delete_all_s1u_tunnel(rrc->module_id, ue_context->ue_context.rrc_ue_id); + // we don't use E1 => we have to free SDAP + nr_sdap_delete_ue_entities(ue_context->ue_context.rrc_ue_id); + rrc_remove_ue(rrc, ue_context); +} - LOG_D(RRC, "calling rrc_remove_nsa_user rnti %x\n", rnti); - PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, rrc->module_id, GNB_FLAG_YES, rnti, 0, 0, rrc->module_id); - - ue_context = rrc_gNB_get_ue_context_by_rnti_any_du(rrc, rnti); - if (ue_context == NULL) { - LOG_W(RRC, "rrc_remove_nsa_user: rnti %x not found\n", rnti); - return; - } - - nr_pdcp_remove_UE(ue_context->ue_context.rrc_ue_id); - rrc_rlc_remove_ue(&ctxt); - - // lock the scheduler before removing the UE. Note: mac_remove_nr_ue() checks - // that the scheduler is actually locked! - NR_SCHED_LOCK(&RC.nrmac[rrc->module_id]->sched_lock); - mac_remove_nr_ue(RC.nrmac[rrc->module_id], rnti); - NR_SCHED_UNLOCK(&RC.nrmac[rrc->module_id]->sched_lock); - gtpv1u_enb_delete_tunnel_req_t tmp={0}; - tmp.rnti=rnti; - tmp.from_gnb=1; - LOG_D(RRC, "ue_context->ue_context.nb_of_e_rabs %d will be deleted for rnti %x\n", ue_context->ue_context.nb_of_e_rabs, rnti); - for (e_rab = 0; e_rab < ue_context->ue_context.nb_of_e_rabs; e_rab++) { - tmp.eps_bearer_id[tmp.num_erab++]= ue_context->ue_context.nsa_gtp_ebi[e_rab]; - // erase data - ue_context->ue_context.nsa_gtp_teid[e_rab] = 0; - memset(&ue_context->ue_context.nsa_gtp_addrs[e_rab], 0, sizeof(ue_context->ue_context.nsa_gtp_addrs[e_rab])); - ue_context->ue_context.nsa_gtp_ebi[e_rab] = 0; - } - gtpv1u_delete_all_s1u_tunnel(rrc->module_id, rnti); - /* remove context */ - rrc_gNB_remove_ue_context(rrc, ue_context); +void rrc_release_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context) +{ + gNB_RRC_UE_t *UE = &ue_context->ue_context; + f1_ue_data_t ue_data = cu_get_f1_ue_data(UE->rrc_ue_id); + RETURN_IF_INVALID_ASSOC_ID(ue_data.du_assoc_id); + f1ap_ue_context_release_cmd_t cmd = { + .gNB_CU_ue_id = UE->rrc_ue_id, + .gNB_DU_ue_id = ue_data.secondary_ue, + .cause = F1AP_CAUSE_RADIO_NETWORK, + .cause_value = 10, // 10 = F1AP_CauseRadioNetwork_normal_release + }; + rrc->mac_rrc.ue_context_release_command(ue_data.du_assoc_id, &cmd); + rrc_remove_nsa_user_context(rrc, ue_context); } From b4a7a1a194777d294c464540f16191b5ca60676f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 3 Apr 2025 12:46:58 +0200 Subject: [PATCH 23/25] Allow F1 to be used in do-ra This is preparatory work to allow NSA-like modes to be used over F1 in the future. Notably, it fills the F1 message for UE context setup with GTP TEID, and fills additional information to "make the F1 encoder happy" (fill in QFI etc). Also, provide some F1 fixes to make this work. Remove stale UE connections, if relevant. --- openair2/F1AP/f1ap_cu_ue_context_management.c | 4 +- openair2/F1AP/f1ap_du_ue_context_management.c | 5 ++ openair2/RRC/NR/mac_rrc_dl_f1ap.c | 9 ++- openair2/RRC/NR/nr_rrc_proto.h | 2 +- openair2/RRC/NR/rrc_gNB.c | 3 +- openair2/RRC/NR/rrc_gNB_du.c | 15 ++++- openair2/RRC/NR/rrc_gNB_nsa.c | 55 +++++++++++++++++-- 7 files changed, 82 insertions(+), 11 deletions(-) diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index d171afaacb..f4bffe6144 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -262,11 +262,13 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu if (f1ap_ue_context_setup_req->cu_to_du_rrc_information!=NULL) { /* optional */ /* 6.1 cG_ConfigInfo */ - if(f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo!=NULL){ + if(f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo_length > 0) { + DevAssert(f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo != NULL); asn1cCalloc(ie6->value.choice.CUtoDURRCInformation.cG_ConfigInfo, cG_ConfigInfo); OCTET_STRING_fromBuf(cG_ConfigInfo, (const char *)f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo, f1ap_ue_context_setup_req->cu_to_du_rrc_information->cG_ConfigInfo_length); } + /* optional */ /* 6.2 uE_CapabilityRAT_ContainerList */ if(f1ap_ue_context_setup_req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList!=NULL){ diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index 98de177af1..cd9b2865c9 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -178,6 +178,11 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_i f1ap_ue_context_setup_req->cu_to_du_rrc_information = (cu_to_du_rrc_information_t *)calloc(1,sizeof(cu_to_du_rrc_information_t)); cu_to_du_rrc_information_t *cu2du = f1ap_ue_context_setup_req->cu_to_du_rrc_information; const F1AP_CUtoDURRCInformation_t *cu2duie = &ieCuRrcInfo->value.choice.CUtoDURRCInformation; + if (cu2duie->cG_ConfigInfo != NULL) { + cu2du->cG_ConfigInfo = malloc_or_fail(cu2duie->cG_ConfigInfo->size); + cu2du->cG_ConfigInfo_length = cu2duie->cG_ConfigInfo->size; + memcpy(cu2du->cG_ConfigInfo, cu2duie->cG_ConfigInfo->buf, cu2du->cG_ConfigInfo_length); + } if(cu2duie->uE_CapabilityRAT_ContainerList!=NULL){ cu2du->uE_CapabilityRAT_ContainerList = calloc(1, cu2duie->uE_CapabilityRAT_ContainerList->size); memcpy(cu2du->uE_CapabilityRAT_ContainerList, diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index ff89f61160..9fef2dea58 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -84,9 +84,14 @@ static void ue_context_setup_request_f1ap(sctp_assoc_t assoc_id, const f1ap_ue_c if (req->cu_to_du_rrc_information != NULL) { f1ap_msg->cu_to_du_rrc_information = calloc(1, sizeof(*f1ap_msg->cu_to_du_rrc_information)); AssertFatal(f1ap_msg->cu_to_du_rrc_information != NULL, "out of memory\n"); - AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL && req->cu_to_du_rrc_information->cG_ConfigInfo_length == 0, "cg_ConfigInfo not implemented\n"); - AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL && req->cu_to_du_rrc_information->measConfig_length == 0, "cg_ConfigInfo not implemented\n"); const cu_to_du_rrc_information_t *du2cu_req = req->cu_to_du_rrc_information; + if (req->cu_to_du_rrc_information->cG_ConfigInfo != NULL) { + cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information; + du2cu_new->cG_ConfigInfo_length = du2cu_req->cG_ConfigInfo_length; + du2cu_new->cG_ConfigInfo = malloc_or_fail(du2cu_new->cG_ConfigInfo_length); + memcpy(du2cu_new->cG_ConfigInfo, du2cu_req->cG_ConfigInfo, du2cu_new->cG_ConfigInfo_length); + } + AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL && req->cu_to_du_rrc_information->measConfig_length == 0, "cg_ConfigInfo not implemented\n"); if (req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList != NULL) { cu_to_du_rrc_information_t* du2cu_new = f1ap_msg->cu_to_du_rrc_information; DevAssert(du2cu_req->uE_CapabilityRAT_ContainerList_length > 0); diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h index b8aab08edb..c5627b6e55 100644 --- a/openair2/RRC/NR/nr_rrc_proto.h +++ b/openair2/RRC/NR/nr_rrc_proto.h @@ -41,7 +41,7 @@ #define NR_MAX_SUPPORTED_DL_LAYERS 4 -void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m); +void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_assoc_t assoc_id); void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_context_setup_t *resp); void rrc_release_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context); void rrc_remove_nsa_user_context(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context); diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index b7e452fd73..13445a8e8d 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -261,7 +261,8 @@ static void rrc_gNB_process_AdditionRequestInformation(const module_id_t gnb_mod { gNB_RRC_INST *rrc = RC.nrrrc[gnb_mod_idP]; AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "NSA, phy_test, and do_ra only work in monolithic\n"); - rrc_add_nsa_user(rrc, m); + sctp_assoc_t assoc_id = -1; // monolithic gNB + rrc_add_nsa_user(rrc, m, assoc_id); } //----------------------------------------------------------------------------- diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index aff74fc984..8aec9a634b 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -440,12 +440,14 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) /* we need to setup one default UE for phy-test and do-ra modes in the MAC */ if (get_softmodem_params()->phy_test > 0 || get_softmodem_params()->do_ra > 0) - rrc_add_nsa_user(rrc, NULL); + rrc_add_nsa_user(rrc, NULL, assoc_id); } static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id) { int count = 0; + seq_arr_t ue_context_to_remove; + seq_arr_init(&ue_context_to_remove, sizeof(rrc_gNB_ue_context_t *)); rrc_gNB_ue_context_t *ue_context_p = NULL; RB_FOREACH(ue_context_p, rrc_nr_ue_tree_s, &rrc->rrc_ue_head) { gNB_RRC_UE_t *UE = &ue_context_p->ue_context; @@ -455,7 +457,7 @@ static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id) nr_rrc_finalize_ho(UE); } f1_ue_data_t ue_data = cu_get_f1_ue_data(ue_id); - if (ue_data.du_assoc_id == assoc_id) { + if (ue_data.du_assoc_id == assoc_id && IS_SA_MODE(get_softmodem_params())) { /* this UE belongs to the DU that disconnected, set du_assoc_id to 0, * meaning DU is offline, then trigger release request */ ue_data.du_assoc_id = 0; @@ -464,8 +466,17 @@ static int invalidate_du_connections(gNB_RRC_INST *rrc, sctp_assoc_t assoc_id) ngap_cause_t cause = {.type = NGAP_CAUSE_RADIO_NETWORK, .value = NGAP_CAUSE_RADIO_NETWORK_RADIO_CONNECTION_WITH_UE_LOST}; rrc_gNB_send_NGAP_UE_CONTEXT_RELEASE_REQ(0, ue_context_p, cause); count++; + } else { + seq_arr_push_back(&ue_context_to_remove, &ue_context_p, sizeof(ue_context_p)); } } + for (int i = 0; i < seq_arr_size(&ue_context_to_remove); ++i) { + /* we retrieve a pointer (=iterator) to the UE context pointer + * (ue_context_p), so dereference once */ + rrc_gNB_ue_context_t *p = *(rrc_gNB_ue_context_t **)seq_arr_at(&ue_context_to_remove, i); + rrc_remove_nsa_user_context(rrc, p); + } + seq_arr_free(&ue_context_to_remove, NULL); return count; } diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index 2683f10a41..120a400bbf 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -71,6 +71,7 @@ #include "x2ap_messages_types.h" #include "xer_decoder.h" #include "xer_encoder.h" +#include "f1ap_common.h" // In case of phy-test and do-ra mode, read UE capabilities directly from file // and put it into a CG-ConfigInfo field @@ -114,16 +115,22 @@ static int cg_config_info_from_ue_cap_file(uint32_t maxlen, uint8_t buf[maxlen]) return (rval.encoded + 7) >> 3; } +static instance_t get_f1_gtp_instance(void) +{ + const f1ap_cudu_inst_t *inst = getCxt(0); + if (!inst) + return -1; // means no F1 + return inst->gtpInst; +} + /* generate prototypes for the tree management functions (RB_INSERT used in rrc_add_nsa_user) */ RB_PROTOTYPE(rrc_nr_ue_tree_s, rrc_gNB_ue_context_s, entries, rrc_gNB_compare_ue_rnti_id); -void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m) +void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m, sctp_assoc_t assoc_id) { AssertFatal(!IS_SA_MODE(get_softmodem_params()), "%s() cannot be called in SA mode, it is intrinsically for NSA\n", __func__); - AssertFatal(NODE_IS_MONOLITHIC(rrc->node_type), "NSA, phy_test and do_ra only work in monolithic\n"); - sctp_assoc_t assoc_id = -1; /* integrated DU, hardcoded: if multiple we would not know what to do? */ /* all the 0 are DU-related info that we will fill later, see rrc_add_nsa_user_resp() below */ rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_create_ue_context(assoc_id, 0, rrc, 0, 0); gNB_RRC_UE_t *UE = &ue_context_p->ue_context; @@ -273,12 +280,36 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, x2ap_ENDC_sgnb_addition_req_t *m) /* assumption: only a single bearer, see above */ NR_DRB_ToAddModList_t *rb_list = UE->rb_config->drb_ToAddModList; AssertFatal(rb_list->list.count == 1, "can only handle one bearer for NSA/phy-test/do-ra, but has %d\n", rb_list->list.count); + int drb_id = rb_list->list.array[0]->drb_Identity; + f1ap_flows_mapped_to_drb_t *flow = calloc(1, sizeof(f1ap_flows_mapped_to_drb_t)); + flow->qos_params.qos_characteristics.qos_type = NON_DYNAMIC; + flow->qfi = flow->qos_params.qos_characteristics.non_dynamic.fiveqi = 9; f1ap_drb_to_be_setup_t drbs = { - .drb_id = rb_list->list.array[0]->drb_Identity, + .drb_id = drb_id, .rlc_mode = F1AP_RLC_MODE_UM_BIDIR, // hardcoded keep it backwards compatible for now // rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM, .up_ul_tnl_length = 1, + .drb_info.flows_to_be_setup_length = 1, + .drb_info.flows_mapped_to_drb = flow, }; + // Note: E1 support for NSA/phy-test/do-ra not implemented yet + instance_t f1inst = get_f1_gtp_instance(); + if (f1inst >= 0) { + gtpv1u_gnb_create_tunnel_req_t req = { + .ue_id = UE->rrc_ue_id, + .incoming_rb_id[0] = drb_id, + .pdusession_id[0] = drb_id, + .outgoing_teid[0] = 0xffff, // will be updated later + .dst_addr[0].length = 32, + .num_tunnels = 1, + }; + gtpv1u_gnb_create_tunnel_resp_t resp = {0}; + int ret = gtpv1u_create_ngu_tunnel(f1inst, &req, &resp, NULL, NULL); + AssertFatal(ret == 0, "gtpv1u_create_ngu_tunnel failed: ret %d\n", ret); + drbs.up_ul_tnl[0].port = rrc->eth_params_s.my_portd; + memcpy(&drbs.up_ul_tnl[0].tl_address, &resp.gnb_addr.buffer, 4); + drbs.up_ul_tnl[0].teid = resp.gnb_NGu_teid[0]; + } f1ap_ue_context_setup_t req = { .gNB_CU_ue_id = UE->rrc_ue_id, .gNB_DU_ue_id = 0xffffffff, /* not known yet */ @@ -363,6 +394,19 @@ void rrc_add_nsa_user_resp(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, const f1ap_ue_co bool success = cu_update_f1_ue_data(UE->rrc_ue_id, &ue_data); DevAssert(success); + instance_t f1inst = get_f1_gtp_instance(); + if (f1inst >= 0) { + // Note: E1 support for NSA/phy-test/do-ra not implemented yet + // so set up GTP from here + for (int i = 0; i < resp->drbs_to_be_setup_length; ++i) { + f1ap_drb_to_be_setup_t *drb = &resp->drbs_to_be_setup[i]; + DevAssert(drb->up_dl_tnl_length == 1); + in_addr_t addr = drb->up_dl_tnl[0].tl_address; + uint32_t teid = drb->up_dl_tnl[0].teid; + GtpuUpdateTunnelOutgoingAddressAndTeid(f1inst, UE->rrc_ue_id, drb->drb_id, addr, teid); + } + } + NR_RRCReconfiguration_t *reconfig = calloc(1, sizeof(NR_RRCReconfiguration_t)); reconfig->rrc_TransactionIdentifier = 0; reconfig->criticalExtensions.present = NR_RRCReconfiguration__criticalExtensions_PR_rrcReconfiguration; @@ -405,6 +449,9 @@ void rrc_remove_nsa_user_context(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_con { if (!IS_SOFTMODEM_NOS1) gtpv1u_delete_all_s1u_tunnel(rrc->module_id, ue_context->ue_context.rrc_ue_id); + instance_t f1inst = get_f1_gtp_instance(); + if (f1inst >= 0) + gtpv1u_delete_all_s1u_tunnel(f1inst, ue_context->ue_context.rrc_ue_id); // we don't use E1 => we have to free SDAP nr_sdap_delete_ue_entities(ue_context->ue_context.rrc_ue_id); rrc_remove_ue(rrc, ue_context); From 5205d1d4b79589b7ad6734e693686c24caf8b50e Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 24 Apr 2025 11:55:27 +0200 Subject: [PATCH 24/25] Read security only for CU or Monolithic: avoid warning at DU --- openair2/GNB_APP/gnb_config.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 22d9ed6f8a..281bda44ef 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -2136,7 +2136,8 @@ gNB_RRC_INST *RCconfig_NRRRC() openair_rrc_gNB_configuration(rrc, &nrrrc_config); }//End if (num_gnbs>0) - config_security(rrc); + if (!NODE_IS_DU(rrc->node_type)) + config_security(rrc); return rrc; } From 2626dbd24b7ce88aff2f1225445e7d0a81f8f65a Mon Sep 17 00:00:00 2001 From: francescomani Date: Sun, 9 Mar 2025 14:56:41 +0100 Subject: [PATCH 25/25] further adjustment in timing test --- ci-scripts/datalog_rt_stats.100.2x2.yaml | 8 ++++---- ci-scripts/datalog_rt_stats.1x1.60.yaml | 8 ++++---- ci-scripts/datalog_rt_stats.60.2x2.yaml | 6 +++--- ci-scripts/datalog_rt_stats.default.yaml | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ci-scripts/datalog_rt_stats.100.2x2.yaml b/ci-scripts/datalog_rt_stats.100.2x2.yaml index 7b5c8cbbeb..e2bbc6b71d 100644 --- a/ci-scripts/datalog_rt_stats.100.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.100.2x2.yaml @@ -15,10 +15,10 @@ Ref : DLSCH encoding : 220.0 L1 Rx processing : 530.0 PUSCH inner-receiver : 360.0 - Schedule Response : 3.0 - DL & UL scheduling timing : 17.0 - UL Indication : 3.0 - Slot Indication : 17.0 + Schedule Response : 1.0 + DL & UL scheduling timing : 12.0 + UL Indication : 1.0 + Slot Indication : 13.0 DeviationThreshold : feprx : 0.25 feptx_prec : 0.25 diff --git a/ci-scripts/datalog_rt_stats.1x1.60.yaml b/ci-scripts/datalog_rt_stats.1x1.60.yaml index acd8251525..47021b502b 100644 --- a/ci-scripts/datalog_rt_stats.1x1.60.yaml +++ b/ci-scripts/datalog_rt_stats.1x1.60.yaml @@ -15,10 +15,10 @@ Ref : DLSCH encoding : 140.0 L1 Rx processing : 345.0 PUSCH inner-receiver : 150.0 - Schedule Response : 3.0 - DL & UL scheduling timing : 7.0 - UL Indication : 3.0 - Slot Indication : 8.0 + Schedule Response : 1.0 + DL & UL scheduling timing : 5.0 + UL Indication : 1.0 + Slot Indication : 6.0 DeviationThreshold : feprx : 0.25 feptx_prec : 0.25 diff --git a/ci-scripts/datalog_rt_stats.60.2x2.yaml b/ci-scripts/datalog_rt_stats.60.2x2.yaml index a196695c4b..064d6374c1 100644 --- a/ci-scripts/datalog_rt_stats.60.2x2.yaml +++ b/ci-scripts/datalog_rt_stats.60.2x2.yaml @@ -15,10 +15,10 @@ Ref : DLSCH encoding : 155.0 L1 Rx processing : 345.0 PUSCH inner-receiver : 155.0 - Schedule Response : 3.0 - DL & UL scheduling timing : 13.0 + Schedule Response : 1.0 + DL & UL scheduling timing : 8.0 UL Indication : 3.0 - Slot Indication : 12.0 + Slot Indication : 9.0 DeviationThreshold : feprx : 0.25 feptx_prec : 0.25 diff --git a/ci-scripts/datalog_rt_stats.default.yaml b/ci-scripts/datalog_rt_stats.default.yaml index 045768829c..17e45cf367 100644 --- a/ci-scripts/datalog_rt_stats.default.yaml +++ b/ci-scripts/datalog_rt_stats.default.yaml @@ -15,10 +15,10 @@ Ref : DLSCH encoding : 100.0 L1 Rx processing : 290.0 PUSCH inner-receiver : 115.0 - Schedule Response : 3.0 - DL & UL scheduling timing : 6.0 + Schedule Response : 1.0 + DL & UL scheduling timing : 4.0 UL Indication : 2.0 - Slot Indication : 7.0 + Slot Indication : 5.0 DeviationThreshold : feprx : 0.25 feptx_prec : 0.25