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.
This commit is contained in:
Laurent THOMAS
2023-10-27 13:02:36 +02:00
committed by Robert Schmidt
parent 724c8c014c
commit a198239084
10 changed files with 344 additions and 292 deletions
+182 -161
View File
@@ -1729,172 +1729,193 @@ void nr_rrc_handle_ra_indication(unsigned int mod_id, bool ra_succeeded)
// reconfigurationWithSync is included in spCellConfig
}
}
void *rrc_nrue_task(void *args_p)
{
MessageDef *msg_p;
instance_t instance;
unsigned int ue_mod_id;
int result;
protocol_ctxt_t ctxt;
itti_mark_task_ready(TASK_RRC_NRUE);
itti_mark_task_ready(TASK_RRC_NRUE);
while(1) {
// Wait for a message
itti_receive_msg (TASK_RRC_NRUE, &msg_p);
instance = ITTI_MSG_DESTINATION_INSTANCE (msg_p);
ue_mod_id = UE_INSTANCE_TO_MODULE_ID(instance);
switch (ITTI_MSG_ID(msg_p)) {
case TERMINATE_MESSAGE:
LOG_W(NR_RRC, " *** Exiting RRC thread\n");
itti_exit_task ();
break;
case MESSAGE_TEST:
LOG_D(NR_RRC, "[UE %d] Received %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p));
break;
case NR_RRC_MAC_SYNC_IND:
LOG_D(NR_RRC, "[UE %d] Received %s: frame %d\n",
ue_mod_id,
ITTI_MSG_NAME (msg_p),
NR_RRC_MAC_SYNC_IND (msg_p).frame);
nr_sync_msg_t sync_msg = NR_RRC_MAC_SYNC_IND (msg_p).in_sync ?
IN_SYNC : OUT_OF_SYNC;
NR_UE_Timers_Constants_t *tac = &NR_UE_rrc_inst[ue_mod_id].timers_and_constants;
handle_rlf_sync(tac, sync_msg);
break;
case NRRRC_FRAME_PROCESS:
LOG_D(NR_RRC, "[UE %d] Received %s: frame %d\n",
ue_mod_id, ITTI_MSG_NAME (msg_p), NRRRC_FRAME_PROCESS (msg_p).frame);
// increase the timers every 10ms (every new frame)
NR_UE_Timers_Constants_t *timers = &NR_UE_rrc_inst[ue_mod_id].timers_and_constants;
nr_rrc_handle_timers(timers);
NR_UE_RRC_SI_INFO *SInfo = &NR_UE_rrc_inst[ue_mod_id].SInfo[NRRRC_FRAME_PROCESS (msg_p).gnb_id];
nr_rrc_SI_timers(SInfo);
break;
case NR_RRC_MAC_MSG3_IND:
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_NO, NR_RRC_MAC_MSG3_IND (msg_p).rnti, 0, 0);
LOG_D(NR_RRC, "[UE %d] Received %s for RNTI %d\n",
ue_mod_id,
ITTI_MSG_NAME (msg_p),
NR_RRC_MAC_MSG3_IND (msg_p).rnti);
nr_rrc_ue_generate_ra_msg(ue_mod_id, NR_RRC_MAC_MSG3_IND (msg_p).rnti);
break;
case NR_RRC_MAC_RA_IND:
LOG_D(NR_RRC, "[UE %d] Received %s: frame %d RA %s\n",
ue_mod_id,
ITTI_MSG_NAME (msg_p),
NR_RRC_MAC_RA_IND (msg_p).frame,
NR_RRC_MAC_RA_IND (msg_p).RA_succeeded ? "successful" : "failed");
nr_rrc_handle_ra_indication(ue_mod_id, NR_RRC_MAC_RA_IND (msg_p).RA_succeeded);
break;
case NR_RRC_MAC_BCCH_DATA_IND:
LOG_D(NR_RRC, "[UE %d] Received %s: gNB %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p),
NR_RRC_MAC_BCCH_DATA_IND (msg_p).gnb_index);
NRRrcMacBcchDataInd *bcch = &NR_RRC_MAC_BCCH_DATA_IND (msg_p);
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, GNB_FLAG_NO, NOT_A_RNTI, bcch->frame, 0, bcch->gnb_index);
if (bcch->is_bch)
nr_rrc_ue_decode_NR_BCCH_BCH_Message(ue_mod_id,
bcch->gnb_index,
bcch->sdu,
bcch->sdu_size);
else
nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(ctxt.module_id,
bcch->gnb_index,
bcch->sdu,
bcch->sdu_size,
bcch->rsrq,
bcch->rsrp);
break;
case NR_RRC_MAC_CCCH_DATA_IND:
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_NO, NR_RRC_MAC_CCCH_DATA_IND (msg_p).rnti, 0, 0);
nr_rrc_ue_decode_ccch(&ctxt,
NR_RRC_MAC_CCCH_DATA_IND (msg_p).sdu,
NR_RRC_MAC_CCCH_DATA_IND (msg_p).sdu_size,
/* gNB_index = */ 0);
break;
/* PDCP messages */
case NR_RRC_DCCH_DATA_IND:
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt,
NR_RRC_DCCH_DATA_IND (msg_p).module_id,
GNB_FLAG_NO,
NR_RRC_DCCH_DATA_IND (msg_p).rnti,
NR_RRC_DCCH_DATA_IND (msg_p).frame,
0,
NR_RRC_DCCH_DATA_IND (msg_p).gNB_index);
LOG_D(NR_RRC, "[UE %d] Received %s: frameP %d, DCCH %d, gNB %d\n",
NR_RRC_DCCH_DATA_IND (msg_p).module_id,
ITTI_MSG_NAME (msg_p),
NR_RRC_DCCH_DATA_IND (msg_p).frame,
NR_RRC_DCCH_DATA_IND (msg_p).dcch_index,
NR_RRC_DCCH_DATA_IND (msg_p).gNB_index);
LOG_D(NR_RRC, PROTOCOL_RRC_CTXT_UE_FMT"Received %s DCCH %d, gNB %d\n",
PROTOCOL_NR_RRC_CTXT_UE_ARGS(&ctxt),
ITTI_MSG_NAME (msg_p),
NR_RRC_DCCH_DATA_IND (msg_p).dcch_index,
NR_RRC_DCCH_DATA_IND (msg_p).gNB_index);
nr_rrc_ue_decode_dcch (
&ctxt,
NR_RRC_DCCH_DATA_IND (msg_p).dcch_index,
NR_RRC_DCCH_DATA_IND (msg_p).sdu_p,
NR_RRC_DCCH_DATA_IND (msg_p).sdu_size,
NR_RRC_DCCH_DATA_IND (msg_p).gNB_index);
break;
case NAS_KENB_REFRESH_REQ:
memcpy((void *)NR_UE_rrc_inst[ue_mod_id].kgnb, (void *)NAS_KENB_REFRESH_REQ(msg_p).kenb, sizeof(NR_UE_rrc_inst[ue_mod_id].kgnb));
LOG_D(RRC, "[UE %d] Received %s: refreshed RRC::KgNB = "
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
"%02x%02x%02x%02x\n",
ue_mod_id, ITTI_MSG_NAME (msg_p),
NR_UE_rrc_inst[ue_mod_id].kgnb[0], NR_UE_rrc_inst[ue_mod_id].kgnb[1], NR_UE_rrc_inst[ue_mod_id].kgnb[2], NR_UE_rrc_inst[ue_mod_id].kgnb[3],
NR_UE_rrc_inst[ue_mod_id].kgnb[4], NR_UE_rrc_inst[ue_mod_id].kgnb[5], NR_UE_rrc_inst[ue_mod_id].kgnb[6], NR_UE_rrc_inst[ue_mod_id].kgnb[7],
NR_UE_rrc_inst[ue_mod_id].kgnb[8], NR_UE_rrc_inst[ue_mod_id].kgnb[9], NR_UE_rrc_inst[ue_mod_id].kgnb[10], NR_UE_rrc_inst[ue_mod_id].kgnb[11],
NR_UE_rrc_inst[ue_mod_id].kgnb[12], NR_UE_rrc_inst[ue_mod_id].kgnb[13], NR_UE_rrc_inst[ue_mod_id].kgnb[14], NR_UE_rrc_inst[ue_mod_id].kgnb[15],
NR_UE_rrc_inst[ue_mod_id].kgnb[16], NR_UE_rrc_inst[ue_mod_id].kgnb[17], NR_UE_rrc_inst[ue_mod_id].kgnb[18], NR_UE_rrc_inst[ue_mod_id].kgnb[19],
NR_UE_rrc_inst[ue_mod_id].kgnb[20], NR_UE_rrc_inst[ue_mod_id].kgnb[21], NR_UE_rrc_inst[ue_mod_id].kgnb[22], NR_UE_rrc_inst[ue_mod_id].kgnb[23],
NR_UE_rrc_inst[ue_mod_id].kgnb[24], NR_UE_rrc_inst[ue_mod_id].kgnb[25], NR_UE_rrc_inst[ue_mod_id].kgnb[26], NR_UE_rrc_inst[ue_mod_id].kgnb[27],
NR_UE_rrc_inst[ue_mod_id].kgnb[28], NR_UE_rrc_inst[ue_mod_id].kgnb[29], NR_UE_rrc_inst[ue_mod_id].kgnb[30], NR_UE_rrc_inst[ue_mod_id].kgnb[31]);
break;
case NAS_UPLINK_DATA_REQ: {
uint32_t length;
uint8_t *buffer;
LOG_I(NR_RRC, "[UE %d] Received %s: UEid %d\n", ue_mod_id, ITTI_MSG_NAME (msg_p), NAS_UPLINK_DATA_REQ (msg_p).UEid);
/* Create message for PDCP (ULInformationTransfer_t) */
length = do_NR_ULInformationTransfer(&buffer, NAS_UPLINK_DATA_REQ (msg_p).nasMsg.length, NAS_UPLINK_DATA_REQ (msg_p).nasMsg.data);
/* Transfer data to PDCP */
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, GNB_FLAG_NO, NR_UE_rrc_inst[ue_mod_id].rnti, 0, 0,0);
// check if SRB2 is created, if yes request data_req on SRB2
rb_id_t srb_id = NR_UE_rrc_inst[ue_mod_id].Srb[0][2].status == RB_ESTABLISHED ? 2 : 1;
nr_pdcp_data_req_srb(ctxt.rntiMaybeUEid, srb_id, nr_rrc_mui++, length, buffer, deliver_pdu_srb_rlc, NULL);
break;
}
default:
LOG_E(NR_RRC, "[UE %d] Received unexpected message %s\n", ue_mod_id, ITTI_MSG_NAME (msg_p));
break;
}
LOG_D(NR_RRC, "[UE %d] RRC Status %d\n", ue_mod_id, NR_UE_rrc_inst[ue_mod_id].nrRrcState);
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;
while (1) {
rrc_nrue(NULL);
}
}
void *rrc_nrue(void *notUsed)
{
protocol_ctxt_t ctxt;
MessageDef *msg_p = NULL;
itti_receive_msg(TASK_RRC_NRUE, &msg_p);
instance_t instance = ITTI_MSG_DESTINATION_INSTANCE(msg_p);
unsigned int ue_mod_id = UE_INSTANCE_TO_MODULE_ID(instance);
switch (ITTI_MSG_ID(msg_p)) {
case TERMINATE_MESSAGE:
LOG_W(NR_RRC, " *** Exiting RRC thread\n");
itti_exit_task();
break;
case MESSAGE_TEST:
LOG_D(NR_RRC, "[UE %d] Received %s\n", ue_mod_id, ITTI_MSG_NAME(msg_p));
break;
case NR_RRC_MAC_SYNC_IND:
LOG_D(NR_RRC, "[UE %d] Received %s: frame %d\n", ue_mod_id, ITTI_MSG_NAME(msg_p), NR_RRC_MAC_SYNC_IND(msg_p).frame);
nr_sync_msg_t sync_msg = NR_RRC_MAC_SYNC_IND(msg_p).in_sync ? IN_SYNC : OUT_OF_SYNC;
NR_UE_Timers_Constants_t *tac = &NR_UE_rrc_inst[ue_mod_id].timers_and_constants;
handle_rlf_sync(tac, sync_msg);
break;
case NRRRC_FRAME_PROCESS:
LOG_D(NR_RRC, "[UE %d] Received %s: frame %d\n", ue_mod_id, ITTI_MSG_NAME(msg_p), NRRRC_FRAME_PROCESS(msg_p).frame);
// increase the timers every 10ms (every new frame)
NR_UE_Timers_Constants_t *timers = &NR_UE_rrc_inst[ue_mod_id].timers_and_constants;
nr_rrc_handle_timers(timers);
NR_UE_RRC_SI_INFO *SInfo = &NR_UE_rrc_inst[ue_mod_id].SInfo[NRRRC_FRAME_PROCESS(msg_p).gnb_id];
nr_rrc_SI_timers(SInfo);
break;
case NR_RRC_MAC_MSG3_IND:
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_NO, NR_RRC_MAC_MSG3_IND(msg_p).rnti, 0, 0);
LOG_D(NR_RRC, "[UE %d] Received %s for RNTI %d\n", ue_mod_id, ITTI_MSG_NAME(msg_p), NR_RRC_MAC_MSG3_IND(msg_p).rnti);
nr_rrc_ue_generate_ra_msg(ue_mod_id, NR_RRC_MAC_MSG3_IND(msg_p).rnti);
break;
case NR_RRC_MAC_RA_IND:
LOG_D(NR_RRC,
"[UE %d] Received %s: frame %d RA %s\n",
ue_mod_id,
ITTI_MSG_NAME(msg_p),
NR_RRC_MAC_RA_IND(msg_p).frame,
NR_RRC_MAC_RA_IND(msg_p).RA_succeeded ? "successful" : "failed");
nr_rrc_handle_ra_indication(ue_mod_id, NR_RRC_MAC_RA_IND(msg_p).RA_succeeded);
break;
case NR_RRC_MAC_BCCH_DATA_IND:
LOG_D(NR_RRC, "[UE %d] Received %s: gNB %d\n", ue_mod_id, ITTI_MSG_NAME(msg_p), NR_RRC_MAC_BCCH_DATA_IND(msg_p).gnb_index);
NRRrcMacBcchDataInd *bcch = &NR_RRC_MAC_BCCH_DATA_IND(msg_p);
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, GNB_FLAG_NO, NOT_A_RNTI, bcch->frame, 0, bcch->gnb_index);
if (bcch->is_bch)
nr_rrc_ue_decode_NR_BCCH_BCH_Message(ue_mod_id, bcch->gnb_index, bcch->sdu, bcch->sdu_size);
else
nr_rrc_ue_decode_NR_BCCH_DL_SCH_Message(ctxt.module_id,
bcch->gnb_index,
bcch->sdu,
bcch->sdu_size,
bcch->rsrq,
bcch->rsrp);
break;
case NR_RRC_MAC_CCCH_DATA_IND:
PROTOCOL_CTXT_SET_BY_INSTANCE(&ctxt, instance, GNB_FLAG_NO, NR_RRC_MAC_CCCH_DATA_IND(msg_p).rnti, 0, 0);
nr_rrc_ue_decode_ccch(&ctxt,
NR_RRC_MAC_CCCH_DATA_IND(msg_p).sdu,
NR_RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size,
/* gNB_index = */ 0);
break;
/* PDCP messages */
case NR_RRC_DCCH_DATA_IND:
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt,
NR_RRC_DCCH_DATA_IND(msg_p).module_id,
GNB_FLAG_NO,
NR_RRC_DCCH_DATA_IND(msg_p).rnti,
NR_RRC_DCCH_DATA_IND(msg_p).frame,
0,
NR_RRC_DCCH_DATA_IND(msg_p).gNB_index);
LOG_D(NR_RRC,
"[UE %d] Received %s: frameP %d, DCCH %d, gNB %d\n",
NR_RRC_DCCH_DATA_IND(msg_p).module_id,
ITTI_MSG_NAME(msg_p),
NR_RRC_DCCH_DATA_IND(msg_p).frame,
NR_RRC_DCCH_DATA_IND(msg_p).dcch_index,
NR_RRC_DCCH_DATA_IND(msg_p).gNB_index);
LOG_D(NR_RRC,
PROTOCOL_RRC_CTXT_UE_FMT "Received %s DCCH %d, gNB %d\n",
PROTOCOL_NR_RRC_CTXT_UE_ARGS(&ctxt),
ITTI_MSG_NAME(msg_p),
NR_RRC_DCCH_DATA_IND(msg_p).dcch_index,
NR_RRC_DCCH_DATA_IND(msg_p).gNB_index);
nr_rrc_ue_decode_dcch(&ctxt,
NR_RRC_DCCH_DATA_IND(msg_p).dcch_index,
NR_RRC_DCCH_DATA_IND(msg_p).sdu_p,
NR_RRC_DCCH_DATA_IND(msg_p).sdu_size,
NR_RRC_DCCH_DATA_IND(msg_p).gNB_index);
break;
case NAS_KENB_REFRESH_REQ:
memcpy((void *)NR_UE_rrc_inst[ue_mod_id].kgnb,
(void *)NAS_KENB_REFRESH_REQ(msg_p).kenb,
sizeof(NR_UE_rrc_inst[ue_mod_id].kgnb));
LOG_D(RRC,
"[UE %d] Received %s: refreshed RRC::KgNB = "
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
"%02x%02x%02x%02x"
"%02x%02x%02x%02x\n",
ue_mod_id,
ITTI_MSG_NAME(msg_p),
NR_UE_rrc_inst[ue_mod_id].kgnb[0],
NR_UE_rrc_inst[ue_mod_id].kgnb[1],
NR_UE_rrc_inst[ue_mod_id].kgnb[2],
NR_UE_rrc_inst[ue_mod_id].kgnb[3],
NR_UE_rrc_inst[ue_mod_id].kgnb[4],
NR_UE_rrc_inst[ue_mod_id].kgnb[5],
NR_UE_rrc_inst[ue_mod_id].kgnb[6],
NR_UE_rrc_inst[ue_mod_id].kgnb[7],
NR_UE_rrc_inst[ue_mod_id].kgnb[8],
NR_UE_rrc_inst[ue_mod_id].kgnb[9],
NR_UE_rrc_inst[ue_mod_id].kgnb[10],
NR_UE_rrc_inst[ue_mod_id].kgnb[11],
NR_UE_rrc_inst[ue_mod_id].kgnb[12],
NR_UE_rrc_inst[ue_mod_id].kgnb[13],
NR_UE_rrc_inst[ue_mod_id].kgnb[14],
NR_UE_rrc_inst[ue_mod_id].kgnb[15],
NR_UE_rrc_inst[ue_mod_id].kgnb[16],
NR_UE_rrc_inst[ue_mod_id].kgnb[17],
NR_UE_rrc_inst[ue_mod_id].kgnb[18],
NR_UE_rrc_inst[ue_mod_id].kgnb[19],
NR_UE_rrc_inst[ue_mod_id].kgnb[20],
NR_UE_rrc_inst[ue_mod_id].kgnb[21],
NR_UE_rrc_inst[ue_mod_id].kgnb[22],
NR_UE_rrc_inst[ue_mod_id].kgnb[23],
NR_UE_rrc_inst[ue_mod_id].kgnb[24],
NR_UE_rrc_inst[ue_mod_id].kgnb[25],
NR_UE_rrc_inst[ue_mod_id].kgnb[26],
NR_UE_rrc_inst[ue_mod_id].kgnb[27],
NR_UE_rrc_inst[ue_mod_id].kgnb[28],
NR_UE_rrc_inst[ue_mod_id].kgnb[29],
NR_UE_rrc_inst[ue_mod_id].kgnb[30],
NR_UE_rrc_inst[ue_mod_id].kgnb[31]);
break;
case NAS_UPLINK_DATA_REQ: {
uint32_t length;
uint8_t *buffer;
LOG_I(NR_RRC, "[UE %d] Received %s: UEid %d\n", ue_mod_id, ITTI_MSG_NAME(msg_p), NAS_UPLINK_DATA_REQ(msg_p).UEid);
/* Create message for PDCP (ULInformationTransfer_t) */
length =
do_NR_ULInformationTransfer(&buffer, NAS_UPLINK_DATA_REQ(msg_p).nasMsg.length, NAS_UPLINK_DATA_REQ(msg_p).nasMsg.data);
/* Transfer data to PDCP */
PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, ue_mod_id, GNB_FLAG_NO, NR_UE_rrc_inst[ue_mod_id].rnti, 0, 0, 0);
// check if SRB2 is created, if yes request data_req on SRB2
rb_id_t srb_id = NR_UE_rrc_inst[ue_mod_id].Srb[0][2].status == RB_ESTABLISHED ? 2 : 1;
nr_pdcp_data_req_srb(ctxt.rntiMaybeUEid, srb_id, nr_rrc_mui++, length, buffer, deliver_pdu_srb_rlc, NULL);
break;
}
default:
LOG_E(NR_RRC, "[UE %d] Received unexpected message %s\n", ue_mod_id, ITTI_MSG_NAME(msg_p));
break;
}
LOG_D(NR_RRC, "[UE %d] RRC Status %d\n", ue_mod_id, NR_UE_rrc_inst[ue_mod_id].nrRrcState);
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;
}
void nr_rrc_ue_process_sidelink_radioResourceConfig(
module_id_t Mod_idP,
uint8_t gNB_index,
+1
View File
@@ -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);