diff --git a/CMakeLists.txt b/CMakeLists.txt index 6952af8691..28b317fedb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1457,6 +1457,7 @@ add_library(L2_NR ${MAC_NR_SRC} ${GNB_APP_SRC} ) +target_link_libraries(L2_NR PRIVATE ds alg) add_library(e1_if ${NR_RRC_DIR}/cucp_cuup_direct.c diff --git a/common/utils/alg/find.c b/common/utils/alg/find.c index 1aea32ab88..e3c0e1337c 100644 --- a/common/utils/alg/find.c +++ b/common/utils/alg/find.c @@ -40,7 +40,7 @@ elm_arr_t find_if_arr_it(seq_arr_t* arr, void* start_it, void* end_it, void* val return (elm_arr_t){.found = false, .it = NULL}; } -elm_arr_t find_if_arr(seq_arr_t* arr, void* value, bool (*f)(const void*, const void*)) +elm_arr_t find_if(seq_arr_t* arr, void* value, bool (*f)(const void*, const void*)) { assert(arr != NULL); void* start_it = seq_arr_front(arr); diff --git a/common/utils/alg/find.h b/common/utils/alg/find.h index a8acde169d..2b11a42fd5 100644 --- a/common/utils/alg/find.h +++ b/common/utils/alg/find.h @@ -42,7 +42,7 @@ typedef struct { * @param f Function representing the predicate * @return Whether the predicate was fullfilled and the iterator to the element if true */ -elm_arr_t find_if_arr(seq_arr_t* arr, void* value, bool (*f)(const void* value, const void* it)); +elm_arr_t find_if(seq_arr_t* arr, void* value, bool (*f)(const void* value, const void* it)); /** * @brief Find elements in an array in the semi-open range [start_it, end_it) diff --git a/common/utils/ds/tests/test_seq_array.c b/common/utils/ds/tests/test_seq_array.c index c642c883c7..28a7c98b1e 100644 --- a/common/utils/ds/tests/test_seq_array.c +++ b/common/utils/ds/tests/test_seq_array.c @@ -52,7 +52,7 @@ int main() // Find element in the array int value = 50; - elm_arr_t elm = find_if_arr(&arr, &value, eq_int); + elm_arr_t elm = find_if(&arr, &value, eq_int); assert(elm.found == true); // Check assert(*(int*)elm.it == 50); diff --git a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c index 77dc12ba24..748b4f7d29 100644 --- a/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c +++ b/openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_kpm.c @@ -53,7 +53,7 @@ typedef struct { // Optional // only used to retreive MAC/RLC stats - NR_UE_info_t* ue_info_list; + NR_UE_info_t** ue_info_list; }arr_ue_id_t; static meas_data_lst_t fill_kpm_meas_data_item(const meas_info_format_1_lst_t* meas_info_lst, const size_t len, const uint32_t gran_period_ms, cudu_ue_info_pair_t ue_info, const size_t ue_idx) @@ -114,14 +114,14 @@ static cudu_ue_info_pair_t fill_ue_related_info(arr_ue_id_t* arr_ue_id, const si if (arr_ue_id->ue_id[ue_idx].type == GNB_UE_ID_E2SM) { ue_info.rrc_ue_id = *arr_ue_id->ue_id[ue_idx].gnb.ran_ue_id; // rrc_ue_id - ue_info.ue = &arr_ue_id->ue_info_list[ue_idx]; + ue_info.ue = arr_ue_id->ue_info_list[ue_idx]; } else if (arr_ue_id->ue_id[ue_idx].type == GNB_CU_UP_UE_ID_E2SM) { /* in OAI implementation, CU-UP ue id = CU-CP ue id => CU-UP ue id = rrc_ue_id, but it should not be the case by the spec */ ue_info.rrc_ue_id = *arr_ue_id->ue_id[ue_idx].gnb_cu_up.ran_ue_id; // cucp_ue_id = rrc_ue_id } else if (arr_ue_id->ue_id[ue_idx].type == GNB_DU_UE_ID_E2SM) { ue_info.rrc_ue_id = *arr_ue_id->ue_id[ue_idx].gnb_du.ran_ue_id; // rrc_ue_id - ue_info.ue = &arr_ue_id->ue_info_list[ue_idx]; + ue_info.ue = arr_ue_id->ue_info_list[ue_idx]; } return ue_info; @@ -275,7 +275,7 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst arr_ue_id.ue_id = calloc(MAX_MOBILES_PER_GNB, sizeof(ue_id_e2sm_t)); assert(arr_ue_id.ue_id != NULL); - arr_ue_id.ue_info_list = calloc(MAX_MOBILES_PER_GNB, sizeof(NR_UE_info_t)); + arr_ue_id.ue_info_list = calloc(MAX_MOBILES_PER_GNB, sizeof(*arr_ue_id.ue_info_list)); assert(arr_ue_id.ue_info_list != NULL); const ngran_node_t node_type = get_e2_node_type(); @@ -284,9 +284,9 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst UE_iterator (RC.nrmac[0]->UE_info.list, ue) { NR_UE_sched_ctrl_t *sched_ctrl = &ue->UE_sched_ctrl; // UE matches if any of its DRBs matches - for (int l = 0; l < sched_ctrl->dl_lc_num; ++l) { - long lcid = sched_ctrl->dl_lc_ids[l]; - if (nssai_matches(sched_ctrl->dl_lc_nssai[lcid], sst, sd)) { + for (size_t l = 0; l < seq_arr_size(&sched_ctrl->lc_config); ++l) { + const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, l); + if (nssai_matches(c->nssai, sst, sd)) { if (node_type == ngran_gNB_DU) { f1_ue_data_t rrc_ue_id = du_get_f1_ue_data(ue->rnti); // gNB CU UE ID = rrc_ue_id arr_ue_id.ue_id[arr_ue_id.sz] = fill_ue_id_data[ngran_gNB_DU](NULL, rrc_ue_id.secondary_ue, 0); @@ -296,7 +296,7 @@ static arr_ue_id_t filter_ues_by_s_nssai_in_du_or_monolithic(const test_info_lst } // store NR_UE_info_t - arr_ue_id.ue_info_list[arr_ue_id.sz] = *ue; + arr_ue_id.ue_info_list[arr_ue_id.sz] = ue; arr_ue_id.sz++; break; diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 29c1f2ce83..e313cdb190 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -266,73 +266,6 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort return mat; } -static void process_rlcBearerConfig(struct NR_CellGroupConfig__rlc_BearerToAddModList *rlc_bearer2add_list, - struct NR_CellGroupConfig__rlc_BearerToReleaseList *rlc_bearer2release_list, - NR_UE_sched_ctrl_t *sched_ctrl) -{ - if (rlc_bearer2release_list) { - for (int i = 0; i < rlc_bearer2release_list->list.count; i++) { - for (int idx = 0; idx < sched_ctrl->dl_lc_num; idx++) { - if (sched_ctrl->dl_lc_ids[idx] == *rlc_bearer2release_list->list.array[i]) { - const int remaining_lcs = sched_ctrl->dl_lc_num - idx - 1; - memmove(&sched_ctrl->dl_lc_ids[idx], &sched_ctrl->dl_lc_ids[idx + 1], sizeof(sched_ctrl->dl_lc_ids[idx]) * remaining_lcs); - sched_ctrl->dl_lc_num--; - break; - } - } - } - } - - if (rlc_bearer2add_list) { - // keep lcids - for (int i = 0; i < rlc_bearer2add_list->list.count; i++) { - const int lcid = rlc_bearer2add_list->list.array[i]->logicalChannelIdentity; - bool found = false; - for (int idx = 0; idx < sched_ctrl->dl_lc_num; idx++) { - if (sched_ctrl->dl_lc_ids[idx] == lcid) { - found = true; - break; - } - } - - if (!found) { - sched_ctrl->dl_lc_num++; - sched_ctrl->dl_lc_ids[sched_ctrl->dl_lc_num - 1] = lcid; - LOG_D(NR_MAC, "Adding LCID %d (%s %d)\n", lcid, lcid < 4 ? "SRB" : "DRB", lcid); - } - } - } - - LOG_D(NR_MAC, "In %s: total num of active bearers %d) \n", - __FUNCTION__, - sched_ctrl->dl_lc_num); - -} - -void process_CellGroup(NR_CellGroupConfig_t *CellGroup, NR_UE_info_t *UE) -{ - /* 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; - - 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); - } - - if (CellGroup->spCellConfig && CellGroup->spCellConfig->reconfigurationWithSync - && CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated - && CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra) { - nr_mac_prepare_ra_ue(RC.nrmac[0], UE->rnti, CellGroup); - } - process_rlcBearerConfig(CellGroup->rlc_BearerToAddModList, CellGroup->rlc_BearerToReleaseList, &UE->UE_sched_ctrl); -} - static void config_common(gNB_MAC_INST *nrmac, nr_pdsch_AntennaPorts_t pdsch_AntennaPorts, int pusch_AntennaPorts, NR_ServingCellConfigCommon_t *scc) { nfapi_nr_config_request_scf_t *cfg = &nrmac->config[0]; @@ -752,20 +685,30 @@ void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const f1ap_plmn_t *plmn, uint64_ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup) { + /* ideally, instead of this function, "users" of this function should call + * the ue context setup request function in mac_rrc_dl_handler.c */ 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); - } else { - LOG_E(NR_MAC,"Error adding UE %04x\n", rnti); + NR_UE_info_t *UE = add_new_nr_ue(nrmac, rnti, CellGroup); + if (!UE) { + LOG_E(NR_MAC, "Error adding UE %04x\n", rnti); + NR_SCHED_UNLOCK(&nrmac->sched_lock); + return false; } + + if (CellGroup->spCellConfig && CellGroup->spCellConfig->reconfigurationWithSync + && CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated + && CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra) { + nr_mac_prepare_ra_ue(RC.nrmac[0], UE->rnti, CellGroup); + } + process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, CellGroup->rlc_BearerToAddModList); + AssertFatal(CellGroup->rlc_BearerToReleaseList == NULL, "cannot release bearers while adding new UEs\n"); NR_SCHED_UNLOCK(&nrmac->sched_lock); - return UE != NULL; + LOG_I(NR_MAC, "Added new UE %x with initial CellGroup\n", rnti); + return true; } bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup) @@ -823,7 +766,6 @@ bool nr_mac_prepare_cellgroup_update(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, NR_C /* we assume that this function is mutex-protected from outside */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); - process_CellGroup(CellGroup, UE); UE->reconfigCellGroup = CellGroup; UE->expect_reconfiguration = true; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 422ae13d89..ca6d44d5b0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -329,8 +329,9 @@ static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_fram /* loop over all activated logical channels */ // Note: DL_SCH_LCID_DCCH, DL_SCH_LCID_DCCH1, DL_SCH_LCID_DTCH - for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) { - const int lcid = sched_ctrl->dl_lc_ids[i]; + for (int i = 0; i < seq_arr_size(&sched_ctrl->lc_config); ++i) { + const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, i); + const int lcid = c->lcid; const uint16_t rnti = UE->rnti; LOG_D(NR_MAC, "In %s: UE %x: LCID %d\n", __FUNCTION__, rnti, lcid); if (lcid == DL_SCH_LCID_DTCH && sched_ctrl->rrc_processing_timer > 0) { @@ -1275,8 +1276,9 @@ void nr_schedule_ue_spec(module_id_t module_id, if (sched_ctrl->num_total_bytes > 0) { /* loop over all activated logical channels */ - for (int i = 0; i < sched_ctrl->dl_lc_num; ++i) { - const int lcid = sched_ctrl->dl_lc_ids[i]; + for (int i = 0; i < seq_arr_size(&sched_ctrl->lc_config); ++i) { + const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, i); + const int lcid = c->lcid; if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0) continue; // no data for this LC tbs_size_t len = 0; diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index a604e13c25..3eb9a9ce7b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -104,9 +104,9 @@ void nr_preprocessor_phytest(module_id_t module_id, } sched_ctrl->num_total_bytes = 0; - sched_ctrl->dl_lc_num = 1; - const int lcid = DL_SCH_LCID_DTCH; - sched_ctrl->dl_lc_ids[sched_ctrl->dl_lc_num - 1] = lcid; + DevAssert(seq_arr_size(&sched_ctrl->lc_config) == 1); + const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, 0); + const int lcid = c->lcid; const uint16_t rnti = UE->rnti; /* update sched_ctrl->num_total_bytes so that postprocessor schedules data, * if available */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 3d90f4a744..1aeba91026 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -59,6 +59,8 @@ #include "common/ran_context.h" #include "nfapi/oai_integration/vendor_ext.h" +#include "common/utils/alg/find.h" + //#define DEBUG_DCI extern RAN_CONTEXT_t RC; @@ -2097,6 +2099,7 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->reconfigCellGroup); ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->capability); NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; + seq_arr_free(&sched_ctrl->lc_config, NULL); destroy_nr_list(&sched_ctrl->available_dl_harq); destroy_nr_list(&sched_ctrl->feedback_dl_harq); destroy_nr_list(&sched_ctrl->retrans_dl_harq); @@ -2490,6 +2493,9 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf sched_ctrl->sched_srs.frame = -1; sched_ctrl->sched_srs.slot = -1; + // initialize LCID structure + seq_arr_init(&sched_ctrl->lc_config, sizeof(nr_lc_config_t)); + // initialize UE BWP information NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP; memset(dl_bwp, 0, sizeof(*dl_bwp)); @@ -2964,7 +2970,6 @@ static void nr_mac_apply_cellgroup(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon; - /* Note! we already did process_CellGroup(), so no need to do this again */ NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; configure_UE_BWP(mac, scc, sched_ctrl, NULL, UE, -1, -1); @@ -3123,12 +3128,12 @@ 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 */ int CC_id = 0; + int srb_id = 1; const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon; const NR_ServingCellConfig_t *sccd = mac->common_channels[CC_id].pre_ServingCellConfig; NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config); UE->CellGroup = cellGroupConfig; - process_CellGroup(cellGroupConfig, UE); /* activate SRB0 */ nr_rlc_activate_srb0(UE->rnti, UE, send_initial_ul_rrc_message); @@ -3136,8 +3141,12 @@ void prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE) /* the cellGroup sent to CU specifies there is SRB1, so create it */ DevAssert(cellGroupConfig->rlc_BearerToAddModList->list.count == 1); const NR_RLC_BearerConfig_t *bearer = cellGroupConfig->rlc_BearerToAddModList->list.array[0]; - DevAssert(bearer->servedRadioBearer->choice.srb_Identity == 1); + DevAssert(bearer->servedRadioBearer->choice.srb_Identity == srb_id); nr_rlc_add_srb(UE->rnti, bearer->servedRadioBearer->choice.srb_Identity, bearer); + + int priority = bearer->mac_LogicalChannelConfig->ul_SpecificParameters->priority; + nr_lc_config_t c = {.lcid = bearer->logicalChannelIdentity, .priority = priority}; + nr_mac_add_lcid(&UE->UE_sched_ctrl, &c); } void nr_mac_trigger_release_timer(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing) @@ -3213,3 +3222,80 @@ void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_ }; nrmac->mac_rrc.ue_context_modification_required(&required); } + +/* \brief add bearers from CellGroupConfig. + * + * This is a kind of hack, as this should be processed through a F1 UE Context + * setup request, but some modes do not use that (NSA/do-ra/phy_test). */ +void process_addmod_bearers_cellGroupConfig(NR_UE_sched_ctrl_t *sched_ctrl, const struct NR_CellGroupConfig__rlc_BearerToAddModList *addmod) +{ + if (addmod == NULL) + return; /* nothing to do */ + + for (int i = 0; i < addmod->list.count; ++i) { + const NR_RLC_BearerConfig_t *conf = addmod->list.array[i]; + int lcid = conf->logicalChannelIdentity; + nr_lc_config_t c = {.lcid = lcid}; + nr_mac_add_lcid(sched_ctrl, &c); + } +} + +long get_lcid_from_drbid(int drb_id) +{ + return drb_id + 3; /* LCID is DRB + 3 */ +} + +long get_lcid_from_srbid(int srb_id) +{ + return srb_id; +} + +static bool eq_lcid_config(const void *vval, const void *vit) +{ + const nr_lc_config_t *val = (const nr_lc_config_t *)vval; + const nr_lc_config_t *it = (const nr_lc_config_t *)vit; + return it->lcid == val->lcid; +} + +static int cmp_lc_config(const void *va, const void *vb) +{ + const nr_lc_config_t *a = (const nr_lc_config_t *)va; + const nr_lc_config_t *b = (const nr_lc_config_t *)vb; + + if (a->priority < b->priority) + return -1; + if (a->priority == b->priority) + return 0; + return 1; +} + +bool nr_mac_add_lcid(NR_UE_sched_ctrl_t* sched_ctrl, const nr_lc_config_t *c) +{ + elm_arr_t elm = find_if(&sched_ctrl->lc_config, (void *) c, eq_lcid_config); + if (elm.found) { + LOG_I(NR_MAC, "cannot add LCID %d: already present, updating configuration\n", c->lcid); + nr_lc_config_t *exist = (nr_lc_config_t *)elm.it; + *exist = *c; + } else { + LOG_D(NR_MAC, "Add LCID %d\n", c->lcid); + seq_arr_push_back(&sched_ctrl->lc_config, (void*) c, sizeof(*c)); + } + void *base = seq_arr_front(&sched_ctrl->lc_config); + size_t nmemb = seq_arr_size(&sched_ctrl->lc_config); + size_t size = sizeof(*c); + qsort(base, nmemb, size, cmp_lc_config); + return true; +} + +bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid) +{ + nr_lc_config_t c = {.lcid = lcid}; + elm_arr_t elm = find_if(&sched_ctrl->lc_config, &c, eq_lcid_config); + if (!elm.found) { + LOG_E(NR_MAC, "can not remove LC: no such LC with ID %ld\n", lcid); + return false; + } + + seq_arr_erase(&sched_ctrl->lc_config, elm.it); + return true; +} diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index fc53a57711..fec34b753f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -811,7 +811,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP, reset_dl_harq_list(UE_scheduling_control); reset_ul_harq_list(UE_scheduling_control); nr_clear_ra_proc(ra); - process_CellGroup(ra->CellGroup, UE); + process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, ra->CellGroup->rlc_BearerToAddModList); } else { LOG_A(NR_MAC, "[RAPROC] RA-Msg3 received (sdu_lenP %d)\n", sdu_lenP); LOG_D(NR_MAC, "[RAPROC] Received Msg3:\n"); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index ac86434927..0fc1071c5f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -424,7 +424,8 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP); size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset_rsrp); -void process_CellGroup(NR_CellGroupConfig_t *CellGroup, NR_UE_info_t *UE); +long get_lcid_from_drbid(int drb_id); +long get_lcid_from_srbid(int srb_id); void prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE); void send_initial_ul_rrc_message(int rnti, const uint8_t *sdu, sdu_size_t sdu_len, void *data); @@ -441,4 +442,10 @@ void nr_mac_check_ul_failure(const gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ct void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, const NR_UE_info_t *UE); +void process_addmod_bearers_cellGroupConfig(NR_UE_sched_ctrl_t *sched_ctrl, + const struct NR_CellGroupConfig__rlc_BearerToAddModList *addmod); + +bool nr_mac_add_lcid(NR_UE_sched_ctrl_t *sched_ctrl, const nr_lc_config_t *c); +bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid); + #endif /*__LAYER2_NR_MAC_PROTO_H__*/ diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 977bbc0403..7353e61711 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -90,16 +90,6 @@ bool DURecvCb(protocol_ctxt_t *ctxt_pP, return true; } -static long get_lcid_from_drbid(int drb_id) -{ - return drb_id + 3; /* LCID is DRB + 3 */ -} - -static long get_lcid_from_srbid(int srb_id) -{ - return srb_id; -} - static bool check_plmn_identity(const f1ap_plmn_t *check_plmn, const f1ap_plmn_t *plmn) { return plmn->mcc == check_plmn->mcc && plmn->mnc_digit_length == check_plmn->mnc_digit_length && plmn->mnc == check_plmn->mnc; @@ -152,13 +142,13 @@ void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_upd 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 + long priority = srb->srb_id == 2 ? 3 : 1; // see 38.331 sec 9.2.1 e_NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration bucket = NR_LogicalChannelConfig__ul_SpecificParameters__bucketSizeDuration_ms5; return get_SRB_RLC_BearerConfig(get_lcid_from_srbid(srb->srb_id), priority, bucket); } -static int handle_ue_context_srbs_setup(int rnti, +static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, int srbs_len, const f1ap_srb_to_be_setup_t *req_srbs, f1ap_srb_to_be_setup_t **resp_srbs, @@ -171,7 +161,11 @@ static int handle_ue_context_srbs_setup(int rnti, for (int i = 0; i < srbs_len; i++) { const f1ap_srb_to_be_setup_t *srb = &req_srbs[i]; NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_srb(srb); - nr_rlc_add_srb(rnti, srb->srb_id, rlc_BearerConfig); + nr_rlc_add_srb(UE->rnti, srb->srb_id, rlc_BearerConfig); + + int priority = rlc_BearerConfig->mac_LogicalChannelConfig->ul_SpecificParameters->priority; + nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .priority = priority}; + nr_mac_add_lcid(&UE->UE_sched_ctrl, &c); (*resp_srbs)[i] = *srb; @@ -188,7 +182,35 @@ static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_set return get_DRB_RLC_BearerConfig(get_lcid_from_drbid(drb->drb_id), drb->drb_id, rlc_conf, priority); } -static int handle_ue_context_drbs_setup(int rnti, +static int get_non_dynamic_priority(int fiveqi) +{ + for (int i = 0; i < sizeofArray(qos_fiveqi); ++i) + if (qos_fiveqi[i] == fiveqi) + return qos_priority[i]; + AssertFatal(false, "illegal 5QI value %d\n", fiveqi); + return 0; +} + +static NR_QoS_config_t get_qos_config(const f1ap_qos_characteristics_t *qos_char) +{ + NR_QoS_config_t qos_c = {0}; + switch (qos_char->qos_type) { + case dynamic: + qos_c.priority = qos_char->dynamic.qos_priority_level; + qos_c.fiveQI = qos_char->dynamic.fiveqi > 0 ? qos_char->dynamic.fiveqi : 0; + break; + case non_dynamic: + qos_c.fiveQI = qos_char->non_dynamic.fiveqi; + qos_c.priority = get_non_dynamic_priority(qos_char->non_dynamic.fiveqi); + break; + default: + AssertFatal(false, "illegal QoS type %d\n", qos_char->qos_type); + break; + } + return qos_c; +} + +static int handle_ue_context_drbs_setup(NR_UE_info_t *UE, int drbs_len, const f1ap_drb_to_be_setup_t *req_drbs, f1ap_drb_to_be_setup_t **resp_drbs, @@ -205,7 +227,16 @@ static int handle_ue_context_drbs_setup(int rnti, const f1ap_drb_to_be_setup_t *drb = &req_drbs[i]; f1ap_drb_to_be_setup_t *resp_drb = &(*resp_drbs)[i]; NR_RLC_BearerConfig_t *rlc_BearerConfig = get_bearerconfig_from_drb(drb); - nr_rlc_add_drb(rnti, drb->drb_id, rlc_BearerConfig); + nr_rlc_add_drb(UE->rnti, drb->drb_id, rlc_BearerConfig); + + nr_lc_config_t c = {.lcid = rlc_BearerConfig->logicalChannelIdentity, .nssai = drb->nssai}; + int prio = 100; + for (int q = 0; q < drb->drb_info.flows_to_be_setup_length; ++q) { + c.qos_config[q] = get_qos_config(&drb->drb_info.flows_mapped_to_drb[q].qos_params.qos_characteristics); + prio = min(prio, c.qos_config[q].priority); + } + c.priority = prio; + nr_mac_add_lcid(&UE->UE_sched_ctrl, &c); *resp_drb = *drb; // just put same number of tunnels in DL as in UL @@ -216,7 +247,7 @@ static int handle_ue_context_drbs_setup(int rnti, int qfi = -1; // don't put PDU session marker in GTP gtpv1u_gnb_create_tunnel_resp_t resp_f1 = {0}; int ret = drb_gtpu_create(f1inst, - rnti, + UE->rnti, drb->drb_id, drb->drb_id, qfi, @@ -236,7 +267,7 @@ static int handle_ue_context_drbs_setup(int rnti, return drbs_len; } -static int handle_ue_context_drbs_release(int rnti, +static int handle_ue_context_drbs_release(NR_UE_info_t *UE, int drbs_len, const f1ap_drb_to_be_released_t *req_drbs, NR_CellGroupConfig_t *cellGroupConfig) @@ -261,9 +292,10 @@ static int handle_ue_context_drbs_release(int rnti, ++idx; } if (idx < cellGroupConfig->rlc_BearerToAddModList->list.count) { - nr_rlc_release_entity(rnti, lcid); + nr_mac_remove_lcid(&UE->UE_sched_ctrl, lcid); + nr_rlc_release_entity(UE->rnti, lcid); if (f1inst >= 0) - newGtpuDeleteOneTunnel(f1inst, rnti, drb->rb_id); + newGtpuDeleteOneTunnel(f1inst, UE->rnti, drb->rb_id); asn_sequence_del(&cellGroupConfig->rlc_BearerToAddModList->list, idx, 1); long *plcid = malloc(sizeof(*plcid)); AssertFatal(plcid, "out of memory\n"); @@ -323,60 +355,6 @@ NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig) return cloned; } -static void set_nssaiConfig(const int drb_len, const f1ap_drb_to_be_setup_t *req_drbs, NR_UE_sched_ctrl_t *sched_ctrl) -{ - for (int i = 0; i < drb_len; i++) { - const f1ap_drb_to_be_setup_t *drb = &req_drbs[i]; - - long lcid = get_lcid_from_drbid(drb->drb_id); - sched_ctrl->dl_lc_nssai[lcid] = drb->nssai; - LOG_I(NR_MAC, "Setting NSSAI sst: %d, sd: %d for DRB: %ld\n", drb->nssai.sst, drb->nssai.sd, drb->drb_id); - } -} - -static void set_QoSConfig(const f1ap_ue_context_modif_req_t *req, NR_UE_sched_ctrl_t *sched_ctrl) -{ - AssertFatal(req != NULL, "f1ap_ue_context_modif_req is NULL\n"); - uint8_t drb_count = req->drbs_to_be_setup_length; - uint8_t srb_count = req->srbs_to_be_setup_length; - LOG_I(NR_MAC, "Number of DRBs = %d and SRBs = %d\n", drb_count, srb_count); - - /* DRBs*/ - for (int i = 0; i < drb_count; i++) { - f1ap_drb_to_be_setup_t *drb_p = &req->drbs_to_be_setup[i]; - uint8_t nb_qos_flows = drb_p->drb_info.flows_to_be_setup_length; - long drb_id = drb_p->drb_id; - LOG_I(NR_MAC, "number of QOS flows mapped to DRB_id %ld: %d\n", drb_id, nb_qos_flows); - - for (int q = 0; q < nb_qos_flows; q++) { - f1ap_flows_mapped_to_drb_t *qos_flow = &drb_p->drb_info.flows_mapped_to_drb[q]; - - f1ap_qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; - uint64_t priority = qos_char->non_dynamic.qos_priority_level; - int64_t fiveqi = qos_char->non_dynamic.fiveqi; - if (qos_char->qos_type == dynamic) { - priority = qos_char->dynamic.qos_priority_level; - fiveqi = qos_char->dynamic.fiveqi > 0 ? qos_char->dynamic.fiveqi : 0; - } - if (qos_char->qos_type == non_dynamic) { - LOG_D(NR_MAC, "Qos Priority level is considered from the standarsdized 5QI to QoS mapping table\n"); - for (int id = 0; id < 26; id++) { - if (qos_fiveqi[id] == fiveqi) - priority = qos_priority[id]; - } - } - sched_ctrl->qos_config[drb_id - 1][q].fiveQI = fiveqi; - sched_ctrl->qos_config[drb_id - 1][q].priority = priority; - LOG_D(NR_MAC, - "In %s: drb_id %ld: 5QI %lu priority %lu\n", - __func__, - drb_id, - sched_ctrl->qos_config[drb_id - 1][q].fiveQI, - sched_ctrl->qos_config[drb_id - 1][q].priority); - } - } -} - void ue_context_setup_request(const f1ap_ue_context_setup_t *req) { gNB_MAC_INST *mac = RC.nrmac[0]; @@ -403,7 +381,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup); if (req->srbs_to_be_setup_length > 0) { - resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(req->gNB_DU_ue_id, + resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE, req->srbs_to_be_setup_length, req->srbs_to_be_setup, &resp.srbs_to_be_setup, @@ -411,7 +389,7 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) } if (req->drbs_to_be_setup_length > 0) { - resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(req->gNB_DU_ue_id, + resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE, req->drbs_to_be_setup_length, req->drbs_to_be_setup, &resp.drbs_to_be_setup, @@ -439,15 +417,8 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req) AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name); resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3; - /* TODO: need to apply after UE context reconfiguration confirmed? */ nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup); - /* Fill the QoS config in MAC for each active DRB */ - set_QoSConfig(req, &UE->UE_sched_ctrl); - - /* Set NSSAI config in MAC for each active DRB */ - set_nssaiConfig(req->drbs_to_be_setup_length, req->drbs_to_be_setup, &UE->UE_sched_ctrl); - NR_SCHED_UNLOCK(&mac->sched_lock); /* some sanity checks, since we use the same type for request and response */ @@ -492,7 +463,7 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) NR_CellGroupConfig_t *new_CellGroup = clone_CellGroupConfig(UE->CellGroup); if (req->srbs_to_be_setup_length > 0) { - resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(req->gNB_DU_ue_id, + resp.srbs_to_be_setup_length = handle_ue_context_srbs_setup(UE, req->srbs_to_be_setup_length, req->srbs_to_be_setup, &resp.srbs_to_be_setup, @@ -500,7 +471,7 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) } if (req->drbs_to_be_setup_length > 0) { - resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(req->gNB_DU_ue_id, + resp.drbs_to_be_setup_length = handle_ue_context_drbs_setup(UE, req->drbs_to_be_setup_length, req->drbs_to_be_setup, &resp.drbs_to_be_setup, @@ -509,7 +480,7 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) if (req->drbs_to_be_released_length > 0) { resp.drbs_to_be_released_length = - handle_ue_context_drbs_release(req->gNB_DU_ue_id, req->drbs_to_be_released_length, req->drbs_to_be_released, new_CellGroup); + handle_ue_context_drbs_release(UE, req->drbs_to_be_released_length, req->drbs_to_be_released, new_CellGroup); } if (req->rrc_container != NULL) { @@ -546,12 +517,6 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req) resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3; nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup); - - /* Fill the QoS config in MAC for each active DRB */ - set_QoSConfig(req, &UE->UE_sched_ctrl); - - /* Set NSSAI config in MAC for each active DRB */ - set_nssaiConfig(req->drbs_to_be_setup_length, req->drbs_to_be_setup, &UE->UE_sched_ctrl); } else { ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, new_CellGroup); // we actually don't need it } @@ -695,8 +660,10 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) UE->expect_reconfiguration = false; /* Re-establish RLC for all remaining bearers */ if (UE->reestablish_rlc) { - for (int i = 1; i < UE->UE_sched_ctrl.dl_lc_num; ++i) - nr_rlc_reestablish_entity(dl_rrc->gNB_DU_ue_id, UE->UE_sched_ctrl.dl_lc_ids[i]); + for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) { + nr_lc_config_t *lc_config = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i); + nr_rlc_reestablish_entity(dl_rrc->gNB_DU_ue_id, lc_config->lcid); + } UE->reestablish_rlc = false; } } @@ -721,6 +688,10 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc) UE->uid = oldUE->uid; oldUE->uid = temp_uid; configure_UE_BWP(mac, scc, sched_ctrl, NULL, UE, -1, -1); + for (int i = 1; i < seq_arr_size(&oldUE->UE_sched_ctrl.lc_config); ++i) { + const nr_lc_config_t *c = seq_arr_at(&oldUE->UE_sched_ctrl.lc_config, i); + nr_mac_add_lcid(&UE->UE_sched_ctrl, c); + } nr_mac_prepare_cellgroup_update(mac, UE, oldUE->CellGroup); oldUE->CellGroup = NULL; diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 09726c86bd..db82085ed6 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -179,15 +179,15 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset "UE %04x: MAC: TX %14"PRIu64" RX %14"PRIu64" bytes\n", UE->rnti, stats->dl.total_bytes, stats->ul.total_bytes); - for (int i = 0; i < sched_ctrl->dl_lc_num; i++) { - int lc_id = sched_ctrl->dl_lc_ids[i]; + for (int i = 0; i < seq_arr_size(&sched_ctrl->lc_config); i++) { + const nr_lc_config_t *c = seq_arr_at(&sched_ctrl->lc_config, i); output += snprintf(output, end - output, "UE %04x: LCID %d: TX %14"PRIu64" RX %14"PRIu64" bytes\n", UE->rnti, - lc_id, - stats->dl.lc_bytes[lc_id], - stats->ul.lc_bytes[lc_id]); + c->lcid, + stats->dl.lc_bytes[c->lcid], + stats->ul.lc_bytes[c->lcid]); } } NR_SCHED_UNLOCK(&gNB->UE_info.mutex); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 5d7f9c7247..eeeff6543c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -42,6 +42,7 @@ #include #include #include +#include "common/utils/ds/seq_arr.h" #define NR_SCHED_LOCK(lock) \ do { \ @@ -518,10 +519,20 @@ typedef struct NR_UE_ul_harq { } NR_UE_ul_harq_t; typedef struct NR_QoS_config_s { - uint64_t fiveQI; - uint64_t priority; + int fiveQI; + int priority; } NR_QoS_config_t; +typedef struct nr_lc_config { + uint8_t lcid; + /// priority as specified in 38.321 + int priority; + /// associated NSSAI for DRB + nssai_t nssai; + /// QoS config for DRB + NR_QoS_config_t qos_config[NR_MAX_NUM_QFI]; +} nr_lc_config_t; + /*! \brief scheduling control information set through an API */ #define MAX_CSI_REPORTS 48 typedef struct { @@ -613,20 +624,15 @@ typedef struct { /// UL HARQ processes that await retransmission NR_list_t retrans_ul_harq; NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl; // MAC CE related information - /// number of active DL LCs - uint8_t dl_lc_num; - /// order in which DLSCH scheduler should allocate LCs - uint8_t dl_lc_ids[NR_MAX_NUM_LCID]; /// Timer for RRC processing procedures uint32_t rrc_processing_timer; /// sri, ul_ri and tpmi based on SRS nr_srs_feedback_t srs_feedback; - nssai_t dl_lc_nssai[NR_MAX_NUM_LCID]; - // Information about the QoS configuration for each LCID/DRB - NR_QoS_config_t qos_config[NR_MAX_NUM_LCID - 4][NR_MAX_NUM_QFI]; // 0 -CCCH and 1- 3 SRBs(0,1,2) + /// per-LC configuration + seq_arr_t lc_config; } NR_UE_sched_ctrl_t; typedef struct {