Merge remote-tracking branch 'origin/reject_UE' into integration_2025_w27 (!3432)

NR RRC Reject UE

Improvements in procedures to handle RRCReject message both at gNB and
UE. At gNB we send RRC Reject if the UE cannot be given resources to go
into connected mode.
This commit is contained in:
Robert Schmidt
2025-07-03 12:09:19 +02:00
19 changed files with 217 additions and 63 deletions
+1 -1
View File
@@ -954,7 +954,7 @@ printf("%d\n", slot);
//Configure UE
NR_BCCH_BCH_Message_t *mib = get_new_MIB_NR(scc);
nr_rrc_mac_config_req_mib(0, 0, mib->message.choice.mib, false);
nr_rrc_mac_config_req_mib(0, 0, mib->message.choice.mib, false, false);
nr_rrc_mac_config_req_cg(0, 0, UE_CellGroup, UE_Capability_nr);
asn1cFreeStruc(asn_DEF_NR_CellGroupConfig, UE_CellGroup);
+1
View File
@@ -486,6 +486,7 @@ typedef struct {
typedef struct {
NR_BCCH_BCH_Message_t *bcch;
int get_sib;
bool access_barred;
} nr_mac_rrc_config_mib_t;
typedef struct {
NR_SIB1_t *sib1;
+13 -1
View File
@@ -955,7 +955,7 @@ static void update_mib_conf(NR_MIB_t *target, NR_MIB_t *source)
target->intraFreqReselection = source->intraFreqReselection;
}
void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib, int sched_sib)
void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib, int sched_sib, bool barred)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
int ret = pthread_mutex_lock(&mac->if_mutex);
@@ -963,6 +963,13 @@ void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mib,
AssertFatal(mib, "MIB should not be NULL\n");
if (!mac->mib)
mac->mib = calloc(1, sizeof(*mac->mib));
if (barred)
mac->state = UE_BARRED;
else if (mac->state == UE_BARRED) {
// it is synched as we received MIB
// nr_ue_decode_mib is transitionining to the correct state
mac->state = UE_NOT_SYNC;
}
update_mib_conf(mac->mib, mib);
mac->phy_config.Mod_id = module_id;
mac->phy_config.CC_id = cc_idP;
@@ -1725,6 +1732,11 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t
reset_mac_inst(mac);
mac->state = UE_PERFORMING_RA; // still in sync but need to restart RA
break;
case REJECT:
reset_ra(mac, false);
reset_mac_inst(mac);
mac->state = UE_BARRED;
break;
case RE_ESTABLISHMENT:
reset_mac_inst(mac);
nr_ue_mac_default_configs(mac);
+2
View File
@@ -148,6 +148,7 @@
// Define the UE L2 states with X-Macro
#define NR_UE_L2_STATES \
UE_STATE(UE_NOT_SYNC) \
UE_STATE(UE_BARRED) \
UE_STATE(UE_RECEIVING_SIB) \
UE_STATE(UE_PERFORMING_RA) \
UE_STATE(UE_CONNECTED) \
@@ -199,6 +200,7 @@ typedef enum {
RE_ESTABLISHMENT,
RRC_SETUP_REESTAB_RESUME,
UL_SYNC_LOST_T430_EXPIRED,
REJECT,
} NR_UE_MAC_reset_cause_t;
typedef struct {
+1 -4
View File
@@ -87,10 +87,7 @@ void nr_rrc_mac_config_req_cg(module_id_t module_id,
NR_CellGroupConfig_t *cell_group_config,
NR_UE_NR_Capability_t *ue_Capability);
void nr_rrc_mac_config_req_mib(module_id_t module_id,
int cc_idP,
NR_MIB_t *mibP,
int sched_sib1);
void nr_rrc_mac_config_req_mib(module_id_t module_id, int cc_idP, NR_MIB_t *mibP, int sched_sib1, bool barred);
void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *sib1, bool can_start_ra);
+1 -1
View File
@@ -971,7 +971,7 @@ bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t
NR_SCHED_LOCK(&nrmac->sched_lock);
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
DevAssert(UE->uid < MAX_MOBILES_PER_GNB); // 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) {
+21 -12
View File
@@ -717,11 +717,6 @@ void nr_initiate_ra_proc(module_id_t module_idP,
}
UE = get_new_nr_ue_inst(&nr_mac->UE_info.uid_allocator, rnti, NULL);
if (!UE) {
LOG_E(NR_MAC, "FAILURE: %4d.%2d cannot create UE context, ignoring RA because RRC Reject not implemented yet\n", frame, slot);
NR_SCHED_UNLOCK(&nr_mac->sched_lock);
return;
}
if (!add_new_UE_RA(nr_mac, UE)) {
LOG_E(NR_MAC, "FAILURE: %4d.%2d initiating RA procedure for preamble index %d: no free RA process\n", frame, slot, preamble_index);
delete_nr_ue_data(UE, NULL, &nr_mac->UE_info.uid_allocator);
@@ -1960,7 +1955,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP,
}
}
void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, NR_UE_info_t *UE, bool success)
bool nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, NR_UE_info_t *UE, bool success)
{
NR_RA_t *ra = UE->ra;
const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4";
@@ -1975,10 +1970,21 @@ void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, N
if (success) {
gNB_MAC_INST *nr_mac = RC.nrmac[module_id];
NR_ServingCellConfigCommon_t *scc = nr_mac->common_channels[0].ServingCellConfigCommon;
// we configure the UE using common search space with DCIX0 while waiting for a reconfiguration
configure_UE_BWP(nr_mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1);
transition_ra_connected_nr_ue(nr_mac, UE);
LOG_A(NR_MAC, "%4d.%2d UE %04x: Received Ack of %s. CBRA procedure succeeded!\n", frame, slot, UE->rnti, ra_type_str);
LOG_A(NR_MAC,
"%4d.%2d UE %04x: Received Ack of %s. CBRA procedure succeeded (%s)\n",
frame,
slot,
UE->rnti,
ra_type_str,
UE->CellGroup ? "UE Connected" : "UE Rejected");
if (UE->CellGroup) {
// we configure the UE using common search space with DCIX0 while waiting for a reconfiguration
configure_UE_BWP(nr_mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1);
transition_ra_connected_nr_ue(nr_mac, UE);
} else { // in case of UE reject
nr_release_ra_UE(nr_mac, UE->rnti);
return true;
}
} else {
LOG_I(NR_MAC, "%4d.%2d UE %04x: RA Procedure failed at %s!\n", frame, slot, UE->rnti, ra_type_str);
nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs);
@@ -1991,6 +1997,7 @@ void nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, N
LOG_I(NR_MAC, "(UE %04x) Received Nack in %s, preparing retransmission!\n", UE->rnti, ra_type_str);
ra->ra_state = ra->ra_type == RA_4_STEP ? nrRA_Msg4 : nrRA_MsgB;
}
return false;
}
/////////////////////////////////////
@@ -2125,7 +2132,7 @@ void nr_release_ra_UE(gNB_MAC_INST *mac, rnti_t rnti)
if (UE) {
delete_nr_ue_data(UE, mac->common_channels, &UE_info->uid_allocator);
} else {
LOG_W(NR_MAC,"Call to del rnti %04x, but not existing\n", rnti);
LOG_W(NR_MAC,"Call to release RA UE with rnti %04x, but not existing\n", rnti);
}
}
@@ -2152,7 +2159,9 @@ void nr_schedule_RA(module_id_t module_idP,
ra->contention_resolution_timer--;
if (ra->contention_resolution_timer == 0) {
LOG_W(NR_MAC, "(%d.%d) RA Contention Resolution timer expired for UE 0x%04x, RA procedure failed...\n", frameP, slotP, UE->rnti);
bool requested = nr_mac_request_release_ue(mac, UE->rnti);
bool requested = false;
if (UE->CellGroup) // request if we did not reject the UE
requested = nr_mac_request_release_ue(mac, UE->rnti);
if (!requested)
nr_release_ra_UE(mac, UE->rnti);
continue;
@@ -2690,19 +2690,10 @@ static void init_bler_stats(const NR_bler_options_t *bler_options, NR_bler_stats
* 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)
{
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;
}
NR_UE_info_t *UE = calloc_or_fail(1, sizeof(NR_UE_info_t));
UE->uid = uid_linear_allocator_new(uia);
UE->rnti = rnti;
UE->CellGroup = CellGroup;
UE->uid = uid;
UE->ra = calloc(1, sizeof(*UE->ra));
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
sched_ctrl->ta_update = 31;
@@ -2734,6 +2725,8 @@ NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size],
{
for (int i = 0; i < list_size; i++) {
NR_UE_info_t *curr_UE = list[i];
if (!curr_UE)
break; /* reached the end of the list */
if (curr_UE->rnti != rnti)
continue;
@@ -2742,7 +2735,6 @@ NR_UE_info_t *remove_UE_from_list(int list_size, NR_UE_info_t *list[list_size],
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;
}
@@ -2848,8 +2840,10 @@ void mac_remove_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rnti)
NR_SCHED_LOCK(&UE_info->mutex);
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);
delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator);
if (UE)
delete_nr_ue_data(UE, nr_mac->common_channels, &UE_info->uid_allocator);
else
nr_release_ra_UE(nr_mac, rnti);
}
// all values passed to this function are in dB x10
@@ -3410,7 +3404,9 @@ void send_initial_ul_rrc_message(int rnti, const uint8_t *sdu, sdu_size_t sdu_le
NR_SCHED_ENSURE_LOCKED(&mac->sched_lock);
uint8_t du2cu[1024];
int encoded = encode_cellGroupConfig(UE->CellGroup, du2cu, sizeof(du2cu));
int encoded_len = 0;
if (UE->CellGroup)
encoded_len = encode_cellGroupConfig(UE->CellGroup, du2cu, sizeof(du2cu));
DevAssert(mac->f1_config.setup_req != NULL);
AssertFatal(mac->f1_config.setup_req->num_cells_available == 1, "can handle only one cell\n");
@@ -3421,8 +3417,8 @@ void send_initial_ul_rrc_message(int rnti, const uint8_t *sdu, sdu_size_t sdu_le
.crnti = rnti,
.rrc_container = (uint8_t *) sdu,
.rrc_container_length = sdu_len,
.du2cu_rrc_container = (uint8_t *) du2cu,
.du2cu_rrc_container_length = encoded
.du2cu_rrc_container = encoded_len ? (uint8_t *) du2cu : NULL,
.du2cu_rrc_container_length = encoded_len
};
mac->mac_rrc.initial_ul_rrc_message_transfer(0, &ul_rrc_msg);
}
@@ -3435,6 +3431,19 @@ bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
if (!nr_rlc_activate_srb0(UE->rnti, UE, send_initial_ul_rrc_message))
return false;
if (UE->uid >= MAX_MOBILES_PER_GNB) {
// verifying if any UE left in the meantime and it is possible to get a valid UID
uid_linear_allocator_free(&mac->UE_info.uid_allocator, UE->uid);
UE->uid = uid_linear_allocator_new(&mac->UE_info.uid_allocator);
if (UE->uid >= MAX_MOBILES_PER_GNB) {
// if the UE list is full, we should reject the UE with an RRC reject message
// to signal the upper layers to send a reject we send an empty CellGroup information element
UE->CellGroup = NULL;
LOG_W(NR_MAC, "Maximum number of UE alllowed at DU reached. Cannot serve UE %04x", UE->rnti);
return true;
}
}
/* create this UE's initial CellGroup */
int CC_id = 0;
int srb_id = 1;
@@ -3444,12 +3453,14 @@ bool prepare_initial_ul_rrc_message(gNB_MAC_INST *mac, NR_UE_info_t *UE)
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
UE->CellGroup = cellGroupConfig;
if (!cellGroupConfig)
return true;
/* the cellGroup sent to CU specifies there is SRB1, so create it */
DevAssert(cellGroupConfig->rlc_BearerToAddModList->list.count == 1);
const NR_RLC_BearerConfig_t *bearer = cellGroupConfig->rlc_BearerToAddModList->list.array[0];
DevAssert(bearer->servedRadioBearer->choice.srb_Identity == srb_id);
nr_rlc_add_srb(UE->rnti, bearer->servedRadioBearer->choice.srb_Identity, bearer);
int priority = bearer->mac_LogicalChannelConfig->ul_SpecificParameters->priority;
nr_lc_config_t c = {.lcid = bearer->logicalChannelIdentity, .priority = priority};
nr_mac_add_lcid(&UE->UE_sched_ctrl, &c);
@@ -899,8 +899,13 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id, frame_t frame, slot_t slot, con
nr_mac_update_pdcch_closed_loop_adjust(sched_ctrl, harq_confidence != 0);
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 (is_ra) {
bool ue_rejected = nr_check_Msg4_MsgB_Ack(mod_id, frame, slot, UE, success);
if (ue_rejected) {
NR_SCHED_UNLOCK(&nrmac->sched_lock);
return;
}
}
if (harq_confidence == 1)
UE->mac_stats.pucch0_DTX++;
}
+1 -1
View File
@@ -331,7 +331,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
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);
bool 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);
@@ -558,7 +558,7 @@ static NR_UE_info_t *create_new_UE(gNB_MAC_INST *mac, uint32_t cu_id, const NR_C
DevAssert(success);
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");
AssertFatal(UE->uid < MAX_MOBILES_PER_GNB, "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];
+52 -5
View File
@@ -238,6 +238,7 @@ static int get_nb_pucch2_per_slot(const NR_ServingCellConfigCommon_t *scc, int b
int nb_pucch2 = (max_csi_reports / (available_report_occasions + 1)) + 1;
// in current implementation we need (nb_pucch2 * PUCCH2_SIZE) prbs for PUCCH2
// and MAX_MOBILES_PER_GNB prbs for PUCCH1
// checked for validity in verify_radio_configuration
AssertFatal((nb_pucch2 * PUCCH2_SIZE) + MAX_MOBILES_PER_GNB <= bwp_size,
"Cannot allocate all required PUCCH resources for max number of %d UEs in BWP with %d PRBs\n",
MAX_MOBILES_PER_GNB, bwp_size);
@@ -402,6 +403,7 @@ static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0,
else {
nzpcsi0->periodicityAndOffset->present = NR_CSI_ResourcePeriodicityAndOffset_PR_slots320;
const int nb_dl_slots_period = get_full_dl_slots_per_period(fs); // full DL slots
// checked for validity in verify_radio_configuration
AssertFatal(offset / 320 < nb_dl_slots_period, "Cannot allocate CSI-RS for BWP %d. Not enough resources for CSI-RS\n", id);
nzpcsi0->periodicityAndOffset->choice.slots320 = (offset % 320) + (offset / 320);
}
@@ -661,7 +663,7 @@ static struct NR_SRS_Resource__resourceType__periodic *configure_periodic_srs(co
{
frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
int offset = get_ul_slot_offset(fs, uid, false); // only full UL slots for SRS
// checked for validity in verify_radio_configuration
AssertFatal(offset < 2560, "Cannot allocate SRS configuration for uid %d, not enough resources\n", uid);
const int ideal_period = set_ideal_period(false);
@@ -1169,6 +1171,7 @@ static void config_pucch_resset0(NR_PUCCH_Config_t *pucch_Config,
NR_PUCCH_Resource_t *pucchres0 = calloc(1,sizeof(*pucchres0));
pucchres0->pucch_ResourceId = *pucchid;
pucchres0->startingPRB = (PUCCH2_SIZE * num_pucch2) + uid;
// checked for validity in verify_radio_configuration
AssertFatal(pucchres0->startingPRB < curr_bwp, "Not enough resources in current BWP (size %d) to allocate uid %d\n", curr_bwp, uid);
pucchres0->intraSlotFrequencyHopping = NULL;
pucchres0->secondHopPRB = NULL;
@@ -1745,13 +1748,11 @@ static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc,
const int ideal_period = set_ideal_period(true);
const int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp);
const int idx = (uid * 2 / num_pucch2) + is_rsrp;
frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
int offset = get_ul_slot_offset(fs, idx, true);
LOG_D(NR_MAC, "set_csi_meas_periodicity: uid = %d, offset = %d, ideal_period = %d", uid, offset, ideal_period);
// checked for validity in verify_radio_configuration
AssertFatal(offset < 320, "Not enough UL slots to accomodate all possible UEs. Need to rework the implementation\n");
if (check_periodicity(4, ideal_period, fs)) {
csirep->reportConfigType.choice.periodic->reportSlotConfig.present = NR_CSI_ReportPeriodicityAndOffset_PR_slots4;
csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots4 = offset;
@@ -3492,12 +3493,58 @@ NR_RLC_BearerConfig_t *get_DRB_RLC_BearerConfig(long lcChannelId,
return rlc_BearerConfig;
}
static bool verify_radio_configuration(int uid, const NR_ServingCellConfigCommon_t *scc, const NR_ServingCellConfig_t *scd)
{
frame_structure_t *fs = &RC.nrmac[0]->frame_structure;
int srs_offset = get_ul_slot_offset(fs, uid, false);
// see configure_periodic_srs
if (srs_offset >= 2560) {
LOG_E(NR_RRC, "UID %d, cannot allocate resources for SRS, rejecting UE\n", uid);
return false;
}
int n_dl_bwp = scd->downlinkBWP_ToAddModList ? scd->downlinkBWP_ToAddModList->list.count : 1;
int csi_offset = fs->numb_slots_period * n_dl_bwp;
// see set_csirs_periodicity
if (csi_offset / 320 >= get_full_dl_slots_per_period(fs)) {
LOG_E(NR_RRC, "UID %d, cannot allocate resources for CSI-RS, rejecting UE\n", uid);
return false; // cannot allocate resources for CSI-RS
}
int curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp);
int pucchres0_startingPRB = (PUCCH2_SIZE * num_pucch2) + uid;
// see config_pucch_resset0
if (pucchres0_startingPRB >= curr_bwp) {
LOG_E(NR_RRC, "UID %d, cannot allocate resources for PUCCH0, rejecting UE\n", uid);
return false; // cannot allocate resources for PUCCH0
}
// see get_nb_pucch2_per_slot
if ((num_pucch2 * PUCCH2_SIZE) + MAX_MOBILES_PER_GNB > curr_bwp) {
LOG_E(NR_RRC, "UID %d, cannot allocate resources for PUCCH2, rejecting UE\n", uid);
return false; // cannot allocate resources for PUCCH2
}
const int idx = (uid * 2 / num_pucch2) + 1;
int offset = get_ul_slot_offset(fs, idx, true);
// see set_csi_meas_periodicity
if (offset >= 320) {
LOG_E(NR_RRC, "UID %d, cannot allocate resources for CSI reporting, rejecting UE\n", uid);
return false; // cannot allocate resources for CSI report
}
return true;
}
NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
const NR_ServingCellConfigCommon_t *scc,
const NR_ServingCellConfig_t *servingcellconfigdedicated,
const nr_mac_config_t *configuration,
const nr_rlc_configuration_t *default_rlc_config)
{
if (!verify_radio_configuration(uid, scc, servingcellconfigdedicated))
return NULL;
NR_SpCellConfig_t *spCellConfig = get_initial_SpCellConfig(uid, scc, servingcellconfigdedicated, configuration);
NR_CellGroupConfig_t *cellGroupConfig = calloc(1, sizeof(*cellGroupConfig));
cellGroupConfig->cellGroupId = 0;
@@ -3515,7 +3562,7 @@ NR_CellGroupConfig_t *get_initial_cellGroupConfig(int uid,
cellGroupConfig->physicalCellGroupConfig = configure_phy_cellgroup();
cellGroupConfig->spCellConfig = get_initial_SpCellConfig(uid, scc, servingcellconfigdedicated, configuration);
cellGroupConfig->spCellConfig = spCellConfig;
cellGroupConfig->sCellToAddModList = NULL;
cellGroupConfig->sCellToReleaseList = NULL;
+1 -1
View File
@@ -248,7 +248,7 @@ int do_RRCReject(uint8_t *const buffer)
rrcReject->criticalExtensions.choice.rrcReject = CALLOC(1, sizeof(struct NR_RRCReject_IEs));
rrcReject->criticalExtensions.choice.rrcReject->waitTime = CALLOC(1, sizeof(NR_RejectWaitTime_t));
*rrcReject->criticalExtensions.choice.rrcReject->waitTime = 1;
*rrcReject->criticalExtensions.choice.rrcReject->waitTime = 10;
rrcReject->criticalExtensions.present = NR_RRCReject__criticalExtensions_PR_rrcReject;
+11 -5
View File
@@ -394,10 +394,9 @@ static void rrc_gNB_generate_RRCSetup(instance_t instance,
rrc->mac_rrc.dl_rrc_message_transfer(ue_data.du_assoc_id, &dl_rrc);
}
static void rrc_gNB_generate_RRCReject(module_id_t module_id, rrc_gNB_ue_context_t *const ue_context_pP)
static void rrc_gNB_generate_RRCReject(gNB_RRC_INST *rrc, rrc_gNB_ue_context_t *const ue_context_pP)
//-----------------------------------------------------------------------------
{
gNB_RRC_INST *rrc = RC.nrrrc[module_id];
gNB_RRC_UE_t *ue_p = &ue_context_pP->ue_context;
LOG_A(NR_RRC, "Send RRCReject to RNTI %04x\n", ue_p->rnti);
@@ -421,10 +420,10 @@ static void rrc_gNB_generate_RRCReject(module_id_t module_id, rrc_gNB_ue_context
.rrc_container = buf,
.rrc_container_length = size,
.srb_id = srbid,
.execute_duplication = 1,
.RAT_frequency_priority_information.en_dc = 0
};
rrc->mac_rrc.dl_rrc_message_transfer(ue_data.du_assoc_id, &dl_rrc);
/* release the created UE context, we rejected the UE */
rrc_remove_ue(rrc, ue_context_pP);
}
//-----------------------------------------------------------------------------
@@ -1137,10 +1136,17 @@ static void rrc_handle_RRCSetupRequest(gNB_RRC_INST *rrc,
ue_context_p = rrc_gNB_create_ue_context(assoc_id, msg->crnti, rrc, random_value, msg->gNB_DU_ue_id);
LOG_E(NR_RRC, "RRCSetupRequest without random UE identity or S-TMSI not supported, let's reject the UE %04x\n", msg->crnti);
rrc_gNB_generate_RRCReject(0, ue_context_p);
rrc_gNB_generate_RRCReject(rrc, ue_context_p);
return;
}
// If the DU to CU RRC Container IE is not included in the INITIAL UL RRC MESSAGE TRANSFER,
// the gNB-CU should reject the UE under the assumption that the gNB-DU is not able to serve such UE
if (msg->du2cu_rrc_container == NULL) {
// this will remove the UE context
rrc_gNB_generate_RRCReject(rrc, ue_context_p);
return;
}
NR_CellGroupConfig_t *cellGroupConfig = NULL;
asn_dec_rval_t dec_rval = uper_decode_complete(NULL,
&asn_DEF_NR_CellGroupConfig,
+5 -1
View File
@@ -133,7 +133,11 @@ void process_msg_rcc_to_mac(MessageDef *msg)
asn1cFreeStruc(asn_DEF_NR_CellGroupConfig, NR_MAC_RRC_CONFIG_CG(msg).cellGroupConfig);
break;
case NR_MAC_RRC_CONFIG_MIB:
nr_rrc_mac_config_req_mib(ue_id, 0, NR_MAC_RRC_CONFIG_MIB(msg).bcch->message.choice.mib, NR_MAC_RRC_CONFIG_MIB(msg).get_sib);
nr_rrc_mac_config_req_mib(ue_id,
0,
NR_MAC_RRC_CONFIG_MIB(msg).bcch->message.choice.mib,
NR_MAC_RRC_CONFIG_MIB(msg).get_sib,
NR_MAC_RRC_CONFIG_MIB(msg).access_barred);
ASN_STRUCT_FREE(asn_DEF_NR_BCCH_BCH_Message, NR_MAC_RRC_CONFIG_MIB(msg).bcch);
break;
case NR_MAC_RRC_CONFIG_SIB1: {
+61 -10
View File
@@ -749,6 +749,7 @@ NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int nb_inst, int num_ant_tx)
rrc->reconfig_after_reestab = false;
/* 5G-S-TMSI */
rrc->fiveG_S_TMSI = UINT64_MAX;
rrc->access_barred = false;
FILE *f = NULL;
if (uecap_file)
@@ -959,11 +960,12 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc,
}
NR_UE_RRC_SI_INFO *SI_info = &rrc->perNB[gNB_index].SInfo;
bool barred = rrc->access_barred || bcch_message->message.choice.mib->cellBarred == NR_MIB__cellBarred_barred;
int get_sib = 0;
if (IS_SA_MODE(get_softmodem_params())
&& !SI_info->sib_pending
&& bcch_message->message.present == NR_BCCH_BCH_MessageType_PR_mib
&& bcch_message->message.choice.mib->cellBarred == NR_MIB__cellBarred_notBarred
&& !barred
&& rrc->nrRrcState != RRC_STATE_DETACH_NR) {
// to schedule MAC to get SI if required
get_sib = check_si_status(SI_info);
@@ -975,6 +977,7 @@ static void nr_rrc_ue_decode_NR_BCCH_BCH_Message(NR_UE_RRC_INST_t *rrc,
// mac will manage the pointer
NR_MAC_RRC_CONFIG_MIB(msg).bcch = bcch_message;
NR_MAC_RRC_CONFIG_MIB(msg).get_sib = get_sib;
NR_MAC_RRC_CONFIG_MIB(msg).access_barred = barred;
itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg);
} else {
LOG_E(NR_RRC, "RRC-received BCCH message is not a MIB\n");
@@ -1376,7 +1379,11 @@ static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, const NR_RRCSetup_t *
nr_timer_stop(&timers->T319);
nr_timer_stop(&timers->T320);
// TODO if T390 and T302 are running (not implemented)
// if T390 (not implemented) and T302 are running
// stop timer
// perform the actions as specified in 5.3.14.4
nr_timer_stop(&timers->T302);
handle_302_expired_stopped(rrc);
// if the RRCSetup is received in response to an RRCResumeRequest, RRCResumeRequest1 or RRCSetupRequest
// enter RRC_CONNECTED
@@ -1394,8 +1401,45 @@ static void nr_rrc_process_rrcsetup(NR_UE_RRC_INST_t *rrc, const NR_RRCSetup_t *
rrc_ue_generate_RRCSetupComplete(rrc, rrcSetup->rrc_TransactionIdentifier);
}
static int8_t nr_rrc_ue_decode_ccch(NR_UE_RRC_INST_t *rrc,
const NRRrcMacCcchDataInd *ind)
static void nr_rrc_process_rrcreject(NR_UE_RRC_INST_t *rrc, const NR_RRCReject_t *rrcReject)
{
// stop timer T300, T302, T319 if running;
NR_UE_Timers_Constants_t *timers = &rrc->timers_and_constants;
nr_timer_stop(&timers->T300);
nr_timer_stop(&timers->T302);
nr_timer_stop(&timers->T319);
// reset MAC and release the default MAC Cell Group configuration
NR_UE_MAC_reset_cause_t cause = REJECT;
MessageDef *msg = itti_alloc_new_message(TASK_RRC_NRUE, 0, NR_MAC_RRC_CONFIG_RESET);
NR_MAC_RRC_CONFIG_RESET(msg).cause = cause;
itti_send_msg_to_task(TASK_MAC_UE, rrc->ue_id, msg);
// if waitTime is configured in the RRCReject: start timer T302, with the timer value set to the waitTime
NR_RejectWaitTime_t *waitTime = NULL;
if (rrcReject->criticalExtensions.present == NR_RRCReject__criticalExtensions_PR_rrcReject) {
NR_RRCReject_IEs_t *ies = rrcReject->criticalExtensions.choice.rrcReject;
waitTime = ies->waitTime; // Wait time value in seconds
}
if (waitTime) {
nr_timer_setup(&timers->T302, *waitTime * 1000, 10);
nr_timer_start(&timers->T302);
rrc->access_barred = true;
} else {
LOG_W(RRC, "Error: waitTime should be always included in RRCReject message\n");
}
// TODO if RRCReject is received in response to a request from upper layers
// inform the upper layer that access barring is applicable for all access categories except categories '0' and '2'
// TODO if RRCReject is received in response to an RRCSetupRequest
// inform upper layers about the failure to setup the RRC connection, upon which the procedure ends
// TODO else if RRCReject is received in response to an RRCResumeRequest or an RRCResumeRequest1
// Resume not implemented yet
}
static int8_t nr_rrc_ue_decode_ccch(NR_UE_RRC_INST_t *rrc, const NRRrcMacCcchDataInd *ind)
{
NR_DL_CCCH_Message_t *dl_ccch_msg = NULL;
asn_dec_rval_t dec_rval;
@@ -1422,7 +1466,8 @@ static int8_t nr_rrc_ue_decode_ccch(NR_UE_RRC_INST_t *rrc,
break;
case NR_DL_CCCH_MessageType__c1_PR_rrcReject:
LOG_I(NR_RRC, "[UE%ld] Logical Channel DL-CCCH (SRB0), Received RRCReject \n", rrc->ue_id);
LOG_W(NR_RRC, "[UE%ld] Logical Channel DL-CCCH (SRB0), Received RRCReject \n", rrc->ue_id);
nr_rrc_process_rrcreject(rrc, dl_ccch_msg->message.choice.c1->choice.rrcReject);
rval = 0;
break;
@@ -2740,17 +2785,16 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc,
nr_timer_setup(&tac->T302, target, 10);
nr_timer_start(&tac->T302);
// TODO inform upper layers that access barring is applicable
// for all access categories except categories '0' and '2'.
LOG_E(NR_RRC,"Go to IDLE. Handling RRCRelease message including a waitTime not implemented\n");
// for all access categories except categories '0' and '2'.
// for now we just set the access barred in RRC
rrc->access_barred = true;
}
}
}
if (!waitTime) {
if (nr_timer_is_active(&tac->T302)) {
nr_timer_stop(&tac->T302);
// TODO barring alleviation as in 5.3.14.4
// not implemented
LOG_E(NR_RRC,"Go to IDLE. Barring alleviation not implemented\n");
handle_302_expired_stopped(rrc);
}
}
if (nr_timer_is_active(&tac->T390)) {
@@ -2860,6 +2904,13 @@ void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc,
itti_send_msg_to_task(TASK_NAS_NRUE, rrc->ue_id, msg_p);
}
void handle_302_expired_stopped(NR_UE_RRC_INST_t *rrc)
{
// for each Access Category for which T390 (TODO not implemented) is not running
// consider the barring for this Access Category to be alleviated
rrc->access_barred = false;
}
void handle_t300_expiry(NR_UE_RRC_INST_t *rrc)
{
rrc->ra_trigger = RRC_CONNECTION_SETUP;
+1 -1
View File
@@ -205,7 +205,7 @@ typedef struct rrcPerNB {
typedef struct NR_UE_RRC_INST_s {
instance_t ue_id;
rrcPerNB_t perNB[NB_CNX_UE];
bool access_barred;
rnti_t rnti;
uint32_t phyCellID;
long arfcn_ssb;
+1
View File
@@ -64,6 +64,7 @@ void *rrc_nrue(void *args_p);
void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc);
void handle_rlf_detection(NR_UE_RRC_INST_t *rrc);
void handle_302_expired_stopped(NR_UE_RRC_INST_t *rrc);
/**\brief RRC NSA UE task.
\param void *args_p Pointer on arguments to start the task. */
@@ -144,6 +144,14 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc)
nr_rrc_going_to_IDLE(rrc, RRC_CONNECTION_FAILURE, NULL);
}
bool t302_expired = nr_timer_tick(&timers->T302);
// 5.3.14.4 in 38.331
// consider the barring for this Access Category to be alleviated
if (t302_expired) {
LOG_W(NR_RRC, "Timer T302 expired! Access barring alleviated!\n");
handle_302_expired_stopped(rrc);
}
bool t304_expired = nr_timer_tick(&timers->T304);
if(t304_expired) {
LOG_W(NR_RRC, "Timer T304 expired\n");