Commit a1982390 authored by Laurent THOMAS's avatar Laurent THOMAS Committed by Robert Schmidt

Introduce no-thread mode in ITTI

Introduce a --no-itti-threads command line option to disable threading
in ITTI, and call message handlers in the current thread. This is being
introduced in order to increase repeatability when testing the nrUE with
the IQPlayer. Without this feature, runs with the IQPlayer will end up
differently, depending on the timing of ITTI threads, mostly when
sending messages to RRC and NAS.
parent 724c8c01
......@@ -30,17 +30,19 @@
extern "C" {
#include <intertask_interface.h>
#include <common/utils/system.h>
#include "executables/softmodem-common.h"
typedef struct timer_elm_s {
typedef struct timer_elm_s {
timer_type_t type; ///< Timer type
long instance;
long duration;
uint64_t timeout;
void *timer_arg; ///< Optional argument that will be passed when timer expires
} timer_elm_t ;
} timer_elm_t;
typedef struct task_list_s {
task_info_t admin;
ittiTask_parms_t task_parms;
pthread_t thread;
pthread_mutex_t queue_cond_lock;
std::vector<MessageDef *> message_queue;
......@@ -162,12 +164,12 @@ extern "C" {
pthread_mutex_lock (&t->queue_cond_lock);
int ret=itti_send_msg_to_task_locked(destination_task_id, destinationInstance, message);
while ( t->message_queue.size()>0 && t->admin.func != NULL ) {
while (t->message_queue.size() > 0 && t->task_parms.shortcut_func != NULL) {
if (t->message_queue.size()>1)
LOG_W(ITTI,"queue in no thread mode is %ld\n", t->message_queue.size());
pthread_mutex_unlock (&t->queue_cond_lock);
t->admin.func(NULL);
t->task_parms.shortcut_func(NULL);
pthread_mutex_lock (&t->queue_cond_lock);
}
......@@ -327,11 +329,20 @@ extern "C" {
pthread_mutex_unlock (&t->queue_cond_lock);
}
int itti_create_task(task_id_t task_id,
void *(*start_routine)(void *),
void *args_p) {
int itti_create_task(const task_id_t task_id, void *(*start_routine)(void *), const ittiTask_parms_t *parms)
{
task_list_t *t=tasks[task_id];
threadCreate (&t->thread, start_routine, args_p, (char *)itti_get_task_name(task_id),-1,OAI_PRIORITY_RT);
if (get_softmodem_params()->no_itti && task_id < sizeofArray(tasks_info) && parms && parms->shortcut_func) {
LOG_W(ITTI, "not starting the thread for %s, the msg processing will be done in place\n", tasks_info[task_id].name);
t->task_parms.shortcut_func = parms->shortcut_func;
return 0;
}
threadCreate(&t->thread,
start_routine,
parms ? parms->args_to_start_routine : NULL,
(char *)itti_get_task_name(task_id),
-1,
OAI_PRIORITY_RT);
LOG_I(ITTI,"Created Posix thread %s\n", itti_get_task_name(task_id) );
return 0;
}
......@@ -353,6 +364,7 @@ extern "C" {
AssertFatal(new_tasks != NULL, "could not realloc() tasks list");
tasks = new_tasks;
tasks[newQueue]= new task_list_t;
tasks[newQueue]->task_parms = {0};
pthread_mutex_unlock (&lock_nb_queues);
LOG_I(ITTI,"Starting itti queue: %s as task %d\n", taskInfo->name, newQueue);
pthread_mutex_init(&tasks[newQueue]->queue_cond_lock, NULL);
......@@ -361,9 +373,6 @@ extern "C" {
AssertFatal( ( tasks[newQueue]->sem_fd = eventfd(0, EFD_SEMAPHORE) ) >=0, "");
itti_subscribe_event_fd((task_id_t)newQueue, tasks[newQueue]->sem_fd);
if (tasks[newQueue]->admin.threadFunc != NULL)
itti_create_task((task_id_t)newQueue, tasks[newQueue]->admin.threadFunc, NULL);
return newQueue;
}
......
......@@ -484,9 +484,11 @@ void itti_poll_msg(task_id_t task_id, MessageDef **received_msg);
\param args_p Optional argument to pass to the start routine
@returns -1 on failure, 0 otherwise
**/
int itti_create_task(task_id_t task_id,
void *(*start_routine) (void *),
void *args_p);
typedef struct {
void *args_to_start_routine;
void *(*shortcut_func)(void *);
} ittiTask_parms_t;
int itti_create_task(const task_id_t task_id, void *(*start_routine)(void *), const ittiTask_parms_t *args_p);
int itti_create_queue(const task_info_t *task_info);
......
......@@ -47,8 +47,8 @@ int create_tasks_ue(uint32_t ue_nb) {
if (users == NULL) abort();
users->count = ue_nb;
if (itti_create_task (TASK_NAS_UE, nas_ue_task, users) < 0) {
ittiTask_parms_t parms = {users, NULL};
if (itti_create_task(TASK_NAS_UE, nas_ue_task, &parms) < 0) {
LOG_E(NAS, "Create task for NAS UE failed\n");
return -1;
}
......
......@@ -197,7 +197,8 @@ int create_tasks_nrue(uint32_t ue_nb) {
if (ue_nb > 0) {
LOG_I(NR_RRC,"create TASK_RRC_NRUE \n");
if (itti_create_task (TASK_RRC_NRUE, rrc_nrue_task, NULL) < 0) {
const ittiTask_parms_t parmsRRC = {NULL, rrc_nrue};
if (itti_create_task(TASK_RRC_NRUE, rrc_nrue_task, &parmsRRC) < 0) {
LOG_E(NR_RRC, "Create task for RRC UE failed\n");
return -1;
}
......@@ -208,7 +209,8 @@ int create_tasks_nrue(uint32_t ue_nb) {
return -1;
}
}
if (itti_create_task (TASK_NAS_NRUE, nas_nrue_task, NULL) < 0) {
const ittiTask_parms_t parmsNAS = {NULL, nas_nrue};
if (itti_create_task(TASK_NAS_NRUE, nas_nrue_task, &parmsNAS) < 0) {
LOG_E(NR_RRC, "Create task for NAS UE failed\n");
return -1;
}
......
......@@ -109,6 +109,7 @@ extern "C"
#define CONFIG_HLP_SYNC_REF "Sync Reference in Sidelink\n"
#define CONFIG_HLP_NID1 "Set NID1 value in Sidelink\n"
#define CONFIG_HLP_NID2 "Set NID2 value in Sidelink\n"
#define CONFIG_HLP_NOITTI "Do not start itti threads, call queue processing in place, inside the caller thread"
/*-----------------------------------------------------------------------------------------------------------------------------------------------------*/
/* command line parameters common to eNodeB and UE */
......@@ -190,6 +191,7 @@ extern int usrp_tx_thread;
{"disable-stats", CONFIG_HLP_STATS_DISABLE, PARAMFLAG_BOOL, .iptr=&stats_disabled, .defintval=0, TYPE_INT, 0}, \
{"nid1", CONFIG_HLP_NID1, 0, .iptr=&NID1, .defintval=10, TYPE_INT, 0}, \
{"nid2", CONFIG_HLP_NID2, 0, .iptr=&NID2, .defintval=1, TYPE_INT, 0}, \
{"no-itti-threads", CONFIG_HLP_NOITTI, PARAMFLAG_BOOL, .iptr=&softmodem_params.no_itti, .defintval=0, TYPE_INT, 0}, \
}
// clang-format on
......@@ -238,6 +240,7 @@ extern int usrp_tx_thread;
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
}
// clang-format on
......@@ -349,6 +352,7 @@ typedef struct {
int sync_ref;
int nid1;
int nid2;
int no_itti;
} softmodem_params_t;
extern uint64_t get_softmodem_optmask(void);
......
......@@ -51,3 +51,7 @@ int8_t nr_mac_rrc_data_ind_ue(const module_id_t module_id,
const channel_t channel,
const uint8_t* pduP,
const sdu_size_t pdu_len) { return 0; }
void *rrc_nrue(void *notUsed)
{
return NULL;
}
This diff is collapsed.
......@@ -114,6 +114,7 @@ int8_t nr_rrc_RA_succeeded(const module_id_t mod_id, const uint8_t gNB_index);
/**\brief RRC UE task.
\param void *args_p Pointer on arguments to start the task. */
void *rrc_nrue_task(void *args_p);
void *rrc_nrue(void *args_p);
void nr_rrc_handle_timers(NR_UE_Timers_Constants_t *timers);
......
......@@ -57,7 +57,7 @@ uint8_t *registration_request_buf;
uint32_t registration_request_len;
extern char *baseNetAddress;
extern uint16_t NB_UE_INST;
static nr_ue_nas_t nr_ue_nas;
static nr_ue_nas_t nr_ue_nas = {0};
static int nas_protected_security_header_encode(
char *buffer,
......@@ -416,6 +416,8 @@ void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) {
nr_ue_nas_t *get_ue_nas_info(module_id_t module_id)
{
DevAssert(module_id == 0);
if (!nr_ue_nas.uicc)
nr_ue_nas.uicc = checkUicc(0);
return &nr_ue_nas;
}
......@@ -912,23 +914,21 @@ static void send_nas_uplink_data_req(instance_t instance, const as_nas_info_t *i
void *nas_nrue_task(void *args_p)
{
MessageDef *msg_p;
instance_t instance;
int result;
uint8_t msg_type = 0;
uint8_t *pdu_buffer = NULL;
nr_ue_nas.uicc = checkUicc(0);
nr_ue_nas_t *nas = get_ue_nas_info(0);
itti_mark_task_ready (TASK_NAS_NRUE);
while (1) {
nas_nrue(NULL);
}
}
while(1) {
void *nas_nrue(void *args_p)
{
// Wait for a message or an event
itti_receive_msg (TASK_NAS_NRUE, &msg_p);
nr_ue_nas.uicc = checkUicc(0);
MessageDef *msg_p;
itti_receive_msg(TASK_NAS_NRUE, &msg_p);
if (msg_p != NULL) {
instance = msg_p->ittiMsgHeader.originInstance;
instance_t instance = msg_p->ittiMsgHeader.originInstance;
AssertFatal(instance == 0, "cannot handle more than one UE!\n");
switch (ITTI_MSG_ID(msg_p)) {
......@@ -959,7 +959,12 @@ void *nas_nrue_task(void *args_p)
break;
case NAS_CELL_SELECTION_IND:
LOG_I(NAS, "[UE %ld] Received %s: cellID %u, tac %u\n", instance, ITTI_MSG_NAME(msg_p), NAS_CELL_SELECTION_IND(msg_p).cellID, NAS_CELL_SELECTION_IND(msg_p).tac);
LOG_I(NAS,
"[UE %ld] Received %s: cellID %u, tac %u\n",
instance,
ITTI_MSG_NAME(msg_p),
NAS_CELL_SELECTION_IND(msg_p).cellID,
NAS_CELL_SELECTION_IND(msg_p).tac);
/* TODO not processed by NAS currently */
break;
......@@ -971,13 +976,19 @@ void *nas_nrue_task(void *args_p)
break;
case NAS_CONN_ESTABLI_CNF: {
LOG_I(NAS, "[UE %ld] Received %s: errCode %u, length %u\n", instance, ITTI_MSG_NAME(msg_p), NAS_CONN_ESTABLI_CNF(msg_p).errCode, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length);
LOG_I(NAS,
"[UE %ld] Received %s: errCode %u, length %u\n",
instance,
ITTI_MSG_NAME(msg_p),
NAS_CONN_ESTABLI_CNF(msg_p).errCode,
NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length);
pdu_buffer = NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.data;
msg_type = get_msg_type(pdu_buffer, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length);
uint8_t *pdu_buffer = NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.data;
int msg_type = get_msg_type(pdu_buffer, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length);
if (msg_type == REGISTRATION_ACCEPT) {
LOG_I(NAS, "[UE] Received REGISTRATION ACCEPT message\n");
nr_ue_nas_t *nas = get_ue_nas_info(0);
decodeRegistrationAccept(pdu_buffer, NAS_CONN_ESTABLI_CNF(msg_p).nasMsg.length, nas);
as_nas_info_t initialNasMsg = {0};
......@@ -1001,8 +1012,7 @@ void *nas_nrue_task(void *args_p)
}
case NAS_CONN_RELEASE_IND:
LOG_I(NAS, "[UE %ld] Received %s: cause %u\n", instance, ITTI_MSG_NAME (msg_p),
NAS_CONN_RELEASE_IND (msg_p).cause);
LOG_I(NAS, "[UE %ld] Received %s: cause %u\n", instance, ITTI_MSG_NAME(msg_p), NAS_CONN_RELEASE_IND(msg_p).cause);
/* the following is not clean, but probably necessary: we need to give
* time to RLC to Ack the SRB1 PDU which contained the RRC release
* message. Hence, we just below wait some time, before finally
......@@ -1012,13 +1022,18 @@ void *nas_nrue_task(void *args_p)
break;
case NAS_UPLINK_DATA_CNF:
LOG_I(NAS, "[UE %ld] Received %s: UEid %u, errCode %u\n", instance, ITTI_MSG_NAME (msg_p),
NAS_UPLINK_DATA_CNF (msg_p).UEid, NAS_UPLINK_DATA_CNF (msg_p).errCode);
LOG_I(NAS,
"[UE %ld] Received %s: UEid %u, errCode %u\n",
instance,
ITTI_MSG_NAME(msg_p),
NAS_UPLINK_DATA_CNF(msg_p).UEid,
NAS_UPLINK_DATA_CNF(msg_p).errCode);
break;
case NAS_DEREGISTRATION_REQ: {
LOG_I(NAS, "[UE %ld] Received %s\n", instance, ITTI_MSG_NAME(msg_p));
nr_ue_nas_t *nas = get_ue_nas_info(0);
if (nas->guti) {
nas_deregistration_req_t *req = &NAS_DEREGISTRATION_REQ(msg_p);
as_nas_info_t initialNasMsg = {0};
......@@ -1027,24 +1042,22 @@ void *nas_nrue_task(void *args_p)
} else {
LOG_E(NAS, "no GUTI, cannot trigger deregistration request\n");
}
}
break;
} break;
case NAS_DOWNLINK_DATA_IND:
{
case NAS_DOWNLINK_DATA_IND: {
LOG_I(NAS,
"[UE %ld] Received %s: length %u , buffer %p\n",
instance,
ITTI_MSG_NAME(msg_p),
NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length,
NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data);
as_nas_info_t initialNasMsg={0};
pdu_buffer = NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data;
msg_type = get_msg_type(pdu_buffer, NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length);
as_nas_info_t initialNasMsg = {0};
switch(msg_type){
uint8_t *pdu_buffer = NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.data;
int msg_type = get_msg_type(pdu_buffer, NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length);
nr_ue_nas_t *nas = get_ue_nas_info(0);
switch (msg_type) {
case FGS_IDENTITY_REQUEST:
generateIdentityResponse(&initialNasMsg, *(pdu_buffer + 3), nas->uicc);
break;
......@@ -1109,28 +1122,23 @@ void *nas_nrue_task(void *args_p)
}
offset++;
}
}
break;
} break;
default:
LOG_W(NR_RRC,"unknown message type %d\n",msg_type);
LOG_W(NR_RRC, "unknown message type %d\n", msg_type);
break;
}
if (initialNasMsg.length > 0)
send_nas_uplink_data_req(instance, &initialNasMsg);
}
break;
} break;
default:
LOG_E(NAS, "[UE %ld] Received unexpected message %s\n", instance, ITTI_MSG_NAME (msg_p));
LOG_E(NAS, "[UE %ld] Received unexpected message %s\n", instance, ITTI_MSG_NAME(msg_p));
break;
}
result = itti_free (ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
msg_p = NULL;
int result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), msg_p);
AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
}
}
return NULL;
}
......@@ -174,6 +174,7 @@ typedef struct {
nr_ue_nas_t *get_ue_nas_info(module_id_t module_id);
void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas);
void *nas_nrue_task(void *args_p);
void *nas_nrue(void *args_p);
#endif /* __NR_NAS_MSG_SIM_H__*/
......
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