Compare commits

...

3 Commits

9 changed files with 80 additions and 46 deletions

View File

@@ -253,28 +253,28 @@ int rrc_gNB_trigger_n2_ho(char *buf, int debug, telnet_printfunc_t prnt)
return 0;
}
int force_ul_failure(char *buf, int debug, telnet_printfunc_t prnt)
int force_link_failure(char *buf, int debug, telnet_printfunc_t prnt)
{
if (!RC.nrmac)
ERROR_MSG_RET("no MAC/RLC present, force_ul_failure failed\n");
ERROR_MSG_RET("no MAC/RLC present, force_link_failure failed\n");
int rnti = fetch_rnti(buf, prnt);
if (rnti < 0)
ERROR_MSG_RET("could not identify UE (no UE, no such RNTI, or multiple UEs)\n");
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, rnti);
nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
nr_mac_trigger_link_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
return 0;
}
int force_ue_release(char *buf, int debug, telnet_printfunc_t prnt)
{
force_ul_failure(buf, debug, prnt);
force_link_failure(buf, debug, prnt);
int rnti = fetch_rnti(buf, prnt);
if (rnti < 0)
ERROR_MSG_RET("could not identify UE (no UE, no such RNTI, or multiple UEs)\n");
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[0]->UE_info, rnti);
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
sched_ctrl->ul_failure_timer = 2;
nr_mac_check_ul_failure(RC.nrmac[0], UE->rnti, sched_ctrl);
sched_ctrl->link_failure_timer = 2;
nr_mac_check_link_failure(RC.nrmac[0], UE->rnti, sched_ctrl);
return 0;
}
@@ -398,7 +398,8 @@ static telnetshell_cmddef_t cicmds[] = {
{"force_reestab", "[rnti(hex,opt)]", trigger_reestab},
{"get_reestab_count", "[rnti(hex,opt)]", get_reestab_count},
{"force_ue_release", "[rnti(hex,opt)]", force_ue_release},
{"force_ul_failure", "[rnti(hex,opt)]", force_ul_failure},
{"force_link_failure", "[rnti(hex,opt)]", force_link_failure},
{"force_ul_failure", "[rnti(hex,opt)]", force_link_failure}, /* backward compat alias, TODO cleanup */
{"trigger_f1_ho", "[rrc_ue_id(int,opt)]", rrc_gNB_trigger_f1_ho},
{"fetch_du_by_ue_id", "[rrc_ue_id(int,opt)]", fetch_du_by_ue_id},
{"get_current_bwp", "[rnti(hex,opt)]", get_current_bwp},

View File

@@ -370,7 +370,7 @@ static int stop_modem(char *buf, int debug, telnet_printfunc_t prnt)
* combinations that won't happen. */
const gNB_MAC_INST *mac = RC.nrmac[0];
UE_iterator((NR_UE_info_t **)mac->UE_info.connected_ue_list, it) {
nr_mac_trigger_ul_failure(&it->UE_sched_ctrl, 1);
nr_mac_trigger_link_failure(&it->UE_sched_ctrl, 1);
}
usleep(50000);

View File

@@ -1999,7 +1999,7 @@ bool nr_check_Msg4_MsgB_Ack(module_id_t module_id, frame_t frame, slot_t slot, N
}
} 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);
nr_mac_trigger_link_failure(sched_ctrl, UE->current_DL_BWP.scs);
}
if (sched_ctrl->retrans_dl_harq.head >= 0) {

View File

@@ -63,6 +63,9 @@
// 3GPP TS 38.331 Section 12 Table 12.1-1: UE performance requirements for RRC procedures for UEs
#define NR_RRC_RECONFIGURATION_DELAY_MS 10
#define NR_RRC_BWP_SWITCHING_DELAY_MS 6
#define RLC_MAX_RETX_RELEASE_THRESHOLD 32
static void gnb_rlf_handler(int rnti);
// #define DEBUG_DCI
// CQI TABLES (10 times the value in 214 to adequately compare with R)
@@ -3055,6 +3058,9 @@ bool add_connected_nr_ue(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE)
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);
// Register gNB-side RLF handler for UE context release on persistent link failure
nr_rlc_set_rlf_handler(UE->rnti, gnb_rlf_handler);
dump_nr_list(UE_info->connected_ue_list);
return true;
}
@@ -3596,8 +3602,8 @@ void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot)
continue;
}
/* check if UL failure and trigger release request if necessary */
bool released = nr_mac_check_ul_failure(mac, UE->rnti, sched_ctrl);
/* check if link failure and trigger release request if necessary */
bool released = nr_mac_check_link_failure(mac, UE->rnti, sched_ctrl);
if (released) {
// go back to examine the next UE, which is at the position the current UE was
UE--;
@@ -3610,8 +3616,8 @@ void nr_mac_update_timers(module_id_t module_id, frame_t frame, slot_t slot)
}
if (nr_timer_tick(&sched_ctrl->transm_timeout)) {
nr_timer_stop(&sched_ctrl->transm_timeout);
LOG_W(NR_MAC, "UE %04x UL failure after transmission timeout\n", UE->rnti);
nr_mac_trigger_ul_failure(sched_ctrl, UE->current_DL_BWP.scs);
LOG_W(NR_MAC, "UE %04x link failure after transmission timeout\n", UE->rnti);
nr_mac_trigger_link_failure(sched_ctrl, UE->current_DL_BWP.scs);
}
if (nr_timer_tick(&sched_ctrl->tci_beam_switch)) {
nr_timer_stop(&sched_ctrl->tci_beam_switch);
@@ -3865,32 +3871,58 @@ bool nr_mac_ue_is_active(const NR_UE_info_t *ue)
{
/* pass NR_UE_info_t, so that later we could adapt, e.g., for DRX */
const NR_UE_sched_ctrl_t *sched_ctrl = &ue->UE_sched_ctrl;
if (sched_ctrl->ul_failure)
if (sched_ctrl->link_failure)
return false;
if (nr_timer_is_active(&sched_ctrl->transm_interrupt))
return false;
return true;
}
#define UL_FAILURE_REQ_GRACE 10000
#define UL_FAILURE_TIMEOUT 30000
void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing)
#define LINK_FAILURE_REQ_GRACE 10000
#define LINK_FAILURE_TIMEOUT 30000
void nr_mac_trigger_link_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing)
{
if (sched_ctrl->ul_failure) {
if (sched_ctrl->link_failure) {
/* already running */
return;
}
sched_ctrl->ul_failure = true;
// UL_FAILURE_TIMEOUT ms till triggering release request
// UL_FAILURE_REQ_GRACE ms till automatically released after request
sched_ctrl->ul_failure_timer = (UL_FAILURE_REQ_GRACE + UL_FAILURE_TIMEOUT) << subcarrier_spacing;
sched_ctrl->link_failure = true;
// LINK_FAILURE_TIMEOUT ms till triggering release request
// LINK_FAILURE_REQ_GRACE ms till automatically released after request
sched_ctrl->link_failure_timer = (LINK_FAILURE_REQ_GRACE + LINK_FAILURE_TIMEOUT) << subcarrier_spacing;
}
void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl)
void nr_mac_reset_link_failure(NR_UE_sched_ctrl_t *sched_ctrl)
{
sched_ctrl->ul_failure = false;
sched_ctrl->ul_failure_timer = 0;
sched_ctrl->link_failure = false;
sched_ctrl->link_failure_timer = 0;
sched_ctrl->pusch_consecutive_dtx_cnt = 0;
sched_ctrl->rlc_max_retx_cnt = 0;
}
/* \brief RLF handler called from RLC when max retransmissions reached.
* Called from scheduler context (sched_lock held), do NOT take sched_lock. */
static void gnb_rlf_handler(int rnti)
{
gNB_MAC_INST *mac = RC.nrmac[0];
NR_UE_info_t *UE = find_nr_UE(&mac->UE_info, rnti);
if (!UE)
return;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
/* Already triggered link failure, ignore further events */
if (sched_ctrl->rlc_max_retx_cnt >= RLC_MAX_RETX_RELEASE_THRESHOLD)
return;
sched_ctrl->rlc_max_retx_cnt++;
LOG_W(NR_MAC, "UE %04x: RLC max RETX reached (%d/%d)\n",
rnti, sched_ctrl->rlc_max_retx_cnt, RLC_MAX_RETX_RELEASE_THRESHOLD);
if (sched_ctrl->rlc_max_retx_cnt >= RLC_MAX_RETX_RELEASE_THRESHOLD) {
LOG_W(NR_MAC, "UE %04x: RLF threshold reached, triggering link failure (context kept for re-establishment)\n", rnti);
nr_mac_trigger_link_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
}
}
/* \brief trigger a release request towards the CU.
@@ -3913,22 +3945,22 @@ bool nr_mac_request_release_ue(const gNB_MAC_INST *nrmac, int rnti)
return true;
}
bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl)
bool nr_mac_check_link_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl)
{
if (!sched_ctrl->ul_failure)
if (!sched_ctrl->link_failure)
return false;
if (sched_ctrl->ul_failure_timer > 0)
sched_ctrl->ul_failure_timer--;
/* trigger once: trigger when ul_failure_timer == UL_FAILURE_REQ_GRACE( we
if (sched_ctrl->link_failure_timer > 0)
sched_ctrl->link_failure_timer--;
/* trigger once: trigger when link_failure_timer == LINK_FAILURE_REQ_GRACE( we
* wait for a UE release command from upper layers), and UE is automatically
* released when no answer after UL_FAILURE_REQ_GRACE */
if (sched_ctrl->ul_failure_timer == UL_FAILURE_REQ_GRACE) {
LOG_W(MAC, "UE %04x: request release after UL failure timer expiry\n", rnti);
* released when no answer after LINK_FAILURE_REQ_GRACE */
if (sched_ctrl->link_failure_timer == LINK_FAILURE_REQ_GRACE) {
LOG_W(MAC, "UE %04x: request release after link failure timer expiry\n", rnti);
bool requested = nr_mac_request_release_ue(nrmac, rnti);
if (!requested)
sched_ctrl->ul_failure_timer = 0; /* force expiry */
sched_ctrl->link_failure_timer = 0; /* force expiry */
}
if (sched_ctrl->ul_failure_timer == 0) {
if (sched_ctrl->link_failure_timer == 0) {
LOG_W(NR_MAC, "UE %04x: no answer for release request, dropping UE\n", rnti);
nr_mac_release_ue(nrmac, rnti);
return true;

View File

@@ -764,7 +764,7 @@ static void nr_rx_ra_sdu(const module_id_t mod_id,
bool cfra = ra->cfra;
if (ra->cfra) {
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
nr_mac_reset_ul_failure(sched_ctrl);
nr_mac_reset_link_failure(sched_ctrl);
reset_dl_harq_list(sched_ctrl);
reset_ul_harq_list(sched_ctrl);
// we configure the UE using dedicated search space: In SA (CFRA used for
@@ -868,8 +868,8 @@ static void nr_rx_ra_sdu(const module_id_t mod_id,
}
// 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 link failure for old UE
nr_mac_reset_link_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);
@@ -1032,7 +1032,7 @@ static void _nr_rx_sdu(const module_id_t gnb_mod_idP,
slotP,
UE->rnti,
UE->UE_sched_ctrl.pusch_consecutive_dtx_cnt);
nr_mac_trigger_ul_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
nr_mac_trigger_link_failure(&UE->UE_sched_ctrl, UE->current_UL_BWP.scs);
}
}
handle_nr_ul_harq(gNB_mac, UE, frameP, slotP, current_rnti, harq_pid, sduP == NULL);

View File

@@ -479,9 +479,9 @@ void clean_bwp_structures(NR_SpCellConfig_t *spCellConfig);
bool nr_mac_ue_is_active(const NR_UE_info_t *ue);
void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing);
void nr_mac_reset_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl);
bool nr_mac_check_ul_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl);
void nr_mac_trigger_link_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing);
void nr_mac_reset_link_failure(NR_UE_sched_ctrl_t *sched_ctrl);
bool nr_mac_check_link_failure(gNB_MAC_INST *nrmac, int rnti, NR_UE_sched_ctrl_t *sched_ctrl);
void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE, int new_bwp_id);

View File

@@ -992,7 +992,7 @@ void ue_context_release_command(const f1ap_ue_context_rel_cmd_t *cmd)
if (f1inst >= 0)
newGtpuDeleteAllTunnels(f1inst, cmd->gNB_DU_ue_id);
if (UE->UE_sched_ctrl.ul_failure || !cmd->rrc_container) {
if (UE->UE_sched_ctrl.link_failure || !cmd->rrc_container) {
/* The UE is already not connected anymore or we have nothing to forward*/
nr_mac_release_ue(mac, cmd->gNB_DU_ue_id);
nr_mac_trigger_release_complete(mac, cmd->gNB_DU_ue_id);

View File

@@ -154,7 +154,7 @@ size_t dump_mac_stats(gNB_MAC_INST *gNB, char *output, size_t strlen, bool reset
output = st_append(output, end, "(none)");
}
bool in_sync = !sched_ctrl->ul_failure;
bool in_sync = !sched_ctrl->link_failure;
output = st_append(output,
end,
" %s PH %d dB PCMAX %d dBm",

View File

@@ -658,8 +658,9 @@ typedef struct {
uint16_t ul_rssi;
int pusch_consecutive_dtx_cnt;
int pucch_consecutive_dtx_cnt;
bool ul_failure;
int ul_failure_timer;
bool link_failure;
int link_failure_timer;
int rlc_max_retx_cnt; // count of RLC max RETX events, triggers release at threshold
int release_timer;
struct CSI_Report CSI_report;
bool SR;