Commit 5c6d90aa authored by Robert Schmidt's avatar Robert Schmidt

Use NR_timer_t for UE transmission interrupt, e.g., RRC processing

Refactor the RRC processing timer to be a generic "transmission
interrupt" timer, and use NR_timer_t for it. Also,
depending on the kind of RRC processing (see 38.331 table 12.1-1),
timing requirements might be different. However, the DU does not always
know which RRC processing is ongoing, and does not get this information
via F1. Hence, introduce a "worst case" delay time, which aligns with
the spec (it says these times are "minima") and is accepted by COTS UE.

The gNB MAC might need to stop transmission either for some time (RRC
processing), or continuously (transmission stop requested by CU). Those
can be handled in one common timer implementation. The continuous case
will be used in a follow-up commit.
Co-authored-by: default avatarLuis Pereira <lpereira@allbesmart.pt>
parent 2c07f008
......@@ -844,9 +844,9 @@ bool nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig
/* 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 timer with nr_mac_enable_ue_rrc_processing_timer(); upon
* expiry nr_mac_apply_cellgroup() will apply the CellGroupConfig (radio config
* etc). */
* 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);
......
......@@ -1698,12 +1698,8 @@ static void nr_generate_Msg2(module_id_t module_idP,
if (ra->cfra) {
NR_UE_info_t *UE = find_nr_UE(&RC.nrmac[module_idP]->UE_info, ra->rnti);
if (UE) {
const NR_ServingCellConfig_t *servingCellConfig = UE->CellGroup ? UE->CellGroup->spCellConfig->spCellConfigDedicated : NULL;
uint32_t delay_ms = servingCellConfig && servingCellConfig->downlinkBWP_ToAddModList
? NR_RRC_SETUP_DELAY_MS + NR_RRC_BWP_SWITCHING_DELAY_MS
: NR_RRC_SETUP_DELAY_MS;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
sched_ctrl->rrc_processing_timer = (delay_ms << ra->DL_BWP.scs);
int delay = nr_mac_get_reconfig_delay_slots(ra->DL_BWP.scs);
nr_mac_interrupt_ue_transmission(RC.nrmac[module_idP], UE, FOLLOW_INSYNC, delay);
}
}
......@@ -2248,8 +2244,9 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP,
// 3GPP TS 38.331 Section 12 Table 12.1-1: UE performance requirements for RRC procedures for UEs
// Msg4 may transmit a RRCReconfiguration, for example when UE sends RRCReestablishmentComplete and MAC CE for C-RNTI in Msg3.
// In that case, gNB will generate a RRCReconfiguration that will be transmitted in Msg4, so we need to apply CellGroup after the Ack,
// UE->apply_cellgroup was already set when processing RRCReestablishment message
nr_mac_enable_ue_rrc_processing_timer(nr_mac, UE, UE->apply_cellgroup);
// UE->reconfigCellGroup was already set when processing RRCReestablishment message
int delay = nr_mac_get_reconfig_delay_slots(UE->current_UL_BWP.scs);
nr_mac_interrupt_ue_transmission(nr_mac, UE, UE->interrupt_action, delay);
nr_clear_ra_proc(ra);
} else {
......@@ -2291,8 +2288,9 @@ static void nr_check_Msg4_MsgB_Ack(module_id_t module_id, int CC_id, frame_t fra
// 3GPP TS 38.331 Section 12 Table 12.1-1: UE performance requirements for RRC procedures for UEs
// Msg4 may transmit a RRCReconfiguration, for example when UE sends RRCReestablishmentComplete and MAC CE for C-RNTI in Msg3.
// In that case, gNB will generate a RRCReconfiguration that will be transmitted in Msg4, so we need to apply CellGroup after the Ack,
// UE->apply_cellgroup was already set when processing RRCReestablishment message
nr_mac_enable_ue_rrc_processing_timer(RC.nrmac[module_id], UE, UE->apply_cellgroup);
// UE->reconfigCellGroup already set when processing RRCReestablishment message
int delay = nr_mac_get_reconfig_delay_slots(UE->current_UL_BWP.scs);
nr_mac_interrupt_ue_transmission(RC.nrmac[module_id], UE, UE->interrupt_action, delay);
nr_clear_ra_proc(ra);
if (sched_ctrl->retrans_dl_harq.head >= 0) {
......
......@@ -334,9 +334,8 @@ static void nr_store_dlsch_buffer(module_id_t module_id, frame_t frame, sub_fram
const int lcid = c->lcid;
const uint16_t rnti = UE->rnti;
LOG_D(NR_MAC, "In %s: UE %x: LCID %d\n", __FUNCTION__, rnti, lcid);
if (lcid == DL_SCH_LCID_DTCH && sched_ctrl->rrc_processing_timer > 0) {
if (lcid == DL_SCH_LCID_DTCH && nr_timer_is_active(&sched_ctrl->transm_interrupt))
continue;
}
start_meas(&RC.nrmac[module_id]->rlc_status_ind);
sched_ctrl->rlc_status[lcid] = mac_rlc_status_ind(module_id,
rnti,
......@@ -985,7 +984,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
* Possible improvement: take the periodicity from input file.
* If such UE is not scheduled now, it will be by the preprocessor later.
* If we add the CE, ta_apply will be reset */
if (frame == (sched_ctrl->ta_frame + 100) % 1024) {
if (frame == ((sched_ctrl->ta_frame + 100) % 1024) && !nr_timer_is_active(&sched_ctrl->transm_interrupt)) {
sched_ctrl->ta_apply = true; /* the timer is reset once TA CE is scheduled */
LOG_D(NR_MAC, "[UE %04x][%d.%d] UL timing alignment procedures: setting flag for Timing Advance command\n", UE->rnti, frame, slot);
}
......
......@@ -2733,9 +2733,8 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo
if (UE_info->sched_csirs & (1 << dl_bwp->bwp_id))
continue;
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
if (sched_ctrl->rrc_processing_timer > 0) {
if (nr_timer_is_active(&sched_ctrl->transm_interrupt))
continue;
}
if (!UE->sc_info.csi_MeasConfig)
continue;
......@@ -2951,15 +2950,15 @@ void nr_csirs_scheduling(int Mod_idP, frame_t frame, sub_frame_t slot, int n_slo
static void nr_mac_apply_cellgroup(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t frame, sub_frame_t slot)
{
LOG_D(NR_MAC, "%4d.%2d RNTI %04x: RRC processing timer expired\n", frame, slot, UE->rnti);
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->apply_cellgroup && UE->reconfigCellGroup != NULL) {
LOG_D(NR_MAC, "%4d.%2d RNTI %04x: Apply CellGroupConfig after RRC processing timer expiry\n", frame, slot, UE->rnti);
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->apply_cellgroup = false;
UE->interrupt_action = FOLLOW_INSYNC;
if (LOG_DEBUGFLAG(DEBUG_ASN1))
xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void *)UE->CellGroup);
......@@ -2987,31 +2986,34 @@ static void nr_mac_apply_cellgroup(gNB_MAC_INST *mac, NR_UE_info_t *UE, frame_t
}
}
int nr_mac_enable_ue_rrc_processing_timer(gNB_MAC_INST *mac, NR_UE_info_t *UE, bool apply_cellgroup)
int nr_mac_get_reconfig_delay_slots(NR_SubcarrierSpacing_t scs)
{
/* we previously assumed a specific "slot ahead" value for the PHY processing
* time. However, we cannot always know it (e.g., third-party PHY), so simply
* assume a tentative worst-case slot processing time */
const uint16_t sl_ahead = 10;
/* 16ms seems to be the most common: See 38.331 Tab 12.1-1 */
int delay_ms = NR_RRC_RECONFIGURATION_DELAY_MS + NR_RRC_BWP_SWITCHING_DELAY_MS;
return (delay_ms << scs) + sl_ahead;
}
int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, interrupt_followup_action_t action, int slots)
{
DevAssert(mac != NULL);
DevAssert(UE != NULL);
NR_SCHED_ENSURE_LOCKED(&mac->sched_lock);
const uint16_t sl_ahead = mac->if_inst->sl_ahead;
// TODO: account for BWP switch with NR_RRC_BWP_SWITCHING_DELAY_MS
int delay = NR_RRC_RECONFIGURATION_DELAY_MS;
NR_SubcarrierSpacing_t scs = UE->current_UL_BWP.scs;
UE->UE_sched_ctrl.rrc_processing_timer = (delay << scs) + sl_ahead;
UE->apply_cellgroup = apply_cellgroup;
AssertFatal(!UE->apply_cellgroup || (UE->apply_cellgroup && UE->reconfigCellGroup),
"logic bug: apply_cellgroup %d and UE->reconfigCellGroup %p: did you try to apply a cellGroup, while none is deposited?\n",
UE->apply_cellgroup,
UE->reconfigCellGroup);
nr_timer_setup(&UE->UE_sched_ctrl.transm_interrupt, slots, 1);
nr_timer_start(&UE->UE_sched_ctrl.transm_interrupt);
UE->interrupt_action = action;
// it might happen that timing advance command should be sent during the RRC
// processing timer. To prevent this, set a variable as if we would have just
// it might happen that timing advance command should be sent during the UE
// inactivity time. To prevent this, set a variable as if we would have just
// sent it. This way, another TA command will for sure be sent in some
// frames, after RRC processing timer.
// frames, after the inactivity of the UE.
UE->UE_sched_ctrl.ta_frame = (mac->frame - 1 + 1024) % 1024;
LOG_D(NR_MAC, "UE %04x: Activate RRC processing timer (%d ms)\n", UE->rnti, delay);
LOG_D(NR_MAC, "UE %04x: Interrupt UE transmission (%d slots) action %d reconfigCellGroup %p\n", UE->rnti, slots, UE->interrupt_action, UE->reconfigCellGroup);
return 0;
}
......@@ -3073,10 +3075,10 @@ void nr_mac_update_timers(module_id_t module_id,
/* check if UL failure and trigger release request if necessary */
nr_mac_check_ul_failure(mac, UE->rnti, sched_ctrl);
if (sched_ctrl->rrc_processing_timer > 0) {
sched_ctrl->rrc_processing_timer--;
if (sched_ctrl->rrc_processing_timer == 0)
nr_mac_apply_cellgroup(mac, UE, frame, slot);
if (nr_timer_tick(&sched_ctrl->transm_interrupt)) {
/* expired */
nr_timer_stop(&sched_ctrl->transm_interrupt);
nr_mac_apply_cellgroup(mac, UE, frame, slot);
}
}
}
......
......@@ -533,7 +533,7 @@ void nr_schedule_srs(int module_id, frame_t frame, int slot)
sched_ctrl->sched_srs.srs_scheduled = false;
}
if ((sched_ctrl->ul_failure && !get_softmodem_params()->phy_test) || sched_ctrl->rrc_processing_timer > 0) {
if ((sched_ctrl->ul_failure && !get_softmodem_params()->phy_test) || nr_timer_is_active(&sched_ctrl->transm_interrupt)) {
continue;
}
......
......@@ -223,7 +223,7 @@ void nr_csi_meas_reporting(int Mod_idP,
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 = nr_slots_per_frame[ul_bwp->scs];
if ((sched_ctrl->rrc_processing_timer > 0) || (sched_ctrl->ul_failure && !get_softmodem_params()->phy_test)) {
if (nr_timer_is_active(&sched_ctrl->transm_interrupt) || (sched_ctrl->ul_failure && !get_softmodem_params()->phy_test)) {
continue;
}
const NR_CSI_MeasConfig_t *csi_measconfig = UE->sc_info.csi_MeasConfig;
......@@ -1389,7 +1389,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot)
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 = nr_slots_per_frame[ul_bwp->scs];
if (sched_ctrl->ul_failure || sched_ctrl->rrc_processing_timer > 0)
if (sched_ctrl->ul_failure || nr_timer_is_active(&sched_ctrl->transm_interrupt))
continue;
NR_PUCCH_Config_t *pucch_Config = ul_bwp->pucch_Config;
......
......@@ -1856,7 +1856,7 @@ static void pf_ul(module_id_t module_id,
const bool do_sched = nr_UE_is_to_be_scheduled(scc, 0, UE, sched_pusch->frame, sched_pusch->slot, nrmac->ulsch_max_frame_inactivity);
LOG_D(NR_MAC,"pf_ul: do_sched UE %04x => %s\n",UE->rnti,do_sched ? "yes" : "no");
if ((B == 0 && !do_sched) || (sched_ctrl->rrc_processing_timer > 0)) {
if ((B == 0 && !do_sched) || nr_timer_is_active(&sched_ctrl->transm_interrupt)) {
continue;
}
......
......@@ -53,8 +53,10 @@ void nr_mac_configure_sib19(gNB_MAC_INST *nrmac);
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);
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_enable_ue_rrc_processing_timer(gNB_MAC_INST *mac, NR_UE_info_t *UE, bool apply_cellGroup);
int nr_mac_interrupt_ue_transmission(gNB_MAC_INST *mac, NR_UE_info_t *UE, interrupt_followup_action_t action, int slots);
void clear_nr_nfapi_information(gNB_MAC_INST *gNB,
int CC_idP,
......
......@@ -728,7 +728,8 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
* 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);
nr_mac_enable_ue_rrc_processing_timer(mac, UE, /* apply_cellGroup = */ true);
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 */
......
......@@ -43,6 +43,7 @@
#include <string.h>
#include <pthread.h>
#include "common/utils/ds/seq_arr.h"
#include "common/utils/nr/nr_common.h"
#define NR_SCHED_LOCK(lock) \
do { \
......@@ -664,8 +665,8 @@ typedef struct {
NR_list_t retrans_ul_harq;
NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl; // MAC CE related information
/// Timer for RRC processing procedures
uint32_t rrc_processing_timer;
/// Timer for RRC processing procedures and transmission activity
NR_timer_t transm_interrupt;
/// sri, ul_ri and tpmi based on SRS
nr_srs_feedback_t srs_feedback;
......@@ -738,6 +739,8 @@ typedef struct nr_mac_rrc_ul_if_s {
initial_ul_rrc_message_transfer_func_t initial_ul_rrc_message_transfer;
} nr_mac_rrc_ul_if_t;
typedef enum interrupt_followup_action { FOLLOW_INSYNC, FOLLOW_INSYNC_RECONFIG } interrupt_followup_action_t;
/*! \brief UE list used by gNB to order UEs/CC for scheduling*/
typedef struct {
rnti_t rnti;
......@@ -756,7 +759,7 @@ typedef struct {
/// reestablishRLC has to be signaled in RRCreconfiguration
bool reestablish_rlc;
NR_CellGroupConfig_t *reconfigCellGroup;
bool apply_cellgroup;
interrupt_followup_action_t interrupt_action;
NR_UE_NR_Capability_t *capability;
// UE selected beam index
uint8_t UE_beam_index;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment