Merge remote-tracking branch 'origin/NR_UE_trigger_reestablishment' into integration_2024_w46 (!2777)

NR UE trigger for re-establishment

The implementation in this MR triggers RRC re-establishment at the UE in case
of radio link failure either for out of sync messages from lower layers or in
case maximum number of RLC retransmissions is reached.
This commit is contained in:
Jaroslava Fiedlerova
2024-11-18 10:12:25 +01:00
20 changed files with 283 additions and 104 deletions
+2 -3
View File
@@ -1611,8 +1611,7 @@ static void configure_timeAlignmentTimer(NR_timer_t *time_alignment_timer, NR_Ti
nr_timer_start(time_alignment_timer);
}
void nr_rrc_mac_config_req_reset(module_id_t module_id,
NR_UE_MAC_reset_cause_t cause)
void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t cause)
{
NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
int ret = pthread_mutex_lock(&mac->if_mutex);
@@ -1621,8 +1620,8 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id,
switch (cause) {
case GO_TO_IDLE:
reset_ra(mac, true);
release_mac_configuration(mac, cause);
nr_ue_init_mac(mac);
release_mac_configuration(mac, cause);
nr_ue_mac_default_configs(mac);
// new sync but no target cell id -> -1
nr_ue_send_synch_request(mac, module_id, 0, &sync_req);
+9
View File
@@ -183,6 +183,15 @@ typedef enum {
#undef UE_STATE
} NR_UE_L2_STATE_t;
typedef struct {
pucch_format_nr_t format;
uint8_t startingSymbolIndex;
uint8_t nrofSymbols;
uint16_t PRB_offset;
uint8_t nb_CS_indexes;
uint8_t initial_CS_indexes[MAX_NB_CYCLIC_SHIFT];
} initial_pucch_resource_t;
typedef enum {
GO_TO_IDLE,
DETACH,
+1 -1
View File
@@ -209,7 +209,7 @@ void set_harq_status(NR_UE_MAC_INST_t *mac,
int slot);
bool get_downlink_ack(NR_UE_MAC_INST_t *mac, frame_t frame, int slot, PUCCH_sched_t *pucch);
initial_pucch_resource_t get_initial_pucch_resource(const int idx);
void multiplex_pucch_resource(NR_UE_MAC_INST_t *mac, PUCCH_sched_t *pucch, int num_res);
int16_t get_pucch_tx_power_ue(NR_UE_MAC_INST_t *mac,
+7 -3
View File
@@ -1514,6 +1514,11 @@ void set_harq_status(NR_UE_MAC_INST_t *mac,
current_harq->dai_cumul);
}
initial_pucch_resource_t get_initial_pucch_resource(const int idx)
{
return initial_pucch_resource[idx];
}
int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
int slot,
frame_t frame,
@@ -1534,10 +1539,9 @@ int nr_ue_configure_pucch(NR_UE_MAC_INST_t *mac,
LOG_D(NR_MAC, "initial_pucch_id %d, pucch_resource %p\n", pucch->initial_pucch_id, pucch->pucch_resource);
// configure pucch from Table 9.2.1-1
// only for ack/nack
if (pucch->initial_pucch_id > -1 &&
pucch->pucch_resource == NULL) {
if (pucch->initial_pucch_id > -1 && pucch->pucch_resource == NULL) {
const int idx = *current_UL_BWP->pucch_ConfigCommon->pucch_ResourceCommon;
const initial_pucch_resource_t pucch_resourcecommon = initial_pucch_resource[idx];
const initial_pucch_resource_t pucch_resourcecommon = get_initial_pucch_resource(idx);
pucch_pdu->format_type = pucch_resourcecommon.format;
pucch_pdu->start_symbol_index = pucch_resourcecommon.startingSymbolIndex;
pucch_pdu->nr_of_symbols = pucch_resourcecommon.nrofSymbols;
+60 -42
View File
@@ -1443,13 +1443,16 @@ static void nr_update_sr(NR_UE_MAC_INST_t *mac, bool BSRsent)
// if the UL-SCH resources available for a new transmission do not meet the LCP mapping restrictions
// TODO not implemented
NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
NR_PUCCH_Config_t *pucch_Config = current_UL_BWP ? current_UL_BWP->pucch_Config : NULL;
if (!pucch_Config || !pucch_Config->schedulingRequestResourceToAddModList)
return; // cannot schedule SR if there is no schedulingRequestResource configured
if (lc_info->sr_id < 0 || lc_info->sr_id >= NR_MAX_SR_ID)
LOG_E(NR_MAC, "No SR corresponding to this LCID\n"); // TODO not sure what to do here
else {
nr_sr_info_t *sr = &sched_info->sr_info[lc_info->sr_id];
if (!sr->pending) {
NR_UE_UL_BWP_t *current_UL_BWP = mac->current_UL_BWP;
NR_PUCCH_Config_t *pucch_Config = current_UL_BWP ? current_UL_BWP->pucch_Config : NULL;
if (check_pucchres_for_pending_SR(pucch_Config, lc_info->sr_id)) {
// trigger SR
LOG_D(NR_MAC, "Triggering SR for ID %d\n", lc_info->sr_id);
@@ -2325,7 +2328,11 @@ void build_ssb_to_ro_map(NR_UE_MAC_INST_t *mac)
LOG_D(NR_MAC,"Map SSB to RO done\n");
}
static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac, frame_t frame_tx, int slot_tx, const PUCCH_sched_t *pucch)
static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac,
frame_t frame_tx,
int slot_tx,
const PUCCH_sched_t *pucch,
NR_UE_UL_BWP_t *current_UL_BWP)
{
fapi_nr_ul_config_request_pdu_t *ulcfg_pdu = lockGet_ul_iterator(mac, frame_tx, slot_tx);
if (!ulcfg_pdu)
@@ -2340,29 +2347,37 @@ static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac, frame_t frame_tx, int s
NR_PUCCH_Resource_t *pucchres = pucch->pucch_resource;
int nr_of_symbols = 0;
int start_symbol_index = 0;
switch(pucchres->format.present) {
case NR_PUCCH_Resource__format_PR_format0 :
nr_of_symbols = pucchres->format.choice.format0->nrofSymbols;
start_symbol_index = pucchres->format.choice.format0->startingSymbolIndex;
break;
case NR_PUCCH_Resource__format_PR_format1 :
nr_of_symbols = pucchres->format.choice.format1->nrofSymbols;
start_symbol_index = pucchres->format.choice.format1->startingSymbolIndex;
break;
case NR_PUCCH_Resource__format_PR_format2 :
nr_of_symbols = pucchres->format.choice.format2->nrofSymbols;
start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex;
break;
case NR_PUCCH_Resource__format_PR_format3 :
nr_of_symbols = pucchres->format.choice.format3->nrofSymbols;
start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex;
break;
case NR_PUCCH_Resource__format_PR_format4 :
nr_of_symbols = pucchres->format.choice.format4->nrofSymbols;
start_symbol_index = pucchres->format.choice.format4->startingSymbolIndex;
break;
default :
AssertFatal(false, "Undefined PUCCH format \n");
if (pucch->initial_pucch_id > -1 && pucch->pucch_resource == NULL) {
const int idx = *current_UL_BWP->pucch_ConfigCommon->pucch_ResourceCommon;
const initial_pucch_resource_t pucch_resourcecommon = get_initial_pucch_resource(idx);
start_symbol_index = pucch_resourcecommon.startingSymbolIndex;
nr_of_symbols = pucch_resourcecommon.nrofSymbols;
}
else {
switch(pucchres->format.present) {
case NR_PUCCH_Resource__format_PR_format0 :
nr_of_symbols = pucchres->format.choice.format0->nrofSymbols;
start_symbol_index = pucchres->format.choice.format0->startingSymbolIndex;
break;
case NR_PUCCH_Resource__format_PR_format1 :
nr_of_symbols = pucchres->format.choice.format1->nrofSymbols;
start_symbol_index = pucchres->format.choice.format1->startingSymbolIndex;
break;
case NR_PUCCH_Resource__format_PR_format2 :
nr_of_symbols = pucchres->format.choice.format2->nrofSymbols;
start_symbol_index = pucchres->format.choice.format2->startingSymbolIndex;
break;
case NR_PUCCH_Resource__format_PR_format3 :
nr_of_symbols = pucchres->format.choice.format3->nrofSymbols;
start_symbol_index = pucchres->format.choice.format3->startingSymbolIndex;
break;
case NR_PUCCH_Resource__format_PR_format4 :
nr_of_symbols = pucchres->format.choice.format4->nrofSymbols;
start_symbol_index = pucchres->format.choice.format4->startingSymbolIndex;
break;
default :
AssertFatal(false, "Undefined PUCCH format \n");
}
}
int final_symbol = nr_of_symbols + start_symbol_index;
// PUCCH overlapping in time with PUSCH
@@ -2393,22 +2408,25 @@ static bool schedule_uci_on_pusch(NR_UE_MAC_INST_t *mac, frame_t frame_tx, int s
// and does not transmit the PUCCH if the UE does not multiplex aperiodic or semi-persistent CSI reports in the PUSCH
bool mux_done = false;
if (pucch->n_harq > 0) {
pusch_pdu->pusch_uci.harq_ack_bit_length = pucch->n_harq;
pusch_pdu->pusch_uci.harq_payload = pucch->ack_payload;
NR_PUSCH_Config_t *pusch_Config = mac->current_UL_BWP->pusch_Config;
AssertFatal(pusch_Config && pusch_Config->uci_OnPUSCH, "UCI on PUSCH need to be configured\n");
NR_UCI_OnPUSCH_t *onPusch = pusch_Config->uci_OnPUSCH->choice.setup;
AssertFatal(onPusch &&
onPusch->betaOffsets &&
onPusch->betaOffsets->present == NR_UCI_OnPUSCH__betaOffsets_PR_semiStatic,
"Only semistatic beta offset is supported\n");
NR_BetaOffsets_t *beta_offsets = onPusch->betaOffsets->choice.semiStatic;
pusch_pdu->pusch_uci.beta_offset_harq_ack = pucch->n_harq > 2 ?
(pucch->n_harq < 12 ? *beta_offsets->betaOffsetACK_Index2 :
*beta_offsets->betaOffsetACK_Index3) :
*beta_offsets->betaOffsetACK_Index1;
pusch_pdu->pusch_uci.alpha_scaling = onPusch->scaling;
mux_done = true;
if (pusch_Config && pusch_Config->uci_OnPUSCH) {
NR_UCI_OnPUSCH_t *onPusch = pusch_Config->uci_OnPUSCH->choice.setup;
AssertFatal(onPusch &&
onPusch->betaOffsets &&
onPusch->betaOffsets->present == NR_UCI_OnPUSCH__betaOffsets_PR_semiStatic,
"Only semistatic beta offset is supported\n");
NR_BetaOffsets_t *beta_offsets = onPusch->betaOffsets->choice.semiStatic;
pusch_pdu->pusch_uci.harq_ack_bit_length = pucch->n_harq;
pusch_pdu->pusch_uci.harq_payload = pucch->ack_payload;
pusch_pdu->pusch_uci.beta_offset_harq_ack = pucch->n_harq > 2 ?
(pucch->n_harq < 12 ? *beta_offsets->betaOffsetACK_Index2 :
*beta_offsets->betaOffsetACK_Index3) :
*beta_offsets->betaOffsetACK_Index1;
pusch_pdu->pusch_uci.alpha_scaling = onPusch->scaling;
mux_done = true;
} else {
LOG_E(NR_MAC, "UCI on PUSCH need to be configured to schedule UCI on PUSCH\n");
}
}
if (pusch_pdu->pusch_uci.csi_part1_bit_length == 0 && pusch_pdu->pusch_uci.csi_part2_bit_length == 0) {
// To support this we would need to shift some bits into CSI part2 -> need to change the logic
@@ -2471,7 +2489,7 @@ void nr_ue_pucch_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, int slotP)
mac->nr_ue_emul_l1.num_csi_reports = pucch[j].n_csi;
// checking if we need to schedule pucch[j] on PUSCH
if (schedule_uci_on_pusch(mac, frameP, slotP, &pucch[j]))
if (schedule_uci_on_pusch(mac, frameP, slotP, &pucch[j], mac->current_UL_BWP))
continue;
fapi_nr_ul_config_request_pdu_t *pdu = lockGet_ul_config(mac, frameP, slotP, FAPI_NR_UL_CONFIG_TYPE_PUCCH);
+30 -24
View File
@@ -114,14 +114,19 @@ logical_chan_id_t nr_rlc_get_lcid_from_rb(int ue_id, bool is_srb, int rb_id)
for (logical_chan_id_t id = 1; id <= 32; id++) {
nr_rlc_rb_t *rb = &ue->lcid2rb[id - 1];
if (is_srb) {
if (rb->type == NR_RLC_SRB && rb->choice.srb_id == rb_id)
if (rb->type == NR_RLC_SRB && rb->choice.srb_id == rb_id) {
nr_rlc_manager_unlock(nr_rlc_ue_manager);
return id;
}
} else {
if (rb->type == NR_RLC_DRB && rb->choice.drb_id == rb_id)
if (rb->type == NR_RLC_DRB && rb->choice.drb_id == rb_id) {
nr_rlc_manager_unlock(nr_rlc_ue_manager);
return id;
}
}
}
LOG_E(RLC, "Couldn't find LCID corresponding to %s %d\n", is_srb ? "SRB" : "DRB", rb_id);
nr_rlc_manager_unlock(nr_rlc_ue_manager);
return 0;
}
@@ -614,10 +619,6 @@ static void max_retx_reached(void *_ue, nr_rlc_entity_t *entity)
int i;
int is_srb;
int rb_id;
#if 0
MessageDef *msg;
#endif
int is_enb;
/* is it SRB? */
for (i = 0; i < 2; i++) {
@@ -645,23 +646,18 @@ rb_found:
is_srb ? "SRB" : "DRB",
rb_id);
/* TODO: do something for DRBs? */
if (is_srb == 0)
return;
if (ue->rlf_handler)
ue->rlf_handler(ue->ue_id);
else
LOG_W(RLC, "UE %04x: RLF detected, but no callable RLF handler registered\n", ue->ue_id);
}
is_enb = nr_rlc_manager_get_enb_flag(nr_rlc_ue_manager);
if (!is_enb)
return;
#if 0
msg = itti_alloc_new_message(TASK_RLC_ENB, RLC_SDU_INDICATION);
RLC_SDU_INDICATION(msg).rnti = ue->rnti;
RLC_SDU_INDICATION(msg).is_successful = 0;
RLC_SDU_INDICATION(msg).srb_id = rb_id;
RLC_SDU_INDICATION(msg).message_id = -1;
/* TODO: accept more than 1 instance? here we send to instance id 0 */
itti_send_msg_to_task(TASK_RRC_ENB, 0, msg);
#endif
void nr_rlc_set_rlf_handler(int ue_id, rlf_handler_t rlf_h)
{
nr_rlc_manager_lock(nr_rlc_ue_manager);
nr_rlc_ue_t *ue = nr_rlc_manager_get_ue(nr_rlc_ue_manager, ue_id);
ue->rlf_handler = rlf_h;
nr_rlc_manager_unlock(nr_rlc_ue_manager);
}
void nr_rlc_reestablish_entity(int ue_id, int lc_id)
@@ -671,6 +667,7 @@ void nr_rlc_reestablish_entity(int ue_id, int lc_id)
if (ue == NULL) {
LOG_E(RLC, "RLC instance for the given UE was not found \n");
nr_rlc_manager_unlock(nr_rlc_ue_manager);
return;
}
nr_rlc_entity_t *rb = get_rlc_entity_from_lcid(ue, lc_id);
@@ -1099,8 +1096,14 @@ bool nr_rlc_update_id(int from_id, int to_id)
return true;
}
/* This function is for testing purposes. At least on a COTS UE, it will
* trigger a reestablishment. */
/**
* @brief This function is for testing purposes.
* Re-establishment is triggered by resetting RLC counters of the bearer,
* which leads to UE reaching maximum RLC retransmissions, RLF detection
* and RRC triggering re-sync. It is assumed that there is ongoing traffic on the bearer.
* - With COTS UEs, triggers re-establishment on SRB 1, where periodical measurement reports are sent.
* - With OAI UE, triggers re-establishment on DRB 1, assuming there is ongoing data traffic.
*/
void nr_rlc_test_trigger_reestablishment(int ue_id)
{
nr_rlc_manager_lock(nr_rlc_ue_manager);
@@ -1114,6 +1117,9 @@ void nr_rlc_test_trigger_reestablishment(int ue_id)
* as the UE context is created. */
nr_rlc_entity_t *ent = ue->srb[0];
ent->reestablishment(ent);
/* Trigger re-establishment on OAI UE */
nr_rlc_entity_t *drb = ue->drb[0];
drb->reestablishment(drb);
nr_rlc_manager_unlock(nr_rlc_ue_manager);
}
+2
View File
@@ -44,6 +44,8 @@ struct NR_LogicalChannelConfig;
void nr_rlc_add_srb(int ue_id, int srb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig);
void nr_rlc_add_drb(int ue_id, int drb_id, const NR_RLC_BearerConfig_t *rlc_BearerConfig);
void nr_rlc_set_rlf_handler(int ue_id, rlf_handler_t rlf_h);
logical_chan_id_t nr_rlc_get_lcid_from_rb(int ue_id, bool is_srb, int rb_id);
void nr_rlc_reestablish_entity(int ue_id, int lc_id);
void nr_rlc_remove_ue(int ue_id);
@@ -37,12 +37,15 @@ typedef struct nr_rlc_rb_t {
} choice;
} nr_rlc_rb_t;
typedef void (*rlf_handler_t)(int rnti);
typedef struct nr_rlc_ue_t {
int ue_id;
nr_rlc_entity_t *srb0;
nr_rlc_entity_t *srb[3];
nr_rlc_entity_t *drb[MAX_DRBS_PER_UE];
nr_rlc_rb_t lcid2rb[32];
rlf_handler_t rlf_handler;
} nr_rlc_ue_t;
/***********************************************************************/