Merge remote-tracking branch 'origin/new_UE_context_improvements' into integration_2025_w18 (!3291)
Improvements in handling UE context in gNB DU The goal of this MR is to improve the handling of UE context in gNB DU. To achieve this goal, the UE structure is created as soon as the gNB receive a PRACH indication. At that stage the UE is placed in a new structure containing UEs performing RA, untill RA is complete where it is moved to the list of connected UEs. To simplify the code and to improve the handling of initial procedures (see #751), DCI 10 and DCI 00 is used at every stage until the DU receives from CU the indication of UE RRC reconfiguration being completed.
This commit is contained in:
@@ -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,18 @@ 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);
|
||||
}
|
||||
int ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
|
||||
configure_UE_BWP(nrmac, nrmac->common_channels[0].ServingCellConfigCommon, UE, false, ss_type, -1, -1);
|
||||
process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, CellGroup->rlc_BearerToAddModList);
|
||||
AssertFatal(CellGroup->rlc_BearerToReleaseList == NULL, "cannot release bearers while adding new UEs\n");
|
||||
NR_SCHED_UNLOCK(&nrmac->sched_lock);
|
||||
@@ -998,32 +990,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,27 +1011,5 @@ 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;
|
||||
}
|
||||
|
||||
/* Prepare a new CellGroupConfig to be applied for this UE. We cannot
|
||||
* immediatly apply it, as we have to wait for the reconfiguration through RRC.
|
||||
* This function sets up everything to apply the reconfiguration. Later, we
|
||||
* will trigger the UE inactivity with nr_mac_interrupt_ue_transmission(); upon
|
||||
* expiry, nr_mac_apply_cellgroup() will apply the CellGroupConfig (radio
|
||||
* config etc). */
|
||||
bool nr_mac_prepare_cellgroup_update(gNB_MAC_INST *nrmac, NR_UE_info_t *UE, NR_CellGroupConfig_t *CellGroup)
|
||||
{
|
||||
DevAssert(nrmac != NULL);
|
||||
DevAssert(UE != NULL);
|
||||
DevAssert(CellGroup != NULL);
|
||||
|
||||
/* we assume that this function is mutex-protected from outside */
|
||||
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
|
||||
|
||||
UE->reconfigCellGroup = CellGroup;
|
||||
UE->expect_reconfiguration = true;
|
||||
|
||||
return true;
|
||||
LOG_I(NR_MAC, "Added new %s process for UE RNTI %04x with initial CellGroup\n", ra->cfra ? "CFRA" : "CBRA", UE->rnti);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -323,7 +323,7 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP,
|
||||
|
||||
static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, slot_t slot)
|
||||
{
|
||||
UE_iterator(RC.nrmac[module_id]->UE_info.list, UE) {
|
||||
UE_iterator(RC.nrmac[module_id]->UE_info.connected_ue_list, UE) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
sched_ctrl->num_total_bytes = 0;
|
||||
sched_ctrl->dl_pdus_total = 0;
|
||||
@@ -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;
|
||||
|
||||
@@ -865,7 +862,7 @@ static void nr_dlsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s
|
||||
gNB_MAC_INST *mac = RC.nrmac[module_id];
|
||||
NR_UEs_t *UE_info = &mac->UE_info;
|
||||
|
||||
if (UE_info->list[0] == NULL)
|
||||
if (UE_info->connected_ue_list[0] == NULL)
|
||||
return;
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
@@ -885,7 +882,7 @@ static void nr_dlsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s
|
||||
max_sched_ues = min(max_sched_ues, MAX_DCI_CORESET);
|
||||
|
||||
/* proportional fair scheduling algorithm */
|
||||
pf_dl(module_id, frame, slot, UE_info->list, max_sched_ues, num_beams, n_rb_sched);
|
||||
pf_dl(module_id, frame, slot, UE_info->connected_ue_list, max_sched_ues, num_beams, n_rb_sched);
|
||||
}
|
||||
|
||||
nr_pp_impl_dl nr_init_dlsch_preprocessor(int CC_id) {
|
||||
@@ -940,7 +937,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
|
||||
const NR_BWP_t *initialDL = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
|
||||
gNB_mac->mac_stats.total_prb_aggregate += NRRIV2BW(initialDL->locationAndBandwidth, MAX_BWP_SIZE);
|
||||
|
||||
UE_iterator(UE_info->list, UE) {
|
||||
UE_iterator(UE_info->connected_ue_list, UE) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_DL_BWP_t *current_BWP = &UE->current_DL_BWP;
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ void nr_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slot)
|
||||
int slot_period = slot % mac->frame_structure.numb_slots_period;
|
||||
if (!is_xlsch_in_slot(dlsch_slot_bitmap, slot_period))
|
||||
return;
|
||||
NR_UE_info_t *UE = mac->UE_info.list[0];
|
||||
NR_UE_info_t *UE = mac->UE_info.connected_ue_list[0];
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP;
|
||||
@@ -214,9 +214,9 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, slot_t slo
|
||||
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
|
||||
NR_COMMON_channels_t *cc = nr_mac->common_channels;
|
||||
NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
NR_UE_info_t *UE = nr_mac->UE_info.list[0];
|
||||
NR_UE_info_t *UE = nr_mac->UE_info.connected_ue_list[0];
|
||||
|
||||
AssertFatal(nr_mac->UE_info.list[1] == NULL,
|
||||
AssertFatal(nr_mac->UE_info.connected_ue_list[1] == NULL,
|
||||
"cannot handle more than one UE\n");
|
||||
if (UE == NULL)
|
||||
return false;
|
||||
|
||||
@@ -125,16 +125,22 @@ static const uint16_t cqi_table3[16][2] = {{0, 0},
|
||||
static void determine_aggregation_level_search_order(int agg_level_search_order[NUM_PDCCH_AGG_LEVELS],
|
||||
float pdcch_cl_adjust);
|
||||
|
||||
uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl,
|
||||
const nr_dci_format_t dci_format) {
|
||||
|
||||
uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format)
|
||||
{
|
||||
// TODO check this but it should be enough for now
|
||||
// if there is not csi report activated RI is 0 from initialization
|
||||
if(dci_format == NR_DL_DCI_FORMAT_1_0)
|
||||
return 1;
|
||||
else
|
||||
return (sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.ri + 1);
|
||||
return sched_ctrl->CSI_report.cri_ri_li_pmi_cqi_report.ri + 1;
|
||||
}
|
||||
|
||||
int get_ul_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format)
|
||||
{
|
||||
if(dci_format == NR_UL_DCI_FORMAT_0_0)
|
||||
return 1;
|
||||
else
|
||||
return sched_ctrl->srs_feedback.ul_ri + 1;
|
||||
}
|
||||
|
||||
// Table 5.2.2.2.1-3 and Table 5.2.2.2.1-4 in 38.214
|
||||
@@ -292,7 +298,7 @@ NR_pdsch_dmrs_t get_dl_dmrs_params(const NR_ServingCellConfigCommon_t *scc,
|
||||
int frontloaded_symb = 1; // default value
|
||||
nr_dci_format_t dci_format = dl_bwp ? dl_bwp->dci_format : NR_DL_DCI_FORMAT_1_0;
|
||||
if (dci_format == NR_DL_DCI_FORMAT_1_0) {
|
||||
dmrs.numDmrsCdmGrpsNoData = tda_info->nrOfSymbols == 2 ? 1 : 2;
|
||||
dmrs.numDmrsCdmGrpsNoData = tda_info->nrOfSymbols <= 2 ? 1 : 2;
|
||||
dmrs.dmrs_ports_id = 0;
|
||||
}
|
||||
else {
|
||||
@@ -394,10 +400,10 @@ NR_ControlResourceSet_t *get_coreset(gNB_MAC_INST *nrmac,
|
||||
}
|
||||
}
|
||||
|
||||
NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc,
|
||||
NR_BWP_DownlinkDedicated_t *bwp_Dedicated,
|
||||
NR_SearchSpace__searchSpaceType_PR target_ss) {
|
||||
|
||||
static NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc,
|
||||
NR_BWP_DownlinkDedicated_t *bwp_Dedicated,
|
||||
NR_SearchSpace__searchSpaceType_PR target_ss)
|
||||
{
|
||||
int n = 0;
|
||||
if(bwp_Dedicated)
|
||||
n = bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count;
|
||||
@@ -696,7 +702,7 @@ NR_pusch_dmrs_t get_ul_dmrs_params(const NR_ServingCellConfigCommon_t *scc,
|
||||
dmrs.num_dmrs_cdm_grps_no_data = 2;
|
||||
} else {
|
||||
if (ul_bwp->transform_precoding && Layers < 3)
|
||||
dmrs.num_dmrs_cdm_grps_no_data = ul_bwp->dci_format == NR_UL_DCI_FORMAT_0_1 || tda_info->nrOfSymbols == 2 ? 1 : 2;
|
||||
dmrs.num_dmrs_cdm_grps_no_data = ul_bwp->dci_format == NR_UL_DCI_FORMAT_0_1 || tda_info->nrOfSymbols <= 2 ? 1 : 2;
|
||||
else
|
||||
dmrs.num_dmrs_cdm_grps_no_data = 2;
|
||||
}
|
||||
@@ -2060,8 +2066,18 @@ 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);
|
||||
return UE;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UE_iterator(UEs->list, UE) {
|
||||
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;
|
||||
@@ -2073,7 +2089,6 @@ NR_UE_info_t *find_nr_UE(NR_UEs_t *UEs, rnti_t rntiP)
|
||||
void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_allocator_t *uia)
|
||||
{
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->reconfigCellGroup);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->capability);
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
seq_arr_free(&sched_ctrl->lc_config, NULL);
|
||||
@@ -2088,6 +2103,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_and_zero(UE->ra);
|
||||
free(UE);
|
||||
}
|
||||
|
||||
@@ -2195,31 +2211,17 @@ 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 target_ss,
|
||||
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;
|
||||
@@ -2230,15 +2232,10 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
|
||||
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;
|
||||
|
||||
if(dl_bwp_switch >= 0 && ul_bwp_switch >= 0) {
|
||||
AssertFatal(dl_bwp_switch == ul_bwp_switch, "Different UL and DL BWP not supported\n");
|
||||
@@ -2298,7 +2295,6 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
|
||||
else {
|
||||
DL_BWP->bwp_id = 0;
|
||||
UL_BWP->bwp_id = 0;
|
||||
target_ss = NR_SearchSpace__searchSpaceType_PR_common;
|
||||
DL_BWP->pdsch_Config = NULL;
|
||||
UL_BWP->pusch_Config = NULL;
|
||||
UL_BWP->pucch_Config = NULL;
|
||||
@@ -2359,7 +2355,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;
|
||||
@@ -2398,23 +2397,16 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
|
||||
sc_info->nrofHARQ_ProcessesForPUSCH_r17 = pusch_servingcellconfig->ext3->nrofHARQ_ProcessesForPUSCH_r17;
|
||||
}
|
||||
}
|
||||
create_dl_harq_list(sched_ctrl, sc_info);
|
||||
create_ul_harq_list(sched_ctrl, sc_info);
|
||||
}
|
||||
|
||||
if (CellGroup && CellGroup->physicalCellGroupConfig)
|
||||
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 +2428,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 +2441,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 +2473,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 +2491,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->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 +2527,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->list[i] == NULL) {
|
||||
UE_info->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);
|
||||
dump_nr_list(UE_info->list);
|
||||
return (UE);
|
||||
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);
|
||||
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 +2712,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->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->list[i] && UE_info->list[i]->rnti != rnti)
|
||||
newUEs[newListIdx++]=UE_info->list[i];
|
||||
memcpy(UE_info->list, newUEs, sizeof(UE_info->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);
|
||||
}
|
||||
|
||||
@@ -2799,7 +2801,7 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, slot_t slot, nfapi_nr_dl_tt
|
||||
|
||||
UE_info->sched_csirs = 0;
|
||||
|
||||
UE_iterator(UE_info->list, UE) {
|
||||
UE_iterator(UE_info->connected_ue_list, UE) {
|
||||
NR_UE_DL_BWP_t *dl_bwp = &UE->current_DL_BWP;
|
||||
|
||||
// CSI-RS is common to all UEs in a given BWP
|
||||
@@ -3030,7 +3032,7 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, slot_t slot, nfapi_nr_dl_tt
|
||||
}
|
||||
}
|
||||
|
||||
static void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group)
|
||||
void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group)
|
||||
{
|
||||
DevAssert(cell_group != NULL);
|
||||
/* remove a reconfigurationWithSync, we don't need it anymore */
|
||||
@@ -3050,38 +3052,6 @@ static void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group)
|
||||
free_and_zero(cell_group->rlc_BearerToAddModList->list.array[i]->reestablishRLC);
|
||||
}
|
||||
|
||||
static void nr_mac_apply_cellgroup(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t frame, slot_t slot)
|
||||
{
|
||||
LOG_D(NR_MAC, "%4d.%2d RNTI %04x: UE inactivity timer expired\n", frame, slot, UE->rnti);
|
||||
|
||||
/* check if there is a new CellGroupConfig to be applied */
|
||||
if (UE->interrupt_action == FOLLOW_INSYNC_RECONFIG && UE->reconfigCellGroup != NULL) {
|
||||
LOG_D(NR_MAC, "%4d.%2d RNTI %04x: Apply CellGroupConfig after UE inactivity\n", frame, slot, UE->rnti);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
|
||||
UE->CellGroup = UE->reconfigCellGroup;
|
||||
UE->reconfigCellGroup = NULL;
|
||||
UE->interrupt_action = FOLLOW_INSYNC;
|
||||
|
||||
if (LOG_DEBUGFLAG(DEBUG_ASN1))
|
||||
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *)UE->CellGroup);
|
||||
|
||||
nr_mac_clean_cellgroup(UE->CellGroup);
|
||||
}
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
configure_UE_BWP(mac, scc, sched_ctrl, NULL, UE, -1, -1);
|
||||
|
||||
reset_srs_stats(UE);
|
||||
|
||||
if (IS_SA_MODE(get_softmodem_params())) {
|
||||
// add all available DL,UL HARQ processes for this UE in SA
|
||||
create_dl_harq_list(sched_ctrl, &UE->sc_info);
|
||||
create_ul_harq_list(sched_ctrl, &UE->sc_info);
|
||||
}
|
||||
}
|
||||
|
||||
int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs)
|
||||
{
|
||||
/* we previously assumed a specific "slot ahead" value for the PHY processing
|
||||
@@ -3109,7 +3079,7 @@ int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, interr
|
||||
// frames, after the inactivity of the UE.
|
||||
UE->UE_sched_ctrl.ta_frame = (mac->frame - 1 + 1024) % 1024;
|
||||
|
||||
LOG_D(NR_MAC, "UE %04x: Interrupt UE transmission (%d slots) action %d reconfigCellGroup %p\n", UE->rnti, slots, UE->interrupt_action, UE->reconfigCellGroup);
|
||||
LOG_D(NR_MAC, "UE %04x: Interrupt UE transmission (%d slots) action %d\n", UE->rnti, slots, UE->interrupt_action);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3161,7 +3131,7 @@ void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot)
|
||||
NR_SCHED_ENSURE_LOCKED(&mac->sched_lock);
|
||||
|
||||
NR_UEs_t *UE_info = &mac->UE_info;
|
||||
UE_iterator(UE_info->list, UE) {
|
||||
UE_iterator(UE_info->connected_ue_list, UE) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
|
||||
if (nr_mac_check_release(sched_ctrl, UE->rnti)) {
|
||||
@@ -3182,8 +3152,6 @@ void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot)
|
||||
nr_timer_stop(&sched_ctrl->transm_interrupt);
|
||||
if (UE->interrupt_action == FOLLOW_OUTOFSYNC)
|
||||
nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs);
|
||||
else
|
||||
nr_mac_apply_cellgroup(mac, UE, frame, slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3519,24 +3487,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
|
||||
|
||||
@@ -521,7 +521,7 @@ void nr_schedule_srs(int module_id, frame_t frame, int slot)
|
||||
|
||||
NR_UEs_t *UE_info = &nrmac->UE_info;
|
||||
|
||||
UE_iterator(UE_info->list, UE) {
|
||||
UE_iterator(UE_info->connected_ue_list, UE) {
|
||||
const int CC_id = 0;
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_UL_BWP_t *current_BWP = &UE->current_UL_BWP;
|
||||
|
||||
@@ -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.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));
|
||||
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) {
|
||||
schedule_pucch_core(nrmac, UE, frame, slot);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -217,7 +232,7 @@ void nr_csi_meas_reporting(int Mod_idP,frame_t frame, slot_t slot)
|
||||
/* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */
|
||||
NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock);
|
||||
|
||||
UE_iterator(nrmac->UE_info.list, UE ) {
|
||||
UE_iterator(nrmac->UE_info.connected_ue_list, UE) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
|
||||
const int n_slots_frame = nrmac->frame_structure.numb_slots_frame;
|
||||
@@ -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
|
||||
@@ -1219,7 +1241,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, slot_t slot)
|
||||
if (!is_ul_slot(slot, &nrmac->frame_structure))
|
||||
return;
|
||||
const int CC_id = 0;
|
||||
UE_iterator(nrmac->UE_info.list, UE) {
|
||||
UE_iterator(nrmac->UE_info.connected_ue_list, UE) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP;
|
||||
const int n_slots_frame = nrmac->frame_structure.numb_slots_frame;
|
||||
|
||||
@@ -56,7 +56,7 @@ int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot)
|
||||
}
|
||||
|
||||
// Avoid slots with the SRS
|
||||
UE_iterator(nrmac->UE_info.list, UE) {
|
||||
UE_iterator(nrmac->UE_info.connected_ue_list, UE) {
|
||||
NR_sched_srs_t sched_srs = UE->UE_sched_ctrl.sched_srs;
|
||||
if(sched_srs.srs_scheduled && sched_srs.frame == frame && sched_srs.slot == slot)
|
||||
return 1;
|
||||
@@ -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,65 +543,31 @@ 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)
|
||||
static void handle_nr_ul_harq(gNB_MAC_INST *nrmac,
|
||||
NR_UE_info_t *UE,
|
||||
frame_t frame,
|
||||
slot_t slot,
|
||||
rnti_t rnti,
|
||||
int crc_harq_id,
|
||||
bool crc_status)
|
||||
{
|
||||
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)
|
||||
{
|
||||
gNB_MAC_INST *nrmac = RC.nrmac[mod_id];
|
||||
if (nrmac->radio_config.disable_harq) {
|
||||
LOG_D(NR_MAC, "skipping UL feedback handling as HARQ is disabled\n");
|
||||
return;
|
||||
}
|
||||
|
||||
NR_SCHED_LOCK(&nrmac->sched_lock);
|
||||
for (int i = 0; i < NR_NB_RA_PROC_MAX; ++i) {
|
||||
NR_RA_t *ra = &nrmac->common_channels[CC_idP].ra[i];
|
||||
// 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) {
|
||||
LOG_D(NR_MAC, "UL for rnti %04x in RA (MSG3), no need to process HARQ\n", crc_pdu->rnti);
|
||||
NR_SCHED_UNLOCK(&nrmac->sched_lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
NR_UE_info_t *UE = find_nr_UE(&nrmac->UE_info, crc_pdu->rnti);
|
||||
if (!UE) {
|
||||
NR_SCHED_UNLOCK(&nrmac->sched_lock);
|
||||
LOG_E(NR_MAC, "Couldn't identify UE connected with current UL HARQ process\n");
|
||||
return;
|
||||
}
|
||||
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
int8_t harq_pid = sched_ctrl->feedback_ul_harq.head;
|
||||
LOG_D(NR_MAC, "Comparing crc_pdu->harq_id vs feedback harq_pid = %d %d\n",crc_pdu->harq_id, harq_pid);
|
||||
while (crc_pdu->harq_id != harq_pid || harq_pid < 0) {
|
||||
LOG_W(NR_MAC, "Unexpected ULSCH HARQ PID %d (have %d) for RNTI 0x%04x\n", crc_pdu->harq_id, harq_pid, crc_pdu->rnti);
|
||||
if (harq_pid < 0) {
|
||||
NR_SCHED_UNLOCK(&nrmac->sched_lock);
|
||||
LOG_D(NR_MAC, "Comparing crc harq_id vs feedback harq_pid = %d %d\n", crc_harq_id, harq_pid);
|
||||
while (crc_harq_id != harq_pid || harq_pid < 0) {
|
||||
LOG_W(NR_MAC, "Unexpected ULSCH HARQ PID %d (have %d) for RNTI 0x%04x\n", crc_harq_id, harq_pid, rnti);
|
||||
if (harq_pid < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
remove_front_nr_list(&sched_ctrl->feedback_ul_harq);
|
||||
sched_ctrl->ul_harq_processes[harq_pid].is_waiting = false;
|
||||
|
||||
if(sched_ctrl->ul_harq_processes[harq_pid].round >= RC.nrmac[mod_id]->ul_bler.harq_round_max - 1) {
|
||||
if(sched_ctrl->ul_harq_processes[harq_pid].round >= nrmac->ul_bler.harq_round_max - 1) {
|
||||
abort_nr_ul_harq(UE, harq_pid);
|
||||
} else {
|
||||
sched_ctrl->ul_harq_processes[harq_pid].round++;
|
||||
@@ -618,52 +580,211 @@ void handle_nr_ul_harq(const int CC_idP, module_id_t mod_id, frame_t frame, slot
|
||||
DevAssert(harq->is_waiting);
|
||||
harq->feedback_slot = -1;
|
||||
harq->is_waiting = false;
|
||||
if (!crc_pdu->tb_crc_status) {
|
||||
if (!crc_status) {
|
||||
finish_nr_ul_harq(sched_ctrl, harq_pid);
|
||||
LOG_D(NR_MAC,
|
||||
"Ulharq id %d crc passed for RNTI %04x\n",
|
||||
harq_pid,
|
||||
crc_pdu->rnti);
|
||||
} else if (harq->round >= RC.nrmac[mod_id]->ul_bler.harq_round_max - 1) {
|
||||
rnti);
|
||||
} else if (harq->round >= nrmac->ul_bler.harq_round_max - 1) {
|
||||
abort_nr_ul_harq(UE, harq_pid);
|
||||
LOG_D(NR_MAC,
|
||||
"RNTI %04x: Ulharq id %d crc failed in all rounds\n",
|
||||
crc_pdu->rnti,
|
||||
rnti,
|
||||
harq_pid);
|
||||
} else {
|
||||
harq->round++;
|
||||
LOG_D(NR_MAC,
|
||||
"Ulharq id %d crc failed for RNTI %04x\n",
|
||||
harq_pid,
|
||||
crc_pdu->rnti);
|
||||
rnti);
|
||||
add_tail_nr_list(&sched_ctrl->retrans_ul_harq, harq_pid);
|
||||
}
|
||||
NR_SCHED_UNLOCK(&nrmac->sched_lock);
|
||||
}
|
||||
|
||||
static void handle_msg3_failed_rx(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 void nr_rx_ra_sdu(const module_id_t mod_id,
|
||||
const int CC_id,
|
||||
const frame_t frame,
|
||||
const sub_frame_t slot,
|
||||
rnti_t rnti,
|
||||
uint8_t *sdu,
|
||||
const uint32_t sdu_len,
|
||||
const uint16_t timing_advance,
|
||||
const uint8_t ul_cqi,
|
||||
const uint16_t rssi)
|
||||
{
|
||||
gNB_MAC_INST *mac = RC.nrmac[mod_id];
|
||||
NR_UE_info_t *UE = find_ra_UE(&mac->UE_info, rnti);
|
||||
if (!UE) {
|
||||
LOG_E(NR_MAC, "UL SDU discarded. Couldn't finde UE with RNTI %04x \n", rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
NR_RA_t *ra = UE->ra;
|
||||
if (ra->ra_type == RA_4_STEP && ra->ra_state != nrRA_WAIT_Msg3) {
|
||||
LOG_W(NR_MAC, "UL SDU discarded for RNTI %04x RA state not waiting for PUSCH\n", UE->rnti);
|
||||
return;
|
||||
}
|
||||
|
||||
const int target_snrx10 = mac->pusch_target_snrx10;
|
||||
if (!sdu) { // NACK
|
||||
if (ra->ra_state != nrRA_WAIT_Msg3)
|
||||
return;
|
||||
|
||||
if((frame!=ra->Msg3_frame) || (slot!=ra->Msg3_slot))
|
||||
return;
|
||||
|
||||
if (ul_cqi != 0xff)
|
||||
ra->msg3_TPC = nr_get_tpc(target_snrx10, ul_cqi, 30, 0);
|
||||
|
||||
handle_msg3_failed_rx(mac, ra, rnti, mac->ul_bler.harq_round_max);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool no_sig = true;
|
||||
for (uint32_t k = 0; k < sdu_len; k++) {
|
||||
if (sdu[k] != 0) {
|
||||
no_sig = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(mod_id), T_INT(CC_id),
|
||||
T_INT(rnti), T_INT(frame), T_INT(slot), T_INT(-1) /* harq_pid */,
|
||||
T_BUFFER(sdu, sdu_len));
|
||||
|
||||
|
||||
if (no_sig) {
|
||||
LOG_W(NR_MAC, "MSG3 ULSCH with no signal\n");
|
||||
handle_msg3_failed_rx(mac, ra, rnti, mac->ul_bler.harq_round_max);
|
||||
return;
|
||||
}
|
||||
if (ra->ra_type == RA_2_STEP) {
|
||||
// random access pusch with RA-RNTI
|
||||
if (ra->RA_rnti != rnti) {
|
||||
LOG_E(NR_MAC, "expected TC_RNTI %04x to match current RNTI %04x\n", ra->RA_rnti, rnti);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// re-initialize ta update variables after RA procedure completion
|
||||
UE->UE_sched_ctrl.ta_frame = frame;
|
||||
|
||||
LOG_A(NR_MAC, "%4d.%2d PUSCH with TC_RNTI 0x%04x received correctly\n", frame, slot, rnti);
|
||||
|
||||
NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl;
|
||||
if (ul_cqi != 0xff) {
|
||||
UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10, ul_cqi, 30, UE_scheduling_control->sched_pusch.phr_txpower_calc);
|
||||
UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640 - UE_scheduling_control->sched_pusch.phr_txpower_calc * 10;
|
||||
}
|
||||
if (timing_advance != 0xffff)
|
||||
UE_scheduling_control->ta_update = timing_advance;
|
||||
UE_scheduling_control->raw_rssi = rssi;
|
||||
LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update);
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
if (ra->cfra) {
|
||||
LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", UE->rnti);
|
||||
nr_mac_reset_ul_failure(UE_scheduling_control);
|
||||
reset_dl_harq_list(UE_scheduling_control);
|
||||
reset_ul_harq_list(UE_scheduling_control);
|
||||
process_addmod_bearers_cellGroupConfig(&UE->UE_sched_ctrl, UE->CellGroup->rlc_BearerToAddModList);
|
||||
int ss_type;
|
||||
// we configure the UE using common search space with DCIX0 while waiting for a reconfiguration in SA
|
||||
// in NSA (or do-ra) there is no reconfiguration in NR
|
||||
if (IS_SA_MODE(get_softmodem_params()))
|
||||
ss_type = NR_SearchSpace__searchSpaceType_PR_common;
|
||||
else
|
||||
ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
|
||||
configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1);
|
||||
if (!transition_ra_connected_nr_ue(mac, UE)) {
|
||||
LOG_E(NR_MAC, "cannot add UE %04x: list is full\n", UE->rnti);
|
||||
delete_nr_ue_data(UE, NULL, &mac->UE_info.uid_allocator);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG_D(NR_MAC, "[RAPROC] Received %s:\n", ra->ra_type == RA_2_STEP ? "MsgA-PUSCH" : "Msg3");
|
||||
for (uint32_t k = 0; k < sdu_len; k++) {
|
||||
LOG_D(NR_MAC, "(%i): 0x%x\n", k, sdu[k]);
|
||||
}
|
||||
|
||||
// 3GPP TS 38.321 Section 5.4.3 Multiplexing and assembly
|
||||
// Logical channels shall be prioritised in accordance with the following order (highest priority listed first):
|
||||
// - MAC CE for C-RNTI, or data from UL-CCCH;
|
||||
// This way, we need to process MAC CE for C-RNTI if RA is active and it is present in the MAC PDU
|
||||
// Search for MAC CE for C-RNTI
|
||||
rnti_t crnti = lcid_crnti_lookahead(sdu, sdu_len);
|
||||
if (crnti != 0) { // 3GPP TS 38.321 Table 7.1-1: RNTI values, RNTI 0x0000: N/A
|
||||
// Replace the current UE by the UE identified by C-RNTI
|
||||
NR_UE_info_t *old_UE = find_nr_UE(&mac->UE_info, crnti);
|
||||
if (!old_UE) {
|
||||
// The UE identified by C-RNTI no longer exists at the gNB
|
||||
// Let's abort the current RA, so the UE will trigger a new RA later but using RRCSetupRequest instead. A better
|
||||
// solution may be implemented
|
||||
LOG_W(NR_MAC, "No UE found with C-RNTI %04x, ignoring Msg3 to have UE come back with new RA attempt\n", UE->rnti);
|
||||
nr_release_ra_UE(mac, rnti);
|
||||
return;
|
||||
}
|
||||
// in case UE beam has changed
|
||||
old_UE->UE_beam_index = UE->UE_beam_index;
|
||||
// Reset UL failure for old UE
|
||||
nr_mac_reset_ul_failure(&old_UE->UE_sched_ctrl);
|
||||
// Reset HARQ processes
|
||||
reset_dl_harq_list(&old_UE->UE_sched_ctrl);
|
||||
reset_ul_harq_list(&old_UE->UE_sched_ctrl);
|
||||
// Trigger RRC Reconfiguration
|
||||
LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", crnti);
|
||||
nr_mac_trigger_reconfiguration(mac, old_UE);
|
||||
nr_release_ra_UE(mac, rnti);
|
||||
LOG_A(NR_MAC, "%4d.%2d UE %04x: RA with C-RNTI complete\n", frame, slot, crnti);
|
||||
// we configure the UE using common search space with DCIX0 while waiting for a reconfiguration
|
||||
configure_UE_BWP(mac, scc, old_UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1);
|
||||
// TODO do we actually need to still process the PDU?
|
||||
nr_process_mac_pdu(mod_id, old_UE, CC_id, frame, slot, sdu, sdu_len, -1);
|
||||
return;
|
||||
} else {
|
||||
// UE Contention Resolution Identity
|
||||
// Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to fill in Msg4
|
||||
// First byte corresponds to R/LCID MAC sub-header
|
||||
memcpy(ra->cont_res_id, &sdu[1], sizeof(uint8_t) * 6);
|
||||
}
|
||||
|
||||
// Decode MAC PDU for the correct UE, after checking for MAC CE for C-RNTI
|
||||
// harq_pid set a non valid value because it is not used in this call
|
||||
// the function is only called to decode the contention resolution sub-header
|
||||
nr_process_mac_pdu(mod_id, UE, CC_id, frame, slot, sdu, sdu_len, -1);
|
||||
|
||||
LOG_I(NR_MAC,
|
||||
"Activating scheduling %s for TC_RNTI 0x%04x (state %s)\n",
|
||||
ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4",
|
||||
UE->rnti,
|
||||
nrra_text[ra->ra_state]);
|
||||
ra->ra_state = ra->ra_type == RA_2_STEP ? nrRA_MsgB : nrRA_Msg4;
|
||||
LOG_D(NR_MAC, "TC_RNTI 0x%04x next RA state %s\n", UE->rnti, nrra_text[ra->ra_state]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
const int CC_idP,
|
||||
const frame_t frameP,
|
||||
@@ -677,20 +798,14 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
const uint16_t rssi)
|
||||
{
|
||||
gNB_MAC_INST *gNB_mac = RC.nrmac[gnb_mod_idP];
|
||||
|
||||
const int current_rnti = rntiP;
|
||||
LOG_D(NR_MAC, "rx_sdu for rnti %04x\n", current_rnti);
|
||||
const int target_snrx10 = gNB_mac->pusch_target_snrx10;
|
||||
const int rssi_threshold = gNB_mac->pusch_rssi_threshold;
|
||||
const int pusch_failure_thres = gNB_mac->pusch_failure_thres;
|
||||
|
||||
NR_UE_info_t *UE = find_nr_UE(&gNB_mac->UE_info, current_rnti);
|
||||
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;
|
||||
|
||||
if (sduP)
|
||||
T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP),
|
||||
T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(harq_pid),
|
||||
@@ -729,7 +844,6 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
UE_scheduling_control->ta_update = timing_advance;
|
||||
UE_scheduling_control->raw_rssi = rssi;
|
||||
UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640 - (txpower_calc * 10);
|
||||
|
||||
if (UE_scheduling_control->tpc0 > 1)
|
||||
LOG_D(NR_MAC,
|
||||
"[UE %04x] %d.%d. PUSCH TPC %d and TA %d pusch_snrx10 %d rssi %d phrx_tx_power %d PHR (1PRB) %d mcs %d, nb_rb %d\n",
|
||||
@@ -747,7 +861,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
|
||||
NR_UE_ul_harq_t *cur_harq = &UE_scheduling_control->ul_harq_processes[harq_pid];
|
||||
if (cur_harq->round == 0)
|
||||
UE->mac_stats.pusch_snrx10 = UE_scheduling_control->pusch_snrx10;
|
||||
UE->mac_stats.pusch_snrx10 = UE_scheduling_control->pusch_snrx10;
|
||||
LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n",UE->rnti,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update);
|
||||
}
|
||||
else{
|
||||
@@ -769,15 +883,13 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
|
||||
|
||||
if (sduP != NULL) {
|
||||
LOG_D(NR_MAC, "Received PDU at MAC gNB \n");
|
||||
|
||||
UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt = 0;
|
||||
UE_scheduling_control->sched_ul_bytes -= sdu_lenP;
|
||||
if (UE_scheduling_control->sched_ul_bytes < 0)
|
||||
UE_scheduling_control->sched_ul_bytes = 0;
|
||||
|
||||
nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP, harq_pid);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (ul_cqi == 0xff || ul_cqi <= 128) {
|
||||
UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt++;
|
||||
UE->mac_stats.ulsch_DTX++;
|
||||
@@ -791,186 +903,9 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
UE->UE_sched_ctrl.ta_frame = frameP;
|
||||
|
||||
LOG_A(NR_MAC, "%4d.%2d PUSCH with TC_RNTI 0x%04x received correctly\n", frameP, slotP, current_rnti);
|
||||
|
||||
NR_UE_sched_ctrl_t *UE_scheduling_control = &UE->UE_sched_ctrl;
|
||||
if (ul_cqi != 0xff) {
|
||||
UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10, ul_cqi, 30, UE_scheduling_control->sched_pusch.phr_txpower_calc);
|
||||
UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640 - UE_scheduling_control->sched_pusch.phr_txpower_calc * 10;
|
||||
}
|
||||
if (timing_advance != 0xffff)
|
||||
UE_scheduling_control->ta_update = timing_advance;
|
||||
UE_scheduling_control->raw_rssi = rssi;
|
||||
LOG_D(NR_MAC, "[UE %04x] PUSCH TPC %d and TA %d\n", UE->rnti, UE_scheduling_control->tpc0, UE_scheduling_control->ta_update);
|
||||
if (ra->cfra) {
|
||||
LOG_A(NR_MAC, "(rnti 0x%04x) CFRA procedure succeeded!\n", ra->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);
|
||||
} else {
|
||||
LOG_D(NR_MAC, "[RAPROC] Received %s:\n", ra->ra_type == RA_2_STEP ? "MsgA-PUSCH" : "Msg3");
|
||||
for (uint32_t k = 0; k < sdu_lenP; k++) {
|
||||
LOG_D(NR_MAC, "(%i): 0x%x\n", k, sduP[k]);
|
||||
}
|
||||
|
||||
// 3GPP TS 38.321 Section 5.4.3 Multiplexing and assembly
|
||||
// Logical channels shall be prioritised in accordance with the following order (highest priority listed first):
|
||||
// - MAC CE for C-RNTI, or data from UL-CCCH;
|
||||
// This way, we need to process MAC CE for C-RNTI if RA is active and it is present in the MAC PDU
|
||||
// Search for MAC CE for C-RNTI
|
||||
rnti_t crnti = lcid_crnti_lookahead(sduP, sdu_lenP);
|
||||
if (crnti != 0) { // 3GPP TS 38.321 Table 7.1-1: RNTI values, RNTI 0x0000: N/A
|
||||
// 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) {
|
||||
// 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);
|
||||
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);
|
||||
}
|
||||
|
||||
if (UE->reconfigCellGroup) {
|
||||
// Nothing to do
|
||||
// A RRCReconfiguration message should be already pending (for example, an ongoing RRCReestablishment), and it will be
|
||||
// transmitted in Msg4
|
||||
} else {
|
||||
// Trigger RRC Reconfiguration
|
||||
LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", UE->rnti);
|
||||
nr_mac_trigger_reconfiguration(gNB_mac, UE);
|
||||
}
|
||||
} else {
|
||||
// UE Contention Resolution Identity
|
||||
// Store the first 48 bits belonging to the uplink CCCH SDU within Msg3 to fill in Msg4
|
||||
// First byte corresponds to R/LCID MAC sub-header
|
||||
memcpy(ra->cont_res_id, &sduP[1], sizeof(uint8_t) * 6);
|
||||
}
|
||||
|
||||
// Decode MAC PDU for the correct UE, after checking for MAC CE for C-RNTI
|
||||
// harq_pid set a non valid value because it is not used in this call
|
||||
// the function is only called to decode the contention resolution sub-header
|
||||
nr_process_mac_pdu(gnb_mod_idP, UE, CC_idP, frameP, slotP, sduP, sdu_lenP, -1);
|
||||
|
||||
LOG_I(NR_MAC,
|
||||
"Activating scheduling %s for TC_RNTI 0x%04x (state %s)\n",
|
||||
ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4",
|
||||
ra->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]);
|
||||
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];
|
||||
if (ra->ra_state != nrRA_WAIT_Msg3)
|
||||
continue;
|
||||
|
||||
if((frameP!=ra->Msg3_frame) || (slotP!=ra->Msg3_slot))
|
||||
continue;
|
||||
|
||||
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_nr_ul_harq(gNB_mac, UE, frameP, slotP, current_rnti, harq_pid, sduP == NULL);
|
||||
} else {
|
||||
nr_rx_ra_sdu(gnb_mod_idP, CC_idP, frameP, slotP, current_rnti, sduP, sdu_lenP, timing_advance, ul_cqi, rssi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1891,7 +1826,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);
|
||||
@@ -2012,7 +1947,7 @@ static void pf_ul(module_id_t module_id,
|
||||
continue;
|
||||
}
|
||||
|
||||
sched_pusch->nrOfLayers = sched_ctrl->srs_feedback.ul_ri + 1;
|
||||
sched_pusch->nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format);
|
||||
sched_pusch->time_domain_allocation = get_ul_tda(nrmac, sched_frame, sched_slot);
|
||||
sched_pusch->tda_info = get_ul_tda_info(current_BWP,
|
||||
sched_ctrl->coreset->controlResourceSetId,
|
||||
@@ -2162,7 +2097,7 @@ static void pf_ul(module_id_t module_id,
|
||||
|
||||
|
||||
|
||||
sched_pusch->nrOfLayers = sched_ctrl->srs_feedback.ul_ri + 1;
|
||||
sched_pusch->nrOfLayers = get_ul_nrOfLayers(sched_ctrl, current_BWP->dci_format);
|
||||
sched_pusch->time_domain_allocation = get_ul_tda(nrmac, sched_frame, sched_slot);
|
||||
sched_pusch->tda_info = get_ul_tda_info(current_BWP,
|
||||
sched_ctrl->coreset->controlResourceSetId,
|
||||
@@ -2279,7 +2214,7 @@ static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s
|
||||
{
|
||||
gNB_MAC_INST *nr_mac = RC.nrmac[module_id];
|
||||
// no UEs
|
||||
if (nr_mac->UE_info.list[0] == NULL)
|
||||
if (nr_mac->UE_info.connected_ue_list[0] == NULL)
|
||||
return false;
|
||||
|
||||
NR_COMMON_channels_t *cc = nr_mac->common_channels;
|
||||
@@ -2308,7 +2243,7 @@ static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, slot_t s
|
||||
max_sched_ues = min(max_sched_ues, MAX_DCI_CORESET);
|
||||
|
||||
/* proportional fair scheduling algorithm */
|
||||
pf_ul(module_id, frame, slot, sched_frame, sched_slot, nr_mac->UE_info.list, max_sched_ues, num_beams, len);
|
||||
pf_ul(module_id, frame, slot, sched_frame, sched_slot, nr_mac->UE_info.connected_ue_list, max_sched_ues, num_beams, len);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2369,7 +2304,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, slot_t slot, nfapi_
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon;
|
||||
NR_UEs_t *UE_info = &nr_mac->UE_info;
|
||||
UE_iterator( UE_info->list, UE) {
|
||||
UE_iterator(UE_info->connected_ue_list, UE) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
if (sched_ctrl->ul_failure && !get_softmodem_params()->phy_test)
|
||||
continue;
|
||||
|
||||
@@ -60,11 +60,10 @@ 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);
|
||||
int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, interrupt_followup_action_t action, int slots);
|
||||
int nr_transmission_action_indicator_stop(gNB_MAC_INST *mac, NR_UE_info_t *UE_info);
|
||||
|
||||
@@ -135,8 +134,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);
|
||||
@@ -273,11 +270,6 @@ NR_ControlResourceSet_t *get_coreset(gNB_MAC_INST *nrmac,
|
||||
NR_SearchSpace_t *ss,
|
||||
NR_SearchSpace__searchSpaceType_PR ss_type);
|
||||
|
||||
/* find a search space within a BWP */
|
||||
NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc,
|
||||
NR_BWP_DownlinkDedicated_t *bwp_Dedicated,
|
||||
NR_SearchSpace__searchSpaceType_PR target_ss);
|
||||
|
||||
long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList,
|
||||
int time_domain_assignment,
|
||||
int mu,
|
||||
@@ -310,21 +302,23 @@ 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 target_ss,
|
||||
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,12 +356,6 @@ void reset_dl_harq_list(NR_UE_sched_ctrl_t *sched_ctrl);
|
||||
|
||||
void reset_ul_harq_list(NR_UE_sched_ctrl_t *sched_ctrl);
|
||||
|
||||
void handle_nr_ul_harq(const int CC_idP,
|
||||
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);
|
||||
|
||||
@@ -392,9 +380,11 @@ uint16_t get_pm_index(const gNB_MAC_INST *nrmac,
|
||||
uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx);
|
||||
|
||||
uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format);
|
||||
int get_ul_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format);
|
||||
|
||||
void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl);
|
||||
|
||||
bool add_UE_to_list(int list_size, NR_UE_info_t *list[list_size], NR_UE_info_t *UE);
|
||||
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 +420,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,11 +456,13 @@ 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,
|
||||
f1ap_served_cell_info_t *info,
|
||||
NR_BCCH_BCH_Message_t *mib,
|
||||
const NR_BCCH_DL_SCH_Message_t *sib1);
|
||||
|
||||
void nr_mac_clean_cellgroup(NR_CellGroupConfig_t *cell_group);
|
||||
#endif /*__LAYER2_NR_MAC_PROTO_H__*/
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
|
||||
#include "F1AP_CauseRadioNetwork.h"
|
||||
#include "NR_HandoverPreparationInformation.h"
|
||||
#include "NR_CG-ConfigInfo.h"
|
||||
#include "openair3/ocp-gtpu/gtp_itf.h"
|
||||
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
||||
#include "lib/f1ap_interface_management.h"
|
||||
@@ -105,7 +106,7 @@ void du_clear_all_ue_states()
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
NR_SCHED_LOCK(&mac->sched_lock);
|
||||
|
||||
NR_UE_info_t *UE = *mac->UE_info.list;
|
||||
NR_UE_info_t *UE = *mac->UE_info.connected_ue_list;
|
||||
|
||||
instance_t f1inst = get_f1_gtp_instance();
|
||||
|
||||
@@ -116,7 +117,7 @@ void du_clear_all_ue_states()
|
||||
if (du_exists_f1_ue_data(rnti))
|
||||
du_remove_f1_ue_data(rnti);
|
||||
newGtpuDeleteAllTunnels(f1inst, rnti);
|
||||
UE = *mac->UE_info.list;
|
||||
UE = *mac->UE_info.connected_ue_list;
|
||||
}
|
||||
NR_SCHED_UNLOCK(&mac->sched_lock);
|
||||
}
|
||||
@@ -342,6 +343,8 @@ static int handle_ue_context_drbs_setup(NR_UE_info_t *UE,
|
||||
resp_drb->up_dl_tnl[0].teid = resp_f1.gnb_NGu_teid[0];
|
||||
}
|
||||
|
||||
if (!cellGroupConfig->rlc_BearerToAddModList)
|
||||
cellGroupConfig->rlc_BearerToAddModList = calloc_or_fail(1, sizeof(*cellGroupConfig->rlc_BearerToAddModList));
|
||||
int ret = ASN_SEQUENCE_ADD(&cellGroupConfig->rlc_BearerToAddModList->list, rlc_BearerConfig);
|
||||
DevAssert(ret == 0);
|
||||
}
|
||||
@@ -461,6 +464,52 @@ static NR_UE_NR_Capability_t *get_ue_nr_cap_from_ho_prep_info(uint8_t *buf, uint
|
||||
return cap;
|
||||
}
|
||||
|
||||
static NR_CG_ConfigInfo_t *get_cg_config_info(uint8_t *buf, uint32_t len)
|
||||
{
|
||||
struct NR_CG_ConfigInfo *cg_configinfo = NULL;
|
||||
asn_dec_rval_t dec_rval = uper_decode_complete(NULL, &asn_DEF_NR_CG_ConfigInfo, (void **)&cg_configinfo, buf, len);
|
||||
if (dec_rval.code != RC_OK) {
|
||||
LOG_W(NR_MAC, "cannot decode CG-ConfigInfo, ignoring it\n");
|
||||
return NULL;
|
||||
}
|
||||
//xer_fprint(stdout, &asn_DEF_NR_CG_ConfigInfo, cg_configinfo);
|
||||
return cg_configinfo;
|
||||
}
|
||||
|
||||
static NR_UE_NR_Capability_t *get_ue_nr_cap_from_cg_config_info(const NR_CG_ConfigInfo_t *cgci)
|
||||
{
|
||||
/* INTO DU handler */
|
||||
if (cgci->criticalExtensions.present != NR_CG_ConfigInfo__criticalExtensions_PR_c1)
|
||||
return NULL;
|
||||
if (!cgci->criticalExtensions.choice.c1
|
||||
|| cgci->criticalExtensions.choice.c1->present != NR_CG_ConfigInfo__criticalExtensions__c1_PR_cg_ConfigInfo)
|
||||
return NULL;
|
||||
|
||||
const NR_CG_ConfigInfo_IEs_t *cgci_ie = cgci->criticalExtensions.choice.c1->choice.cg_ConfigInfo;
|
||||
if (!cgci_ie->ue_CapabilityInfo)
|
||||
return NULL;
|
||||
|
||||
// Decode UE-CapabilityRAT-ContainerList
|
||||
const OCTET_STRING_t *cap_buf = cgci_ie->ue_CapabilityInfo;
|
||||
NR_UE_CapabilityRAT_ContainerList_t *clist = NULL;
|
||||
asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
|
||||
&asn_DEF_NR_UE_CapabilityRAT_ContainerList,
|
||||
(void **)&clist,
|
||||
cap_buf->buf,
|
||||
cap_buf->size);
|
||||
|
||||
if (dec_rval.code != RC_OK) {
|
||||
LOG_W(NR_MAC,
|
||||
"Failed to decode NR_UE_CapabilityRAT_ContainerList (%zu bits), size of OCTET_STRING %lu\n",
|
||||
dec_rval.consumed,
|
||||
cap_buf->size);
|
||||
return NULL;
|
||||
}
|
||||
NR_UE_NR_Capability_t *cap = get_nr_cap(clist);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_UE_CapabilityRAT_ContainerList, clist);
|
||||
return cap;
|
||||
}
|
||||
|
||||
NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig)
|
||||
{
|
||||
uint8_t buf[16636];
|
||||
@@ -473,43 +522,74 @@ NR_CellGroupConfig_t *clone_CellGroupConfig(const NR_CellGroupConfig_t *orig)
|
||||
return cloned;
|
||||
}
|
||||
|
||||
static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id)
|
||||
static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_CG_ConfigInfo_t *cgci)
|
||||
{
|
||||
const bool is_SA = IS_SA_MODE(get_softmodem_params());
|
||||
int CC_id = 0;
|
||||
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);
|
||||
if (!found)
|
||||
return NULL;
|
||||
|
||||
NR_UE_info_t* UE = add_new_nr_ue(mac, rnti, NULL);
|
||||
if (!UE)
|
||||
return NULL;
|
||||
if (get_softmodem_params()->phy_test) {
|
||||
AssertFatal(mac->UE_info.connected_ue_list[0] == NULL, "phytest: UE already present\n");
|
||||
rnti = 0x1234;
|
||||
} else {
|
||||
bool found = nr_mac_get_new_rnti(&mac->UE_info, &rnti);
|
||||
if (!found)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f1_ue_data_t new_ue_data = {.secondary_ue = cu_id};
|
||||
bool success = du_add_f1_ue_data(rnti, &new_ue_data);
|
||||
DevAssert(success);
|
||||
|
||||
const NR_ServingCellConfigCommon_t *scc = mac->common_channels[CC_id].ServingCellConfigCommon;
|
||||
const NR_ServingCellConfig_t *sccd = mac->common_channels[CC_id].pre_ServingCellConfig;
|
||||
NR_CellGroupConfig_t *cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config);
|
||||
cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc);
|
||||
NR_UE_info_t *UE = get_new_nr_ue_inst(&mac->UE_info.uid_allocator, rnti, NULL);
|
||||
AssertFatal(UE != NULL, "cannot create UE context, UE context setup failure not implemented\n");
|
||||
|
||||
NR_CellGroupConfig_t *cellGroupConfig = NULL;
|
||||
NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
|
||||
const NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
|
||||
const NR_ServingCellConfig_t *sccd = cc->pre_ServingCellConfig;
|
||||
const nr_mac_config_t *configuration = &mac->radio_config;
|
||||
if (is_SA) {
|
||||
cellGroupConfig = get_initial_cellGroupConfig(UE->uid, scc, sccd, &mac->radio_config);
|
||||
cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc);
|
||||
} else {
|
||||
NR_UE_NR_Capability_t *cap = get_ue_nr_cap_from_cg_config_info(cgci);
|
||||
cellGroupConfig = get_default_secondaryCellGroup(scc, sccd, cap, 1, 1, configuration, UE->uid);
|
||||
cellGroupConfig->spCellConfig->reconfigurationWithSync = get_reconfiguration_with_sync(UE->rnti, UE->uid, scc);
|
||||
// TODO: in NSA we assign capabilities here, otherwise outside => not logic
|
||||
UE->capability = cap;
|
||||
}
|
||||
// note: we don't pass the cellGroupConfig to add_new_nr_ue() because we need
|
||||
// the uid to create the CellGroupConfig (which is in the UE context created
|
||||
// by add_new_nr_ue(); it's a kind of chicken-and-egg problem), so below we
|
||||
// complete the UE context with the information that add_new_nr_ue() would
|
||||
// have added
|
||||
UE->Msg4_MsgB_ACKed = true;
|
||||
AssertFatal(cellGroupConfig != NULL, "out of memory\n");
|
||||
UE->CellGroup = cellGroupConfig;
|
||||
|
||||
nr_rlc_activate_srb0(UE->rnti, UE, NULL);
|
||||
nr_mac_prepare_ra_ue(mac, rnti, UE->CellGroup);
|
||||
/* SRB1 is added to RLC and MAC in the handler later */
|
||||
if (get_softmodem_params()->phy_test) {
|
||||
// phytest mode: we don't set up RA, etc
|
||||
free_and_zero(UE->ra); // test-mode: UE will not do RA
|
||||
bool res = add_connected_nr_ue(mac, UE);
|
||||
DevAssert(res);
|
||||
} else {
|
||||
if (!add_new_UE_RA(mac, UE)) {
|
||||
delete_nr_ue_data(UE, /*not used*/ NULL, &mac->UE_info.uid_allocator);
|
||||
LOG_E(NR_MAC, "UE list full while creating new UE\n");
|
||||
return NULL;
|
||||
}
|
||||
nr_mac_prepare_ra_ue(mac, UE);
|
||||
|
||||
if (is_SA) {
|
||||
/* SRB1 is added to RLC and MAC in the handler later */
|
||||
nr_rlc_activate_srb0(UE->rnti, UE, NULL);
|
||||
}
|
||||
}
|
||||
return UE;
|
||||
}
|
||||
|
||||
void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
{
|
||||
const bool is_SA = IS_SA_MODE(get_softmodem_params());
|
||||
gNB_MAC_INST *mac = RC.nrmac[0];
|
||||
/* response has same type as request... */
|
||||
f1ap_ue_context_setup_t resp = {
|
||||
@@ -523,9 +603,11 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
bool ue_id_provided = resp.gNB_DU_ue_id > 0 && resp.gNB_DU_ue_id < 0xffff;
|
||||
|
||||
NR_UE_NR_Capability_t *ue_cap = NULL;
|
||||
NR_CG_ConfigInfo_t *cg_configinfo = NULL;
|
||||
if (req->cu_to_du_rrc_information != NULL) {
|
||||
const cu_to_du_rrc_information_t *cu2du = req->cu_to_du_rrc_information;
|
||||
AssertFatal(cu2du->cG_ConfigInfo == NULL, "CG-ConfigInfo not handled\n");
|
||||
if (cu2du->cG_ConfigInfo != NULL)
|
||||
cg_configinfo = get_cg_config_info(cu2du->cG_ConfigInfo, cu2du->cG_ConfigInfo_length);
|
||||
if (cu2du->handoverPreparationInfo != NULL) {
|
||||
ue_cap = get_ue_nr_cap_from_ho_prep_info(cu2du->handoverPreparationInfo, cu2du->handoverPreparationInfo_length);
|
||||
} else if (cu2du->uE_CapabilityRAT_ContainerList != NULL) {
|
||||
@@ -533,15 +615,21 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
}
|
||||
AssertFatal(cu2du->measConfig == NULL, "MeasConfig not handled\n");
|
||||
}
|
||||
/* 38.473: "For DC operation, the CG-ConfigInfo IE shall be included in the CU
|
||||
* to DU RRC Information IE at the gNB acting as secondary node" As of now,
|
||||
* we only handle NSA => we check we have CG-ConfigInfo if not SA or have SA
|
||||
* and no CG-ConfigInfo */
|
||||
AssertFatal(is_SA ^ (cg_configinfo != NULL), "cannot have SA and CG-ConfigInfo: NR-DC not supported xor need CG-ConfigInfo for NSA/phy-test/do-ra\n");
|
||||
|
||||
NR_SCHED_LOCK(&mac->sched_lock);
|
||||
|
||||
NR_UE_info_t *UE = NULL;
|
||||
if (!ue_id_provided) {
|
||||
UE = create_new_UE(mac, req->gNB_CU_ue_id);
|
||||
UE = create_new_UE(mac, req->gNB_CU_ue_id, cg_configinfo);
|
||||
resp.gNB_DU_ue_id = UE->rnti;
|
||||
resp.crnti = &UE->rnti;
|
||||
} else {
|
||||
DevAssert(is_SA);
|
||||
UE = find_nr_UE(&mac->UE_info, req->gNB_DU_ue_id);
|
||||
}
|
||||
AssertFatal(UE, "no UE found or could not be created, but UE Context Setup Failed not implemented\n");
|
||||
@@ -569,18 +657,23 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container, req->rrc_container_length);
|
||||
}
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
UE->capability = ue_cap;
|
||||
if (ue_cap != NULL) {
|
||||
if (ue_cap != NULL && cg_configinfo == NULL) {
|
||||
// store the new UE capabilities, and update the cellGroupConfig
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
// only to be done if we did not already update through the cg_configinfo
|
||||
update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc);
|
||||
}
|
||||
|
||||
if (!ue_id_provided) {
|
||||
if (!ue_id_provided && cg_configinfo == NULL) {
|
||||
/* new UE: tell the UE to reestablish RLC */
|
||||
struct NR_CellGroupConfig__rlc_BearerToAddModList *addmod = new_CellGroup->rlc_BearerToAddModList;
|
||||
for (int i = 0; i < addmod->list.count; ++i) {
|
||||
asn1cCallocOne(addmod->list.array[i]->reestablishRLC, NR_RLC_BearerConfig__reestablishRLC_true);
|
||||
for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) {
|
||||
nr_lc_config_t *lc_config = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i);
|
||||
nr_rlc_reestablish_entity(UE->rnti, lc_config->lcid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -593,7 +686,10 @@ void ue_context_setup_request(const f1ap_ue_context_setup_t *req)
|
||||
AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name);
|
||||
resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3;
|
||||
|
||||
nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
|
||||
UE->CellGroup = new_CellGroup;
|
||||
int ss_type = cg_configinfo ? NR_SearchSpace__searchSpaceType_PR_ue_Specific: NR_SearchSpace__searchSpaceType_PR_common;
|
||||
configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1);
|
||||
|
||||
NR_SCHED_UNLOCK(&mac->sched_lock);
|
||||
|
||||
@@ -664,9 +760,15 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
nr_rlc_srb_recv_sdu(req->gNB_DU_ue_id, id, req->rrc_container, req->rrc_container_length);
|
||||
}
|
||||
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
if (req->ReconfigComplOutcome != RRCreconf_info_not_present && req->ReconfigComplOutcome != RRCreconf_success) {
|
||||
LOG_E(NR_MAC,
|
||||
"RRC reconfiguration outcome unsuccessful, but no rollback mechanism implemented to come back to old configuration\n");
|
||||
} else if (req->ReconfigComplOutcome == RRCreconf_success) {
|
||||
LOG_I(NR_MAC, "DU received confirmation of successful RRC Reconfiguration\n");
|
||||
// we re-configure the BWP to apply the CellGroup and to use UE specific Search Space with DCIX1
|
||||
nr_mac_clean_cellgroup(UE->CellGroup);
|
||||
configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_ue_Specific, -1, -1);
|
||||
}
|
||||
|
||||
if (ue_cap != NULL) {
|
||||
@@ -674,7 +776,6 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->capability);
|
||||
UE->capability = ue_cap;
|
||||
LOG_I(NR_MAC, "UE %04x: received capabilities, updating CellGroupConfig\n", UE->rnti);
|
||||
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
|
||||
update_cellGroupConfig(new_CellGroup, UE->uid, UE->capability, &mac->radio_config, scc);
|
||||
}
|
||||
|
||||
@@ -692,7 +793,9 @@ void ue_context_modification_request(const f1ap_ue_context_modif_req_t *req)
|
||||
AssertFatal(enc_rval.encoded > 0, "Could not encode CellGroup, failed element %s\n", enc_rval.failed_type->name);
|
||||
resp.du_to_cu_rrc_information->cellGroupConfig_length = (enc_rval.encoded + 7) >> 3;
|
||||
|
||||
nr_mac_prepare_cellgroup_update(mac, UE, new_CellGroup);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
|
||||
UE->CellGroup = new_CellGroup;
|
||||
configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1);
|
||||
} else {
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, new_CellGroup); // we actually don't need it
|
||||
}
|
||||
@@ -759,13 +862,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 +918,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);
|
||||
@@ -836,24 +933,13 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
|
||||
DevAssert(success);
|
||||
}
|
||||
|
||||
if (UE->expect_reconfiguration && dl_rrc->srb_id == 1) {
|
||||
/* we expected a reconfiguration, and this is on DCCH. We assume this is
|
||||
* the reconfiguration: nr_mac_prepare_cellgroup_update() already stored
|
||||
* the CellGroupConfig. Below, we trigger a timer, and the CellGroupConfig
|
||||
* will be applied after its expiry in nr_mac_apply_cellgroup().*/
|
||||
NR_SCHED_LOCK(&mac->sched_lock);
|
||||
int delay = nr_mac_get_reconfig_delay_slots(UE->current_UL_BWP.scs);
|
||||
nr_mac_interrupt_ue_transmission(mac, UE, FOLLOW_INSYNC_RECONFIG, delay);
|
||||
NR_SCHED_UNLOCK(&mac->sched_lock);
|
||||
UE->expect_reconfiguration = false;
|
||||
/* Re-establish RLC for all remaining bearers */
|
||||
if (UE->reestablish_rlc) {
|
||||
for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) {
|
||||
nr_lc_config_t *lc_config = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i);
|
||||
nr_rlc_reestablish_entity(dl_rrc->gNB_DU_ue_id, lc_config->lcid);
|
||||
}
|
||||
UE->reestablish_rlc = false;
|
||||
if (UE->reestablish_rlc && dl_rrc->srb_id == 1) {
|
||||
// we expected a reconfiguration to re-establish RLC, and this is on DCCH. We assume this is the reconfiguration.
|
||||
for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) {
|
||||
nr_lc_config_t *lc_config = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i);
|
||||
nr_rlc_reestablish_entity(dl_rrc->gNB_DU_ue_id, lc_config->lcid);
|
||||
}
|
||||
UE->reestablish_rlc = false;
|
||||
}
|
||||
|
||||
if (dl_rrc->old_gNB_DU_ue_id != NULL) {
|
||||
@@ -870,28 +956,25 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
|
||||
* from the current configuration. Also, expect the reconfiguration from
|
||||
* the CU, so save the old UE's CellGroup for the new UE */
|
||||
UE->CellGroup->spCellConfig = NULL;
|
||||
NR_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);
|
||||
for (int i = 1; i < seq_arr_size(&oldUE->UE_sched_ctrl.lc_config); ++i) {
|
||||
const nr_lc_config_t *c = seq_arr_at(&oldUE->UE_sched_ctrl.lc_config, i);
|
||||
nr_mac_add_lcid(&UE->UE_sched_ctrl, c);
|
||||
}
|
||||
|
||||
nr_mac_prepare_cellgroup_update(mac, UE, oldUE->CellGroup);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
|
||||
UE->CellGroup = oldUE->CellGroup;
|
||||
oldUE->CellGroup = NULL;
|
||||
mac_remove_nr_ue(mac, *dl_rrc->old_gNB_DU_ue_id);
|
||||
pthread_mutex_unlock(&mac->sched_lock);
|
||||
nr_rlc_remove_ue(dl_rrc->gNB_DU_ue_id);
|
||||
nr_rlc_update_id(*dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id);
|
||||
/* 38.331 clause 5.3.7.4: apply the specified configuration defined in 9.2.1 for SRB1 */
|
||||
nr_rlc_reconfigure_entity(dl_rrc->gNB_DU_ue_id, 1, NULL);
|
||||
/* Set flag to trigger RLC re-establishment
|
||||
* for remaining RBs in next RRCReconfiguration */
|
||||
UE->reestablish_rlc = true;
|
||||
/* 38.331 clause 5.3.7.4: apply the specified configuration defined in 9.2.1 for SRB1 */
|
||||
nr_rlc_reconfigure_entity(dl_rrc->gNB_DU_ue_id, 1, NULL);
|
||||
instance_t f1inst = get_f1_gtp_instance();
|
||||
if (f1inst >= 0) // we actually use F1-U
|
||||
gtpv1u_update_ue_id(f1inst, *dl_rrc->old_gNB_DU_ue_id, dl_rrc->gNB_DU_ue_id);
|
||||
|
||||
@@ -106,7 +106,7 @@ void *nrmac_stats_thread(void *arg) {
|
||||
}
|
||||
|
||||
void clear_mac_stats(gNB_MAC_INST *gNB) {
|
||||
UE_iterator(gNB->UE_info.list, UE) {
|
||||
UE_iterator(gNB->UE_info.connected_ue_list, UE) {
|
||||
memset(&UE->mac_stats,0,sizeof(UE->mac_stats));
|
||||
}
|
||||
}
|
||||
@@ -121,7 +121,7 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
|
||||
NR_SCHED_ENSURE_LOCKED(&gNB->sched_lock);
|
||||
|
||||
NR_SCHED_LOCK(&gNB->UE_info.mutex);
|
||||
UE_iterator(gNB->UE_info.list, UE) {
|
||||
UE_iterator(gNB->UE_info.connected_ue_list, UE) {
|
||||
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
|
||||
NR_mac_stats_t *stats = &UE->mac_stats;
|
||||
const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0;
|
||||
@@ -312,29 +312,6 @@ void mac_top_init_gNB(ngran_node_t node_type,
|
||||
|
||||
// These should be out of here later
|
||||
if (get_softmodem_params()->usim_test == 0 ) nr_pdcp_layer_init();
|
||||
|
||||
if(IS_SOFTMODEM_NOS1 && get_softmodem_params()->phy_test) {
|
||||
// get default noS1 configuration
|
||||
NR_RadioBearerConfig_t *rbconfig = NULL;
|
||||
NR_RLC_BearerConfig_t *rlc_rbconfig = NULL;
|
||||
fill_nr_noS1_bearer_config(&rbconfig, &rlc_rbconfig);
|
||||
|
||||
/* Note! previously, in nr_DRB_preconfiguration(), we passed ENB_FLAG_NO
|
||||
* if ENB_NAS_USE_TUN was *not* set. It seems to me that we could not set
|
||||
* this flag anywhere in the code, hence we would always configure PDCP
|
||||
* with ENB_FLAG_NO in nr_DRB_preconfiguration(). This makes sense for
|
||||
* noS1, because the result of passing ENB_FLAG_NO to PDCP is that PDCP
|
||||
* will output the packets at a local interface, which is in line with
|
||||
* the noS1 mode. Hence, below, we simply hardcode ENB_FLAG_NO */
|
||||
// setup PDCP, RLC
|
||||
nr_pdcp_entity_security_keys_and_algos_t null_security_parameters = {0};
|
||||
nr_pdcp_add_drbs(ENB_FLAG_NO, 0x1234, rbconfig->drb_ToAddModList, &null_security_parameters);
|
||||
nr_rlc_add_drb(0x1234, rbconfig->drb_ToAddModList->list.array[0]->drb_Identity, rlc_rbconfig);
|
||||
|
||||
// free memory
|
||||
free_nr_noS1_bearer_config(&rbconfig, &rlc_rbconfig);
|
||||
}
|
||||
|
||||
} else {
|
||||
RC.nrmac = NULL;
|
||||
}
|
||||
@@ -359,9 +336,12 @@ void mac_top_destroy_gNB(gNB_MAC_INST *mac)
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_ServingCellConfig, cc->pre_ServingCellConfig);
|
||||
ASN_STRUCT_FREE(asn_DEF_NR_ServingCellConfigCommon, cc->ServingCellConfigCommon);
|
||||
NR_UEs_t *UE_info = &mac->UE_info;
|
||||
for (int i = 0; i < sizeofArray(UE_info->list); ++i)
|
||||
if (UE_info->list[i])
|
||||
delete_nr_ue_data(UE_info->list[i], cc, &UE_info->uid_allocator);
|
||||
for (int i = 0; i < sizeofArray(UE_info->connected_ue_list); ++i)
|
||||
if (UE_info->connected_ue_list[i])
|
||||
delete_nr_ue_data(UE_info->connected_ue_list[i], cc, &UE_info->uid_allocator);
|
||||
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)
|
||||
|
||||
@@ -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;
|
||||
@@ -761,27 +743,25 @@ typedef struct {
|
||||
NR_mac_stats_t mac_stats;
|
||||
/// currently active CellGroupConfig
|
||||
NR_CellGroupConfig_t *CellGroup;
|
||||
/// CellGroupConfig that is to be activated after the next reconfiguration
|
||||
bool expect_reconfiguration;
|
||||
/// reestablishRLC has to be signaled in RRCreconfiguration
|
||||
bool reestablish_rlc;
|
||||
NR_CellGroupConfig_t *reconfigCellGroup;
|
||||
interrupt_followup_action_t interrupt_action;
|
||||
NR_UE_NR_Capability_t *capability;
|
||||
// UE selected beam index
|
||||
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 {
|
||||
/// scheduling control info
|
||||
// last element always NULL
|
||||
pthread_mutex_t mutex;
|
||||
NR_UE_info_t *list[MAX_MOBILES_PER_GNB+1];
|
||||
NR_UE_info_t *connected_ue_list[MAX_MOBILES_PER_GNB + 1];
|
||||
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;
|
||||
|
||||
@@ -899,12 +899,6 @@ void nr_rlc_remove_ue(int ue_id)
|
||||
nr_rlc_manager_unlock(nr_rlc_ue_manager);
|
||||
}
|
||||
|
||||
rlc_op_status_t rrc_rlc_remove_ue (const protocol_ctxt_t* const x)
|
||||
{
|
||||
nr_rlc_remove_ue(x->rntiMaybeUEid);
|
||||
return RLC_OP_STATUS_OK;
|
||||
}
|
||||
|
||||
bool nr_rlc_update_id(int from_id, int to_id)
|
||||
{
|
||||
nr_rlc_manager_lock(nr_rlc_ue_manager);
|
||||
|
||||
Reference in New Issue
Block a user