From f2a8b5c41d1ae157295c18477f14320c51d32305 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 16 Apr 2023 14:11:11 +0200 Subject: [PATCH 01/18] Remove wrong comment: SRBs are not handled via E1 --- openair2/RRC/NR/rrc_gNB.c | 1 - 1 file changed, 1 deletion(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 2d3628f765..e2eca3b0bd 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -363,7 +363,6 @@ static void rrc_gNB_generate_RRCSetup(instance_t instance, // remove UE after 10 frames after RRCConnectionRelease is triggered ue_context_pP->ue_context.ue_release_timer_thres = 1000; - /* TODO: this should go through the E1 interface */ nr_pdcp_add_srbs(true, rnti, ue_context_pP->ue_context.SRB_configList, 0, NULL, NULL); f1ap_dl_rrc_message_t dl_rrc = { From 6d7d075d8c71e590abd7af6903019233d69e1757 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sat, 22 Apr 2023 09:03:39 +0200 Subject: [PATCH 02/18] Refactor NR MAC config: mark unimplemented functions as such --- openair2/LAYER2/NR_MAC_gNB/config.c | 46 +++++++---------------------- 1 file changed, 11 insertions(+), 35 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 1a72fa951d..95e868d13a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -99,48 +99,28 @@ static void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddMo static void process_drx_Config(NR_UE_sched_ctrl_t *sched_ctrl, NR_SetupRelease_DRX_Config_t *drx_Config) { - - if (!drx_Config) return; - AssertFatal(drx_Config->present != NR_SetupRelease_DRX_Config_PR_NOTHING, "Cannot have NR_SetupRelease_DRX_Config_PR_NOTHING\n"); - - if (drx_Config->present == NR_SetupRelease_DRX_Config_PR_setup) { - LOG_I(NR_MAC,"Adding DRX config\n"); - } - else { - LOG_I(NR_MAC,"Removing DRX config\n"); - } + AssertFatal(false, "%s() not implemented\n", __func__); + AssertFatal(drx_Config->present != NR_SetupRelease_DRX_Config_PR_NOTHING, "Cannot have NR_SetupRelease_DRX_Config_PR_NOTHING\n"); } static void process_schedulingRequestConfig(NR_UE_sched_ctrl_t *sched_ctrl, NR_SchedulingRequestConfig_t *schedulingRequestConfig) { - if (!schedulingRequestConfig) return; - - LOG_I(NR_MAC,"Adding SchedulingRequestconfig\n"); + AssertFatal(false, "%s() not implemented\n", __func__); } static void process_bsrConfig(NR_UE_sched_ctrl_t *sched_ctrl, NR_BSR_Config_t *bsr_Config) { - if (!bsr_Config) return; - LOG_I(NR_MAC,"Adding BSR config\n"); + AssertFatal(false, "%s() not implemented\n", __func__); } static void process_tag_Config(NR_UE_sched_ctrl_t *sched_ctrl, NR_TAG_Config_t *tag_Config) { - if (!tag_Config) return; - LOG_I(NR_MAC,"Adding TAG config\n"); + AssertFatal(false, "%s() not implemented\n", __func__); } static void process_phr_Config(NR_UE_sched_ctrl_t *sched_ctrl, NR_SetupRelease_PHR_Config_t *phr_Config) { - if (!phr_Config) return; - AssertFatal(phr_Config->present != NR_SetupRelease_PHR_Config_PR_NOTHING, "Cannot have NR_SetupRelease_PHR_Config_PR_NOTHING\n"); - - if (phr_Config->present == NR_SetupRelease_PHR_Config_PR_setup) { - LOG_I(NR_MAC,"Adding PHR config\n"); - } - else { - LOG_I(NR_MAC,"Removing PHR config\n"); - } + AssertFatal(false, "%s() not implemented\n", __func__); } void process_CellGroup(NR_CellGroupConfig_t *CellGroup, NR_UE_sched_ctrl_t *sched_ctrl) @@ -149,15 +129,11 @@ void process_CellGroup(NR_CellGroupConfig_t *CellGroup, NR_UE_sched_ctrl_t *sche NR_MAC_CellGroupConfig_t *mac_CellGroupConfig = CellGroup->mac_CellGroupConfig; if (mac_CellGroupConfig) { - process_drx_Config(sched_ctrl,mac_CellGroupConfig->drx_Config); - process_schedulingRequestConfig(sched_ctrl,mac_CellGroupConfig->schedulingRequestConfig); - process_bsrConfig(sched_ctrl,mac_CellGroupConfig->bsr_Config); - process_tag_Config(sched_ctrl,mac_CellGroupConfig->tag_Config); - process_phr_Config(sched_ctrl,mac_CellGroupConfig->phr_Config); - } - else { - // apply defaults - + //process_drx_Config(sched_ctrl,mac_CellGroupConfig->drx_Config); + //process_schedulingRequestConfig(sched_ctrl,mac_CellGroupConfig->schedulingRequestConfig); + //process_bsrConfig(sched_ctrl,mac_CellGroupConfig->bsr_Config); + //process_tag_Config(sched_ctrl,mac_CellGroupConfig->tag_Config); + //process_phr_Config(sched_ctrl,mac_CellGroupConfig->phr_Config); } process_rlcBearerConfig(CellGroup->rlc_BearerToAddModList,CellGroup->rlc_BearerToReleaseList,sched_ctrl); From 2a0142fb965fdd0c7cde9a6a29c642e64ce54b09 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 12 Apr 2023 16:32:32 +0200 Subject: [PATCH 03/18] Suppress any CellGroupConfig updates in F1 The CellGroupConfig should come from the DU. Currently, any update made to the CellGroupConfig is done at CU. In split-operation, we have no way of telling the DU about this update. Hence, in this commit, check if we are in F1 split mode operation during a CellGroupConfig update, and if so, suppress any updates to the CellGroupConfig, alongside a warning. --- openair2/RRC/NR/nr_rrc_config.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index 6626fc2240..6b5de8188d 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -2326,6 +2326,8 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid, return cellGroupConfig; } +#include "common/ran_context.h" +#include "nr_rrc_defs.h" void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, const int uid, NR_UE_NR_Capability_t *uecap, @@ -2341,6 +2343,13 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, return; DevAssert(configuration->scc != NULL); + /* This is a hack and will be removed once the CellGroupConfig is fully + * handled at the DU */ + if (NODE_IS_CU(RC.nrrrc[0]->node_type)) { + LOG_W(RRC, "update of CellGroupConfig not yet supported in F1\n"); + return; + } + NR_SpCellConfig_t *SpCellConfig = cellGroupConfig->spCellConfig; NR_ServingCellConfigCommon_t *scc = configuration->scc; From e7a8eb950e2c2bb562d7c1a31af177bf449cfc25 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 24 Apr 2023 18:48:13 +0200 Subject: [PATCH 04/18] NR MAC: make many functions static To know which functions are used from outside and which are module-local, make many functions static. This will allow us to protect only those functions with a mutex for which it is necessary. --- openair2/LAYER2/NR_MAC_gNB/config.c | 4 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 273 ++++++++++-------- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 78 +++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 37 ++- .../NR_MAC_gNB/gNB_scheduler_primitives.c | 2 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c | 20 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 133 ++++----- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 107 +++---- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 82 ------ 9 files changed, 338 insertions(+), 398 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 95e868d13a..861c392a54 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -140,8 +140,8 @@ void process_CellGroup(NR_CellGroupConfig_t *CellGroup, NR_UE_sched_ctrl_t *sche } -void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch_AntennaPorts, NR_ServingCellConfigCommon_t *scc) { - +static void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch_AntennaPorts, NR_ServingCellConfigCommon_t *scc) +{ nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0]; nrmac->common_channels[0].ServingCellConfigCommon = scc; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 2461d9618d..3beaac6c6b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -49,17 +49,32 @@ extern RAN_CONTEXT_t RC; extern const uint8_t nr_slots_per_frame[5]; extern uint16_t sl_ahead; +// 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, + int round, + int startSymbolAndLength, + rnti_t rnti, + int scs, + int bwp_size, + int bwp_start, + int mappingtype, + int fh, + int msg3_first_rb, + int msg3_nb_rb); +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 const uint8_t DELTA[4] = {2, 3, 4, 6}; static const float ssb_per_rach_occasion[8] = {0.125, 0.25, 0.5, 1, 2, 4, 8}; -int16_t ssb_index_from_prach(module_id_t module_idP, - frame_t frameP, - sub_frame_t slotP, - uint16_t preamble_index, - uint8_t freq_index, - uint8_t symbol) { - +static int16_t ssb_index_from_prach(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + uint16_t preamble_index, + uint8_t freq_index, + uint8_t symbol) +{ gNB_MAC_INST *gNB = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &gNB->common_channels[0]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -399,15 +414,20 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP } } -void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot, - uint16_t *msg2_frame, uint16_t *msg2_slot, - int mu, NR_ServingCellConfigCommon_t *scc, - frame_type_t frame_type, - uint16_t monitoring_slot_period, - uint16_t monitoring_offset,uint8_t beam_index, - uint8_t num_active_ssb, - int16_t *tdd_beam_association, int sl_ahead){ - +static void nr_schedule_msg2(uint16_t rach_frame, + uint16_t rach_slot, + uint16_t *msg2_frame, + uint16_t *msg2_slot, + int mu, + NR_ServingCellConfigCommon_t *scc, + frame_type_t frame_type, + uint16_t monitoring_slot_period, + uint16_t monitoring_offset, + uint8_t beam_index, + uint8_t num_active_ssb, + int16_t *tdd_beam_association, + int sl_ahead) +{ // preferentially we schedule the msg2 in the mixed slot or in the last dl slot // if they are allowed by search space configuration uint8_t response_window = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow; @@ -662,50 +682,12 @@ void nr_initiate_ra_proc(module_id_t module_idP, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0); } -void nr_schedule_RA(module_id_t module_idP, - frame_t frameP, - sub_frame_t slotP, - nfapi_nr_ul_dci_request_t *ul_dci_req, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req) -{ - gNB_MAC_INST *mac = RC.nrmac[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]; - LOG_D(NR_MAC, "RA[state:%d]\n", ra->state); - switch (ra->state) { - case Msg2: - nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); - break; - case Msg3_retransmission: - nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req); - break; - case Msg3_dcch_dtch: - nr_generate_Msg3_dcch_dtch_response(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); - case Msg4: - nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); - break; - case WAIT_Msg4_ACK: - nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP, ra); - break; - default: - break; - } - } - } - stop_meas(&mac->schedule_ra); -} - -void nr_generate_Msg3_retransmission(module_id_t module_idP, - int CC_id, - frame_t frame, - sub_frame_t slot, - NR_RA_t *ra, - nfapi_nr_ul_dci_request_t *ul_dci_req) +static void nr_generate_Msg3_retransmission(module_id_t module_idP, + int CC_id, + frame_t frame, + sub_frame_t slot, + NR_RA_t *ra, + nfapi_nr_ul_dci_request_t *ul_dci_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; @@ -877,15 +859,14 @@ void nr_generate_Msg3_retransmission(module_id_t module_idP, } } -void nr_get_Msg3alloc(module_id_t module_id, - int CC_id, - NR_ServingCellConfigCommon_t *scc, - sub_frame_t current_slot, - frame_t current_frame, - NR_RA_t *ra, - int16_t *tdd_beam_association) +static void nr_get_Msg3alloc(module_id_t module_id, + int CC_id, + NR_ServingCellConfigCommon_t *scc, + sub_frame_t current_slot, + frame_t current_frame, + NR_RA_t *ra, + int16_t *tdd_beam_association) { - // msg3 is scheduled in mixed slot in the following TDD period uint16_t msg3_nb_rb = 8; // sdu has 6 or 8 bytes @@ -999,16 +980,19 @@ void nr_get_Msg3alloc(module_id_t module_id, ra->msg3_bwp_start = bwpStart; } - -void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, - NR_ServingCellConfigCommon_t *scc, - int round, - int startSymbolAndLength, - rnti_t rnti, int scs, - int bwp_size, int bwp_start, - int mappingtype, int fh, - int msg3_first_rb, int msg3_nb_rb) { - +static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, + NR_ServingCellConfigCommon_t *scc, + int round, + int startSymbolAndLength, + rnti_t rnti, + int scs, + int bwp_size, + int bwp_start, + int mappingtype, + int fh, + int msg3_first_rb, + int msg3_nb_rb) +{ int start_symbol_index,nr_of_symbols; SLIV2SL(startSymbolAndLength, &start_symbol_index, &nr_of_symbols); @@ -1087,7 +1071,7 @@ void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, } } -void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_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, sub_frame_t slotP, NR_RA_t *ra, uint8_t *RAR_pdu) { gNB_MAC_INST *mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &mac->common_channels[CC_id]; @@ -1155,13 +1139,14 @@ void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t nr_fill_rar(module_idP, ra, RAR_pdu, pusch_pdu); } -void nr_generate_Msg2(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - NR_RA_t *ra, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req) + +static void nr_generate_Msg2(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + 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]; @@ -1427,22 +1412,29 @@ void nr_generate_Msg2(module_id_t module_idP, } } -void prepare_dl_pdus(gNB_MAC_INST *nr_mac, - NR_RA_t *ra, - NR_UE_DL_BWP_t *dl_bwp, - nfapi_nr_dl_tti_request_body_t *dl_req, - NR_sched_pucch_t *pucch, - NR_pdsch_dmrs_t dmrs_info, - NR_tda_info_t tda, - int aggregation_level, - int CCEIndex, - int tb_size, int ndi, - int tpc, int delta_PRI, - int current_harq_pid, - int time_domain_assignment, - int CC_id, int rnti, int round, - int mcsIndex, int tb_scaling, - int pduindex, int rbStart, int rbSize) +static void prepare_dl_pdus(gNB_MAC_INST *nr_mac, + NR_RA_t *ra, + NR_UE_DL_BWP_t *dl_bwp, + nfapi_nr_dl_tti_request_body_t *dl_req, + NR_sched_pucch_t *pucch, + NR_pdsch_dmrs_t dmrs_info, + NR_tda_info_t tda, + int aggregation_level, + int CCEIndex, + int tb_size, + int ndi, + int tpc, + int delta_PRI, + int current_harq_pid, + int time_domain_assignment, + int CC_id, + int rnti, + int round, + int mcsIndex, + int tb_scaling, + int pduindex, + int rbStart, + int rbSize) { // 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 @@ -1613,13 +1605,13 @@ void prepare_dl_pdus(gNB_MAC_INST *nr_mac, LOG_D(NR_MAC,"numDlDci: %i\n", pdcch_pdu_rel15->numDlDci); } -void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - NR_RA_t *ra, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req) +static void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + 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]; @@ -1799,13 +1791,13 @@ void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, sched_ctrl->ul_failure = 0; } -void nr_generate_Msg4(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - NR_RA_t *ra, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req) +static void nr_generate_Msg4(module_id_t module_idP, + int CC_id, + frame_t frameP, + sub_frame_t slotP, + NR_RA_t *ra, + 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]; @@ -2056,8 +2048,8 @@ void nr_generate_Msg4(module_id_t module_idP, } } -void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra) { - +static void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra) +{ NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, ra->rnti); const int current_harq_pid = ra->harq_pid; @@ -2141,11 +2133,8 @@ void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t // - sending only 1 RAR subPDU // - UL Grant: hardcoded CSI, TPC, time alloc // - padding -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_RA_t *ra, 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_HEADER_BI *rarbi = (NR_RA_HEADER_BI *) dlsch_buffer; NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) (dlsch_buffer + 1); @@ -2239,3 +2228,41 @@ void nr_fill_rar(uint8_t Mod_idP, csi_req, t_crnti); } + +void nr_schedule_RA(module_id_t module_idP, + frame_t frameP, + sub_frame_t slotP, + nfapi_nr_ul_dci_request_t *ul_dci_req, + nfapi_nr_dl_tti_request_t *DL_req, + nfapi_nr_tx_data_request_t *TX_req) +{ + gNB_MAC_INST *mac = RC.nrmac[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]; + LOG_D(NR_MAC, "RA[state:%d]\n", ra->state); + switch (ra->state) { + case Msg2: + nr_generate_Msg2(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); + break; + case Msg3_retransmission: + nr_generate_Msg3_retransmission(module_idP, CC_id, frameP, slotP, ra, ul_dci_req); + break; + case Msg3_dcch_dtch: + nr_generate_Msg3_dcch_dtch_response(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); + case Msg4: + nr_generate_Msg4(module_idP, CC_id, frameP, slotP, ra, DL_req, TX_req); + break; + case WAIT_Msg4_ACK: + nr_check_Msg4_Ack(module_idP, CC_id, frameP, slotP, ra); + break; + default: + break; + } + } + } + stop_meas(&mac->schedule_ra); +} diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index f6d1f83e35..bc5710e2ec 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -51,11 +51,15 @@ extern RAN_CONTEXT_t RC; -void schedule_ssb(frame_t frame, sub_frame_t slot, - NR_ServingCellConfigCommon_t *scc, - nfapi_nr_dl_tti_request_body_t *dl_req, - int i_ssb, uint8_t scoffset, uint16_t offset_pointa, uint32_t payload) { - +static void schedule_ssb(frame_t frame, + sub_frame_t slot, + NR_ServingCellConfigCommon_t *scc, + nfapi_nr_dl_tti_request_body_t *dl_req, + int i_ssb, + uint8_t scoffset, + uint16_t offset_pointa, + uint32_t payload) +{ uint8_t beam_index = 0; nfapi_nr_dl_tti_request_pdu_t *dl_config_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs]; memset((void *) dl_config_pdu, 0,sizeof(nfapi_nr_dl_tti_request_pdu_t)); @@ -86,7 +90,19 @@ void schedule_ssb(frame_t frame, sub_frame_t slot, dl_req->nPDUs++; LOG_D(MAC,"Scheduling ssb %d at frame %d and slot %d\n",i_ssb,frame,slot); +} +static void fill_ssb_vrb_map(NR_COMMON_channels_t *cc, int rbStart, int ssb_subcarrier_offset, uint16_t symStart, int CC_id) +{ + AssertFatal(*cc->ServingCellConfigCommon->ssbSubcarrierSpacing != + NR_SubcarrierSpacing_kHz240, + "240kHZ subcarrier won't work with current VRB map because a single SSB might be across 2 slots\n"); + + uint16_t *vrb_map = cc[CC_id].vrb_map; + + const int extra_prb = ssb_subcarrier_offset > 0; + for (int rb = 0; rb < 20+extra_prb; rb++) + vrb_map[rbStart + rb] = SL_to_bitmap(symStart, 4); } void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, nfapi_nr_dl_tti_request_t *DL_req) @@ -254,33 +270,15 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, } } -void schedule_nr_SI(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP) { -//---------------------------------------- -} - -void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, int ssb_subcarrier_offset, uint16_t symStart, int CC_id) { - - AssertFatal(*cc->ServingCellConfigCommon->ssbSubcarrierSpacing != - NR_SubcarrierSpacing_kHz240, - "240kHZ subcarrier won't work with current VRB map because a single SSB might be across 2 slots\n"); - - uint16_t *vrb_map = cc[CC_id].vrb_map; - - const int extra_prb = ssb_subcarrier_offset > 0; - for (int rb = 0; rb < 20+extra_prb; rb++) - vrb_map[rbStart + rb] = SL_to_bitmap(symStart, 4); - -} - -uint32_t schedule_control_sib1(module_id_t module_id, - int CC_id, - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, - int time_domain_allocation, - NR_pdsch_dmrs_t *dmrs_parms, - NR_tda_info_t *tda_info, - uint8_t candidate_idx, - uint16_t num_total_bytes) { - +static uint32_t schedule_control_sib1(module_id_t module_id, + int CC_id, + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, + int time_domain_allocation, + NR_pdsch_dmrs_t *dmrs_parms, + NR_tda_info_t *tda_info, + uint8_t candidate_idx, + uint16_t num_total_bytes) +{ gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; @@ -377,14 +375,14 @@ uint32_t schedule_control_sib1(module_id_t module_id, return TBS; } -void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, - nfapi_nr_dl_tti_request_body_t *dl_req, - int pdu_index, - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, - uint32_t TBS, - int StartSymbolIndex, - int NrOfSymbols) { - +static void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, + nfapi_nr_dl_tti_request_body_t *dl_req, + int pdu_index, + NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, + uint32_t TBS, + int StartSymbolIndex, + int NrOfSymbols) +{ gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP]; NR_COMMON_channels_t *cc = gNB_mac->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 71b4499c55..846a7a35f0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -311,10 +311,8 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, return offset; } -void nr_store_dlsch_buffer(module_id_t module_id, - frame_t frame, - sub_frame_t slot) { - +static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_frame_t slot) +{ UE_iterator(RC.nrmac[module_id]->UE_info.list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; sched_ctrl->num_total_bytes = 0; @@ -375,13 +373,13 @@ void abort_nr_dl_harq(NR_UE_info_t* UE, int8_t harq_pid) { } -bool allocate_dl_retransmission(module_id_t module_id, - frame_t frame, - sub_frame_t slot, - uint16_t *rballoc_mask, - int *n_rb_sched, - NR_UE_info_t *UE, - int current_harq_pid) +static bool allocate_dl_retransmission(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + uint16_t *rballoc_mask, + int *n_rb_sched, + NR_UE_info_t *UE, + int current_harq_pid) { int CC_id = 0; @@ -549,15 +547,14 @@ static int comparator(const void *p, const void *q) { return ((UEsched_t*)p)->coef < ((UEsched_t*)q)->coef; } -void pf_dl(module_id_t module_id, - frame_t frame, - sub_frame_t slot, - NR_UE_info_t **UE_list, - int max_num_ue, - int n_rb_sched, - uint16_t *rballoc_mask) +static void pf_dl(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + NR_UE_info_t **UE_list, + int max_num_ue, + int n_rb_sched, + uint16_t *rballoc_mask) { - gNB_MAC_INST *mac = RC.nrmac[module_id]; NR_ServingCellConfigCommon_t *scc=mac->common_channels[0].ServingCellConfigCommon; // UEs that could be scheduled @@ -784,7 +781,7 @@ void pf_dl(module_id_t module_id, } } -void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot) +static void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot) { NR_UEs_t *UE_info = &RC.nrmac[module_id]->UE_info; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 0deb86a5db..411a9609c1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -509,7 +509,7 @@ void fill_pdcch_vrb_map(gNB_MAC_INST *mac, } } -bool multiple_2_3_5(int rb) +static bool multiple_2_3_5(int rb) { while (rb % 2 == 0) rb /= 2; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index 8a85448c7f..fd11023387 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -42,7 +42,8 @@ const uint16_t m_SRS[64] = { 4, 8, 12, 16, 16, 20, 24, 24, 28, 32, 36, 40, 48, 4 160, 160, 168, 176, 184, 192, 192, 192, 192, 208, 216, 224, 240, 240, 240, 240, 256, 256, 256, 264, 272, 272, 272 }; -uint32_t max4(uint32_t a, uint32_t b,uint32_t c,uint32_t d) { +static uint32_t max4(uint32_t a, uint32_t b, uint32_t c, uint32_t d) +{ int x = max(a, b); x = max(x, c); x = max(x, d); @@ -137,7 +138,14 @@ void nr_srs_ri_computation(const nfapi_nr_srs_normalized_channel_iq_matrix_t *nr } -void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, int slot, int module_id, int CC_id, NR_UE_info_t *UE, NR_SRS_ResourceSet_t *srs_resource_set, NR_SRS_Resource_t *srs_resource, int buffer_index) +static void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, + int slot, + int module_id, + int CC_id, + NR_UE_info_t *UE, + NR_SRS_ResourceSet_t *srs_resource_set, + NR_SRS_Resource_t *srs_resource, + int buffer_index) { NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP; @@ -196,7 +204,13 @@ void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, int slot, int module_id, int vrb_map_UL[i + srs_pdu->bwp_start] |= mask; } -void nr_fill_nfapi_srs(int module_id, int CC_id, NR_UE_info_t* UE, int frame, int slot, NR_SRS_ResourceSet_t *srs_resource_set, NR_SRS_Resource_t *srs_resource) +static void nr_fill_nfapi_srs(int module_id, + int CC_id, + NR_UE_info_t *UE, + int frame, + int slot, + NR_SRS_ResourceSet_t *srs_resource_set, + NR_SRS_Resource_t *srs_resource) { int index = ul_buffer_index(frame, slot, UE->current_UL_BWP.scs, RC.nrmac[module_id]->UL_tti_req_ahead_size); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index bc1796a6dc..d7ff3c962b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -144,7 +144,7 @@ static const int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = { -30 // 10 - 15 }; -int get_pucch_index(int frame, int slot, int n_slots_frame, const NR_TDD_UL_DL_Pattern_t *tdd, int sched_pucch_size) +static int get_pucch_index(int frame, int slot, int n_slots_frame, const NR_TDD_UL_DL_Pattern_t *tdd, int sched_pucch_size) { // PUCCH structures are indexed by slot in the PUCCH period determined by sched_pucch_size number of UL slots // this functions return the index to the structure for slot passed to the function @@ -324,8 +324,8 @@ static void handle_dl_harq(NR_UE_info_t * UE, } } -int checkTargetSSBInFirst64TCIStates_pdschConfig(int ssb_index_t, NR_UE_info_t * UE) { - +static int checkTargetSSBInFirst64TCIStates_pdschConfig(int ssb_index_t, NR_UE_info_t *UE) +{ const NR_PDSCH_Config_t *pdsch_Config = UE->current_DL_BWP.pdsch_Config; int nb_tci_states = pdsch_Config ? pdsch_Config->tci_StatesToAddModList->list.count : 0; NR_TCI_State_t *tci =NULL; @@ -350,8 +350,8 @@ int checkTargetSSBInFirst64TCIStates_pdschConfig(int ssb_index_t, NR_UE_info_t * return -1; } -int checkTargetSSBInTCIStates_pdcchConfig(int ssb_index_t, NR_UE_info_t *UE) { - +static int checkTargetSSBInTCIStates_pdcchConfig(int ssb_index_t, NR_UE_info_t *UE) +{ NR_TCI_State_t *tci =NULL; NR_TCI_StateId_t *tci_id = NULL; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -390,7 +390,8 @@ int checkTargetSSBInTCIStates_pdcchConfig(int ssb_index_t, NR_UE_info_t *UE) { } //returns the measured RSRP value (upper limit) -int get_measured_rsrp(uint8_t index) { +static int get_measured_rsrp(uint8_t index) +{ //if index is invalid returning minimum rsrp -140 if(index <= 15 || index >= 114) return MIN_RSRP_VALUE; @@ -399,7 +400,7 @@ int get_measured_rsrp(uint8_t index) { } //returns the differential RSRP value (upper limit) -int get_diff_rsrp(uint8_t index, int strongest_rsrp) { +static int get_diff_rsrp(uint8_t index, int strongest_rsrp) { if(strongest_rsrp != -1) { return strongest_rsrp + diff_rsrp_ssb_csi_meas_10_1_6_1_2[index]; } else @@ -409,8 +410,8 @@ int get_diff_rsrp(uint8_t index, int strongest_rsrp) { //identifies the target SSB Beam index //keeps the required date for PDCCH and PDSCH TCI state activation/deactivation CE consutruction globally //handles triggering of PDCCH and PDSCH MAC CEs -void tci_handling(NR_UE_info_t *UE, frame_t frame, slot_t slot) { - +static void tci_handling(NR_UE_info_t *UE, frame_t frame, slot_t slot) +{ int strongest_ssb_rsrp = 0; int cqi_idx = 0; int curr_ssb_beam_index = 0; //ToDo: yet to know how to identify the serving ssb beam index @@ -583,24 +584,23 @@ void tci_handling(NR_UE_info_t *UE, frame_t frame, slot_t slot) { } }//tci_presentInDCI }//is-triggering_beam_switch -}//tci handling +} // tci handling - -uint8_t pickandreverse_bits(uint8_t *payload, uint16_t bitlen, uint8_t start_bit) { +static uint8_t pickandreverse_bits(uint8_t *payload, uint16_t bitlen, uint8_t start_bit) +{ uint8_t rev_bits = 0; for (int i=0; i>((start_bit+i)%8))&0x01)<<(bitlen-i-1); return rev_bits; } - -void evaluate_rsrp_report(NR_UE_info_t *UE, - NR_UE_sched_ctrl_t *sched_ctrl, - uint8_t csi_report_id, - uint8_t *payload, - int *cumul_bits, - NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type){ - +static void evaluate_rsrp_report(NR_UE_info_t *UE, + NR_UE_sched_ctrl_t *sched_ctrl, + uint8_t csi_report_id, + uint8_t *payload, + int *cumul_bits, + NR_CSI_ReportConfig__reportQuantity_PR reportQuantity_type) +{ nr_csi_report_t *csi_report = &UE->csi_report_template[csi_report_id]; uint8_t cri_ssbri_bitlen = csi_report->CSI_report_bitlen.cri_ssbri_bitlen; uint16_t curr_payload; @@ -659,21 +659,18 @@ void evaluate_rsrp_report(NR_UE_info_t *UE, stats->num_rsrp_meas++; } -void evaluate_cri_report(uint8_t *payload, - uint8_t cri_bitlen, - int cumul_bits, - NR_UE_sched_ctrl_t *sched_ctrl){ - +static void evaluate_cri_report(uint8_t *payload, uint8_t cri_bitlen, int cumul_bits, NR_UE_sched_ctrl_t *sched_ctrl) +{ uint8_t temp_cri = pickandreverse_bits(payload, cri_bitlen, cumul_bits); sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.cri = temp_cri; } -int evaluate_ri_report(uint8_t *payload, - uint8_t ri_bitlen, - uint8_t ri_restriction, - int cumul_bits, - NR_UE_sched_ctrl_t *sched_ctrl){ - +static int evaluate_ri_report(uint8_t *payload, + uint8_t ri_bitlen, + uint8_t ri_restriction, + int cumul_bits, + NR_UE_sched_ctrl_t *sched_ctrl) +{ uint8_t ri_index = pickandreverse_bits(payload, ri_bitlen, cumul_bits); int count=0; for (int i=0; i<8; i++) { @@ -689,13 +686,12 @@ int evaluate_ri_report(uint8_t *payload, AssertFatal(1==0, "Decoded ri %d does not correspond to any valid value in ri_restriction %d\n",ri_index,ri_restriction); } - -void evaluate_cqi_report(uint8_t *payload, - nr_csi_report_t *csi_report, - int cumul_bits, - uint8_t ri, - NR_UE_info_t *UE, - uint8_t cqi_Table) +static void evaluate_cqi_report(uint8_t *payload, + nr_csi_report_t *csi_report, + int cumul_bits, + uint8_t ri, + NR_UE_info_t *UE, + uint8_t cqi_Table) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -723,13 +719,12 @@ void evaluate_cqi_report(uint8_t *payload, sched_ctrl->dl_max_mcs = get_mcs_from_cqi(mcs_table, cqi_Table, cqi_idx); } - -uint8_t evaluate_pmi_report(uint8_t *payload, - nr_csi_report_t *csi_report, - int cumul_bits, - uint8_t ri, - NR_UE_sched_ctrl_t *sched_ctrl){ - +static uint8_t evaluate_pmi_report(uint8_t *payload, + nr_csi_report_t *csi_report, + int cumul_bits, + uint8_t ri, + NR_UE_sched_ctrl_t *sched_ctrl) +{ int x1_bitlen = csi_report->csi_meas_bitlen.pmi_x1_bitlen[ri]; int x2_bitlen = csi_report->csi_meas_bitlen.pmi_x2_bitlen[ri]; int tot_bitlen = x1_bitlen + x2_bitlen; @@ -744,16 +739,14 @@ uint8_t evaluate_pmi_report(uint8_t *payload, sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.pmi_x2); return tot_bitlen; - } - -int evaluate_li_report(uint8_t *payload, - nr_csi_report_t *csi_report, - int cumul_bits, - uint8_t ri, - NR_UE_sched_ctrl_t *sched_ctrl){ - +static int evaluate_li_report(uint8_t *payload, + nr_csi_report_t *csi_report, + int cumul_bits, + uint8_t ri, + NR_UE_sched_ctrl_t *sched_ctrl) +{ int li_bitlen = csi_report->csi_meas_bitlen.li_bitlen[ri]; if (li_bitlen>0) { @@ -762,14 +755,10 @@ int evaluate_li_report(uint8_t *payload, sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.li = temp_li; } return li_bitlen; - } -void skip_zero_padding(int *cumul_bits, - nr_csi_report_t *csi_report, - uint8_t ri, - uint16_t max_bitlen) { - +static void skip_zero_padding(int *cumul_bits, nr_csi_report_t *csi_report, uint8_t ri, uint16_t max_bitlen) +{ // actual number of reported bits depends on the reported rank // zero padding bits are added to have a predetermined max bit length to decode @@ -783,13 +772,12 @@ void skip_zero_padding(int *cumul_bits, *cumul_bits+=(max_bitlen-reported_bitlen); } - -void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig, - const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu, - frame_t frame, - slot_t slot, - NR_UE_info_t *UE, - NR_ServingCellConfigCommon_t *scc) +static void extract_pucch_csi_report(NR_CSI_MeasConfig_t *csi_MeasConfig, + const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_pdu, + frame_t frame, + slot_t slot, + NR_UE_info_t *UE, + NR_ServingCellConfigCommon_t *scc) { /** From Table 6.3.1.1.2-3: RI, LI, CQI, and CRI of codebookType=typeI-SinglePanel */ uint8_t *payload = uci_pdu->csi_part1.csi_part1_payload; @@ -1031,7 +1019,7 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, } } -void set_pucch_allocation(const NR_UE_UL_BWP_t *ul_bwp, const int r_pucch, const int bwp_size, NR_sched_pucch_t *pucch) +static void set_pucch_allocation(const NR_UE_UL_BWP_t *ul_bwp, const int r_pucch, const int bwp_size, NR_sched_pucch_t *pucch) { if(r_pucch<0){ const NR_PUCCH_Resource_t *resource = ul_bwp->pucch_Config->resourceToAddModList->list.array[0]; @@ -1053,11 +1041,8 @@ void set_pucch_allocation(const NR_UE_UL_BWP_t *ul_bwp, const int r_pucch, const } } -bool test_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, - uint16_t *vrb_map_UL, - const int bwp_start, - const int bwp_size) { - +static bool test_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, uint16_t *vrb_map_UL, const int bwp_start, const int bwp_size) +{ // We assume initial cyclic shift is always 0 so different pucch resources can't overlap // verifying occupation of PRBs for ACK/NACK on dedicated pucch @@ -1076,9 +1061,7 @@ bool test_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, return true; } -void set_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, - uint16_t *vrb_map_UL, - const int bwp_start) +static void set_pucch0_vrb_occupation(const NR_sched_pucch_t *pucch, uint16_t *vrb_map_UL, const int bwp_start) { for (int l=0; lnr_of_symb; l++) { uint16_t symb = SL_to_bitmap(pucch->start_symb+l, 1); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index e1a4e716ef..a7ed11e8f6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -61,14 +61,8 @@ const int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *sc return 0; // if FDD or not mixed slot in TDD, for now use default TDA (TODO handle CSI-RS slots) } -int compute_ph_factor(int mu, - int tbs_bits, - int rb, - int n_layers, - int n_symbols, - int n_dmrs, - long *deltaMCS) { - +static int compute_ph_factor(int mu, int tbs_bits, int rb, int n_layers, int n_symbols, int n_dmrs, long *deltaMCS) +{ // 38.213 7.1.1 // if the PUSCH transmission is over more than one layer delta_tf = 0 int delta_tf = 0; @@ -109,14 +103,14 @@ int compute_ph_factor(int mu, // F: length of L is 0:8 or 1:16 bits wide // R: Reserved bit, set to zero. -int nr_process_mac_pdu(instance_t module_idP, - NR_UE_info_t* UE, - uint8_t CC_id, - frame_t frameP, - sub_frame_t slot, - uint8_t *pduP, - int pdu_len, - const int8_t harq_pid) +static int nr_process_mac_pdu(instance_t module_idP, + NR_UE_info_t *UE, + uint8_t CC_id, + frame_t frameP, + sub_frame_t slot, + uint8_t *pduP, + int pdu_len, + const int8_t harq_pid) { uint8_t done = 0; @@ -462,7 +456,7 @@ int nr_process_mac_pdu(instance_t module_idP, return 0; } -void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid) +static void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_ul_harq_t *harq = &sched_ctrl->ul_harq_processes[harq_pid]; @@ -479,7 +473,7 @@ void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid) sched_ctrl->sched_ul_bytes = 0; } -bool get_UE_waiting_CFRA_msg3(const gNB_MAC_INST *gNB_mac, const int CC_id, const frame_t frame, const sub_frame_t slot) +static bool get_UE_waiting_CFRA_msg3(const gNB_MAC_INST *gNB_mac, const int CC_id, const frame_t frame, const sub_frame_t slot) { bool UE_waiting_CFRA_msg3 = false; for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) { @@ -841,8 +835,8 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, } } -uint32_t calc_power_complex(const int16_t *x, const int16_t *y, const uint32_t size) { - +static uint32_t calc_power_complex(const int16_t *x, const int16_t *y, const uint32_t size) +{ // Real part value int64_t sum_x = 0; int64_t sum_x2 = 0; @@ -864,7 +858,8 @@ uint32_t calc_power_complex(const int16_t *x, const int16_t *y, const uint32_t s return power_re+power_im; } -c16_t nr_h_times_w(c16_t h, char w) { +static c16_t nr_h_times_w(c16_t h, char w) +{ c16_t output; switch (w) { case '0': // 0 @@ -893,11 +888,11 @@ c16_t nr_h_times_w(c16_t h, char w) { return output; } -uint8_t get_max_tpmi(const NR_PUSCH_Config_t *pusch_Config, - const uint16_t num_ue_srs_ports, - const uint8_t *nrOfLayers, - int *additional_max_tpmi) { - +static uint8_t get_max_tpmi(const NR_PUSCH_Config_t *pusch_Config, + const uint16_t num_ue_srs_ports, + const uint8_t *nrOfLayers, + int *additional_max_tpmi) +{ uint8_t max_tpmi = 0; if ((pusch_Config && pusch_Config->txConfig != NULL && *pusch_Config->txConfig == NR_PUSCH_Config__txConfig_nonCodebook) || @@ -1056,13 +1051,13 @@ uint8_t get_max_tpmi(const NR_PUSCH_Config_t *pusch_Config, return max_tpmi; } -void get_precoder_matrix_coef(char *w, - const uint8_t ul_ri, - const uint16_t num_ue_srs_ports, - const long transform_precoding, - const uint8_t tpmi, - const uint8_t uI, - int layer_idx) +static void get_precoder_matrix_coef(char *w, + const uint8_t ul_ri, + const uint16_t num_ue_srs_ports, + const long transform_precoding, + const uint8_t tpmi, + const uint8_t uI, + int layer_idx) { if (ul_ri == 0) { if (num_ue_srs_ports == 2) { @@ -1085,15 +1080,16 @@ void get_precoder_matrix_coef(char *w, } } -int nr_srs_tpmi_estimation(const NR_PUSCH_Config_t *pusch_Config, - const long transform_precoding, - const uint8_t *channel_matrix, - const uint8_t normalized_iq_representation, - const uint16_t num_gnb_antenna_elements, - const uint16_t num_ue_srs_ports, - const uint16_t prg_size, - const uint16_t num_prgs, - const uint8_t ul_ri) { +static int nr_srs_tpmi_estimation(const NR_PUSCH_Config_t *pusch_Config, + const long transform_precoding, + const uint8_t *channel_matrix, + const uint8_t normalized_iq_representation, + const uint16_t num_gnb_antenna_elements, + const uint16_t num_ue_srs_ports, + const uint16_t prg_size, + const uint16_t num_prgs, + const uint8_t ul_ri) +{ if (ul_ri > 1) { LOG_D(NR_MAC, "TPMI computation for ul_ri %i is not implemented yet!\n", ul_ri); return 0; @@ -1363,7 +1359,7 @@ static bool nr_UE_is_to_be_scheduled(const NR_ServingCellConfigCommon_t *scc, in return has_data || sched_ctrl->SR || high_inactivity; } -void update_ul_ue_R_Qm(int mcs, int mcs_table, const NR_PUSCH_Config_t *pusch_Config, uint16_t *R, uint8_t *Qm) +static void update_ul_ue_R_Qm(int mcs, int mcs_table, const NR_PUSCH_Config_t *pusch_Config, uint16_t *R, uint8_t *Qm) { *R = nr_get_code_rate_ul(mcs, mcs_table); *Qm = nr_get_Qm_ul(mcs, mcs_table); @@ -1374,7 +1370,14 @@ void update_ul_ue_R_Qm(int mcs, int mcs_table, const NR_PUSCH_Config_t *pusch_Co } } -void nr_ue_max_mcs_min_rb(int mu, int ph_limit, NR_sched_pusch_t *sched_pusch, NR_UE_UL_BWP_t *ul_bwp, uint16_t minRb, uint32_t tbs, uint16_t *Rb, uint8_t *mcs) +static void nr_ue_max_mcs_min_rb(int mu, + int ph_limit, + NR_sched_pusch_t *sched_pusch, + NR_UE_UL_BWP_t *ul_bwp, + uint16_t minRb, + uint32_t tbs, + uint16_t *Rb, + uint8_t *mcs) { AssertFatal(*Rb >= minRb, "illegal Rb %d < minRb %d\n", *Rb, minRb); AssertFatal(*mcs >= 0 && *mcs <= 28, "illegal MCS %d\n", *mcs); @@ -1577,13 +1580,13 @@ static int comparator(const void *p, const void *q) { return ((UEsched_t*)p)->coef < ((UEsched_t*)q)->coef; } -void pf_ul(module_id_t module_id, - frame_t frame, - sub_frame_t slot, - NR_UE_info_t *UE_list[], - int max_num_ue, - int n_rb_sched, - uint16_t *rballoc_mask) +static void pf_ul(module_id_t module_id, + frame_t frame, + sub_frame_t slot, + NR_UE_info_t *UE_list[], + int max_num_ue, + int n_rb_sched, + uint16_t *rballoc_mask) { const int CC_id = 0; @@ -1870,7 +1873,7 @@ void pf_ul(module_id_t module_id, } } -bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot) +static bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot) { gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; NR_COMMON_channels_t *cc = nr_mac->common_channels; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index a700c5c652..01036ea82b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -40,8 +40,6 @@ void set_cset_offset(uint16_t); void mac_top_init_gNB(ngran_node_t node_type); -void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch_AntennaPorts, NR_ServingCellConfigCommon_t *scc); - int nr_mac_enable_ue_rrc_processing_timer(module_id_t Mod_idP, rnti_t rnti, NR_SubcarrierSpacing_t subcarrierSpacing, @@ -87,15 +85,6 @@ void nr_schedule_ue_spec(module_id_t module_id, nfapi_nr_dl_tti_request_t *DL_req, nfapi_nr_tx_data_request_t *TX_req); -uint32_t schedule_control_sib1(module_id_t module_id, - int CC_id, - NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config, - int time_domain_allocation, - NR_pdsch_dmrs_t *dmrs_parms, - NR_tda_info_t *tda_info, - uint8_t candidate_idx, - uint16_t num_total_bytes); - /* \brief default FR1 DL preprocessor init routine, returns preprocessor to call */ nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(int CC_id); @@ -139,41 +128,6 @@ void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t int nr_allocate_CCEs(int module_idP, int CC_idP, frame_t frameP, sub_frame_t slotP, int test_only); -void nr_get_Msg3alloc(module_id_t module_id, - int CC_id, - NR_ServingCellConfigCommon_t *scc, - sub_frame_t current_subframe, - frame_t current_frame, - NR_RA_t *ra, - int16_t *tdd_beam_association); - -void nr_generate_Msg3_retransmission(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - NR_RA_t *ra, - nfapi_nr_ul_dci_request_t *ul_dci_req); - -/* \brief Function in gNB to fill RAR pdu when requested by PHY. -@param ra Instance of RA resources of gNB -@param dlsch_buffer Pointer to RAR input buffer -@param N_RB_UL Number of UL resource blocks -*/ -void nr_fill_rar(uint8_t Mod_idP, - NR_RA_t * ra, - uint8_t * dlsch_buffer, - nfapi_nr_pusch_pdu_t *pusch_pdu); - -void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, - NR_ServingCellConfigCommon_t *scc, - int round, - int startSymbolAndLength, - rnti_t rnti, int scs, - int bwp_size, int bwp_start, - int mappingtype, int fh, - int msg3_first_rb, int msg3_nb_rb); - - void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP); uint16_t nr_mac_compute_RIV(uint16_t N_RB_DL, uint16_t RBstart, uint16_t Lcrbs); @@ -380,39 +334,10 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, unsigned char drx_cmd, unsigned char *ue_cont_res_id); -void nr_generate_Msg2(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - NR_RA_t *ra, - nfapi_nr_dl_tti_request_t *dl_req, - nfapi_nr_tx_data_request_t *TX_req); - -void nr_generate_Msg4(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - NR_RA_t *ra, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req); - -void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t slot, NR_RA_t *ra); - -void nr_generate_Msg3_dcch_dtch_response(module_id_t module_idP, - int CC_id, - frame_t frameP, - sub_frame_t slotP, - NR_RA_t *ra, - nfapi_nr_dl_tti_request_t *DL_req, - nfapi_nr_tx_data_request_t *TX_req); - int binomial(int n, int k); bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot); -void fill_ssb_vrb_map (NR_COMMON_channels_t *cc, int rbStart, int ssb_subcarrier_offset, uint16_t symStart, int CC_id); - - /* \brief Function to indicate a received SDU on ULSCH. @param Mod_id Instance ID of gNB @param CC_id Component carrier index @@ -451,13 +376,6 @@ void handle_nr_srs_measurements(const module_id_t module_id, const sub_frame_t slot, nfapi_nr_srs_indication_pdu_t *srs_ind); -int16_t ssb_index_from_prach(module_id_t module_idP, - frame_t frameP, - sub_frame_t slotP, - uint16_t preamble_index, - uint8_t freq_index, - uint8_t symbol); - void find_SSB_and_RO_available(gNB_MAC_INST *nrmac); NR_pdsch_dmrs_t get_dl_dmrs_params(const NR_ServingCellConfigCommon_t *scc, From 44bf62758acea728660458c3dce7923399ee4505 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 25 Apr 2023 12:07:50 +0200 Subject: [PATCH 05/18] Remove nr_mac_update_RA() There is no point in updating RA, when we update the CellGroupConfig. We simply drop this function, therefore --- openair2/LAYER2/NR_MAC_gNB/config.c | 51 -------------------------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 1 - 2 files changed, 52 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 861c392a54..0ca7e05f96 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -653,58 +653,7 @@ bool nr_mac_update_cellgroup(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupCon exit(1); } - nr_mac_update_RA(nrmac, rnti, CellGroup); process_CellGroup(CellGroup, &UE->UE_sched_ctrl); return true; } - -bool nr_mac_update_RA(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup) -{ - // Checking for free RA process - NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; - uint8_t ra_index = 0; - for (; ra_index < NR_NB_RA_PROC_MAX; ra_index++) { - if ((cc->ra[ra_index].state == RA_IDLE) && (!cc->ra[ra_index].cfra)) - break; - } - if (ra_index == NR_NB_RA_PROC_MAX) { - LOG_E(NR_MAC, "%s() %s:%d RA processes are not available for CFRA RNTI :%x\n", __FUNCTION__, __FILE__, __LINE__, rnti); - return -1; - } - - NR_RA_t *ra = &cc->ra[ra_index]; - if (CellGroup->spCellConfig && CellGroup->spCellConfig->reconfigurationWithSync - && CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated != NULL) { - if (CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra != NULL) { - ra->cfra = true; - ra->rnti = rnti; - ra->CellGroup = CellGroup; - 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; - ra->preambles.preamble_list = (uint8_t *)malloc(num_preamble * sizeof(uint8_t)); - 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) { - // One dedicated preamble for each beam - ra->preambles.preamble_list[i] = cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ra_PreambleIndex; - break; - } - } - } - } - } else { - ra->cfra = false; - ra->rnti = 0; - if (ra->preambles.preamble_list == NULL) { - ra->preambles.num_preambles = MAX_NUM_NR_PRACH_PREAMBLES; - ra->preambles.preamble_list = (uint8_t *)malloc(MAX_NUM_NR_PRACH_PREAMBLES * sizeof(uint8_t)); - for (int i = 0; i < MAX_NUM_NR_PRACH_PREAMBLES; i++) - ra->preambles.preamble_list[i] = i; - } - } - LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup\n", ra->cfra ? "CFRA" : "CBRA", rnti); - - return true; -} diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 01036ea82b..c2cbe8799d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -56,7 +56,6 @@ void nr_mac_config_sib1(gNB_MAC_INST *nrmac, NR_BCCH_DL_SCH_Message_t *sib1); bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); bool nr_mac_prepare_ra_nsa_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); bool nr_mac_update_cellgroup(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); -bool nr_mac_update_RA(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); void clear_nr_nfapi_information(gNB_MAC_INST *gNB, int CC_idP, From 31a1003349ec55da3ce8c2fedbd1a17dbba27b46 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 25 Apr 2023 12:07:10 +0200 Subject: [PATCH 06/18] Introduce mutex for MAC scheduler Different threads (e.g., RRC, DU tasks) might access the scheduler at the same time as the thread that drivers the scheduler itself (ru_thread). To avoid data races, introduce this mutex. Most functions of the scheduler are only used internally and have been marked static in the previous commit. The remaining ones, in this commit, either lock the scheduler mutex sched_lock, or a comment has been added of the assumption of how such function is to be locked (e.g., if it might be called from different places, or if it is called by a function that already locks the scheduler). --- openair1/SIMULATION/NR_PHY/dlsim.c | 3 + openair2/LAYER2/NR_MAC_gNB/config.c | 37 +++++++-- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c | 5 +- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 24 ++++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c | 3 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c | 16 +++- .../LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c | 2 + .../NR_MAC_gNB/gNB_scheduler_primitives.c | 31 ++++++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c | 7 +- .../LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c | 38 ++++++++-- .../LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c | 75 ++++++++++++++----- openair2/LAYER2/NR_MAC_gNB/main.c | 12 ++- openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 21 ++++++ openair2/RRC/NR/L2_nr_interface.c | 7 +- 14 files changed, 225 insertions(+), 56 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index a7465ad99b..0007a3b4d1 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -1010,7 +1010,10 @@ int main(int argc, char **argv) UE_info->UE_sched_ctrl.harq_processes[harq_pid].ndi = !(trial&1); UE_info->UE_sched_ctrl.harq_processes[harq_pid].round = round; + // nr_schedule_ue_spec() requires the mutex to be locked + NR_SCHED_LOCK(&gNB_mac->sched_lock); nr_schedule_ue_spec(0, frame, slot, &Sched_INFO->DL_req, &Sched_INFO->TX_req); + NR_SCHED_UNLOCK(&gNB_mac->sched_lock); Sched_INFO->module_id = 0; Sched_INFO->CC_id = 0; Sched_INFO->frame = frame; diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 0ca7e05f96..4ba189c4bd 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -125,6 +125,9 @@ static void process_phr_Config(NR_UE_sched_ctrl_t *sched_ctrl, NR_SetupRelease_P void process_CellGroup(NR_CellGroupConfig_t *CellGroup, NR_UE_sched_ctrl_t *sched_ctrl) { + /* we assume that this function is mutex-protected from outside */ + NR_SCHED_ENSURE_LOCKED(&RC.nrmac[0]->sched_lock); + AssertFatal(CellGroup, "CellGroup is null\n"); NR_MAC_CellGroupConfig_t *mac_CellGroupConfig = CellGroup->mac_CellGroupConfig; @@ -436,19 +439,23 @@ static void config_common(gNB_MAC_INST *nrmac, int pdsch_AntennaPorts, int pusch } } -int nr_mac_enable_ue_rrc_processing_timer(module_id_t Mod_idP, rnti_t rnti, NR_SubcarrierSpacing_t subcarrierSpacing, uint32_t rrc_reconfiguration_delay) { - +int nr_mac_enable_ue_rrc_processing_timer(module_id_t Mod_idP, rnti_t rnti, NR_SubcarrierSpacing_t subcarrierSpacing, uint32_t rrc_reconfiguration_delay) +{ if (rrc_reconfiguration_delay == 0) { return -1; } - NR_UE_info_t *UE_info = find_nr_UE(&RC.nrmac[Mod_idP]->UE_info,rnti); + gNB_MAC_INST *nrmac = RC.nrmac[Mod_idP]; + NR_SCHED_LOCK(&nrmac->sched_lock); + + NR_UE_info_t *UE_info = find_nr_UE(&nrmac->UE_info,rnti); if (!UE_info) { LOG_W(NR_MAC, "Could not find UE for RNTI 0x%04x\n", rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); return -1; } NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl; - const uint16_t sl_ahead = RC.nrmac[Mod_idP]->if_inst->sl_ahead; + const uint16_t sl_ahead = nrmac->if_inst->sl_ahead; sched_ctrl->rrc_processing_timer = (rrc_reconfiguration_delay<rnti, rrc_reconfiguration_delay); @@ -456,8 +463,9 @@ int nr_mac_enable_ue_rrc_processing_timer(module_id_t Mod_idP, rnti_t rnti, NR_S // processing timer. To prevent this, set a variable as if we would have just // sent it. This way, another TA command will for sure be sent in some // frames, after RRC processing timer. - sched_ctrl->ta_frame = (RC.nrmac[Mod_idP]->frame - 1 + 1024) % 1024; + sched_ctrl->ta_frame = (nrmac->frame - 1 + 1024) % 1024; + NR_SCHED_UNLOCK(&nrmac->sched_lock); return 0; } @@ -470,6 +478,7 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, { DevAssert(nrmac != NULL); AssertFatal(nrmac->common_channels[0].ServingCellConfigCommon == NULL, "logic error: multiple configurations of SCC\n"); + NR_SCHED_LOCK(&nrmac->sched_lock); DevAssert(scc != NULL); AssertFatal(scc->ssb_PositionsInBurst->present > 0 && scc->ssb_PositionsInBurst->present < 4, @@ -549,26 +558,31 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, ra->preambles.preamble_list[i] = i; } } + NR_SCHED_UNLOCK(&nrmac->sched_lock); } void nr_mac_config_mib(gNB_MAC_INST *nrmac, NR_BCCH_BCH_Message_t *mib) { DevAssert(nrmac != NULL); DevAssert(mib != NULL); + NR_SCHED_LOCK(&nrmac->sched_lock); NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; AssertFatal(cc->mib == NULL, "logic bug: updated MIB multiple times\n"); cc->mib = mib; + NR_SCHED_UNLOCK(&nrmac->sched_lock); } void nr_mac_config_sib1(gNB_MAC_INST *nrmac, NR_BCCH_DL_SCH_Message_t *sib1) { DevAssert(nrmac != NULL); DevAssert(sib1 != NULL); + NR_SCHED_LOCK(&nrmac->sched_lock); NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; AssertFatal(cc->sib1 == NULL, "logic bug: updated SIB1 multiple times\n"); cc->sib1 = sib1; + NR_SCHED_UNLOCK(&nrmac->sched_lock); } bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup) @@ -576,16 +590,17 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t DevAssert(nrmac != NULL); DevAssert(CellGroup != NULL); 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) { LOG_I(NR_MAC,"Force-added new UE %x with initial CellGroup\n", rnti); + process_CellGroup(CellGroup,&UE->UE_sched_ctrl); } else { LOG_E(NR_MAC,"Error adding UE %04x\n", rnti); - return false; } - process_CellGroup(CellGroup,&UE->UE_sched_ctrl); - return true; + NR_SCHED_UNLOCK(&nrmac->sched_lock); + return UE != NULL; } bool nr_mac_prepare_ra_nsa_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup) @@ -593,6 +608,7 @@ bool nr_mac_prepare_ra_nsa_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupCo DevAssert(nrmac != NULL); DevAssert(CellGroup != NULL); DevAssert(!get_softmodem_params()->phy_test); + NR_SCHED_LOCK(&nrmac->sched_lock); // NSA case: need to pre-configure CFRA const int CC_id = 0; @@ -604,6 +620,7 @@ bool nr_mac_prepare_ra_nsa_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupCo } if (ra_index == NR_NB_RA_PROC_MAX) { LOG_E(NR_MAC, "RA processes are not available for CFRA RNTI %04x\n", rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); return false; } NR_RA_t *ra = &cc->ra[ra_index]; @@ -632,12 +649,16 @@ bool nr_mac_prepare_ra_nsa_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupCo } } LOG_I(NR_MAC,"Added new RA process for UE RNTI %04x with initial CellGroup\n", rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); return true; } bool nr_mac_update_cellgroup(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup) { DevAssert(nrmac != NULL); + /* we assume that this function is mutex-protected from outside */ + NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); + DevAssert(CellGroup != NULL); NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, rnti); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index e831f6d4a8..2d4cd16eb4 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -63,6 +63,7 @@ void clear_nr_nfapi_information(gNB_MAC_INST *gNB, nfapi_nr_tx_data_request_t *TX_req, nfapi_nr_ul_dci_request_t *UL_dci_req) { + /* called below and in simulators, so we assume a lock but don't require it */ NR_ServingCellConfigCommon_t *scc = gNB->common_channels->ServingCellConfigCommon; const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; @@ -149,6 +150,8 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_ NR_COMMON_channels_t *cc = gNB->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; + NR_SCHED_LOCK(&gNB->sched_lock); + if (slot==0 && (*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]>=257)) { //FR2 const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; @@ -254,6 +257,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP, frame_t frame, sub_frame_ copy_ul_tti_req(&sched_info->UL_tti_req, &gNB->UL_tti_req_ahead[0][current_index]); stop_meas(&gNB->eNB_scheduler); - + NR_SCHED_UNLOCK(&gNB->sched_lock); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_OUT); } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 3beaac6c6b..fb78ff0d13 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -154,10 +154,12 @@ static int16_t ssb_index_from_prach(module_id_t module_idP, return index; } - //Compute Total active SSBs and RO available void find_SSB_and_RO_available(gNB_MAC_INST *nrmac) { + /* already mutex protected through nr_mac_config_scc() */ + NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); + NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0]; @@ -257,6 +259,9 @@ void find_SSB_and_RO_available(gNB_MAC_INST *nrmac) void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) { gNB_MAC_INST *gNB = RC.nrmac[module_idP]; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + NR_SCHED_ENSURE_LOCKED(&gNB->sched_lock); + NR_COMMON_channels_t *cc = gNB->common_channels; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; int mu; @@ -536,12 +541,13 @@ void nr_initiate_ra_proc(module_id_t module_idP, uint16_t preamble_index, uint8_t freq_index, uint8_t symbol, - int16_t timing_offset){ + int16_t timing_offset) +{ + gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; + NR_SCHED_LOCK(&nr_mac->sched_lock); uint8_t ul_carrier_id = 0; // 0 for NUL 1 for SUL - uint16_t msg2_frame, msg2_slot,monitoring_slot_period,monitoring_offset; - gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; frame_type_t frame_type = cc->frame_type; @@ -675,8 +681,11 @@ void nr_initiate_ra_proc(module_id_t module_idP, cc->ssb_index[beam_index], i); + NR_SCHED_UNLOCK(&nr_mac->sched_lock); return; } + + NR_SCHED_UNLOCK(&nr_mac->sched_lock); LOG_E(NR_MAC, "[gNB %d][RAPROC] FAILURE: CC_id %d Frame %d initiating RA procedure for preamble index %d\n", module_idP, CC_id, frameP, preamble_index); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0); @@ -2090,7 +2099,10 @@ static void nr_check_Msg4_Ack(module_id_t module_id, int CC_id, frame_t frame, s } } -void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t *ra){ +void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, NR_RA_t *ra) +{ + /* we assume that this function is mutex-protected from outside */ + NR_SCHED_ENSURE_LOCKED(&RC.nrmac[module_idP]->sched_lock); LOG_D(NR_MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Clear Random access information rnti %x\n", module_idP, CC_id, frameP, ra->rnti); ra->state = RA_IDLE; ra->timing_offset = 0; @@ -2237,6 +2249,8 @@ void nr_schedule_RA(module_id_t module_idP, nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *mac = RC.nrmac[module_idP]; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + NR_SCHED_ENSURE_LOCKED(&mac->sched_lock); start_meas(&mac->schedule_ra); for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index bc5710e2ec..0d66ec0842 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -108,6 +108,7 @@ static void fill_ssb_vrb_map(NR_COMMON_channels_t *cc, int rbStart, int ssb_subc void schedule_nr_mib(module_id_t module_idP, frame_t frameP, sub_frame_t slotP, nfapi_nr_dl_tti_request_t *DL_req) { gNB_MAC_INST *gNB = RC.nrmac[module_idP]; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ NR_COMMON_channels_t *cc; nfapi_nr_dl_tti_request_body_t *dl_req; NR_MIB_t *mib = RC.nrrrc[module_idP]->carrier.mib->message.choice.mib; @@ -513,7 +514,6 @@ static void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP, LOG_D(MAC,"ShiftIndex: %i\n", pdcch_pdu_rel15->ShiftIndex); LOG_D(MAC,"precoderGranularity: %i\n", pdcch_pdu_rel15->precoderGranularity); LOG_D(MAC,"numDlDci: %i\n", pdcch_pdu_rel15->numDlDci); - } void schedule_nr_sib1(module_id_t module_idP, @@ -522,6 +522,7 @@ void schedule_nr_sib1(module_id_t module_idP, nfapi_nr_dl_tti_request_t *DL_req, nfapi_nr_tx_data_request_t *TX_req) { + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ // TODO: Get these values from RRC const int CC_id = 0; uint8_t candidate_idx = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 846a7a35f0..4d3d59c12e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -55,6 +55,7 @@ const int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot) { + /* we assume that this function is mutex-protected from outside */ const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; AssertFatal(tdd || nrmac->common_channels->frame_type == FDD, "Dynamic TDD not handled yet\n"); @@ -76,8 +77,12 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, const NR_UE_sched_ctrl_t *ue_sched_ctl, unsigned char *mac_pdu, unsigned char drx_cmd, - unsigned char *ue_cont_res_id) { + unsigned char *ue_cont_res_id) +{ gNB_MAC_INST *gNB = RC.nrmac[module_idP]; + /* already mutex protected: called below and in _RA.c */ + NR_SCHED_ENSURE_LOCKED(&gNB->sched_lock); + NR_MAC_SUBHEADER_FIXED *mac_pdu_ptr = (NR_MAC_SUBHEADER_FIXED *) mac_pdu; uint8_t last_size = 0; int offset = 0, mac_ce_size, i, timing_advance_cmd, tag_id = 0; @@ -361,8 +366,9 @@ static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_fram } } -void abort_nr_dl_harq(NR_UE_info_t* UE, int8_t harq_pid) { - +void abort_nr_dl_harq(NR_UE_info_t* UE, int8_t harq_pid) +{ + /* already mutex protected through handle_dl_harq() */ NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_harq_t *harq = &sched_ctrl->harq_processes[harq_pid]; @@ -840,6 +846,7 @@ static void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_ } nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(int CC_id) { + /* during initialization: no mutex needed */ /* in the PF algorithm, we have to use the TBsize to compute the coefficient. * This would include the number of DMRS symbols, which in turn depends on * the time domain allocation. In case we are in a mixed slot, we do not want @@ -873,6 +880,9 @@ void nr_schedule_ue_spec(module_id_t module_id, nfapi_nr_tx_data_request_t *TX_req) { gNB_MAC_INST *gNB_mac = RC.nrmac[module_id]; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + AssertFatal(pthread_mutex_trylock(&gNB_mac->sched_lock) == EBUSY, + "this function should be called with the scheduler mutex locked\n"); if (!is_xlsch_in_slot(gNB_mac->dlsch_slot_bitmap[slot / 64], slot)) return; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 96756d41cd..d59efafdc2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -50,6 +50,7 @@ void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_t slot) { + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ if (!is_xlsch_in_slot(dlsch_slot_bitmap, slot)) return; NR_UE_info_t *UE = RC.nrmac[module_id]->UE_info.list[0]; @@ -192,6 +193,7 @@ uint64_t ulsch_slot_bitmap = (1 << 8); bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_t slot) { gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + /* 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]; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 411a9609c1..2a8457356a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -2369,7 +2369,7 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf reset_srs_stats(UE); - pthread_mutex_lock(&UE_info->mutex); + NR_SCHED_LOCK(&UE_info->mutex); int i; for(i=0; ilist[i] == NULL) { @@ -2380,10 +2380,10 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf 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); - pthread_mutex_unlock(&UE_info->mutex); + NR_SCHED_UNLOCK(&UE_info->mutex); return NULL; } - pthread_mutex_unlock(&UE_info->mutex); + NR_SCHED_UNLOCK(&UE_info->mutex); LOG_D(NR_MAC, "Add NR rnti %x\n", rntiP); dump_nr_list(UE_info->list); @@ -2487,8 +2487,11 @@ void reset_ul_harq_list(NR_UE_sched_ctrl_t *sched_ctrl) { 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; - pthread_mutex_lock(&UE_info->mutex); + NR_SCHED_LOCK(&UE_info->mutex); UE_iterator(UE_info->list, UE) { if (UE->rnti==rnti) break; @@ -2496,7 +2499,7 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti) if (!UE) { LOG_W(NR_MAC,"Call to del rnti %04x, but not existing\n", rnti); - pthread_mutex_unlock(&UE_info->mutex); + NR_SCHED_UNLOCK(&UE_info->mutex); return; } @@ -2506,7 +2509,7 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti) if(UE_info->list[i] && UE_info->list[i]->rnti != rnti) newUEs[newListIdx++]=UE_info->list[i]; memcpy(UE_info->list, newUEs, sizeof(UE_info->list)); - pthread_mutex_unlock(&UE_info->mutex); + NR_SCHED_UNLOCK(&UE_info->mutex); delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator); } @@ -2525,6 +2528,7 @@ uint8_t nr_get_tpc(int target, uint8_t cqi, int incr) { int get_pdsch_to_harq_feedback(NR_PUCCH_Config_t *pucch_Config, nr_dci_format_t dci_format, uint8_t *pdsch_to_harq_feedback) { + /* already mutex protected: held in nr_acknack_scheduling() */ if (dci_format == NR_DL_DCI_FORMAT_1_0) { for (int i = 0; i < 8; i++) @@ -2545,6 +2549,9 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo int CC_id = 0; NR_UEs_t *UE_info = &RC.nrmac[Mod_idP]->UE_info; gNB_MAC_INST *gNB_mac = RC.nrmac[Mod_idP]; + + NR_SCHED_ENSURE_LOCKED(&gNB_mac->sched_lock); + uint16_t *vrb_map = gNB_mac->common_channels[CC_id].vrb_map; UE_info->sched_csirs = false; @@ -2770,7 +2777,10 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo void nr_mac_update_timers(module_id_t module_id, frame_t frame, - sub_frame_t slot) { + sub_frame_t slot) +{ + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + NR_SCHED_ENSURE_LOCKED(&RC.nrmac[module_id]->sched_lock); NR_UEs_t *UE_info = &RC.nrmac[module_id]->UE_info; UE_iterator(UE_info->list, UE) { @@ -2824,7 +2834,10 @@ void nr_mac_update_timers(module_id_t module_id, void schedule_nr_bwp_switch(module_id_t module_id, frame_t frame, - sub_frame_t slot) { + sub_frame_t slot) +{ + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + NR_SCHED_ENSURE_LOCKED(&RC.nrmac[module_id]->sched_lock); NR_UEs_t *UE_info = &RC.nrmac[module_id]->UE_info; @@ -2887,6 +2900,7 @@ void send_initial_ul_rrc_message(gNB_MAC_INST *mac, int rnti, const uint8_t *sdu LOG_W(MAC, "[RAPROC] Received SDU for CCCH length %d for UE %04x\n", sdu_len, rnti); NR_UE_info_t *UE = (NR_UE_info_t *)rawUE; + NR_SCHED_ENSURE_LOCKED(&mac->sched_lock); uint8_t du2cu[1024]; int encoded = encode_cellGroupConfig(UE->CellGroup, du2cu, sizeof(du2cu)); @@ -2904,6 +2918,7 @@ void send_initial_ul_rrc_message(gNB_MAC_INST *mac, int rnti, const uint8_t *sdu void prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE) { + NR_SCHED_ENSURE_LOCKED(&mac->sched_lock); /* create this UE's initial CellGroup */ /* Note: relying on the RRC is a hack, as we are in the DU; there should be * no RRC, remove in the future */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index fd11023387..3309e1af34 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -54,6 +54,9 @@ void nr_srs_ri_computation(const nfapi_nr_srs_normalized_channel_iq_matrix_t *nr const NR_UE_UL_BWP_t *current_BWP, uint8_t *ul_ri) { + /* already mutex protected: held in handle_nr_srs_measurements() */ + NR_SCHED_ENSURE_LOCKED(&RC.nrmac[0]->sched_lock); + // If the gNB or UE has 1 antenna, the rank is always 1, i.e., *ul_ri = 0. // For 2x2 scenario, we compute the rank of channel. // The computation for 2x4, 4x2, 4x4, ... scenarios are not implemented yet. In these cases, the function sets *ul_ri = 0, which is always a valid value. @@ -240,8 +243,10 @@ static void nr_fill_nfapi_srs(int module_id, *********************************************************************/ void nr_schedule_srs(int module_id, frame_t frame, int slot) { - + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ gNB_MAC_INST *nrmac = RC.nrmac[module_id]; + NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); + NR_UEs_t *UE_info = &nrmac->UE_info; UE_iterator(UE_info->list, UE) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index d7ff3c962b..e1716458d2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -167,6 +167,9 @@ void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP) { + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); + if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slotP / 64], slotP)) return; @@ -198,7 +201,10 @@ void nr_csi_meas_reporting(int Mod_idP, frame_t frame, sub_frame_t slot) { + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ gNB_MAC_INST *nrmac = RC.nrmac[Mod_idP]; + NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); + UE_iterator(nrmac->UE_info.list, UE ) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; @@ -917,9 +923,12 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, sub_frame_t slot, const nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01) { - NR_UE_info_t * UE = find_nr_UE(&RC.nrmac[mod_id]->UE_info, uci_01->rnti); + gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; + NR_SCHED_LOCK(&nrmac->sched_lock); + NR_UE_info_t * UE = find_nr_UE(&nrmac->UE_info, uci_01->rnti); 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; } NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; @@ -929,7 +938,7 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) { const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value; const uint8_t harq_confidence = uci_01->harq->harq_confidence_level; - NR_UE_harq_t *harq = find_harq(frame, slot, UE, RC.nrmac[mod_id]->dl_bler.harq_round_max); + NR_UE_harq_t *harq = find_harq(frame, slot, UE, nrmac->dl_bler.harq_round_max); if (!harq) { LOG_E(NR_MAC, "Oh no! Could not find a harq in %s!\n", __FUNCTION__); break; @@ -938,13 +947,13 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, const int8_t pid = sched_ctrl->feedback_dl_harq.head; 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); - handle_dl_harq(UE, pid, harq_value == 0 && harq_confidence == 0, RC.nrmac[mod_id]->dl_bler.harq_round_max); + handle_dl_harq(UE, pid, harq_value == 0 && harq_confidence == 0, nrmac->dl_bler.harq_round_max); if (harq_confidence == 1) UE->mac_stats.pucch0_DTX++; } // tpc (power control) only if we received AckNack if (uci_01->harq->harq_confidence_level==0) - sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10, uci_01->ul_cqi, 30); + sched_ctrl->tpc1 = nr_get_tpc(nrmac->pucch_target_snrx10, uci_01->ul_cqi, 30); else sched_ctrl->tpc1 = 3; sched_ctrl->pucch_snrx10 = uci_01->ul_cqi * 5 - 640; @@ -962,6 +971,7 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, } free(uci_01->sr); } + NR_SCHED_UNLOCK(&nrmac->sched_lock); } void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, @@ -969,15 +979,21 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, sub_frame_t slot, const nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234) { - NR_UE_info_t * UE = find_nr_UE(&RC.nrmac[mod_id]->UE_info, uci_234->rnti); + gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; + NR_SCHED_LOCK(&nrmac->sched_lock); + + NR_UE_info_t * UE = find_nr_UE(&nrmac->UE_info, uci_234->rnti); if (!UE) { + NR_SCHED_UNLOCK(&nrmac->sched_lock); LOG_E(NR_MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_234->rnti); return; } NR_CSI_MeasConfig_t *csi_MeasConfig = UE->current_UL_BWP.csi_MeasConfig; - if (csi_MeasConfig==NULL) + if (csi_MeasConfig==NULL) { + NR_SCHED_UNLOCK(&nrmac->sched_lock); return; + } NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; // tpc (power control) @@ -1002,13 +1018,13 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, DevAssert(harq->is_waiting); const int8_t pid = sched_ctrl->feedback_dl_harq.head; remove_front_nr_list(&sched_ctrl->feedback_dl_harq); - handle_dl_harq(UE, pid, uci_234->harq.harq_crc != 1 && acknack, RC.nrmac[mod_id]->dl_bler.harq_round_max); + handle_dl_harq(UE, pid, uci_234->harq.harq_crc != 1 && acknack, nrmac->dl_bler.harq_round_max); } free(uci_234->harq.harq_payload); } if ((uci_234->pduBitmap >> 2) & 0x01) { //API to parse the csi report and store it into sched_ctrl - extract_pucch_csi_report(csi_MeasConfig, uci_234, frame, slot, UE, RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon); + extract_pucch_csi_report(csi_MeasConfig, uci_234, frame, slot, UE, nrmac->common_channels->ServingCellConfigCommon); //TCI handling function tci_handling(UE,frame, slot); free(uci_234->csi_part1.csi_part1_payload); @@ -1017,6 +1033,7 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, //@TODO:Handle CSI Report 2 // nothing to free (yet) } + NR_SCHED_UNLOCK(&nrmac->sched_lock); } static void set_pucch_allocation(const NR_UE_UL_BWP_t *ul_bwp, const int r_pucch, const int bwp_size, NR_sched_pucch_t *pucch) @@ -1083,6 +1100,8 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac, int r_pucch, int is_common) { + /* we assume that this function is mutex-protected from outside. Since it is + * called often, don't try to lock every time */ const int CC_id = 0; const int minfbtime = mac->minRXTXTIMEpdsch; @@ -1187,6 +1206,9 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac, void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) { + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); + if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slot / 64], slot)) return; const int CC_id = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index a7ed11e8f6..80c1652b61 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -39,7 +39,10 @@ //#define SRS_IND_DEBUG -const int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot) { +const int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot) +{ + /* we assume that this function is mutex-protected from outside */ + NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); /* there is a mixed slot only when in TDD */ const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; @@ -492,17 +495,22 @@ void handle_nr_ul_harq(const int CC_idP, sub_frame_t slot, const nfapi_nr_crc_t *crc_pdu) { - NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[mod_id]->UE_info, crc_pdu->rnti); - bool UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(RC.nrmac[mod_id], CC_idP, frame, slot); + gNB_MAC_INST *nrmac = RC.nrmac[mod_id]; + NR_SCHED_LOCK(&nrmac->sched_lock); + + NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, crc_pdu->rnti); + bool UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(nrmac, CC_idP, frame, slot); if (!UE || UE_waiting_CFRA_msg3 == true) { LOG_W(NR_MAC, "handle harq for rnti %04x, in RA process\n", crc_pdu->rnti); for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) { - NR_RA_t *ra = &RC.nrmac[mod_id]->common_channels[CC_idP].ra[i]; - if (ra->state >= WAIT_Msg3 && - ra->rnti == crc_pdu->rnti) + NR_RA_t *ra = &nrmac->common_channels[CC_idP].ra[i]; + if (ra->state >= WAIT_Msg3 && ra->rnti == crc_pdu->rnti) { + NR_SCHED_UNLOCK(&nrmac->sched_lock); return; + } } + NR_SCHED_UNLOCK(&nrmac->sched_lock); LOG_E(NR_MAC, "%s(): unknown RNTI 0x%04x in PUSCH\n", __func__, crc_pdu->rnti); return; } @@ -515,8 +523,10 @@ void handle_nr_ul_harq(const int CC_idP, crc_pdu->harq_id, harq_pid, crc_pdu->rnti); - if (harq_pid < 0) + if (harq_pid < 0) { + NR_SCHED_UNLOCK(&nrmac->sched_lock); return; + } remove_front_nr_list(&sched_ctrl->feedback_ul_harq); sched_ctrl->ul_harq_processes[harq_pid].is_waiting = false; @@ -556,22 +566,23 @@ void handle_nr_ul_harq(const int CC_idP, crc_pdu->rnti); add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid); } + NR_SCHED_UNLOCK(&nrmac->sched_lock); } /* * When data are received on PHY and transmitted to MAC */ -void nr_rx_sdu(const module_id_t gnb_mod_idP, - const int CC_idP, - const frame_t frameP, - const sub_frame_t slotP, - const rnti_t rntiP, - uint8_t *sduP, - const uint16_t sdu_lenP, - const uint16_t timing_advance, - const uint8_t ul_cqi, - const uint16_t rssi){ - +static void _nr_rx_sdu(const module_id_t gnb_mod_idP, + const int CC_idP, + const frame_t frameP, + const sub_frame_t slotP, + const rnti_t rntiP, + uint8_t *sduP, + const uint16_t sdu_lenP, + const uint16_t timing_advance, + const uint8_t ul_cqi, + const uint16_t rssi) +{ gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP]; const int current_rnti = rntiP; @@ -835,6 +846,23 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP, } } +void nr_rx_sdu(const module_id_t gnb_mod_idP, + const int CC_idP, + const frame_t frameP, + const sub_frame_t slotP, + const rnti_t rntiP, + uint8_t *sduP, + const uint16_t sdu_lenP, + const uint16_t timing_advance, + const uint8_t ul_cqi, + const uint16_t rssi) +{ + gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP]; + NR_SCHED_LOCK(&gNB_mac->sched_lock); + _nr_rx_sdu(gnb_mod_idP, CC_idP, frameP, slotP, rntiP, sduP, sdu_lenP, timing_advance, ul_cqi, rssi); + NR_SCHED_UNLOCK(&gNB_mac->sched_lock); +} + static uint32_t calc_power_complex(const int16_t *x, const int16_t *y, const uint32_t size) { // Real part value @@ -1169,6 +1197,8 @@ void handle_nr_srs_measurements(const module_id_t module_id, const sub_frame_t slot, nfapi_nr_srs_indication_pdu_t *srs_ind) { + gNB_MAC_INST *nrmac = RC.nrmac[module_id]; + NR_SCHED_LOCK(&nrmac->sched_lock); LOG_D(NR_MAC, "(%d.%d) Received SRS indication for UE %04x\n", frame, slot, srs_ind->rnti); #ifdef SRS_IND_DEBUG @@ -1184,11 +1214,13 @@ void handle_nr_srs_measurements(const module_id_t module_id, NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_id]->UE_info, srs_ind->rnti); if (!UE) { LOG_W(NR_MAC, "Could not find UE for RNTI %04x\n", srs_ind->rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); return; } if (srs_ind->timing_advance_offset == 0xFFFF) { LOG_W(NR_MAC, "Invalid timing advance offset for RNTI %04x\n", srs_ind->rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); return; } @@ -1206,6 +1238,7 @@ void handle_nr_srs_measurements(const module_id_t module_id, if (nr_srs_bf_report.wide_band_snr == 0xFF) { LOG_W(NR_MAC, "Invalid wide_band_snr for RNTI %04x\n", srs_ind->rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); return; } @@ -1304,12 +1337,14 @@ void handle_nr_srs_measurements(const module_id_t module_id, default: AssertFatal(1 == 0, "Invalid SRS usage\n"); } + NR_SCHED_UNLOCK(&nrmac->sched_lock); } long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList, int time_domain_assignment, int mu) { + /* we assume that this function is mutex-protected from outside */ NR_PUSCH_TimeDomainResourceAllocation_t *tda = tdaList->list.array[time_domain_assignment]; if (tda->k2) @@ -1974,6 +2009,7 @@ static bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_ nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(int CC_id) { + /* during initialization: no mutex needed */ /* in the PF algorithm, we have to use the TBsize to compute the coefficient. * This would include the number of DMRS symbols, which in turn depends on * the time domain allocation. In case we are in a mixed slot, we do not want @@ -2005,6 +2041,9 @@ nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(int CC_id) void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, nfapi_nr_ul_dci_request_t *ul_dci_req) { gNB_MAC_INST *nr_mac = RC.nrmac[module_id]; + /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ + NR_SCHED_ENSURE_LOCKED(&nr_mac->sched_lock); + /* Uplink data ONLY can be scheduled when the current slot is downlink slot, * because we have to schedule the DCI0 first before schedule uplink data */ if (!is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slot / 64], slot)) { diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index cd8e16c48b..d7cd8e1b4b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -60,7 +60,9 @@ void *nrmac_stats_thread(void *arg) { while (oai_exit == 0) { char *p = output; + NR_SCHED_LOCK(&gNB->sched_lock); p += dump_mac_stats(gNB, p, end - p, false); + NR_SCHED_UNLOCK(&gNB->sched_lock); p += snprintf(p, end - p, "\n"); p += print_meas_log(&gNB->eNB_scheduler, "DL & UL scheduling timing", NULL, NULL, p, end - p); p += print_meas_log(&gNB->schedule_dlsch, "dlsch scheduler", NULL, NULL, p, end - p); @@ -87,7 +89,11 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset const char *begin = output; const char *end = output + strlen; - pthread_mutex_lock(&gNB->UE_info.mutex); + /* this function is called from gNB_dlsch_ulsch_scheduler(), so assumes the + * scheduler to be locked*/ + NR_SCHED_ENSURE_LOCKED(&gNB->sched_lock); + + NR_SCHED_LOCK(&gNB->UE_info.mutex); UE_iterator(gNB->UE_info.list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_mac_stats_t *stats = &UE->mac_stats; @@ -175,7 +181,7 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset stats->ul.lc_bytes[lc_id]); } } - pthread_mutex_unlock(&gNB->UE_info.mutex); + NR_SCHED_UNLOCK(&gNB->UE_info.mutex); return output - begin; } @@ -233,6 +239,8 @@ void mac_top_init_gNB(ngran_node_t node_type) RC.nrmac[i]->first_MIB = true; + pthread_mutex_init(&RC.nrmac[i]->sched_lock, NULL); + pthread_mutex_init(&RC.nrmac[i]->UE_info.mutex, NULL); uid_linear_allocator_init(&RC.nrmac[i]->UE_info.uid_allocator); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index b8517da55e..9f28ffe546 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -41,6 +41,25 @@ #include #include #include +#include + +#define NR_SCHED_LOCK(lock) \ + do { \ + int rc = pthread_mutex_lock(lock); \ + AssertFatal(rc == 0, "error while locking scheduler mutex\n"); \ + } while (0) + +#define NR_SCHED_UNLOCK(lock) \ + do { \ + int rc = pthread_mutex_unlock(lock); \ + AssertFatal(rc == 0, "error while locking scheduler mutex\n"); \ + } while (0) + +#define NR_SCHED_ENSURE_LOCKED(lock)\ + do {\ + int rc = pthread_mutex_trylock(lock); \ + AssertFatal(rc == EBUSY, "this function should be called with the scheduler mutex locked\n");\ + } while (0) /* Commmon */ #include "radio/COMMON/common_lib.h" @@ -795,6 +814,8 @@ typedef struct gNB_MAC_INST_s { int16_t frame; int16_t slot; + pthread_mutex_t sched_lock; + } gNB_MAC_INST; #endif /*__LAYER2_NR_MAC_GNB_H__ */ diff --git a/openair2/RRC/NR/L2_nr_interface.c b/openair2/RRC/NR/L2_nr_interface.c index 2e83c69af2..4e9c077afa 100644 --- a/openair2/RRC/NR/L2_nr_interface.c +++ b/openair2/RRC/NR/L2_nr_interface.c @@ -55,12 +55,17 @@ void nr_rrc_mac_remove_ue(rnti_t rntiMaybeUEid) nr_rlc_remove_ue(rntiMaybeUEid); gNB_MAC_INST *nrmac = RC.nrmac[0]; + NR_SCHED_LOCK(&nrmac->sched_lock); mac_remove_nr_ue(nrmac, rntiMaybeUEid); + NR_SCHED_UNLOCK(&nrmac->sched_lock); } void nr_rrc_mac_update_cellgroup(rnti_t rntiMaybeUEid, NR_CellGroupConfig_t *cgc) { - nr_mac_update_cellgroup(RC.nrmac[0], rntiMaybeUEid, cgc); + gNB_MAC_INST *nrmac = RC.nrmac[0]; + NR_SCHED_LOCK(&nrmac->sched_lock); + nr_mac_update_cellgroup(nrmac, rntiMaybeUEid, cgc); + NR_SCHED_UNLOCK(&nrmac->sched_lock); } uint16_t mac_rrc_nr_data_req(const module_id_t Mod_idP, From 10b996f5db2d1a465a5ca4937b96cd81486a0b42 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 11 Apr 2023 13:49:31 +0200 Subject: [PATCH 07/18] Stubs for F1 UE Context Setup Req+Resp messages --- openair2/F1AP/f1ap_du_ue_context_management.c | 12 ++++++------ openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 8 ++++++++ openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h | 2 ++ openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h | 2 ++ openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 7 +++++++ openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 8 ++++++++ openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 1 + openair2/RRC/NR/mac_rrc_dl.h | 2 ++ openair2/RRC/NR/mac_rrc_dl_direct.c | 1 + openair2/RRC/NR/mac_rrc_dl_f1ap.c | 9 +++++++++ openair2/RRC/NR/nr_rrc_defs.h | 1 + 11 files changed, 47 insertions(+), 6 deletions(-) diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index fbe8388714..4c119dd8ad 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -35,6 +35,7 @@ #include "f1ap_decoder.h" #include "f1ap_itti_messaging.h" #include "f1ap_du_ue_context_management.h" +#include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h" #include "rrc_extern.h" #include "openair2/RRC/NR/rrc_gNB_UE_context.h" @@ -65,13 +66,13 @@ bool lteDURecvCb(protocol_ctxt_t *ctxt_pP, int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, uint32_t assoc_id, uint32_t stream, - F1AP_F1AP_PDU_t *pdu) { - MessageDef *msg_p; // message to RRC + F1AP_F1AP_PDU_t *pdu) +{ F1AP_UEContextSetupRequest_t *container; int i; DevAssert(pdu); - msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_UE_CONTEXT_SETUP_REQ); - f1ap_ue_context_setup_t *f1ap_ue_context_setup_req = &F1AP_UE_CONTEXT_SETUP_REQ(msg_p); + f1ap_ue_context_setup_t ue_context_setup = {0}; + f1ap_ue_context_setup_t *f1ap_ue_context_setup_req = &ue_context_setup; container = &pdu->choice.initiatingMessage->value.choice.UEContextSetupRequest; /* GNB_CU_UE_F1AP_ID */ F1AP_UEContextSetupRequestIEs_t *ieCU; @@ -224,8 +225,7 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, LOG_W(F1AP, "can't find RRCContainer in UEContextSetupRequestIEs by id %ld \n", F1AP_ProtocolIE_ID_id_RRCContainer); } - itti_send_msg_to_task(TASK_RRC_GNB, instance, msg_p); - + ue_context_setup_request(f1ap_ue_context_setup_req); return 0; } 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 0a47699591..838c68fcb6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -19,6 +19,8 @@ * contact@openairinterface.org */ +#include + #include "mac_rrc_dl_handler.h" #include "mac_proto.h" @@ -29,6 +31,12 @@ #include "NR_DL-CCCH-Message.h" #include "NR_CellGroupConfig.h" +void ue_context_setup_request(const f1ap_ue_context_setup_t *req) +{ + (void) req; + abort(); +} + int dl_rrc_message(module_id_t module_id, const f1ap_dl_rrc_message_t *dl_rrc) { LOG_I(NR_MAC, "DL RRC Message Transfer with %d bytes for RNTI %04x SRB %d\n", dl_rrc->rrc_container_length, dl_rrc->rnti, dl_rrc->srb_id); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h index ecbc95eef0..25b51c2d84 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h @@ -25,6 +25,8 @@ #include "platform_types.h" #include "f1ap_messages_types.h" +void ue_context_setup_request(const f1ap_ue_context_setup_t *req); + int dl_rrc_message(module_id_t module_id, const f1ap_dl_rrc_message_t *dl_rrc); #endif /* MAC_RRC_DL_HANDLER_H */ diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index cb80ba4fa5..53736a1695 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -25,6 +25,8 @@ #include "platform_types.h" #include "f1ap_messages_types.h" +typedef void (*ue_context_setup_response_func_t)(const f1ap_ue_context_setup_t* req, const f1ap_ue_context_setup_t *resp); + typedef void (*initial_ul_rrc_message_transfer_func_t)(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc); struct nr_mac_rrc_ul_if_s; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index ace8b17f49..5402b03000 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -24,6 +24,12 @@ #include "mac_rrc_ul.h" +static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) +{ + (void) req; /* we don't need the request -- it is to set up GTP in F1 case */ + AssertFatal(false, "not implemented\n"); +} + static void initial_ul_rrc_message_transfer_direct(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_INITIAL_UL_RRC_MESSAGE); @@ -46,5 +52,6 @@ static void initial_ul_rrc_message_transfer_direct(module_id_t module_id, const void mac_rrc_ul_direct_init(struct nr_mac_rrc_ul_if_s *mac_rrc) { + mac_rrc->ue_context_setup_response = ue_context_setup_response_direct; mac_rrc->initial_ul_rrc_message_transfer = initial_ul_rrc_message_transfer_direct; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index 13547c5291..4e175ad68e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -24,6 +24,13 @@ #include "mac_rrc_ul.h" +static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) +{ + AssertFatal(false, "not implemented\n"); + + /* TODO: set up GTP tunnel for DL, and fill UL TEID in resp */ +} + static void initial_ul_rrc_message_transfer_f1ap(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_INITIAL_UL_RRC_MESSAGE); @@ -46,6 +53,7 @@ static void initial_ul_rrc_message_transfer_f1ap(module_id_t module_id, const f1 void mac_rrc_ul_f1ap_init(struct nr_mac_rrc_ul_if_s *mac_rrc) { + mac_rrc->ue_context_setup_response = ue_context_setup_response_f1ap; mac_rrc->initial_ul_rrc_message_transfer = initial_ul_rrc_message_transfer_f1ap; } diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 9f28ffe546..5f25713650 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -660,6 +660,7 @@ typedef struct NR_bler_options { typedef struct nr_mac_rrc_ul_if_s { /* TODO add other message types as necessary */ + ue_context_setup_response_func_t ue_context_setup_response; initial_ul_rrc_message_transfer_func_t initial_ul_rrc_message_transfer; } nr_mac_rrc_ul_if_t; diff --git a/openair2/RRC/NR/mac_rrc_dl.h b/openair2/RRC/NR/mac_rrc_dl.h index 1943490cd6..49ffccd4a7 100644 --- a/openair2/RRC/NR/mac_rrc_dl.h +++ b/openair2/RRC/NR/mac_rrc_dl.h @@ -25,6 +25,8 @@ #include "platform_types.h" #include "f1ap_messages_types.h" +typedef void (*ue_context_setup_request_func_t)(const f1ap_ue_context_setup_t *req); + typedef void (*dl_rrc_message_transfer_func_t)(module_id_t module_id, const f1ap_dl_rrc_message_t *dl_rrc); struct nr_mac_rrc_dl_if_s; diff --git a/openair2/RRC/NR/mac_rrc_dl_direct.c b/openair2/RRC/NR/mac_rrc_dl_direct.c index 5c8d9d9d5b..be416d6921 100644 --- a/openair2/RRC/NR/mac_rrc_dl_direct.c +++ b/openair2/RRC/NR/mac_rrc_dl_direct.c @@ -33,5 +33,6 @@ static void dl_rrc_message_transfer_direct(module_id_t module_id, const f1ap_dl_ void mac_rrc_dl_direct_init(nr_mac_rrc_dl_if_t *mac_rrc) { + mac_rrc->ue_context_setup_request = ue_context_setup_request; mac_rrc->dl_rrc_message_transfer = dl_rrc_message_transfer_direct; } diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 40f3b4b6ea..7030babd1e 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -19,9 +19,17 @@ * conmnc_digit_lengtht@openairinterface.org */ +#include + #include "mac_rrc_dl.h" #include "nr_rrc_defs.h" +static void ue_context_setup_request_f1ap(const f1ap_ue_context_setup_t *req) +{ + (void) req; + abort(); +} + static void dl_rrc_message_transfer_f1ap(module_id_t module_id, const f1ap_dl_rrc_message_t *dl_rrc) { /* TODO call F1AP function directly? no real-time constraint here */ @@ -40,5 +48,6 @@ static void dl_rrc_message_transfer_f1ap(module_id_t module_id, const f1ap_dl_rr void mac_rrc_dl_f1ap_init(nr_mac_rrc_dl_if_t *mac_rrc) { + mac_rrc->ue_context_setup_request = ue_context_setup_request_f1ap; mac_rrc->dl_rrc_message_transfer = dl_rrc_message_transfer_f1ap; } diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 93acdeac7b..942e9ffb1f 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -481,6 +481,7 @@ typedef struct { typedef struct nr_mac_rrc_dl_if_s { /* TODO add other message types as necessary */ + ue_context_setup_request_func_t ue_context_setup_request; dl_rrc_message_transfer_func_t dl_rrc_message_transfer; } nr_mac_rrc_dl_if_t; From 6ced3cd8a76c70e102f3eb55e1ea8ab0dbf49d93 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 12 Apr 2023 14:03:23 +0200 Subject: [PATCH 08/18] Implementation for F1 UE Context Setup+Response in monolithic --- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 126 +++++- .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 27 +- openair2/RRC/NR/rrc_gNB.c | 379 ++---------------- 3 files changed, 186 insertions(+), 346 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 838c68fcb6..4fdad6fb81 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -19,22 +19,132 @@ * contact@openairinterface.org */ -#include - #include "mac_rrc_dl_handler.h" #include "mac_proto.h" -#include "openair2/RRC/NR/rrc_gNB_UE_context.h" #include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h" +#include "openair2/RRC/NR/MESSAGES/asn1_msg.h" -#include "NR_RRCSetup.h" -#include "NR_DL-CCCH-Message.h" -#include "NR_CellGroupConfig.h" +static NR_RLC_BearerConfig_t *get_bearerconfig_from_srb(const f1ap_srb_to_be_setup_t *srb) +{ + long priority = srb->srb_id; // high priority for SRB + e_NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration bucket = + NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms5; + return get_SRB_RLC_BearerConfig(srb->srb_id, priority, bucket); +} + +static void handle_ue_context_srbs_setup(const f1ap_ue_context_setup_t *req, + f1ap_ue_context_setup_t *resp, + NR_CellGroupConfig_t *cellGroupConfig) +{ + DevAssert(req != NULL && resp != NULL && cellGroupConfig != NULL); + + resp->srbs_to_be_setup_length = req->srbs_to_be_setup_length; + resp->srbs_to_be_setup = calloc(req->srbs_to_be_setup_length, sizeof(*resp->srbs_to_be_setup)); + AssertFatal(resp->srbs_to_be_setup != NULL, "out of memory\n"); + for (int i = 0; i < req->srbs_to_be_setup_length; i++) { + f1ap_srb_to_be_setup_t *srb = &req->srbs_to_be_setup[i]; + NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_srb(srb); + nr_rlc_add_srb(req->rnti, srb->srb_id, rlc_BearerConfig); + + resp->srbs_to_be_setup[i] = *srb; + + int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig); + DevAssert(ret == 0); + } +} + +static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_setup_t *drb) +{ + const NR_RLC_Config_PR rlc_conf = drb->rlc_mode == RLC_MODE_UM ? NR_RLC_Config_PR_um_Bi_Directional : NR_RLC_Config_PR_am; + long priority = 13; // hardcoded for the moment + return get_DRB_RLC_BearerConfig(3 + drb->drb_id, drb->drb_id, rlc_conf, priority); +} + +static void handle_ue_context_drbs_setup(const f1ap_ue_context_setup_t *req, + f1ap_ue_context_setup_t *resp, + NR_CellGroupConfig_t *cellGroupConfig) +{ + DevAssert(req != NULL && resp != NULL && cellGroupConfig != NULL); + + /* Note: the actual GTP tunnels are created in the F1AP breanch of + * ue_context_*_response() */ + resp->drbs_to_be_setup_length = req->drbs_to_be_setup_length; + resp->drbs_to_be_setup = calloc(req->drbs_to_be_setup_length, sizeof(*resp->drbs_to_be_setup)); + AssertFatal(resp->drbs_to_be_setup != NULL, "out of memory\n"); + for (int i = 0; i < req->drbs_to_be_setup_length; i++) { + f1ap_drb_to_be_setup_t *drb = &req->drbs_to_be_setup[i]; + NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb); + nr_rlc_add_drb(req->rnti, drb->drb_id, rlc_BearerConfig); + + resp->drbs_to_be_setup[i] = *drb; + + int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig); + DevAssert(ret == 0); + } +} void ue_context_setup_request(const f1ap_ue_context_setup_t *req) { - (void) req; - abort(); + gNB_MAC_INST *mac = RC.nrmac[0]; + /* response has same type as request... */ + f1ap_ue_context_setup_t resp = { + .gNB_CU_ue_id = req->gNB_CU_ue_id, + .gNB_DU_ue_id = req->gNB_DU_ue_id, + .rnti = req->rnti, + }; + + if (req->cu_to_du_rrc_information != NULL) { + AssertFatal(req->cu_to_du_rrc_information->cG_ConfigInfo == NULL, "CG-ConfigInfo not handled\n"); + AssertFatal(req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList == NULL, "UE capabilities not handled yet\n"); + AssertFatal(req->cu_to_du_rrc_information->measConfig == NULL, "MeasConfig not handled\n"); + } + + NR_SCHED_LOCK(&mac->sched_lock); + + NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, req->rnti); + AssertFatal(UE != NULL, "did not find UE with RNTI %04x, but UE Context Setup Failed not implemented\n", UE->rnti); + + if (req->srbs_to_be_setup_length > 0) + handle_ue_context_srbs_setup(req, &resp, UE->CellGroup); + + if (req->drbs_to_be_setup_length > 0) { + handle_ue_context_drbs_setup(req, &resp, NULL); + } + + if (req->rrc_container != NULL) + nr_rlc_srb_recv_sdu(req->rnti, DCCH, req->rrc_container, req->rrc_container_length); + + //nr_mac_update_cellgroup() + resp.du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t)); + AssertFatal(resp.du_to_cu_rrc_information != NULL, "out of memory\n"); + resp.du_to_cu_rrc_information->cellGroupConfig = calloc(1,1024); + AssertFatal(resp.du_to_cu_rrc_information->cellGroupConfig != NULL, "out of memory\n"); + asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, + NULL, + UE->CellGroup, + resp.du_to_cu_rrc_information->cellGroupConfig, + 1024); + 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; + + /* TODO: need to apply after UE context reconfiguration confirmed? */ + process_CellGroup(UE->CellGroup, &UE->UE_sched_ctrl); + + NR_SCHED_UNLOCK(&mac->sched_lock); + + /* some sanity checks, since we use the same type for request and response */ + DevAssert(resp.cu_to_du_rrc_information == NULL); + DevAssert(resp.du_to_cu_rrc_information != NULL); + DevAssert(resp.rrc_container == NULL && resp.rrc_container_length == 0); + + mac->mac_rrc.ue_context_setup_response(req, &resp); + + /* free the memory we allocated above */ + free(resp.srbs_to_be_setup); + free(resp.drbs_to_be_setup); + free(resp.du_to_cu_rrc_information->cellGroupConfig); + free(resp.du_to_cu_rrc_information); } int dl_rrc_message(module_id_t module_id, const f1ap_dl_rrc_message_t *dl_rrc) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index 5402b03000..eafa544185 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -26,8 +26,33 @@ static void ue_context_setup_response_direct(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) { + DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length); + AssertFatal(req->drbs_to_be_setup_length == 0, "not implemented\n"); + (void) req; /* we don't need the request -- it is to set up GTP in F1 case */ - AssertFatal(false, "not implemented\n"); + MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); + f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg); + /* copy all fields, but reallocate memory buffers! */ + *f1ap_msg = *resp; + + if (resp->srbs_to_be_setup_length > 0) { + DevAssert(resp->srbs_to_be_setup != NULL); + f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; + f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); + for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) + f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; + } + + f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information)); + AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); + f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; + du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; + du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; + du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); + AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); + memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); + + itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } static void initial_ul_rrc_message_transfer_direct(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index e2eca3b0bd..93b897f3a8 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2284,71 +2284,10 @@ rrc_gNB_decode_dcch( ul_dcch_msg); } - if (!NODE_IS_CU(gnb_rrc_inst->node_type)) { - if (UE->established_pdu_sessions_flag == 1) { - rrc_gNB_generate_dedicatedRRCReconfiguration(ctxt_pP, ue_context_p, NULL); - } else { - rrc_gNB_generate_defaultRRCReconfiguration(ctxt_pP, ue_context_p); - } + if (UE->established_pdu_sessions_flag == 1) { + rrc_gNB_generate_dedicatedRRCReconfiguration(ctxt_pP, ue_context_p, NULL); } else { - /*Generate a UE context setup request message towards the DU to provide the UE - *capability info and get the updates on master cell group config from the DU*/ - MessageDef *message_p; - message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_SETUP_REQ); - f1ap_ue_context_setup_t *req=&F1AP_UE_CONTEXT_SETUP_REQ (message_p); - //UE_IDs will be extracted from F1AP layer - req->gNB_CU_ue_id = 0; - req->gNB_DU_ue_id = 0; - req->rnti = UE->rnti; - req->mcc = gnb_rrc_inst->configuration.mcc[0]; - req->mnc = gnb_rrc_inst->configuration.mnc[0]; - req->mnc_digit_length = gnb_rrc_inst->configuration.mnc_digit_length[0]; - req->nr_cellid = gnb_rrc_inst->nr_cellid; - - if (UE->established_pdu_sessions_flag == 1) { - /*Instruction towards the DU for SRB2 configuration*/ - req->srbs_to_be_setup = malloc(1*sizeof(f1ap_srb_to_be_setup_t)); - req->srbs_to_be_setup_length = 1; - f1ap_srb_to_be_setup_t *SRBs=req->srbs_to_be_setup; - SRBs[0].srb_id = 2; - SRBs[0].lcid = 2; - - /*Instruction towards the DU for DRB configuration and tunnel creation*/ - req->drbs_to_be_setup = malloc(1*sizeof(f1ap_drb_to_be_setup_t)); - req->drbs_to_be_setup_length = 1; - f1ap_drb_to_be_setup_t *DRBs=req->drbs_to_be_setup; - LOG_I(RRC, "Length of DRB list:%d \n", req->drbs_to_be_setup_length); - DRBs[0].drb_id = 1; - DRBs[0].rlc_mode = RLC_MODE_AM; - DRBs[0].up_ul_tnl[0].tl_address = inet_addr(gnb_rrc_inst->eth_params_s.my_addr); - DRBs[0].up_ul_tnl[0].port = gnb_rrc_inst->eth_params_s.my_portd; - DRBs[0].up_ul_tnl_length = 1; - DRBs[0].up_dl_tnl[0].tl_address = inet_addr(gnb_rrc_inst->eth_params_s.remote_addr); - DRBs[0].up_dl_tnl[0].port = gnb_rrc_inst->eth_params_s.remote_portd; - DRBs[0].up_dl_tnl_length = 1; - } - if( ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.present == - NR_UECapabilityInformation__criticalExtensions_PR_ueCapabilityInformation ) { - struct NR_UE_CapabilityRAT_ContainerList *ue_CapabilityRAT_ContainerList = - ul_dcch_msg->message.choice.c1->choice.ueCapabilityInformation->criticalExtensions.choice.ueCapabilityInformation->ue_CapabilityRAT_ContainerList; - if(ue_CapabilityRAT_ContainerList!=NULL){ - LOG_I(NR_RRC, "ue_CapabilityRAT_ContainerList is present \n"); - req->cu_to_du_rrc_information = calloc(1,sizeof(cu_to_du_rrc_information_t)); - req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList = calloc(1,4096); - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_UE_CapabilityRAT_ContainerList, - NULL, - ue_CapabilityRAT_ContainerList, - req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList, - 4096); - AssertFatal (enc_rval.encoded > 0, "ASN1 ue_CapabilityRAT_ContainerList encoding failed (%s, %jd)!\n", - enc_rval.failed_type->name, enc_rval.encoded); - req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length = (enc_rval.encoded+7)>>3; - } - else{ - LOG_I(NR_RRC, "ue_CapabilityRAT_ContainerList is not present \n"); - } - } - itti_send_msg_to_task (TASK_CU_F1, ctxt_pP->module_id, message_p); + rrc_gNB_generate_defaultRRCReconfiguration(ctxt_pP, ue_context_p); } break; @@ -2524,233 +2463,6 @@ void rrc_gNB_process_dc_overall_timeout(const module_id_t gnb_mod_idP, x2ap_ENDC rrc_remove_nsa_user(rrc, m->rnti); } -static void rrc_DU_process_ue_context_setup_request(MessageDef *msg_p, instance_t instance) -{ - f1ap_ue_context_setup_t * req=&F1AP_UE_CONTEXT_SETUP_REQ(msg_p); - gNB_RRC_INST *rrc = RC.nrrrc[instance]; - gNB_MAC_INST *mac = RC.nrmac[instance]; - rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, req->rnti); - gNB_RRC_UE_t *UE = &ue_context_p->ue_context; - MessageDef *message_p; - message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); - f1ap_ue_context_setup_t * resp=&F1AP_UE_CONTEXT_SETUP_RESP(message_p); - uint32_t incoming_teid = 0; - - if(req->cu_to_du_rrc_information!=NULL){ - if(req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList!=NULL){ - LOG_I(NR_RRC, "Length of ue_CapabilityRAT_ContainerList is: %d \n", (int) req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length); - struct NR_UE_CapabilityRAT_ContainerList *ue_CapabilityRAT_ContainerList = NULL; - asn_dec_rval_t dec_rval = uper_decode_complete( NULL, - &asn_DEF_NR_UE_CapabilityRAT_ContainerList, - (void **)&ue_CapabilityRAT_ContainerList, - (uint8_t *)req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList, - (int) req->cu_to_du_rrc_information->uE_CapabilityRAT_ContainerList_length); - - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - AssertFatal(1==0,"UE Capability RAT ContainerList decode error\n"); - // free the memory - SEQUENCE_free( &asn_DEF_NR_UE_CapabilityRAT_ContainerList, ue_CapabilityRAT_ContainerList, 1 ); - return; - } - //To fill ue_context.UE_Capability_MRDC, ue_context.UE_Capability_nr ... - int NR_index = -1; - for(int i = 0;i < ue_CapabilityRAT_ContainerList->list.count; i++){ - if(ue_CapabilityRAT_ContainerList->list.array[i]->rat_Type == - NR_RAT_Type_nr){ - LOG_I(NR_RRC, "DU received NR_RAT_Type_nr UE capabilities Info through the UE Context Setup Request from the CU \n"); - if (UE->UE_Capability_nr) { - ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); - UE->UE_Capability_nr = 0; - } - - dec_rval = uper_decode(NULL, - &asn_DEF_NR_UE_NR_Capability, - (void **)&UE->UE_Capability_nr, - ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.buf, - ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.size, - 0, - 0); - if(LOG_DEBUGFLAG(DEBUG_ASN1)){ - xer_fprint(stdout, &asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); - } - - if((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)){ - LOG_E(NR_RRC, "UE %04x Failed to decode nr UE capabilities (%zu bytes)\n", req->rnti, dec_rval.consumed); - ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->UE_Capability_nr); - UE->UE_Capability_nr = 0; - } - - UE->UE_Capability_size = ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.size; - if(NR_index != -1){ - LOG_E(NR_RRC,"fatal: more than 1 eutra capability\n"); - exit(1); - } - NR_index = i; - } - - if(ue_CapabilityRAT_ContainerList->list.array[i]->rat_Type == - NR_RAT_Type_eutra_nr){ - LOG_I(NR_RRC, "DU received NR_RAT_Type_eutra_nr UE capabilities Info through the UE Context Setup Request from the CU \n"); - if (UE->UE_Capability_MRDC) { - ASN_STRUCT_FREE(asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC); - UE->UE_Capability_MRDC = 0; - } - dec_rval = uper_decode(NULL, - &asn_DEF_NR_UE_MRDC_Capability, - (void **)&UE->UE_Capability_MRDC, - ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.buf, - ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.size, - 0, - 0); - if(LOG_DEBUGFLAG(DEBUG_ASN1)){ - xer_fprint(stdout, &asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC); - } - - if((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)){ - LOG_E(NR_RRC, "UE %04x Failed to decode nr UE capabilities (%zu bytes)\n", req->rnti, dec_rval.consumed); - ASN_STRUCT_FREE(asn_DEF_NR_UE_MRDC_Capability, UE->UE_Capability_MRDC); - UE->UE_Capability_MRDC = 0; - } - UE->UE_MRDC_Capability_size = ue_CapabilityRAT_ContainerList->list.array[i]->ue_CapabilityRAT_Container.size; - } - - if(ue_CapabilityRAT_ContainerList->list.array[i]->rat_Type == - NR_RAT_Type_eutra){ - //TODO - } - } - } - } - - - /* Configure SRB2 */ - NR_SRB_ToAddMod_t *SRB2_config = NULL; - NR_SRB_ToAddModList_t *SRB_configList = NULL; - uint8_t SRBs_before_new_addition = 0; - - if(req->srbs_to_be_setup_length>0){ - if (UE->SRB_configList == NULL) { - LOG_W(NR_RRC, "The SRB list of the UE context is empty before the addition of new SRB at the DU \n"); - UE->SRB_configList = CALLOC(1, sizeof(*UE->SRB_configList)); - } - SRB_configList = UE->SRB_configList; - SRBs_before_new_addition = SRB_configList->list.count; - for (int i=0; isrbs_to_be_setup_length; i++){ - SRB2_config = CALLOC(1, sizeof(*SRB2_config)); - SRB2_config->srb_Identity = req->srbs_to_be_setup[i].srb_id; - asn1cSeqAdd(&SRB_configList->list, SRB2_config); - } - } - - /* Configure DRB */ - NR_DRB_ToAddMod_t *DRB_config = NULL; - NR_DRB_ToAddModList_t *DRB_configList = NULL; - uint8_t drb_id_to_setup_start = 0; - uint8_t nb_drb_to_setup = 0; - long drb_priority[NGAP_MAX_DRBS_PER_UE]; - if(req->drbs_to_be_setup_length>0){ - if (UE->DRB_configList == NULL) { - UE->DRB_configList = CALLOC(1, sizeof(*UE->DRB_configList)); - } - DRB_configList = UE->DRB_configList; - nb_drb_to_setup = req->drbs_to_be_setup_length; - for (int i=0; idrbs_to_be_setup_length; i++){ - DRB_config = CALLOC(1, sizeof(*DRB_config)); - DRB_config->drb_Identity = req->drbs_to_be_setup[i].drb_id; - if (drb_id_to_setup_start == 0) drb_id_to_setup_start = DRB_config->drb_Identity; - asn1cSeqAdd(&DRB_configList->list, DRB_config); - f1ap_drb_to_be_setup_t drb_p = req->drbs_to_be_setup[i]; - transport_layer_addr_t addr; - memcpy(addr.buffer, &drb_p.up_ul_tnl[0].tl_address, sizeof(drb_p.up_ul_tnl[0].tl_address)); - addr.length=sizeof(drb_p.up_ul_tnl[0].tl_address)*8; - extern instance_t DUuniqInstance; - incoming_teid = newGtpuCreateTunnel(DUuniqInstance, - req->rnti, - drb_p.drb_id, - drb_p.drb_id, - drb_p.up_ul_tnl[0].teid, - -1, // no qfi - addr, - drb_p.up_ul_tnl[0].port, - DURecvCb, - NULL); - /* TODO: hardcoded to 13 for the time being, to be changed? */ - drb_priority[DRB_config->drb_Identity-1] = 13; - } - } - - NR_CellGroupConfig_t *cellGroupConfig = calloc(1, sizeof(NR_CellGroupConfig_t)); - if (req->srbs_to_be_setup_length > 0 || req->drbs_to_be_setup_length>0) - // FIXME: fill_mastercellGroupConfig() won't fill the right priorities or - // bearer IDs for the DRBs - fill_mastercellGroupConfig(cellGroupConfig, UE->masterCellGroup, rrc->um_on_default_drb, SRB2_config ? 1 : 0, drb_id_to_setup_start, nb_drb_to_setup, drb_priority); - protocol_ctxt_t ctxt = {.rntiMaybeUEid = req->rnti, .module_id = instance, .instance = instance, .enb_flag = 1, .eNB_index = instance}; - apply_macrlc_config(rrc, ue_context_p, &ctxt); - - if(req->rrc_container_length > 0){ - mem_block_t *pdcp_pdu_p = get_free_mem_block(req->rrc_container_length, __func__); - memcpy(&pdcp_pdu_p->data[0], req->rrc_container, req->rrc_container_length); - du_rlc_data_req(&ctxt, 1, 0x00, 1, 1, 0, req->rrc_container_length, pdcp_pdu_p); - LOG_I(F1AP, "Printing RRC Container of UE context setup request: \n"); - for (int j=0; jrrc_container_length; j++){ - printf("%02x ", pdcp_pdu_p->data[j]); - } - printf("\n"); - } - - /* Fill the UE context setup response ITTI message to send to F1AP */ - resp->gNB_CU_ue_id = req->gNB_CU_ue_id; - resp->rnti = req->rnti; - if(DRB_configList){ - if(DRB_configList->list.count > 0){ - resp->drbs_to_be_setup = calloc(1,DRB_configList->list.count*sizeof(f1ap_drb_to_be_setup_t)); - resp->drbs_to_be_setup_length = DRB_configList->list.count; - for (int i=0; ilist.count; i++){ - resp->drbs_to_be_setup[i].drb_id = DRB_configList->list.array[i]->drb_Identity; - resp->drbs_to_be_setup[i].rlc_mode = RLC_MODE_AM; - resp->drbs_to_be_setup[i].up_dl_tnl[0].teid = incoming_teid; - resp->drbs_to_be_setup[i].up_dl_tnl[0].tl_address = inet_addr(mac->eth_params_n.my_addr); - resp->drbs_to_be_setup[i].up_dl_tnl_length = 1; - } - } - else{ - LOG_W(NR_RRC, "No DRB added upon reception of F1 UE context setup request with a DRB to setup list\n"); - } - } - if(SRB_configList){ - if(SRB_configList->list.count >0 && SRBs_before_new_addition < SRB_configList->list.count){ - resp->srbs_to_be_setup = calloc(1,req->srbs_to_be_setup_length*sizeof(f1ap_srb_to_be_setup_t)); - resp->srbs_to_be_setup_length = req->srbs_to_be_setup_length; - for (int i=SRBs_before_new_addition; ilist.count; i++){ - resp->srbs_to_be_setup[i-SRBs_before_new_addition].srb_id = SRB_configList->list.array[i]->srb_Identity; - } - } - else{ - LOG_W(NR_RRC, "No SRB added upon reception of F1 UE Context setup request at the DU\n"); - } - } - else{ - LOG_W(NR_RRC, "No SRB added upon reception of F1 UE Context setup request at the DU\n"); - } - /* fixme: - * Here we should be encoding the updates on cellgroupconfig based on the content of UE capabilities - */ - resp->du_to_cu_rrc_information = calloc(1, sizeof(du_to_cu_rrc_information_t)); - resp->du_to_cu_rrc_information->cellGroupConfig = calloc(1,1024); - asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, - NULL, - UE->masterCellGroup, //(void *)cellGroupConfig, - resp->du_to_cu_rrc_information->cellGroupConfig, - 1024); - if (enc_rval.encoded == -1) { - LOG_E(F1AP,"Could not encode ue_context.masterCellGroup, failed element %s\n",enc_rval.failed_type->name); - exit(-1); - } - resp->du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded+7)>>3; - free(cellGroupConfig); - itti_send_msg_to_task(TASK_DU_F1, instance, message_p); -} - static void rrc_DU_process_ue_context_modification_request(MessageDef *msg_p, instance_t instance) { f1ap_ue_context_setup_t * req=&F1AP_UE_CONTEXT_MODIFICATION_REQ(msg_p); @@ -2898,54 +2610,29 @@ static void rrc_DU_process_ue_context_modification_request(MessageDef *msg_p, in static void rrc_CU_process_ue_context_setup_response(MessageDef *msg_p, instance_t instance) { f1ap_ue_context_setup_t * resp=&F1AP_UE_CONTEXT_SETUP_RESP(msg_p); - protocol_ctxt_t ctxt = {.rntiMaybeUEid = resp->rnti, .module_id = instance, .instance = instance, .enb_flag = 1, .eNB_index = instance}; - gNB_RRC_INST *rrc = RC.nrrrc[ctxt.module_id]; + gNB_RRC_INST *rrc = RC.nrrrc[instance]; rrc_gNB_ue_context_t *ue_context_p = rrc_gNB_get_ue_context_by_rnti(rrc, resp->rnti); gNB_RRC_UE_t *UE = &ue_context_p->ue_context; + NR_CellGroupConfig_t *cellGroupConfig = NULL; + asn_dec_rval_t dec_rval = uper_decode_complete(NULL, + &asn_DEF_NR_CellGroupConfig, + (void **)&cellGroupConfig, + (uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig, + resp->du_to_cu_rrc_information->cellGroupConfig_length); + AssertFatal(dec_rval.code == RC_OK && dec_rval.consumed > 0, "Cell group config decode error\n"); - asn_dec_rval_t dec_rval = uper_decode_complete( NULL, - &asn_DEF_NR_CellGroupConfig, - (void **)&cellGroupConfig, - (uint8_t *)resp->du_to_cu_rrc_information->cellGroupConfig, - (int) resp->du_to_cu_rrc_information->cellGroupConfig_length); - - if ((dec_rval.code != RC_OK) && (dec_rval.consumed == 0)) { - AssertFatal(1==0,"Cell group config decode error\n"); - // free the memory - SEQUENCE_free( &asn_DEF_NR_CellGroupConfig, cellGroupConfig, 1 ); - return; + if (UE->masterCellGroup) { + ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); + LOG_I(RRC, "UE %04x replacing existing CellGroupConfig with new one received from DU\n", UE->rnti); } - //xer_fprint(stdout,&asn_DEF_NR_CellGroupConfig, cellGroupConfig); - - if (UE->masterCellGroup == NULL) { - UE->masterCellGroup = calloc(1, sizeof(NR_CellGroupConfig_t)); - } - if(cellGroupConfig->rlc_BearerToAddModList!=NULL){ - if (UE->masterCellGroup->rlc_BearerToAddModList != NULL) { - int ue_ctxt_rlc_Bearers = UE->masterCellGroup->rlc_BearerToAddModList->list.count; - for(int i=ue_ctxt_rlc_Bearers; irlc_BearerToAddModList->list.count; i++){ - asn1cSeqAdd(&UE->masterCellGroup->rlc_BearerToAddModList->list, cellGroupConfig->rlc_BearerToAddModList->list.array[i - ue_ctxt_rlc_Bearers]); - } - } else { - LOG_W(NR_RRC, "Empty rlc_BearerToAddModList at ue_context of the CU before filling the updates from UE context setup response \n"); - UE->masterCellGroup->rlc_BearerToAddModList = calloc(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList)); - memcpy(UE->masterCellGroup->rlc_BearerToAddModList, cellGroupConfig->rlc_BearerToAddModList, sizeof(*cellGroupConfig->rlc_BearerToAddModList)); - } - } - if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + UE->masterCellGroup = cellGroupConfig; + if (LOG_DEBUGFLAG(DEBUG_ASN1)) xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, UE->masterCellGroup); - } - if (UE->established_pdu_sessions_flag == 1) { - fill_DRB_configList(&ctxt, ue_context_p); - rrc_gNB_generate_dedicatedRRCReconfiguration(&ctxt, ue_context_p, cellGroupConfig); - } else { - rrc_gNB_generate_defaultRRCReconfiguration(&ctxt, ue_context_p); - } - - free(cellGroupConfig->rlc_BearerToAddModList); - free(cellGroupConfig); + /* at this point, we don't have to do anything: the UE context setup request + * includes the Security Command, whose response will trigger the following + * messages (UE capability, to be specific) */ } static void rrc_CU_process_ue_context_modification_response(MessageDef *msg_p, instance_t instance) @@ -3507,10 +3194,6 @@ void *rrc_gnb_task(void *args_p) { AssertFatal(NODE_IS_CU(RC.nrrrc[instance]->node_type), "should not receive F1AP_SETUP_REQUEST, need call by CU!\n"); rrc_gNB_process_f1_setup_req(&F1AP_SETUP_REQ(msg_p)); break; - - case F1AP_UE_CONTEXT_SETUP_REQ: - rrc_DU_process_ue_context_setup_request(msg_p, instance); - break; case F1AP_UE_CONTEXT_SETUP_RESP: rrc_CU_process_ue_context_setup_response(msg_p, instance); @@ -3582,6 +3265,27 @@ void *rrc_gnb_task(void *args_p) { } } +static void rrc_deliver_ue_ctxt_setup_req(void *deliver_pdu_data, ue_id_t ue_id, int srb_id, char *buf, int size, int sdu_id) +{ + DevAssert(deliver_pdu_data != NULL); + gNB_RRC_INST *rrc = deliver_pdu_data; + f1ap_ue_context_setup_t ue_context_setup_req = { + .gNB_CU_ue_id = 0xffffffff, /* filled by F1 for the moment */ + .gNB_DU_ue_id = 0xffffffff, /* filled by F1 for the moment */ + .rnti = ue_id, + .mcc = rrc->configuration.mcc[0], + .mnc = rrc->configuration.mnc[0], + .mnc_digit_length = rrc->configuration.mnc_digit_length[0], + .nr_cellid = rrc->nr_cellid, + .servCellId = 0, /* TODO: correct value? */ + .srbs_to_be_setup = 0, /* no new SRBs */ + .drbs_to_be_setup = 0, /* no new DRBs */ + .rrc_container = (uint8_t*) buf, /* security mode command */ + .rrc_container_length = size, + }; + rrc->mac_rrc.ue_context_setup_request(&ue_context_setup_req); +} + //----------------------------------------------------------------------------- void rrc_gNB_generate_SecurityModeCommand( @@ -3603,7 +3307,8 @@ rrc_gNB_generate_SecurityModeCommand( gNB_RRC_INST *rrc = RC.nrrrc[ctxt_pP->module_id]; AssertFatal(!NODE_IS_DU(rrc->node_type), "illegal node type DU!\n"); - nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, deliver_pdu_srb_f1, rrc); + /* the callback will fill the UE context setup request and forward it */ + nr_pdcp_data_req_srb(ctxt_pP->rntiMaybeUEid, DCCH, rrc_gNB_mui++, size, buffer, rrc_deliver_ue_ctxt_setup_req, rrc); } void From ca30b9ee5552ad6eda2e90de5eb7e30b8ffaf054 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 24 Apr 2023 14:27:12 +0200 Subject: [PATCH 09/18] Implement F1/split case for UE Context Setup --- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 33 ++++++++++++++++++-- openair2/RRC/NR/mac_rrc_dl_f1ap.c | 14 +++++++-- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index 4e175ad68e..c5bcb8814a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -19,16 +19,45 @@ * conmnc_digit_lengtht@openairinterface.org */ +#include +#include +#include + #include "nr_mac_gNB.h" #include "intertask_interface.h" +#include "openair3/ocp-gtpu/gtp_itf.h" #include "mac_rrc_ul.h" static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) { - AssertFatal(false, "not implemented\n"); + DevAssert(req->drbs_to_be_setup_length == resp->drbs_to_be_setup_length); + AssertFatal(req->drbs_to_be_setup_length == 0, "not implmented\n"); - /* TODO: set up GTP tunnel for DL, and fill UL TEID in resp */ + DevAssert(req->srbs_to_be_setup_length == resp->srbs_to_be_setup_length); + MessageDef *msg = itti_alloc_new_message (TASK_MAC_GNB, 0, F1AP_UE_CONTEXT_SETUP_RESP); + f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_RESP(msg); + /* copy all fields, but reallocate rrc_containers! */ + *f1ap_msg = *resp; + + if (resp->srbs_to_be_setup_length > 0) { + DevAssert(resp->srbs_to_be_setup != NULL); + f1ap_msg->srbs_to_be_setup_length = resp->srbs_to_be_setup_length; + f1ap_msg->srbs_to_be_setup = calloc(f1ap_msg->srbs_to_be_setup_length, sizeof(*f1ap_msg->srbs_to_be_setup)); + for (int i = 0; i < f1ap_msg->srbs_to_be_setup_length; ++i) + f1ap_msg->srbs_to_be_setup[i] = resp->srbs_to_be_setup[i]; + } + + f1ap_msg->du_to_cu_rrc_information = malloc(sizeof(*resp->du_to_cu_rrc_information)); + AssertFatal(f1ap_msg->du_to_cu_rrc_information != NULL, "out of memory\n"); + f1ap_msg->du_to_cu_rrc_information_length = resp->du_to_cu_rrc_information_length; + du_to_cu_rrc_information_t *du2cu = f1ap_msg->du_to_cu_rrc_information; + du2cu->cellGroupConfig_length = resp->du_to_cu_rrc_information->cellGroupConfig_length; + du2cu->cellGroupConfig = calloc(du2cu->cellGroupConfig_length, sizeof(*du2cu->cellGroupConfig)); + AssertFatal(du2cu->cellGroupConfig != NULL, "out of memory\n"); + memcpy(du2cu->cellGroupConfig, resp->du_to_cu_rrc_information->cellGroupConfig, du2cu->cellGroupConfig_length); + + itti_send_msg_to_task(TASK_DU_F1, 0, msg); } static void initial_ul_rrc_message_transfer_f1ap(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc) diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 7030babd1e..9bbddaf476 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -26,8 +26,18 @@ static void ue_context_setup_request_f1ap(const f1ap_ue_context_setup_t *req) { - (void) req; - abort(); + MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_UE_CONTEXT_SETUP_REQ); + f1ap_ue_context_setup_t *f1ap_msg = &F1AP_UE_CONTEXT_SETUP_REQ(msg); + *f1ap_msg = *req; + AssertFatal(req->cu_to_du_rrc_information == NULL, "cu_to_du_rrc_information not supported yet\n"); + f1ap_msg->cu_to_du_rrc_information = malloc(sizeof(*f1ap_msg->cu_to_du_rrc_information)); + if (req->rrc_container_length > 0) { + f1ap_msg->rrc_container = calloc(req->rrc_container_length, sizeof(*f1ap_msg->rrc_container)); + AssertFatal(f1ap_msg->rrc_container != NULL, "out of memory\n"); + f1ap_msg->rrc_container_length = req->rrc_container_length; + memcpy(f1ap_msg->rrc_container, req->rrc_container, req->rrc_container_length); + } + itti_send_msg_to_task(TASK_CU_F1, 0, msg); } static void dl_rrc_message_transfer_f1ap(module_id_t module_id, const f1ap_dl_rrc_message_t *dl_rrc) From 1eb4f857afcb880e2d3172c1d9b12f4b9b80f0e5 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 16 Apr 2023 14:12:07 +0200 Subject: [PATCH 10/18] UE Capabilities: we request during RRC Connection Setup, so no PDU sessions --- openair2/RRC/NR/rrc_gNB.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 93b897f3a8..8f4a3a3a4d 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2284,11 +2284,12 @@ rrc_gNB_decode_dcch( ul_dcch_msg); } - if (UE->established_pdu_sessions_flag == 1) { - rrc_gNB_generate_dedicatedRRCReconfiguration(ctxt_pP, ue_context_p, NULL); - } else { - rrc_gNB_generate_defaultRRCReconfiguration(ctxt_pP, ue_context_p); - } + // we send the UE capabilities request before RRC connection is complete, + // so we cannot have a PDU session yet + AssertFatal(UE->established_pdu_sessions_flag == 0, "logic bug: received capabilities while PDU session established\n"); + // TODO: send UE context modification response with UE capabilities to + // allow DU configure CellGroupConfig + rrc_gNB_generate_defaultRRCReconfiguration(ctxt_pP, ue_context_p); break; From 67c7d5233320c79d7f6cb35bcc7ef22d649ce187 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Sun, 16 Apr 2023 14:12:49 +0200 Subject: [PATCH 11/18] Default RRC Connection <-> no PDU sessions --- openair2/RRC/NR/rrc_gNB.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 8f4a3a3a4d..81a17afab1 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -496,6 +496,7 @@ static void rrc_gNB_generate_defaultRRCReconfiguration(const protocol_ctxt_t *co /******************** Radio Bearer Config ********************/ gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context; + AssertFatal(ue_p->nb_of_pdusessions == 0, "logic bug: PDU sessions present before RRC Connection established\n"); struct NR_RRCReconfiguration_v1530_IEs__dedicatedNAS_MessageList *dedicatedNAS_MessageList = CALLOC(1, sizeof(*dedicatedNAS_MessageList)); From 3eea99a3125f22f53b4051f6cdcc750218f3bae9 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 27 Apr 2023 20:47:19 +0200 Subject: [PATCH 12/18] Add documentation for internal F1 interface --- doc/F1-design.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/doc/F1-design.md b/doc/F1-design.md index 80417b1ae3..7e491f5346 100644 --- a/doc/F1-design.md +++ b/doc/F1-design.md @@ -11,6 +11,7 @@ + # 1. Introduction We use OpenAirInterface source code, and it's regular deployment scheme. @@ -208,3 +209,46 @@ DU rlc north output goes to du_pdcp_data_ind() that push a outgoing packet reque CU pdcp south output calls cu_rlc_data_ind() that do the same symetric processing. +# High-level F1-C code structure + +The F1 interface is used internally between CU (mostly RRC) and DU (mostly MAC) +to exchange information. In DL, the CU sends messages as defined by the +callbacks in `mac_rrc_dl.h`, whose implementation is defined in files +`mac_rrc_dl_direct.c` (monolithic) and `mac_rrc_dl_f1ap.c` (for F1AP). In the +monolithic case, the RRC calls directly into the message handler on the DU side +(`mac_rrc_dl_handler.c`). In the F1 case, an ITTI message is sent to the CU +task, sending an ASN.1-encoded F1AP message. The DU side's DU task decodes the +message, and then calls the corresponding handler in `mac_rrc_dl_handler.c`. +Thus, the message flow is the same in both F1 and monolithic cases, with the +difference that F1AP encodes the messages using ASN.1 and sends over a socket. + +In UL, the callbacks defined in `mac_rrc_ul.h` are implemented by +`mac_rrc_ul_direct.c` (monolithic) and `mac_rrc_ul_f1ap.c` (F1). In the direct +case, an ITTI message is directly sent to the RRC task (hence, there is no +dedicated handler). In F1, the DU task receives the ITTI message, encodes using +ASN.1, and sends it over a network socket. The CU task decodes, and sends the +same ITTI message to the RRC task as done directly in the monolithic case. + +``` + +-------------+ + | | + | CU/RRC | + | | + +-------------+ + | ^ + Callback def: mac_rrc_dl.h | | No handler needed: + F1 impl: mac_rrc_dl_f1ap.c | | RRC has ITTI +Monolithic: mac_rrc_dl_direct.c | | + | | + DL | | UL + | | + | | Callback def: mac_rrc_ul.h + Message handler: | | F1 impl: mac_rrc_ul_f1ap.c + mac_rrc_dl_handler.c | | Monolithic: mac_rrc_ul_direct.c + v | + +-------------+ + | | + | DU/MAC | + | | + +-------------+ +``` From 8e30f99eeea183724d283227e4f2c3c59cc87265 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 2 May 2023 17:30:12 +0200 Subject: [PATCH 13/18] CI: docker-compose file for OAI DU with Accelleran CU --- .../docker-compose.yaml | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 ci-scripts/yaml_files/5g_rfsimulator_accelleran/docker-compose.yaml diff --git a/ci-scripts/yaml_files/5g_rfsimulator_accelleran/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_accelleran/docker-compose.yaml new file mode 100644 index 0000000000..3551cc27c6 --- /dev/null +++ b/ci-scripts/yaml_files/5g_rfsimulator_accelleran/docker-compose.yaml @@ -0,0 +1,38 @@ +version: '3.8' +services: + oai-du: + image: oaisoftwarealliance/oai-gnb:develop + privileged: true + container_name: rfsim5g-oai-du + network_mode: "host" + environment: + RFSIMULATOR: server + USE_VOLUMED_CONF: 'yes' + USE_ADDITIONAL_OPTIONS: --sa --rfsim --MACRLCs.[0].local_n_address 172.21.16.109 --MACRLCs.[0].remote_n_address 172.21.6.22 --log_config.global_log_options level,nocolor,time + volumes: + - ../../conf_files/gnb-du.band78.106prb.rfsim.conf:/opt/oai-gnb/etc/mounted.conf + healthcheck: + test: /bin/bash -c "pgrep nr-softmodem" + interval: 10s + timeout: 5s + retries: 5 + oai-nr-ue: + image: oaisoftwarealliance/oai-nr-ue:develop + privileged: true + container_name: rfsim5g-oai-nr-ue + network_mode: "host" + environment: + RFSIMULATOR: 127.0.0.1 + FULL_IMSI: '208990100001140' + FULL_KEY: 'fec86ba6eb707ed08905757b1bb44b8f' + OPC: 'C42449363BBAD02B66D16BC975D77CC1' + DNN: oai + NSSAI_SST: 1 + USE_ADDITIONAL_OPTIONS: --sa --rfsim -r 106 --numerology 1 -C 3619200000 --log_config.global_log_options level,nocolor,time + depends_on: + - oai-du + healthcheck: + test: /bin/bash -c "pgrep nr-uesoftmodem" + interval: 10s + timeout: 5s + retries: 5 From 3e282f95739978928005092e34fb9b6af29fe854 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 2 May 2023 17:52:13 +0200 Subject: [PATCH 14/18] Add Accelleran-CU interoperability test --- .../container_5g_rfsim_f1_accelleran.xml | 74 +++++++++++++++++++ .../container_5g_rfsim_f1_accelleran_down.xml | 45 +++++++++++ 2 files changed, 119 insertions(+) create mode 100644 ci-scripts/xml_files/container_5g_rfsim_f1_accelleran.xml create mode 100644 ci-scripts/xml_files/container_5g_rfsim_f1_accelleran_down.xml diff --git a/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran.xml b/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran.xml new file mode 100644 index 0000000000..d727fdfd1e --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran.xml @@ -0,0 +1,74 @@ + + + rfsim-5gnr-f1-accelleran + F1 DU Interop Accelleran CU + wrench + + 111111 + 000020 + 000021 + 020021 + 100021 + 100022 + + + + + Pull_Local_Registry + Pull Images from Local Registry + 0 + oai-gnb oai-nr-ue + + + + DeployGenObject + Deploy OAI-DU + yaml_files/5g_rfsimulator_accelleran + oai-du + 1 + + + + DeployGenObject + Deploy nrUE + yaml_files/5g_rfsimulator_accelleran + oai-nr-ue + 2 + + + + PingFromContainer + Test Connectivity (ping) + rfsim5g-oai-nr-ue + -I oaitun_ue1 -c 20 12.1.1.1 + 0 + + + + UndeployGenObject + Undeploy all OAI 5G stack + yaml_files/5g_rfsimulator_accelleran + + + diff --git a/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran_down.xml b/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran_down.xml new file mode 100644 index 0000000000..0a4f9fcbfa --- /dev/null +++ b/ci-scripts/xml_files/container_5g_rfsim_f1_accelleran_down.xml @@ -0,0 +1,45 @@ + + + rfsim-5gnr-down-f1-accelleran + CleanUp + trash + + 100022 + 222222 + + + + + UndeployGenObject + Undeploy all OAI 5G stack + yaml_files/5g_rfsimulator_accelleran + + + + Clean_Test_Server_Images + Clean Test Images on Test Server + 0 + + + From 3ea2afdca523cb90f0799c501f5875a11bfcef5f Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 3 May 2023 16:12:45 +0200 Subject: [PATCH 15/18] Fix NSA: lock scheduler before removing UE --- openair2/RRC/NR/rrc_gNB_nsa.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c index bf69aa703b..250402a2cf 100644 --- a/openair2/RRC/NR/rrc_gNB_nsa.c +++ b/openair2/RRC/NR/rrc_gNB_nsa.c @@ -401,8 +401,11 @@ void rrc_remove_nsa_user(gNB_RRC_INST *rrc, int rnti) { rrc_rlc_remove_ue(&ctxt); - // WHAT A RACE CONDITION + // 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; From a990cba81ff587f6f2cded6f84c58bd64059e3dd Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 3 May 2023 16:20:03 +0200 Subject: [PATCH 16/18] Add Interop-F1 pipeline to RAN-Container-Parent Jenkinsfile --- ci-scripts/Jenkinsfile-GitLab-Container | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index 118eb844d4..d97219bfc8 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -425,6 +425,26 @@ pipeline { } } } + stage ("Interop-F1") { + when { expression {do5Gtest} } + steps { + script { + triggerSlaveJob ('RAN-Interop-F1', 'Interop-F1') + } + } + post { + always { + script { + finalizeSlaveJob('RAN-Interop-F1') + } + } + failure { + script { + currentBuild.result = 'FAILURE' + } + } + } + } //avra is offline, re-enable once it is available //stage ("T1-Offload-Test") { From 375a11b1191dda4f258eab1aadeeea7bdd9ba403 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Wed, 3 May 2023 16:20:38 +0200 Subject: [PATCH 17/18] Remove non-existing T1-Offload-Test pipeline from RAN-Container-Parent Jenkinsfile --- ci-scripts/Jenkinsfile-GitLab-Container | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/ci-scripts/Jenkinsfile-GitLab-Container b/ci-scripts/Jenkinsfile-GitLab-Container index d97219bfc8..ebb2fbd5e0 100644 --- a/ci-scripts/Jenkinsfile-GitLab-Container +++ b/ci-scripts/Jenkinsfile-GitLab-Container @@ -445,28 +445,6 @@ pipeline { } } } - - //avra is offline, re-enable once it is available - //stage ("T1-Offload-Test") { - // when { expression {do5Gtest} } - // steps { - // script { - // triggerSlaveJob ('RAN-T1-Offload-Test', 'T1-Offload-Test') - // } - // } - // post { - // always { - // script { - // finalizeSlaveJob('RAN-T1-Offload-Test') - // } - // } - // failure { - // script { - // currentBuild.result = 'FAILURE' - // } - // } - // } - //} } } stage ("DockerHub-Push") { From da2ba65685933b2b1d99aceef6d8b29e4a8c5e09 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Thu, 4 May 2023 14:29:21 +0200 Subject: [PATCH 18/18] Add new Interop-F1 pipeline documentation --- doc/TESTBenches.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/TESTBenches.md b/doc/TESTBenches.md index aef3a7f63e..3f50abaa11 100644 --- a/doc/TESTBenches.md +++ b/doc/TESTBenches.md @@ -82,6 +82,9 @@ Webhook - [RAN-gNB-N300-Timing-Phytest-LDPC](https://jenkins-oai.eurecom.fr/view/RAN/job/RAN-gNB-N300-Timing-Phytest-LDPC/) - caracal + N310 - pure performance test through phy-test scheduler, see command line for more details +- [RAN-Interop-F1](https://jenkins-oai.eurecom.fr/job/RAN-Interop-F1/) + - ofqot (DU, 1x UE) + - F1 interoperability testing: sets up connection to Accelleran CU, UE connection and connectivity test - [RAN-L2-Sim-Test-5G](https://jenkins-oai.eurecom.fr/job/RAN-L2-Sim-Test-4G/) - obelix (eNB, 1x UE, OAI EPC) - L2simulator: skips physical layer and uses proxy between eNB and UE