Commit 12f29b82 authored by Jaroslava Fiedlerova's avatar Jaroslava Fiedlerova

Merge remote-tracking branch 'origin/NR_UE_trigger_reestablishment' into...

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.
parents 9b1ccbf3 6b3f26f5
......@@ -34,6 +34,11 @@
030020
030021
030022
040001
020022
040002
030021
030022
100021
222222
</TestCaseRequestedList>
......@@ -117,11 +122,36 @@
<iperf_bitrate_threshold>90</iperf_bitrate_threshold>
</testCase>
<testCase id="040001">
<class>Custom_Command</class>
<desc>Trigger Reestablishment</desc>
<node>cacofonix</node>
<command>echo ci force_reestab | nc 192.168.71.171 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment'</command>
<command_fail>yes</command_fail>
</testCase>
<testCase id="020022">
<class>Ping</class>
<desc>Ping ext-dn from all NR-UEs</desc>
<id>rfsim5g_ue</id>
<nodes>cacofonix</nodes>
<ping_args> -c 20 192.168.72.135 -i0.5 -w25</ping_args>
<ping_packetloss_threshold>80</ping_packetloss_threshold>
</testCase>
<testCase id="040002">
<class>Custom_Command</class>
<desc>Verify Reestablishment</desc>
<node>cacofonix</node>
<command>echo ci get_reestab_count | nc 192.168.71.150 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1'</command>
<command_fail>yes</command_fail>
</testCase>
<testCase id="040021">
<class>Custom_Command</class>
<desc>Simulate a disruption of DL radio channel (ploss 55)(5 sec)</desc>
<node>cacofonix</node>
<command>echo channelmod modify 0 ploss 55 | nc -N 192.168.71.181 8091 &amp;&amp; sleep 5</command>
<command>echo channelmod modify 0 ploss 55 | nc 192.168.71.181 8091 &amp;&amp; sleep 5</command>
<command_fail>yes</command_fail>
</testCase>
......@@ -129,7 +159,7 @@
<class>Custom_Command</class>
<desc>Get UE sync state (UE ID 0)</desc>
<node>cacofonix</node>
<command>echo ciUE sync_state 0 | nc -N 192.168.71.181 8091 | grep -E UE_NOT_SYNC</command>
<command>echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_NOT_SYNC</command>
<command_fail>yes</command_fail>
</testCase>
......@@ -137,7 +167,7 @@
<class>Custom_Command</class>
<desc>Restoration of the original DL channel conditions (ploss 0)(5 sec)</desc>
<node>cacofonix</node>
<command>echo channelmod modify 0 ploss 0 | nc -N 192.168.71.181 8091 &amp;&amp; sleep 5</command>
<command>echo channelmod modify 0 ploss 0 | nc 192.168.71.181 8091 &amp;&amp; sleep 5</command>
<command_fail>yes</command_fail>
</testCase>
......@@ -145,7 +175,7 @@
<class>Custom_Command</class>
<desc>Get UE sync state (UE ID 0)</desc>
<node>cacofonix</node>
<command>echo ciUE sync_state 0 | nc -N 192.168.71.181 8091 | grep -E UE_CONNECTED &amp;&amp; sleep 10</command>
<command>echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_CONNECTED &amp;&amp; sleep 10</command>
<command_fail>yes</command_fail>
</testCase>
......
......@@ -87,9 +87,12 @@ services:
container_name: rfsim5g-oai-cu
cap_drop:
- ALL
environment:
environment:
USE_ADDITIONAL_OPTIONS: --log_config.global_log_options level,nocolor,time
ASAN_OPTIONS: detect_leaks=0
--rfsimulator.options chanmod
--telnetsrv --telnetsrv.listenaddr 192.168.71.150
--telnetsrv.shrmod ci
ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0
depends_on:
- oai-ext-dn
networks:
......@@ -113,6 +116,7 @@ services:
--log_config.global_log_options level,nocolor,time
--rfsimulator.options chanmod
--telnetsrv --telnetsrv.listenaddr 192.168.71.171
--telnetsrv.shrmod ci
ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0
depends_on:
- oai-cu
......
......@@ -67,6 +67,12 @@ static telnetsrv_params_t telnetparams;
#define TELNETSRV_OPTNAME_STATICMOD "staticmod"
#define TELNETSRV_OPTNAME_SHRMOD "shrmod"
#define TELNET_LOG(fmt, ...) \
do { \
printf("[TELNETSRV] " fmt __VA_OPT__(, ) __VA_ARGS__); \
fflush(stdout); \
} while (0)
// clang-format off
paramdef_t telnetoptions[] = {
/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
......@@ -653,10 +659,10 @@ void run_telnetsrv(void) {
using_history();
int plen=sprintf(prompt,"%s_%s> ",TELNET_PROMPT_PREFIX,get_softmodem_function(NULL));
printf("\nInitializing telnet server...\n");
TELNET_LOG("\nInitializing telnet server...\n");
while( (telnetparams.new_socket = accept(sock, &cli_addr, &cli_len)) ) {
printf("[TELNETSRV] Telnet client connected....\n");
TELNET_LOG("Telnet client connected....\n");
read_history(telnetparams.histfile);
stifle_history(telnetparams.histsize);
......@@ -682,12 +688,12 @@ void run_telnetsrv(void) {
}
if(!readc) {
printf ("[TELNETSRV] Telnet Client disconnected.\n");
TELNET_LOG("Telnet Client disconnected.\n");
break;
}
if (telnetparams.telnetdbg > 0)
printf("[TELNETSRV] Command received: readc %i filled %i \"%s\"\n", readc, filled,buf);
TELNET_LOG("Command received: readc %i filled %i \"%s\"\n", readc, filled, buf);
if (buf[0] == '!') {
if (buf[1] == '!') {
......@@ -720,7 +726,7 @@ void run_telnetsrv(void) {
send(telnetparams.new_socket, prompt, strlen(prompt), MSG_NOSIGNAL);
} else {
printf ("[TELNETSRV] Closing telnet connection...\n");
TELNET_LOG("Closing telnet connection...\n");
break;
}
}
......@@ -728,7 +734,7 @@ void run_telnetsrv(void) {
write_history(telnetparams.histfile);
clear_history();
close(telnetparams.new_socket);
printf ("[TELNETSRV] Telnet server waitting for connection...\n");
TELNET_LOG("Telnet server waiting for connection...\n");
}
close(sock);
......@@ -927,7 +933,7 @@ int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmdde
cmd[j].qptr = afifo;
}
}
printf("[TELNETSRV] Telnet server: module %i = %s added to shell\n", i, telnetparams.CmdParsers[i].module);
TELNET_LOG("Telnet server: module %i = %s added to shell\n", i, telnetparams.CmdParsers[i].module);
break;
}
}
......
......@@ -37,6 +37,7 @@
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_entity_am.h"
#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
#define TELNETSERVERCODE
#include "telnetsrv.h"
......@@ -115,10 +116,8 @@ int get_reestab_count(char *buf, int debug, telnet_printfunc_t prnt)
return 0;
}
int trigger_reestab(char *buf, int debug, telnet_printfunc_t prnt)
int fetch_rnti(char *buf, telnet_printfunc_t prnt)
{
if (!RC.nrmac)
ERROR_MSG_RET("no MAC/RLC present, cannot trigger reestablishment\n");
int rnti = -1;
if (!buf) {
rnti = get_single_ue_rnti_mac();
......@@ -129,9 +128,15 @@ int trigger_reestab(char *buf, int debug, telnet_printfunc_t prnt)
if (rnti < 1 || rnti >= 0xfffe)
ERROR_MSG_RET("RNTI needs to be [1,0xfffe]\n");
}
return rnti;
}
int trigger_reestab(char *buf, int debug, telnet_printfunc_t prnt)
{
if (!RC.nrmac)
ERROR_MSG_RET("no MAC/RLC present, cannot trigger reestablishment\n");
int rnti = fetch_rnti(buf, prnt);
nr_rlc_test_trigger_reestablishment(rnti);
prnt("Reset RLC counters of UE RNTI %04x to trigger reestablishment\n", rnti);
return 0;
}
......@@ -163,7 +168,27 @@ int rrc_gNB_trigger_f1_ho(char *buf, int debug, telnet_printfunc_t prnt)
gNB_RRC_UE_t *UE = &ue->ue_context;
nr_HO_F1_trigger_telnet(RC.nrrrc[0], UE->rrc_ue_id);
prnt("RRC F1 handover triggered for UE %u\n", UE->rrc_ue_id);
return 0;
}
int force_ul_failure(char *buf, int debug, telnet_printfunc_t prnt)
{
if (!RC.nrmac)
ERROR_MSG_RET("no MAC/RLC present, force_ul_failure failed\n");
int rnti = fetch_rnti(buf, prnt);
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);
return 0;
}
int force_ue_release(char *buf, int debug, telnet_printfunc_t prnt)
{
force_ul_failure(buf, debug, prnt);
int rnti = fetch_rnti(buf, prnt);
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);
return 0;
}
......@@ -171,6 +196,8 @@ static telnetshell_cmddef_t cicmds[] = {
{"get_single_rnti", "", get_single_rnti},
{"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},
{"trigger_f1_ho", "[rrc_ue_id(int,opt)]", rrc_gNB_trigger_f1_ho},
{"", "", NULL},
};
......
......@@ -36,6 +36,7 @@
#include <stdarg.h>
#include "openair2/LAYER2/NR_MAC_UE/mac_defs.h"
#include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
#include "openair2/RRC/NR_UE/rrc_proto.h"
#define TELNETSERVERCODE
#include "telnetsrv.h"
......@@ -73,9 +74,31 @@ int get_sync_state(char *buf, int debug, telnet_printfunc_t prnt)
return 0;
}
/**
* Force RLF on UE
*/
int force_rlf(char *buf, int debug, telnet_printfunc_t prnt)
{
NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(0);
handle_rlf_detection(rrc);
return 0;
}
/**
* Send UE to RRC_IDLE
*/
int force_RRC_IDLE(char *buf, int debug, telnet_printfunc_t prnt)
{
NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(0);
nr_rrc_going_to_IDLE(rrc, OTHER, NULL);
return 0;
}
/* Telnet shell command definitions */
static telnetshell_cmddef_t cicmds[] = {
{"sync_state", "[UE_ID(int,opt)]", get_sync_state},
{"force_rlf", "", force_rlf},
{"force_RRC_IDLE", "", force_RRC_IDLE},
{"", "", NULL},
};
......
......@@ -607,7 +607,13 @@ static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *proc
if (UE->synch_request.received_synch_request == 1) {
fapi_nr_synch_request_t *synch_req = &UE->synch_request.synch_req;
UE->is_synchronized = 0;
UE->UE_scan_carrier = synch_req->ssb_bw_scan;
// if upper layers signal BW scan we do as instructed by command line parameter
// if upper layers disable BW scan we set it to false
if (UE->synch_request.synch_req.ssb_bw_scan)
UE->UE_scan_carrier = get_nrUE_params()->UE_scan_carrier;
else
UE->UE_scan_carrier = false;
UE->target_Nid_cell = UE->synch_request.synch_req.target_Nid_cell;
UE->target_Nid_cell = synch_req->target_Nid_cell;
uint64_t dl_bw = (12 * fp->N_RB_DL) * (15000 << fp->numerology_index);
......
......@@ -487,16 +487,6 @@ typedef enum {
reserved = 7
} PUCCH_MaxCodeRate_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;
/***********************************************************************
*
* FUNCTIONALITY : Scheduling Request Configuration (SR)
......
......@@ -85,3 +85,6 @@ MESSAGE_DEF(NRRRC_FRAME_PROCESS, MESSAGE_PRIORITY_MED, NRRrcFramePr
// eNB: RLC -> RRC messages
MESSAGE_DEF(RLC_SDU_INDICATION, MESSAGE_PRIORITY_MED, RlcSduIndication, rlc_sdu_indication)
MESSAGE_DEF(NAS_PDU_SESSION_REQ, MESSAGE_PRIORITY_MED, nas_pdu_session_req_t, nas_pdu_session_req)
// UE: RLC -> RRC messages
MESSAGE_DEF(NR_RRC_RLC_MAXRTX, MESSAGE_PRIORITY_MED, RlcMaxRtxIndication, nr_rlc_maxrtx_indication)
......@@ -97,6 +97,8 @@
#define NAS_OAI_TUN_NSA(mSGpTR) (mSGpTR)->ittiMsg.nas_oai_tun_nsa
#define NAS_PDU_SESSION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nas_pdu_session_req
#define NR_RRC_RLC_MAXRTX(mSGpTR) (mSGpTR)->ittiMsg.nr_rlc_maxrtx_indication
//-------------------------------------------------------------------------------------------//
typedef struct RrcStateInd_s {
Rrc_State_t state;
......@@ -453,4 +455,8 @@ typedef struct rlc_sdu_indication_s {
int message_id;
} RlcSduIndication;
typedef struct {
int ue_id;
} RlcMaxRtxIndication;
#endif /* RRC_MESSAGES_TYPES_H_ */
......@@ -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);
......
......@@ -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,
......
......@@ -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,
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
is_enb = nr_rlc_manager_get_enb_flag(nr_rlc_ue_manager);
if (!is_enb)
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);
}
#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);
}
......
......@@ -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;
/***********************************************************************/
......
......@@ -151,6 +151,11 @@ static void nr_rrc_ue_process_masterCellGroup(NR_UE_RRC_INST_t *rrc,
static void nr_rrc_ue_process_measConfig(rrcPerNB_t *rrc, NR_MeasConfig_t *const measConfig, NR_UE_Timers_Constants_t *timers);
NR_UE_RRC_INST_t* get_NR_UE_rrc_inst(int instance)
{
return &NR_UE_rrc_inst[instance];
}
static NR_RB_status_t get_DRB_status(const NR_UE_RRC_INST_t *rrc, NR_DRB_Identity_t drb_id)
{
AssertFatal(drb_id > 0 && drb_id < 33, "Invalid DRB ID %ld\n", drb_id);
......@@ -873,6 +878,13 @@ static int8_t nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(NR_UE_RRC_INST_t *rrc,
return 0;
}
static void nr_rrc_signal_maxrtxindication(int ue_id)
{
MessageDef *msg = itti_alloc_new_message(TASK_RLC_UE, ue_id, NR_RRC_RLC_MAXRTX);
NR_RRC_RLC_MAXRTX(msg).ue_id = ue_id;
itti_send_msg_to_task(TASK_RRC_NRUE, ue_id, msg);
}
static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc,
const NR_CellGroupConfig_t *cellGroupConfig)
{
......@@ -901,9 +913,11 @@ static void nr_rrc_manage_rlc_bearers(NR_UE_RRC_INST_t *rrc,
if (rlc_bearer->servedRadioBearer->present == NR_RLC_BearerConfig__servedRadioBearer_PR_srb_Identity) {
NR_SRB_Identity_t srb_id = rlc_bearer->servedRadioBearer->choice.srb_Identity;
nr_rlc_add_srb(rrc->ue_id, srb_id, rlc_bearer);
nr_rlc_set_rlf_handler(rrc->ue_id, nr_rrc_signal_maxrtxindication);
} else { // DRB
NR_DRB_Identity_t drb_id = rlc_bearer->servedRadioBearer->choice.drb_Identity;
nr_rlc_add_drb(rrc->ue_id, drb_id, rlc_bearer);
nr_rlc_set_rlf_handler(rrc->ue_id, nr_rrc_signal_maxrtxindication);
}
}
}
......@@ -1843,6 +1857,15 @@ void *rrc_nrue(void *notUsed)
nr_rrc_going_to_IDLE(rrc, release_cause, NULL);
break;
case NR_RRC_RLC_MAXRTX:
// detection of RLF upon indication from RLC that the maximum number of retransmissions has been reached
LOG_W(NR_RRC,
"[UE %ld ID %d] Received indication that RLC reached max retransmissions\n",
instance,
NR_RRC_RLC_MAXRTX(msg_p).ue_id);
handle_rlf_detection(rrc);
break;
case NR_RRC_MAC_MSG3_IND:
nr_rrc_handle_msg3_indication(rrc, NR_RRC_MAC_MSG3_IND(msg_p).rnti);
break;
......@@ -2285,6 +2308,26 @@ void handle_RRCRelease(NR_UE_RRC_INST_t *rrc)
asn1cFreeStruc(asn_DEF_NR_RRCRelease, rrc->RRCRelease);
}
void handle_rlf_detection(NR_UE_RRC_INST_t *rrc)
{
// 5.3.10.3 in 38.331
bool srb2 = rrc->Srb[2] != RB_NOT_PRESENT;
bool any_drb = false;
for (int i = 0; i < MAX_DRBS_PER_UE; i++) {
if (rrc->status_DRBs[i] != RB_NOT_PRESENT) {
any_drb = true;
break;
}
}
if (rrc->as_security_activated && srb2 && any_drb) // initiate the connection re-establishment procedure
nr_rrc_initiate_rrcReestablishment(rrc, NR_ReestablishmentCause_otherFailure, 0);
else {
NR_Release_Cause_t cause = rrc->as_security_activated ? RRC_CONNECTION_FAILURE : OTHER;
nr_rrc_going_to_IDLE(rrc, cause, NULL);
}
}
void nr_rrc_going_to_IDLE(NR_UE_RRC_INST_t *rrc,
NR_Release_Cause_t release_cause,
NR_RRCRelease_t *RRCRelease)
......
......@@ -42,7 +42,7 @@
#include "common/utils/ocp_itti/intertask_interface.h"
NR_UE_RRC_INST_t *nr_rrc_init_ue(char* uecap_file, int nb_inst, int num_ant_tx);
NR_UE_RRC_INST_t* get_NR_UE_rrc_inst(int instance);
void init_nsa_message (NR_UE_RRC_INST_t *rrc, char* reconfig_file, char* rbconfig_file);
void process_nsa_message(NR_UE_RRC_INST_t *rrc, nsa_message_t nsa_message_type, void *message, int msg_len);
......@@ -63,6 +63,7 @@ void *rrc_nrue_task(void *args_p);
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);
/**\brief RRC NSA UE task.
\param void *args_p Pointer on arguments to start the task. */
......
......@@ -157,10 +157,9 @@ void nr_rrc_handle_timers(NR_UE_RRC_INST_t *rrc)
bool t310_expired = nr_timer_tick(&timers->T310);
if(t310_expired) {
LOG_W(NR_RRC, "Timer T310 expired\n");
// TODO
// handle detection of radio link failure
// as described in 5.3.10.3 of 38.331
AssertFatal(false, "Radio link failure! Not handled yet!\n");
handle_rlf_detection(rrc);
}
bool t311_expired = nr_timer_tick(&timers->T311);
......
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