CI: rework log analysis to simplify and allow new use cases
The CI has some log analysis, but it is unmaintainable (huge functions
that mix eNB/gNB or lteUE/nrUE, are not tested, most of it is not used
or useful...) or limited to specific use cases (the timing-phytest time
analysis is hardcoded to source builds instead of also handling analysis
when running from docker images). This MR reimplements both functions.
For the log analysis, the CI team decided to throw away the old
analysis, and reimplement a mechanism that checks the couple of things
we care for.
- Allow to analyze phy-test timing analysis from docker files, and add a
unit test
- Rework existing log analysis to remove useless checks, and make it
more composable
* The undeployment steps (Undeploy_Object(), Terminate_eNB()) take an
<analysis> XML object which then either has a <services> subelement
with check that are whitespace delimited (similar to how other xml
task steps have <services>). For checks that contain whitespace,
they can use <service> (singular) that encodes a single check, such
that e.g., arguments could include spaces.
* Each check is of form service=check[=arguments], where service is
the docker services, check is a checking function (implemented as a
class with run(file, options) function inside cls_loganalysis.py,
and options arguments after the second = that is to be read by run()
(basically, options will contain arguments that can be freeform)
* these definitions can occur multiple times, e.g., it could be
serviceA=Check1 and serviceA=Check2=Args and it will execute both
Check1 and Check2
* if a service is declared, it will execute alse the Default check
which currently checks for an assertion
* Implemented (and inspired from the existing CI analysis) are:
- Default check to check for assertions (will be extended, to e.g.,
address/undefined behavior sanitizer analysis)
- RetxCheck: retransmission check as used in the CI
- LastLineContains to check the last line containes a specific
string
- ContainsString to check a specific string appears in logs
- EndsWithBye: check that towards the end (but not necessarily the
last line), there is a Bye. string (a workaround since we don't
always terminate with 0)
- There is a plan to use return codes after stopping in docker, but most
executables do not end with 0 most of the time, such that we needed to
abandon this plan.
- Additional fixes (see commit messages) and delete unused code
507 lines
18 KiB
C
507 lines
18 KiB
C
/*
|
|
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The OpenAirInterface Software Alliance licenses this file to You under
|
|
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.openairinterface.org/?page_id=698
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*-------------------------------------------------------------------------------
|
|
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
|
* contact@openairinterface.org
|
|
*/
|
|
|
|
|
|
#define _GNU_SOURCE /* See feature_test_macros(7) */
|
|
#include <sched.h>
|
|
#include <stdbool.h>
|
|
#include <signal.h>
|
|
#include <errno.h>
|
|
|
|
#include "T.h"
|
|
#include "common/oai_version.h"
|
|
#include "assertions.h"
|
|
#include "PHY/types.h"
|
|
#include "PHY/defs_nr_UE.h"
|
|
#include "SCHED_NR_UE/defs.h"
|
|
#include "common/ran_context.h"
|
|
#include "common/config/config_userapi.h"
|
|
#include "common/utils/load_module_shlib.h"
|
|
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
|
|
#include "common/utils/nr/nr_common.h"
|
|
|
|
#include "radio/COMMON/common_lib.h"
|
|
#include "radio/ETHERNET/if_defs.h"
|
|
|
|
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
|
|
#include "openair1/PHY/MODULATION/nr_modulation.h"
|
|
#include "PHY/CODING/nrLDPC_coding/nrLDPC_coding_interface.h"
|
|
#include "PHY/phy_vars_nr_ue.h"
|
|
#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
|
|
#include "PHY/NR_TRANSPORT/nr_dlsch.h"
|
|
//#include "../../SIMU/USER/init_lte.h"
|
|
|
|
#include "PHY_INTERFACE/phy_interface_vars.h"
|
|
#include "NR_IF_Module.h"
|
|
#include "openair1/SIMULATION/TOOLS/sim.h"
|
|
#include "openair2/RRC/NR_UE/L2_interface_ue.h"
|
|
|
|
#ifdef SMBV
|
|
#include "PHY/TOOLS/smbv.h"
|
|
unsigned short config_frames[4] = {2,9,11,13};
|
|
#endif
|
|
#include "common/utils/LOG/log.h"
|
|
#include "common/utils/time_manager/time_manager.h"
|
|
|
|
#include "UTIL/OPT/opt.h"
|
|
#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
|
|
|
|
#include "intertask_interface.h"
|
|
|
|
#include "PHY/INIT/nr_phy_init.h"
|
|
#include "system.h"
|
|
#include <openair2/RRC/NR_UE/rrc_proto.h>
|
|
#include <openair2/LAYER2/NR_MAC_UE/mac_defs.h>
|
|
#include <openair2/LAYER2/NR_MAC_UE/mac_proto.h>
|
|
#include <openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h>
|
|
#include <openair1/SCHED_NR_UE/fapi_nr_ue_l1.h>
|
|
#include "nr_rlc/nr_rlc_oai_api.h"
|
|
/* Callbacks, globals and object handlers */
|
|
|
|
//#include "stats.h"
|
|
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
|
|
#include "PHY/TOOLS/phy_scope_interface.h"
|
|
#include "PHY/TOOLS/nr_phy_scope.h"
|
|
#include "executables/nr-ue-ru.h"
|
|
#include <executables/nr-uesoftmodem.h>
|
|
#include "executables/softmodem-common.h"
|
|
#include "executables/thread-common.h"
|
|
|
|
#include "nr_nas_msg.h"
|
|
#include <openair1/PHY/MODULATION/nr_modulation.h>
|
|
#include "openair2/GNB_APP/gnb_paramdef.h"
|
|
#include "actor.h"
|
|
|
|
THREAD_STRUCT thread_struct;
|
|
nrUE_params_t nrUE_params = {0};
|
|
|
|
// not used in UE
|
|
instance_t CUuniqInstance=0;
|
|
instance_t DUuniqInstance=0;
|
|
|
|
int get_node_type() {return -1;}
|
|
|
|
RAN_CONTEXT_t RC;
|
|
int oai_exit = 0;
|
|
|
|
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
|
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
|
uint64_t sidelink_frequency[MAX_NUM_CCs][4];
|
|
|
|
// UE and OAI config variables
|
|
double cpuf;
|
|
|
|
int create_tasks_nrue(uint32_t ue_nb) {
|
|
LOG_D(NR_RRC, "%s(ue_nb:%d)\n", __FUNCTION__, ue_nb);
|
|
itti_wait_ready(1);
|
|
|
|
if (ue_nb > 0) {
|
|
LOG_I(NR_RRC,"create TASK_RRC_NRUE \n");
|
|
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;
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
|
|
itti_wait_ready(0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
|
|
{
|
|
LOG_W(NR_PHY, "called by: %s:%d %s() Exiting OAI softmodem: %s\n", file, line, function, s ? s : "no msg");
|
|
|
|
oai_exit = 1;
|
|
|
|
nrue_ru_end();
|
|
|
|
if (assert) {
|
|
abort();
|
|
} else {
|
|
sleep(1); // allow lte-softmodem threads to exit first
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
}
|
|
|
|
uint64_t get_nrUE_optmask(void) {
|
|
return nrUE_params.optmask;
|
|
}
|
|
|
|
uint64_t set_nrUE_optmask(uint64_t bitmask) {
|
|
nrUE_params.optmask = nrUE_params.optmask | bitmask;
|
|
return nrUE_params.optmask;
|
|
}
|
|
|
|
nrUE_params_t *get_nrUE_params(void) {
|
|
return &nrUE_params;
|
|
}
|
|
static void get_options(configmodule_interface_t *cfg)
|
|
{
|
|
paramdef_t cmdline_params[] = CMDLINE_NRUEPARAMS_DESC;
|
|
int numparams = sizeofArray(cmdline_params);
|
|
config_get(cfg, cmdline_params, numparams, NULL);
|
|
AssertFatal(nrUE_params.extra_pdu_id == -1,
|
|
"Add additional PDU sessions in uicc.pdu_sessions array instead\n");
|
|
}
|
|
|
|
// set PHY vars from command line
|
|
static void set_UE_options(int CC_id, PHY_VARS_NR_UE *UE, int ru_id)
|
|
{
|
|
const nrUE_RU_params_t *RU = nrue_get_ru(ru_id);
|
|
|
|
// Set UE variables
|
|
UE->rx_total_gain_dB = RU->max_rxgain - RU->att_rx;
|
|
UE->tx_total_gain_dB = RU->att_tx;
|
|
UE->if_freq = RU->if_frequency;
|
|
UE->if_freq_off = RU->if_freq_offset;
|
|
UE->rf_map.card = ru_id;
|
|
UE->rf_map.chain = CC_id;
|
|
|
|
UE->tx_power_max_dBm = nrUE_params.tx_max_power;
|
|
UE->max_ldpc_iterations = nrUE_params.max_ldpc_iterations;
|
|
UE->UE_scan_carrier = nrUE_params.UE_scan_carrier;
|
|
UE->UE_fo_compensation = nrUE_params.UE_fo_compensation;
|
|
UE->chest_freq = nrUE_params.chest_freq;
|
|
UE->chest_time = nrUE_params.chest_time;
|
|
UE->no_timing_correction = nrUE_params.no_timing_correction;
|
|
UE->initial_fo = nrUE_params.initial_fo;
|
|
UE->cont_fo_comp = nrUE_params.cont_fo_comp;
|
|
|
|
LOG_I(PHY,"Set UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, chest-freq %d, chest-time %d\n",
|
|
UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->chest_freq, UE->chest_time);
|
|
}
|
|
|
|
static void set_fp_options(int cell_id, int ru_id)
|
|
{
|
|
NR_DL_FRAME_PARMS *fp = nrue_get_cell_fp(cell_id);
|
|
const nrUE_RU_params_t *RU = nrue_get_ru(ru_id);
|
|
|
|
// Set FP variables
|
|
fp->nb_antennas_rx = RU->nb_rx;
|
|
fp->nb_antennas_tx = RU->nb_tx;
|
|
|
|
fp->threequarter_fs = get_softmodem_params()->threequarter_fs;
|
|
fp->ofdm_offset_divisor = nrUE_params.ofdm_offset_divisor;
|
|
|
|
LOG_I(PHY, "Set UE nb_rx_antenna %d, nb_tx_antenna %d, threequarter_fs %d, ofdm_offset_divisor %d\n", fp->nb_antennas_rx, fp->nb_antennas_tx, fp->threequarter_fs, fp->ofdm_offset_divisor);
|
|
}
|
|
|
|
// Stupid function addition because UE itti messages queues definition is common with eNB
|
|
void *rrc_enb_process_msg(void *notUsed) {
|
|
return NULL;
|
|
}
|
|
|
|
static bool stop_immediately = false;
|
|
static void trigger_stop(int sig)
|
|
{
|
|
if (!oai_exit)
|
|
itti_wait_tasks_unblock();
|
|
}
|
|
static void trigger_deregistration(int sig)
|
|
{
|
|
if (!stop_immediately && IS_SA_MODE(get_softmodem_params())) {
|
|
for (int ue_inst = 0; ue_inst < NB_UE_INST; ue_inst++) {
|
|
MessageDef *msg = itti_alloc_new_message(TASK_NAS_NRUE, ue_inst, NAS_DEREGISTRATION_REQ);
|
|
NAS_DEREGISTRATION_REQ(msg).cause = AS_DETACH;
|
|
itti_send_msg_to_task(TASK_NAS_NRUE, ue_inst, msg);
|
|
}
|
|
stop_immediately = true;
|
|
static const char m[] = "Press ^C again to trigger immediate shutdown\n";
|
|
__attribute__((unused)) int unused = write(STDOUT_FILENO, m, sizeof(m) - 1);
|
|
signal(SIGALRM, trigger_stop);
|
|
alarm(5);
|
|
} else {
|
|
itti_wait_tasks_unblock();
|
|
}
|
|
}
|
|
|
|
int NB_UE_INST = 1;
|
|
configmodule_interface_t *uniqCfg = NULL;
|
|
nrLDPC_coding_interface_t nrLDPC_coding_interface = {0};
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
start_background_system();
|
|
|
|
if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == NULL || CONFIG_ISFLAGSET(CONFIG_ABORT)) {
|
|
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
|
|
}
|
|
//set_softmodem_sighandler();
|
|
CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
|
|
// initialize logging
|
|
logInit();
|
|
// get options and fill parameters from configuration file
|
|
|
|
get_options(uniqCfg); // Command-line options specific for NRUE
|
|
IS_SOFTMODEM_5GUE = true;
|
|
get_common_options(uniqCfg);
|
|
CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
|
|
|
|
softmodem_verify_mode(get_softmodem_params());
|
|
|
|
#if T_TRACER
|
|
T_Config_Init();
|
|
#endif
|
|
initTpool(get_softmodem_params()->threadPoolConfig, &(nrUE_params.Tpool), cpumeas(CPUMEAS_GETSTATE));
|
|
set_taus_seed (0);
|
|
|
|
if (!has_cap_sys_nice())
|
|
LOG_W(UTIL,
|
|
"no SYS_NICE capability: cannot set thread priority and affinity, consider running with sudo for optimum performance\n");
|
|
|
|
cpuf=get_cpu_freq_GHz();
|
|
itti_init(TASK_MAX, tasks_info);
|
|
|
|
init_opt();
|
|
|
|
int ret_loader = load_nrLDPC_coding_interface(NULL, &nrLDPC_coding_interface);
|
|
AssertFatal(ret_loader == 0, "error loading LDPC library\n");
|
|
|
|
// strdup to put the sring in the core file for post mortem identification
|
|
char *pckg = strdup(OAI_PACKAGE_VERSION);
|
|
LOG_I(HW, "Version: %s\n", pckg);
|
|
|
|
PHY_vars_UE_g = calloc_or_fail(NB_UE_INST, sizeof(*PHY_vars_UE_g));
|
|
for (int inst = 0; inst < NB_UE_INST; inst++) {
|
|
PHY_vars_UE_g[inst] = calloc_or_fail(MAX_NUM_CCs, sizeof(*PHY_vars_UE_g[inst]));
|
|
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
|
PHY_vars_UE_g[inst][CC_id] = calloc_or_fail(1, sizeof(*PHY_vars_UE_g[inst][CC_id]));
|
|
// All instances use the same coding interface
|
|
PHY_vars_UE_g[inst][CC_id]->nrLDPC_coding_interface = nrLDPC_coding_interface;
|
|
}
|
|
}
|
|
|
|
if (create_tasks_nrue(1) < 0) {
|
|
printf("cannot create ITTI tasks\n");
|
|
exit(-1); // need a softer mode
|
|
}
|
|
|
|
nr_pdcp_layer_init();
|
|
nas_init_nrue(NB_UE_INST);
|
|
|
|
nrue_set_ru_params(uniqCfg);
|
|
nrue_set_cell_params(uniqCfg);
|
|
|
|
init_NR_UE(NB_UE_INST,
|
|
get_nrUE_params()->uecap_file,
|
|
get_nrUE_params()->reconfig_file,
|
|
get_nrUE_params()->rbconfig_file,
|
|
nrue_get_cell(0)->numerology);
|
|
|
|
// start time manager with some reasonable default for the running mode
|
|
// (may be overwritten in configuration file or command line)
|
|
void nr_pdcp_ms_tick(void);
|
|
void nr_rlc_ms_tick(void);
|
|
time_manager_tick_function_t tick_functions[] = {
|
|
nr_pdcp_ms_tick,
|
|
nr_rlc_ms_tick
|
|
};
|
|
int tick_functions_count = 2;
|
|
time_manager_start(tick_functions, tick_functions_count,
|
|
// iq_samples time source for rfsim,
|
|
// realtime time source if not
|
|
IS_SOFTMODEM_RFSIM ? TIME_SOURCE_IQ_SAMPLES
|
|
: TIME_SOURCE_REALTIME);
|
|
|
|
// initialize per-cell frame parameters
|
|
for (int cell_id = 0; cell_id < nrue_get_cell_count(); cell_id++) {
|
|
int ru_id = nrue_get_cell(cell_id)->ru_id;
|
|
AssertFatal(ru_id >= 0 && ru_id < nrue_get_ru_count(),
|
|
"Invalid ru_id (%d) for cell %d. Should be >= 0 and < %d\n",
|
|
ru_id,
|
|
cell_id,
|
|
nrue_get_ru_count());
|
|
AssertFatal(nrue_get_ru(ru_id)->used_by_cell == -1,
|
|
"RU %d is already used by cell %d and therefore cannot also be used by cell %d\n",
|
|
ru_id,
|
|
nrue_get_ru(ru_id)->used_by_cell,
|
|
cell_id);
|
|
nrue_set_ru_cell_id(ru_id, cell_id);
|
|
|
|
set_fp_options(cell_id, ru_id);
|
|
if (IS_SA_MODE(get_softmodem_params()) || get_softmodem_params()->sl_mode)
|
|
nr_init_frame_parms_ue_sa(nrue_get_cell_fp(cell_id), nrue_get_cell(cell_id));
|
|
}
|
|
|
|
int cell_id = 0;
|
|
for (int inst = 0; inst < NB_UE_INST; inst++) {
|
|
NR_UE_MAC_INST_t *mac = get_mac_inst(inst);
|
|
|
|
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
|
PHY_VARS_NR_UE *UE_CC = PHY_vars_UE_g[inst][CC_id];
|
|
|
|
AssertFatal(cell_id >= 0 && cell_id < nrue_get_cell_count(),
|
|
"There are not enough cell definitions for all UEs! NB_UE_INST = %d, MAX_NUM_CCs = %d, nrue_cell_count = %d\n",
|
|
NB_UE_INST,
|
|
MAX_NUM_CCs,
|
|
nrue_get_cell_count());
|
|
nrUE_cell_params_t cell = *nrue_get_cell(cell_id);
|
|
|
|
AssertFatal(cell.used_by_ue == -1,
|
|
"Cell %d is already used by UE %d and cannot also be used by UE %d as cells map 1:1 to RUs and RU sharing is not implemented\n",
|
|
cell_id,
|
|
cell.used_by_ue,
|
|
inst);
|
|
cell.used_by_ue = inst;
|
|
|
|
set_UE_options(CC_id, UE_CC, cell.ru_id);
|
|
init_nr_ue_phy_cpu_stats(&UE_CC->phy_cpu_stats);
|
|
|
|
NR_DL_FRAME_PARMS *fp = nrue_get_cell_fp(cell_id);
|
|
if (!IS_SA_MODE(get_softmodem_params()) && !get_softmodem_params()->sl_mode) {
|
|
do {
|
|
notifiedFIFO_elt_t *elt = pollNotifiedFIFO(&mac->input_nf);
|
|
if (!elt) {
|
|
break;
|
|
}
|
|
process_msg_rcc_to_mac(NotifiedFifoData(elt), inst);
|
|
delNotifiedFIFO_elt(elt);
|
|
} while (true);
|
|
fapi_nr_config_request_t *nrUE_config = &UE_CC->nrUE_config;
|
|
nr_init_frame_parms_ue(fp, nrUE_config, mac->nr_band);
|
|
|
|
cell.band = mac->nr_band;
|
|
cell.rf_frequency = fp->dl_CarrierFreq;
|
|
cell.rf_freq_offset = fp->ul_CarrierFreq - fp->dl_CarrierFreq;
|
|
cell.numerology = fp->numerology_index;
|
|
cell.N_RB_DL = fp->N_RB_DL;
|
|
cell.ssb_start = fp->ssb_start_subcarrier;
|
|
}
|
|
nrue_set_cell(cell_id, &cell);
|
|
|
|
UE_CC->frame_parms = *fp;
|
|
mac->nr_band = cell.band;
|
|
mac->ssb_start_subcarrier = cell.ssb_start;
|
|
mac->dl_frequency = cell.rf_frequency;
|
|
|
|
UE_CC->sl_mode = get_softmodem_params()->sl_mode;
|
|
init_actor(&UE_CC->sync_actor, "SYNC_", -1);
|
|
if (get_nrUE_params()->num_dl_actors > 0) {
|
|
UE_CC->dl_actors = calloc_or_fail(get_nrUE_params()->num_dl_actors, sizeof(*UE_CC->dl_actors));
|
|
for (int i = 0; i < get_nrUE_params()->num_dl_actors; i++) {
|
|
init_actor(&UE_CC->dl_actors[i], "DL_", -1);
|
|
}
|
|
}
|
|
if (get_nrUE_params()->num_ul_actors > 0) {
|
|
UE_CC->ul_actors = calloc_or_fail(get_nrUE_params()->num_ul_actors, sizeof(*UE_CC->ul_actors));
|
|
for (int i = 0; i < get_nrUE_params()->num_ul_actors; i++) {
|
|
init_actor(&UE_CC->ul_actors[i], "UL_", -1);
|
|
}
|
|
}
|
|
init_nr_ue_vars(UE_CC, inst);
|
|
|
|
if (UE_CC->sl_mode) {
|
|
AssertFatal(UE_CC->sl_mode == 2, "Only Sidelink mode 2 supported. Mode 1 not yet supported\n");
|
|
DevAssert(mac->if_module != NULL && mac->if_module->sl_phy_config_request != NULL);
|
|
nr_sl_phy_config_t *phycfg = &mac->SL_MAC_PARAMS->sl_phy_config;
|
|
phycfg->sl_config_req.sl_carrier_config.sl_num_rx_ant = get_nrUE_params()->nb_antennas_rx;
|
|
phycfg->sl_config_req.sl_carrier_config.sl_num_tx_ant = get_nrUE_params()->nb_antennas_tx;
|
|
mac->if_module->sl_phy_config_request(phycfg);
|
|
sl_nr_ue_phy_params_t *sl_phy = &UE_CC->SL_UE_PHY_PARAMS;
|
|
nr_init_frame_parms_ue_sl(&sl_phy->sl_frame_params,
|
|
&sl_phy->sl_config,
|
|
get_softmodem_params()->threequarter_fs,
|
|
get_nrUE_params()->ofdm_offset_divisor);
|
|
sl_ue_phy_init(UE_CC);
|
|
}
|
|
|
|
cell_id++; // initially connect each UE and carrier to its own cell
|
|
}
|
|
}
|
|
|
|
nrue_init_openair0();
|
|
|
|
lock_memory_to_ram();
|
|
|
|
if (IS_SOFTMODEM_DOSCOPE) {
|
|
load_softscope("nr", PHY_vars_UE_g[0][0]);
|
|
}
|
|
if (IS_SOFTMODEM_IMSCOPE_ENABLED) {
|
|
load_softscope("im", PHY_vars_UE_g[0][0]);
|
|
}
|
|
AssertFatal(!(IS_SOFTMODEM_IMSCOPE_ENABLED && IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED),
|
|
"Data recoding and ImScope cannot be enabled at the same time\n");
|
|
if (IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED) {
|
|
load_module_shlib("imscope_record", NULL, 0, PHY_vars_UE_g[0][0]);
|
|
}
|
|
|
|
nrue_ru_start();
|
|
|
|
for (int inst = 0; inst < NB_UE_INST; inst++) {
|
|
LOG_I(PHY,"Intializing UE Threads for instance %d ...\n", inst);
|
|
init_NR_UE_threads(PHY_vars_UE_g[inst][0]);
|
|
}
|
|
printf("UE threads created by %ld\n", gettid());
|
|
|
|
// wait for end of program
|
|
printf("TYPE <CTRL-C> TO TERMINATE\n");
|
|
|
|
// Sleep a while before checking all parameters have been used
|
|
// Some are used directly in external threads, asynchronously
|
|
sleep(2);
|
|
config_check_unknown_cmdlineopt(uniqCfg, CONFIG_CHECKALLSECTIONS);
|
|
|
|
// wait for end of program
|
|
printf("Entering ITTI signals handler\n");
|
|
printf("TYPE <CTRL-C> TO TERMINATE\n");
|
|
itti_wait_tasks_end(trigger_deregistration);
|
|
LOG_W(NR_PHY, "Returned from ITTI signal handler\n");
|
|
oai_exit = 1;
|
|
|
|
if (PHY_vars_UE_g && PHY_vars_UE_g[0]) {
|
|
for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
|
|
PHY_VARS_NR_UE *phy_vars = PHY_vars_UE_g[0][CC_id];
|
|
if (phy_vars) {
|
|
for (int i = 0; i < get_nrUE_params()->num_ul_actors; i++) {
|
|
shutdown_actor(&phy_vars->ul_actors[i]);
|
|
}
|
|
for (int i = 0; i < get_nrUE_params()->num_dl_actors; i++) {
|
|
shutdown_actor(&phy_vars->dl_actors[i]);
|
|
}
|
|
int ret = pthread_join(phy_vars->main_thread, NULL);
|
|
AssertFatal(ret == 0, "pthread_join error %d, errno %d (%s)\n", ret, errno, strerror(errno));
|
|
if (!IS_SOFTMODEM_NOSTATS) {
|
|
ret = pthread_join(phy_vars->stat_thread, NULL);
|
|
AssertFatal(ret == 0, "pthread_join error %d, errno %d (%s)\n", ret, errno, strerror(errno));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
nrue_ru_end();
|
|
|
|
free_nrLDPC_coding_interface(&nrLDPC_coding_interface);
|
|
|
|
time_manager_finish();
|
|
|
|
free(pckg);
|
|
printf("Bye.\n");
|
|
return 0;
|
|
}
|
|
|