/* * 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.0 (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 */ /*! \file lte-enb.c * \brief Top-level threads for eNodeB * \author R. Knopp, F. Kaltenberger, Navid Nikaein * \date 2012 * \version 0.1 * \company Eurecom * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr * \note * \warning */ #include "lte-softmodem.h" #include "T.h" #include "rt_wrapper.h" #include "../../ARCH/ETHERNET/USERSPACE/LIB/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/vars.h" #include "SCHED/vars.h" #include "LAYER2/MAC/vars.h" #include "../../SIMU/USER/init_lte.h" #include "LAYER2/MAC/defs.h" #include "LAYER2/MAC/vars.h" #include "LAYER2/MAC/proto.h" #include "RRC/LITE/vars.h" #include "PHY_INTERFACE/vars.h" #ifdef SMBV #include "PHY/TOOLS/smbv.h" unsigned short config_frames[4] = {2,9,11,13}; #endif #include "UTIL/LOG/log_extern.h" #include "UTIL/OTG/otg_tx.h" #include "UTIL/OTG/otg_externs.h" #include "UTIL/MATH/oml.h" #include "UTIL/LOG/vcd_signal_dumper.h" #include "UTIL/OPT/opt.h" #include "enb_config.h" //#include "PHY/TOOLS/time_meas.h" #ifndef OPENAIR2 #include "UTIL/OTG/otg_vars.h" #endif #if defined(ENABLE_ITTI) #include "intertask_interface_init.h" #include "create_tasks.h" #endif #include "system.h" #ifdef XFORMS #include "PHY/TOOLS/lte_phy_scope.h" #include "stats.h" // current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0) // at eNB 0, an UL scope for every UE FD_lte_phy_scope_ue *form_ue[NUMBER_OF_UE_MAX]; FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; FD_stats_form *form_stats=NULL,*form_stats_l2=NULL; char title[255]; unsigned char scope_enb_num_ue = 2; static pthread_t forms_thread; //xforms #endif //XFORMS pthread_cond_t sync_cond; pthread_mutex_t sync_mutex; int sync_var=-1; //!< protected by mutex \ref sync_mutex. uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100] #if defined(ENABLE_ITTI) volatile int start_eNB = 0; volatile int start_UE = 0; #endif volatile int oai_exit = 0; static clock_source_t clock_source = internal; static int wait_for_sync = 0; static char UE_flag=0; unsigned int mmapped_dma=0; int single_thread_flag=1; static char threequarter_fs=0; uint32_t downlink_frequency[MAX_NUM_CCs][4]; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; static char *conf_config_file_name = NULL; #if defined(ENABLE_ITTI) static char *itti_dump_file = NULL; #endif int UE_scan = 1; int UE_scan_carrier = 0; runmode_t mode = normal_txrx; FILE *input_fd=NULL; #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; double sample_rate=30.72e6; double bw = 10.0e6; static int tx_max_power[MAX_NUM_CCs]; /* = {0,0}*/; char rf_config_file[1024]; int chain_offset=0; int phy_test = 0; uint8_t usim_test = 0; uint8_t dci_Format = 0; uint8_t agregation_Level =0xFF; uint8_t nb_antenna_tx = 1; uint8_t nb_antenna_rx = 1; char ref[128] = "internal"; char channels[128] = "0"; int rx_input_level_dBm; static int online_log_messages=0; #ifdef XFORMS extern int otg_enabled; static char do_forms=0; #else int otg_enabled; #endif //int number_of_cards = 1; static LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; eNB_func_t node_function[MAX_NUM_CCs]; eNB_timing_t node_timing[MAX_NUM_CCs]; int16_t node_synch_ref[MAX_NUM_CCs]; uint32_t target_dl_mcs = 28; //maximum allowed mcs uint32_t target_ul_mcs = 20; uint32_t timing_advance = 0; uint8_t exit_missed_slots=1; uint64_t num_missed_slots=0; // counter for the number of missed slots int transmission_mode=1; int16_t glog_level = LOG_INFO; int16_t glog_verbosity = LOG_MED; int16_t hw_log_level = LOG_INFO; int16_t hw_log_verbosity = LOG_MED; int16_t phy_log_level = LOG_INFO; int16_t phy_log_verbosity = LOG_MED; int16_t mac_log_level = LOG_INFO; int16_t mac_log_verbosity = LOG_MED; int16_t rlc_log_level = LOG_INFO; int16_t rlc_log_verbosity = LOG_MED; int16_t pdcp_log_level = LOG_INFO; int16_t pdcp_log_verbosity = LOG_MED; int16_t rrc_log_level = LOG_INFO; int16_t rrc_log_verbosity = LOG_MED; int16_t opt_log_level = LOG_INFO; int16_t opt_log_verbosity = LOG_MED; # if defined(ENABLE_USE_MME) int16_t gtpu_log_level = LOG_DEBUG; int16_t gtpu_log_verbosity = LOG_MED; int16_t udp_log_level = LOG_DEBUG; int16_t udp_log_verbosity = LOG_MED; #endif #if defined (ENABLE_SECURITY) int16_t osa_log_level = LOG_INFO; int16_t osa_log_verbosity = LOG_MED; #endif char *rrh_UE_ip = "127.0.0.1"; int rrh_UE_port = 51000; /* flag set by eNB conf file to specify if the radio head is local or remote (default option is local) */ uint8_t local_remote_radio = BBU_LOCAL_RADIO_HEAD; /* struct for ethernet specific parameters given in eNB conf file */ eth_params_t *eth_params; openair0_config_t openair0_cfg[MAX_CARDS]; double cpuf; char uecap_xer[1024],uecap_xer_in=0; int oaisim_flag=0; threads_t threads= {-1,-1,-1,-1,-1,-1,-1}; /* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed * this is very hackish - find a proper solution */ uint8_t abstraction_flag=0; /* override the enb configuration parameters */ static void reconfigure_enb_params(int enb_id); /*---------------------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) { #ifdef DEBUG printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); #else LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); #endif } 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)); } #if !defined(ENABLE_ITTI) void signal_handler(int sig) { void *array[10]; size_t size; if (sig==SIGSEGV) { // get void*'s for all entries on the stack size = backtrace(array, 10); // print out all the frames to stderr fprintf(stderr, "Error: signal %d:\n", sig); backtrace_symbols_fd(array, size, 2); exit(-1); } else { printf("trying to exit gracefully...\n"); oai_exit = 1; } } #endif #define KNRM "\x1B[0m" #define KRED "\x1B[31m" #define KGRN "\x1B[32m" #define KBLU "\x1B[34m" #define RESET "\033[0m" void help (void) { printf (KGRN "Usage:\n"); printf(" sudo -E lte-softmodem [options]\n"); printf(" sudo -E ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.openEPC.conf -S -V -m 26 -t 16 -x 1 --ulsch-max-errors 100 -W\n\n"); printf("Options:\n"); printf(" --rf-config-file Configuration file for front-end (e.g. LMS7002M)\n"); printf(" --ulsch-max-errors set the max ULSCH erros\n"); printf(" --calib-ue-rx set UE RX calibration\n"); printf(" --calib-ue-rx-med \n"); printf(" --calib-ue-rxbyp\n"); printf(" --debug-ue-prach run normal prach power ramping, but don't continue random-access\n"); printf(" --calib-prach-tx run normal prach with maximum power, but don't continue random-access\n"); printf(" --no-L2-connect bypass L2 and upper layers\n"); printf(" --ue-rxgain set UE RX gain\n"); printf(" --ue-rxgain-off external UE amplifier offset\n"); printf(" --ue-txgain set UE TX gain\n"); printf(" --ue-nb-ant-rx set UE number of rx antennas\n"); printf(" --ue-scan-carrier set UE to scan around carrier\n"); printf(" --dlsch-demod-shift dynamic shift for LLR compuation for TM3/4 (default 0)\n"); printf(" --loop-memory get softmodem (UE) to loop through memory instead of acquiring from HW\n"); printf(" --mmapped-dma sets flag for improved EXMIMO UE performance\n"); printf(" --external-clock tells hardware to use an external clock reference\n"); printf(" --usim-test use XOR autentication algo in case of test usim mode\n"); printf(" --single-thread-disable. Disables single-thread mode in lte-softmodem\n"); printf(" --AgregationLevel Choose the agregation level used by tghe eNB for the OAI use 1, it will save some time of processing the pdcch\n"); printf(" --DCIformat choose the DCI format, be careful when using this option(for the moment only valid for SISO DCI format 1)\n"); printf(" -A Set timing_advance\n"); printf(" -C Set the downlink frequency for all component carriers\n"); printf(" -d Enable soft scope and L1 and L2 stats (Xforms)\n"); printf(" -F Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n"); printf(" -g Set the global log level, valide options: (9:trace, 8/7:debug, 6:info, 4:warn, 3:error)\n"); printf(" -G Set the global log verbosity \n"); printf(" -h provides this help message!\n"); printf(" -K Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n"); printf(" -m Set the maximum downlink MCS\n"); printf(" -O eNB configuration file (located in targets/PROJECTS/GENERIC-LTE-EPC/CONF\n"); printf(" -q Enable processing timing measurement of lte softmodem on per subframe basis \n"); printf(" -r Set the PRB, valid values: 6, 25, 50, 100 \n"); printf(" -S Skip the missed slots/subframes \n"); printf(" -t Set the maximum uplink MCS\n"); printf(" -T Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n"); printf(" -U Set the lte softmodem as a UE\n"); printf(" -W Enable L2 wireshark messages on localhost \n"); printf(" -V Enable VCD (generated file will be located atopenair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n"); printf(" -x Set the transmission mode, valid options: 1 \n"); printf(" -E Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n"); #if T_TRACER printf(" --T_port [port] use given port\n"); printf(" --T_nowait don't wait for tracer, start immediately\n"); printf(" --T_dont_fork to ease debugging with gdb\n"); #endif printf(RESET); fflush(stdout); } void exit_fun(const char* s) { int CC_id; if (s != NULL) { printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s); } oai_exit = 1; for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { if (UE_flag == 0) { if (PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func) PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func) PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); } else { if (PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func) PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice); } } #if defined(ENABLE_ITTI) sleep(1); //allow lte-softmodem threads to exit first itti_terminate_tasks (TASK_UNKNOWN); #endif } #ifdef XFORMS void reset_stats(FL_OBJECT *button, long arg) { int i,j,k; PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0]; for (i=0; i<NUMBER_OF_UE_MAX; i++) { for (k=0; k<8; k++) { //harq_processes for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) { phy_vars_eNB->UE_stats[i].dlsch_NAK[k][j]=0; phy_vars_eNB->UE_stats[i].dlsch_ACK[k][j]=0; phy_vars_eNB->UE_stats[i].dlsch_trials[k][j]=0; } phy_vars_eNB->UE_stats[i].dlsch_l2_errors[k]=0; phy_vars_eNB->UE_stats[i].ulsch_errors[k]=0; phy_vars_eNB->UE_stats[i].ulsch_consecutive_errors=0; for (j=0; j<phy_vars_eNB->ulsch[i]->Mlimit; j++) { phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts[k][j]=0; phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j]=0; phy_vars_eNB->UE_stats[i].ulsch_round_errors[k][j]=0; phy_vars_eNB->UE_stats[i].ulsch_round_fer[k][j]=0; } } phy_vars_eNB->UE_stats[i].dlsch_sliding_cnt=0; phy_vars_eNB->UE_stats[i].dlsch_NAK_round0=0; phy_vars_eNB->UE_stats[i].dlsch_mcs_offset=0; } } static void *scope_thread(void *arg) { char stats_buffer[16384]; # ifdef ENABLE_XFORMS_WRITE_STATS FILE *UE_stats, *eNB_stats; # endif int len = 0; struct sched_param sched_param; int UE_id, CC_id; int ue_cnt=0; sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1; sched_setscheduler(0, SCHED_FIFO,&sched_param); printf("Scope thread has priority %d\n",sched_param.sched_priority); # ifdef ENABLE_XFORMS_WRITE_STATS if (UE_flag==1) UE_stats = fopen("UE_stats.txt", "w"); else eNB_stats = fopen("eNB_stats.txt", "w"); #endif while (!oai_exit) { if (UE_flag==1) { len = dump_ue_stats (PHY_vars_UE_g[0][0], &PHY_vars_UE_g[0][0]->proc.proc_rxtx[0],stats_buffer, 0, mode,rx_input_level_dBm); //fl_set_object_label(form_stats->stats_text, stats_buffer); fl_clear_browser(form_stats->stats_text); fl_add_browser_line(form_stats->stats_text, stats_buffer); phy_scope_UE(form_ue[0], PHY_vars_UE_g[0][0], 0, 0,7); } else { if (PHY_vars_eNB_g[0][0]->mac_enabled==1) { len = dump_eNB_l2_stats (stats_buffer, 0); //fl_set_object_label(form_stats_l2->stats_text, stats_buffer); fl_clear_browser(form_stats_l2->stats_text); fl_add_browser_line(form_stats_l2->stats_text, stats_buffer); } len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0); if (MAX_NUM_CCs>1) len += dump_eNB_stats (PHY_vars_eNB_g[0][1], &stats_buffer[len], 0); //fl_set_object_label(form_stats->stats_text, stats_buffer); fl_clear_browser(form_stats->stats_text); fl_add_browser_line(form_stats->stats_text, stats_buffer); ue_cnt=0; for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) { for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { // if ((PHY_vars_eNB_g[0][CC_id]->dlsch[UE_id][0]->rnti>0) && (ue_cnt<scope_enb_num_ue)) { if ((ue_cnt<scope_enb_num_ue)) { phy_scope_eNB(form_enb[CC_id][ue_cnt], PHY_vars_eNB_g[0][CC_id], UE_id); ue_cnt++; } } } } //printf("doing forms\n"); //usleep(100000); // 100 ms sleep(1); } // printf("%s",stats_buffer); # ifdef ENABLE_XFORMS_WRITE_STATS if (UE_flag==1) { if (UE_stats) { rewind (UE_stats); fwrite (stats_buffer, 1, len, UE_stats); fclose (UE_stats); } } else { if (eNB_stats) { rewind (eNB_stats); fwrite (stats_buffer, 1, len, eNB_stats); fclose (eNB_stats); } } # endif pthread_exit((void*)arg); } #endif #if defined(ENABLE_ITTI) void *l2l1_task(void *arg) { MessageDef *message_p = NULL; int result; itti_set_task_real_time(TASK_L2L1); itti_mark_task_ready(TASK_L2L1); if (UE_flag == 0) { /* Wait for the initialize message */ printf("Wait for the ITTI initialize message\n"); do { if (message_p != NULL) { result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p); AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); } itti_receive_msg (TASK_L2L1, &message_p); switch (ITTI_MSG_ID(message_p)) { case INITIALIZE_MESSAGE: /* Start eNB thread */ LOG_D(EMU, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p)); start_eNB = 1; break; case TERMINATE_MESSAGE: LOG_W(TASK_L2L1, " *** Exiting L2L1 thread\n"); oai_exit = 1; start_eNB = 0; itti_exit_task (); break; default: LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p)); break; } } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE); result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p); AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); } do { // Wait for a message itti_receive_msg (TASK_L2L1, &message_p); switch (ITTI_MSG_ID(message_p)) { case TERMINATE_MESSAGE: LOG_W(TASK_L2L1, " *** Exiting L2L1 thread\n"); oai_exit=1; itti_exit_task (); break; case ACTIVATE_MESSAGE: start_UE = 1; break; case DEACTIVATE_MESSAGE: start_UE = 0; break; case MESSAGE_TEST: LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p)); break; default: LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p)); break; } result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p); AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); } while(!oai_exit); return NULL; } #endif static void get_options (int argc, char **argv) { int c; // char line[1000]; // int l; int k,i;//,j,k; #if defined(OAI_USRP) || defined(CPRIGW) int clock_src; #endif int CC_id; const Enb_properties_array_t *enb_properties; enum long_option_e { LONG_OPTION_START = 0x100, /* Start after regular single char options */ LONG_OPTION_RF_CONFIG_FILE, LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS, LONG_OPTION_CALIB_UE_RX, LONG_OPTION_CALIB_UE_RX_MED, LONG_OPTION_CALIB_UE_RX_BYP, LONG_OPTION_DEBUG_UE_PRACH, LONG_OPTION_NO_L2_CONNECT, LONG_OPTION_CALIB_PRACH_TX, LONG_OPTION_RXGAIN, LONG_OPTION_RXGAINOFF, LONG_OPTION_TXGAIN, LONG_OPTION_NBRXANT, LONG_OPTION_NBTXANT, LONG_OPTION_SCANCARRIER, LONG_OPTION_MAXPOWER, LONG_OPTION_DUMP_FRAME, LONG_OPTION_LOOPMEMORY, LONG_OPTION_PHYTEST, LONG_OPTION_USIMTEST, LONG_OPTION_MMAPPED_DMA, LONG_OPTION_EXTERNAL_CLOCK, LONG_OPTION_WAIT_FOR_SYNC, LONG_OPTION_SINGLE_THREAD_DISABLE, LONG_OPTION_THREADIQ, LONG_OPTION_THREADONESUBFRAME, LONG_OPTION_THREADTWOSUBFRAME, LONG_OPTION_THREADTHREESUBFRAME, LONG_OPTION_THREADSLOT1PROCONE, LONG_OPTION_THREADSLOT1PROCTWO, LONG_OPTION_THREADSLOT1PROCTHREE, LONG_OPTION_DCIFORMAT, LONG_OPTION_AGREGATIONLEVEL, LONG_OPTION_DEMOD_SHIFT, #if T_TRACER LONG_OPTION_T_PORT, LONG_OPTION_T_NOWAIT, LONG_OPTION_T_DONT_FORK, #endif }; static const struct option long_options[] = { {"rf-config-file",required_argument, NULL, LONG_OPTION_RF_CONFIG_FILE}, {"ulsch-max-errors",required_argument, NULL, LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS}, {"calib-ue-rx", required_argument, NULL, LONG_OPTION_CALIB_UE_RX}, {"calib-ue-rx-med", required_argument, NULL, LONG_OPTION_CALIB_UE_RX_MED}, {"calib-ue-rx-byp", required_argument, NULL, LONG_OPTION_CALIB_UE_RX_BYP}, {"debug-ue-prach", no_argument, NULL, LONG_OPTION_DEBUG_UE_PRACH}, {"no-L2-connect", no_argument, NULL, LONG_OPTION_NO_L2_CONNECT}, {"calib-prach-tx", no_argument, NULL, LONG_OPTION_CALIB_PRACH_TX}, {"ue-rxgain", required_argument, NULL, LONG_OPTION_RXGAIN}, {"ue-rxgain-off", required_argument, NULL, LONG_OPTION_RXGAINOFF}, {"ue-txgain", required_argument, NULL, LONG_OPTION_TXGAIN}, {"ue-nb-ant-rx", required_argument, NULL, LONG_OPTION_NBRXANT}, {"ue-nb-ant-tx", required_argument, NULL, LONG_OPTION_NBTXANT}, {"ue-scan-carrier", no_argument, NULL, LONG_OPTION_SCANCARRIER}, {"ue-max-power", required_argument, NULL, LONG_OPTION_MAXPOWER}, {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME}, {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY}, {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST}, {"usim-test", no_argument, NULL, LONG_OPTION_USIMTEST}, {"mmapped-dma", no_argument, NULL, LONG_OPTION_MMAPPED_DMA}, {"external-clock", no_argument, NULL, LONG_OPTION_EXTERNAL_CLOCK}, {"wait-for-sync", no_argument, NULL, LONG_OPTION_WAIT_FOR_SYNC}, {"single-thread-disable", no_argument, NULL, LONG_OPTION_SINGLE_THREAD_DISABLE}, {"threadIQ", required_argument, NULL, LONG_OPTION_THREADIQ}, {"threadOneSubframe", required_argument, NULL, LONG_OPTION_THREADONESUBFRAME}, {"threadTwoSubframe", required_argument, NULL, LONG_OPTION_THREADTWOSUBFRAME}, {"threadThreeSubframe", required_argument, NULL, LONG_OPTION_THREADTHREESUBFRAME}, {"threadSlot1ProcOne", required_argument, NULL, LONG_OPTION_THREADSLOT1PROCONE}, {"threadSlot1ProcTwo", required_argument, NULL, LONG_OPTION_THREADSLOT1PROCTWO}, {"threadSlot1ProcThree", required_argument, NULL, LONG_OPTION_THREADSLOT1PROCTHREE}, {"DCIformat", required_argument, NULL, LONG_OPTION_DCIFORMAT}, {"AgregationLevel", required_argument, NULL, LONG_OPTION_AGREGATIONLEVEL}, {"dlsch-demod-shift", required_argument, NULL, LONG_OPTION_DEMOD_SHIFT}, #if T_TRACER {"T_port", required_argument, 0, LONG_OPTION_T_PORT}, {"T_nowait", no_argument, 0, LONG_OPTION_T_NOWAIT}, {"T_dont_fork", no_argument, 0, LONG_OPTION_T_DONT_FORK}, #endif {NULL, 0, NULL, 0} }; while ((c = getopt_long (argc, argv, "A:a:C:dEK:g:F:G:hqO:m:SUVRM:r:P:Ws:t:Tx:",long_options,NULL)) != -1) { switch (c) { case LONG_OPTION_RF_CONFIG_FILE: if ((strcmp("null", optarg) == 0) || (strcmp("NULL", optarg) == 0)) { printf("no configuration filename is provided\n"); } else if (strlen(optarg)<=1024){ strcpy(rf_config_file,optarg); }else { printf("Configuration filename is too long\n"); exit(-1); } break; case LONG_OPTION_MAXPOWER: tx_max_power[0]=atoi(optarg); for (CC_id=1;CC_id<MAX_NUM_CCs;CC_id++) tx_max_power[CC_id]=tx_max_power[0]; break; case LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS: ULSCH_max_consecutive_errors = atoi(optarg); printf("Set ULSCH_max_consecutive_errors = %d\n",ULSCH_max_consecutive_errors); break; case LONG_OPTION_CALIB_UE_RX: mode = rx_calib_ue; rx_input_level_dBm = atoi(optarg); printf("Running with UE calibration on (LNA max), input level %d dBm\n",rx_input_level_dBm); break; case LONG_OPTION_CALIB_UE_RX_MED: mode = rx_calib_ue_med; rx_input_level_dBm = atoi(optarg); printf("Running with UE calibration on (LNA med), input level %d dBm\n",rx_input_level_dBm); break; case LONG_OPTION_CALIB_UE_RX_BYP: mode = rx_calib_ue_byp; rx_input_level_dBm = atoi(optarg); printf("Running with UE calibration on (LNA byp), input level %d dBm\n",rx_input_level_dBm); break; case LONG_OPTION_DEBUG_UE_PRACH: mode = debug_prach; break; case LONG_OPTION_NO_L2_CONNECT: mode = no_L2_connect; break; case LONG_OPTION_CALIB_PRACH_TX: mode = calib_prach_tx; printf("Setting mode to calib_prach_tx (%d)\n",mode); break; case LONG_OPTION_RXGAIN: for (i=0; i<4; i++) rx_gain[0][i] = atof(optarg); break; case LONG_OPTION_RXGAINOFF: rx_gain_off = atof(optarg); break; case LONG_OPTION_TXGAIN: for (i=0; i<4; i++) tx_gain[0][i] = atof(optarg); break; case LONG_OPTION_NBRXANT: nb_antenna_rx = atof(optarg); break; case LONG_OPTION_NBTXANT: nb_antenna_tx = atof(optarg); break; case LONG_OPTION_SCANCARRIER: UE_scan_carrier=1; break; case LONG_OPTION_LOOPMEMORY: mode=loop_through_memory; input_fd = fopen(optarg,"r"); AssertFatal(input_fd != NULL,"Please provide an input file\n"); break; case LONG_OPTION_DUMP_FRAME: mode = rx_dump_frame; break; case LONG_OPTION_PHYTEST: phy_test = 1; break; case LONG_OPTION_USIMTEST: usim_test = 1; break; case LONG_OPTION_MMAPPED_DMA: mmapped_dma = 1; break; case LONG_OPTION_SINGLE_THREAD_DISABLE: single_thread_flag = 0; break; case LONG_OPTION_EXTERNAL_CLOCK: clock_source = external; break; case LONG_OPTION_WAIT_FOR_SYNC: wait_for_sync = 1; break; case LONG_OPTION_THREADIQ: threads.iq=atoi(optarg); break; case LONG_OPTION_THREADONESUBFRAME: threads.one=atoi(optarg); break; case LONG_OPTION_THREADTWOSUBFRAME: threads.two=atoi(optarg); break; case LONG_OPTION_THREADTHREESUBFRAME: threads.three=atoi(optarg); break; case LONG_OPTION_THREADSLOT1PROCONE: threads.slot1_proc_one=atoi(optarg); break; case LONG_OPTION_THREADSLOT1PROCTWO: threads.slot1_proc_two=atoi(optarg); break; case LONG_OPTION_THREADSLOT1PROCTHREE: threads.slot1_proc_three=atoi(optarg); break; case LONG_OPTION_DCIFORMAT: dci_Format = atoi(optarg); break; case LONG_OPTION_AGREGATIONLEVEL: agregation_Level = atoi(optarg); break; case LONG_OPTION_DEMOD_SHIFT: { extern int16_t dlsch_demod_shift; dlsch_demod_shift = atof(optarg); break; } #if T_TRACER case LONG_OPTION_T_PORT: { extern int T_port; if (optarg == NULL) abort(); /* should not happen */ T_port = atoi(optarg); break; } case LONG_OPTION_T_NOWAIT: { extern int T_wait; T_wait = 0; break; } case LONG_OPTION_T_DONT_FORK: { extern int T_dont_fork; T_dont_fork = 1; break; } #endif case 'A': timing_advance = atoi (optarg); break; case 'C': for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { downlink_frequency[CC_id][0] = atof(optarg); // 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]; printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]); } UE_scan=0; break; case 'a': chain_offset = atoi(optarg); break; case 'd': #ifdef XFORMS do_forms=1; printf("Running with XFORMS!\n"); #endif break; case 'E': threequarter_fs=1; break; case 'K': #if defined(ENABLE_ITTI) itti_dump_file = strdup(optarg); #else printf("-K option is disabled when ENABLE_ITTI is not defined\n"); #endif break; case 'O': conf_config_file_name = optarg; break; case 'U': UE_flag = 1; break; case 'm': target_dl_mcs = atoi (optarg); break; case 't': target_ul_mcs = atoi (optarg); break; case 'W': opt_enabled=1; opt_type = OPT_WIRESHARK; strncpy(in_ip, "127.0.0.1", sizeof(in_ip)); in_ip[sizeof(in_ip) - 1] = 0; // terminate string printf("Enabling OPT for wireshark for local interface"); /* if (optarg == NULL){ in_ip[0] =NULL; printf("Enabling OPT for wireshark for local interface"); } else { strncpy(in_ip, optarg, sizeof(in_ip)); in_ip[sizeof(in_ip) - 1] = 0; // terminate string printf("Enabling OPT for wireshark with %s \n",in_ip); } */ break; case 'P': opt_type = OPT_PCAP; opt_enabled=1; if (optarg == NULL) { strncpy(in_path, "/tmp/oai_opt.pcap", sizeof(in_path)); in_path[sizeof(in_path) - 1] = 0; // terminate string printf("Enabling OPT for PCAP with the following path /tmp/oai_opt.pcap"); } else { strncpy(in_path, optarg, sizeof(in_path)); in_path[sizeof(in_path) - 1] = 0; // terminate string printf("Enabling OPT for PCAP with the following file %s \n",in_path); } break; case 'V': ouput_vcd = 1; break; case 'q': opp_enabled = 1; break; case 'R' : online_log_messages =1; break; case 'r': UE_scan = 0; for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { switch(atoi(optarg)) { case 6: frame_parms[CC_id]->N_RB_DL=6; frame_parms[CC_id]->N_RB_UL=6; break; case 25: frame_parms[CC_id]->N_RB_DL=25; frame_parms[CC_id]->N_RB_UL=25; break; case 50: frame_parms[CC_id]->N_RB_DL=50; frame_parms[CC_id]->N_RB_UL=50; break; case 100: frame_parms[CC_id]->N_RB_DL=100; frame_parms[CC_id]->N_RB_UL=100; break; default: printf("Unknown N_RB_DL %d, switching to 25\n",atoi(optarg)); break; } } break; case 's': #if defined(OAI_USRP) || defined(CPRIGW) clock_src = atoi(optarg); if (clock_src == 0) { // char ref[128] = "internal"; //strncpy(uhd_ref, ref, strlen(ref)+1); } else if (clock_src == 1) { //char ref[128] = "external"; //strncpy(uhd_ref, ref, strlen(ref)+1); } #else printf("Note: -s not defined for ExpressMIMO2\n"); #endif break; case 'S': exit_missed_slots=0; printf("Skip exit for missed slots\n"); break; case 'g': glog_level=atoi(optarg); // value between 1 - 9 break; case 'F': break; case 'G': glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75 break; case 'x': printf("Transmission mode should be set in config file now\n"); exit(-1); /* transmission_mode = atoi(optarg); if (transmission_mode > 7) { printf("Transmission mode %d not supported for the moment\n",transmission_mode); exit(-1); } */ break; case 'T': for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) frame_parms[CC_id]->frame_type = TDD; break; case 'h': help (); exit (-1); default: help (); exit (-1); break; } } if (UE_flag == 0) AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n"); if ((UE_flag == 0) && (conf_config_file_name != NULL)) { int i,j; NB_eNB_INST = 1; /* Read eNB configuration file */ enb_properties = enb_config_init(conf_config_file_name); AssertFatal (NB_eNB_INST <= enb_properties->number, "Number of eNB is greater than eNB defined in configuration file %s (%d/%d)!", conf_config_file_name, NB_eNB_INST, enb_properties->number); NB_eNB_INST=enb_properties->number; /* Update some simulation parameters */ for (i=0; i < enb_properties->number; i++) { AssertFatal (MAX_NUM_CCs == enb_properties->properties[i]->nb_cc, "lte-softmodem compiled with MAX_NUM_CCs=%d, but only %d CCs configured for eNB %d!", MAX_NUM_CCs, enb_properties->properties[i]->nb_cc, i); #ifdef FLEXRAN_AGENT_SB_IF if (enb_properties->properties[i]->flexran_agent_reconf == 1) { node_control_state = ENB_WAIT_RECONFIGURATION_CMD; } else { node_control_state = ENB_NORMAL_OPERATION; } #endif eth_params = (eth_params_t*)malloc(enb_properties->properties[i]->nb_rrh_gw * sizeof(eth_params_t)); memset(eth_params, 0, enb_properties->properties[i]->nb_rrh_gw * sizeof(eth_params_t)); for (j=0; j<enb_properties->properties[i]->nb_rrh_gw; j++) { if (enb_properties->properties[i]->rrh_gw_config[j].active == 1 ) { local_remote_radio = BBU_REMOTE_RADIO_HEAD; (eth_params+j)->local_if_name = enb_properties->properties[i]->rrh_gw_config[j].rrh_gw_if_name; (eth_params+j)->my_addr = enb_properties->properties[i]->rrh_gw_config[j].local_address; (eth_params+j)->my_port = enb_properties->properties[i]->rrh_gw_config[j].local_port; (eth_params+j)->remote_addr = enb_properties->properties[i]->rrh_gw_config[j].remote_address; (eth_params+j)->remote_port = enb_properties->properties[i]->rrh_gw_config[j].remote_port; if (enb_properties->properties[i]->rrh_gw_config[j].raw == 1) { (eth_params+j)->transp_preference = ETH_RAW_MODE; } else if (enb_properties->properties[i]->rrh_gw_config[j].rawif4p5 == 1) { (eth_params+j)->transp_preference = ETH_RAW_IF4p5_MODE; } else if (enb_properties->properties[i]->rrh_gw_config[j].udpif4p5 == 1) { (eth_params+j)->transp_preference = ETH_UDP_IF4p5_MODE; } else if (enb_properties->properties[i]->rrh_gw_config[j].rawif5_mobipass == 1) { (eth_params+j)->transp_preference = ETH_RAW_IF5_MOBIPASS; } else { (eth_params+j)->transp_preference = ETH_UDP_MODE; } (eth_params+j)->iq_txshift = enb_properties->properties[i]->rrh_gw_config[j].iq_txshift; (eth_params+j)->tx_sample_advance = enb_properties->properties[i]->rrh_gw_config[j].tx_sample_advance; (eth_params+j)->tx_scheduling_advance = enb_properties->properties[i]->rrh_gw_config[j].tx_scheduling_advance; if (enb_properties->properties[i]->rrh_gw_config[j].exmimo == 1) { (eth_params+j)->rf_preference = EXMIMO_DEV; } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_b200 == 1) { (eth_params+j)->rf_preference = USRP_B200_DEV; } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_x300 == 1) { (eth_params+j)->rf_preference = USRP_X300_DEV; } else if (enb_properties->properties[i]->rrh_gw_config[j].bladerf == 1) { (eth_params+j)->rf_preference = BLADERF_DEV; } else if (enb_properties->properties[i]->rrh_gw_config[j].lmssdr == 1) { //(eth_params+j)->rf_preference = LMSSDR_DEV; } else { (eth_params+j)->rf_preference = 0; } (eth_params+j)->if_compress = enb_properties->properties[i]->rrh_gw_config[j].if_compress; } else { local_remote_radio = BBU_LOCAL_RADIO_HEAD; } } reconfigure_enb_params(i); init_all_otg(0); g_otg->seed = 0; init_seeds(g_otg->seed); for (k=0; k<enb_properties->properties[i]->num_otg_elements; k++) { j=enb_properties->properties[i]->otg_ue_id[k]; // ue_id g_otg->application_idx[i][j] = 1; //g_otg->packet_gen_type=SUBSTRACT_STRING; g_otg->background[i][j][0] =enb_properties->properties[i]->otg_bg_traffic[k]; g_otg->application_type[i][j][0] =enb_properties->properties[i]->otg_app_type[k];// BCBR; //MCBR, BCBR printf("[OTG] configuring traffic type %d for eNB %d UE %d (Background traffic is %s)\n", g_otg->application_type[i][j][0], i, j,(g_otg->background[i][j][0]==1)?"Enabled":"Disabled"); } init_predef_traffic(enb_properties->properties[i]->num_otg_elements, 1); glog_level = enb_properties->properties[i]->glog_level; glog_verbosity = enb_properties->properties[i]->glog_verbosity; hw_log_level = enb_properties->properties[i]->hw_log_level; hw_log_verbosity = enb_properties->properties[i]->hw_log_verbosity ; phy_log_level = enb_properties->properties[i]->phy_log_level; phy_log_verbosity = enb_properties->properties[i]->phy_log_verbosity; mac_log_level = enb_properties->properties[i]->mac_log_level; mac_log_verbosity = enb_properties->properties[i]->mac_log_verbosity; rlc_log_level = enb_properties->properties[i]->rlc_log_level; rlc_log_verbosity = enb_properties->properties[i]->rlc_log_verbosity; pdcp_log_level = enb_properties->properties[i]->pdcp_log_level; pdcp_log_verbosity = enb_properties->properties[i]->pdcp_log_verbosity; rrc_log_level = enb_properties->properties[i]->rrc_log_level; rrc_log_verbosity = enb_properties->properties[i]->rrc_log_verbosity; # if defined(ENABLE_USE_MME) gtpu_log_level = enb_properties->properties[i]->gtpu_log_level; gtpu_log_verbosity = enb_properties->properties[i]->gtpu_log_verbosity; udp_log_level = enb_properties->properties[i]->udp_log_level; udp_log_verbosity = enb_properties->properties[i]->udp_log_verbosity; #endif #if defined (ENABLE_SECURITY) osa_log_level = enb_properties->properties[i]->osa_log_level; osa_log_verbosity = enb_properties->properties[i]->osa_log_verbosity; #endif }// i //this is needed for phy-test option transmission_mode = enb_properties->properties[0]->ue_TransmissionMode[0]+1; } else if (UE_flag == 1) { if (conf_config_file_name != NULL) { // Here the configuration file is the XER encoded UE capabilities // Read it in and store in asn1c data structures strcpy(uecap_xer,conf_config_file_name); uecap_xer_in=1; } } } static void reconfigure_enb_params(int enb_id) { int CC_id, k; const Enb_properties_array_t *enb_properties=enb_config_get(); for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { node_function[CC_id] = enb_properties->properties[enb_id]->cc_node_function[CC_id]; node_timing[CC_id] = enb_properties->properties[enb_id]->cc_node_timing[CC_id]; node_synch_ref[CC_id] = enb_properties->properties[enb_id]->cc_node_synch_ref[CC_id]; frame_parms[CC_id]->frame_type = enb_properties->properties[enb_id]->frame_type[CC_id]; frame_parms[CC_id]->tdd_config = enb_properties->properties[enb_id]->tdd_config[CC_id]; frame_parms[CC_id]->tdd_config_S = enb_properties->properties[enb_id]->tdd_config_s[CC_id]; frame_parms[CC_id]->Ncp = enb_properties->properties[enb_id]->prefix_type[CC_id]; //for (j=0; j < enb_properties->properties[i]->nb_cc; j++ ){ frame_parms[CC_id]->Nid_cell = enb_properties->properties[enb_id]->Nid_cell[CC_id]; frame_parms[CC_id]->N_RB_DL = enb_properties->properties[enb_id]->N_RB_DL[CC_id]; frame_parms[CC_id]->N_RB_UL = enb_properties->properties[enb_id]->N_RB_DL[CC_id]; frame_parms[CC_id]->nb_antennas_tx = enb_properties->properties[enb_id]->nb_antennas_tx[CC_id]; frame_parms[CC_id]->nb_antenna_ports_eNB = enb_properties->properties[enb_id]->nb_antenna_ports[CC_id]; frame_parms[CC_id]->nb_antennas_rx = enb_properties->properties[enb_id]->nb_antennas_rx[CC_id]; frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex = enb_properties->properties[enb_id]->prach_config_index[CC_id]; frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset = enb_properties->properties[enb_id]->prach_freq_offset[CC_id]; frame_parms[CC_id]->mode1_flag = (frame_parms[CC_id]->nb_antenna_ports_eNB == 1) ? 1 : 0; frame_parms[CC_id]->threequarter_fs = threequarter_fs; for (k = 0 ; k < 4; k++) { downlink_frequency[CC_id][k] = enb_properties->properties[enb_id]->downlink_frequency[CC_id]; uplink_frequency_offset[CC_id][k] = enb_properties->properties[enb_id]->uplink_frequency_offset[CC_id]; rx_gain[CC_id][k] = (double)enb_properties->properties[enb_id]->rx_gain[CC_id]; tx_gain[CC_id][k] = (double)enb_properties->properties[enb_id]->tx_gain[CC_id]; } printf("Downlink frequency/ uplink offset of CC_id %d set to %ju/%d\n", CC_id, enb_properties->properties[enb_id]->downlink_frequency[CC_id], enb_properties->properties[enb_id]->uplink_frequency_offset[CC_id]); init_ul_hopping(frame_parms[CC_id]); init_frame_parms(frame_parms[CC_id],1); // phy_init_top(frame_parms[CC_id]); phy_init_lte_top(frame_parms[CC_id]); } // CC_id } #if T_TRACER int T_wait = 1; /* by default we wait for the tracer */ int T_port = 2021; /* default port to listen to to wait for the tracer */ int T_dont_fork = 0; /* default is to fork, see 'T_init' to understand */ #endif void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]); void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) { int CC_id; for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { frame_parms[CC_id] = (LTE_DL_FRAME_PARMS*) malloc(sizeof(LTE_DL_FRAME_PARMS)); /* 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_eNB = 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]; //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]); } } void init_openair0(void); void init_openair0() { int card; int i; for (card=0; card<MAX_CARDS; card++) { openair0_cfg[card].mmapped_dma=mmapped_dma; openair0_cfg[card].configFilename = NULL; if(frame_parms[0]->N_RB_DL == 100) { if (frame_parms[0]->threequarter_fs) { openair0_cfg[card].sample_rate=23.04e6; openair0_cfg[card].samples_per_frame = 230400; openair0_cfg[card].tx_bw = 10e6; openair0_cfg[card].rx_bw = 10e6; } else { openair0_cfg[card].sample_rate=30.72e6; openair0_cfg[card].samples_per_frame = 307200; openair0_cfg[card].tx_bw = 10e6; openair0_cfg[card].rx_bw = 10e6; } } else if(frame_parms[0]->N_RB_DL == 50) { openair0_cfg[card].sample_rate=15.36e6; openair0_cfg[card].samples_per_frame = 153600; openair0_cfg[card].tx_bw = 5e6; openair0_cfg[card].rx_bw = 5e6; } else if (frame_parms[0]->N_RB_DL == 25) { openair0_cfg[card].sample_rate=7.68e6; openair0_cfg[card].samples_per_frame = 76800; openair0_cfg[card].tx_bw = 2.5e6; openair0_cfg[card].rx_bw = 2.5e6; } else if (frame_parms[0]->N_RB_DL == 6) { openair0_cfg[card].sample_rate=1.92e6; openair0_cfg[card].samples_per_frame = 19200; openair0_cfg[card].tx_bw = 1.5e6; openair0_cfg[card].rx_bw = 1.5e6; } if (frame_parms[0]->frame_type==TDD) openair0_cfg[card].duplex_mode = duplex_mode_TDD; else //FDD openair0_cfg[card].duplex_mode = duplex_mode_FDD; if (local_remote_radio == BBU_REMOTE_RADIO_HEAD) { openair0_cfg[card].remote_addr = (eth_params+card)->remote_addr; openair0_cfg[card].remote_port = (eth_params+card)->remote_port; openair0_cfg[card].my_addr = (eth_params+card)->my_addr; openair0_cfg[card].my_port = (eth_params+card)->my_port; } printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card, ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx), ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx)); openair0_cfg[card].Mod_id = 0; if (UE_flag) { printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port); openair0_cfg[card].remote_addr = &rrh_UE_ip[0]; openair0_cfg[card].remote_port = rrh_UE_port; } openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; openair0_cfg[card].clock_source = clock_source; openair0_cfg[card].tx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx)); openair0_cfg[card].rx_num_channels=min(2,((UE_flag==0) ? PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx)); for (i=0; i<4; i++) { if (i<openair0_cfg[card].tx_num_channels) openair0_cfg[card].tx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] : downlink_frequency[0][i]+uplink_frequency_offset[0][i]; else openair0_cfg[card].tx_freq[i]=0.0; if (i<openair0_cfg[card].rx_num_channels) openair0_cfg[card].rx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] + uplink_frequency_offset[0][i] : downlink_frequency[0][i]; else openair0_cfg[card].rx_freq[i]=0.0; openair0_cfg[card].autocal[i] = 1; openair0_cfg[card].tx_gain[i] = tx_gain[0][i]; if (UE_flag == 0) { openair0_cfg[card].rx_gain[i] = PHY_vars_eNB_g[0][0]->rx_total_gain_dB; } else { openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB - rx_gain_off; } openair0_cfg[card].configFilename = rf_config_file; printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n", card,i, openair0_cfg[card].tx_gain[i], openair0_cfg[card].rx_gain[i], openair0_cfg[card].tx_freq[i], openair0_cfg[card].rx_freq[i]); } } } void fill_PHY_vars_eNB_g(uint8_t abstraction_flag, uint8_t beta_ACK, uint8_t beta_RI, uint8_t beta_CQI) { int CC_id, i, j, k, re; for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { PHY_vars_eNB_g[0][CC_id] = init_lte_eNB(frame_parms[CC_id], 0, frame_parms[CC_id]->Nid_cell, node_function[CC_id], abstraction_flag); PHY_vars_eNB_g[0][CC_id]->ue_dl_rb_alloc = 0x1fff; PHY_vars_eNB_g[0][CC_id]->target_ue_dl_mcs = target_dl_mcs; PHY_vars_eNB_g[0][CC_id]->ue_ul_nb_rb = 6; PHY_vars_eNB_g[0][CC_id]->target_ue_ul_mcs = target_ul_mcs; // initialization for phy-test for (k = 0; k < NUMBER_OF_UE_MAX; k++) { PHY_vars_eNB_g[0][CC_id]->transmission_mode[k] = transmission_mode; if (transmission_mode == 7) lte_gold_ue_spec_port5(PHY_vars_eNB_g[0][CC_id]->lte_gold_uespec_port5_table[k], frame_parms[CC_id]->Nid_cell, 0x1235+k); } if ((transmission_mode == 1) || (transmission_mode == 7)) { for (j = 0; j < frame_parms[CC_id]->nb_antennas_tx; j++) for (re = 0; re < frame_parms[CC_id]->ofdm_symbol_size; re++) PHY_vars_eNB_g[0][CC_id]->common_vars.beam_weights[0][0][j][re] = 0x00007fff / frame_parms[CC_id]->nb_antennas_tx; } if (phy_test==1) PHY_vars_eNB_g[0][CC_id]->mac_enabled = 0; else PHY_vars_eNB_g[0][CC_id]->mac_enabled = 1; if (PHY_vars_eNB_g[0][CC_id]->mac_enabled == 0) { //set default parameters for testing mode for (i = 0; i < NUMBER_OF_UE_MAX; i++) { PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK; PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index = beta_RI; PHY_vars_eNB_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI; PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = i; PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(i%3); PHY_vars_eNB_g[0][CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4; } } compute_prach_seq(&PHY_vars_eNB_g[0][CC_id]->frame_parms.prach_config_common, PHY_vars_eNB_g[0][CC_id]->frame_parms.frame_type, PHY_vars_eNB_g[0][CC_id]->X_u); PHY_vars_eNB_g[0][CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0]; if (frame_parms[CC_id]->frame_type == FDD) { PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0; } else { if (frame_parms[CC_id]->N_RB_DL == 100) PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624; else if (frame_parms[CC_id]->N_RB_DL == 50) PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624/2; else if (frame_parms[CC_id]->N_RB_DL == 25) PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624/4; } } } #if defined(ENABLE_ITTI) && defined(FLEXRAN_AGENT_SB_IF) /* * helper function to terminate a certain ITTI task */ void terminate_task(task_id_t task_id, mid_t mod_id) { LOG_I(ENB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id); MessageDef *msg; msg = itti_alloc_new_message (ENB_APP, TERMINATE_MESSAGE); itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg); } int stop_L1L2(int enb_id) { int CC_id; LOG_W(ENB_APP, "stopping lte-softmodem\n"); oai_exit = 1; /* stop trx devices */ for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { if (PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_stop_func) { LOG_I(ENB_APP, "stopping PHY_vars_eNB_g[0][%d]->rfdevice (via trx_stop_func())\n", CC_id); PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_stop_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); } if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_stop_func) { LOG_I(ENB_APP, "stopping PHY_vars_eNB_g[0][%d]->ifdevice (via trx_stop_func())\n", CC_id); PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_stop_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); } } /* these tasks need to pick up new configuration */ terminate_task(TASK_RRC_ENB, enb_id); terminate_task(TASK_L2L1, enb_id); LOG_W(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id); kill_eNB_proc(enb_id); oai_exit = 0; return 0; } /* * Restart the lte-softmodem. * This function checks whether we are in ENB_NORMAL_OPERATION (defined by * FlexRAN). If yes, first stop L1/L2/L3, then resume. */ int restart_L1L2(int enb_id) { int i, aa, CC_id; /* needed for fill_PHY_vars_eNB_g(), defined locally in main(); * abstraction flag is needed too, but defined both globally and in main () */ uint8_t beta_ACK = 0, beta_RI = 0, beta_CQI = 2; /* needed for macphy_init() */ int eMBMS_active = 0; LOG_W(ENB_APP, "restarting lte-softmodem\n"); /* block threads */ sync_var = -1; reconfigure_enb_params(enb_id); /* set frame parameters from configuration */ /* PHY_vars_eNB_g will be filled by init_lte_eNB(), so free and * let the data structure be filled again */ for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { free(PHY_vars_eNB_g[0][CC_id]); fill_PHY_vars_eNB_g(abstraction_flag, beta_ACK, beta_RI, beta_CQI); } dump_frame_parms(frame_parms[0]); init_openair0(); /* give MAC interface current cell information, the rest is the same. * For more info, check l2_init(). Then, initialize it (cf. line 1904). */ mac_xface->frame_parms = frame_parms[0]; mac_xface->macphy_init(eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,0,0); LOG_I(ENB_APP, "attempting to create ITTI tasks\n"); if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) { LOG_E(RRC, "Create task for RRC eNB failed\n"); return -1; } else { LOG_I(RRC, "Re-created task for RRC eNB successfully\n"); } if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) { LOG_E(PDCP, "Create task for L2L1 failed\n"); return -1; } else { LOG_I(PDCP, "Re-created task for L2L1 successfully\n"); } /* TODO XForms here */ printf("Initializing eNB threads\n"); init_eNB(node_function, node_timing, 1, eth_params, single_thread_flag, wait_for_sync); for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { PHY_vars_eNB_g[0][CC_id]->rf_map.card=0; PHY_vars_eNB_g[0][CC_id]->rf_map.chain=CC_id+chain_offset; } mlockall(MCL_CURRENT | MCL_FUTURE); printf("Setting eNB buffer to all-RX\n"); // Set LSBs for antenna switch (ExpressMIMO) for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { PHY_vars_eNB_g[0][CC_id]->hw_timing_advance = 0; for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++) for (aa=0; aa<frame_parms[CC_id]->nb_antennas_tx; aa++) PHY_vars_eNB_g[0][CC_id]->common_vars.txdata[0][aa][i] = 0x00010001; } 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); return 0; } #endif int main( int argc, char **argv ) { int i,aa; #if defined (XFORMS) void *status; #endif int CC_id; uint8_t abstraction_flag=0; uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2; PHY_vars_eNB_g=NULL; #if defined (XFORMS) int ret; #endif start_background_system(); #ifdef DEBUG_CONSOLE setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); #endif PHY_VARS_UE *UE[MAX_NUM_CCs]; mode = normal_txrx; memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS); memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs); set_latency_target(); // set default parameters set_default_frame_parms(frame_parms); // initialize logging logInit(); // get options and fill parameters from configuration file get_options (argc, argv); //Command-line options, enb_properties #if T_TRACER T_init(T_port, T_wait, T_dont_fork); #endif // initialize the log (see log.h for details) set_glog(glog_level, glog_verbosity); //randominit (0); set_taus_seed (0); if (UE_flag==1) { printf("configuring for UE\n"); set_comp_log(HW, LOG_DEBUG, LOG_HIGH, 1); set_comp_log(PHY, LOG_DEBUG, LOG_HIGH, 1); set_comp_log(MAC, LOG_INFO, LOG_HIGH, 1); set_comp_log(RLC, LOG_INFO, LOG_HIGH | FLAG_THREAD, 1); set_comp_log(PDCP, LOG_INFO, LOG_HIGH, 1); set_comp_log(OTG, LOG_INFO, LOG_HIGH, 1); set_comp_log(RRC, LOG_INFO, LOG_HIGH, 1); #if defined(ENABLE_ITTI) set_comp_log(EMU, LOG_INFO, LOG_MED, 1); # if defined(ENABLE_USE_MME) set_comp_log(NAS, LOG_INFO, LOG_HIGH, 1); # endif #endif } else { printf("configuring for eNB\n"); set_comp_log(HW, hw_log_level, hw_log_verbosity, 1); set_comp_log(PHY, phy_log_level, phy_log_verbosity, 1); if (opt_enabled == 1 ) set_comp_log(OPT, opt_log_level, opt_log_verbosity, 1); set_comp_log(MAC, mac_log_level, mac_log_verbosity, 1); set_comp_log(RLC, rlc_log_level, rlc_log_verbosity, 1); set_comp_log(PDCP, pdcp_log_level, pdcp_log_verbosity, 1); set_comp_log(RRC, rrc_log_level, rrc_log_verbosity, 1); #if defined(ENABLE_ITTI) set_comp_log(EMU, LOG_INFO, LOG_MED, 1); # if defined(ENABLE_USE_MME) set_comp_log(UDP_, udp_log_level, udp_log_verbosity, 1); set_comp_log(GTPU, gtpu_log_level, gtpu_log_verbosity, 1); set_comp_log(S1AP, LOG_DEBUG, LOG_HIGH, 1); set_comp_log(SCTP, LOG_INFO, LOG_HIGH, 1); # endif #if defined(ENABLE_SECURITY) set_comp_log(OSA, osa_log_level, osa_log_verbosity, 1); #endif #endif #ifdef LOCALIZATION set_comp_log(LOCALIZE, LOG_DEBUG, LOG_LOW, 1); set_component_filelog(LOCALIZE); #endif set_comp_log(ENB_APP, LOG_INFO, LOG_HIGH, 1); set_comp_log(OTG, LOG_INFO, LOG_HIGH, 1); if (online_log_messages == 1) { set_component_filelog(RRC); set_component_filelog(PDCP); } } if (ouput_vcd) { if (UE_flag==1) VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd"); else VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd"); } if (opp_enabled ==1) { reset_opp_meas(); } cpuf=get_cpu_freq_GHz(); #if defined(ENABLE_ITTI) if (UE_flag == 1) { log_set_instance_type (LOG_INSTANCE_UE); } else { log_set_instance_type (LOG_INSTANCE_ENB); } itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file); // initialize mscgen log after ITTI MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX); #endif if (opt_type != OPT_NONE) { radio_type_t radio_type; if (frame_parms[0]->frame_type == FDD) radio_type = RADIO_TYPE_FDD; else radio_type = RADIO_TYPE_TDD; if (init_opt(in_path, in_ip, NULL, radio_type) == -1) LOG_E(OPT,"failed to run OPT \n"); } #ifdef PDCP_USE_NETLINK netlink_init(); #if defined(PDCP_USE_NETLINK_QUEUES) pdcp_netlink_init(); #endif #endif #if !defined(ENABLE_ITTI) // to make a graceful exit when ctrl-c is pressed signal(SIGSEGV, signal_handler); signal(SIGINT, signal_handler); #endif check_clock(); #ifndef PACKAGE_VERSION # define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL" #endif LOG_I(HW, "Version: %s\n", PACKAGE_VERSION); // init the parameters for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { if (UE_flag==1) { frame_parms[CC_id]->nb_antennas_tx = nb_antenna_tx; frame_parms[CC_id]->nb_antennas_rx = nb_antenna_rx; frame_parms[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later LOG_I(PHY,"Set nb_rx_antenna %d , nb_tx_antenna %d \n",frame_parms[CC_id]->nb_antennas_rx, frame_parms[CC_id]->nb_antennas_tx); } } for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { //init prach for openair1 test // prach_fmt = get_prach_fmt(frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, frame_parms->frame_type); // N_ZC = (prach_fmt <4)?839:139; } #ifdef FLEXRAN_AGENT_SB_IF pthread_mutex_init(&mutex_node_ctrl, NULL); pthread_cond_init(&cond_node_ctrl, NULL); for (i = 0; i < NB_eNB_INST; i++) { flexran_agent_start(i, enb_config_get()); } LOG_I(ENB_APP, " * Waiting for FlexRAN RTController command *\n"); pthread_mutex_lock(&mutex_node_ctrl); while (ENB_NORMAL_OPERATION != node_control_state) pthread_cond_wait(&cond_node_ctrl, &mutex_node_ctrl); pthread_mutex_unlock(&mutex_node_ctrl); /* reconfigure eNB in case FlexRAN controller applied changes */ for (i=0; i < NB_eNB_INST; i++){ LOG_I(ENB_APP, "Reconfigure eNB module %d and FlexRAN eNB variables\n", i); reconfigure_enb_params(i); flexran_set_enb_vars(i, RAN_LTE_OAI); } #endif if (UE_flag==1) { NB_UE_INST=1; NB_INST=1; PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**)); PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs); for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { PHY_vars_UE_g[0][CC_id] = init_lte_UE(frame_parms[CC_id], 0,abstraction_flag); UE[CC_id] = PHY_vars_UE_g[0][CC_id]; printf("PHY_vars_UE_g[0][%d] = %p\n",CC_id,UE[CC_id]); if (phy_test==1) UE[CC_id]->mac_enabled = 0; else UE[CC_id]->mac_enabled = 1; if (UE[CC_id]->mac_enabled == 0) { //set default UL parameters for testing mode for (i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) { UE[CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK; UE[CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index = beta_RI; UE[CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI; UE[CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0; UE[CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3); UE[CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4; } } UE[CC_id]->UE_scan = UE_scan; UE[CC_id]->UE_scan_carrier = UE_scan_carrier; UE[CC_id]->mode = mode; printf("UE[%d]->mode = %d\n",CC_id,mode); for (uint8_t i=0; i<RX_NB_TH_MAX; i++) { UE[CC_id]->pdcch_vars[i][0]->agregationLevel = agregation_Level; UE[CC_id]->pdcch_vars[i][0]->dciFormat = dci_Format; } compute_prach_seq(&UE[CC_id]->frame_parms.prach_config_common, UE[CC_id]->frame_parms.frame_type, UE[CC_id]->X_u); if (UE[CC_id]->mac_enabled == 1) { UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1234; UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1234; } else { UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1235; UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1235; } UE[CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off; UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id]; if (frame_parms[CC_id]->frame_type==FDD) { UE[CC_id]->N_TA_offset = 0; } else { if (frame_parms[CC_id]->N_RB_DL == 100) UE[CC_id]->N_TA_offset = 624; else if (frame_parms[CC_id]->N_RB_DL == 50) UE[CC_id]->N_TA_offset = 624/2; else if (frame_parms[CC_id]->N_RB_DL == 25) UE[CC_id]->N_TA_offset = 624/4; } } // printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_poHwer,tx_max_power)); } else { //this is eNB PHY_vars_eNB_g = malloc(sizeof(PHY_VARS_eNB**)); PHY_vars_eNB_g[0] = malloc(sizeof(PHY_VARS_eNB*)); fill_PHY_vars_eNB_g(abstraction_flag, beta_ACK, beta_RI, beta_CQI); NB_eNB_INST=1; NB_INST=1; } fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx); cpuf=get_cpu_freq_GHz(); dump_frame_parms(frame_parms[0]); init_openair0(); #ifndef DEADLINE_SCHEDULER /* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */ cpu_set_t cpuset; int s; char cpu_affinity[1024]; CPU_ZERO(&cpuset); #ifdef CPU_AFFINITY if (get_nprocs() > 2) { CPU_SET(0, &cpuset); s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); if (s != 0) { perror( "pthread_setaffinity_np"); exit_fun("Error setting processor affinity"); } LOG_I(HW, "Setting the affinity of main function to CPU 0, for device library to use CPU 0 only!\n"); } #endif /* Check the actual affinity mask assigned to the thread */ s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); if (s != 0) { perror( "pthread_getaffinity_np"); exit_fun("Error getting processor affinity "); } memset(cpu_affinity, 0 , sizeof(cpu_affinity)); for (int j = 0; j < CPU_SETSIZE; j++) { if (CPU_ISSET(j, &cpuset)) { char temp[1024]; sprintf(temp, " CPU_%d ", j); strcat(cpu_affinity, temp); } } LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity); #endif openair0_cfg[0].log_level = glog_level; int eMBMS_active=0; if (node_function[0] <= NGFI_RAU_IF4p5) { // don't initialize L2 for RRU LOG_I(PHY,"Intializing L2\n"); mac_xface = malloc(sizeof(MAC_xface)); l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL, 0,// cba_group_active 0); // HO flag mac_xface->macphy_exit = &exit_fun; } else if (node_function[0] == NGFI_RRU_IF4p5) { // Initialize PRACH in this case } #if defined(ENABLE_ITTI) if ((UE_flag == 1)|| ((node_function[0]<NGFI_RAU_IF4p5)&&(phy_test==0))) // don't create if node doesn't connect to RRC/S1/GTP if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) { printf("cannot create ITTI tasks\n"); exit(-1); // need a softer mode } printf("ITTI tasks created\n"); #endif if (phy_test==0) { if (UE_flag==1) { printf("Filling UE band info\n"); fill_ue_band_info(); mac_xface->dl_phy_sync_success (0, 0, 0, 1); } else if (node_function[0]>NGFI_RRU_IF4p5) mac_xface->mrbch_phy_sync_failure (0, 0, 0); } mlockall(MCL_CURRENT | MCL_FUTURE); pthread_cond_init(&sync_cond,NULL); pthread_mutex_init(&sync_mutex, NULL); #ifdef XFORMS int UE_id; if (do_forms==1) { fl_initialize (&argc, argv, NULL, 0, 0); if (UE_flag==0) { form_stats_l2 = create_form_stats_form(); fl_show_form (form_stats_l2->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "l2 stats"); form_stats = create_form_stats_form(); fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats"); for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) { for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { form_enb[CC_id][UE_id] = create_lte_phy_scope_enb(); sprintf (title, "LTE UL SCOPE eNB for CC_id %d, UE %d",CC_id,UE_id); fl_show_form (form_enb[CC_id][UE_id]->lte_phy_scope_enb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); if (otg_enabled) { fl_set_button(form_enb[CC_id][UE_id]->button_0,1); fl_set_object_label(form_enb[CC_id][UE_id]->button_0,"DL Traffic ON"); } else { fl_set_button(form_enb[CC_id][UE_id]->button_0,0); fl_set_object_label(form_enb[CC_id][UE_id]->button_0,"DL Traffic OFF"); } } // CC_id } // UE_id } else { form_stats = create_form_stats_form(); fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats"); UE_id = 0; form_ue[UE_id] = create_lte_phy_scope_ue(); sprintf (title, "LTE DL SCOPE UE"); fl_show_form (form_ue[UE_id]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); /* if (openair_daq_vars.use_ia_receiver) { fl_set_button(form_ue[UE_id]->button_0,1); fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver ON"); } else { fl_set_button(form_ue[UE_id]->button_0,0); fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF"); }*/ fl_set_button(form_ue[UE_id]->button_0,0); fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF"); } ret = pthread_create(&forms_thread, NULL, scope_thread, NULL); if (ret == 0) pthread_setname_np( forms_thread, "xforms" ); printf("Scope thread created, ret=%d\n",ret); } #endif rt_sleep_ns(10*100000000ULL); // start the main thread if (UE_flag == 1) { init_UE(1); number_of_cards = 1; for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { PHY_vars_UE_g[0][CC_id]->rf_map.card=0; PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset; } } else { printf("Initializing eNB threads\n"); init_eNB(node_function,node_timing,1,eth_params,single_thread_flag,wait_for_sync); number_of_cards = 1; for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { PHY_vars_eNB_g[0][CC_id]->rf_map.card=0; PHY_vars_eNB_g[0][CC_id]->rf_map.chain=CC_id+chain_offset; } } // connect the TX/RX buffers if (UE_flag==1) { for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { #ifdef OAI_USRP UE[CC_id]->hw_timing_advance = timing_advance; #else UE[CC_id]->hw_timing_advance = 160; #endif } if (setup_ue_buffers(UE,&openair0_cfg[0])!=0) { printf("Error setting up eNB buffer\n"); exit(-1); } if (input_fd) { printf("Reading in from file to antenna buffer %d\n",0); if (fread(UE[0]->common_vars.rxdata[0], sizeof(int32_t), frame_parms[0]->samples_per_tti*10, input_fd) != frame_parms[0]->samples_per_tti*10) printf("error reading from file\n"); } //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX; } else { printf("Setting eNB buffer to all-RX\n"); // Set LSBs for antenna switch (ExpressMIMO) for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { PHY_vars_eNB_g[0][CC_id]->hw_timing_advance = 0; for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++) for (aa=0; aa<frame_parms[CC_id]->nb_antennas_tx; aa++) PHY_vars_eNB_g[0][CC_id]->common_vars.txdata[0][aa][i] = 0x00010001; } } sleep(3); 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); // wait for end of program printf("TYPE <CTRL-C> TO TERMINATE\n"); //getchar(); #if defined(ENABLE_ITTI) printf("Entering ITTI signals handler\n"); itti_wait_tasks_end(); oai_exit=1; #else while (oai_exit==0) rt_sleep_ns(100000000ULL); #endif // stop threads #ifdef XFORMS printf("waiting for XFORMS thread\n"); if (do_forms==1) { pthread_join(forms_thread,&status); fl_hide_form(form_stats->stats_form); fl_free_form(form_stats->stats_form); if (UE_flag==1) { fl_hide_form(form_ue[0]->lte_phy_scope_ue); fl_free_form(form_ue[0]->lte_phy_scope_ue); } else { fl_hide_form(form_stats_l2->stats_form); fl_free_form(form_stats_l2->stats_form); for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) { for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { fl_hide_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb); fl_free_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb); } } } } #endif printf("stopping MODEM threads\n"); // cleanup if (UE_flag == 1) { } else { stop_eNB(1); } #ifdef FLEXRAN_AGENT_SB_IF pthread_cond_destroy(&cond_node_ctrl); pthread_mutex_destroy(&mutex_node_ctrl); #endif pthread_cond_destroy(&sync_cond); pthread_mutex_destroy(&sync_mutex); // *** Handle per CC_id openair0 if (UE_flag==1) { if (PHY_vars_UE_g[0][0]->rfdevice.trx_end_func) PHY_vars_UE_g[0][0]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][0]->rfdevice); } else { for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { if (PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func) PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice); if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func) PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice); } } if (ouput_vcd) VCD_SIGNAL_DUMPER_CLOSE(); if (opt_enabled == 1) terminate_opt(); logClean(); printf("Bye.\n"); return 0; }