Use list of UEs during RA instead of array of RA processes

- rewrite add_UE_to_list() and rewrite remove_UE_from_list() to simplify
  list handling
- return pointer from get_new_nr_ue_inst(); it's completely freed by
  delete_nr_ue_data()
- have add_new_UE_RA() add UE context to access list; remove with
  nr_release_ra_UE()
- have add_connected_nr_ue() only add UE to connected list; to move from
  access to connected use transition_ra_connected_nr_ue(); remove with
  mac_remove_nr_ue() as previously
- free memory on problems during RA
- add some documentation
- in NSA/HO: check for pre-configured RA process
- there are asserts in all functions to clarify when a UE has RA
This commit is contained in:
francescomani
2025-03-03 09:52:21 +01:00
committed by Robert Schmidt
parent a7c199cabf
commit 8f62baefa6
13 changed files with 584 additions and 672 deletions

View File

@@ -185,7 +185,7 @@ int g_mcsIndex = -1, g_mcsTableIdx = 0, g_rbStart = -1, g_rbSize = -1, g_nrOfLay
void nr_dlsim_preprocessor(module_id_t module_id, frame_t frame, slot_t slot)
{
NR_UE_info_t *UE_info = RC.nrmac[module_id]->UE_info.connected_ue_list[0];
AssertFatal(RC.nrmac[module_id]->UE_info.connected_ue_list[1] == NULL, "can have only a single UE\n");
AssertFatal(RC.nrmac[module_id]->UE_info.connected_ue_list[1] == NULL, "Only single UE allowed in dlsim\n");
NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl;
NR_UE_DL_BWP_t *current_BWP = &UE_info->current_DL_BWP;
NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon;
@@ -804,7 +804,7 @@ printf("%d\n", slot);
N_RB_DL = gNB->frame_parms.N_RB_DL;
NR_UE_info_t *UE_info = RC.nrmac[0]->UE_info.connected_ue_list[0];
configure_UE_BWP(RC.nrmac[0], scc, &UE_info->UE_sched_ctrl, NULL, UE_info, -1, -1);
configure_UE_BWP(RC.nrmac[0], scc, UE_info, false, -1, -1);
// stub to configure frame_parms
// nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions);

View File

@@ -858,14 +858,6 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
find_SSB_and_RO_available(nrmac);
NR_COMMON_channels_t *cc = &nrmac->common_channels[0];
NR_SCHED_LOCK(&nrmac->sched_lock);
for (int n = 0; n < NR_NB_RA_PROC_MAX; n++) {
NR_RA_t *ra = &cc->ra[n];
nr_clear_ra_proc(ra);
}
NR_SCHED_UNLOCK(&nrmac->sched_lock);
if (IS_SA_MODE(get_softmodem_params()))
config_sched_ctrlCommon(nrmac);
}
@@ -979,18 +971,17 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t
DevAssert(get_softmodem_params()->phy_test);
NR_SCHED_LOCK(&nrmac->sched_lock);
NR_UE_info_t *UE = add_new_nr_ue(nrmac, rnti, CellGroup);
if (!UE) {
NR_UE_info_t *UE = get_new_nr_ue_inst(&nrmac->UE_info.uid_allocator, rnti, CellGroup);
DevAssert(UE != NULL); // test-mode: we assume we can always create a UE
free_and_zero(UE->ra); // test-mode (sims, phy-test): UE will not do RA
bool res = add_connected_nr_ue(nrmac, UE);
if (!res) {
LOG_E(NR_MAC, "Error adding UE %04x\n", rnti);
delete_nr_ue_data(UE, NULL, &nrmac->UE_info.uid_allocator);
NR_SCHED_UNLOCK(&nrmac->sched_lock);
return false;
}
if (CellGroup->spCellConfig && CellGroup->spCellConfig->reconfigurationWithSync
&& CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated
&& CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra) {
nr_mac_prepare_ra_ue(RC.nrmac[0], UE->rnti, CellGroup);
}
configure_UE_BWP(nrmac, nrmac->common_channels[0].ServingCellConfigCommon, UE, false, -1, -1);
process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, CellGroup->rlc_BearerToAddModList);
AssertFatal(CellGroup->rlc_BearerToReleaseList == NULL, "cannot release bearers while adding new UEs\n");
NR_SCHED_UNLOCK(&nrmac->sched_lock);
@@ -998,32 +989,18 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t
return true;
}
bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup)
void nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, NR_UE_info_t *UE)
{
DevAssert(nrmac != NULL);
DevAssert(CellGroup != NULL);
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
// NSA case: need to pre-configure CFRA
const int CC_id = 0;
NR_COMMON_channels_t *cc = &nrmac->common_channels[CC_id];
uint8_t ra_index = 0;
/* checking for free RA process */
for(; ra_index < NR_NB_RA_PROC_MAX; ra_index++) {
if ((cc->ra[ra_index].ra_state == nrRA_gNB_IDLE) && (!cc->ra[ra_index].cfra))
break;
}
if (ra_index == NR_NB_RA_PROC_MAX) {
LOG_E(NR_MAC, "RA processes are not available for CFRA RNTI %04x\n", rnti);
return false;
}
NR_RA_t *ra = &cc->ra[ra_index];
NR_RA_t *ra = UE->ra;
ra->cfra = true;
ra->rnti = rnti;
ra->CellGroup = CellGroup;
NR_CellGroupConfig_t *CellGroup = UE->CellGroup;
DevAssert(CellGroup != NULL);
struct NR_CFRA *cfra = CellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra;
uint8_t num_preamble = cfra->resources.choice.ssb->ssb_ResourceList.list.count;
ra->preambles.num_preambles = num_preamble;
NR_COMMON_channels_t *cc = &nrmac->common_channels[0];
for (int i = 0; i < cc->num_active_ssb; i++) {
for (int j = 0; j < num_preamble; j++) {
if (cc->ssb_index[i] == cfra->resources.choice.ssb->ssb_ResourceList.list.array[j]->ssb) {
@@ -1033,8 +1010,7 @@ bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig
}
}
}
LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup\n", ra->cfra ? "CFRA" : "CBRA", rnti);
return true;
LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup\n", ra->cfra ? "CFRA" : "CBRA", UE->rnti);
}
/* Prepare a new CellGroupConfig to be applied for this UE. We cannot

File diff suppressed because it is too large Load Diff

View File

@@ -609,9 +609,6 @@ static void pf_dl(module_id_t module_id,
/* Loop UE_info->list to check retransmission */
UE_iterator(UE_list, UE) {
if (!UE->Msg4_MsgB_ACKed)
continue;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP;

View File

@@ -2060,7 +2060,6 @@ void remove_front_nr_list(NR_list_t *listP)
NR_UE_info_t *find_nr_UE(NR_UEs_t *UEs, rnti_t rntiP)
{
UE_iterator(UEs->connected_ue_list, UE) {
if (UE->rnti == rntiP) {
LOG_D(NR_MAC,"Search and found rnti: %04x\n", rntiP);
@@ -2070,6 +2069,17 @@ NR_UE_info_t *find_nr_UE(NR_UEs_t *UEs, rnti_t rntiP)
return NULL;
}
NR_UE_info_t *find_ra_UE(NR_UEs_t *UEs, rnti_t rntiP)
{
UE_iterator(UEs->access_ue_list, UE) {
if (UE->rnti == rntiP) {
LOG_D(NR_MAC,"Search and found rnti: %04x\n", rntiP);
return UE;
}
}
return NULL;
}
void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_allocator_t *uia)
{
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
@@ -2088,6 +2098,7 @@ void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_alloca
free_sched_pucch_list(sched_ctrl);
uid_linear_allocator_free(uia, UE->uid);
LOG_I(NR_MAC, "Remove NR rnti 0x%04x\n", UE->rnti);
free(UE->ra);
free(UE);
}
@@ -2195,31 +2206,16 @@ static void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl,
// main function to configure parameters of current BWP
void configure_UE_BWP(gNB_MAC_INST *nr_mac,
NR_ServingCellConfigCommon_t *scc,
NR_UE_sched_ctrl_t *sched_ctrl,
NR_RA_t *ra,
NR_UE_info_t *UE,
bool is_RA,
int dl_bwp_switch,
int ul_bwp_switch)
{
AssertFatal((ra != NULL && UE == NULL) || (ra == NULL && UE != NULL), "RA and UE structures are mutually exlusive in BWP configuration\n");
NR_CellGroupConfig_t *CellGroup = UE->CellGroup;
NR_UE_ServingCell_Info_t *sc_info = &UE->sc_info;
NR_UE_DL_BWP_t *DL_BWP = &UE->current_DL_BWP;
NR_UE_UL_BWP_t *UL_BWP = &UE->current_UL_BWP;
NR_CellGroupConfig_t *CellGroup;
NR_UE_ServingCell_Info_t *sc_info;
NR_UE_DL_BWP_t *DL_BWP;
NR_UE_UL_BWP_t *UL_BWP;
if (ra) {
DL_BWP = &ra->DL_BWP;
UL_BWP = &ra->UL_BWP;
CellGroup = ra->CellGroup;
sc_info = &ra->sc_info;
}
else {
DL_BWP = &UE->current_DL_BWP;
UL_BWP = &UE->current_UL_BWP;
CellGroup = UE->CellGroup;
sc_info = &UE->sc_info;
}
NR_BWP_Downlink_t *dl_bwp = NULL;
NR_BWP_Uplink_t *ul_bwp = NULL;
NR_BWP_DownlinkDedicated_t *bwpd = NULL;
@@ -2229,13 +2225,10 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
sc_info->n_ul_bwp = 0;
int old_dl_bwp_id = DL_BWP->bwp_id;
int old_ul_bwp_id = UL_BWP->bwp_id;
int target_ss;
NR_ServingCellConfig_t *servingCellConfig = NULL;
if (CellGroup &&
CellGroup->spCellConfig &&
CellGroup->spCellConfig->spCellConfigDedicated) {
if (CellGroup && CellGroup->spCellConfig && CellGroup->spCellConfig->spCellConfigDedicated) {
servingCellConfig = CellGroup->spCellConfig->spCellConfigDedicated;
target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
@@ -2359,7 +2352,10 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
UL_BWP->rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
}
if(UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
// Reset required fields in sched_ctrl (e.g. ul_ri and tpmi)
reset_sched_ctrl(sched_ctrl);
if(!is_RA) {
if (servingCellConfig) {
if (servingCellConfig->csi_MeasConfig) {
sc_info->csi_MeasConfig = servingCellConfig->csi_MeasConfig->choice.setup;
@@ -2403,18 +2399,9 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
if (CellGroup && CellGroup->physicalCellGroupConfig)
UE->pdsch_HARQ_ACK_Codebook = CellGroup->physicalCellGroupConfig->pdsch_HARQ_ACK_Codebook;
// Reset required fields in sched_ctrl (e.g. ul_ri and tpmi)
reset_sched_ctrl(sched_ctrl);
// setting PDCCH related structures for sched_ctrl
sched_ctrl->search_space = get_searchspace(scc,
bwpd,
target_ss);
sched_ctrl->coreset = get_coreset(nr_mac,
scc,
bwpd,
sched_ctrl->search_space,
target_ss);
sched_ctrl->search_space = get_searchspace(scc, bwpd, target_ss);
sched_ctrl->coreset = get_coreset(nr_mac, scc, bwpd, sched_ctrl->search_space, target_ss);
sched_ctrl->sched_pdcch = set_pdcch_structure(nr_mac,
sched_ctrl->search_space,
@@ -2436,11 +2423,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0) :
NR_UL_DCI_FORMAT_0_0;
set_max_fb_time(UL_BWP, DL_BWP);
set_sched_pucch_list(sched_ctrl, UL_BWP, scc, &nr_mac->frame_structure);
}
if(ra) {
} else {
// setting PDCCH related structures for RA
struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = NULL;
NR_SearchSpaceId_t ra_SearchSpace = 0;
@@ -2453,26 +2436,29 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
}
AssertFatal(commonSearchSpaceList->list.count > 0, "common SearchSpace list has 0 elements\n");
for (int i = 0; i < commonSearchSpaceList->list.count; i++) {
NR_SearchSpace_t * ss = commonSearchSpaceList->list.array[i];
NR_SearchSpace_t *ss = commonSearchSpaceList->list.array[i];
if (ss->searchSpaceId == ra_SearchSpace)
ra->ra_ss = ss;
sched_ctrl->search_space = ss;
}
AssertFatal(ra->ra_ss!=NULL,"SearchSpace cannot be null for RA\n");
AssertFatal(sched_ctrl->search_space != NULL, "SearchSpace cannot be null for RA\n");
ra->coreset = get_coreset(nr_mac, scc, dl_bwp, ra->ra_ss, NR_SearchSpace__searchSpaceType_PR_common);
sched_ctrl->coreset = get_coreset(nr_mac, scc, dl_bwp, sched_ctrl->search_space, NR_SearchSpace__searchSpaceType_PR_common);
NR_COMMON_channels_t *cc = &nr_mac->common_channels[0];
int ssb_index = cc->ssb_index[ra->beam_id];
ra->sched_pdcch = set_pdcch_structure(nr_mac,
ra->ra_ss,
ra->coreset,
scc,
&dl_genericParameters,
&nr_mac->type0_PDCCH_CSS_config[ssb_index]);
int ssb_index = cc->ssb_index[UE->UE_beam_index];
sched_ctrl->sched_pdcch = set_pdcch_structure(nr_mac,
sched_ctrl->search_space,
sched_ctrl->coreset,
scc,
&dl_genericParameters,
&nr_mac->type0_PDCCH_CSS_config[ssb_index]);
UL_BWP->dci_format = NR_UL_DCI_FORMAT_0_0;
DL_BWP->dci_format = NR_DL_DCI_FORMAT_1_0;
}
set_max_fb_time(UL_BWP, DL_BWP);
set_sched_pucch_list(sched_ctrl, UL_BWP, scc, &nr_mac->frame_structure);
// Set MCS tables
long *dl_mcs_Table = DL_BWP->pdsch_Config ? DL_BWP->pdsch_Config->mcs_Table : NULL;
DL_BWP->mcsTableIdx = get_pdsch_mcs_table(dl_mcs_Table, DL_BWP->dci_format, TYPE_C_RNTI_, target_ss);
@@ -2482,9 +2468,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
// Set uplink MCS table
long *mcs_Table = NULL;
if (UL_BWP->pusch_Config)
mcs_Table = UL_BWP->transform_precoding ?
UL_BWP->pusch_Config->mcs_Table :
UL_BWP->pusch_Config->mcs_TableTransformPrecoder;
mcs_Table = UL_BWP->transform_precoding ? UL_BWP->pusch_Config->mcs_Table : UL_BWP->pusch_Config->mcs_TableTransformPrecoder;
UL_BWP->mcs_table = get_pusch_mcs_table(mcs_Table, !UL_BWP->transform_precoding, UL_BWP->dci_format, TYPE_C_RNTI_, target_ss, false);
}
@@ -2502,49 +2486,29 @@ static void init_bler_stats(const NR_bler_options_t *bler_options, NR_bler_stats
bler_stats->bler = (float)(bler_options->lower + bler_options->upper) / 2.0f;
}
//------------------------------------------------------------------------------
NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup)
/* @brief returns a new UE allocated instance.
*
* It will be typically added to the access_ue_list, but not always (e.g.,
* phytest mode), so this is not done in this function (and also, to allow
* error handling). Remove with delete_nr_ue_data(). */
NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup)
{
NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon;
NR_UEs_t *UE_info = &nr_mac->UE_info;
LOG_I(NR_MAC, "Adding new UE context with RNTI 0x%04x\n", rntiP);
dump_nr_list(UE_info->connected_ue_list);
// We will attach at the end, to mitigate race conditions
// This is not good, but we will fix it progressively
NR_UE_info_t *UE = calloc(1, sizeof(NR_UE_info_t));
if(!UE) {
LOG_E(NR_MAC,"want to add UE %04x but the fixed allocated size is full\n",rntiP);
uid_t uid = uid_linear_allocator_new(uia);
/* if the UE list is full, we should reject the UE with an RRC reject
* message, but we do not have this functionality. To keep it simple, do not
* create a UE context here, so we can print an error message. */
if (uid >= MAX_MOBILES_PER_GNB) {
uid_linear_allocator_free(uia, uid);
return NULL;
}
UE->rnti = rntiP;
UE->uid = uid_linear_allocator_new(&UE_info->uid_allocator);
NR_UE_info_t *UE = calloc_or_fail(1, sizeof(NR_UE_info_t));
UE->rnti = rnti;
UE->CellGroup = CellGroup;
UE->Msg4_MsgB_ACKed = CellGroup != NULL;
UE->uid = uid;
UE->ra = calloc(1, sizeof(*UE->ra));
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
memset(sched_ctrl, 0, sizeof(*sched_ctrl));
sched_ctrl->dl_max_mcs = 28; /* do not limit MCS for individual UEs */
sched_ctrl->ta_update = 31;
sched_ctrl->sched_srs.frame = -1;
sched_ctrl->sched_srs.slot = -1;
sched_ctrl->pdcch_cl_adjust = 0;
// Initialize bler_stats
init_bler_stats(&nr_mac->dl_bler, &sched_ctrl->dl_bler_stats, nr_mac->frame);
init_bler_stats(&nr_mac->ul_bler, &sched_ctrl->ul_bler_stats, nr_mac->frame);
// initialize LCID structure
seq_arr_init(&sched_ctrl->lc_config, sizeof(nr_lc_config_t));
// initialize UE BWP information
NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP;
memset(dl_bwp, 0, sizeof(*dl_bwp));
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
memset(ul_bwp, 0, sizeof(*ul_bwp));
configure_UE_BWP(nr_mac, scc, sched_ctrl, NULL, UE, -1, -1);
/* set illegal time domain allocation to force recomputation of all fields */
sched_ctrl->sched_pdsch.time_domain_allocation = -1;
@@ -2558,27 +2522,87 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf
create_dl_harq_list(sched_ctrl, &UE->sc_info);
create_ul_harq_list(sched_ctrl, &UE->sc_info);
reset_srs_stats(UE);
// initialize LCID structure
seq_arr_init(&sched_ctrl->lc_config, sizeof(nr_lc_config_t));
return UE;
}
NR_SCHED_LOCK(&UE_info->mutex);
int i;
for(i=0; i<MAX_MOBILES_PER_GNB; i++) {
if (UE_info->connected_ue_list[i] == NULL) {
UE_info->connected_ue_list[i] = UE;
break;
bool add_UE_to_list(int list_size, NR_UE_info_t *list[list_size], NR_UE_info_t *UE)
{
for (int i = 0; i < list_size; i++) {
if (!list[i]) {
list[i] = UE;
return true;
}
}
if (i == MAX_MOBILES_PER_GNB) {
LOG_E(NR_MAC,"Try to add UE %04x but the list is full\n", rntiP);
delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator);
NR_SCHED_UNLOCK(&UE_info->mutex);
return NULL;
}
NR_SCHED_UNLOCK(&UE_info->mutex);
return false;
}
LOG_D(NR_MAC, "Add NR rnti %x\n", rntiP);
NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], rnti_t rnti)
{
for (int i = 0; i < list_size; i++) {
NR_UE_info_t *curr_UE = list[i];
if (curr_UE->rnti != rnti)
continue;
/* remove this UE from the list, return the pointer */
memmove(&list[i], &list[i+1], sizeof(list[0]) * (list_size - i - 1));
list[list_size - 1] = NULL;
return curr_UE;
}
LOG_E(NR_MAC, "UE %04x to be removed not found in list\n", rnti);
return NULL;
}
/** @brief Transitions a UE from access list to connected list (i.e., the RA
* list to the "normal" UE context list. */
bool transition_ra_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE)
{
NR_UEs_t *UE_info = &nr_mac->UE_info;
// remove UE from initial access list (moved to connected mode)
NR_UE_info_t *r = remove_UE_from_list(NR_NB_RA_PROC_MAX, UE_info->access_ue_list, UE->rnti);
DevAssert(r == UE); /* sanity check: we should have removed the current UE ptr from list */
free_and_zero(UE->ra);
return add_connected_nr_ue(nr_mac, UE);
}
/** @brief Add a UE to the list of UEs in * connected mode.
*
* To remove the UE, use mac_remove_nr_ue(). */
bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE)
{
LOG_I(NR_MAC, "Adding new UE context with RNTI 0x%04x\n", UE->rnti);
NR_UEs_t *UE_info = &nr_mac->UE_info;
dump_nr_list(UE_info->connected_ue_list);
return (UE);
AssertFatal(!UE->ra, "UE in connected cannot have RA process\n");
NR_SCHED_LOCK(&UE_info->mutex);
bool success = add_UE_to_list(MAX_MOBILES_PER_GNB, UE_info->connected_ue_list, UE);
if (!success) {
LOG_E(NR_MAC,"Try to add UE %04x but the list is full\n", UE->rnti);
delete_nr_ue_data(UE, NULL, &UE_info->uid_allocator);
NR_SCHED_UNLOCK(&UE_info->mutex);
return false;
}
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
sched_ctrl->dl_max_mcs = 28; /* do not limit MCS for individual UEs */
sched_ctrl->sched_srs.frame = -1;
sched_ctrl->sched_srs.slot = -1;
sched_ctrl->pdcch_cl_adjust = 0;
reset_srs_stats(UE);
// Initialize bler_stats
init_bler_stats(&nr_mac->dl_bler, &sched_ctrl->dl_bler_stats, nr_mac->frame);
init_bler_stats(&nr_mac->ul_bler, &sched_ctrl->ul_bler_stats, nr_mac->frame);
NR_SCHED_UNLOCK(&UE_info->mutex);
dump_nr_list(UE_info->connected_ue_list);
return true;
}
void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl)
@@ -2683,38 +2707,11 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti)
{
/* already mutex protected */
NR_SCHED_ENSURE_LOCKED(&nr_mac->sched_lock);
NR_UEs_t *UE_info = &nr_mac->UE_info;
NR_SCHED_LOCK(&UE_info->mutex);
UE_iterator(UE_info->connected_ue_list, UE) {
if (UE->rnti==rnti)
break;
}
if (!UE) {
LOG_W(NR_MAC,"Call to del rnti %04x, but not existing\n", rnti);
NR_SCHED_UNLOCK(&UE_info->mutex);
return;
}
NR_UE_info_t * newUEs[MAX_MOBILES_PER_GNB+1]={0};
int newListIdx = 0;
for (int i = 0; i < MAX_MOBILES_PER_GNB; i++)
if(UE_info->connected_ue_list[i] && UE_info->connected_ue_list[i]->rnti != rnti)
newUEs[newListIdx++] = UE_info->connected_ue_list[i];
memcpy(UE_info->connected_ue_list, newUEs, sizeof(UE_info->connected_ue_list));
NR_UE_info_t *UE = remove_UE_from_list(MAX_MOBILES_PER_GNB + 1, UE_info->connected_ue_list, rnti);
NR_SCHED_UNLOCK(&UE_info->mutex);
const int CC_id = 0;
NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
NR_RA_t *ra = &cc->ra[i];
if (ra->rnti == UE->rnti) {
nr_clear_ra_proc(ra);
ra->cfra = 0;
}
}
delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator);
}
@@ -3071,7 +3068,7 @@ static void nr_mac_apply_cellgroup(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
configure_UE_BWP(mac, scc, sched_ctrl, NULL, UE, -1, -1);
configure_UE_BWP(mac, scc, UE, false, -1, -1);
reset_srs_stats(UE);
@@ -3519,24 +3516,14 @@ bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid)
return true;
}
static const NR_RA_t *find_nr_RA_rnti(const NR_RA_t *ra_base, int ra_count, rnti_t rnti)
{
for (int i = 0; i < ra_count; ++i) {
const NR_RA_t *ra = &ra_base[i];
if (ra->ra_state != nrRA_gNB_IDLE && ra->rnti == rnti)
return ra;
}
return NULL;
}
bool nr_mac_get_new_rnti(NR_UEs_t *UEs, const NR_RA_t *ra_base, int ra_count, rnti_t *rnti)
bool nr_mac_get_new_rnti(NR_UEs_t *UEs, rnti_t *rnti)
{
int loop = 0;
bool exist_connected_ue, exist_in_pending_ra_ue;
do {
*rnti = (taus() % 0xffef) + 1;
exist_connected_ue = find_nr_UE(UEs, *rnti) != NULL;
exist_in_pending_ra_ue = find_nr_RA_rnti(ra_base, ra_count, *rnti) != NULL;
exist_in_pending_ra_ue = find_ra_UE(UEs, *rnti) != NULL;
loop++;
} while (loop < 100 && (exist_connected_ue || exist_in_pending_ra_ue));
return loop < 100; // nothing found: loop count 100

View File

@@ -171,39 +171,54 @@ static int get_pucch_index(int frame, int slot, const frame_structure_t *fs, int
return (frame_start + ul_period_start + ul_period_slot) % sched_pucch_size;
}
void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, slot_t slotP)
static void schedule_pucch_core(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, frame_t frame, slot_t slot)
{
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
const int pucch_index = get_pucch_index(frame, slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size);
NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[pucch_index];
if (!curr_pucch->active)
return;
if (frame != curr_pucch->frame || slot != curr_pucch->ul_slot) {
LOG_E(NR_MAC,
"PUCCH frame/slot mismatch: current %4d.%2d vs. request %4d.%2d: not scheduling PUCCH\n",
curr_pucch->frame,
curr_pucch->ul_slot,
frame,
slot);
memset(curr_pucch, 0, sizeof(*curr_pucch));;
return;
}
const uint16_t O_ack = curr_pucch->dai_c;
const uint16_t O_csi = curr_pucch->csi_bits;
const uint8_t O_sr = curr_pucch->sr_flag;
LOG_D(NR_MAC,
"Scheduling PUCCH[%d] RX for UE %04x in %4d.%2d O_ack %d, O_sr %d, O_csi %d\n",
pucch_index,
UE->rnti,
curr_pucch->frame,
curr_pucch->ul_slot,
O_ack,O_sr,
O_csi);
nr_fill_nfapi_pucch(nrmac, frame, slot, curr_pucch, UE);
memset(curr_pucch, 0, sizeof(*curr_pucch));
}
void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frame, slot_t slot)
{
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
if (!is_ul_slot(slotP, &nrmac->frame_structure))
if (!is_ul_slot(slot, &nrmac->frame_structure))
return;
UE_iterator(nrmac->UE_info.access_ue_list, init_UE) {
if (init_UE->ra->ra_state == nrRA_WAIT_Msg4_MsgB_ACK)
schedule_pucch_core(nrmac, init_UE, frame, slot);
}
UE_iterator(nrmac->UE_info.connected_ue_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
const int pucch_index = get_pucch_index(frameP, slotP, &nrmac->frame_structure, sched_ctrl->sched_pucch_size);
NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[pucch_index];
if (!curr_pucch->active)
continue;
if (frameP != curr_pucch->frame || slotP != curr_pucch->ul_slot) {
LOG_E(NR_MAC,
"PUCCH frame/slot mismatch: current %4d.%2d vs. request %4d.%2d: not scheduling PUCCH\n",
curr_pucch->frame,
curr_pucch->ul_slot,
frameP,
slotP);
memset(curr_pucch, 0, sizeof(*curr_pucch));;
continue;
}
const uint16_t O_ack = curr_pucch->dai_c;
const uint16_t O_csi = curr_pucch->csi_bits;
const uint8_t O_sr = curr_pucch->sr_flag;
LOG_D(NR_MAC,"Scheduling PUCCH[%d] RX for UE %04x in %4d.%2d O_ack %d, O_sr %d, O_csi %d\n",
pucch_index,UE->rnti,curr_pucch->frame,curr_pucch->ul_slot,O_ack,O_sr,O_csi);
nr_fill_nfapi_pucch(nrmac, frameP, slotP, curr_pucch, UE);
memset(curr_pucch, 0, sizeof(*curr_pucch));
schedule_pucch_core(nrmac, UE, frame, slot);
}
}
@@ -854,14 +869,19 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, slot_t slot, con
gNB_MAC_INST *nrmac = RC.nrmac[mod_id];
int rssi_threshold = nrmac->pucch_rssi_threshold;
NR_SCHED_LOCK(&nrmac->sched_lock);
NR_UE_info_t * UE = find_nr_UE(&nrmac->UE_info, uci_01->rnti);
NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, uci_01->rnti);
bool is_ra = false;
if (!UE) {
LOG_E(NR_MAC, "%s(): unknown RNTI %04x in PUCCH UCI\n", __func__, uci_01->rnti);
NR_SCHED_UNLOCK(&nrmac->sched_lock);
return;
UE = find_ra_UE(&nrmac->UE_info, uci_01->rnti);
if (UE)
is_ra = true;
else {
LOG_E(NR_MAC, "Unknown RNTI %04x in PUCCH UCI\n", uci_01->rnti);
NR_SCHED_UNLOCK(&nrmac->sched_lock);
return;
}
}
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
if (((uci_01->pduBitmap >> 1) & 0x01)) {
// iterate over received harq bits
for (int harq_bit = 0; harq_bit < uci_01->harq.num_harq; harq_bit++) {
@@ -877,10 +897,12 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, slot_t slot, con
remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
LOG_D(NR_MAC,"%4d.%2d bit %d pid %d ack/nack %d\n",frame, slot, harq_bit,pid,harq_value);
nr_mac_update_pdcch_closed_loop_adjust(sched_ctrl, harq_confidence != 0);
handle_dl_harq(UE, pid, harq_value == 0 && harq_confidence == 0, nrmac->dl_bler.harq_round_max);
if (!UE->Msg4_MsgB_ACKed && harq_value == 0 && harq_confidence == 0)
UE->Msg4_MsgB_ACKed = true;
if (harq_confidence == 1) UE->mac_stats.pucch0_DTX++;
bool success = harq_value == 0 && harq_confidence == 0;
handle_dl_harq(UE, pid, success, nrmac->dl_bler.harq_round_max);
if (is_ra)
nr_check_Msg4_MsgB_Ack(mod_id, frame, slot, UE, success);
if (harq_confidence == 1)
UE->mac_stats.pucch0_DTX++;
}
// tpc (power control) only if we received AckNack

View File

@@ -461,17 +461,13 @@ static int nr_process_mac_pdu(instance_t module_idP,
break;
case UL_SCH_LCID_C_RNTI:
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[i];
if (ra->ra_state == nrRA_gNB_IDLE && ra->rnti == UE->rnti) {
// Extract C-RNTI value
rnti_t crnti = ((pduP[1] & 0xFF) << 8) | (pduP[2] & 0xFF);
AssertFatal(false,
"Received MAC CE for C-RNTI %04x without RA running, procedure exists? Or is it a bug while decoding the "
"MAC PDU?\n",
crnti);
break;
}
if (UE->ra && UE->ra->ra_state == nrRA_gNB_IDLE) {
// Extract C-RNTI value
rnti_t crnti = ((pduP[1] & 0xFF) << 8) | (pduP[2] & 0xFF);
AssertFatal(false,
"Received MAC CE for C-RNTI %04x without RA running, procedure exists? Or is it a bug while decoding the "
"MAC PDU?\n",
crnti);
}
break;
@@ -547,24 +543,7 @@ static void abort_nr_ul_harq(NR_UE_info_t *UE, int8_t harq_pid)
sched_ctrl->sched_ul_bytes = 0;
}
static bool get_UE_waiting_CFRA_msg3(const gNB_MAC_INST *gNB_mac,
const int CC_id,
const frame_t frame,
const slot_t slot,
rnti_t rnti)
{
bool UE_waiting_CFRA_msg3 = false;
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
const NR_RA_t *ra = &gNB_mac->common_channels[CC_id].ra[i];
if (ra->cfra && ra->ra_state == nrRA_WAIT_Msg3 && frame == ra->Msg3_frame && slot == ra->Msg3_slot && rnti == ra->rnti) {
UE_waiting_CFRA_msg3 = true;
break;
}
}
return UE_waiting_CFRA_msg3;
}
void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, slot_t slot, const nfapi_nr_crc_t *crc_pdu)
void handle_nr_ul_harq(module_id_t mod_id, frame_t frame, slot_t slot, const nfapi_nr_crc_t *crc_pdu)
{
gNB_MAC_INST *nrmac = RC.nrmac[mod_id];
if (nrmac->radio_config.disable_harq) {
@@ -573,12 +552,13 @@ void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, slot
}
NR_SCHED_LOCK(&nrmac->sched_lock);
for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
NR_RA_t *ra = &nrmac->common_channels[CC_idP].ra[i];
NR_UEs_t *UE_info = &nrmac->UE_info;
UE_iterator(UE_info->access_ue_list, ra_UE) {
const NR_RA_t *ra = ra_UE->ra;
// if we find any ongoing RA that has already scheduled MSG3
// and it is expecting its reception in current frame and slot with matching RNTI
// we can exit the function (no HARQ involved)
if (ra->ra_state >= nrRA_WAIT_Msg3 && ra->rnti == crc_pdu->rnti && frame == ra->Msg3_frame && slot == ra->Msg3_slot) {
if (ra->ra_state >= nrRA_WAIT_Msg3 && ra_UE->rnti == crc_pdu->rnti && frame == ra->Msg3_frame && slot == ra->Msg3_slot) {
LOG_D(NR_MAC, "UL for rnti %04x in RA (MSG3), no need to process HARQ\n", crc_pdu->rnti);
NR_SCHED_UNLOCK(&nrmac->sched_lock);
return;
@@ -586,6 +566,7 @@ void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, slot
}
NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, crc_pdu->rnti);
UE = UE ? UE : find_ra_UE(&nrmac->UE_info, crc_pdu->rnti);
if (!UE) {
NR_SCHED_UNLOCK(&nrmac->sched_lock);
LOG_E(NR_MAC, "Couldn't identify UE connected with current UL HARQ process\n");
@@ -641,29 +622,56 @@ void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, slot
NR_SCHED_UNLOCK(&nrmac->sched_lock);
}
static void handle_msg3_failed_rx(NR_RA_t *ra, int i, int harq_round_max)
static void handle_msg3_failed_rx(gNB_MAC_INST *mac, NR_RA_t *ra, rnti_t rnti, int harq_round_max)
{
// for CFRA (NSA) do not schedule retransmission of msg3
if (ra->cfra) {
LOG_D(NR_MAC, "Random Access %i failed at state %s (NSA msg3 reception failed)\n", i, nrra_text[ra->ra_state]);
nr_clear_ra_proc(ra);
LOG_W(NR_MAC, "UE %04x RA failed at state %s (NSA msg3 reception failed)\n", rnti, nrra_text[ra->ra_state]);
nr_release_ra_UE(mac, rnti);
return;
}
if (ra->msg3_round >= harq_round_max - 1) {
LOG_W(NR_MAC, "Random Access %i failed at state %s (Reached msg3 max harq rounds)\n", i, nrra_text[ra->ra_state]);
nr_clear_ra_proc(ra);
LOG_W(NR_MAC, "UE %04x RA failed at state %s (Reached msg3 max harq rounds)\n", rnti, nrra_text[ra->ra_state]);
nr_release_ra_UE(mac, rnti);
return;
}
LOG_D(NR_MAC, "Random Access %i Msg3 CRC did not pass\n", i);
LOG_D(NR_MAC, "UE %04x Msg3 CRC did not pass\n", rnti);
ra->msg3_round++;
ra->ra_state = nrRA_Msg3_retransmission;
}
/*
* When data are received on PHY and transmitted to MAC
*/
static NR_UE_info_t *configure_UE_crnti_msg3(gNB_MAC_INST *mac, NR_UE_info_t *old_UE, NR_UE_info_t *new_UE)
{
// in case UE beam has changed
old_UE->UE_beam_index = new_UE->UE_beam_index;
// Reset UL failure for old UE
nr_mac_reset_ul_failure(&old_UE->UE_sched_ctrl);
// Reset HARQ processes
reset_dl_harq_list(&old_UE->UE_sched_ctrl);
reset_ul_harq_list(&old_UE->UE_sched_ctrl);
// old UE need to complete RA by sending DL
free_and_zero(old_UE->ra);
old_UE->ra = new_UE->ra;
new_UE->ra = NULL;
NR_UE_sched_ctrl_t *sched_ctrl = &old_UE->UE_sched_ctrl;
sched_ctrl->search_space = new_UE->UE_sched_ctrl.search_space;
sched_ctrl->coreset = new_UE->UE_sched_ctrl.coreset;
memcpy(&sched_ctrl->sched_pdcch, &new_UE->UE_sched_ctrl.sched_pdcch, sizeof(NR_sched_pdcch_t));
old_UE->current_DL_BWP.dci_format = NR_DL_DCI_FORMAT_1_0;
// replace new UE with old UE in the access list
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
if (mac->UE_info.access_ue_list[i] && mac->UE_info.access_ue_list[i]->rnti == new_UE->rnti) {
mac->UE_info.access_ue_list[i] = old_UE;
break;
}
}
// remove new UE
delete_nr_ue_data(new_UE, mac->common_channels, &mac->UE_info.uid_allocator);
return old_UE;
}
static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
const int CC_idP,
const frame_t frameP,
@@ -685,9 +693,8 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
const int pusch_failure_thres = gNB_mac->pusch_failure_thres;
NR_UE_info_t *UE = find_nr_UE(&gNB_mac->UE_info, current_rnti);
bool UE_waiting_CFRA_msg3 = get_UE_waiting_CFRA_msg3(gNB_mac, CC_idP, frameP, slotP, current_rnti);
if (UE && UE_waiting_CFRA_msg3 == false) {
if (UE) {
NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl;
@@ -791,74 +798,45 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
}
}
} else if (sduP) {
bool no_sig = true;
for (uint32_t k = 0; k < sdu_lenP; k++) {
if (sduP[k] != 0) {
no_sig = false;
break;
}
} else {
UE = find_ra_UE(&gNB_mac->UE_info, current_rnti);
if (!UE) {
LOG_E(NR_MAC, "UL SDU discarded. Couldn't finde UE with RNTI %04x \n", current_rnti);
return;
}
NR_RA_t *ra = UE->ra;
if (ra->ra_type == RA_4_STEP && ra->ra_state != nrRA_WAIT_Msg3) {
LOG_W(NR_MAC, "UL SDU discarded for RNTI %04x RA state not waiting for PUSCH\n", UE->rnti);
return;
}
if (sduP) {
bool no_sig = true;
for (uint32_t k = 0; k < sdu_lenP; k++) {
if (sduP[k] != 0) {
no_sig = false;
break;
}
}
T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP),
T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */,
T_BUFFER(sduP, sdu_lenP));
T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP),
T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */,
T_BUFFER(sduP, sdu_lenP));
/* we don't know this UE (yet). Check whether there is a ongoing RA (Msg 3)
* and check the corresponding UE's RNTI match, in which case we activate
* it. */
for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i];
if (ra->ra_type == RA_4_STEP && ra->ra_state != nrRA_WAIT_Msg3)
continue;
if (no_sig) {
LOG_W(NR_MAC, "Random Access %i ULSCH with no signal\n", i);
handle_msg3_failed_rx(ra, i, gNB_mac->ul_bler.harq_round_max);
continue;
LOG_W(NR_MAC, "MSG3 ULSCH with no signal\n");
handle_msg3_failed_rx(gNB_mac, ra, current_rnti, gNB_mac->ul_bler.harq_round_max);
return;
}
if (ra->ra_type == RA_2_STEP) {
// random access pusch with RA-RNTI
if (ra->RA_rnti != current_rnti) {
LOG_E(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->RA_rnti, current_rnti);
continue;
}
} else {
// random access pusch with TC-RNTI
if (ra->rnti != current_rnti) {
LOG_E(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->rnti, current_rnti);
if ((frameP == ra->Msg3_frame) && (slotP == ra->Msg3_slot)) {
LOG_W(NR_MAC,
"Random Access %i failed at state %s (TC_RNTI %04x RNTI %04x)\n",
i,
nrra_text[ra->ra_state],
ra->rnti,
current_rnti);
nr_clear_ra_proc(ra);
}
continue;
return;
}
}
UE = UE ? UE : add_new_nr_ue(gNB_mac, ra->rnti, ra->CellGroup);
if (!UE) {
LOG_W(NR_MAC,
"Random Access %i discarded at state %s (TC_RNTI %04x RNTI %04x): max number of users achieved!\n",
i,
nrra_text[ra->ra_state],
ra->rnti,
current_rnti);
nr_clear_ra_proc(ra);
return;
}
UE->UE_beam_index = ra->beam_id;
// re-initialize ta update variables after RA procedure completion
// re-initialize ta update variables after RA procedure completion
UE->UE_sched_ctrl.ta_frame = frameP;
LOG_A(NR_MAC, "%4d.%2d PUSCH with TC_RNTI 0x%04x received correctly\n", frameP, slotP, current_rnti);
@@ -873,12 +851,16 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
UE_scheduling_control->raw_rssi = rssi;
LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update);
if (ra->cfra) {
LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", ra->rnti);
LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", UE->rnti);
nr_mac_reset_ul_failure(UE_scheduling_control);
reset_dl_harq_list(UE_scheduling_control);
reset_ul_harq_list(UE_scheduling_control);
process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, ra->CellGroup->rlc_BearerToAddModList);
nr_clear_ra_proc(ra);
process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, UE->CellGroup->rlc_BearerToAddModList);
if (!transition_ra_connected_nr_ue(gNB_mac, UE)) {
LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti);
delete_nr_ue_data(UE, NULL, &gNB_mac->UE_info.uid_allocator);
return;
}
} else {
LOG_D(NR_MAC, "[RAPROC] Received %s:\n", ra->ra_type == RA_2_STEP ? "MsgA-PUSCH" : "Msg3");
for (uint32_t k = 0; k < sdu_lenP; k++) {
@@ -892,40 +874,20 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
// Search for MAC CE for C-RNTI
rnti_t crnti = lcid_crnti_lookahead(sduP, sdu_lenP);
if (crnti != 0) { // 3GPP TS 38.321 Table 7.1-1: RNTI values, RNTI 0x0000: N/A
// this UE is the one identified by the RNTI in sduP
ra->rnti = crnti;
// Remove UE context just created after Msg.3 in some milliseconds as the UE is one already known (not now, as the UE
// context is still needed for the moment)
nr_mac_trigger_release_timer(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
// Replace the current UE by the UE identified by C-RNTI
UE = find_nr_UE(&gNB_mac->UE_info, crnti);
if (!UE) {
NR_UE_info_t *old_UE = find_nr_UE(&gNB_mac->UE_info, crnti);
if (!old_UE) {
// The UE identified by C-RNTI no longer exists at the gNB
// Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better
// solution may be implemented
LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg3 to have UE come back with new RA attempt\n", ra->rnti);
mac_remove_nr_ue(gNB_mac, ra->rnti);
nr_clear_ra_proc(ra);
LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg3 to have UE come back with new RA attempt\n", UE->rnti);
nr_release_ra_UE(gNB_mac, current_rnti);
return;
}
// The UE identified by C-RNTI still exists at the gNB
// Reset Msg4_ACKed to not schedule ULSCH and DLSCH before RRC Reconfiguration
UE->Msg4_MsgB_ACKed = false;
nr_mac_reset_ul_failure(&UE->UE_sched_ctrl);
// Reset HARQ processes
reset_dl_harq_list(&UE->UE_sched_ctrl);
reset_ul_harq_list(&UE->UE_sched_ctrl);
// Switch to BWP where RA is configured, typically in the InitialBWP
// At this point, UE already switched and triggered RA in that BWP, need to do BWP switching also at gNB for C-RNTI
if (ra->DL_BWP.bwp_id != UE->current_DL_BWP.bwp_id || ra->UL_BWP.bwp_id != UE->current_UL_BWP.bwp_id) {
LOG_D(NR_MAC, "UE %04x Switch BWP from %ld to BWP id %ld\n", UE->rnti, UE->current_DL_BWP.bwp_id, ra->DL_BWP.bwp_id);
NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_idP].ServingCellConfigCommon;
configure_UE_BWP(gNB_mac, scc, &UE->UE_sched_ctrl, NULL, UE, ra->DL_BWP.bwp_id, ra->UL_BWP.bwp_id);
}
// remove old UE from connected UEs
remove_UE_from_list(MAX_MOBILES_PER_GNB + 1, gNB_mac->UE_info.connected_ue_list, crnti);
UE = configure_UE_crnti_msg3(gNB_mac, old_UE, UE);
ra = UE->ra;
if (UE->reconfigCellGroup) {
// Nothing to do
// A RRCReconfiguration message should be already pending (for example, an ongoing RRCReestablishment), and it will be
@@ -950,26 +912,23 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
LOG_I(NR_MAC,
"Activating scheduling %s for TC_RNTI 0x%04x (state %s)\n",
ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4",
ra->rnti,
UE->rnti,
nrra_text[ra->ra_state]);
ra->ra_state = ra->ra_type == RA_2_STEP ? nrRA_MsgB : nrRA_Msg4;
LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", ra->rnti, nrra_text[ra->ra_state]);
LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", UE->rnti, nrra_text[ra->ra_state]);
return;
}
}
} else {
for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[i];
} else {
if (ra->ra_state != nrRA_WAIT_Msg3)
continue;
return;
if((frameP!=ra->Msg3_frame) || (slotP!=ra->Msg3_slot))
continue;
return;
if (ul_cqi != 0xff)
ra->msg3_TPC = nr_get_tpc(target_snrx10, ul_cqi, 30, 0);
handle_msg3_failed_rx(ra, i, gNB_mac->ul_bler.harq_round_max);
handle_msg3_failed_rx(gNB_mac, ra, current_rnti, gNB_mac->ul_bler.harq_round_max);
}
}
}
@@ -1891,7 +1850,7 @@ static void pf_ul(module_id_t module_id,
UE_iterator(UE_list, UE) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
if (!UE->Msg4_MsgB_ACKed || sched_ctrl->ul_failure)
if (sched_ctrl->ul_failure)
continue;
LOG_D(NR_MAC,"pf_ul: preparing UL scheduling for UE %04x\n",UE->rnti);

View File

@@ -60,8 +60,8 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c
void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const plmn_id_t *plmn, uint64_t cellID, int tac);
bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_sib_msg_t cu_sib[num_cu_sib]);
bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup);
bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup);
void nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, NR_UE_info_t *UE);
bool add_new_UE_RA(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE);
int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs);
bool nr_mac_prepare_cellgroup_update(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, NR_CellGroupConfig_t *CellGroup);
@@ -135,8 +135,6 @@ void nr_initiate_ra_proc(module_id_t module_idP,
int16_t timing_offset,
uint32_t preamble_power);
void nr_clear_ra_proc(NR_RA_t *ra);
int nr_allocate_CCEs(int module_idP, int CC_idP, frame_t frameP, slot_t slotP, int test_only);
void schedule_nr_prach(module_id_t module_idP, frame_t frameP, slot_t slotP);
@@ -310,21 +308,22 @@ void remove_nr_list(NR_list_t *listP, int id);
void add_tail_nr_list(NR_list_t *listP, int id);
void add_front_nr_list(NR_list_t *listP, int id);
void remove_front_nr_list(NR_list_t *listP);
void nr_release_ra_UE(gNB_MAC_INST *mac, rnti_t rnti);
NR_UE_info_t * find_nr_UE(NR_UEs_t* UEs, rnti_t rntiP);
NR_UE_info_t *find_ra_UE(NR_UEs_t *UEs, rnti_t rntiP);
void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_allocator_t *uia);
void configure_UE_BWP(gNB_MAC_INST *nr_mac,
NR_ServingCellConfigCommon_t *scc,
NR_UE_sched_ctrl_t *sched_ctrl,
NR_RA_t *ra,
NR_UE_info_t *UE,
bool is_RA,
int dl_bwp_switch,
int ul_bwp_switch);
NR_UE_info_t* add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConfig_t *CellGroup);
bool transition_ra_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE);
bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE);
void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, NR_UE_info_t *UE, bool success);
void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti);
NR_UE_info_t *get_new_nr_ue_inst(uid_allocator_t *uia, rnti_t rnti, NR_CellGroupConfig_t *CellGroup);
int nr_get_default_pucch_res(int pucch_ResourceCommon);
int nr_write_ce_dlsch_pdu(module_id_t module_idP,
@@ -362,11 +361,7 @@ void reset_dl_harq_list(NR_UE_sched_ctrl_t *sched_ctrl);
void reset_ul_harq_list(NR_UE_sched_ctrl_t *sched_ctrl);
void handle_nr_ul_harq(const int CC_idP,
module_id_t mod_id,
frame_t frame,
slot_t slot,
const nfapi_nr_crc_t *crc_pdu);
void handle_nr_ul_harq(module_id_t mod_id, frame_t frame, slot_t slot, const nfapi_nr_crc_t *crc_pdu);
uint8_t *allocate_transportBlock_buffer(byte_array_t *tb, uint32_t needed);
void free_transportBlock_buffer(byte_array_t *tb);
@@ -394,7 +389,8 @@ uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx);
uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format);
void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl);
bool add_UE_to_list(int list_size, NR_UE_info_t *list[list_size], NR_UE_info_t *UE);
NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size], rnti_t rnti);
int get_dl_tda(const gNB_MAC_INST *nrmac, int slot);
int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot);
@@ -430,7 +426,6 @@ int get_mcs_from_bler(const NR_bler_options_t *bler_options,
int ul_buffer_index(int frame, int slot, int slots_per_frame, int size);
void UL_tti_req_ahead_initialization(gNB_MAC_INST *gNB, int n, int CCid, frame_t frameP, int slotP);
void fapi_beam_index_allocation(NR_ServingCellConfigCommon_t *scc, gNB_MAC_INST *mac);
int get_fapi_beamforming_index(gNB_MAC_INST *mac, int ssb_idx);
NR_beam_alloc_t beam_allocation_procedure(NR_beam_info_t *beam_info, int frame, int slot, int beam_index, int slots_per_frame);
@@ -467,7 +462,7 @@ void process_addmod_bearers_cellGroupConfig(NR_UE_sched_ctrl_t *sched_ctrl,
bool nr_mac_add_lcid(NR_UE_sched_ctrl_t *sched_ctrl, const nr_lc_config_t *c);
bool nr_mac_remove_lcid(NR_UE_sched_ctrl_t *sched_ctrl, long lcid);
bool nr_mac_get_new_rnti(NR_UEs_t *UEs, const NR_RA_t *ra_base, int ra_count, rnti_t *rnti);
bool nr_mac_get_new_rnti(NR_UEs_t *UEs, rnti_t *rnti);
void nr_mac_update_pdcch_closed_loop_adjust(NR_UE_sched_ctrl_t *sched_ctrl, bool feedback_not_detected);
void prepare_du_configuration_update(gNB_MAC_INST *mac,

View File

@@ -476,15 +476,18 @@ NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig)
static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id)
{
int CC_id = 0;
const NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
rnti_t rnti;
bool found = nr_mac_get_new_rnti(&mac->UE_info, cc->ra, sizeofArray(cc->ra), &rnti);
bool found = nr_mac_get_new_rnti(&mac->UE_info, &rnti);
if (!found)
return NULL;
NR_UE_info_t* UE = add_new_nr_ue(mac, rnti, NULL);
if (!UE)
NR_UE_info_t *UE = get_new_nr_ue_inst(&mac->UE_info.uid_allocator, rnti, NULL);
AssertFatal(UE != NULL, "cannot create UE context, UE context setup failure not implemented\n");
if (!add_new_UE_RA(mac, UE)) {
delete_nr_ue_data(UE, /*not used*/ NULL, &mac->UE_info.uid_allocator);
LOG_E(NR_MAC, "UE list full while creating new UE\n");
return NULL;
}
f1_ue_data_t new_ue_data = {.secondary_ue = cu_id};
bool success = du_add_f1_ue_data(rnti, &new_ue_data);
@@ -499,11 +502,10 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id)
// by add_new_nr_ue(); it's a kind of chicken-and-egg problem), so below we
// complete the UE context with the information that add_new_nr_ue() would
// have added
UE->Msg4_MsgB_ACKed = true;
UE->CellGroup = cellGroupConfig;
nr_rlc_activate_srb0(UE->rnti, UE, NULL);
nr_mac_prepare_ra_ue(mac, rnti, UE->CellGroup);
nr_mac_prepare_ra_ue(mac, UE);
/* SRB1 is added to RLC and MAC in the handler later */
return UE;
}
@@ -759,13 +761,6 @@ void ue_context_modification_refuse(const f1ap_ue_context_modif_refuse_t *refuse
return;
}
const int CC_id = 0;
NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
NR_RA_t *ra = &cc->ra[i];
if (ra->rnti == UE->rnti)
nr_clear_ra_proc(ra);
}
NR_SCHED_UNLOCK(&mac->sched_lock);
f1ap_ue_context_release_req_t request = {
@@ -822,6 +817,7 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
pthread_mutex_lock(&mac->sched_lock);
/* check first that the scheduler knows such UE */
NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, dl_rrc->gNB_DU_ue_id);
UE = UE ? UE : find_ra_UE(&mac->UE_info, dl_rrc->gNB_DU_ue_id);
if (UE == NULL) {
LOG_E(MAC, "ERROR: unknown UE with RNTI %04x, ignoring DL RRC Message Transfer\n", dl_rrc->gNB_DU_ue_id);
pthread_mutex_unlock(&mac->sched_lock);
@@ -870,12 +866,11 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
* from the current configuration. Also, expect the reconfiguration from
* the CU, so save the old UE's CellGroup for the new UE */
UE->CellGroup->spCellConfig = NULL;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
uid_t temp_uid = UE->uid;
UE->uid = oldUE->uid;
oldUE->uid = temp_uid;
configure_UE_BWP(mac, scc, sched_ctrl, NULL, UE, -1, -1);
configure_UE_BWP(mac, scc, UE, false, -1, -1);
for (int i = 1; i < seq_arr_size(&oldUE->UE_sched_ctrl.lc_config); ++i) {
const nr_lc_config_t *c = seq_arr_at(&oldUE->UE_sched_ctrl.lc_config, i);
nr_mac_add_lcid(&UE->UE_sched_ctrl, c);

View File

@@ -362,6 +362,9 @@ void mac_top_destroy_gNB(gNB_MAC_INST *mac)
for (int i = 0; i < sizeofArray(UE_info->connected_ue_list); ++i)
if (UE_info->connected_ue_list[i])
delete_nr_ue_data(UE_info->connected_ue_list[i], cc, &UE_info->uid_allocator);
for (int i = 0; i < sizeofArray(UE_info->access_ue_list); ++i)
if (UE_info->access_ue_list[i])
delete_nr_ue_data(UE_info->access_ue_list[i], cc, &UE_info->uid_allocator);
}
void nr_mac_send_f1_setup_req(void)

View File

@@ -229,8 +229,6 @@ typedef struct {
NR_beam_alloc_t Msg3_beam;
/// harq_pid used for Msg4 transmission
uint8_t harq_pid;
/// UE RNTI allocated during RAR
rnti_t rnti;
/// RA RNTI allocated from received PRACH
uint16_t RA_rnti;
/// MsgB RNTI allocated from received MsgA
@@ -251,25 +249,12 @@ typedef struct {
int msg3_nbSymb;
/// MAC PDU length for Msg4
int mac_pdu_length;
/// RA search space
NR_SearchSpace_t *ra_ss;
/// RA Coreset
NR_ControlResourceSet_t *coreset;
NR_sched_pdcch_t sched_pdcch;
// Beam index
uint8_t beam_id;
/// CellGroup for UE that is to come (NSA is non-null, null for SA)
NR_CellGroupConfig_t *CellGroup;
/// Preambles for contention-free access
NR_preamble_ue_t preambles;
int contention_resolution_timer;
nr_ra_type_t ra_type;
/// CFRA flag
bool cfra;
// BWP for RA
NR_UE_DL_BWP_t DL_BWP;
NR_UE_UL_BWP_t UL_BWP;
NR_UE_ServingCell_Info_t sc_info;
} NR_RA_t;
/*! \brief gNB common channels */
@@ -289,8 +274,6 @@ typedef struct {
/// used for otherSIB data
uint8_t other_sib_bcch_pdu[2][NR_MAX_SIB_LENGTH / 8];
int other_sib_bcch_length[2];
/// Template for RA computations
NR_RA_t ra[NR_NB_RA_PROC_MAX];
/// VRB map for common channels
uint16_t vrb_map[MAX_NUM_BEAM_PERIODS][275];
/// VRB map for common channels and PUSCH, dynamically allocated because
@@ -654,7 +637,6 @@ typedef struct {
int pusch_snrx10;
int pucch_snrx10;
uint16_t ul_rssi;
uint8_t current_harq_pid;
int pusch_consecutive_dtx_cnt;
int pucch_consecutive_dtx_cnt;
bool ul_failure;
@@ -770,11 +752,11 @@ typedef struct {
NR_UE_NR_Capability_t *capability;
// UE selected beam index
uint8_t UE_beam_index;
bool Msg4_MsgB_ACKed;
float ul_thr_ue;
float dl_thr_ue;
long pdsch_HARQ_ACK_Codebook;
bool is_redcap;
NR_RA_t *ra;
} NR_UE_info_t;
typedef struct {
@@ -782,6 +764,7 @@ typedef struct {
// last element always NULL
pthread_mutex_t mutex;
NR_UE_info_t *connected_ue_list[MAX_MOBILES_PER_GNB + 1];
NR_UE_info_t *access_ue_list[NR_NB_RA_PROC_MAX];
// bitmap of CSI-RS already scheduled in current slot
int sched_csirs;
uid_allocator_t uid_allocator;

View File

@@ -203,7 +203,7 @@ static void handle_nr_ulsch(NR_UL_IND_t *UL_info)
crc->timing_advance,
crc->ul_cqi,
crc->rssi);
handle_nr_ul_harq(UL_info->CC_id, UL_info->module_id, UL_info->frame, UL_info->slot, crc);
handle_nr_ul_harq(UL_info->module_id, UL_info->frame, UL_info->slot, crc);
}
UL_info->rx_ind.number_of_pdus = 0;
UL_info->crc_ind.number_crcs = 0;

View File

@@ -371,9 +371,17 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *ue_context_p, x2a
&& secondaryCellGroup->spCellConfig->reconfigurationWithSync
&& secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated
&& secondaryCellGroup->spCellConfig->reconfigurationWithSync->rach_ConfigDedicated->choice.uplink->cfra);
NR_SCHED_LOCK(&RC.nrmac[rrc->module_id]->sched_lock);
ret = nr_mac_prepare_ra_ue(RC.nrmac[rrc->module_id], du_ue_id, secondaryCellGroup);
NR_SCHED_UNLOCK(&RC.nrmac[rrc->module_id]->sched_lock);
gNB_MAC_INST *nrmac = RC.nrmac[rrc->module_id];
NR_SCHED_LOCK(&nrmac->sched_lock);
NR_UE_info_t *UE_info = get_new_nr_ue_inst(&nrmac->UE_info.uid_allocator, UE->rnti, secondaryCellGroup);
AssertFatal(UE_info != NULL, "cannot create UE context: list is full?\n");
if (add_new_UE_RA(nrmac, UE_info)) {
ret = true;
nr_mac_prepare_ra_ue(nrmac, UE_info);
} else {
delete_nr_ue_data(UE_info, /* not used */ NULL, &nrmac->UE_info.uid_allocator);
}
NR_SCHED_UNLOCK(&nrmac->sched_lock);
}
AssertFatal(ret, "cannot add NSA UE in MAC, aborting\n");