diff --git a/ci-scripts/xml_files/container_5g_f1_rfsim.xml b/ci-scripts/xml_files/container_5g_f1_rfsim.xml
index 16c02050d2..8c925cbc5f 100644
--- a/ci-scripts/xml_files/container_5g_f1_rfsim.xml
+++ b/ci-scripts/xml_files/container_5g_f1_rfsim.xml
@@ -34,6 +34,11 @@
030020
030021
030022
+ 040001
+ 020022
+ 040002
+ 030021
+ 030022
100021
222222
@@ -117,11 +122,36 @@
90
+
+ Custom_Command
+ Trigger Reestablishment
+ cacofonix
+ 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'
+ yes
+
+
+
+ Ping
+ Ping ext-dn from all NR-UEs
+ rfsim5g_ue
+ cacofonix
+ -c 20 192.168.72.135 -i0.5 -w25
+ 80
+
+
+
+ Custom_Command
+ Verify Reestablishment
+ cacofonix
+ echo ci get_reestab_count | nc 192.168.71.150 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1'
+ yes
+
+
Custom_Command
Simulate a disruption of DL radio channel (ploss 55)(5 sec)
cacofonix
- echo channelmod modify 0 ploss 55 | nc -N 192.168.71.181 8091 && sleep 5
+ echo channelmod modify 0 ploss 55 | nc 192.168.71.181 8091 && sleep 5
yes
@@ -129,7 +159,7 @@
Custom_Command
Get UE sync state (UE ID 0)
cacofonix
- echo ciUE sync_state 0 | nc -N 192.168.71.181 8091 | grep -E UE_NOT_SYNC
+ echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_NOT_SYNC
yes
@@ -137,7 +167,7 @@
Custom_Command
Restoration of the original DL channel conditions (ploss 0)(5 sec)
cacofonix
- echo channelmod modify 0 ploss 0 | nc -N 192.168.71.181 8091 && sleep 5
+ echo channelmod modify 0 ploss 0 | nc 192.168.71.181 8091 && sleep 5
yes
@@ -145,7 +175,7 @@
Custom_Command
Get UE sync state (UE ID 0)
cacofonix
- echo ciUE sync_state 0 | nc -N 192.168.71.181 8091 | grep -E UE_CONNECTED && sleep 10
+ echo ciUE sync_state 0 | nc 192.168.71.181 8091 | grep -E UE_CONNECTED && sleep 10
yes
diff --git a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml
index c925af1adb..df0a9f4b07 100644
--- a/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_f1_rfsimulator/docker-compose.yaml
@@ -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
diff --git a/common/utils/telnetsrv/telnetsrv.c b/common/utils/telnetsrv/telnetsrv.c
index 43208748d0..9e708efc38 100644
--- a/common/utils/telnetsrv/telnetsrv.c
+++ b/common/utils/telnetsrv/telnetsrv.c
@@ -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;
}
}
diff --git a/common/utils/telnetsrv/telnetsrv_ci.c b/common/utils/telnetsrv/telnetsrv_ci.c
index 700ff73135..ba3062178f 100644
--- a/common/utils/telnetsrv/telnetsrv_ci.c
+++ b/common/utils/telnetsrv/telnetsrv_ci.c
@@ -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},
};
diff --git a/common/utils/telnetsrv/telnetsrv_ciUE.c b/common/utils/telnetsrv/telnetsrv_ciUE.c
index 673d904969..dd95f8009c 100644
--- a/common/utils/telnetsrv/telnetsrv_ciUE.c
+++ b/common/utils/telnetsrv/telnetsrv_ciUE.c
@@ -36,6 +36,7 @@
#include
#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},
};
diff --git a/executables/nr-ue.c b/executables/nr-ue.c
index bd64a9d361..d6c3086317 100644
--- a/executables/nr-ue.c
+++ b/executables/nr-ue.c
@@ -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);
diff --git a/openair1/PHY/impl_defs_nr.h b/openair1/PHY/impl_defs_nr.h
index 7f9dfad719..16d5854604 100644
--- a/openair1/PHY/impl_defs_nr.h
+++ b/openair1/PHY/impl_defs_nr.h
@@ -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)
diff --git a/openair2/COMMON/rrc_messages_def.h b/openair2/COMMON/rrc_messages_def.h
index ef09d98284..fb94aeb29e 100644
--- a/openair2/COMMON/rrc_messages_def.h
+++ b/openair2/COMMON/rrc_messages_def.h
@@ -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)
diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h
index 15509b1807..0e57120ee4 100644
--- a/openair2/COMMON/rrc_messages_types.h
+++ b/openair2/COMMON/rrc_messages_types.h
@@ -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_ */
diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c
index 3c66515eef..80e2255aa5 100644
--- a/openair2/LAYER2/NR_MAC_UE/config_ue.c
+++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c
@@ -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);
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
index 6b0322fc50..1530846d6b 100644
--- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
@@ -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,
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
index 3f97c6c4fc..094d1e5965 100644
--- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
@@ -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,
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index 36714fd80a..c871a696da 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -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;
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
index 3f0e3a78a5..ff44c21541 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
@@ -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);
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
index b8fd148876..2ebd18f5e7 100644
--- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c
@@ -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);
}
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h
index 736c42a0b7..10182f3793 100644
--- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h
@@ -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);
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h
index e37d7929d8..13f5c55a2f 100644
--- a/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_ue_manager.h
@@ -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;
/***********************************************************************/
diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c
index 53364b0768..13e5965d75 100644
--- a/openair2/RRC/NR_UE/rrc_UE.c
+++ b/openair2/RRC/NR_UE/rrc_UE.c
@@ -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)
diff --git a/openair2/RRC/NR_UE/rrc_proto.h b/openair2/RRC/NR_UE/rrc_proto.h
index 95685c8e2f..d1f1d3228f 100644
--- a/openair2/RRC/NR_UE/rrc_proto.h
+++ b/openair2/RRC/NR_UE/rrc_proto.h
@@ -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. */
diff --git a/openair2/RRC/NR_UE/rrc_timers_and_constants.c b/openair2/RRC/NR_UE/rrc_timers_and_constants.c
index f0635b16b2..7e0c040731 100644
--- a/openair2/RRC/NR_UE/rrc_timers_and_constants.c
+++ b/openair2/RRC/NR_UE/rrc_timers_and_constants.c
@@ -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);