:::warning
# <center><i class="fa fa-edit"></i> Begining of Main function </center>
:::
[TOC]
### E2 Agent headers
```c=
#include "agent_if/read/sm_ag_if_rd.h"
#include "agent_if/sm_io.h"
#include "agent_if/e2_agent_api.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_entity.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp_entity.h"
#include "openair2/LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "openair2/LAYER2/nr_pdcp/nr_pdcp.h"
#include <time.h>
```
### Main function
```c=
int main( int argc, char **argv ) {
int ru_id, CC_id = 0;
start_background_system();
///static configuration for NR at the moment
if ( 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(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
logInit();
configure_linux();
printf("Reading in command-line options\n");
get_options ();
if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
fprintf(stderr,"Getting configuration failed\n");
exit(-1);
}
openair0_cfg[0].threequarter_fs = threequarter_fs;
AMF_MODE_ENABLED = get_softmodem_params()->sa;
NGAP_CONF_MODE = get_softmodem_params()->sa;
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);
printf("configuring for RAU/RRU\n");
if (opp_enabled ==1) {
reset_opp_meas();
}
cpuf=get_cpu_freq_GHz();
itti_init(TASK_MAX, tasks_info);
// initialize mscgen log after ITTI
MSC_INIT(MSC_E_UTRAN, ADDED_QUEUES_MAX+TASK_MAX);
init_opt();
if(PDCP_USE_NETLINK)
if(!IS_SOFTMODEM_NOS1)
netlink_init();
#ifndef PACKAGE_VERSION
# define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
if (RC.nb_nr_L1_inst > 0)
RCconfig_NR_L1();
// don't create if node doesn't connect to RRC/S1/GTP
AssertFatal(create_gNB_tasks(1) == 0,"cannot create ITTI tasks\n");
/* Start the agent. If it is turned off in the configuration, it won't start */
/*
RCconfig_nr_flexran();
for (i = 0; i < RC.nb_nr_L1_inst; i++) {
flexran_agent_start(i);
}
*/
// init UE_PF_PO and mutex lock
pthread_mutex_init(&ue_pf_po_mutex, NULL);
memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs);
mlockall(MCL_CURRENT | MCL_FUTURE);
pthread_cond_init(&sync_cond,NULL);
pthread_mutex_init(&sync_mutex, NULL);
usleep(1000);
if (NFAPI_MODE) {
printf("NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
pthread_cond_init(&sync_cond,NULL);
pthread_mutex_init(&sync_mutex, NULL);
}
const char *nfapi_mode_str = "<UNKNOWN>";
switch(NFAPI_MODE) {
case 0:
nfapi_mode_str = "MONOLITHIC";
break;
case 1:
nfapi_mode_str = "PNF";
break;
case 2:
nfapi_mode_str = "VNF";
break;
default:
nfapi_mode_str = "<UNKNOWN NFAPI MODE>";
break;
}
printf("NFAPI MODE:%s\n", nfapi_mode_str);
if (NFAPI_MODE==NFAPI_MODE_VNF)
wait_nfapi_init("main?");
printf("START MAIN THREADS\n");
// start the main threads
number_of_cards = 1;
printf("RC.nb_nr_L1_inst:%d\n", RC.nb_nr_L1_inst);
if (RC.nb_nr_L1_inst > 0) {
printf("Initializing gNB threads single_thread_flag:%d wait_for_sync:%d\n", single_thread_flag,wait_for_sync);
init_gNB(single_thread_flag,wait_for_sync);
}
printf("wait_gNBs()\n");
wait_gNBs();
printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
if (RC.nb_RU >0) {
printf("Initializing RU threads\n");
init_NR_RU(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;
}
}
config_sync_var=0;
//////////////////////////////////
//////////////////////////////////
//// Init the E2 Agent
sleep(2);
const gNB_RRC_INST* rrc = RC.nrrrc[mod_id];
assert(rrc != NULL && "rrc cannot be NULL");
const int mcc = rrc->configuration.mcc[0]; // 208;
const int mnc = rrc->configuration.mnc[0]; // 94;
const int mnc_digit_len = rrc->configuration.mnc_digit_length[0]; // 2;
const int nb_id = rrc->configuration.cell_identity; //42;
sm_io_ag_t io = {.read = read_RAN, .write = write_RAN};
printf("[E2 NODE]: mcc = %d mnc = %d mnc_digit = %d nd_id = %d \n", mcc, mnc, mnc_digit_len, nb_id);
init_agent_api( mcc, mnc, mnc_digit_len, nb_id, io);
//////////////////////////////////
//////////////////////////////////
if (NFAPI_MODE==NFAPI_MODE_PNF) {
wait_nfapi_init("main?");
}
if (RC.nb_nr_L1_inst > 0) {
printf("wait RUs\n");
wait_RUs();
printf("ALL RUs READY!\n");
printf("RC.nb_RU:%d\n", RC.nb_RU);
// once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration)
printf("ALL RUs ready - init gNBs\n");
if(IS_SOFTMODEM_DOSCOPE) {
sleep(1);
scopeParms_t p;
p.argc=&argc;
p.argv=argv;
p.gNB=RC.gNB[0];
p.ru=RC.ru[0];
load_softscope("nr",&p);
}
if (NFAPI_MODE != NFAPI_MODE_PNF && NFAPI_MODE != NFAPI_MODE_VNF) {
printf("Not NFAPI mode - call init_eNB_afterRU()\n");
init_eNB_afterRU();
} else {
printf("NFAPI mode - DO NOT call init_gNB_afterRU()\n");
}
printf("ALL RUs ready - ALL gNBs ready\n");
// connect the TX/RX buffers
printf("Sending sync to all threads\n");
pthread_mutex_lock(&sync_mutex);
sync_var=0;
pthread_cond_broadcast(&sync_cond);
pthread_mutex_unlock(&sync_mutex);
}
printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
// We have to set PARAMFLAG_NOFREE on right paramters before re-enabling end_configmodule()
//end_configmodule();
printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
// wait for end of program
printf("TYPE <CTRL-C> TO TERMINATE\n");
//getchar();
printf("Entering ITTI signals handler\n");
itti_wait_tasks_end();
printf("Returned from ITTI signal handler\n");
oai_exit=1;
printf("oai_exit=%d\n",oai_exit);
// stop threads
printf("stopping MODEM threads\n");
// cleanup
stop_gNB(NB_gNB_INST);
if (RC.nb_nr_L1_inst > 0) {
stop_RU(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 < NB_gNB_INST; inst++) {
//free_transport(RC.gNB[inst]);
phy_free_nr_gNB(RC.gNB[inst]);
}
for (int inst = 0; inst < NB_RU; inst++) {
nr_phy_free_RU(RC.ru[inst]);
}
free_lte_top();
pthread_cond_destroy(&sync_cond);
pthread_mutex_destroy(&sync_mutex);
pthread_cond_destroy(&nfapi_sync_cond);
pthread_mutex_destroy(&nfapi_sync_mutex);
pthread_mutex_destroy(&ue_pf_po_mutex);
// *** Handle per CC_id openair0
for(ru_id=0; ru_id<NB_RU; ru_id++) {
if (RC.ru[ru_id]->rfdevice.trx_end_func)
RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
if (RC.ru[ru_id]->ifdevice.trx_end_func)
RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
}
logClean();
printf("Bye.\n");
return 0;
}
```
#### Lets describe this part of code
```c=
///static configuration for NR at the moment
if ( 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(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
logInit();
configure_linux();
printf("Reading in command-line options\n");
get_options ();
if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
fprintf(stderr,"Getting configuration failed\n");
exit(-1);
}
```
| exit_fun | Exit function |
| ----------------- | ----------------------------- |
| configure_linux() | Block CPU C-states deep sleep |
| CONFIG_ABORT | config failed,abort execution |
| logInit() | initialize message |
| openair0_cfg |RF frontend parameters set by application |
| load_configmodule | Loading of config module |
#### Code of exit_fun
```c=
#define exit_fun(msg) exit_function(__FILE__,__FUNCTION__,__LINE__,msg)
```
#### Code of load_configmodule
```c=
configmodule_interface_t *load_configmodule(int argc, char **argv, <error-type> initflags)
```