Files
openairinterface5g/executables/nr-softmodem.c
T
Robert Schmidt 68f8ef7c7a Reduce amount of logs in L1/L2
This commit removes many logs that just show memory addresses, indices,
etc., which, I presume, do not mean anything to the "average user" and
developers alike.
2024-10-29 16:36:13 +01:00

776 lines
25 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 "T.h"
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
#include <common/utils/assertions.h>
#include "common/oai_version.h"
#include "PHY/types.h"
#include "common/ran_context.h"
#include "PHY/defs_gNB.h"
#include "PHY/defs_common.h"
#include "common/config/config_userapi.h"
#include "common/utils/load_module_shlib.h"
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
#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 "PHY/phy_vars.h"
#include "RRC/LTE/rrc_vars.h"
#include "PHY_INTERFACE/phy_interface_vars.h"
#include "gnb_config.h"
#include "SIMULATION/TOOLS/sim.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/LOG/vcd_signal_dumper.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/GNB_APP/gnb_app.h>
#include "PHY/TOOLS/phy_scope_interface.h"
#include "PHY/TOOLS/nr_phy_scope.h"
#include "nr-softmodem.h"
#include "executables/softmodem-common.h"
#include "executables/thread-common.h"
#include "NB_IoT_interface.h"
#include "x2ap_eNB.h"
#include "ngap_gNB.h"
#include "gnb_paramdef.h"
#include <openair3/ocp-gtpu/gtp_itf.h>
#include "nfapi/oai_integration/vendor_ext.h"
#include "gnb_config.h"
#include "openair2/E1AP/e1ap_common.h"
#include "LAYER2/NR_MAC_gNB/nr_mac_gNB.h"
#ifdef ENABLE_AERIAL
#include "nfapi/oai_integration/aerial/fapi_nvIPC.h"
#endif
#ifdef E2_AGENT
#include "openair2/E2AP/flexric/src/agent/e2_agent_api.h"
#include "openair2/E2AP/RAN_FUNCTION/init_ran_func.h"
#endif
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex
extern uint8_t nfapi_mode; // Default to monolithic mode
THREAD_STRUCT thread_struct;
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
int config_sync_var=-1;
volatile int start_gNB = 0;
int oai_exit = 0;
int NB_UE_INST = 0;
static int wait_for_sync = 0;
unsigned int mmapped_dma=0;
uint64_t downlink_frequency[MAX_NUM_CCs][4];
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
//Temp fix for inexistent NR upper layer
unsigned char NB_gNB_INST = 1;
char *uecap_file;
runmode_t mode = normal_txrx;
#if MAX_NUM_CCs == 1
rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
#else
rx_gain_t rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}};
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
#endif
double rx_gain_off = 0.0;
static int tx_max_power[MAX_NUM_CCs]; /* = {0,0}*/;
int chain_offset=0;
uint8_t dci_Format = 0;
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
int otg_enabled;
extern void *udp_eNB_task(void *args_p);
int transmission_mode=1;
int emulate_rf = 0;
int numerology = 0;
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;
double cpuf;
/* hack: pdcp_run() is required by 4G scheduler which is compiled into
* nr-softmodem because of linker issues */
void pdcp_run(const protocol_ctxt_t *const ctxt_pP)
{
abort();
}
/* forward declarations */
void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs], NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
/*---------------------BMC: timespec helpers -----------------------------*/
struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
struct timespec clock_difftime(struct timespec start, struct timespec end) {
struct timespec temp;
if ((end.tv_nsec-start.tv_nsec)<0) {
temp.tv_sec = end.tv_sec-start.tv_sec-1;
temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
} else {
temp.tv_sec = end.tv_sec-start.tv_sec;
temp.tv_nsec = end.tv_nsec-start.tv_nsec;
}
return temp;
}
void print_difftimes(void)
{
LOG_I(HW, "difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
}
void update_difftimes(struct timespec start, struct timespec end) {
struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
int changed = 0;
diff_time = clock_difftime(start, end);
if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) {
min_diff_time.tv_nsec = diff_time.tv_nsec;
changed = 1;
}
if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) {
max_diff_time.tv_nsec = diff_time.tv_nsec;
changed = 1;
}
#if 1
if (changed) print_difftimes();
#endif
}
/*------------------------------------------------------------------------*/
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
}
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
}
#define KNRM "\x1B[0m"
#define KRED "\x1B[31m"
#define KGRN "\x1B[32m"
#define KBLU "\x1B[34m"
#define RESET "\033[0m"
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
{
int ru_id;
if (s != NULL) {
printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, s);
}
oai_exit = 1;
if (RC.ru == NULL)
exit(-1); // likely init not completed, prevent crash or hang, exit now...
for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
if (RC.ru[ru_id] && RC.ru[ru_id]->rfdevice.trx_end_func) {
RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
}
if (RC.ru[ru_id] && RC.ru[ru_id]->ifdevice.trx_end_func) {
RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
}
}
if (assert) {
abort();
} else {
sleep(1); // allow nr-softmodem threads to exit first
exit(EXIT_SUCCESS);
}
}
static int create_gNB_tasks(ngran_node_t node_type, configmodule_interface_t *cfg)
{
uint32_t gnb_nb = RC.nb_nr_inst;
uint32_t gnb_id_start = 0;
uint32_t gnb_id_end = gnb_id_start + gnb_nb;
LOG_D(GNB_APP, "%s(gnb_nb:%d)\n", __FUNCTION__, gnb_nb);
itti_wait_ready(1);
LOG_D(PHY, "%s() Task ready initialize structures\n", __FUNCTION__);
#ifdef ENABLE_AERIAL
AssertFatal(NFAPI_MODE == NFAPI_MODE_AERIAL,"Can only be run with '--nfapi AERIAL' when compiled with AERIAL support, if you want to run other (n)FAPI modes, please run ./build_oai without -w AERIAL");
#endif
RCconfig_verify(cfg, node_type);
if(NFAPI_MODE != NFAPI_MODE_AERIAL){
RCconfig_nr_prs();
}
if (RC.nb_nr_macrlc_inst > 0)
RCconfig_nr_macrlc(cfg);
LOG_D(PHY, "%s() RC.nb_nr_L1_inst:%d\n", __FUNCTION__, RC.nb_nr_L1_inst);
if (RC.nb_nr_L1_inst>0) AssertFatal(l1_north_init_gNB()==0,"could not initialize L1 north interface\n");
AssertFatal (gnb_nb <= RC.nb_nr_inst,
"Number of gNB is greater than gNB defined in configuration file (%d/%d)!",
gnb_nb, RC.nb_nr_inst);
LOG_D(GNB_APP, "Allocating gNB_RRC_INST for %d instances\n", RC.nb_nr_inst);
if (RC.nb_nr_inst > 0) {
AssertFatal(RC.nb_nr_inst == 1, "multiple RRC instances are not supported\n");
RC.nrrrc = calloc(1, sizeof(*RC.nrrrc));
RC.nrrrc[0] = calloc(1,sizeof(gNB_RRC_INST));
RCconfig_NRRRC(RC.nrrrc[0]);
}
if (RC.nb_nr_inst > 0 &&
!get_softmodem_params()->nsa &&
!(node_type == ngran_gNB_DU)) {
// we start pdcp in both cuup (for drb) and cucp (for srb)
init_pdcp();
}
if (is_x2ap_enabled() ) { //&& !NODE_IS_DU(node_type)
LOG_I(X2AP, "X2AP enabled \n");
__attribute__((unused)) uint32_t x2_register_gnb_pending = gNB_app_register_x2 (gnb_id_start, gnb_id_end);
}
/* For the CU case the gNB registration with the AMF might have to take place after the F1 setup, as the PLMN info
* can originate from the DU. Add check on whether x2ap is enabled to account for ENDC NSA scenario.*/
if ((get_softmodem_params()->sa || is_x2ap_enabled()) &&
!NODE_IS_DU(node_type)) {
/* Try to register each gNB */
//registered_gnb = 0;
__attribute__((unused)) uint32_t register_gnb_pending = gNB_app_register (gnb_id_start, gnb_id_end);
}
if (gnb_nb > 0) {
if(itti_create_task(TASK_SCTP, sctp_eNB_task, NULL) < 0) {
LOG_E(SCTP, "Create task for SCTP failed\n");
return -1;
}
if (is_x2ap_enabled()) {
if(itti_create_task(TASK_X2AP, x2ap_task, NULL) < 0) {
LOG_E(X2AP, "Create task for X2AP failed\n");
}
} else {
LOG_I(X2AP, "X2AP is disabled.\n");
}
}
if (get_softmodem_params()->sa &&
!NODE_IS_DU(node_type)) {
char* gnb_ipv4_address_for_NGU = NULL;
uint32_t gnb_port_for_NGU = 0;
char* gnb_ipv4_address_for_S1U = NULL;
uint32_t gnb_port_for_S1U = 0;
paramdef_t NETParams[] = GNBNETPARAMS_DESC;
char aprefix[MAX_OPTNAME_SIZE*2 + 8];
sprintf(aprefix,"%s.[%i].%s",GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG);
config_get(cfg, NETParams, sizeofArray(NETParams), aprefix);
if (gnb_nb > 0) {
if (itti_create_task (TASK_NGAP, ngap_gNB_task, NULL) < 0) {
LOG_E(NGAP, "Create task for NGAP failed\n");
return -1;
}
}
}
if (gnb_nb > 0) {
if (itti_create_task (TASK_GNB_APP, gNB_app_task, NULL) < 0) {
LOG_E(GNB_APP, "Create task for gNB APP failed\n");
return -1;
}
if (!NODE_IS_DU(node_type)) {
if (itti_create_task (TASK_RRC_GNB, rrc_gnb_task, NULL) < 0) {
LOG_E(NR_RRC, "Create task for NR RRC gNB failed\n");
return -1;
}
}
// E1AP initialisation, whether the node is a CU or has integrated CU
if (node_type == ngran_gNB_CU || node_type == ngran_gNB) {
MessageDef *msg = RCconfig_NR_CU_E1(NULL);
instance_t inst = 0;
createE1inst(UPtype, inst, E1AP_REGISTER_REQ(msg).gnb_id, &E1AP_REGISTER_REQ(msg).net_config, NULL);
cuup_init_n3(inst);
RC.nrrrc[gnb_id_start]->e1_inst = inst; // stupid instance !!!*/
/* send E1 Setup Request to RRC */
MessageDef *new_msg = itti_alloc_new_message(TASK_GNB_APP, 0, E1AP_SETUP_REQ);
E1AP_SETUP_REQ(new_msg) = E1AP_REGISTER_REQ(msg).setup_req;
new_msg->ittiMsgHeader.originInstance = -1; /* meaning, it is local */
itti_send_msg_to_task(TASK_RRC_GNB, 0 /*unused by callee*/, new_msg);
itti_free(TASK_UNKNOWN, msg);
}
//Use check on x2ap to consider the NSA scenario
if((is_x2ap_enabled() || get_softmodem_params()->sa) && (node_type != ngran_gNB_CUCP)) {
if (itti_create_task (TASK_GTPV1_U, &gtpv1uTask, NULL) < 0) {
LOG_E(GTPU, "Create task for GTPV1U failed\n");
return -1;
}
}
}
return 0;
}
static void get_options(configmodule_interface_t *cfg)
{
paramdef_t cmdline_params[] = CMDLINE_PARAMS_DESC_GNB ;
CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
get_common_options(cfg, SOFTMODEM_GNB_BIT);
config_process_cmdline(cfg, cmdline_params, sizeofArray(cmdline_params), NULL);
CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
memset((void *)&RC,0,sizeof(RC));
/* Read RC configuration file */
NRRCConfig();
NB_gNB_INST = RC.nb_nr_inst;
NB_RU = RC.nb_RU;
}
}
void set_default_frame_parms(nfapi_nr_config_request_scf_t *config[MAX_NUM_CCs],
NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
frame_parms[CC_id] = (NR_DL_FRAME_PARMS *) malloc(sizeof(NR_DL_FRAME_PARMS));
config[CC_id] = (nfapi_nr_config_request_scf_t *) malloc(sizeof(nfapi_nr_config_request_scf_t));
config[CC_id]->ssb_config.scs_common.value = 1;
config[CC_id]->cell_config.frame_duplex_type.value = 1; //FDD
//config[CC_id]->subframe_config.dl_cyclic_prefix_type.value = 0; //NORMAL
config[CC_id]->carrier_config.dl_grid_size[1].value = 106;
config[CC_id]->carrier_config.ul_grid_size[1].value = 106;
config[CC_id]->cell_config.phy_cell_id.value = 0;
///dl frequency to be filled in
/* //Set some default values that may be overwritten while reading options
frame_parms[CC_id]->frame_type = FDD;
frame_parms[CC_id]->tdd_config = 3;
frame_parms[CC_id]->tdd_config_S = 0;
frame_parms[CC_id]->N_RB_DL = 100;
frame_parms[CC_id]->N_RB_UL = 100;
frame_parms[CC_id]->Ncp = NORMAL;
frame_parms[CC_id]->Ncp_UL = NORMAL;
frame_parms[CC_id]->Nid_cell = 0;
frame_parms[CC_id]->num_MBSFN_config = 0;
frame_parms[CC_id]->nb_antenna_ports_gNB = 1;
frame_parms[CC_id]->nb_antennas_tx = 1;
frame_parms[CC_id]->nb_antennas_rx = 1;
frame_parms[CC_id]->nushift = 0;
frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth;
frame_parms[CC_id]->phich_config_common.phich_duration = normal;
// UL RS Config
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0;
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0;
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0;
frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0;
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;
// downlink_frequency[CC_id][0] = 2680000000; // Use float to avoid issue with frequency over 2^31.
// downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
// downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
// downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0];
frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
*/
}
}
void wait_RUs(void) {
LOG_D(PHY, "Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask);
// wait for all RUs to be configured over fronthaul
pthread_mutex_lock(&RC.ru_mutex);
while (RC.ru_mask>0) {
pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
}
pthread_mutex_unlock(&RC.ru_mutex);
LOG_D(PHY, "RUs configured\n");
}
void wait_gNBs(void) {
int i;
int waiting=1;
while (waiting==1) {
LOG_D(GNB_APP, "Waiting for gNB L1 instances to all get configured ... sleeping 50ms (nb_nr_sL1_inst %d)\n", RC.nb_nr_L1_inst);
usleep(50*1000);
waiting=0;
for (i=0; i<RC.nb_nr_L1_inst; i++) {
if (RC.gNB[i]->configured==0) {
waiting=1;
break;
}
}
}
LOG_D(GNB_APP, "gNB L1 are configured\n");
}
/*
* helper function to terminate a certain ITTI task
*/
void terminate_task(task_id_t task_id, module_id_t mod_id) {
LOG_I(GNB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id);
MessageDef *msg;
msg = itti_alloc_new_message (TASK_ENB_APP, 0, TERMINATE_MESSAGE);
itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
}
//extern void free_transport(PHY_VARS_gNB *);
extern void nr_phy_free_RU(RU_t *);
static void wait_nfapi_init(char *thread_name)
{
pthread_mutex_lock( &nfapi_sync_mutex );
while (nfapi_sync_var<0)
pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
pthread_mutex_unlock(&nfapi_sync_mutex);
}
void init_pdcp(void) {
uint32_t pdcp_initmask = IS_SOFTMODEM_NOS1 ? ENB_NAS_USE_TUN_BIT : LINK_ENB_PDCP_TO_GTPV1U_BIT;
if (!NODE_IS_DU(get_node_type())) {
nr_pdcp_layer_init();
nr_pdcp_module_init(pdcp_initmask, 0);
}
}
#ifdef E2_AGENT
#include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" // need to get info from MAC
static void initialize_agent(ngran_node_t node_type, e2_agent_args_t oai_args)
{
AssertFatal(oai_args.sm_dir != NULL , "Please, specify the directory where the SMs are located in the config file, i.e., add in config file the next line: e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\");} ");
AssertFatal(oai_args.ip != NULL , "Please, specify the IP address of the nearRT-RIC in the config file, i.e., e2_agent = {near_ric_ip_addr = \"127.0.0.1\"; sm_dir = \"/usr/local/lib/flexric/\"");
printf("After RCconfig_NR_E2agent %s %s \n",oai_args.sm_dir, oai_args.ip );
fr_args_t args = { .ip = oai_args.ip }; // init_fr_args(0, NULL);
memcpy(args.libs_dir, oai_args.sm_dir, 128);
sleep(1);
const gNB_RRC_INST* rrc = RC.nrrrc[0];
assert(rrc != NULL && "rrc cannot be NULL");
const int mcc = rrc->configuration.mcc[0];
const int mnc = rrc->configuration.mnc[0];
const int mnc_digit_len = rrc->configuration.mnc_digit_length[0];
// const ngran_node_t node_type = rrc->node_type;
int nb_id = 0;
int cu_du_id = 0;
if (node_type == ngran_gNB) {
nb_id = rrc->node_id;
} else if (node_type == ngran_gNB_DU) {
const gNB_MAC_INST* mac = RC.nrmac[0];
AssertFatal(mac, "MAC not initialized\n");
cu_du_id = mac->f1_config.gnb_id;
nb_id = mac->f1_config.setup_req->gNB_DU_id;
} else if (node_type == ngran_gNB_CU || node_type == ngran_gNB_CUCP) {
// agent buggy: the CU has no second ID, it is the CU-UP ID
// however, that is not a problem her for us, so put the same ID twice
nb_id = rrc->node_id;
cu_du_id = rrc->node_id;
} else {
LOG_E(NR_RRC, "not supported ran type detect\n");
}
printf("[E2 NODE]: mcc = %d mnc = %d mnc_digit = %d nb_id = %d \n", mcc, mnc, mnc_digit_len, nb_id);
printf("[E2 NODE]: Args %s %s \n", args.ip, args.libs_dir);
sm_io_ag_ran_t io = init_ran_func_ag();
init_agent_api(mcc, mnc, mnc_digit_len, nb_id, cu_du_id, node_type, io, &args);
}
#endif
void init_eNB_afterRU(void);
configmodule_interface_t *uniqCfg = NULL;
int main( int argc, char **argv ) {
int ru_id, CC_id = 0;
start_background_system();
///static configuration for NR at the moment
if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == NULL) {
exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
}
set_softmodem_sighandler();
#ifdef DEBUG_CONSOLE
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
#endif
mode = normal_txrx;
memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
logInit();
lock_memory_to_ram();
get_options(uniqCfg);
EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
fprintf(stderr,"Getting configuration failed\n");
exit(-1);
}
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");
if (get_softmodem_params()->do_ra)
AssertFatal(get_softmodem_params()->phy_test == 0,"RA and phy_test are mutually exclusive\n");
if (get_softmodem_params()->sa)
AssertFatal(get_softmodem_params()->phy_test == 0,"Standalone mode and phy_test are mutually exclusive\n");
#if T_TRACER
T_Config_Init();
#endif
//randominit (0);
set_taus_seed (0);
cpuf=get_cpu_freq_GHz();
itti_init(TASK_MAX, tasks_info);
// initialize mscgen log after ITTI
init_opt();
// 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);
// don't create if node doesn't connect to RRC/S1/GTP
const ngran_node_t node_type = get_node_type();
if (RC.nb_nr_L1_inst > 0)
RCconfig_NR_L1();
if (NFAPI_MODE != NFAPI_MODE_PNF) {
int ret = create_gNB_tasks(node_type, uniqCfg);
AssertFatal(ret == 0, "cannot create ITTI tasks\n");
}
pthread_cond_init(&sync_cond,NULL);
pthread_mutex_init(&sync_mutex, NULL);
usleep(1000);
if (NFAPI_MODE && NFAPI_MODE != NFAPI_MODE_AERIAL) {
pthread_cond_init(&sync_cond,NULL);
pthread_mutex_init(&sync_mutex, NULL);
}
// start the main threads
number_of_cards = 1;
if (RC.nb_nr_L1_inst > 0) {
init_gNB(wait_for_sync);
}
wait_gNBs();
int sl_ahead = NFAPI_MODE == NFAPI_MODE_AERIAL ? 0 : 6;
if (RC.nb_RU >0) {
init_NR_RU(uniqCfg, get_softmodem_params()->rf_config_file);
for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
RC.ru[ru_id]->rf_map.card=0;
RC.ru[ru_id]->rf_map.chain=CC_id+chain_offset;
if (ru_id==0) sl_ahead = RC.ru[ru_id]->sl_ahead;
else AssertFatal(RC.ru[ru_id]->sl_ahead != RC.ru[0]->sl_ahead,"RU %d has different sl_ahead %d than RU 0 %d\n",ru_id,RC.ru[ru_id]->sl_ahead,RC.ru[0]->sl_ahead);
}
}
config_sync_var=0;
#ifdef E2_AGENT
//////////////////////////////////
//////////////////////////////////
//// Init the E2 Agent
// OAI Wrapper
e2_agent_args_t oai_args = RCconfig_NR_E2agent();
if (oai_args.enabled) {
initialize_agent(node_type, oai_args);
}
#endif // E2_AGENT
if (NFAPI_MODE==NFAPI_MODE_PNF) {
wait_nfapi_init("main?");
}
// wait for F1 Setup Response before starting L1 for real
if (NODE_IS_DU(node_type) || NODE_IS_MONOLITHIC(node_type))
wait_f1_setup_response();
if (RC.nb_RU > 0)
start_NR_RU();
#ifdef ENABLE_AERIAL
gNB_MAC_INST *nrmac = RC.nrmac[0];
nvIPC_Init(nrmac->nvipc_params_s);
#endif
if (RC.nb_nr_L1_inst > 0) {
wait_RUs();
// once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration)
for (int idx=0;idx<RC.nb_nr_L1_inst;idx++) RC.gNB[idx]->if_inst->sl_ahead = sl_ahead;
if (IS_SOFTMODEM_DOSCOPE || IS_SOFTMODEM_IMSCOPE_ENABLED) {
sleep(1);
scopeParms_t p;
p.argc = &argc;
p.argv = argv;
p.gNB = RC.gNB[0];
p.ru = RC.ru[0];
if (IS_SOFTMODEM_DOSCOPE) {
load_softscope("nr", &p);
}
if (IS_SOFTMODEM_IMSCOPE_ENABLED) {
load_softscope("im", &p);
}
}
if (NFAPI_MODE != NFAPI_MODE_PNF && NFAPI_MODE != NFAPI_MODE_VNF && NFAPI_MODE != NFAPI_MODE_AERIAL) {
init_eNB_afterRU();
}
// connect the TX/RX buffers
pthread_mutex_lock(&sync_mutex);
sync_var=0;
pthread_cond_broadcast(&sync_cond);
pthread_mutex_unlock(&sync_mutex);
}
// wait for end of program
printf("TYPE <CTRL-C> TO TERMINATE\n");
itti_wait_tasks_end(NULL);
printf("Returned from ITTI signal handler\n");
oai_exit=1;
// cleanup
if (RC.nb_nr_L1_inst > 0)
stop_gNB(RC.nb_nr_L1_inst);
if (RC.nb_RU > 0)
stop_RU(RC.nb_RU);
/* release memory used by the RU/gNB threads (incomplete), after all
* threads have been stopped (they partially use the same memory) */
for (int inst = 0; inst < RC.nb_RU; inst++) {
nr_phy_free_RU(RC.ru[inst]);
}
for (int inst = 0; inst < RC.nb_nr_L1_inst; inst++) {
phy_free_nr_gNB(RC.gNB[inst]);
}
pthread_cond_destroy(&sync_cond);
pthread_mutex_destroy(&sync_mutex);
pthread_cond_destroy(&nfapi_sync_cond);
pthread_mutex_destroy(&nfapi_sync_mutex);
// *** Handle per CC_id openair0
for(ru_id = 0; ru_id < RC.nb_RU; ru_id++) {
if (RC.ru[ru_id]->ifdevice.trx_end_func)
RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
}
free(pckg);
logClean();
printf("Bye.\n");
return 0;
}