Merge remote-tracking branch 'origin/develop' into enhancement-74-SoDeRa
Conflicts: cmake_targets/CMakeLists.txt cmake_targets/build_oai targets/ARCH/COMMON/common_lib.c targets/ARCH/COMMON/common_lib.h targets/RT/USER/lte-softmodem.c
This commit is contained in:
@@ -38,6 +38,11 @@
|
||||
#include <inttypes.h>
|
||||
#include "bladerf_lib.h"
|
||||
|
||||
/** @addtogroup _BLADERF_PHY_RF_INTERFACE_
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! Number of BladeRF devices
|
||||
#ifdef __SSE4_1__
|
||||
# include <smmintrin.h>
|
||||
#endif
|
||||
@@ -47,13 +52,21 @@
|
||||
#endif
|
||||
|
||||
int num_devices=0;
|
||||
|
||||
/*These items configure the underlying asynch stream used by the the sync interface.
|
||||
*/
|
||||
|
||||
int trx_brf_init(openair0_device *openair0) {
|
||||
/*! \brief BladeRF Init function (not used at the moment)
|
||||
* \param device RF frontend parameters set by application
|
||||
*/
|
||||
int trx_brf_init(openair0_device *device) {
|
||||
|
||||
}
|
||||
|
||||
/*! \brief get current timestamp
|
||||
*\param device the hardware to use
|
||||
*\param module the bladeRf module
|
||||
*/
|
||||
|
||||
openair0_timestamp trx_get_timestamp(openair0_device *device, bladerf_module module) {
|
||||
int status;
|
||||
@@ -69,17 +82,29 @@ openair0_timestamp trx_get_timestamp(openair0_device *device, bladerf_module mod
|
||||
return meta.timestamp;
|
||||
}
|
||||
|
||||
|
||||
int trx_brf_start(openair0_device *openair0) {
|
||||
/*! \brief Start BladeRF
|
||||
*\param device the hardware to use
|
||||
*/
|
||||
int trx_brf_start(openair0_device *device) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief Get BladeRF stats
|
||||
*\param device the hardware to use
|
||||
*/
|
||||
static void trx_brf_stats(openair0_device *device){
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*! \brief Called to send samples to the BladeRF RF target
|
||||
@param device pointer to the device structure specific to the RF hardware target
|
||||
@param timestamp The timestamp at whicch the first sample MUST be sent
|
||||
@param buff Buffer which holds the samples
|
||||
@param nsamps number of samples to be sent
|
||||
@param cc index of the component carrier
|
||||
*/
|
||||
static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp, void **buff, int nsamps, int cc) {
|
||||
|
||||
int status;
|
||||
@@ -121,6 +146,16 @@ static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp,
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*! \brief Receive samples from hardware.
|
||||
* Read \ref nsamps samples from each channel to buffers. buff[0] is the array for
|
||||
* the first channel. *ptimestamp is the time at which the first sample
|
||||
* was received.
|
||||
* \param device the hardware to use
|
||||
* \param[out] ptimestamp the time at which the first sample was received.
|
||||
* \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps.
|
||||
* \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte.
|
||||
* \param cc Index of component carrier
|
||||
*/
|
||||
static int trx_brf_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
|
||||
|
||||
int status=0;
|
||||
@@ -157,6 +192,9 @@ static int trx_brf_read(openair0_device *device, openair0_timestamp *ptimestamp,
|
||||
|
||||
}
|
||||
|
||||
/*! \brief Terminate operation of the BladeRF transceiver -- free all associated resources
|
||||
* \param device the hardware to use
|
||||
*/
|
||||
int trx_brf_end(openair0_device *device) {
|
||||
|
||||
int status;
|
||||
@@ -172,25 +210,39 @@ int trx_brf_end(openair0_device *device) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*! \brief print the BladeRF statistics
|
||||
* \param device the hardware to use
|
||||
* \returns 0 on success
|
||||
*/
|
||||
int trx_brf_get_stats(openair0_device* device) {
|
||||
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
/*! \brief Reset the BladeRF statistics
|
||||
* \param device the hardware to use
|
||||
* \returns 0 on success
|
||||
*/
|
||||
int trx_brf_reset_stats(openair0_device* device) {
|
||||
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
/*! \brief Stop USRP
|
||||
* \param device the hardware to use
|
||||
*/
|
||||
int trx_brf_stop(openair0_device* device) {
|
||||
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
/*! \brief Set frequencies (TX/RX)
|
||||
* \param device the hardware to use
|
||||
* \returns 0 in success
|
||||
*/
|
||||
int trx_brf_set_freq(openair0_device* device) {
|
||||
|
||||
int status;
|
||||
@@ -213,12 +265,19 @@ int trx_brf_set_freq(openair0_device* device) {
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
/*! \brief Set Gains (TX/RX)
|
||||
* \param device the hardware to use
|
||||
* \returns 0 in success
|
||||
*/
|
||||
int trx_brf_set_gains(openair0_device* device) {
|
||||
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define RXDCLENGTH 16384
|
||||
int16_t cos_fsover8[8] = {2047, 1447, 0, -1448, -2047, -1448, 0, 1447};
|
||||
int16_t cos_3fsover8[8] = {2047, -1448, 0, 1447, -2047, 1447, 0, -1448};
|
||||
@@ -822,15 +881,23 @@ void calibrate_rf(openair0_device *device) {
|
||||
// write_output("blade_rf_test.m","rxs",calib_buff,RXDCLENGTH,1,1);
|
||||
}
|
||||
|
||||
int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
|
||||
/*! \brief Initialize Openair BLADERF target. It returns 0 if OK
|
||||
* \param device the hardware to use
|
||||
* \param openair0_cfg RF frontend parameters set by application
|
||||
*/
|
||||
int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
int status;
|
||||
int card=0;
|
||||
|
||||
brf_state_t *brf = (brf_state_t*)malloc(sizeof(brf_state_t));
|
||||
memset(brf, 0, sizeof(brf_state_t));
|
||||
/* device specific */
|
||||
openair0_cfg->txlaunch_wait = 1;//manage when TX processing is triggered
|
||||
openair0_cfg->txlaunch_wait_slotcount = 1; //manage when TX processing is triggered
|
||||
openair0_cfg->iq_txshift = 0;// shift
|
||||
openair0_cfg->iq_rxrescale = 15;//rescale iqs
|
||||
|
||||
// init required params
|
||||
|
||||
switch ((int)openair0_cfg->sample_rate) {
|
||||
case 30720000:
|
||||
openair0_cfg->samples_per_packet = 2048;
|
||||
@@ -857,7 +924,8 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai
|
||||
exit(-1);
|
||||
break;
|
||||
}
|
||||
|
||||
openair0_cfg->iq_txshift= 0;
|
||||
openair0_cfg->iq_rxrescale = 15; /*not sure*/
|
||||
openair0_cfg->rx_gain_calib_table = calib_table_fx4;
|
||||
|
||||
// The number of buffers to use in the underlying data stream
|
||||
@@ -1001,6 +1069,7 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai
|
||||
printf("BLADERF: Initializing openair0_device\n");
|
||||
device->priv = brf;
|
||||
device->Mod_id = num_devices++;
|
||||
device->type = BLADERF_DEV;
|
||||
device->trx_start_func = trx_brf_start;
|
||||
device->trx_end_func = trx_brf_end;
|
||||
device->trx_read_func = trx_brf_read;
|
||||
@@ -1019,6 +1088,9 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief bladeRF error report
|
||||
* \param status
|
||||
*/
|
||||
int brf_error(int status) {
|
||||
|
||||
//exit(-1);
|
||||
@@ -1026,7 +1098,9 @@ int brf_error(int status) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*! \brief Open BladeRF from serial port
|
||||
* \param serial name of serial port on which to open BladeRF device
|
||||
*/
|
||||
struct bladerf * open_bladerf_from_serial(const char *serial) {
|
||||
|
||||
int status;
|
||||
@@ -1053,6 +1127,10 @@ struct bladerf * open_bladerf_from_serial(const char *serial) {
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
|
||||
/*! \brief Get BladeRF log level
|
||||
* \param log_level log level
|
||||
*/
|
||||
int get_brf_log_level(int log_level){
|
||||
|
||||
int level=BLADERF_LOG_LEVEL_INFO;
|
||||
@@ -1081,3 +1159,4 @@ int get_brf_log_level(int log_level){
|
||||
}
|
||||
return level;
|
||||
}
|
||||
/*@}*/
|
||||
|
||||
@@ -37,45 +37,69 @@
|
||||
#include "common_lib.h"
|
||||
#include "log.h"
|
||||
|
||||
/** @addtogroup _BLADERF_PHY_RF_INTERFACE_
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! \brief BladeRF specific data structure */
|
||||
typedef struct {
|
||||
|
||||
// opaque BRF data struct
|
||||
//! opaque BladeRF device struct. An empty ("") or NULL device identifier will result in the first encountered device being opened (using the first discovered backend)
|
||||
struct bladerf *dev;
|
||||
// An empty ("") or NULL device identifier will result in the first encountered device being opened (using the first discovered backend)
|
||||
|
||||
|
||||
//! Number of buffers
|
||||
unsigned int num_buffers;
|
||||
//! Buffer size
|
||||
unsigned int buffer_size;
|
||||
//! Number of transfers
|
||||
unsigned int num_transfers;
|
||||
//! RX timeout
|
||||
unsigned int rx_timeout_ms;
|
||||
//! TX timeout
|
||||
unsigned int tx_timeout_ms;
|
||||
|
||||
//! Metadata for RX
|
||||
struct bladerf_metadata meta_rx;
|
||||
//!Metadata for TX
|
||||
struct bladerf_metadata meta_tx;
|
||||
|
||||
//! Sample rate
|
||||
unsigned int sample_rate;
|
||||
// time offset between transmiter timestamp and receiver timestamp;
|
||||
//! time offset between transmiter timestamp and receiver timestamp;
|
||||
double tdiff;
|
||||
// use brf_time_offset to get this value
|
||||
//! TX number of forward samples use brf_time_offset to get this value
|
||||
int tx_forward_nsamps; //166 for 20Mhz
|
||||
|
||||
|
||||
// --------------------------------
|
||||
// Debug and output control
|
||||
// --------------------------------
|
||||
//! Number of underflows
|
||||
int num_underflows;
|
||||
//! Number of overflows
|
||||
int num_overflows;
|
||||
//! number of sequential errors
|
||||
int num_seq_errors;
|
||||
//! number of RX errors
|
||||
int num_rx_errors;
|
||||
//! Number of TX errors
|
||||
int num_tx_errors;
|
||||
|
||||
//! timestamp of current TX
|
||||
uint64_t tx_current_ts;
|
||||
//! timestamp of current RX
|
||||
uint64_t rx_current_ts;
|
||||
//! number of actual samples transmitted
|
||||
uint64_t tx_actual_nsamps;
|
||||
//! number of actual samples received
|
||||
uint64_t rx_actual_nsamps;
|
||||
//! number of TX samples
|
||||
uint64_t tx_nsamps;
|
||||
//! number of RX samples
|
||||
uint64_t rx_nsamps;
|
||||
//! number of TX count
|
||||
uint64_t tx_count;
|
||||
//! number of RX count
|
||||
uint64_t rx_count;
|
||||
//! timestamp of RX packet
|
||||
openair0_timestamp rx_timestamp;
|
||||
|
||||
} brf_state_t;
|
||||
@@ -84,3 +108,4 @@ typedef struct {
|
||||
*/
|
||||
|
||||
int brf_error(int status);
|
||||
/*@}*/
|
||||
|
||||
@@ -37,40 +37,140 @@
|
||||
* \warning
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common_lib.h"
|
||||
|
||||
int set_device(openair0_device *device) {
|
||||
|
||||
int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
|
||||
#ifdef ETHERNET
|
||||
device->type=ETH_IF;
|
||||
device->func_type = BBU_FUNC;
|
||||
printf(" openair0_dev_init_eth ...\n");
|
||||
return(openair0_dev_init_eth(device, openair0_cfg));
|
||||
|
||||
#elif EXMIMO
|
||||
device->type=EXMIMO_IF;
|
||||
printf("openair0_dev_init_exmimo...\n");
|
||||
return(openair0_dev_init_exmimo(device, openair0_cfg));
|
||||
#elif OAI_USRP
|
||||
device->type=USRP_B200_IF;
|
||||
openair0_dev_init_usrp(device, openair0_cfg);
|
||||
printf("openair0_dev_init_usrp ...\n");
|
||||
return(openair0_dev_init_usrp(device, openair0_cfg));
|
||||
#elif OAI_BLADERF
|
||||
device->type=BLADERF_IF;
|
||||
printf("openair0_dev_init_bladerf ...\n");
|
||||
return(openair0_dev_init_bladerf(device, openair0_cfg));
|
||||
#elif OAI_LMSSDR
|
||||
device->type=LMSSDR_IF;
|
||||
printf("openair0_dev_init_lmssdr ...\n");
|
||||
/*
|
||||
if (openair0_cfg[0].configFilename==NULL) {
|
||||
printf("Please provide a configuration file for SoDeRa\n");
|
||||
exit(-1);
|
||||
}*/
|
||||
|
||||
return(openair0_dev_init_lms(device, openair0_cfg));
|
||||
#endif
|
||||
|
||||
switch (device->type) {
|
||||
|
||||
case EXMIMO_DEV:
|
||||
printf("[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"));
|
||||
break;
|
||||
case USRP_B200_DEV:
|
||||
printf("[%s] has loaded USRP B200 device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"));
|
||||
break;
|
||||
case USRP_X300_DEV:
|
||||
printf("[%s] has loaded USRP X300 device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"));
|
||||
break;
|
||||
case BLADERF_DEV:
|
||||
printf("[%s] has loaded BLADERF device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"));
|
||||
break;
|
||||
case LMSSDR_DEV:
|
||||
printf("[%s] has loaded LMSSDR device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"));
|
||||
break;
|
||||
case NONE_DEV:
|
||||
printf("[%s] has not loaded a HW device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"));
|
||||
break;
|
||||
default:
|
||||
printf("[%s] invalid HW device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int set_transport(openair0_device *device) {
|
||||
|
||||
switch (device->transp_type) {
|
||||
|
||||
case ETHERNET_TP:
|
||||
printf("[%s] has loaded ETHERNET trasport protocol.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"));
|
||||
return 0;
|
||||
break;
|
||||
case NONE_TP:
|
||||
printf("[%s] has not loaded a transport protocol.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"));
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
printf("[%s] invalid transport protocol.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"));
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* look for the interface library and load it */
|
||||
int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * cfg, uint8_t flag) {
|
||||
|
||||
void *lib_handle;
|
||||
oai_device_initfunc_t dp ;
|
||||
oai_transport_initfunc_t tp ;
|
||||
|
||||
if (flag == BBU_LOCAL_RADIO_HEAD) {
|
||||
lib_handle = dlopen(OAI_RF_LIBNAME, RTLD_LAZY);
|
||||
if (!lib_handle) {
|
||||
printf( "Unable to locate %s: HW device set to NONE_DEV.\n", OAI_RF_LIBNAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dp = dlsym(lib_handle,"device_init");
|
||||
|
||||
if (dp != NULL ) {
|
||||
dp(device,openair0_cfg);
|
||||
} else {
|
||||
fprintf(stderr, "%s %d:oai device intializing function not found %s\n", __FILE__, __LINE__, dlerror());
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
lib_handle = dlopen(OAI_TP_LIBNAME, RTLD_LAZY);
|
||||
if (!lib_handle) {
|
||||
printf( "Unable to locate %s: transport protocol set to NONE_TP.\n", OAI_TP_LIBNAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tp = dlsym(lib_handle,"transport_init");
|
||||
|
||||
if (tp != NULL ) {
|
||||
tp(device,openair0_cfg,cfg);
|
||||
} else {
|
||||
fprintf(stderr, "%s %d:oai device intializing function not found %s\n", __FILE__, __LINE__, dlerror());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
|
||||
int rc;
|
||||
//ToDo: EXMIMO harmonization is not complete. That is the reason for this ifdef
|
||||
#ifdef EXMIMO
|
||||
device_init(device, openair0_cfg);
|
||||
#else
|
||||
rc=load_lib(device, openair0_cfg, NULL,BBU_LOCAL_RADIO_HEAD );
|
||||
if ( rc >= 0) {
|
||||
if ( set_device(device) < 0) {
|
||||
fprintf(stderr, "%s %d:Unsupported radio head\n",__FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params) {
|
||||
int rc;
|
||||
rc=load_lib(device, openair0_cfg, eth_params, BBU_REMOTE_RADIO_HEAD);
|
||||
if ( rc >= 0) {
|
||||
if ( set_transport(device) < 0) {
|
||||
fprintf(stderr, "%s %d:Unsupported transport protocol\n",__FILE__, __LINE__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -42,11 +42,20 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* name of shared library implementing the radio front end */
|
||||
#define OAI_RF_LIBNAME "liboai_device.so"
|
||||
/* name of shared library implementing the transport */
|
||||
#define OAI_TP_LIBNAME "liboai_transpro.so"
|
||||
|
||||
/* flags for BBU to determine whether the attached radio head is local or remote */
|
||||
#define BBU_LOCAL_RADIO_HEAD 0
|
||||
#define BBU_REMOTE_RADIO_HEAD 1
|
||||
|
||||
typedef int64_t openair0_timestamp;
|
||||
typedef volatile int64_t openair0_vtimestamp;
|
||||
|
||||
|
||||
/* structrue holds the parameters to configure USRP devices*/
|
||||
/*!\brief structrue holds the parameters to configure USRP devices*/
|
||||
typedef struct openair0_device_t openair0_device;
|
||||
|
||||
|
||||
@@ -65,10 +74,56 @@ typedef enum {
|
||||
} duplex_mode_t;
|
||||
|
||||
|
||||
/** @addtogroup _PHY_RF_INTERFACE_
|
||||
|
||||
/** @addtogroup _GENERIC_PHY_RF_INTERFACE_
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!\brief RF device types
|
||||
*/
|
||||
typedef enum {
|
||||
MIN_RF_DEV_TYPE = 0,
|
||||
/*!\brief device is ExpressMIMO */
|
||||
EXMIMO_DEV,
|
||||
/*!\brief device is USRP B200/B210*/
|
||||
USRP_B200_DEV,
|
||||
/*!\brief device is USRP X300/X310*/
|
||||
USRP_X300_DEV,
|
||||
/*!\brief device is BLADE RF*/
|
||||
BLADERF_DEV,
|
||||
/*!\brief device is LMSSDR (SoDeRa)*/
|
||||
LMSSDR_DEV,
|
||||
/*!\brief device is NONE*/
|
||||
NONE_DEV,
|
||||
MAX_RF_DEV_TYPE
|
||||
|
||||
} dev_type_t;
|
||||
|
||||
/*!\brief transport protocol types
|
||||
*/
|
||||
typedef enum {
|
||||
MIN_TRANSP_TYPE = 0,
|
||||
/*!\brief transport protocol ETHERNET */
|
||||
ETHERNET_TP,
|
||||
/*!\brief no transport protocol*/
|
||||
NONE_TP,
|
||||
MAX_TRANSP_TYPE
|
||||
|
||||
} transport_type_t;
|
||||
|
||||
|
||||
/*!\brief openair0 device host type */
|
||||
typedef enum {
|
||||
MIN_HOST_TYPE = 0,
|
||||
/*!\brief device functions within a BBU */
|
||||
BBU_HOST,
|
||||
/*!\brief device functions within a RRH */
|
||||
RRH_HOST,
|
||||
MAX_HOST_TYPE
|
||||
|
||||
}host_type_t;
|
||||
|
||||
|
||||
/*! \brief RF Gain clibration */
|
||||
typedef struct {
|
||||
//! Frequency for which RX chain was calibrated
|
||||
double freq;
|
||||
@@ -76,10 +131,11 @@ typedef struct {
|
||||
double offset;
|
||||
} rx_gain_calib_table_t;
|
||||
|
||||
/*! \brief RF frontend parameters set by application */
|
||||
typedef struct {
|
||||
//! Module ID for this configuration
|
||||
int Mod_id;
|
||||
// device log level
|
||||
//! device log level
|
||||
int log_level;
|
||||
//! duplexing mode
|
||||
duplex_mode_t duplex_mode;
|
||||
@@ -90,11 +146,15 @@ typedef struct {
|
||||
//! the sample rate for both transmit and receive.
|
||||
double sample_rate;
|
||||
//! number of samples per RX/TX packet (USRP + Ethernet)
|
||||
int samples_per_packet;
|
||||
unsigned int samples_per_packet;
|
||||
//! delay in sending samples (write) due to hardware access, softmodem processing and fronthaul delay if exist
|
||||
int tx_scheduling_advance;
|
||||
//! offset in samples between TX and RX paths
|
||||
int tx_sample_advance;
|
||||
//! configurable tx thread lauch delay
|
||||
int txlaunch_wait; /* 1 or 0 */
|
||||
//! configurable tx thread lauch delay
|
||||
int txlaunch_wait_slotcount;
|
||||
//! number of RX channels (=RX antennas)
|
||||
int rx_num_channels;
|
||||
//! number of TX channels (=TX antennas)
|
||||
@@ -125,80 +185,64 @@ typedef struct {
|
||||
double tx_bw;
|
||||
//! Auto calibration flag
|
||||
int autocal[4];
|
||||
//! RRH IP addr for Ethernet interface
|
||||
char *remote_ip;
|
||||
//! RRH port number for Ethernet interface
|
||||
int remote_port;
|
||||
//! my IP addr for Ethernet interface (eNB/BBU, UE)
|
||||
char *my_ip;
|
||||
//! my port number for Ethernet interface (eNB/BBU, UE)
|
||||
int my_port;
|
||||
//! rf devices work with x bits iqs when oai have its own iq format
|
||||
//! the two following parameters are used to convert iqs
|
||||
int iq_txshift;
|
||||
int iq_rxrescale;
|
||||
//! remote IP/MAC addr for Ethernet interface
|
||||
char *remote_addr;
|
||||
//! remote port number for Ethernet interface
|
||||
unsigned int remote_port;
|
||||
//! local IP/MAC addr for Ethernet interface (eNB/BBU, UE)
|
||||
char *my_addr;
|
||||
//! local port number for Ethernet interface (eNB/BBU, UE)
|
||||
unsigned int my_port;
|
||||
//! Configuration file for LMS7002M
|
||||
char *configFilename;
|
||||
} openair0_config_t;
|
||||
|
||||
/*! \brief RF mapping */
|
||||
typedef struct {
|
||||
/* card id */
|
||||
//! card id
|
||||
int card;
|
||||
/* rf chain id */
|
||||
//! rf chain id
|
||||
int chain;
|
||||
} openair0_rf_map;
|
||||
|
||||
|
||||
|
||||
/*!\brief interface types that apply to modules (RRH_BBU/RRH_UE) created in RRH (rrh_gw.c)
|
||||
and are defined with respect to the RF device that is present in RRH
|
||||
-RRH_BBU modules have two devices, one is by default ETHERNET (will have ETH_IF) and the other one is a
|
||||
RF device (EXMIMO,USRP,BLADERF) or no device (NONE_IF).
|
||||
-RRH_UE modules have two devices one is by default ETHERNET (will have ETH_IF)
|
||||
and the other one by default not present so it will have NONE_IF
|
||||
*/
|
||||
typedef enum {
|
||||
MIN_DEV_TYPE = 0,
|
||||
/*!\brief device is ETH */
|
||||
ETH_IF,
|
||||
/*!\brief device is ExpressMIMO */
|
||||
EXMIMO_IF,
|
||||
/*!\brief device is USRP B200/B210*/
|
||||
USRP_B200_IF,
|
||||
/*!\brief device is USRP X300/X310*/
|
||||
USRP_X300_IF,
|
||||
/*!\brief device is BLADE RF*/
|
||||
BLADERF_IF,
|
||||
/*!\brief device is LMSSDR*/
|
||||
LMSSDR_IF,
|
||||
/*!\brief device is NONE*/
|
||||
NONE_IF,
|
||||
MAX_DEV_TYPE
|
||||
|
||||
} dev_type_t;
|
||||
typedef struct {
|
||||
char *remote_addr;
|
||||
//! remote port number for Ethernet interface
|
||||
unsigned int remote_port;
|
||||
//! local IP/MAC addr for Ethernet interface (eNB/BBU, UE)
|
||||
char *my_addr;
|
||||
//! local port number for Ethernet interface (eNB/BBU, UE)
|
||||
unsigned int my_port;
|
||||
//! local port number for Ethernet interface (eNB/BBU, UE)
|
||||
char *local_if_name;
|
||||
//! local port number for Ethernet interface (eNB/BBU, UE)
|
||||
uint8_t transp_preference;
|
||||
} eth_params_t;
|
||||
|
||||
|
||||
/*!\brief openair0 device host type */
|
||||
typedef enum {
|
||||
MIN_FUNC_TYPE = 0,
|
||||
/*!\brief device functions within a BBU */
|
||||
BBU_FUNC,
|
||||
/*!\brief device functions within a RRH */
|
||||
RRH_FUNC,
|
||||
MAX_FUNC_TYPE
|
||||
|
||||
}func_type_t;
|
||||
|
||||
/*!\brief structure holds the parameters to configure USRP devices */
|
||||
struct openair0_device_t {
|
||||
/* Module ID of this device */
|
||||
/*!brief Module ID of this device */
|
||||
int Mod_id;
|
||||
|
||||
/* Type of this device */
|
||||
/*!brief Type of this device */
|
||||
dev_type_t type;
|
||||
|
||||
/* Type of the device's host (BBU/RRH) */
|
||||
func_type_t func_type;
|
||||
/*!brief Transport protocol type that the device suppports (in case I/Q samples need to be transported) */
|
||||
transport_type_t transp_type;
|
||||
|
||||
/* RF frontend parameters set by application */
|
||||
/*!brief Type of the device's host (BBU/RRH) */
|
||||
host_type_t host_type;
|
||||
|
||||
/* !brief RF frontend parameters set by application */
|
||||
openair0_config_t *openair0_cfg;
|
||||
|
||||
/* Can be used by driver to hold internal structure*/
|
||||
/*!brief Can be used by driver to hold internal structure*/
|
||||
void *priv;
|
||||
|
||||
/* Functions API, which are called by the application*/
|
||||
@@ -220,7 +264,7 @@ struct openair0_device_t {
|
||||
@param msg pointer to the message structure passed between BBU-RRH
|
||||
@param msg_len length of the message
|
||||
*/
|
||||
int (*trx_reply_func)(openair0_device *openair0, void *msg, ssize_t msg_len);
|
||||
int (*trx_reply_func)(openair0_device *device, void *msg, ssize_t msg_len);
|
||||
|
||||
/*! \brief Called to send samples to the RF target
|
||||
@param device pointer to the device structure specific to the RF hardware target
|
||||
@@ -238,9 +282,9 @@ struct openair0_device_t {
|
||||
* was received.
|
||||
* \param device the hardware to use
|
||||
* \param[out] ptimestamp the time at which the first sample was received.
|
||||
* \param[out] An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps.
|
||||
* \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps.
|
||||
* \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte.
|
||||
* \param cc Number of channels. If cc == 1, only buff[0] is filled with samples.
|
||||
* \param antenna_id Index of antenna for which to receive samples
|
||||
* \returns the number of sample read
|
||||
*/
|
||||
int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int antenna_id);
|
||||
@@ -257,50 +301,64 @@ struct openair0_device_t {
|
||||
*/
|
||||
int (*trx_reset_stats_func)(openair0_device *device);
|
||||
|
||||
/*! \brief Terminate operation of the transceiver -- free all associated resources */
|
||||
/*! \brief Terminate operation of the transceiver -- free all associated resources
|
||||
* \param device the hardware to use
|
||||
*/
|
||||
void (*trx_end_func)(openair0_device *device);
|
||||
|
||||
/* Terminate operation */
|
||||
/*! \brief Stop operation of the transceiver
|
||||
* \param card RF Card to use
|
||||
*/
|
||||
int (*trx_stop_func)(int card);
|
||||
|
||||
/* Functions API related to UE*/
|
||||
|
||||
/*! \brief Set RX feaquencies
|
||||
* \param
|
||||
* \param device the hardware to use
|
||||
* \param openair0_cfg RF frontend parameters set by application
|
||||
* \param exmimo_dump_config dump EXMIMO configuration
|
||||
* \returns 0 in success
|
||||
*/
|
||||
int (*trx_set_freq_func)(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config);
|
||||
|
||||
/*! \brief Set gains
|
||||
* \param
|
||||
* \param device the hardware to use
|
||||
* \param openair0_cfg RF frontend parameters set by application
|
||||
* \returns 0 in success
|
||||
*/
|
||||
int (*trx_set_gains_func)(openair0_device* device, openair0_config_t *openair0_cfg);
|
||||
|
||||
};
|
||||
|
||||
/* type of device init function, implemented in shared lib */
|
||||
typedef int(*oai_device_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg);
|
||||
/* type of transport init function, implemented in shared lib */
|
||||
typedef int(*oai_transport_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*! \brief Initialize Openair RF target. It returns 0 if OK */
|
||||
int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg);
|
||||
|
||||
/*! \brief Initialize openair RF target. It returns 0 if OK */
|
||||
int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg);
|
||||
/*! \brief Initialize transport protocol . It returns 0 if OK */
|
||||
int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params);
|
||||
|
||||
|
||||
//USRP
|
||||
/*! \brief Get the current timestamp of USRP */
|
||||
/*! \brief Get current timestamp of USRP
|
||||
* \param device the hardware to use
|
||||
*/
|
||||
openair0_timestamp get_usrp_time(openair0_device *device);
|
||||
/*! \brief Set the RX frequency of USRP RF TARGET */
|
||||
|
||||
/*! \brief Set RX frequencies
|
||||
* \param device the hardware to use
|
||||
* \param openair0_cfg RF frontend parameters set by application
|
||||
* \returns 0 in success
|
||||
*/
|
||||
int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg);
|
||||
|
||||
//extern
|
||||
/*! \brief Initialize Openair ETHERNET target. It returns 0 if OK */
|
||||
int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg);
|
||||
int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg);
|
||||
int openair0_dev_init_lms(openair0_device *device, openair0_config_t *openair0_cfg);
|
||||
int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg);
|
||||
int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair0_cfg);
|
||||
|
||||
/*@}*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -0,0 +1,319 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
OpenAirInterface is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenAirInterface.The full GNU General Public License is
|
||||
included in this distribution in the file called "COPYING". If not,
|
||||
see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Contact Information
|
||||
OpenAirInterface Admin: openair_admin@eurecom.fr
|
||||
OpenAirInterface Tech : openair_tech@eurecom.fr
|
||||
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
/*! \file ethernet_lib.c
|
||||
* \brief API to stream I/Q samples over standard ethernet
|
||||
* \author add alcatel Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp
|
||||
* \date 2015
|
||||
* \version 0.2
|
||||
* \company Eurecom
|
||||
* \maintainer: navid.nikaein@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "common_lib.h"
|
||||
#include "ethernet_lib.h"
|
||||
|
||||
#define DEBUG 0
|
||||
|
||||
struct sockaddr_ll dest_addr[MAX_INST];
|
||||
struct sockaddr_ll local_addr[MAX_INST];
|
||||
int addr_len[MAX_INST];
|
||||
struct ifreq if_index[MAX_INST];
|
||||
struct ether_header eh;
|
||||
|
||||
int eth_socket_init_raw(openair0_device *device) {
|
||||
|
||||
int i = 0;
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
int Mod_id = device->Mod_id;
|
||||
const char *local_mac, *remote_mac;
|
||||
int local_port=0, remote_port=0;
|
||||
int sock_dom=0;
|
||||
int sock_type=0;
|
||||
int sock_proto=0;
|
||||
|
||||
if (device->host_type == RRH_HOST ) { /* RRH doesn't know remote MAC(will be retrieved from first packet send from BBU) and remote port(don't care) */
|
||||
local_mac = device->openair0_cfg->my_addr;
|
||||
local_port = device->openair0_cfg->my_port;
|
||||
remote_mac = malloc(ETH_ALEN);
|
||||
memset(remote_mac,0,ETH_ALEN);
|
||||
remote_port = 0;
|
||||
printf("[%s] local MAC addr %s remote MAC addr %s\n","RRH", local_mac,remote_mac);
|
||||
} else {
|
||||
local_mac = device->openair0_cfg->my_addr;
|
||||
local_port = device->openair0_cfg->my_port;
|
||||
remote_mac = device->openair0_cfg->remote_addr;
|
||||
remote_port = device->openair0_cfg->remote_port;
|
||||
printf("[%s] local MAC addr %s remote MAC addr %s\n","BBU", local_mac,remote_mac);
|
||||
}
|
||||
|
||||
|
||||
/* Open a RAW socket to send on */
|
||||
sock_dom=AF_PACKET;
|
||||
sock_type=SOCK_RAW;
|
||||
sock_proto=IPPROTO_RAW;
|
||||
if ((eth->sockfd[Mod_id] = socket(sock_dom, sock_type, sock_proto)) == -1) {
|
||||
perror("ETHERNET: Error opening RAW socket");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* initialize destination address */
|
||||
for (i=0; i< MAX_INST; i++) {
|
||||
bzero((void *)&(local_addr[i]), sizeof(struct sockaddr_ll));
|
||||
bzero((void *)&(if_index[i]), sizeof(struct ifreq));
|
||||
}
|
||||
/* Get the index of the interface to send on */
|
||||
strcpy(if_index[Mod_id].ifr_name,eth->if_name[Mod_id]);
|
||||
if (ioctl(eth->sockfd[Mod_id], SIOCGIFINDEX, &(if_index[Mod_id])) < 0)
|
||||
perror("SIOCGIFINDEX");
|
||||
|
||||
local_addr[Mod_id].sll_family = AF_PACKET;
|
||||
local_addr[Mod_id].sll_ifindex = if_index[Mod_id].ifr_ifindex;
|
||||
/* hear traffic from specific protocol*/
|
||||
local_addr[Mod_id].sll_protocol = htons((short)device->openair0_cfg->my_port);
|
||||
local_addr[Mod_id].sll_halen = ETH_ALEN;
|
||||
local_addr[Mod_id].sll_pkttype = PACKET_OTHERHOST;
|
||||
addr_len[Mod_id] = sizeof(struct sockaddr_ll);
|
||||
|
||||
if (bind(eth->sockfd[Mod_id],(struct sockaddr *)&local_addr[Mod_id],addr_len[Mod_id])<0) {
|
||||
perror("ETHERNET: Cannot bind to socket");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Construct the Ethernet header */
|
||||
ether_aton_r(local_mac, (struct ether_addr *)(&(eh.ether_shost)));
|
||||
ether_aton_r(remote_mac, (struct ether_addr *)(&(eh.ether_dhost)));
|
||||
eh.ether_type = htons((short)device->openair0_cfg->my_port);
|
||||
|
||||
printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eh.ether_shost[0],eh.ether_shost[1],eh.ether_shost[2],eh.ether_shost[3],eh.ether_shost[4],eh.ether_shost[5]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) {
|
||||
|
||||
int bytes_sent=0;
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
int Mod_id = device->Mod_id;
|
||||
int sendto_flag =0;
|
||||
int i=0;
|
||||
//sendto_flag|=flags;
|
||||
|
||||
eth->tx_nsamps=nsamps;
|
||||
|
||||
for (i=0;i<cc;i++) {
|
||||
/* buff[i] points to the position in tx buffer where the payload to be sent is
|
||||
buff2 points to the position in tx buffer where the packet header will be placed */
|
||||
void *buff2 = (void*)(buff[i]-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES);
|
||||
|
||||
/* we don't want to ovewrite with the header info the previous tx buffer data so we store it*/
|
||||
struct ether_header temp = *(struct ether_header *)buff2;
|
||||
int32_t temp0 = *(int32_t *)(buff2 + MAC_HEADER_SIZE_BYTES);
|
||||
openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t));
|
||||
|
||||
bytes_sent = 0;
|
||||
memcpy(buff2,(void*)&eh,MAC_HEADER_SIZE_BYTES);
|
||||
*(int16_t *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int16_t))=1+(i<<1);
|
||||
*(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)) = timestamp;
|
||||
|
||||
/*printf("[RRH]write mod_%d %d , len %d, buff %p \n",
|
||||
Mod_id,eth->sockfd[Mod_id],RAW_PACKET_SIZE_BYTES(nsamps), buff2);*/
|
||||
|
||||
while(bytes_sent < RAW_PACKET_SIZE_BYTES(nsamps)) {
|
||||
#if DEBUG
|
||||
printf("------- TX ------: buff2 current position=%d remaining_bytes=%d bytes_sent=%d \n",
|
||||
(void *)(buff2+bytes_sent),
|
||||
RAW_PACKET_SIZE_BYTES(nsamps) - bytes_sent,
|
||||
bytes_sent);
|
||||
#endif
|
||||
/* Send packet */
|
||||
bytes_sent += send(eth->sockfd[Mod_id],
|
||||
buff2,
|
||||
RAW_PACKET_SIZE_BYTES(nsamps),
|
||||
sendto_flag);
|
||||
if ( bytes_sent == -1) {
|
||||
eth->num_tx_errors++;
|
||||
perror("ETHERNET WRITE: ");
|
||||
exit(-1);
|
||||
} else {
|
||||
#if DEBUG
|
||||
printf("------- TX ------: nu=%x an_id=%d ts%d bytes_sent=%d\n",
|
||||
*(uint8_t *)(buff2+ETH_ALEN),
|
||||
*(int16_t *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int16_t)),
|
||||
*(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)),
|
||||
bytes_sent);
|
||||
dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, RAW_PACKET_SIZE_BYTES(nsamps), TX_FLAG);
|
||||
#endif
|
||||
eth->tx_actual_nsamps=bytes_sent>>2;
|
||||
eth->tx_count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* tx buffer values restored */
|
||||
*(struct ether_header *)buff2 = temp;
|
||||
*(int32_t *)(buff2 + MAC_HEADER_SIZE_BYTES) = temp0;
|
||||
*(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)) = temp1;
|
||||
}
|
||||
return (bytes_sent-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES)>>2;
|
||||
}
|
||||
|
||||
|
||||
int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) {
|
||||
|
||||
int bytes_received=0;
|
||||
int i=0;
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
int Mod_id = device->Mod_id;
|
||||
int rcvfrom_flag =0;
|
||||
|
||||
eth->rx_nsamps=nsamps;
|
||||
|
||||
for (i=0;i<cc;i++) {
|
||||
/* buff[i] points to the position in rx buffer where the payload to be received will be placed
|
||||
buff2 points to the position in rx buffer where the packet header will be placed */
|
||||
void *buff2 = (void*)(buff[i]-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES);
|
||||
|
||||
/* we don't want to ovewrite with the header info the previous rx buffer data so we store it*/
|
||||
struct ether_header temp = *(struct ether_header *)buff2;
|
||||
int32_t temp0 = *(int32_t *)(buff2 + MAC_HEADER_SIZE_BYTES);
|
||||
openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t));
|
||||
|
||||
bytes_received=0;
|
||||
|
||||
while(bytes_received < RAW_PACKET_SIZE_BYTES(nsamps)) {
|
||||
bytes_received +=recv(eth->sockfd[Mod_id],
|
||||
buff2,
|
||||
RAW_PACKET_SIZE_BYTES(nsamps),
|
||||
rcvfrom_flag);
|
||||
|
||||
if (bytes_received ==-1) {
|
||||
eth->num_rx_errors++;
|
||||
perror("ETHERNET READ: ");
|
||||
exit(-1);
|
||||
} else {
|
||||
/* store the timestamp value from packet's header */
|
||||
*timestamp = *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t));
|
||||
eth->rx_actual_nsamps=bytes_received>>2;
|
||||
eth->rx_count++;
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
printf("------- RX------: nu=%x an_id=%d ts%d bytes_recv=%d \n",
|
||||
*(uint8_t *)(buff2+ETH_ALEN),
|
||||
*(int16_t *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int16_t)),
|
||||
*(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)),
|
||||
bytes_received);
|
||||
dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, RAW_PACKET_SIZE_BYTES(nsamps),RX_FLAG);
|
||||
|
||||
#endif
|
||||
|
||||
/* tx buffer values restored */
|
||||
*(struct ether_header *)buff2 = temp;
|
||||
*(int32_t *)(buff2 + MAC_HEADER_SIZE_BYTES) = temp0;
|
||||
*(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)) = temp1;
|
||||
}
|
||||
return (bytes_received-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES)>>2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int eth_set_dev_conf_raw(openair0_device *device) {
|
||||
|
||||
int Mod_id = device->Mod_id;
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
void *msg;
|
||||
ssize_t msg_len;
|
||||
|
||||
/* a BBU client sends to RRH a set of configuration parameters (openair0_config_t)
|
||||
so that RF front end is configured appropriately and
|
||||
frame/packet size etc. can be set */
|
||||
|
||||
msg = malloc(MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t));
|
||||
msg_len = MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t);
|
||||
|
||||
|
||||
memcpy(msg,(void*)&eh,MAC_HEADER_SIZE_BYTES);
|
||||
memcpy((msg+MAC_HEADER_SIZE_BYTES),(void*)device->openair0_cfg,sizeof(openair0_config_t));
|
||||
|
||||
if (send(eth->sockfd[Mod_id],
|
||||
msg,
|
||||
msg_len,
|
||||
0)==-1) {
|
||||
perror("ETHERNET: ");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int eth_get_dev_conf_raw(openair0_device *device) {
|
||||
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
int Mod_id = device->Mod_id;
|
||||
char str[INET_ADDRSTRLEN];
|
||||
void *msg;
|
||||
ssize_t msg_len;
|
||||
|
||||
msg = malloc(MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t));
|
||||
msg_len = MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t);
|
||||
|
||||
/* RRH receives from BBU openair0_config_t */
|
||||
if (recv(eth->sockfd[Mod_id],
|
||||
msg,
|
||||
msg_len,
|
||||
0)==-1) {
|
||||
perror("ETHERNET: ");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* RRH stores the remote MAC address */
|
||||
memcpy(eh.ether_dhost,(msg+ETH_ALEN),ETH_ALEN);
|
||||
//memcpy((void*)&device->openair0_cfg,(msg + MAC_HEADER_SIZE_BYTES), sizeof(openair0_config_t));
|
||||
device->openair0_cfg=(openair0_config_t *)(msg + MAC_HEADER_SIZE_BYTES);
|
||||
printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eh.ether_shost[0],eh.ether_shost[1],eh.ether_shost[2],eh.ether_shost[3],eh.ether_shost[4],eh.ether_shost[5],eh.ether_dhost[0],eh.ether_dhost[1],eh.ether_dhost[2],eh.ether_dhost[3],eh.ether_dhost[4],eh.ether_dhost[5]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,383 @@
|
||||
/*******************************************************************************
|
||||
OpenAirInterface
|
||||
Copyright(c) 1999 - 2014 Eurecom
|
||||
|
||||
OpenAirInterface is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
|
||||
OpenAirInterface is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenAirInterface.The full GNU General Public License is
|
||||
included in this distribution in the file called "COPYING". If not,
|
||||
see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Contact Information
|
||||
OpenAirInterface Admin: openair_admin@eurecom.fr
|
||||
OpenAirInterface Tech : openair_tech@eurecom.fr
|
||||
OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr
|
||||
|
||||
Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
|
||||
|
||||
*******************************************************************************/
|
||||
/*! \file ethernet_lib.c
|
||||
* \brief API to stream I/Q samples over standard ethernet
|
||||
* \author add alcatel Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp
|
||||
* \date 2015
|
||||
* \version 0.2
|
||||
* \company Eurecom
|
||||
* \maintainer: navid.nikaein@eurecom.fr
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/ether.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include "vcd_signal_dumper.h"
|
||||
|
||||
#include "common_lib.h"
|
||||
#include "ethernet_lib.h"
|
||||
|
||||
#define DEBUG 0
|
||||
struct sockaddr_in dest_addr[MAX_INST];
|
||||
struct sockaddr_in local_addr[MAX_INST];
|
||||
int addr_len[MAX_INST];
|
||||
|
||||
|
||||
uint16_t pck_seq_num = 1;
|
||||
uint16_t pck_seq_num_cur=0;
|
||||
uint16_t pck_seq_num_prev=0;
|
||||
|
||||
int eth_socket_init_udp(openair0_device *device) {
|
||||
|
||||
int i = 0;
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
int Mod_id = device->Mod_id;
|
||||
char str_local[INET_ADDRSTRLEN];
|
||||
char str_remote[INET_ADDRSTRLEN];
|
||||
const char *local_ip, *remote_ip;
|
||||
int local_port=0, remote_port=0;
|
||||
int sock_dom=0;
|
||||
int sock_type=0;
|
||||
int sock_proto=0;
|
||||
int enable=1;
|
||||
|
||||
if (device->host_type == RRH_HOST ) {
|
||||
local_ip = device->openair0_cfg->my_addr;
|
||||
local_port = device->openair0_cfg->my_port;
|
||||
remote_ip = "0.0.0.0";
|
||||
remote_port = 0;
|
||||
printf("[%s] local ip addr %s port %d\n", "RRH", local_ip, local_port);
|
||||
} else {
|
||||
local_ip = device->openair0_cfg->my_addr;
|
||||
local_port = device->openair0_cfg->my_port;
|
||||
remote_ip = device->openair0_cfg->remote_addr;
|
||||
remote_port = device->openair0_cfg->remote_port;
|
||||
printf("[%s] local ip addr %s port %d\n","BBU", local_ip, local_port);
|
||||
}
|
||||
|
||||
/* Open socket to send on */
|
||||
sock_dom=AF_INET;
|
||||
sock_type=SOCK_DGRAM;
|
||||
sock_proto=IPPROTO_UDP;
|
||||
|
||||
if ((eth->sockfd[Mod_id] = socket(sock_dom, sock_type, sock_proto)) == -1) {
|
||||
perror("ETHERNET: Error opening socket");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* initialize addresses */
|
||||
for (i=0; i< MAX_INST; i++) {
|
||||
bzero((void *)&(dest_addr[i]), sizeof(dest_addr[i]));
|
||||
bzero((void *)&(local_addr[i]), sizeof(local_addr[i]));
|
||||
}
|
||||
|
||||
addr_len[Mod_id] = sizeof(struct sockaddr_in);
|
||||
|
||||
dest_addr[Mod_id].sin_family = AF_INET;
|
||||
inet_pton(AF_INET,remote_ip,&(dest_addr[Mod_id].sin_addr.s_addr));
|
||||
dest_addr[Mod_id].sin_port=htons(remote_port);
|
||||
inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str_remote, INET_ADDRSTRLEN);
|
||||
|
||||
|
||||
local_addr[Mod_id].sin_family = AF_INET;
|
||||
inet_pton(AF_INET,local_ip,&(local_addr[Mod_id].sin_addr.s_addr));
|
||||
local_addr[Mod_id].sin_port=htons(local_port);
|
||||
inet_ntop(AF_INET, &(local_addr[Mod_id].sin_addr), str_local, INET_ADDRSTRLEN);
|
||||
|
||||
|
||||
/* set reuse address flag */
|
||||
if (setsockopt(eth->sockfd[Mod_id], SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int))) {
|
||||
perror("ETHERNET: Cannot set SO_REUSEADDR option on socket");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* want to receive -> so bind */
|
||||
if (bind(eth->sockfd[Mod_id],(struct sockaddr *)&local_addr[Mod_id],addr_len[Mod_id])<0) {
|
||||
perror("ETHERNET: Cannot bind to socket");
|
||||
exit(0);
|
||||
} else {
|
||||
printf("[%s] binding mod_%d to %s:%d\n","RRH",Mod_id,str_local,ntohs(local_addr[Mod_id].sin_port));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) {
|
||||
|
||||
int bytes_sent=0;
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
int Mod_id = device->Mod_id;
|
||||
int sendto_flag =0;
|
||||
int i=0;
|
||||
//sendto_flag|=flags;
|
||||
eth->tx_nsamps=nsamps;
|
||||
|
||||
for (i=0;i<cc;i++) {
|
||||
/* buff[i] points to the position in tx buffer where the payload to be sent is
|
||||
buff2 points to the position in tx buffer where the packet header will be placed */
|
||||
void *buff2 = (void*)(buff[i]- APP_HEADER_SIZE_BYTES);
|
||||
|
||||
/* we don't want to ovewrite with the header info the previous tx buffer data so we store it*/
|
||||
int32_t temp0 = *(int32_t *)buff2;
|
||||
openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
|
||||
|
||||
bytes_sent = 0;
|
||||
|
||||
/* constract application header */
|
||||
// eth->pck_header.seq_num = pck_seq_num;
|
||||
//eth->pck_header.antenna_id = 1+(i<<1);
|
||||
//eth->pck_header.timestamp = timestamp;
|
||||
*(uint16_t *)buff2 = pck_seq_num;
|
||||
*(uint16_t *)(buff2 + sizeof(uint16_t)) = 1+(i<<1);
|
||||
*(openair0_timestamp *)(buff2 + sizeof(int32_t)) = timestamp;
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_SEQ_NUM, pck_seq_num);
|
||||
|
||||
while(bytes_sent < UDP_PACKET_SIZE_BYTES(nsamps)) {
|
||||
#if DEBUG
|
||||
printf("------- TX ------: buff2 current position=%d remaining_bytes=%d bytes_sent=%d \n",
|
||||
(void *)(buff2+bytes_sent),
|
||||
UDP_PACKET_SIZE_BYTES(nsamps) - bytes_sent,
|
||||
bytes_sent);
|
||||
#endif
|
||||
/* Send packet */
|
||||
bytes_sent += sendto(eth->sockfd[Mod_id],
|
||||
buff2,
|
||||
UDP_PACKET_SIZE_BYTES(nsamps),
|
||||
sendto_flag,
|
||||
(struct sockaddr*)&dest_addr[Mod_id],
|
||||
addr_len[Mod_id]);
|
||||
|
||||
if ( bytes_sent == -1) {
|
||||
eth->num_tx_errors++;
|
||||
perror("ETHERNET WRITE: ");
|
||||
exit(-1);
|
||||
} else {
|
||||
#if DEBUG
|
||||
printf("------- TX ------: nu=%d an_id=%d ts%d bytes_send=%d\n",
|
||||
*(int16_t *)buff2,
|
||||
*(int16_t *)(buff2 + sizeof(int16_t)),
|
||||
*(openair0_timestamp *)(buff2 + sizeof(int32_t)),
|
||||
bytes_sent);
|
||||
dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, UDP_PACKET_SIZE_BYTES(nsamps), TX_FLAG);
|
||||
#endif
|
||||
eth->tx_actual_nsamps=bytes_sent>>2;
|
||||
eth->tx_count++;
|
||||
pck_seq_num++;
|
||||
if ( pck_seq_num > MAX_PACKET_SEQ_NUM(nsamps,76800) ) pck_seq_num = 1;
|
||||
}
|
||||
}
|
||||
/* tx buffer values restored */
|
||||
*(int32_t *)buff2 = temp0;
|
||||
*(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1;
|
||||
}
|
||||
|
||||
return (bytes_sent-APP_HEADER_SIZE_BYTES)>>2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) {
|
||||
|
||||
int bytes_received=0;
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
openair0_timestamp prev_timestamp = -1;
|
||||
int Mod_id = device->Mod_id;
|
||||
int rcvfrom_flag =0;
|
||||
int block_cnt=0;
|
||||
int again_cnt=0;
|
||||
int i=0;
|
||||
|
||||
eth->rx_nsamps=nsamps;
|
||||
|
||||
for (i=0;i<cc;i++) {
|
||||
/* buff[i] points to the position in rx buffer where the payload to be received will be placed
|
||||
buff2 points to the position in rx buffer where the packet header will be placed */
|
||||
void *buff2 = (void*)(buff[i]- APP_HEADER_SIZE_BYTES);
|
||||
|
||||
/* we don't want to ovewrite with the header info the previous rx buffer data so we store it*/
|
||||
int32_t temp0 = *(int32_t *)buff2;
|
||||
openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
|
||||
|
||||
bytes_received=0;
|
||||
block_cnt=0;
|
||||
|
||||
|
||||
while(bytes_received < UDP_PACKET_SIZE_BYTES(nsamps)) {
|
||||
again:
|
||||
#if DEBUG
|
||||
printf("------- RX------: buff2 current position=%d remaining_bytes=%d bytes_recv=%d \n",
|
||||
(void *)(buff2+bytes_received),
|
||||
UDP_PACKET_SIZE_BYTES(nsamps) - bytes_received,
|
||||
bytes_received);
|
||||
#endif
|
||||
bytes_received +=recvfrom(eth->sockfd[Mod_id],
|
||||
buff2,
|
||||
UDP_PACKET_SIZE_BYTES(nsamps),
|
||||
rcvfrom_flag,
|
||||
(struct sockaddr *)&dest_addr[Mod_id],
|
||||
(socklen_t *)&addr_len[Mod_id]);
|
||||
|
||||
if (bytes_received ==-1) {
|
||||
eth->num_rx_errors++;
|
||||
if (errno == EAGAIN) {
|
||||
again_cnt++;
|
||||
usleep(10);
|
||||
if (again_cnt == 1000) {
|
||||
perror("ETHERNET READ: ");
|
||||
exit(-1);
|
||||
} else {
|
||||
printf("AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN \n");
|
||||
goto again;
|
||||
}
|
||||
} else if (errno == EWOULDBLOCK) {
|
||||
block_cnt++;
|
||||
usleep(10);
|
||||
if (block_cnt == 1000) {
|
||||
perror("ETHERNET READ: ");
|
||||
exit(-1);
|
||||
} else {
|
||||
printf("BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK \n");
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#if DEBUG
|
||||
printf("------- RX------: nu=%d an_id=%d ts%d bytes_recv=%d\n",
|
||||
*(int16_t *)buff2,
|
||||
*(int16_t *)(buff2 + sizeof(int16_t)),
|
||||
*(openair0_timestamp *)(buff2 + sizeof(int32_t)),
|
||||
bytes_received);
|
||||
dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, UDP_PACKET_SIZE_BYTES(nsamps),RX_FLAG);
|
||||
#endif
|
||||
|
||||
/* store the timestamp value from packet's header */
|
||||
*timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
|
||||
/* store the sequence number of the previous packet received */
|
||||
if (pck_seq_num_cur == 0) {
|
||||
pck_seq_num_prev = *(uint16_t *)buff2;
|
||||
} else {
|
||||
pck_seq_num_prev = pck_seq_num_cur;
|
||||
}
|
||||
/* get the packet sequence number from packet's header */
|
||||
pck_seq_num_cur = *(uint16_t *)buff2;
|
||||
//printf("cur=%d prev=%d buff=%d\n",pck_seq_num_cur,pck_seq_num_prev,*(uint16_t *)(buff2));
|
||||
if ( ( pck_seq_num_cur != (pck_seq_num_prev + 1) ) && !((pck_seq_num_prev==75) && (pck_seq_num_cur==1 ))){
|
||||
printf("out of order packet received1! %d|%d|%d\n",pck_seq_num_cur,pck_seq_num_prev, *timestamp);
|
||||
}
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM,pck_seq_num_cur);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM_PRV,pck_seq_num_prev);
|
||||
eth->rx_actual_nsamps=bytes_received>>2;
|
||||
eth->rx_count++;
|
||||
}
|
||||
|
||||
}
|
||||
/* tx buffer values restored */
|
||||
*(int32_t *)buff2 = temp0;
|
||||
*(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1;
|
||||
|
||||
}
|
||||
return (bytes_received-APP_HEADER_SIZE_BYTES)>>2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int eth_set_dev_conf_udp(openair0_device *device) {
|
||||
|
||||
int Mod_id = device->Mod_id;
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
void *msg;
|
||||
ssize_t msg_len;
|
||||
|
||||
|
||||
/* a BBU client sents to RRH a set of configuration parameters (openair0_config_t)
|
||||
so that RF front end is configured appropriately and
|
||||
frame/packet size etc. can be set */
|
||||
|
||||
msg=malloc(sizeof(openair0_config_t));
|
||||
msg_len=sizeof(openair0_config_t);
|
||||
memcpy(msg,(void*)device->openair0_cfg,msg_len);
|
||||
|
||||
if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)&dest_addr[Mod_id],addr_len[Mod_id])==-1) {
|
||||
perror("ETHERNET: ");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int eth_get_dev_conf_udp(openair0_device *device) {
|
||||
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
int Mod_id = device->Mod_id;
|
||||
char str1[INET_ADDRSTRLEN],str[INET_ADDRSTRLEN];
|
||||
void *msg;
|
||||
ssize_t msg_len;
|
||||
|
||||
msg=malloc(sizeof(openair0_config_t));
|
||||
msg_len=sizeof(openair0_config_t);
|
||||
|
||||
inet_ntop(AF_INET, &(local_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN);
|
||||
inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str1, INET_ADDRSTRLEN);
|
||||
|
||||
/* RRH receives from BBU openair0_config_t */
|
||||
if (recvfrom(eth->sockfd[Mod_id],
|
||||
msg,
|
||||
msg_len,
|
||||
0,
|
||||
(struct sockaddr *)&dest_addr[Mod_id],
|
||||
(socklen_t *)&addr_len[Mod_id])==-1) {
|
||||
perror("ETHERNET: ");
|
||||
exit(0);
|
||||
}
|
||||
device->openair0_cfg=(openair0_config_t *)msg;
|
||||
|
||||
/* get remote ip address and port */
|
||||
/* inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str1, INET_ADDRSTRLEN); */
|
||||
/* device->openair0_cfg->remote_port =ntohs(dest_addr[Mod_id].sin_port); */
|
||||
/* device->openair0_cfg->remote_addr =str1; */
|
||||
|
||||
/* /\* restore local ip address and port *\/ */
|
||||
/* inet_ntop(AF_INET, &(local_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN); */
|
||||
/* device->openair0_cfg->my_port =ntohs(local_addr[Mod_id].sin_port); */
|
||||
/* device->openair0_cfg->my_addr =str; */
|
||||
|
||||
/* printf("[RRH] mod_%d socket %d connected to BBU %s:%d %s:%d\n", Mod_id, eth->sockfd[Mod_id],str1, device->openair0_cfg->remote_port, str, device->openair0_cfg->my_port); */
|
||||
return 0;
|
||||
}
|
||||
@@ -28,7 +28,7 @@
|
||||
*******************************************************************************/
|
||||
/*! \file ethernet_lib.c
|
||||
* \brief API to stream I/Q samples over standard ethernet
|
||||
* \author Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp
|
||||
* \author add alcatel Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp
|
||||
* \date 2015
|
||||
* \version 0.2
|
||||
* \company Eurecom
|
||||
@@ -52,196 +52,56 @@
|
||||
#include "common_lib.h"
|
||||
#include "ethernet_lib.h"
|
||||
|
||||
//#define DEBUG 1
|
||||
|
||||
int num_devices_eth = 0;
|
||||
struct sockaddr_in dest_addr[MAX_INST];
|
||||
int dest_addr_len[MAX_INST];
|
||||
char sendbuf[MAX_INST][BUF_SIZ]; /*TODO*/
|
||||
|
||||
|
||||
/*! \fn static int eth_socket_init(openair0_device *device)
|
||||
* \brief initialization of UDP Socket to communicate with one destination
|
||||
* \param[in] *device openair device for which the socket will be created
|
||||
* \param[out]
|
||||
* \return 0 on success, otherwise -1
|
||||
* \note
|
||||
* @ingroup _oai
|
||||
*/
|
||||
static int eth_socket_init(openair0_device *device);
|
||||
|
||||
/*! \fn static int eth_set_dev_conf(openair0_device *device)
|
||||
* \brief
|
||||
* \param[in] *device openair device
|
||||
* \param[out]
|
||||
* \return 0 on success, otherwise -1
|
||||
* \note
|
||||
* @ingroup _oai
|
||||
*/
|
||||
static int eth_set_dev_conf(openair0_device *device);
|
||||
|
||||
/*! \fn static int eth_get_dev_conf(openair0_device *device)
|
||||
* \brief
|
||||
* \param[in] *device openair device
|
||||
* \param[out]
|
||||
* \return 0 on success, otherwise -1
|
||||
* \note
|
||||
* @ingroup _oai
|
||||
*/
|
||||
static int eth_get_dev_conf(openair0_device *device);
|
||||
|
||||
|
||||
|
||||
int trx_eth_start(openair0_device *device) {
|
||||
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
|
||||
/* initialize socket */
|
||||
if (eth_socket_init(device)!=0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* RRH gets openair0 device configuration BBU sets openair0 device configuration*/
|
||||
if (device->func_type == BBU_FUNC) {
|
||||
return eth_set_dev_conf(device);
|
||||
if ((eth->flags & ETH_RAW_MODE) != 0 ) {
|
||||
if (eth_socket_init_raw(device)!=0) return -1;
|
||||
/* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/
|
||||
if (device->host_type == BBU_HOST) {
|
||||
if(eth_set_dev_conf_raw(device)!=0) return -1;
|
||||
} else {
|
||||
if(eth_get_dev_conf_raw(device)!=0) return -1;
|
||||
}
|
||||
/* adjust MTU wrt number of samples per packet */
|
||||
if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1;
|
||||
} else {
|
||||
return eth_get_dev_conf(device);
|
||||
if (eth_socket_init_udp(device)!=0) return -1;
|
||||
/* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/
|
||||
if (device->host_type == BBU_HOST) {
|
||||
if(eth_set_dev_conf_udp(device)!=0) return -1;
|
||||
} else {
|
||||
if(eth_get_dev_conf_udp(device)!=0) return -1;
|
||||
}
|
||||
/* adjust MTU wrt number of samples per packet */
|
||||
//if(ethernet_tune (device,MTU_SIZE,UDP_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1;
|
||||
}
|
||||
|
||||
/* apply additional configuration */
|
||||
if(ethernet_tune (device, SND_BUF_SIZE,2000000000)!=0) return -1;
|
||||
if(ethernet_tune (device, RCV_BUF_SIZE,2000000000)!=0) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int trx_eth_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) {
|
||||
|
||||
int n_written=0,i;
|
||||
uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp);
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
int Mod_id = device->Mod_id;
|
||||
int sendto_flag =0;
|
||||
sendto_flag|=MSG_DONTWAIT;
|
||||
|
||||
for (i=0;i<cc;i++) {
|
||||
/* buff[i] points to the position in tx buffer where the payload to be sent is
|
||||
buff2 points to the position in tx buffer where the packet header will be placed */
|
||||
void *buff2 = (void*)(buff[i]-header_size);
|
||||
|
||||
/* we don't want to ovewrite with the header info the previous tx buffer data so we store it*/
|
||||
int32_t temp0 = *(int32_t *)buff2;
|
||||
openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
|
||||
|
||||
n_written = 0;
|
||||
|
||||
*(int16_t *)(buff2 + sizeof(int16_t))=1+(i<<1);
|
||||
*(openair0_timestamp *)(buff2 + sizeof(int32_t)) = timestamp;
|
||||
|
||||
/* printf("[RRH]write mod_%d %d , len %d, buff %p antenna %d\n",
|
||||
Mod_id,eth->sockfd[Mod_id],(nsamps<<2)+header_size, buff2, antenna_id);*/
|
||||
|
||||
while(n_written < nsamps) {
|
||||
/* Send packet */
|
||||
if ((n_written += sendto(eth->sockfd[Mod_id],
|
||||
buff2,
|
||||
(nsamps<<2)+header_size,
|
||||
0,
|
||||
(struct sockaddr*)ð->dest_addr[Mod_id],
|
||||
dest_addr_len[Mod_id])) < 0) {
|
||||
perror("ETHERNET WRITE");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
printf("Buffer head TX: nu=%d an_id=%d ts%d samples_send=%d i=%d data=%x\n",
|
||||
*(int16_t *)buff2,
|
||||
*(int16_t *)(buff2 + sizeof(int16_t)),
|
||||
*(openair0_timestamp *)(buff2 + sizeof(int32_t)),
|
||||
n_written>>2,i,*(int32_t *)(buff2 + 20*sizeof(int32_t)));
|
||||
#endif
|
||||
|
||||
/* tx buffer values restored */
|
||||
*(int32_t *)buff2 = temp0;
|
||||
*(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1;
|
||||
}
|
||||
return n_written;
|
||||
|
||||
}
|
||||
|
||||
int trx_eth_read(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) {
|
||||
|
||||
int bytes_received=0;
|
||||
int block_cnt=0;
|
||||
int ret=0,i;
|
||||
uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp);
|
||||
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
int Mod_id = device->Mod_id;
|
||||
|
||||
for (i=0;i<cc;i++) {
|
||||
/* buff[i] points to the position in rx buffer where the payload to be received will be placed
|
||||
buff2 points to the position in rx buffer where the packet header will be placed */
|
||||
void *buff2 = (void*)(buff[i]-header_size);
|
||||
|
||||
/* we don't want to ovewrite with the header info the previous rx buffer data so we store it*/
|
||||
int32_t temp0 = *(int32_t *)buff2;
|
||||
openair0_timestamp temp1 = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
|
||||
|
||||
bytes_received=0;
|
||||
block_cnt=0;
|
||||
ret=0;
|
||||
|
||||
/* printf("[RRH] read mod_%d %d,len %d, buff %p antenna %d\n",
|
||||
Mod_id,eth->sockfd[Mod_id],(nsamps<<2)+header_size, buff2, antenna_id);*/
|
||||
|
||||
while(bytes_received < (int)((nsamps<<2))) {
|
||||
ret=recvfrom(eth->sockfd[Mod_id],
|
||||
buff2+bytes_received,
|
||||
(nsamps<<2)+header_size-bytes_received,
|
||||
0,//MSG_DONTWAIT,
|
||||
(struct sockaddr *)ð->dest_addr[Mod_id],
|
||||
(socklen_t *)&dest_addr_len[Mod_id]);
|
||||
|
||||
if (ret==-1) {
|
||||
if (errno == EAGAIN) {
|
||||
perror("ETHERNET READ: ");
|
||||
return((nsamps<<2) + header_size);
|
||||
} else if (errno == EWOULDBLOCK) {
|
||||
block_cnt++;
|
||||
usleep(10);
|
||||
|
||||
if (block_cnt == 100) return(-1);
|
||||
}
|
||||
} else {
|
||||
bytes_received+=ret;
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
printf("Buffer head RX: nu=%d an_id=%d ts%d samples_recv=%d i=%d data=%x\n",
|
||||
*(int16_t *)buff2,
|
||||
*(int16_t *)(buff2 + sizeof(int16_t)),
|
||||
*(openair0_timestamp *)(buff2 + sizeof(int32_t)),
|
||||
ret>>2,i,*(int32_t *)(buff2 + 20*sizeof(int32_t)));
|
||||
#endif
|
||||
|
||||
/* store the timestamp value from packet's header */
|
||||
*timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t));
|
||||
|
||||
/* tx buffer values restored */
|
||||
*(int32_t *)buff2 = temp0;
|
||||
*(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1;
|
||||
}
|
||||
return nsamps;
|
||||
|
||||
}
|
||||
|
||||
void trx_eth_end(openair0_device *device) {
|
||||
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
int Mod_id = device->Mod_id;
|
||||
/*destroys socket only for the processes that call the eth_end fuction-- shutdown() for beaking the pipe */
|
||||
/* destroys socket only for the processes that call the eth_end fuction-- shutdown() for beaking the pipe */
|
||||
if ( close(eth->sockfd[Mod_id]) <0 ) {
|
||||
perror("ETHERNET: Failed to close socket");
|
||||
exit(0);
|
||||
} else {
|
||||
printf("[RRH] socket for mod_id %d has been successfully closed.\n",Mod_id);
|
||||
printf("[%s] socket for mod_id %d has been successfully closed.\n",(device->host_type == BBU_HOST)? "BBU":"RRH",Mod_id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -253,7 +113,7 @@ int trx_eth_request(openair0_device *device, void *msg, ssize_t msg_len) {
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
|
||||
/* BBU sends a message to RRH */
|
||||
if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)ð->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1) {
|
||||
if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)&dest_addr[Mod_id],dest_addr_len[Mod_id])==-1) {
|
||||
perror("ETHERNET: ");
|
||||
exit(0);
|
||||
}
|
||||
@@ -262,7 +122,6 @@ int trx_eth_request(openair0_device *device, void *msg, ssize_t msg_len) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) {
|
||||
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
@@ -273,7 +132,7 @@ int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) {
|
||||
msg,
|
||||
msg_len,
|
||||
0,
|
||||
(struct sockaddr *)ð->dest_addr[Mod_id],
|
||||
(struct sockaddr *)&dest_addr[Mod_id],
|
||||
(socklen_t *)&dest_addr_len[Mod_id])==-1) {
|
||||
perror("ETHERNET: ");
|
||||
exit(0);
|
||||
@@ -283,65 +142,6 @@ int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) {
|
||||
}
|
||||
|
||||
|
||||
static int eth_set_dev_conf(openair0_device *device) {
|
||||
|
||||
int Mod_id = device->Mod_id;
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
void *msg;
|
||||
ssize_t msg_len;
|
||||
|
||||
|
||||
/* a BBU client sents to RRH a set of configuration parameters (openair0_config_t)
|
||||
so that RF front end is configured appropriately and
|
||||
frame/packet size etc. can be set */
|
||||
|
||||
msg=malloc(sizeof(openair0_config_t));
|
||||
msg_len=sizeof(openair0_config_t);
|
||||
memcpy(msg,(void*)&device->openair0_cfg,msg_len);
|
||||
|
||||
if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)ð->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1) {
|
||||
perror("ETHERNET: ");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int eth_get_dev_conf(openair0_device *device) {
|
||||
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
int Mod_id = device->Mod_id;
|
||||
char str[INET_ADDRSTRLEN];
|
||||
void *msg;
|
||||
ssize_t msg_len;
|
||||
|
||||
msg=malloc(sizeof(openair0_config_t));
|
||||
msg_len=sizeof(openair0_config_t);
|
||||
|
||||
/* RRH receives from BBU openair0_config_t */
|
||||
if (recvfrom(eth->sockfd[Mod_id],
|
||||
msg,
|
||||
msg_len,
|
||||
0,
|
||||
(struct sockaddr *)ð->dest_addr[Mod_id],
|
||||
(socklen_t *)&dest_addr_len[Mod_id])==-1) {
|
||||
perror("ETHERNET: ");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
memcpy((void*)&device->openair0_cfg,msg,msg_len);
|
||||
inet_ntop(AF_INET, &(eth->dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN);
|
||||
device->openair0_cfg.remote_port =ntohs(eth->dest_addr[Mod_id].sin_port);
|
||||
device->openair0_cfg.remote_ip=str;
|
||||
/*apply additional configuration*/
|
||||
//ethernet_tune (device, RING_PAR);
|
||||
// printf("[RRH] write mod_%d %d to %s:%d\n",Mod_id,eth->sockfd[Mod_id],str,ntohs(eth->dest_addr[Mod_id].sin_port));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int trx_eth_stop(int card) {
|
||||
return(0);
|
||||
@@ -364,186 +164,315 @@ int trx_eth_reset_stats(openair0_device* device) {
|
||||
}
|
||||
|
||||
|
||||
static int eth_socket_init(openair0_device *device) {
|
||||
|
||||
int i = 0;
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
int Mod_id = device->Mod_id;
|
||||
char str[INET_ADDRSTRLEN];
|
||||
const char *dest_ip;
|
||||
int dest_port=0;
|
||||
|
||||
if (device->func_type == RRH_FUNC ) {
|
||||
dest_ip = device->openair0_cfg.my_ip;
|
||||
dest_port = device->openair0_cfg.my_port;
|
||||
printf("[RRH] ip addr %s port %d\n",dest_ip, dest_port);
|
||||
} else {
|
||||
dest_ip = device->openair0_cfg.remote_ip;
|
||||
dest_port = device->openair0_cfg.remote_port;
|
||||
printf("[BBU] ip addr %s port %d\n",dest_ip, dest_port);
|
||||
}
|
||||
|
||||
/* Open RAW socket to send on */
|
||||
if ((eth->sockfd[Mod_id] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
|
||||
perror("ETHERNET: Error opening socket");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* initialize destination address */
|
||||
for (i=0; i< MAX_INST; i++) {
|
||||
bzero((void *)&(eth->dest_addr[i]), sizeof(eth->dest_addr[i]));
|
||||
}
|
||||
|
||||
// bzero((void *)dest,sizeof(struct sockaddr_in));
|
||||
eth->dest_addr[Mod_id].sin_family = AF_INET;
|
||||
inet_pton(AF_INET,dest_ip,&(eth->dest_addr[Mod_id].sin_addr.s_addr));
|
||||
eth->dest_addr[Mod_id].sin_port=htons(dest_port);
|
||||
dest_addr_len[Mod_id] = sizeof(struct sockaddr_in);
|
||||
inet_ntop(AF_INET, &(eth->dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN);
|
||||
|
||||
/* if RRH, then I am the server, so bind */
|
||||
if (device->func_type == RRH_FUNC ) {
|
||||
if (bind(eth->sockfd[Mod_id],(struct sockaddr *)ð->dest_addr[Mod_id], dest_addr_len[Mod_id])<0) {
|
||||
perror("ETHERNET: Cannot bind to socket");
|
||||
exit(0);
|
||||
} else {
|
||||
printf("[RRH] binding mod_%d to %s:%d\n",Mod_id,str,ntohs(eth->dest_addr[Mod_id].sin_port));
|
||||
}
|
||||
|
||||
} else {
|
||||
printf("[BBU] Connecting to %s:%d\n",str,ntohs(eth->dest_addr[Mod_id].sin_port));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ethernet_tune(openair0_device *device , eth_opt_t option) {
|
||||
int ethernet_tune(openair0_device *device, unsigned int option, int value) {
|
||||
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
int Mod_id=device->Mod_id;
|
||||
|
||||
unsigned int sndbuf_size=0, rcvbuf_size=0;
|
||||
struct timeval snd_timeout, rcv_timeout;
|
||||
struct timeval timeout;
|
||||
struct ifreq ifr;
|
||||
char system_cmd[256];
|
||||
char* if_name=DEFAULT_IF;
|
||||
|
||||
/****************** socket level options ************************/
|
||||
if (option== SND_BUF_SIZE) { /* transmit socket buffer size */
|
||||
struct in_addr ia;
|
||||
struct if_nameindex *ids;
|
||||
int ret=0;
|
||||
int i=0;
|
||||
|
||||
/****************** socket level options ************************/
|
||||
switch(option) {
|
||||
case SND_BUF_SIZE: /* transmit socket buffer size */
|
||||
if (setsockopt(eth->sockfd[Mod_id],
|
||||
SOL_SOCKET,
|
||||
SO_SNDBUF,
|
||||
&sndbuf_size,sizeof(sndbuf_size))) {
|
||||
&value,sizeof(value))) {
|
||||
perror("[ETHERNET] setsockopt()");
|
||||
} else {
|
||||
printf( "sndbuf_size= %d bytes\n", sndbuf_size);
|
||||
}
|
||||
} else if (option== RCV_BUF_SIZE) { /* receive socket buffer size */
|
||||
printf("send buffer size= %d bytes\n",value);
|
||||
}
|
||||
break;
|
||||
|
||||
case RCV_BUF_SIZE: /* receive socket buffer size */
|
||||
if (setsockopt(eth->sockfd[Mod_id],
|
||||
SOL_SOCKET,
|
||||
SO_RCVBUF,
|
||||
&rcvbuf_size,sizeof(rcvbuf_size))) {
|
||||
&value,sizeof(value))) {
|
||||
perror("[ETHERNET] setsockopt()");
|
||||
} else {
|
||||
printf( "rcvbuf_size= %d bytes\n", rcvbuf_size);
|
||||
printf("receive bufffer size= %d bytes\n",value);
|
||||
}
|
||||
} else if (option==RCV_TIMEOUT) {
|
||||
rcv_timeout.tv_sec = 0;
|
||||
rcv_timeout.tv_usec = 180;//less than rt_period
|
||||
break;
|
||||
|
||||
case RCV_TIMEOUT:
|
||||
timeout.tv_sec = value/1000000000;
|
||||
timeout.tv_usec = value%1000000000;//less than rt_period?
|
||||
if (setsockopt(eth->sockfd[Mod_id],
|
||||
SOL_SOCKET,
|
||||
SO_RCVTIMEO,
|
||||
(char *)&rcv_timeout,sizeof(rcv_timeout))) {
|
||||
(char *)&timeout,sizeof(timeout))) {
|
||||
perror("[ETHERNET] setsockopt()");
|
||||
} else {
|
||||
printf( "rcv_timeout= %d usecs\n", rcv_timeout.tv_usec);
|
||||
printf( "receive timeout= %d,%d sec\n",timeout.tv_sec,timeout.tv_usec);
|
||||
}
|
||||
} else if (option==SND_TIMEOUT) {
|
||||
snd_timeout.tv_sec = 0;
|
||||
snd_timeout.tv_usec = 180;//less than rt_period
|
||||
break;
|
||||
|
||||
case SND_TIMEOUT:
|
||||
timeout.tv_sec = value/1000000000;
|
||||
timeout.tv_usec = value%1000000000;//less than rt_period?
|
||||
if (setsockopt(eth->sockfd[Mod_id],
|
||||
SOL_SOCKET,
|
||||
SO_SNDTIMEO,
|
||||
(char *)&snd_timeout,sizeof(snd_timeout))) {
|
||||
(char *)&timeout,sizeof(timeout))) {
|
||||
perror("[ETHERNET] setsockopt()");
|
||||
} else {
|
||||
printf( "snd_timeout= %d usecs\n", snd_timeout.tv_usec);
|
||||
printf( "send timeout= %d,%d sec\n",timeout.tv_sec,timeout.tv_usec);
|
||||
}
|
||||
}
|
||||
|
||||
/******************* interface level options *************************/
|
||||
else if (option==MTU_SIZE) { /* change MTU of the eth interface */
|
||||
break;
|
||||
|
||||
|
||||
/******************* interface level options *************************/
|
||||
case MTU_SIZE: /* change MTU of the eth interface */
|
||||
ifr.ifr_addr.sa_family = AF_INET;
|
||||
strncpy(ifr.ifr_name,if_name, sizeof(ifr.ifr_name));
|
||||
ifr.ifr_mtu =8960;
|
||||
strncpy(ifr.ifr_name,eth->if_name[Mod_id], sizeof(ifr.ifr_name));
|
||||
ifr.ifr_mtu =value;
|
||||
if (ioctl(eth->sockfd[Mod_id],SIOCSIFMTU,(caddr_t)&ifr) < 0 )
|
||||
perror ("[ETHERNET] Can't set the MTU");
|
||||
else
|
||||
printf("[ETHERNET] %s MTU size has changed to %d\n",DEFAULT_IF,ifr.ifr_mtu);
|
||||
} else if (option==TX_Q_LEN) { /* change TX queue length of eth interface */
|
||||
printf("[ETHERNET] %s MTU size has changed to %d\n",eth->if_name[Mod_id],ifr.ifr_mtu);
|
||||
break;
|
||||
|
||||
case TX_Q_LEN: /* change TX queue length of eth interface */
|
||||
ifr.ifr_addr.sa_family = AF_INET;
|
||||
strncpy(ifr.ifr_name,if_name, sizeof(ifr.ifr_name));
|
||||
ifr.ifr_qlen =3000 ;
|
||||
strncpy(ifr.ifr_name,eth->if_name[Mod_id], sizeof(ifr.ifr_name));
|
||||
ifr.ifr_qlen =value;
|
||||
if (ioctl(eth->sockfd[Mod_id],SIOCSIFTXQLEN,(caddr_t)&ifr) < 0 )
|
||||
perror ("[ETHERNET] Can't set the txqueuelen");
|
||||
else
|
||||
printf("[ETHERNET] %s txqueuelen size has changed to %d\n",DEFAULT_IF,ifr.ifr_qlen);
|
||||
|
||||
|
||||
printf("[ETHERNET] %s txqueuelen size has changed to %d\n",eth->if_name[Mod_id],ifr.ifr_qlen);
|
||||
break;
|
||||
|
||||
/******************* device level options *************************/
|
||||
} else if (option==COALESCE_PAR) {
|
||||
if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -C %s rx-usecs 3",DEFAULT_IF) > 0) {
|
||||
system(system_cmd);
|
||||
case COALESCE_PAR:
|
||||
ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -C %s rx-usecs %d",eth->if_name[Mod_id],value);
|
||||
if (ret > 0) {
|
||||
ret=system(system_cmd);
|
||||
if (ret == -1) {
|
||||
fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno));
|
||||
} else {
|
||||
printf ("[ETHERNET] status of %s is %i\n",WEXITSTATUS(ret));
|
||||
}
|
||||
printf("[ETHERNET] Coalesce parameters %s\n",system_cmd);
|
||||
} else {
|
||||
perror("[ETHERNET] Can't set coalesce parameters\n");
|
||||
}
|
||||
break;
|
||||
|
||||
} else if (option==PAUSE_PAR ) {
|
||||
if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg off rx off tx off",DEFAULT_IF) > 0) {
|
||||
system(system_cmd);
|
||||
case PAUSE_PAR:
|
||||
if (value==1) ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg off rx off tx off",eth->if_name[Mod_id]);
|
||||
else if (value==0) ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg on rx on tx on",eth->if_name[Mod_id]);
|
||||
else break;
|
||||
if (ret > 0) {
|
||||
ret=system(system_cmd);
|
||||
if (ret == -1) {
|
||||
fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno));
|
||||
} else {
|
||||
printf ("[ETHERNET] status of %s is %i\n",WEXITSTATUS(ret));
|
||||
}
|
||||
printf("[ETHERNET] Pause parameters %s\n",system_cmd);
|
||||
} else {
|
||||
perror("[ETHERNET] Can't set pause parameters\n");
|
||||
}
|
||||
} else if (option==RING_PAR ) {
|
||||
if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -G %s rx 4096 tx 4096",DEFAULT_IF) > 0) {
|
||||
system(system_cmd);
|
||||
break;
|
||||
|
||||
case RING_PAR:
|
||||
ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -G %s rx %d tx %d",eth->if_name[Mod_id],value);
|
||||
if (ret > 0) {
|
||||
ret=system(system_cmd);
|
||||
if (ret == -1) {
|
||||
fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno));
|
||||
} else {
|
||||
printf ("[ETHERNET] status of %s is %i\n",WEXITSTATUS(ret));
|
||||
}
|
||||
printf("[ETHERNET] Ring parameters %s\n",system_cmd);
|
||||
} else {
|
||||
perror("[ETHERNET] Can't set ring parameters\n");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params ) {
|
||||
|
||||
eth_state_t *eth = (eth_state_t*)malloc(sizeof(eth_state_t));
|
||||
int card = 0;
|
||||
memset(eth, 0, sizeof(eth_state_t));
|
||||
eth->buffer_size = (unsigned int)openair0_cfg[card].samples_per_packet*sizeof(int32_t); // buffer size = 4096 for sample_len of 1024
|
||||
eth->sample_rate = (unsigned int)openair0_cfg[card].sample_rate;
|
||||
device->priv = eth;
|
||||
|
||||
printf("ETHERNET: Initializing openair0_device for %s ...\n", ((device->func_type == BBU_FUNC) ? "BBU": "RRH"));
|
||||
if (eth_params->transp_preference == 1) {
|
||||
eth->flags = ETH_RAW_MODE;
|
||||
} else {
|
||||
eth->flags = ETH_UDP_MODE;
|
||||
}
|
||||
|
||||
printf("[ETHERNET]: Initializing openair0_device for %s ...\n", ((device->host_type == BBU_HOST) ? "BBU": "RRH"));
|
||||
device->Mod_id = num_devices_eth++;
|
||||
device->transp_type = ETHERNET_TP;
|
||||
device->trx_start_func = trx_eth_start;
|
||||
device->trx_request_func = trx_eth_request;
|
||||
device->trx_reply_func = trx_eth_reply;
|
||||
device->trx_write_func = trx_eth_write;
|
||||
device->trx_read_func = trx_eth_read;
|
||||
device->trx_get_stats_func = trx_eth_get_stats;
|
||||
device->trx_reset_stats_func = trx_eth_reset_stats;
|
||||
device->trx_end_func = trx_eth_end;
|
||||
device->trx_stop_func = trx_eth_stop;
|
||||
device->trx_end_func = trx_eth_end;
|
||||
device->trx_stop_func = trx_eth_stop;
|
||||
device->trx_set_freq_func = trx_eth_set_freq;
|
||||
device->trx_set_gains_func = trx_eth_set_gains;
|
||||
|
||||
memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t));
|
||||
|
||||
if ((eth->flags & ETH_RAW_MODE) != 0 ) {
|
||||
device->trx_write_func = trx_eth_write_raw;
|
||||
device->trx_read_func = trx_eth_read_raw;
|
||||
} else {
|
||||
device->trx_write_func = trx_eth_write_udp;
|
||||
device->trx_read_func = trx_eth_read_udp;
|
||||
}
|
||||
|
||||
eth->if_name[device->Mod_id] = eth_params->local_if_name;
|
||||
device->priv = eth;
|
||||
|
||||
/* device specific */
|
||||
openair0_cfg[0].txlaunch_wait = 0;//manage when TX processing is triggered
|
||||
openair0_cfg[0].txlaunch_wait_slotcount = 0; //manage when TX processing is triggered
|
||||
openair0_cfg[0].iq_txshift = 5;// shift
|
||||
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
|
||||
|
||||
/* RRH does not have any information to make this configuration atm */
|
||||
if (device->host_type == BBU_HOST) {
|
||||
/*Note scheduling advance values valid only for case 7680000 */
|
||||
switch ((int)openair0_cfg[0].sample_rate) {
|
||||
case 30720000:
|
||||
openair0_cfg[0].samples_per_packet = 4096;
|
||||
openair0_cfg[0].tx_sample_advance = 0;
|
||||
openair0_cfg[0].tx_scheduling_advance = 22*openair0_cfg[0].samples_per_packet;
|
||||
break;
|
||||
case 23040000:
|
||||
openair0_cfg[0].samples_per_packet = 2048;
|
||||
openair0_cfg[0].tx_sample_advance = 0;
|
||||
openair0_cfg[0].tx_scheduling_advance = 16*openair0_cfg[0].samples_per_packet;
|
||||
break;
|
||||
case 15360000:
|
||||
openair0_cfg[0].samples_per_packet = 2048;
|
||||
openair0_cfg[0].tx_sample_advance = 0;
|
||||
openair0_cfg[0].tx_scheduling_advance = 10*openair0_cfg[0].samples_per_packet;
|
||||
break;
|
||||
case 7680000:
|
||||
openair0_cfg[0].samples_per_packet = 1024;
|
||||
openair0_cfg[0].tx_sample_advance = 0;
|
||||
openair0_cfg[0].tx_scheduling_advance = 10*openair0_cfg[0].samples_per_packet;
|
||||
break;
|
||||
case 1920000:
|
||||
openair0_cfg[0].samples_per_packet = 256;
|
||||
openair0_cfg[0].tx_sample_advance = 0;
|
||||
openair0_cfg[0].tx_scheduling_advance = 16*openair0_cfg[0].samples_per_packet;
|
||||
break;
|
||||
default:
|
||||
printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
|
||||
exit(-1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
device->openair0_cfg=&openair0_cfg[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************************************************************
|
||||
* DEBUGING-RELATED FUNCTIONS *
|
||||
**************************************************************************************************************************/
|
||||
void dump_packet(char *title, unsigned char* pkt, int bytes, unsigned int tx_rx_flag) {
|
||||
|
||||
static int numSend = 1;
|
||||
static int numRecv = 1;
|
||||
int num, k;
|
||||
char tmp[48];
|
||||
unsigned short int cksum;
|
||||
|
||||
num = (tx_rx_flag)? numSend++:numRecv++;
|
||||
for (k = 0; k < 24; k++) sprintf(tmp+k, "%02X", pkt[k]);
|
||||
cksum = calc_csum((unsigned short *)pkt, bytes>>2);
|
||||
printf("%s-%s (%06d): %s 0x%04X\n", title,(tx_rx_flag)? "TX":"RX", num, tmp, cksum);
|
||||
}
|
||||
|
||||
unsigned short calc_csum (unsigned short *buf, int nwords) {
|
||||
|
||||
unsigned long sum;
|
||||
for (sum = 0; nwords > 0; nwords--)
|
||||
sum += *buf++;
|
||||
sum = (sum >> 16) + (sum & 0xffff);
|
||||
sum += (sum >> 16);
|
||||
return ~sum;
|
||||
}
|
||||
|
||||
void dump_dev(openair0_device *device) {
|
||||
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
|
||||
printf("Ethernet device interface %i configuration:\n" ,device->openair0_cfg->Mod_id);
|
||||
printf(" Log level is %i :\n" ,device->openair0_cfg->log_level);
|
||||
printf(" RB number: %i, sample rate: %lf \n" ,
|
||||
device->openair0_cfg->num_rb_dl, device->openair0_cfg->sample_rate);
|
||||
printf(" Scheduling_advance: %i, Sample_advance: %u \n" ,
|
||||
device->openair0_cfg->tx_scheduling_advance, device->openair0_cfg->tx_sample_advance);
|
||||
printf(" BBU configured for %i tx/%i rx channels)\n",
|
||||
device->openair0_cfg->tx_num_channels,device->openair0_cfg->rx_num_channels);
|
||||
printf(" Running flags: %s %s %s\n",
|
||||
((eth->flags & ETH_RAW_MODE) ? "RAW socket mode - ":""),
|
||||
((eth->flags & ETH_UDP_MODE) ? "UDP socket mode - ":""));
|
||||
printf(" Number of iqs dumped when displaying packets: %i\n\n",eth->iqdumpcnt);
|
||||
|
||||
}
|
||||
|
||||
void inline dump_txcounters(openair0_device *device) {
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
printf(" Ethernet device interface %i, tx counters:\n" ,device->openair0_cfg->Mod_id);
|
||||
printf(" Sent packets: %llu send errors: %i\n", eth->tx_count, eth->num_tx_errors);
|
||||
}
|
||||
|
||||
void inline dump_rxcounters(openair0_device *device) {
|
||||
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
printf(" Ethernet device interface %i rx counters:\n" ,device->openair0_cfg->Mod_id);
|
||||
printf(" Received packets: %llu missed packets errors: %i\n", eth->rx_count, eth->num_underflows);
|
||||
}
|
||||
|
||||
void inline dump_buff(openair0_device *device, char *buff,unsigned int tx_rx_flag, int nsamps) {
|
||||
|
||||
char *strptr;
|
||||
eth_state_t *eth = (eth_state_t*)device->priv;
|
||||
/*need to add ts number of iqs in printf need to fix dump iqs call */
|
||||
strptr = (( tx_rx_flag == TX_FLAG) ? "TX" : "RX");
|
||||
printf("\n %s, nsamps=%i \n" ,strptr,nsamps);
|
||||
|
||||
if (tx_rx_flag == 1) {
|
||||
dump_txcounters(device);
|
||||
printf(" First %i iqs of TX buffer\n",eth->iqdumpcnt);
|
||||
dump_iqs(buff,eth->iqdumpcnt);
|
||||
} else {
|
||||
dump_rxcounters(device);
|
||||
printf(" First %i iqs of RX buffer\n",eth->iqdumpcnt);
|
||||
dump_iqs(buff,eth->iqdumpcnt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void dump_iqs(char * buff, int iq_cnt) {
|
||||
int i;
|
||||
for (i=0;i<iq_cnt;i++) {
|
||||
printf("s%02i: Q=%+ij I=%+i%s",i,
|
||||
((iqoai_t *)(buff))[i].q,
|
||||
((iqoai_t *)(buff))[i].i,
|
||||
((i+1)%3 == 0) ? "\n" : " ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
* \note
|
||||
* \warning
|
||||
*/
|
||||
#ifndef ETHERNET_LIB_H
|
||||
#define ETHERNET_LIB_H
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <linux/if_packet.h>
|
||||
@@ -47,71 +49,90 @@
|
||||
#include <net/if.h>
|
||||
#include <netinet/ether.h>
|
||||
|
||||
#define MAX_INST 4
|
||||
#define DEFAULT_IF "lo"
|
||||
#define BUF_SIZ 8960 /*Jumbo frame size*/
|
||||
#define MAX_INST 4
|
||||
#define DEFAULT_IF "lo"
|
||||
|
||||
#define ETH_RAW_MODE 1
|
||||
#define ETH_UDP_MODE 0
|
||||
|
||||
#define TX_FLAG 1
|
||||
#define RX_FLAG 0
|
||||
|
||||
#define MAX_PACKET_SEQ_NUM(spp,spf) (spf/spp)
|
||||
#define MAC_HEADER_SIZE_BYTES (sizeof(struct ether_header))
|
||||
#define APP_HEADER_SIZE_BYTES (sizeof(int32_t) + sizeof(openair0_timestamp))
|
||||
#define PAYLOAD_SIZE_BYTES(nsamps) (nsamps<<2)
|
||||
#define UDP_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps))
|
||||
#define RAW_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps))
|
||||
|
||||
|
||||
/*!\brief opaque ethernet data structure */
|
||||
typedef struct {
|
||||
|
||||
// opaque eth data struct
|
||||
//struct eth_if *dev;
|
||||
// An empty ("") or NULL device identifier will result in the first encountered device being opened (using the first discovered backend)
|
||||
|
||||
|
||||
/*!\brief socket file desc */
|
||||
int sockfd[MAX_INST];
|
||||
struct sockaddr_in dest_addr[MAX_INST];
|
||||
|
||||
/*!\brief interface name */
|
||||
char *if_name[MAX_INST];
|
||||
/*!\brief buffer size */
|
||||
unsigned int buffer_size;
|
||||
unsigned int timeout_ns;
|
||||
|
||||
//struct eth_metadata meta_rx;
|
||||
//struct eth_metadata meta_tx;
|
||||
|
||||
unsigned int sample_rate;
|
||||
// time offset between transmiter timestamp and receiver timestamp;
|
||||
/*!\brief timeout ms */
|
||||
unsigned int rx_timeout_ms;
|
||||
/*!\brief timeout ms */
|
||||
unsigned int tx_timeout_ms;
|
||||
/*!\brief runtime flags */
|
||||
uint32_t flags;
|
||||
/*!\ time offset between transmiter timestamp and receiver timestamp */
|
||||
double tdiff;
|
||||
// use brf_time_offset to get this value
|
||||
int tx_forward_nsamps; //166 for 20Mhz
|
||||
|
||||
|
||||
/*!\ calibration */
|
||||
int tx_forward_nsamps;
|
||||
|
||||
// --------------------------------
|
||||
// Debug and output control
|
||||
// --------------------------------
|
||||
int num_underflows;
|
||||
int num_overflows;
|
||||
int num_seq_errors;
|
||||
int num_rx_errors;
|
||||
int num_tx_errors;
|
||||
|
||||
/*!\brief number of I/Q samples to be printed */
|
||||
int iqdumpcnt;
|
||||
|
||||
uint64_t tx_actual_nsamps; // actual number of samples transmitted
|
||||
/*!\brief number of underflows in interface */
|
||||
int num_underflows;
|
||||
/*!\brief number of overflows in interface */
|
||||
int num_overflows;
|
||||
/*!\brief number of concesutive errors in interface */
|
||||
int num_seq_errors;
|
||||
/*!\brief number of errors in interface's receiver */
|
||||
int num_rx_errors;
|
||||
/*!\brief umber of errors in interface's transmitter */
|
||||
int num_tx_errors;
|
||||
|
||||
/*!\brief current TX timestamp */
|
||||
openair0_timestamp tx_current_ts;
|
||||
/*!\brief socket file desc */
|
||||
openair0_timestamp rx_current_ts;
|
||||
/*!\brief actual number of samples transmitted */
|
||||
uint64_t tx_actual_nsamps;
|
||||
/*!\brief actual number of samples received */
|
||||
uint64_t rx_actual_nsamps;
|
||||
uint64_t tx_nsamps; // number of planned samples
|
||||
/*!\brief number of samples to be transmitted */
|
||||
uint64_t tx_nsamps;
|
||||
/*!\brief number of samples to be received */
|
||||
uint64_t rx_nsamps;
|
||||
uint64_t tx_count; // number pf packets
|
||||
/*!\brief number of packets transmitted */
|
||||
uint64_t tx_count;
|
||||
/*!\brief number of packets received */
|
||||
uint64_t rx_count;
|
||||
//openair0_timestamp rx_timestamp;
|
||||
|
||||
} eth_state_t;
|
||||
|
||||
#define ETH_META_STATUS_OVERRUN (1 << 0)
|
||||
#define ETH_META_STATUS_UNDERRUN (1 << 1)
|
||||
|
||||
struct eth_meta_data{
|
||||
uint64_t timestamp;
|
||||
uint32_t flags;
|
||||
uint32_t status;
|
||||
unsigned int actual_count;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*!\brief packet header */
|
||||
typedef struct {
|
||||
/*!\brief packet sequence number max value=packets per frame*/
|
||||
uint16_t seq_num ;
|
||||
/*!\brief antenna port used to resynchronize */
|
||||
uint16_t antenna_id;
|
||||
/*!\brief packet's timestamp */
|
||||
openair0_timestamp timestamp;
|
||||
/*!\brief variable declared for alignment purposes (sample size=32 bit) */
|
||||
int16_t not_used;
|
||||
/*!\brief antenna port used to resynchronize */
|
||||
int16_t antenna_id;
|
||||
} header_t;
|
||||
|
||||
/*!\brief different options for ethernet tuning in socket and driver level */
|
||||
@@ -138,9 +159,37 @@ typedef enum {
|
||||
MAX_OPT
|
||||
} eth_opt_t;
|
||||
|
||||
/*
|
||||
#define SND_BUF_SIZE 1
|
||||
#define RCV_BUF_SIZE 1<<1
|
||||
#define SND_TIMEOUT 1<<2
|
||||
#define RCV_TIMEOUT 1<<3
|
||||
#define MTU_SIZE 1<<4
|
||||
#define TX_Q_LEN 1<<5
|
||||
#define RING_PAR 1<<5
|
||||
#define COALESCE_PAR 1<<6
|
||||
#define PAUSE_PAR 1<<7
|
||||
*/
|
||||
|
||||
/*!\brief I/Q samples */
|
||||
typedef struct {
|
||||
/*!\brief phase */
|
||||
short i;
|
||||
/*!\brief quadrature */
|
||||
short q;
|
||||
} iqoai_t ;
|
||||
|
||||
void dump_packet(char *title, unsigned char* pkt, int bytes, unsigned int tx_rx_flag);
|
||||
unsigned short calc_csum (unsigned short *buf, int nwords);
|
||||
void dump_dev(openair0_device *device);
|
||||
void inline dump_buff(openair0_device *device, char *buff,unsigned int tx_rx_flag,int nsamps);
|
||||
void inline dump_rxcounters(openair0_device *device);
|
||||
void inline dump_txcounters(openair0_device *device);
|
||||
void dump_iqs(char * buff, int iq_cnt);
|
||||
|
||||
|
||||
/*! \fn int ethernet_tune (openair0_device *device, eth_opt_t option)
|
||||
|
||||
/*! \fn int ethernet_tune (openair0_device *device, unsigned int option, int value);
|
||||
* \brief this function allows you to configure certain ethernet parameters in socket or device level
|
||||
* \param[in] openair0 device which bears the socket
|
||||
* \param[in] name of parameter to configure
|
||||
@@ -148,6 +197,37 @@ typedef enum {
|
||||
* \note
|
||||
* @ingroup _oai
|
||||
*/
|
||||
int ethernet_tune (openair0_device *device, eth_opt_t option);
|
||||
int ethernet_write_data(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc) ;
|
||||
int ethernet_read_data(openair0_device *device,openair0_timestamp *timestamp,void **buff, int nsamps,int cc);
|
||||
int ethernet_tune(openair0_device *device, unsigned int option, int value);
|
||||
|
||||
|
||||
|
||||
/*! \fn int eth_socket_init_udp(openair0_device *device)
|
||||
* \brief initialization of UDP Socket to communicate with one destination
|
||||
* \param[in] *device openair device for which the socket will be created
|
||||
* \param[out]
|
||||
* \return 0 on success, otherwise -1
|
||||
* \note
|
||||
* @ingroup _oai
|
||||
*/
|
||||
int eth_socket_init_udp(openair0_device *device);
|
||||
int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags);
|
||||
int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc);
|
||||
int eth_get_dev_conf_udp(openair0_device *device);
|
||||
|
||||
/*! \fn static int eth_set_dev_conf_udp(openair0_device *device)
|
||||
* \brief
|
||||
* \param[in] *device openair device
|
||||
* \param[out]
|
||||
* \return 0 on success, otherwise -1
|
||||
* \note
|
||||
* @ingroup _oai
|
||||
*/
|
||||
int eth_set_dev_conf_udp(openair0_device *device);
|
||||
int eth_socket_init_raw(openair0_device *device);
|
||||
int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags);
|
||||
int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc);
|
||||
int eth_get_dev_conf_raw(openair0_device *device);
|
||||
int eth_set_dev_conf_raw(openair0_device *device);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -247,7 +247,7 @@ int openair0_stop_without_reset(int card)
|
||||
#define MY_RF_MODE (RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + DMAMODE_RX + DMAMODE_TX)
|
||||
#define RF_MODE_BASE (LNA1ON + RFBBNORM)
|
||||
|
||||
int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
|
||||
// Initialize card
|
||||
// exmimo_config_t *p_exmimo_config;
|
||||
@@ -287,6 +287,8 @@ int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair
|
||||
return(-1);
|
||||
}
|
||||
|
||||
device->type = EXMIMO_DEV;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -323,6 +325,12 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag)
|
||||
else
|
||||
p_exmimo_config->framing.multicard_syncmode=SYNCMODE_SLAVE;
|
||||
|
||||
/* device specific */
|
||||
openair0_cfg[card].txlaunch_wait = 1;//manage when TX processing is triggered
|
||||
openair0_cfg[card].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered
|
||||
openair0_cfg[card].iq_txshift = 4;//shift
|
||||
openair0_cfg[card].iq_rxrescale = 15;//rescale iqs
|
||||
|
||||
if (openair0_cfg[card].sample_rate==30.72e6) {
|
||||
resampling_factor = 0;
|
||||
rx_filter = RXLPF10;
|
||||
|
||||
@@ -812,11 +812,15 @@ void trx_lms_end(openair0_device *device) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
int openair0_dev_init_lms(openair0_device *device, openair0_config_t *openair0_cfg){
|
||||
extern "C" {
|
||||
/*! \brief Initialize Openair LMSSDR target. It returns 0 if OK
|
||||
* \param device the hardware to use
|
||||
* \param openair0_cfg RF frontend parameters set by application
|
||||
*/
|
||||
int device_init(openair0_device *device, openair0_config_t *openair0_cfg){
|
||||
|
||||
|
||||
printf("LMSSDR: Initializing openair0_device for %s ...\n", ((device->func_type == BBU_FUNC) ? "BBU": "RRH"));
|
||||
printf("LMSSDR: Initializing openair0_device for %s ...\n", ((device->host_type == BBU_HOST) ? "BBU": "RRH"));
|
||||
|
||||
switch ((int)openair0_cfg[0].sample_rate) {
|
||||
case 30720000:
|
||||
@@ -872,3 +876,4 @@ int openair0_dev_init_lms(openair0_device *device, openair0_config_t *openair0_c
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
/** usrp_lib.cpp
|
||||
*
|
||||
* Author: HongliangXU : hong-liang-xu@agilent.com
|
||||
* \author: HongliangXU : hong-liang-xu@agilent.com
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -55,47 +55,71 @@
|
||||
# include <immintrin.h>
|
||||
#endif
|
||||
|
||||
/** @addtogroup _USRP_PHY_RF_INTERFACE_
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*! \brief USRP Configuration */
|
||||
typedef struct
|
||||
{
|
||||
|
||||
// --------------------------------
|
||||
// variables for USRP configuration
|
||||
// --------------------------------
|
||||
//! USRP device pointer
|
||||
uhd::usrp::multi_usrp::sptr usrp;
|
||||
//uhd::usrp::multi_usrp::sptr rx_usrp;
|
||||
|
||||
//create a send streamer and a receive streamer
|
||||
//! USRP TX Stream
|
||||
uhd::tx_streamer::sptr tx_stream;
|
||||
//! USRP RX Stream
|
||||
uhd::rx_streamer::sptr rx_stream;
|
||||
|
||||
//! USRP TX Metadata
|
||||
uhd::tx_metadata_t tx_md;
|
||||
//! USRP RX Metadata
|
||||
uhd::rx_metadata_t rx_md;
|
||||
|
||||
//! USRP Timestamp Information
|
||||
uhd::time_spec_t tm_spec;
|
||||
|
||||
//setup variables and allocate buffer
|
||||
//! USRP Metadata
|
||||
uhd::async_metadata_t async_md;
|
||||
|
||||
//! Sampling rate
|
||||
double sample_rate;
|
||||
// time offset between transmiter timestamp and receiver timestamp;
|
||||
|
||||
//! time offset between transmiter timestamp and receiver timestamp;
|
||||
double tdiff;
|
||||
// use usrp_time_offset to get this value
|
||||
|
||||
//! TX forward samples. We use usrp_time_offset to get this value
|
||||
int tx_forward_nsamps; //166 for 20Mhz
|
||||
|
||||
|
||||
// --------------------------------
|
||||
// Debug and output control
|
||||
// --------------------------------
|
||||
//! Number of underflows
|
||||
int num_underflows;
|
||||
//! Number of overflows
|
||||
int num_overflows;
|
||||
|
||||
//! Number of sequential errors
|
||||
int num_seq_errors;
|
||||
|
||||
//! tx count
|
||||
int64_t tx_count;
|
||||
//! rx count
|
||||
int64_t rx_count;
|
||||
//! timestamp of RX packet
|
||||
openair0_timestamp rx_timestamp;
|
||||
|
||||
} usrp_state_t;
|
||||
|
||||
|
||||
/*! \brief Called to start the USRP transceiver. Return 0 if OK, < 0 if error
|
||||
@param device pointer to the device structure specific to the RF hardware target
|
||||
*/
|
||||
static int trx_usrp_start(openair0_device *device)
|
||||
{
|
||||
usrp_state_t *s = (usrp_state_t*)device->priv;
|
||||
@@ -118,7 +142,9 @@ static int trx_usrp_start(openair0_device *device)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief Terminate operation of the USRP transceiver -- free all associated resources
|
||||
* \param device the hardware to use
|
||||
*/
|
||||
static void trx_usrp_end(openair0_device *device)
|
||||
{
|
||||
usrp_state_t *s = (usrp_state_t*)device->priv;
|
||||
@@ -132,6 +158,14 @@ static void trx_usrp_end(openair0_device *device)
|
||||
|
||||
}
|
||||
|
||||
/*! \brief Called to send samples to the USRP RF target
|
||||
@param device pointer to the device structure specific to the RF hardware target
|
||||
@param timestamp The timestamp at whicch the first sample MUST be sent
|
||||
@param buff Buffer which holds the samples
|
||||
@param nsamps number of samples to be sent
|
||||
@param antenna_id index of the antenna if the device has multiple anteannas
|
||||
@param flags flags must be set to TRUE if timestamp parameter needs to be applied
|
||||
*/
|
||||
static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags)
|
||||
{
|
||||
usrp_state_t *s = (usrp_state_t*)device->priv;
|
||||
@@ -153,6 +187,17 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief Receive samples from hardware.
|
||||
* Read \ref nsamps samples from each channel to buffers. buff[0] is the array for
|
||||
* the first channel. *ptimestamp is the time at which the first sample
|
||||
* was received.
|
||||
* \param device the hardware to use
|
||||
* \param[out] ptimestamp the time at which the first sample was received.
|
||||
* \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps.
|
||||
* \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte.
|
||||
* \param antenna_id Index of antenna for which to receive samples
|
||||
* \returns the number of sample read
|
||||
*/
|
||||
static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc)
|
||||
{
|
||||
usrp_state_t *s = (usrp_state_t*)device->priv;
|
||||
@@ -172,7 +217,7 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
|
||||
#endif
|
||||
|
||||
|
||||
if (device->type == USRP_B200_IF) {
|
||||
if (device->type == USRP_B200_DEV) {
|
||||
if (cc>1) {
|
||||
// receive multiple channels (e.g. RF A and RF B)
|
||||
std::vector<void *> buff_ptrs;
|
||||
@@ -198,7 +243,7 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} else if (device->type == USRP_X300_IF) {
|
||||
} else if (device->type == USRP_X300_DEV) {
|
||||
if (cc>1) {
|
||||
// receive multiple channels (e.g. RF A and RF B)
|
||||
std::vector<void *> buff_ptrs;
|
||||
@@ -238,6 +283,9 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
|
||||
return samples_received;
|
||||
}
|
||||
|
||||
/*! \brief Get current timestamp of USRP
|
||||
* \param device the hardware to use
|
||||
*/
|
||||
openair0_timestamp get_usrp_time(openair0_device *device)
|
||||
{
|
||||
|
||||
@@ -246,11 +294,21 @@ openair0_timestamp get_usrp_time(openair0_device *device)
|
||||
return s->usrp->get_time_now().to_ticks(s->sample_rate);
|
||||
}
|
||||
|
||||
/*! \brief Compares two variables within precision
|
||||
* \param a first variable
|
||||
* \param b second variable
|
||||
*/
|
||||
static bool is_equal(double a, double b)
|
||||
{
|
||||
return std::fabs(a-b) < std::numeric_limits<double>::epsilon();
|
||||
}
|
||||
|
||||
/*! \brief Set frequencies (TX/RX)
|
||||
* \param device the hardware to use
|
||||
* \param openair0_cfg RF frontend parameters set by application
|
||||
* \param dummy dummy variable not used
|
||||
* \returns 0 in success
|
||||
*/
|
||||
int trx_usrp_set_freq(openair0_device* device, openair0_config_t *openair0_cfg, int dummy) {
|
||||
|
||||
usrp_state_t *s = (usrp_state_t*)device->priv;
|
||||
@@ -262,6 +320,11 @@ int trx_usrp_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,
|
||||
|
||||
}
|
||||
|
||||
/*! \brief Set RX frequencies
|
||||
* \param device the hardware to use
|
||||
* \param openair0_cfg RF frontend parameters set by application
|
||||
* \returns 0 in success
|
||||
*/
|
||||
int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg) {
|
||||
|
||||
usrp_state_t *s = (usrp_state_t*)device->priv;
|
||||
@@ -279,6 +342,11 @@ int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *open
|
||||
|
||||
}
|
||||
|
||||
/*! \brief Set Gains (TX/RX)
|
||||
* \param device the hardware to use
|
||||
* \param openair0_cfg RF frontend parameters set by application
|
||||
* \returns 0 in success
|
||||
*/
|
||||
int trx_usrp_set_gains(openair0_device* device,
|
||||
openair0_config_t *openair0_cfg) {
|
||||
|
||||
@@ -299,11 +367,14 @@ int trx_usrp_set_gains(openair0_device* device,
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*! \brief Stop USRP
|
||||
* \param card refers to the hardware index to use
|
||||
*/
|
||||
int trx_usrp_stop(int card) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief USRPB210 RX calibration table */
|
||||
rx_gain_calib_table_t calib_table_b210[] = {
|
||||
{3500000000.0,44.0},
|
||||
{2660000000.0,49.0},
|
||||
@@ -312,6 +383,7 @@ rx_gain_calib_table_t calib_table_b210[] = {
|
||||
{816000000.0,58.0},
|
||||
{-1,0}};
|
||||
|
||||
/*! \brief USRPB210 RX calibration table */
|
||||
rx_gain_calib_table_t calib_table_b210_38[] = {
|
||||
{3500000000.0,44.0},
|
||||
{2660000000.0,49.8},
|
||||
@@ -320,6 +392,7 @@ rx_gain_calib_table_t calib_table_b210_38[] = {
|
||||
{816000000.0,57.0},
|
||||
{-1,0}};
|
||||
|
||||
/*! \brief USRPx310 RX calibration table */
|
||||
rx_gain_calib_table_t calib_table_x310[] = {
|
||||
{3500000000.0,77.0},
|
||||
{2660000000.0,81.0},
|
||||
@@ -328,6 +401,11 @@ rx_gain_calib_table_t calib_table_x310[] = {
|
||||
{816000000.0,85.0},
|
||||
{-1,0}};
|
||||
|
||||
/*! \brief Set RX gain offset
|
||||
* \param openair0_cfg RF frontend parameters set by application
|
||||
* \param chain_index RF chain to apply settings to
|
||||
* \returns 0 in success
|
||||
*/
|
||||
void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index,int bw_gain_adjust) {
|
||||
|
||||
int i=0;
|
||||
@@ -373,12 +451,20 @@ void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index,int bw_
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*! \brief print the USRP statistics
|
||||
* \param device the hardware to use
|
||||
* \returns 0 on success
|
||||
*/
|
||||
int trx_usrp_get_stats(openair0_device* device) {
|
||||
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
/*! \brief Reset the USRP statistics
|
||||
* \param device the hardware to use
|
||||
* \returns 0 on success
|
||||
*/
|
||||
int trx_usrp_reset_stats(openair0_device* device) {
|
||||
|
||||
return(0);
|
||||
@@ -386,13 +472,20 @@ int trx_usrp_reset_stats(openair0_device* device) {
|
||||
}
|
||||
|
||||
|
||||
int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg)
|
||||
{
|
||||
uhd::set_thread_priority_safe(1.0);
|
||||
usrp_state_t *s = (usrp_state_t*)malloc(sizeof(usrp_state_t));
|
||||
memset(s, 0, sizeof(usrp_state_t));
|
||||
|
||||
// Initialize USRP device
|
||||
extern "C" {
|
||||
/*! \brief Initialize Openair USRP target. It returns 0 if OK
|
||||
* \param device the hardware to use
|
||||
* \param openair0_cfg RF frontend parameters set by application
|
||||
*/
|
||||
int device_init(openair0_device* device, openair0_config_t *openair0_cfg) {
|
||||
|
||||
uhd::set_thread_priority_safe(1.0);
|
||||
usrp_state_t *s = (usrp_state_t*)malloc(sizeof(usrp_state_t));
|
||||
memset(s, 0, sizeof(usrp_state_t));
|
||||
|
||||
// Initialize USRP device
|
||||
|
||||
|
||||
std::string args = "type=b200";
|
||||
|
||||
@@ -436,14 +529,14 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_
|
||||
s->usrp->set_clock_source("internal");
|
||||
|
||||
//Setting device type to USRP X300/X310
|
||||
device->type=USRP_X300_IF;
|
||||
device->type=USRP_X300_DEV;
|
||||
|
||||
// this is not working yet, master clock has to be set via constructor
|
||||
// set master clock rate and sample rate for tx & rx for streaming
|
||||
//s->usrp->set_master_clock_rate(usrp_master_clock);
|
||||
|
||||
openair0_cfg[0].rx_gain_calib_table = calib_table_x310;
|
||||
|
||||
|
||||
switch ((int)openair0_cfg[0].sample_rate) {
|
||||
case 30720000:
|
||||
// from usrp_time_offset
|
||||
@@ -482,17 +575,18 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_
|
||||
|
||||
} else {
|
||||
printf("Found USRP B200");
|
||||
args += ",num_recv_frames=256" ;
|
||||
s->usrp = uhd::usrp::multi_usrp::make(args);
|
||||
|
||||
// s->usrp->set_rx_subdev_spec(rx_subdev);
|
||||
// s->usrp->set_tx_subdev_spec(tx_subdev);
|
||||
|
||||
// do not explicitly set the clock to "internal", because this will disable the gpsdo
|
||||
// // lock mboard clocks
|
||||
// s->usrp->set_clock_source("internal");
|
||||
|
||||
// do not explicitly set the clock to "internal", because this will disable the gpsdo
|
||||
// // lock mboard clocks
|
||||
// s->usrp->set_clock_source("internal");
|
||||
// set master clock rate and sample rate for tx & rx for streaming
|
||||
|
||||
device->type = USRP_B200_IF;
|
||||
device->type = USRP_B200_DEV;
|
||||
|
||||
|
||||
if ((vers == 3) && (subvers == 9) && (subsubvers>=2)) {
|
||||
@@ -552,6 +646,12 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_
|
||||
}
|
||||
}
|
||||
|
||||
/* device specific */
|
||||
openair0_cfg[0].txlaunch_wait = 1;//manage when TX processing is triggered
|
||||
openair0_cfg[0].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered
|
||||
openair0_cfg[0].iq_txshift = 4;//shift
|
||||
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
|
||||
|
||||
for(i=0;i<s->usrp->get_rx_num_channels();i++) {
|
||||
if (i<openair0_cfg[0].rx_num_channels) {
|
||||
s->usrp->set_rx_rate(openair0_cfg[0].sample_rate,i);
|
||||
@@ -605,10 +705,7 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_
|
||||
|
||||
|
||||
s->usrp->set_time_now(uhd::time_spec_t(0.0));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for (i=0;i<openair0_cfg[0].rx_num_channels;i++) {
|
||||
if (i<openair0_cfg[0].rx_num_channels) {
|
||||
@@ -656,4 +753,6 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_
|
||||
if(is_equal(s->sample_rate, (double)7.68e6))
|
||||
s->tx_forward_nsamps = 50;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*@}*/
|
||||
|
||||
@@ -793,7 +793,10 @@ INPUT = $(OPENAIR1_DIR)/PHY/defs.h \
|
||||
$(OPENAIR2_DIR)/LAYER2/RLC/UM_v9.3.0/rlc_um.h \
|
||||
$(OPENAIR2_DIR)/LAYER2/RLC/UM_v9.3.0/rlc_um_entity.h \
|
||||
$(OPENAIR2_DIR)/NETWORK_DRIVER/MESH/proto_extern.h \
|
||||
$(OPENAIR_TARGETS)/ARCH/COMMON/common_lib.h
|
||||
$(OPENAIR_TARGETS)/ARCH/COMMON/common_lib.h \
|
||||
$(OPENAIR_TARGETS)/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp \
|
||||
$(OPENAIR_TARGETS)/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c \
|
||||
$(OPENAIR_TARGETS)/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.h
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
|
||||
@@ -0,0 +1,189 @@
|
||||
Active_eNBs = ( "eNB_Eurecom_LTEBox");
|
||||
# Asn1_verbosity, choice in: none, info, annoying
|
||||
Asn1_verbosity = "none";
|
||||
|
||||
eNBs =
|
||||
(
|
||||
{
|
||||
////////// Identification parameters:
|
||||
eNB_ID = 0xe00;
|
||||
|
||||
cell_type = "CELL_MACRO_ENB";
|
||||
|
||||
eNB_name = "eNB_Eurecom_LTEBox";
|
||||
|
||||
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||
tracking_area_code = "1";
|
||||
|
||||
mobile_country_code = "208";
|
||||
|
||||
mobile_network_code = "92";
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
component_carriers = (
|
||||
{
|
||||
frame_type = "FDD";
|
||||
tdd_config = 3;
|
||||
tdd_config_s = 0;
|
||||
prefix_type = "NORMAL";
|
||||
eutra_band = 7;
|
||||
downlink_frequency = 2660000000L;
|
||||
uplink_frequency_offset = -120000000;
|
||||
Nid_cell = 0;
|
||||
N_RB_DL = 25;
|
||||
Nid_cell_mbsfn = 0;
|
||||
nb_antennas_tx = 1;
|
||||
nb_antennas_rx = 1;
|
||||
tx_gain = 90;
|
||||
rx_gain = 125;
|
||||
prach_root = 0;
|
||||
prach_config_index = 0;
|
||||
prach_high_speed = "DISABLE";
|
||||
prach_zero_correlation = 1;
|
||||
prach_freq_offset = 2;
|
||||
pucch_delta_shift = 1;
|
||||
pucch_nRB_CQI = 1;
|
||||
pucch_nCS_AN = 0;
|
||||
pucch_n1_AN = 32;
|
||||
pdsch_referenceSignalPower = -29;
|
||||
pdsch_p_b = 0;
|
||||
pusch_n_SB = 1;
|
||||
pusch_enable64QAM = "DISABLE";
|
||||
pusch_hoppingMode = "interSubFrame";
|
||||
pusch_hoppingOffset = 0;
|
||||
pusch_groupHoppingEnabled = "ENABLE";
|
||||
pusch_groupAssignment = 0;
|
||||
pusch_sequenceHoppingEnabled = "DISABLE";
|
||||
pusch_nDMRS1 = 1;
|
||||
phich_duration = "NORMAL";
|
||||
phich_resource = "ONESIXTH";
|
||||
srs_enable = "DISABLE";
|
||||
/* srs_BandwidthConfig =;
|
||||
srs_SubframeConfig =;
|
||||
srs_ackNackST =;
|
||||
srs_MaxUpPts =;*/
|
||||
|
||||
pusch_p0_Nominal = -90;
|
||||
pusch_alpha = "AL1";
|
||||
pucch_p0_Nominal = -96;
|
||||
msg3_delta_Preamble = 6;
|
||||
pucch_deltaF_Format1 = "deltaF2";
|
||||
pucch_deltaF_Format1b = "deltaF3";
|
||||
pucch_deltaF_Format2 = "deltaF0";
|
||||
pucch_deltaF_Format2a = "deltaF0";
|
||||
pucch_deltaF_Format2b = "deltaF0";
|
||||
|
||||
rach_numberOfRA_Preambles = 64;
|
||||
rach_preamblesGroupAConfig = "DISABLE";
|
||||
/*
|
||||
rach_sizeOfRA_PreamblesGroupA = ;
|
||||
rach_messageSizeGroupA = ;
|
||||
rach_messagePowerOffsetGroupB = ;
|
||||
*/
|
||||
rach_powerRampingStep = 4;
|
||||
rach_preambleInitialReceivedTargetPower = -108;
|
||||
rach_preambleTransMax = 10;
|
||||
rach_raResponseWindowSize = 10;
|
||||
rach_macContentionResolutionTimer = 48;
|
||||
rach_maxHARQ_Msg3Tx = 4;
|
||||
|
||||
pcch_default_PagingCycle = 128;
|
||||
pcch_nB = "oneT";
|
||||
bcch_modificationPeriodCoeff = 2;
|
||||
ue_TimersAndConstants_t300 = 1000;
|
||||
ue_TimersAndConstants_t301 = 1000;
|
||||
ue_TimersAndConstants_t310 = 1000;
|
||||
ue_TimersAndConstants_t311 = 10000;
|
||||
ue_TimersAndConstants_n310 = 20;
|
||||
ue_TimersAndConstants_n311 = 1;
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
srb1_parameters :
|
||||
{
|
||||
# timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
|
||||
timer_poll_retransmit = 80;
|
||||
|
||||
# timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
|
||||
timer_reordering = 35;
|
||||
|
||||
# timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
|
||||
timer_status_prohibit = 0;
|
||||
|
||||
# poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
|
||||
poll_pdu = 4;
|
||||
|
||||
# poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
|
||||
poll_byte = 99999;
|
||||
|
||||
# max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
|
||||
max_retx_threshold = 4;
|
||||
}
|
||||
|
||||
# ------- SCTP definitions
|
||||
SCTP :
|
||||
{
|
||||
# Number of streams to use in input/output
|
||||
SCTP_INSTREAMS = 2;
|
||||
SCTP_OUTSTREAMS = 2;
|
||||
};
|
||||
|
||||
|
||||
////////// MME parameters:
|
||||
mme_ip_address = ( { ipv4 = "192.168.12.170";
|
||||
ipv6 = "192:168:30::17";
|
||||
active = "yes";
|
||||
preference = "ipv4";
|
||||
}
|
||||
);
|
||||
|
||||
rrh_gw_config = (
|
||||
{
|
||||
local_if_name = "eth0";
|
||||
remote_address = "169.254.8.28";
|
||||
#remote_address = "127.0.0.1";
|
||||
#remote_address = "74:d4:35:cc:88:45";
|
||||
local_address = "169.254.7.91";
|
||||
#local_address = "127.0.0.1";
|
||||
#local_address = "d4:be:d9:22:0a:ac";
|
||||
#for raw option local port must be the same to remote
|
||||
local_port = 50001;
|
||||
remote_port = 50000;
|
||||
active = "yes";
|
||||
preference = "udp";
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
NETWORK_INTERFACES :
|
||||
{
|
||||
ENB_INTERFACE_NAME_FOR_S1_MME = "eth0";
|
||||
ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.242/24";
|
||||
|
||||
ENB_INTERFACE_NAME_FOR_S1U = "eth0";
|
||||
ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.242/24";
|
||||
ENB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||
};
|
||||
|
||||
log_config :
|
||||
{
|
||||
global_log_level ="info";
|
||||
global_log_verbosity ="medium";
|
||||
hw_log_level ="info";
|
||||
hw_log_verbosity ="medium";
|
||||
phy_log_level ="info";
|
||||
phy_log_verbosity ="medium";
|
||||
mac_log_level ="info";
|
||||
mac_log_verbosity ="high";
|
||||
rlc_log_level ="info";
|
||||
rlc_log_verbosity ="medium";
|
||||
pdcp_log_level ="info";
|
||||
pdcp_log_verbosity ="medium";
|
||||
rrc_log_level ="info";
|
||||
rrc_log_verbosity ="medium";
|
||||
};
|
||||
}
|
||||
);
|
||||
@@ -148,7 +148,7 @@ void *rrh_proc_UE_thread(void * arg) {
|
||||
unsigned int samples_per_frame=0;
|
||||
rrh_module_t *dev=(rrh_module_t *)arg;
|
||||
|
||||
samples_per_frame= dev->eth_dev.openair0_cfg.samples_per_frame;
|
||||
samples_per_frame= dev->eth_dev.openair0_cfg->samples_per_frame;
|
||||
AssertFatal(samples_per_frame <=0, "invalide samples_per_frame !%u\n",samples_per_frame);
|
||||
|
||||
time_req.tv_sec = 0;
|
||||
@@ -260,7 +260,7 @@ void *rrh_UE_thread(void *arg) {
|
||||
void *tmp;
|
||||
unsigned int samples_per_frame=0;
|
||||
|
||||
samples_per_frame= dev->eth_dev.openair0_cfg.samples_per_frame;
|
||||
samples_per_frame= dev->eth_dev.openair0_cfg->samples_per_frame;
|
||||
time_req_1us.tv_sec = 0;
|
||||
time_req_1us.tv_nsec = 1000;
|
||||
|
||||
@@ -269,26 +269,26 @@ void *rrh_UE_thread(void *arg) {
|
||||
cmd=dev->eth_dev.trx_start_func(&dev->eth_dev);
|
||||
|
||||
/* allocate memory for TX/RX buffers */
|
||||
rx_buffer_UE = (int32_t**)malloc16(dev->eth_dev.openair0_cfg.rx_num_channels*sizeof(int32_t*));
|
||||
tx_buffer_UE = (int32_t**)malloc16(dev->eth_dev.openair0_cfg.tx_num_channels*sizeof(int32_t*));
|
||||
rx_buffer_UE = (int32_t**)malloc16(dev->eth_dev.openair0_cfg->rx_num_channels*sizeof(int32_t*));
|
||||
tx_buffer_UE = (int32_t**)malloc16(dev->eth_dev.openair0_cfg->tx_num_channels*sizeof(int32_t*));
|
||||
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg.rx_num_channels; i++) {
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg->rx_num_channels; i++) {
|
||||
tmp=(void *)malloc(sizeof(int32_t)*(samples_per_frame+4));
|
||||
memset(tmp,0,sizeof(int32_t)*(samples_per_frame+4));
|
||||
rx_buffer_UE[i]=(tmp+4*sizeof(int32_t));
|
||||
}
|
||||
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg.tx_num_channels; i++) {
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg->tx_num_channels; i++) {
|
||||
tmp=(void *)malloc(sizeof(int32_t)*(samples_per_frame+4));
|
||||
memset(tmp,0,sizeof(int32_t)*(samples_per_frame+4));
|
||||
tx_buffer_UE[i]=(tmp+4*sizeof(int32_t));
|
||||
}
|
||||
|
||||
printf("Client %s:%d is connected (DL_RB=%d) rt=%d|%d. \n" , dev->eth_dev.openair0_cfg.remote_ip,
|
||||
dev->eth_dev.openair0_cfg.remote_port,
|
||||
dev->eth_dev.openair0_cfg.num_rb_dl,
|
||||
dev->eth_dev.openair0_cfg.rx_num_channels,
|
||||
dev->eth_dev.openair0_cfg.tx_num_channels);
|
||||
printf("Client %s:%d is connected (DL_RB=%d) rt=%d|%d. \n" , dev->eth_dev.openair0_cfg->remote_addr,
|
||||
dev->eth_dev.openair0_cfg->remote_port,
|
||||
dev->eth_dev.openair0_cfg->num_rb_dl,
|
||||
dev->eth_dev.openair0_cfg->rx_num_channels,
|
||||
dev->eth_dev.openair0_cfg->tx_num_channels);
|
||||
|
||||
if (cmd==START_CMD) {
|
||||
|
||||
@@ -348,8 +348,8 @@ void *rrh_UE_rx_thread(void *arg) {
|
||||
openair0_timestamp temp, last_hw_counter=0;
|
||||
|
||||
antenna_index = 0;
|
||||
nsamps = dev->eth_dev.openair0_cfg.samples_per_packet;
|
||||
samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame;
|
||||
nsamps = dev->eth_dev.openair0_cfg->samples_per_packet;
|
||||
samples_per_frame = dev->eth_dev.openair0_cfg->samples_per_frame;
|
||||
|
||||
while (rrh_exit == 0) {
|
||||
if (!UE_rx_started) {
|
||||
@@ -492,8 +492,8 @@ void *rrh_UE_tx_thread(void *arg) {
|
||||
unsigned int samples_per_frame=0;
|
||||
|
||||
antenna_index = 0;
|
||||
nsamps = dev->eth_dev.openair0_cfg.samples_per_packet;
|
||||
samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame;
|
||||
nsamps = dev->eth_dev.openair0_cfg->samples_per_packet;
|
||||
samples_per_frame = dev->eth_dev.openair0_cfg->samples_per_frame;
|
||||
|
||||
|
||||
while (rrh_exit == 0) {
|
||||
|
||||
+123
-223
@@ -127,7 +127,7 @@ static void check_dev_config( rrh_module_t *mod_enb);
|
||||
* \note
|
||||
* @ingroup _oai
|
||||
*/
|
||||
static void calc_rt_period_ns( openair0_config_t openair0_cfg);
|
||||
static void calc_rt_period_ns( openair0_config_t *openair0_cfg);
|
||||
|
||||
|
||||
|
||||
@@ -140,104 +140,33 @@ void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag) {
|
||||
|
||||
RT_flag_eNB=RT_flag;
|
||||
NRT_flag_eNB=NRT_flag;
|
||||
|
||||
/* handshake with client to exchange parameters */
|
||||
|
||||
/* init socket and have handshake-like msg with client to exchange parameters */
|
||||
mod_enb->eth_dev.trx_start_func(&mod_enb->eth_dev);//change port make it plus_id
|
||||
|
||||
/* if a RF iterface is added to RRH module get the configuration parameters sent from eNB */
|
||||
if (mod_enb->devs->type != NONE_IF ) {
|
||||
|
||||
memcpy((void*)&mod_enb->devs->openair0_cfg,(void *)&mod_enb->eth_dev.openair0_cfg,sizeof(openair0_config_t));
|
||||
|
||||
/* certain parameters have to be updated (calibration related)*/
|
||||
if ( mod_enb->devs->type == EXMIMO_IF ) {
|
||||
if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) {
|
||||
mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
|
||||
mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175;
|
||||
mod_enb->devs->openair0_cfg.tx_delay = 8;
|
||||
}
|
||||
else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 50 ) {
|
||||
mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
|
||||
mod_enb->devs->openair0_cfg.tx_forward_nsamps = 95;
|
||||
mod_enb->devs->openair0_cfg.tx_delay = 5;
|
||||
}
|
||||
else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 25 ) {
|
||||
mod_enb->devs->openair0_cfg.samples_per_packet = 1024;
|
||||
mod_enb->devs->openair0_cfg.tx_forward_nsamps = 70;
|
||||
mod_enb->devs->openair0_cfg.tx_delay = 6;
|
||||
}
|
||||
else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 6 ) {
|
||||
mod_enb->devs->openair0_cfg.samples_per_packet = 256;
|
||||
mod_enb->devs->openair0_cfg.tx_forward_nsamps = 40;
|
||||
mod_enb->devs->openair0_cfg.tx_delay = 8;
|
||||
}
|
||||
}
|
||||
else if ((mod_enb->devs->type == USRP_B200_IF )||(mod_enb->devs->type == USRP_X300_IF )) {
|
||||
if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) {
|
||||
mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
|
||||
mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175;
|
||||
mod_enb->devs->openair0_cfg.tx_delay = 8;
|
||||
}
|
||||
else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 50 ) {
|
||||
mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
|
||||
mod_enb->devs->openair0_cfg.tx_forward_nsamps = 95;
|
||||
mod_enb->devs->openair0_cfg.tx_delay = 5;
|
||||
}
|
||||
else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 25 ) {
|
||||
mod_enb->devs->openair0_cfg.samples_per_packet = 1024;
|
||||
mod_enb->devs->openair0_cfg.tx_forward_nsamps = 70;
|
||||
mod_enb->devs->openair0_cfg.tx_delay = 6;
|
||||
}
|
||||
else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 6 ) {
|
||||
mod_enb->devs->openair0_cfg.samples_per_packet = 256;
|
||||
mod_enb->devs->openair0_cfg.tx_forward_nsamps = 40;
|
||||
mod_enb->devs->openair0_cfg.tx_delay = 8;
|
||||
}
|
||||
}
|
||||
else if(mod_enb->devs->type == BLADERF_IF) {
|
||||
if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) {
|
||||
mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
|
||||
mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175;
|
||||
mod_enb->devs->openair0_cfg.tx_delay = 8;
|
||||
}
|
||||
else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 50 ) {
|
||||
mod_enb->devs->openair0_cfg.samples_per_packet = 2048;
|
||||
mod_enb->devs->openair0_cfg.tx_forward_nsamps = 95;
|
||||
mod_enb->devs->openair0_cfg.tx_delay = 5;
|
||||
}
|
||||
else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 25 ) {
|
||||
mod_enb->devs->openair0_cfg.samples_per_packet = 1024;
|
||||
mod_enb->devs->openair0_cfg.tx_forward_nsamps = 70;
|
||||
mod_enb->devs->openair0_cfg.tx_delay = 6;
|
||||
}
|
||||
else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 6 ) {
|
||||
mod_enb->devs->openair0_cfg.samples_per_packet = 256;
|
||||
mod_enb->devs->openair0_cfg.tx_forward_nsamps = 40;
|
||||
mod_enb->devs->openair0_cfg.tx_delay = 8;
|
||||
}
|
||||
}
|
||||
|
||||
/* check sanity of configuration parameters and print */
|
||||
check_dev_config(mod_enb);
|
||||
|
||||
/* initialize and configure the RF device */
|
||||
if (openair0_device_init(mod_enb->devs, &mod_enb->devs->openair0_cfg)<0){
|
||||
LOG_E(RRH,"Exiting, cannot initialize RF device.\n");
|
||||
exit(-1);
|
||||
}
|
||||
else {
|
||||
LOG_I(RRH,"RF device has been successfully initialized.\n");
|
||||
}
|
||||
mod_enb->devs->openair0_cfg = mod_enb->eth_dev.openair0_cfg;
|
||||
|
||||
/* start RF device */
|
||||
if (mod_enb->devs->type == EXMIMO_IF ) {
|
||||
/* check sanity of configuration parameters and print */
|
||||
check_dev_config(mod_enb);
|
||||
|
||||
/* initialize and configure the RF device */
|
||||
if (openair0_device_load(mod_enb->devs, mod_enb->devs->openair0_cfg)<0) {
|
||||
LOG_E(RRH,"Exiting, cannot initialize RF device.\n");
|
||||
exit(-1);
|
||||
} else {
|
||||
if (mod_enb->devs->type != NONE_DEV) {
|
||||
/* start RF device */
|
||||
if (mod_enb->devs->type == EXMIMO_DEV) {
|
||||
//call start function for exmino
|
||||
} else {
|
||||
if (mod_enb->devs->trx_start_func(mod_enb->devs)!=0)
|
||||
LOG_E(RRH,"Unable to initiate RF device.\n");
|
||||
else
|
||||
LOG_I(RRH,"RF device has been initiated.\n");
|
||||
}
|
||||
|
||||
} else {
|
||||
if (mod_enb->devs->trx_start_func(mod_enb->devs)!=0)
|
||||
LOG_E(RRH,"Unable to initiate RF device.\n");
|
||||
}
|
||||
LOG_I(RRH,"RF device has been initiated.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* create main eNB module thread
|
||||
main_rrh_eNB_thread allocates memory
|
||||
@@ -266,7 +195,7 @@ void *rrh_eNB_thread(void *arg) {
|
||||
void *tmp;
|
||||
unsigned int samples_per_frame=0;
|
||||
|
||||
samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame;
|
||||
samples_per_frame = dev->eth_dev.openair0_cfg->samples_per_frame;
|
||||
|
||||
while (rrh_exit==0) {
|
||||
|
||||
@@ -278,42 +207,42 @@ void *rrh_eNB_thread(void *arg) {
|
||||
/* allocate memory for TX/RX buffers
|
||||
each antenna port has a TX and a RX buffer
|
||||
each TX and RX buffer is of (samples_per_frame + HEADER_SIZE) samples (size of samples is 4 bytes) */
|
||||
rx_buffer_eNB = (int32_t**)malloc16(dev->eth_dev.openair0_cfg.rx_num_channels*sizeof(int32_t*));
|
||||
tx_buffer_eNB = (int32_t**)malloc16(dev->eth_dev.openair0_cfg.tx_num_channels*sizeof(int32_t*));
|
||||
rx_buffer_eNB = (int32_t**)malloc16(dev->eth_dev.openair0_cfg->rx_num_channels*sizeof(int32_t*));
|
||||
tx_buffer_eNB = (int32_t**)malloc16(dev->eth_dev.openair0_cfg->tx_num_channels*sizeof(int32_t*));
|
||||
LOG_D(RRH,"rx_buffer_eNB address =%p tx_buffer_eNB address =%p \n",rx_buffer_eNB,tx_buffer_eNB);
|
||||
|
||||
/* rx_buffer_eNB points to the beginning of data */
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg.rx_num_channels; i++) {
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg->rx_num_channels; i++) {
|
||||
tmp=(void *)malloc16(sizeof(int32_t)*(samples_per_frame + 32));
|
||||
memset(tmp,0,sizeof(int32_t)*(samples_per_frame + 32));
|
||||
rx_buffer_eNB[i]=( tmp + (32*sizeof(int32_t)) );
|
||||
LOG_D(RRH,"i=%d rx_buffer_eNB[i]=%p tmp= %p\n",i,rx_buffer_eNB[i],tmp);
|
||||
}
|
||||
/* tx_buffer_eNB points to the beginning of data */
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg.tx_num_channels; i++) {
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg->tx_num_channels; i++) {
|
||||
tmp=(void *)malloc16(sizeof(int32_t)*(samples_per_frame + 32));
|
||||
memset(tmp,0,sizeof(int32_t)*(samples_per_frame + 32));
|
||||
tx_buffer_eNB[i]=( tmp + (32*sizeof(int32_t)) );
|
||||
LOG_D(RRH,"i= %d tx_buffer_eNB[i]=%p tmp= %p \n",i,tx_buffer_eNB[i],tmp);
|
||||
}
|
||||
/* dummy initialization for TX/RX buffers */
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg.rx_num_channels; i++) {
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg->rx_num_channels; i++) {
|
||||
for (j=0; j<samples_per_frame; j++) {
|
||||
rx_buffer_eNB[i][j]=32+i;
|
||||
}
|
||||
}
|
||||
/* dummy initialization for TX/RX buffers */
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg.tx_num_channels; i++) {
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg->tx_num_channels; i++) {
|
||||
for (j=0; j<samples_per_frame; j++) {
|
||||
tx_buffer_eNB[i][j]=12+i;
|
||||
}
|
||||
}
|
||||
/* allocate TX/RX buffers pointers used in write/read operations */
|
||||
rx_eNB = (void**)malloc16(dev->eth_dev.openair0_cfg.rx_num_channels*sizeof(int32_t*));
|
||||
tx_eNB = (void**)malloc16(dev->eth_dev.openair0_cfg.tx_num_channels*sizeof(int32_t*));
|
||||
rx_eNB = (void**)malloc16(dev->eth_dev.openair0_cfg->rx_num_channels*sizeof(int32_t*));
|
||||
tx_eNB = (void**)malloc16(dev->eth_dev.openair0_cfg->tx_num_channels*sizeof(int32_t*));
|
||||
|
||||
/* init mutexes */
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg.tx_num_channels; i++) {
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg->tx_num_channels; i++) {
|
||||
pthread_mutex_init(&sync_eNB_mutex[i],NULL);
|
||||
pthread_cond_init(&sync_eNB_cond[i],NULL);
|
||||
}
|
||||
@@ -353,7 +282,7 @@ void *rrh_eNB_thread(void *arg) {
|
||||
}
|
||||
|
||||
/* create timer thread; when no RF device is present a software clock is generated */
|
||||
if (dev->devs->type == NONE_IF) {
|
||||
if (dev->devs->type == NONE_DEV) {
|
||||
|
||||
int error_code_timer;
|
||||
pthread_t main_timer_proc_thread;
|
||||
@@ -405,10 +334,11 @@ void *rrh_eNB_thread(void *arg) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Receive from RF and transmit to RRH */
|
||||
|
||||
void *rrh_eNB_rx_thread(void *arg) {
|
||||
|
||||
/* measuremnt related vars */
|
||||
/* measurement related vars */
|
||||
struct timespec time0,time1,time2;
|
||||
unsigned long long max_rx_time=0, min_rx_time=rt_period, total_rx_time=0, average_rx_time=rt_period, s_period=0, trial=0;
|
||||
int trace_cnt=0;
|
||||
@@ -425,10 +355,10 @@ void *rrh_eNB_rx_thread(void *arg) {
|
||||
|
||||
time_req_1us.tv_sec = 0;
|
||||
time_req_1us.tv_nsec =1000; //time_req_1us.tv_nsec = (int)rt_period/2;--->granularity issue
|
||||
spp_eth = dev->eth_dev.openair0_cfg.samples_per_packet;
|
||||
spp_rf = dev->devs->openair0_cfg.samples_per_packet;
|
||||
spp_eth = dev->eth_dev.openair0_cfg->samples_per_packet;
|
||||
spp_rf = dev->devs->openair0_cfg->samples_per_packet;
|
||||
|
||||
samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame;
|
||||
samples_per_frame = dev->eth_dev.openair0_cfg->samples_per_frame;
|
||||
samples_per_subframe = (unsigned int)samples_per_frame/10;
|
||||
loopback = dev->loopback;
|
||||
measurements = dev->measurements;
|
||||
@@ -456,14 +386,14 @@ void *rrh_eNB_rx_thread(void *arg) {
|
||||
|
||||
while (rrh_exit == 0) {
|
||||
while (rx_pos <(1 + subframe)*samples_per_subframe) {
|
||||
LOG_D(RRH,"starting a new send:%d %d\n",sync_trx,frame);
|
||||
//LOG_D(RRH,"starting a new send:%d %d\n",sync_trx,frame);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX, 1 );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME_RX, frame);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME_RX, subframe );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_PCK, pck_rx );
|
||||
LOG_D(RRH,"pack=%d rx_pos=%d subframe=%d frame=%d\n ",pck_rx, rx_pos, subframe,frame);
|
||||
|
||||
if (dev->devs->type == NONE_IF) {
|
||||
if (dev->devs->type == NONE_DEV) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_HWCNT, hw_counter );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_LHWCNT, last_hw_counter );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_CNT, s_cnt );
|
||||
@@ -501,19 +431,19 @@ void *rrh_eNB_rx_thread(void *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg.rx_num_channels; i++) {
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg->rx_num_channels; i++) {
|
||||
rx_eNB[i] = (void*)&rx_buffer_eNB[i][rx_pos];
|
||||
LOG_D(RRH," rx_eNB[i]=%p rx_buffer_eNB[i][rx_pos]=%p ,rx_pos=%d, i=%d ts=%d\n",rx_eNB[i],&rx_buffer_eNB[i][rx_pos],rx_pos,i,timestamp_rx);
|
||||
}
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RXCNT, rx_pos );
|
||||
if (dev->devs->type != NONE_IF) {
|
||||
if (dev->devs->type != NONE_DEV) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_RF, 1 );
|
||||
/* Read operation to RF device (RX)*/
|
||||
if ( dev->devs->trx_read_func (dev->devs,
|
||||
×tamp_rx,
|
||||
rx_eNB,
|
||||
spp_rf,
|
||||
dev->devs->openair0_cfg.rx_num_channels
|
||||
dev->devs->openair0_cfg->rx_num_channels
|
||||
)<0) {
|
||||
perror("RRH eNB : USRP read");
|
||||
}
|
||||
@@ -526,14 +456,14 @@ void *rrh_eNB_rx_thread(void *arg) {
|
||||
timestamp_rx,
|
||||
rx_eNB,
|
||||
spp_eth,
|
||||
dev->eth_dev.openair0_cfg.rx_num_channels,
|
||||
dev->eth_dev.openair0_cfg->rx_num_channels,
|
||||
0))<0) {
|
||||
perror("RRH eNB : ETHERNET write");
|
||||
}
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
|
||||
|
||||
/* when there is no RF timestamp is updated by number of samples */
|
||||
if (dev->devs->type == NONE_IF) {
|
||||
if (dev->devs->type == NONE_DEV) {
|
||||
timestamp_rx+=spp_eth;
|
||||
last_hw_counter=hw_counter;
|
||||
}
|
||||
@@ -559,7 +489,7 @@ void *rrh_eNB_rx_thread(void *arg) {
|
||||
}
|
||||
if (s_period++ == PRINTF_PERIOD) {
|
||||
s_period=0;
|
||||
LOG_I(RRH,"Average eNB RX time : %lu\tMax RX time : %lu\tMin RX time : %lu\n",average_rx_time,max_rx_time,min_rx_time);
|
||||
LOG_I(RRH,"Average eNB RX time : %lu ns\tMax RX time : %lu ns\tMin RXX time : %lu ns\n",average_rx_time,max_rx_time,min_rx_time);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -577,7 +507,7 @@ void *rrh_eNB_rx_thread(void *arg) {
|
||||
next_rx_pos=(rx_pos+spp_eth);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX, 0 );
|
||||
/**/
|
||||
/*
|
||||
if (frame>50) {
|
||||
pthread_mutex_lock(&sync_trx_mutex);
|
||||
while (sync_trx) {
|
||||
@@ -587,7 +517,7 @@ void *rrh_eNB_rx_thread(void *arg) {
|
||||
LOG_D(RRH,"out of while send:%d %d\n",sync_trx,frame);
|
||||
pthread_cond_signal(&sync_trx_cond);
|
||||
pthread_mutex_unlock(&sync_trx_mutex);
|
||||
}
|
||||
}*/
|
||||
} // while
|
||||
|
||||
subframe++;
|
||||
@@ -609,6 +539,7 @@ void *rrh_eNB_rx_thread(void *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Receive from eNB and transmit to RF */
|
||||
|
||||
void *rrh_eNB_tx_thread(void *arg) {
|
||||
|
||||
@@ -647,60 +578,34 @@ void *rrh_eNB_tx_thread(void *arg) {
|
||||
|
||||
time_req_1us.tv_sec = 1;
|
||||
time_req_1us.tv_nsec = 0;
|
||||
spp_eth = dev->eth_dev.openair0_cfg.samples_per_packet;
|
||||
spp_rf = dev->devs->openair0_cfg.samples_per_packet;
|
||||
samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame;
|
||||
spp_eth = dev->eth_dev.openair0_cfg->samples_per_packet;
|
||||
spp_rf = dev->devs->openair0_cfg->samples_per_packet;
|
||||
samples_per_frame = dev->eth_dev.openair0_cfg->samples_per_frame;
|
||||
samples_per_subframe = (unsigned int)samples_per_frame/10;
|
||||
tx_pos=0;
|
||||
//tx_pos_rf=spp_rf*dev->devs->openair0_cfg.tx_delay;
|
||||
|
||||
|
||||
loopback = dev->loopback;
|
||||
measurements = dev->measurements;
|
||||
|
||||
while (rrh_exit == 0) {
|
||||
while (tx_pos < (1 + subframe)*samples_per_subframe) {
|
||||
|
||||
LOG_D(RRH,"bef lock read:%d %d\n",sync_trx,frame);
|
||||
pthread_mutex_lock(&sync_trx_mutex);
|
||||
//LOG_D(RRH,"bef lock read:%d %d\n",sync_trx,frame);
|
||||
//pthread_mutex_lock(&sync_trx_mutex);
|
||||
|
||||
while (!sync_trx) {
|
||||
LOG_D(RRH,"in sync read:%d %d\n",sync_trx,frame);
|
||||
pthread_cond_wait(&sync_trx_cond,&sync_trx_mutex);
|
||||
}
|
||||
LOG_D(RRH,"out of while read:%d %d\n",sync_trx,frame);
|
||||
//while (!sync_trx) {
|
||||
//LOG_D(RRH,"in sync read:%d %d\n",sync_trx,frame);
|
||||
//pthread_cond_wait(&sync_trx_cond,&sync_trx_mutex);
|
||||
//}
|
||||
//LOG_D(RRH,"out of while read:%d %d\n",sync_trx,frame);
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 1 );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, subframe );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_PCK, pck_tx );
|
||||
|
||||
/*
|
||||
if (dev->devs->type == NONE_IF) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_HWCNT, hw_counter );
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_LHWCNT, last_hw_counter );
|
||||
|
||||
if (!eNB_tx_started) {
|
||||
eNB_tx_started=1; // set this flag to 1 to indicate that eNB started
|
||||
if (RT_flag_eNB==1) {
|
||||
last_hw_counter=hw_counter;
|
||||
}
|
||||
} else {
|
||||
if (RT_flag_eNB==1) {
|
||||
if (hw_counter > last_hw_counter+1) {
|
||||
printf("LT");
|
||||
} else {
|
||||
while ((hw_counter < last_hw_counter+1)) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP, 1 );
|
||||
nanosleep(&time_req_1us,&time_rem_1us);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
|
||||
if (measurements == 1 ) clock_gettime(CLOCK_MONOTONIC,&time1);
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg.tx_num_channels; i++) tx_eNB[i] = (void*)&tx_buffer_eNB[i][tx_pos]; //RF!!!!!
|
||||
for (i=0; i<dev->eth_dev.openair0_cfg->tx_num_channels; i++) tx_eNB[i] = (void*)&tx_buffer_eNB[i][tx_pos];
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TXCNT, tx_pos );
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
|
||||
@@ -710,12 +615,12 @@ void *rrh_eNB_tx_thread(void *arg) {
|
||||
×tamp_tx,
|
||||
tx_eNB,
|
||||
spp_eth,
|
||||
dev->eth_dev.openair0_cfg.tx_num_channels))<0) {
|
||||
dev->eth_dev.openair0_cfg->tx_num_channels))<0) {
|
||||
perror("RRH eNB : ETHERNET read");
|
||||
}
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
|
||||
|
||||
if (dev->devs->type != NONE_IF) {
|
||||
if (dev->devs->type != NONE_DEV) {
|
||||
LOG_D(RRH," tx_buffer_eNB[i][tx_pos]=%x t_buffer_eNB[i][tx_pos+1]=%x t_buffer_eNB[i][tx_pos+2]=%x \n",tx_buffer_eNB[0][tx_pos],tx_buffer_eNB[0][tx_pos+1],tx_buffer_eNB[0][tx_pos+2]);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_RF, 1 );
|
||||
/* Write operation to RF device (TX)*/
|
||||
@@ -723,8 +628,8 @@ void *rrh_eNB_tx_thread(void *arg) {
|
||||
timestamp_tx,
|
||||
tx_eNB,
|
||||
spp_rf,
|
||||
dev->devs->openair0_cfg.tx_num_channels,
|
||||
0)<0){
|
||||
dev->devs->openair0_cfg->tx_num_channels,
|
||||
1)<0){
|
||||
perror("RRH eNB : USRP write");
|
||||
}
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_RF, 0 );
|
||||
@@ -733,7 +638,7 @@ void *rrh_eNB_tx_thread(void *arg) {
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_TS, timestamp_tx&0xffffffff );
|
||||
|
||||
|
||||
if (dev->devs->type == NONE_IF) last_hw_counter=hw_counter;
|
||||
if (dev->devs->type == NONE_DEV) last_hw_counter=hw_counter;
|
||||
|
||||
|
||||
if (loopback ==1 ) {
|
||||
@@ -754,10 +659,10 @@ void *rrh_eNB_tx_thread(void *arg) {
|
||||
tx_pos += spp_eth;
|
||||
pck_tx++;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 0 );
|
||||
sync_trx=0;
|
||||
pthread_cond_signal(&sync_trx_cond);
|
||||
pthread_mutex_unlock(&sync_trx_mutex);
|
||||
//VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 0 );
|
||||
//sync_trx=0;
|
||||
//pthread_cond_signal(&sync_trx_cond);
|
||||
//pthread_mutex_unlock(&sync_trx_mutex);
|
||||
}
|
||||
|
||||
/* wrap around tx buffer index */
|
||||
@@ -775,72 +680,67 @@ void *rrh_eNB_tx_thread(void *arg) {
|
||||
}
|
||||
|
||||
|
||||
static void calc_rt_period_ns( openair0_config_t openair0_cfg) {
|
||||
static void calc_rt_period_ns( openair0_config_t *openair0_cfg) {
|
||||
|
||||
rt_period= (double)(openair0_cfg.samples_per_packet/(openair0_cfg.samples_per_frame/10.0)*1000000);
|
||||
rt_period= (double)(openair0_cfg->samples_per_packet/(openair0_cfg->samples_per_frame/10.0)*1000000);
|
||||
AssertFatal(rt_period > 0, "Invalid rt period !%u\n", rt_period);
|
||||
LOG_I(RRH,"[eNB] Real time period is set to %u ns\n", rt_period);
|
||||
}
|
||||
|
||||
|
||||
static void check_dev_config( rrh_module_t *mod_enb) {
|
||||
|
||||
|
||||
AssertFatal( (mod_enb->devs->openair0_cfg.num_rb_dl==100 || mod_enb->devs->openair0_cfg.num_rb_dl==50 || mod_enb->devs->openair0_cfg.num_rb_dl==25 || mod_enb->devs->openair0_cfg.num_rb_dl==6) , "Invalid number of resource blocks! %d\n", mod_enb->devs->openair0_cfg.num_rb_dl);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg.samples_per_frame > 0 , "Invalid number of samples per frame! %d\n",mod_enb->devs->openair0_cfg.samples_per_frame);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg.sample_rate > 0.0, "Invalid sample rate! %f\n", mod_enb->devs->openair0_cfg.sample_rate);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg.samples_per_packet > 0 , "Invalid number of samples per packet! %d\n",mod_enb->devs->openair0_cfg.samples_per_packet);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg.rx_num_channels > 0 , "Invalid number of RX antennas! %d\n", mod_enb->devs->openair0_cfg.rx_num_channels);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg.tx_num_channels > 0 , "Invalid number of TX antennas! %d\n", mod_enb->devs->openair0_cfg.tx_num_channels);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg.rx_freq[0] > 0.0 ,"Invalid RX frequency! %f\n", mod_enb->devs->openair0_cfg.rx_freq[0]);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg.tx_freq[0] > 0.0 ,"Invalid TX frequency! %f\n", mod_enb->devs->openair0_cfg.tx_freq[0]);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg.rx_gain[0] > 0.0 ,"Invalid RX gain! %f\n", mod_enb->devs->openair0_cfg.rx_gain[0]);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg.tx_gain[0] > 0.0 ,"Invalid TX gain! %f\n", mod_enb->devs->openair0_cfg.tx_gain[0]);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg.rx_bw > 0.0 ,"Invalid RX bw! %f\n", mod_enb->devs->openair0_cfg.rx_bw);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg.tx_bw > 0.0 ,"Invalid RX bw! %f\n", mod_enb->devs->openair0_cfg.tx_bw);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg.autocal[0] > 0 , "Invalid auto calibration choice! %d\n", mod_enb->devs->openair0_cfg.autocal[0]);
|
||||
|
||||
AssertFatal( (mod_enb->devs->openair0_cfg->num_rb_dl==100 || mod_enb->devs->openair0_cfg->num_rb_dl==50 || mod_enb->devs->openair0_cfg->num_rb_dl==25 || mod_enb->devs->openair0_cfg->num_rb_dl==6) , "Invalid number of resource blocks! %d\n", mod_enb->devs->openair0_cfg->num_rb_dl);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg->samples_per_frame > 0 , "Invalid number of samples per frame! %d\n",mod_enb->devs->openair0_cfg->samples_per_frame);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg->sample_rate > 0.0, "Invalid sample rate! %f\n", mod_enb->devs->openair0_cfg->sample_rate);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg->samples_per_packet > 0 , "Invalid number of samples per packet! %d\n",mod_enb->devs->openair0_cfg->samples_per_packet);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg->rx_num_channels > 0 , "Invalid number of RX antennas! %d\n", mod_enb->devs->openair0_cfg->rx_num_channels);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg->tx_num_channels > 0 , "Invalid number of TX antennas! %d\n", mod_enb->devs->openair0_cfg->tx_num_channels);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg->rx_freq[0] > 0.0 ,"Invalid RX frequency! %f\n", mod_enb->devs->openair0_cfg->rx_freq[0]);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg->tx_freq[0] > 0.0 ,"Invalid TX frequency! %f\n", mod_enb->devs->openair0_cfg->tx_freq[0]);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg->rx_gain[0] > 0.0 ,"Invalid RX gain! %f\n", mod_enb->devs->openair0_cfg->rx_gain[0]);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg->tx_gain[0] > 0.0 ,"Invalid TX gain! %f\n", mod_enb->devs->openair0_cfg->tx_gain[0]);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg->rx_bw > 0.0 ,"Invalid RX bw! %f\n", mod_enb->devs->openair0_cfg->rx_bw);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg->tx_bw > 0.0 ,"Invalid RX bw! %f\n", mod_enb->devs->openair0_cfg->tx_bw);
|
||||
AssertFatal( mod_enb->devs->openair0_cfg->autocal[0] > 0 , "Invalid auto calibration choice! %d\n", mod_enb->devs->openair0_cfg->autocal[0]);
|
||||
|
||||
printf("\n---------------------RF device configuration parameters---------------------\n");
|
||||
|
||||
printf("\tMod_id=%d\n \tlog level=%d\n \tDL_RB=%d\n \tsamples_per_frame=%d\n \tsample_rate=%f\n \tsamples_per_packet=%d\n \ttx_delay=%d\n \ttx_forward_nsamps=%d\n \trx_num_channels=%d\n \ttx_num_channels=%d\n \trx_freq_0=%f\n \ttx_freq_0=%f\n \trx_freq_1=%f\n \ttx_freq_1=%f\n \trx_freq_2=%f\n \ttx_freq_2=%f\n \trx_freq_3=%f\n \ttx_freq_3=%f\n \trxg_mode=%d\n \trx_gain_0=%f\n \ttx_gain_0=%f\n \trx_gain_1=%f\n \ttx_gain_1=%f\n \trx_gain_2=%f\n \ttx_gain_2=%f\n \trx_gain_3=%f\n \ttx_gain_3=%f\n \trx_gain_offset_2=%f\n \ttx_gain_offset_3=%f\n \trx_bw=%f\n \ttx_bw=%f\n \tautocal=%d\n \trem_addr %s:%d\n \tmy_addr %s:%d\n",
|
||||
mod_enb->devs->openair0_cfg.Mod_id,
|
||||
mod_enb->devs->openair0_cfg.log_level,
|
||||
mod_enb->devs->openair0_cfg.num_rb_dl,
|
||||
mod_enb->devs->openair0_cfg.samples_per_frame,
|
||||
mod_enb->devs->openair0_cfg.sample_rate,
|
||||
mod_enb->devs->openair0_cfg.samples_per_packet,
|
||||
mod_enb->devs->openair0_cfg.tx_delay,
|
||||
mod_enb->devs->openair0_cfg.tx_forward_nsamps,
|
||||
mod_enb->devs->openair0_cfg.rx_num_channels,
|
||||
mod_enb->devs->openair0_cfg.tx_num_channels,
|
||||
mod_enb->devs->openair0_cfg.rx_freq[0],
|
||||
mod_enb->devs->openair0_cfg.tx_freq[0],
|
||||
mod_enb->devs->openair0_cfg.rx_freq[1],
|
||||
mod_enb->devs->openair0_cfg.tx_freq[1],
|
||||
mod_enb->devs->openair0_cfg.rx_freq[2],
|
||||
mod_enb->devs->openair0_cfg.tx_freq[2],
|
||||
mod_enb->devs->openair0_cfg.rx_freq[3],
|
||||
mod_enb->devs->openair0_cfg.tx_freq[3],
|
||||
mod_enb->devs->openair0_cfg.rxg_mode[0],
|
||||
mod_enb->devs->openair0_cfg.rx_gain[0],
|
||||
mod_enb->devs->openair0_cfg.tx_gain[0],
|
||||
mod_enb->devs->openair0_cfg.rx_gain[1],
|
||||
mod_enb->devs->openair0_cfg.tx_gain[1],
|
||||
mod_enb->devs->openair0_cfg.rx_gain[2],
|
||||
mod_enb->devs->openair0_cfg.tx_gain[2],
|
||||
mod_enb->devs->openair0_cfg.rx_gain[3],
|
||||
mod_enb->devs->openair0_cfg.tx_gain[3],
|
||||
//mod_enb->devs->openair0_cfg.rx_gain_offset[0],
|
||||
//mod_enb->devs->openair0_cfg.rx_gain_offset[1],
|
||||
mod_enb->devs->openair0_cfg.rx_gain_offset[2],
|
||||
mod_enb->devs->openair0_cfg.rx_gain_offset[3],
|
||||
mod_enb->devs->openair0_cfg.rx_bw,
|
||||
mod_enb->devs->openair0_cfg.tx_bw,
|
||||
mod_enb->devs->openair0_cfg.autocal[0],
|
||||
mod_enb->devs->openair0_cfg.remote_ip,
|
||||
mod_enb->devs->openair0_cfg.remote_port,
|
||||
mod_enb->devs->openair0_cfg.my_ip,
|
||||
mod_enb->devs->openair0_cfg.my_port
|
||||
printf("\tMod_id=%d\n \tlog level=%d\n \tDL_RB=%d\n \tsamples_per_frame=%d\n \tsample_rate=%f\n \tsamples_per_packet=%d\n \ttx_scheduling_advance=%d\n \ttx_sample_advance=%d\n \trx_num_channels=%d\n \ttx_num_channels=%d\n \trx_freq_0=%f\n \ttx_freq_0=%f\n \trx_freq_1=%f\n \ttx_freq_1=%f\n \trx_freq_2=%f\n \ttx_freq_2=%f\n \trx_freq_3=%f\n \ttx_freq_3=%f\n \trxg_mode=%d\n \trx_gain_0=%f\n \ttx_gain_0=%f\n \trx_gain_1=%f\n \ttx_gain_1=%f\n \trx_gain_2=%f\n \ttx_gain_2=%f\n \trx_gain_3=%f\n \ttx_gain_3=%f\n \trx_gain_offset_2=%f\n \ttx_gain_offset_3=%f\n \trx_bw=%f\n \ttx_bw=%f\n \tautocal=%d\n",
|
||||
mod_enb->devs->openair0_cfg->Mod_id,
|
||||
mod_enb->devs->openair0_cfg->log_level,
|
||||
mod_enb->devs->openair0_cfg->num_rb_dl,
|
||||
mod_enb->devs->openair0_cfg->samples_per_frame,
|
||||
mod_enb->devs->openair0_cfg->sample_rate,
|
||||
mod_enb->devs->openair0_cfg->samples_per_packet,
|
||||
mod_enb->devs->openair0_cfg->tx_scheduling_advance,
|
||||
mod_enb->devs->openair0_cfg->tx_sample_advance,
|
||||
mod_enb->devs->openair0_cfg->rx_num_channels,
|
||||
mod_enb->devs->openair0_cfg->tx_num_channels,
|
||||
mod_enb->devs->openair0_cfg->rx_freq[0],
|
||||
mod_enb->devs->openair0_cfg->tx_freq[0],
|
||||
mod_enb->devs->openair0_cfg->rx_freq[1],
|
||||
mod_enb->devs->openair0_cfg->tx_freq[1],
|
||||
mod_enb->devs->openair0_cfg->rx_freq[2],
|
||||
mod_enb->devs->openair0_cfg->tx_freq[2],
|
||||
mod_enb->devs->openair0_cfg->rx_freq[3],
|
||||
mod_enb->devs->openair0_cfg->tx_freq[3],
|
||||
mod_enb->devs->openair0_cfg->rxg_mode[0],
|
||||
mod_enb->devs->openair0_cfg->tx_gain[0],
|
||||
mod_enb->devs->openair0_cfg->tx_gain[0],
|
||||
mod_enb->devs->openair0_cfg->rx_gain[1],
|
||||
mod_enb->devs->openair0_cfg->tx_gain[1],
|
||||
mod_enb->devs->openair0_cfg->rx_gain[2],
|
||||
mod_enb->devs->openair0_cfg->tx_gain[2],
|
||||
mod_enb->devs->openair0_cfg->rx_gain[3],
|
||||
mod_enb->devs->openair0_cfg->tx_gain[3],
|
||||
//mod_enb->devs->openair0_cfg->rx_gain_offset[0],
|
||||
//mod_enb->devs->openair0_cfg->rx_gain_offset[1],
|
||||
mod_enb->devs->openair0_cfg->rx_gain_offset[2],
|
||||
mod_enb->devs->openair0_cfg->rx_gain_offset[3],
|
||||
mod_enb->devs->openair0_cfg->rx_bw,
|
||||
mod_enb->devs->openair0_cfg->tx_bw,
|
||||
mod_enb->devs->openair0_cfg->autocal[0]
|
||||
);
|
||||
|
||||
printf("----------------------------------------------------------------------------\n");
|
||||
|
||||
+140
-78
@@ -332,7 +332,6 @@ void reset_opp_meas(void);
|
||||
void print_opp_meas(void);
|
||||
int transmission_mode=1;
|
||||
|
||||
|
||||
int16_t glog_level = LOG_INFO;
|
||||
int16_t glog_verbosity = LOG_MED;
|
||||
int16_t hw_log_level = LOG_INFO;
|
||||
@@ -363,16 +362,60 @@ int16_t osa_log_verbosity = LOG_MED;
|
||||
|
||||
|
||||
#ifdef ETHERNET
|
||||
char rrh_eNB_ip[20] = "127.0.0.1";
|
||||
int rrh_eNB_port = 50000;
|
||||
char *rrh_UE_ip = "127.0.0.1";
|
||||
int rrh_UE_port = 51000;
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
|
||||
char uecap_xer[1024],uecap_xer_in=0;
|
||||
extern void *UE_thread(void *arg);
|
||||
extern void init_UE_threads(void);
|
||||
|
||||
/*---------------------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()
|
||||
{
|
||||
#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));
|
||||
@@ -433,7 +476,6 @@ void help (void) {
|
||||
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(" -M IP address of RRH\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");
|
||||
@@ -958,27 +1000,9 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB)
|
||||
if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti))
|
||||
tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti;
|
||||
|
||||
((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0]=
|
||||
#ifdef EXMIMO
|
||||
((short*)dummy_tx_b)[2*i]<<4;
|
||||
#elif OAI_BLADERF
|
||||
((short*)dummy_tx_b)[2*i];
|
||||
#elif OAI_LMSSDR
|
||||
//phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset]=dummy_tx_b[i];
|
||||
((short*)dummy_tx_b)[2*i];
|
||||
#else
|
||||
((short*)dummy_tx_b)[2*i]<<4;
|
||||
#endif
|
||||
((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1]=
|
||||
#ifdef EXMIMO
|
||||
((short*)dummy_tx_b)[2*i+1]<<4;
|
||||
#elif OAI_BLADERF
|
||||
((short*)dummy_tx_b)[2*i+1];
|
||||
#elif OAI_LMSSDR
|
||||
((short*)dummy_tx_b)[2*i+1];
|
||||
#else
|
||||
((short*)dummy_tx_b)[2*i+1]<<4;
|
||||
#endif
|
||||
((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<<openair0_cfg[0].iq_txshift;
|
||||
|
||||
((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<<openair0_cfg[0].iq_txshift;
|
||||
}
|
||||
// if S-subframe switch to RX in second subframe
|
||||
if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S) {
|
||||
@@ -1835,7 +1859,9 @@ static void* eNB_thread( void* arg )
|
||||
PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx);
|
||||
|
||||
stop_meas( &softmodem_stats_hw );
|
||||
clock_gettime( CLOCK_MONOTONIC, &trx_time1 );
|
||||
if (frame > 50) {
|
||||
clock_gettime( CLOCK_MONOTONIC, &trx_time1 );
|
||||
}
|
||||
|
||||
if (frame > 20){
|
||||
if (rxs != spp)
|
||||
@@ -1844,8 +1870,6 @@ static void* eNB_thread( void* arg )
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
|
||||
|
||||
// Transmit TX buffer based on timestamp from RX
|
||||
|
||||
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
|
||||
// prepare tx buffer pointers
|
||||
@@ -1865,17 +1889,28 @@ static void* eNB_thread( void* arg )
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp+(openair0_cfg[card].tx_scheduling_advance)-openair0_cfg[card].tx_sample_advance)&0xffffffff );
|
||||
|
||||
stop_meas( &softmodem_stats_mt );
|
||||
clock_gettime( CLOCK_MONOTONIC, &trx_time2 );
|
||||
if (frame > 50) {
|
||||
clock_gettime( CLOCK_MONOTONIC, &trx_time2 );
|
||||
//update_difftimes(trx_time1, trx_time2);
|
||||
}
|
||||
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0);
|
||||
#else
|
||||
// USRP_DEBUG is active
|
||||
rt_sleep_ns(1000000);
|
||||
#endif
|
||||
|
||||
if ((frame>50) &&
|
||||
(tx_launched == 0) &&
|
||||
(rx_pos >= (((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) {
|
||||
/* FT configurable tx lauch delay (in slots): txlaunch_wait, txlaunch_wait_slotcount is device specific and
|
||||
set in the corresponding library (with txlaunch_wait=1 and txlaunch_wait_slotcount=1 the check is as it previously was) */
|
||||
/* old check:
|
||||
if ((frame>50) &&
|
||||
(tx_launched == 0) &&
|
||||
(rx_pos >= (((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) {*/
|
||||
if ( (frame>50) && (tx_launched == 0) &&
|
||||
((openair0_cfg[card].txlaunch_wait == 0) ||
|
||||
((openair0_cfg[card].txlaunch_wait == 1) &&
|
||||
(rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))))) {
|
||||
|
||||
tx_launched = 1;
|
||||
|
||||
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
@@ -2037,6 +2072,9 @@ eNB_thread_cleanup:
|
||||
#endif
|
||||
|
||||
eNB_thread_status = 0;
|
||||
|
||||
// print_difftimes();
|
||||
|
||||
return &eNB_thread_status;
|
||||
}
|
||||
|
||||
@@ -2175,14 +2213,7 @@ static void get_options (int argc, char **argv)
|
||||
|
||||
case LONG_OPTION_DUMP_FRAME:
|
||||
mode = rx_dump_frame;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
#ifdef ETHERNET
|
||||
strcpy(rrh_eNB_ip,optarg);
|
||||
#endif
|
||||
break;
|
||||
|
||||
break;
|
||||
case 'A':
|
||||
timing_advance = atoi (optarg);
|
||||
break;
|
||||
@@ -2425,6 +2456,34 @@ static void get_options (int argc, char **argv)
|
||||
"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);
|
||||
|
||||
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 = (eth_params_t*)malloc(sizeof(eth_params_t));
|
||||
memset(eth_params, 0, sizeof(eth_params_t));
|
||||
|
||||
printf( "\n\tRRH GW %d config for eNB %u:\n\n", j, i);
|
||||
printf( "\tinterface name : \t%s:\n",enb_properties->properties[i]->rrh_gw_if_name);
|
||||
printf( "\tlocal address : \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].local_address);
|
||||
printf( "\tlocal port : \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].local_port);
|
||||
printf( "\tremote address : \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_address);
|
||||
printf( "\tremote port : \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_port);
|
||||
printf( "\ttransport : \t%s Ethernet:\n\n",(enb_properties->properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : "UDP");
|
||||
|
||||
eth_params->local_if_name = enb_properties->properties[i]->rrh_gw_if_name;
|
||||
eth_params->my_addr = enb_properties->properties[i]->rrh_gw_config[j].local_address;
|
||||
eth_params->my_port = enb_properties->properties[i]->rrh_gw_config[j].local_port;
|
||||
eth_params->remote_addr = enb_properties->properties[i]->rrh_gw_config[j].remote_address;
|
||||
eth_params->remote_port = enb_properties->properties[i]->rrh_gw_config[j].remote_port;
|
||||
eth_params->transp_preference = enb_properties->properties[i]->rrh_gw_config[j].raw;
|
||||
|
||||
} else {
|
||||
local_remote_radio = BBU_LOCAL_RADIO_HEAD;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
frame_parms[CC_id]->frame_type = enb_properties->properties[i]->frame_type[CC_id];
|
||||
frame_parms[CC_id]->tdd_config = enb_properties->properties[i]->tdd_config[CC_id];
|
||||
@@ -2967,20 +3026,13 @@ int main( int argc, char **argv )
|
||||
else //FDD
|
||||
openair0_cfg[card].duplex_mode = duplex_mode_FDD;
|
||||
|
||||
#ifdef ETHERNET
|
||||
|
||||
//calib needed
|
||||
openair0_cfg[card].tx_scheduling_advance = 0;
|
||||
openair0_cfg[card].tx_sample_advance = 0;
|
||||
|
||||
if (frame_parms[0]->N_RB_DL == 6)
|
||||
openair0_cfg[card].samples_per_packet = 256;
|
||||
else
|
||||
openair0_cfg[card].samples_per_packet = 1024;
|
||||
|
||||
printf("HW: samples_per_packet %d\n",openair0_cfg[card].samples_per_packet);
|
||||
#endif
|
||||
|
||||
if (local_remote_radio == BBU_REMOTE_RADIO_HEAD) {
|
||||
openair0_cfg[card].remote_addr = eth_params->remote_addr;
|
||||
openair0_cfg[card].remote_port = eth_params->remote_port;
|
||||
openair0_cfg[card].my_addr = eth_params->my_addr;
|
||||
openair0_cfg[card].my_port = eth_params->my_port;
|
||||
}
|
||||
|
||||
printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
|
||||
((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_tx),
|
||||
@@ -2990,13 +3042,10 @@ int main( int argc, char **argv )
|
||||
|
||||
if (UE_flag) {
|
||||
printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port);
|
||||
openair0_cfg[card].remote_ip = &rrh_UE_ip[0];
|
||||
openair0_cfg[card].remote_addr = &rrh_UE_ip[0];
|
||||
openair0_cfg[card].remote_port = rrh_UE_port;
|
||||
} else {
|
||||
printf("ETHERNET: Configuring eNB ETH for %s:%d\n",rrh_eNB_ip,rrh_eNB_port);
|
||||
openair0_cfg[card].remote_ip = &rrh_eNB_ip[0];
|
||||
openair0_cfg[card].remote_port = rrh_eNB_port;
|
||||
}
|
||||
}
|
||||
|
||||
openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
|
||||
#endif
|
||||
|
||||
@@ -3053,22 +3102,40 @@ int main( int argc, char **argv )
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
openair0.func_type = BBU_FUNC;
|
||||
/* device host type is set*/
|
||||
openair0.host_type = BBU_HOST;
|
||||
/* device type is initialized NONE_DEV (no RF device) when the RF device will be initiated device type will be set */
|
||||
openair0.type = NONE_DEV;
|
||||
/* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */
|
||||
openair0.transp_type = NONE_TP;
|
||||
openair0_cfg[0].log_level = glog_level;
|
||||
|
||||
if (mode!=loop_through_memory){
|
||||
int ret;
|
||||
ret= openair0_device_init(&openair0, &openair0_cfg[0]);
|
||||
printf("openair0_device_init returns %d\n",ret);
|
||||
if (ret<0) {
|
||||
printf("Exiting, cannot initialize device\n");
|
||||
exit(-1);
|
||||
int returns=-1;
|
||||
/* BBU can have either a local or a remote radio head */
|
||||
if (local_remote_radio == BBU_LOCAL_RADIO_HEAD) { //local radio head active - load library of radio head and initiate it
|
||||
if (mode!=loop_through_memory) {
|
||||
returns=openair0_device_load(&openair0, &openair0_cfg[0]);
|
||||
printf("openair0_device_init returns %d\n",returns);
|
||||
if (returns<0) {
|
||||
printf("Exiting, cannot initialize device\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mode==loop_through_memory) {
|
||||
}
|
||||
|
||||
else if (mode==loop_through_memory) {
|
||||
}
|
||||
} else { //remote radio head active - load library of transport protocol and initiate it
|
||||
if (mode!=loop_through_memory) {
|
||||
returns=openair0_transport_load(&openair0, &openair0_cfg[0], eth_params);
|
||||
printf("openair0_transport_init returns %d\n",returns);
|
||||
if (returns<0) {
|
||||
printf("Exiting, cannot initialize transport protocol\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
else if (mode==loop_through_memory) {
|
||||
}
|
||||
}
|
||||
|
||||
printf("Done\n");
|
||||
|
||||
mac_xface = malloc(sizeof(MAC_xface));
|
||||
@@ -3491,7 +3558,6 @@ int main( int argc, char **argv )
|
||||
if (multi_thread>0) {
|
||||
printf("Killing eNB processing threads\n");
|
||||
kill_eNB_proc();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3583,10 +3649,6 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// replace RX signal buffers with mmaped HW versions
|
||||
#ifdef EXMIMO
|
||||
openair0_cfg[CC_id].tx_num_channels = 0;
|
||||
|
||||
+92
-16
@@ -1,19 +1,19 @@
|
||||
[*]
|
||||
[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
|
||||
[*] Thu Sep 17 14:23:43 2015
|
||||
[*] Fri Jan 29 16:34:46 2016
|
||||
[*]
|
||||
[dumpfile] "/tmp/openair_dump_rrh.vcd"
|
||||
[dumpfile_mtime] "Thu Sep 17 14:21:43 2015"
|
||||
[dumpfile_size] 636509125
|
||||
[savefile] "/home/guepe/openair4G/targets/RT/USER/rrh.gtkw"
|
||||
[timestart] 17746655400
|
||||
[size] 1855 1056
|
||||
[pos] -1 -1
|
||||
*-15.826077 17746846200 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[dumpfile_mtime] "Fri Jan 29 16:20:55 2016"
|
||||
[dumpfile_size] 224259458
|
||||
[savefile] "/home/guepe/openairinterface5g_rrh/openairinterface5g/targets/RT/USER/rrh.gtkw"
|
||||
[timestart] 31315875900
|
||||
[size] 1004 1028
|
||||
[pos] 926 -1
|
||||
*-17.429794 31316090054 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
|
||||
[sst_width] 224
|
||||
[signals_width] 230
|
||||
[signals_width] 261
|
||||
[sst_expanded] 1
|
||||
[sst_vpaned_height] 287
|
||||
[sst_vpaned_height] 278
|
||||
@24
|
||||
[color] 1
|
||||
variables.hw_frame_rx[63:0]
|
||||
@@ -23,7 +23,10 @@ variables.hw_subframe_rx[63:0]
|
||||
[color] 1
|
||||
functions.eNB_rx
|
||||
functions.eNB_rx_sleep
|
||||
functions.trx_write_rf
|
||||
[color] 3
|
||||
functions.trx_read_rf
|
||||
[color] 7
|
||||
functions.trx_write
|
||||
@c00024
|
||||
variables.rxcnt[63:0]
|
||||
@28
|
||||
@@ -95,24 +98,97 @@ variables.rxcnt[63:0]
|
||||
-group_end
|
||||
@24
|
||||
variables.pck_rx[63:0]
|
||||
variables.rx_ts[63:0]
|
||||
@c00024
|
||||
variables.tx_seq_num[63:0]
|
||||
@28
|
||||
(0)variables.tx_seq_num[63:0]
|
||||
(1)variables.tx_seq_num[63:0]
|
||||
(2)variables.tx_seq_num[63:0]
|
||||
(3)variables.tx_seq_num[63:0]
|
||||
(4)variables.tx_seq_num[63:0]
|
||||
(5)variables.tx_seq_num[63:0]
|
||||
(6)variables.tx_seq_num[63:0]
|
||||
(7)variables.tx_seq_num[63:0]
|
||||
(8)variables.tx_seq_num[63:0]
|
||||
(9)variables.tx_seq_num[63:0]
|
||||
(10)variables.tx_seq_num[63:0]
|
||||
(11)variables.tx_seq_num[63:0]
|
||||
(12)variables.tx_seq_num[63:0]
|
||||
(13)variables.tx_seq_num[63:0]
|
||||
(14)variables.tx_seq_num[63:0]
|
||||
(15)variables.tx_seq_num[63:0]
|
||||
(16)variables.tx_seq_num[63:0]
|
||||
(17)variables.tx_seq_num[63:0]
|
||||
(18)variables.tx_seq_num[63:0]
|
||||
(19)variables.tx_seq_num[63:0]
|
||||
(20)variables.tx_seq_num[63:0]
|
||||
(21)variables.tx_seq_num[63:0]
|
||||
(22)variables.tx_seq_num[63:0]
|
||||
(23)variables.tx_seq_num[63:0]
|
||||
(24)variables.tx_seq_num[63:0]
|
||||
(25)variables.tx_seq_num[63:0]
|
||||
(26)variables.tx_seq_num[63:0]
|
||||
(27)variables.tx_seq_num[63:0]
|
||||
(28)variables.tx_seq_num[63:0]
|
||||
(29)variables.tx_seq_num[63:0]
|
||||
(30)variables.tx_seq_num[63:0]
|
||||
(31)variables.tx_seq_num[63:0]
|
||||
(32)variables.tx_seq_num[63:0]
|
||||
(33)variables.tx_seq_num[63:0]
|
||||
(34)variables.tx_seq_num[63:0]
|
||||
(35)variables.tx_seq_num[63:0]
|
||||
(36)variables.tx_seq_num[63:0]
|
||||
(37)variables.tx_seq_num[63:0]
|
||||
(38)variables.tx_seq_num[63:0]
|
||||
(39)variables.tx_seq_num[63:0]
|
||||
(40)variables.tx_seq_num[63:0]
|
||||
(41)variables.tx_seq_num[63:0]
|
||||
(42)variables.tx_seq_num[63:0]
|
||||
(43)variables.tx_seq_num[63:0]
|
||||
(44)variables.tx_seq_num[63:0]
|
||||
(45)variables.tx_seq_num[63:0]
|
||||
(46)variables.tx_seq_num[63:0]
|
||||
(47)variables.tx_seq_num[63:0]
|
||||
(48)variables.tx_seq_num[63:0]
|
||||
(49)variables.tx_seq_num[63:0]
|
||||
(50)variables.tx_seq_num[63:0]
|
||||
(51)variables.tx_seq_num[63:0]
|
||||
(52)variables.tx_seq_num[63:0]
|
||||
(53)variables.tx_seq_num[63:0]
|
||||
(54)variables.tx_seq_num[63:0]
|
||||
(55)variables.tx_seq_num[63:0]
|
||||
(56)variables.tx_seq_num[63:0]
|
||||
(57)variables.tx_seq_num[63:0]
|
||||
(58)variables.tx_seq_num[63:0]
|
||||
(59)variables.tx_seq_num[63:0]
|
||||
(60)variables.tx_seq_num[63:0]
|
||||
(61)variables.tx_seq_num[63:0]
|
||||
(62)variables.tx_seq_num[63:0]
|
||||
(63)variables.tx_seq_num[63:0]
|
||||
@1401200
|
||||
-group_end
|
||||
@24
|
||||
variables.hw_frame[63:0]
|
||||
variables.hw_subframe[63:0]
|
||||
@28
|
||||
[color] 1
|
||||
functions.eNB_tx
|
||||
functions.eNB_tx_sleep
|
||||
functions.trx_read_rf
|
||||
[color] 7
|
||||
functions.trx_write
|
||||
[color] 7
|
||||
functions.trx_read
|
||||
[color] 3
|
||||
functions.trx_write_rf
|
||||
@24
|
||||
variables.txcnt[63:0]
|
||||
variables.rx_ts[63:0]
|
||||
variables.pck_tx[63:0]
|
||||
variables.tx_ts[63:0]
|
||||
@25
|
||||
variables.rx_seq_num_prv[63:0]
|
||||
@24
|
||||
variables.rx_seq_num[63:0]
|
||||
variables.hw_cnt_rx[63:0]
|
||||
variables.lhw_cnt_rx[63:0]
|
||||
@25
|
||||
[color] 3
|
||||
variables.cnt[63:0]
|
||||
[pattern_trace] 1
|
||||
|
||||
+73
-67
@@ -51,9 +51,9 @@
|
||||
#include <time.h>
|
||||
|
||||
#include "common_lib.h"
|
||||
#include "rrh_gw.h" // change to rrh_new.h, put externs in rrh_extern.h
|
||||
#include "rrh_gw.h"
|
||||
#include "rt_wrapper.h"
|
||||
#include "rrh_gw_externs.h" // change to rrh_new.h, put externs in rrh_extern.h
|
||||
#include "rrh_gw_externs.h"
|
||||
|
||||
|
||||
#include "log_if.h"
|
||||
@@ -71,8 +71,9 @@
|
||||
*****************************************************************************************/
|
||||
|
||||
|
||||
|
||||
char rrh_ip[20] = "192.168.12.242"; // there is code to detect the my ip address
|
||||
/* local IP/MAC address is detected*/
|
||||
char rrh_ip[20] = "0.0.0.0";
|
||||
unsigned char rrh_mac[6] = "0:0:0:0:0:0";
|
||||
int rrh_port = 50000; // has to be an option
|
||||
|
||||
/* log */
|
||||
@@ -86,7 +87,7 @@ int16_t ue_log_level = LOG_INFO;
|
||||
int16_t ue_log_verbosity = LOG_MED;
|
||||
|
||||
|
||||
/* flags definitions */
|
||||
/* flag definitions */
|
||||
uint8_t eNB_flag=0;
|
||||
uint8_t UE_flag=0;
|
||||
uint8_t EXMIMO_flag=0;
|
||||
@@ -102,10 +103,8 @@ uint8_t measurements_flag=0;
|
||||
- default ethernet interface is local */
|
||||
uint8_t num_eNB_mod=0;
|
||||
uint8_t num_UE_mod=0;
|
||||
uint8_t num_EXMIMO_mod=0;
|
||||
uint8_t num_USRP_mod=0;
|
||||
uint8_t hardware_target=NONE_IF;
|
||||
char* if_name="lo";
|
||||
char* if_name="lo";
|
||||
uint8_t eth_mode=ETH_UDP_MODE;
|
||||
|
||||
rrh_module_t *enb_array;
|
||||
rrh_module_t *ue_array;
|
||||
@@ -128,14 +127,14 @@ static void print_help(void);
|
||||
*/
|
||||
static rrh_module_t new_module(unsigned int id);
|
||||
|
||||
/*!\fn static int get_ip_address(char* if_name)
|
||||
/*!\fn static int get_address(char* if_name, uint8_t flag);
|
||||
* \brief retrieves IP address from the specified network interface
|
||||
* \param[in] name of network interface
|
||||
* \return 0
|
||||
* \note
|
||||
* @ingroup _oai
|
||||
*/
|
||||
static int get_ip_address(char* if_name);
|
||||
static int get_address(char* if_name, uint8_t flag);
|
||||
|
||||
|
||||
|
||||
@@ -192,48 +191,53 @@ static rrh_module_t new_module (unsigned int id) {
|
||||
rrh_mod.measurements=measurements_flag;
|
||||
|
||||
/* each module is associated with an ethernet device */
|
||||
rrh_mod.eth_dev.type=ETH_IF;
|
||||
rrh_mod.eth_dev.type=NONE_DEV;
|
||||
rrh_mod.eth_dev.transp_type=NONE_TP;
|
||||
/* ethernet device is functioning within RRH */
|
||||
rrh_mod.eth_dev.func_type=RRH_FUNC;
|
||||
/* specify IP address */
|
||||
get_ip_address(if_name);
|
||||
openair0_cfg.my_ip=&rrh_ip[0];
|
||||
openair0_cfg.my_port=rrh_port;
|
||||
rrh_mod.eth_dev.host_type=RRH_HOST;
|
||||
/* */
|
||||
rrh_mod.eth_dev.openair0_cfg = (openair0_config_t*)malloc(sizeof(openair0_config_t));
|
||||
memset(rrh_mod.eth_dev.openair0_cfg,0,sizeof(openair0_config_t));
|
||||
/* get IP and MAC address */
|
||||
get_address(if_name,eth_mode);
|
||||
|
||||
if(eth_mode==ETH_UDP_MODE) {
|
||||
openair0_cfg.my_addr = &rrh_ip[0];
|
||||
openair0_cfg.my_port = rrh_port;
|
||||
LOG_I(RRH,"UDP mode selected for ethernet.\n");
|
||||
} else if (eth_mode==ETH_RAW_MODE) {
|
||||
openair0_cfg.my_addr = &rrh_mac[0];
|
||||
openair0_cfg.my_port = rrh_port;
|
||||
LOG_I(RRH,"RAW mode selected for ethernet.\n");
|
||||
}
|
||||
|
||||
/* */
|
||||
eth_params_t *eth_params = (eth_params_t*)malloc(sizeof(eth_params_t));
|
||||
memset(eth_params, 0, sizeof(eth_params_t));
|
||||
eth_params->local_if_name = if_name;
|
||||
eth_params->transp_preference = eth_mode;
|
||||
|
||||
/* ethernet device initialization */
|
||||
if (openair0_dev_init_eth(&rrh_mod.eth_dev, &openair0_cfg)<0){
|
||||
if (openair0_transport_load(&rrh_mod.eth_dev, &openair0_cfg,eth_params)<0) {
|
||||
LOG_E(RRH,"Exiting, cannot initialize ethernet interface.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
/* allocate space and specify associated RF device */
|
||||
openair0_device *oai_dv = (openair0_device *)malloc(sizeof(openair0_device));
|
||||
memset(oai_dv,0, sizeof(openair0_device));
|
||||
memset(oai_dv,0,sizeof(openair0_device));
|
||||
|
||||
#ifdef EXMIMO
|
||||
rrh_mod.devs=oai_dv;
|
||||
rrh_mod.devs->type=EXMIMO_IF;
|
||||
LOG_I(RRH,"Setting RF device to EXMIMO\n");
|
||||
#elif OAI_USRP
|
||||
rrh_mod.devs=oai_dv;
|
||||
rrh_mod.devs->type=USRP_B200_IF;
|
||||
LOG_I(RRH,"Setting RF device to USRP\n");
|
||||
#elif OAI_BLADERF
|
||||
rrh_mod.devs=oai_dv;
|
||||
rrh_mod.devs->type=BLADERF_IF;
|
||||
LOG_I(RRH,"Setting RF device to BLADERF\n");
|
||||
#else
|
||||
rrh_mod.devs=oai_dv;
|
||||
rrh_mod.devs->type=NONE_IF;
|
||||
LOG_I(RRH,"Setting RF interface to NONE_IF... \n");
|
||||
#endif
|
||||
|
||||
rrh_mod.devs->type=NONE_DEV;
|
||||
rrh_mod.devs->transp_type=NONE_TP;
|
||||
rrh_mod.devs->host_type=RRH_HOST;
|
||||
|
||||
return rrh_mod;
|
||||
}
|
||||
|
||||
static void debug_init(void) {
|
||||
|
||||
// log initialization
|
||||
/* log initialization */
|
||||
logInit();
|
||||
set_glog(glog_level, glog_verbosity);
|
||||
|
||||
@@ -241,7 +245,7 @@ static void debug_init(void) {
|
||||
//set_comp_log(ENB_LOG, enb_log_level, enb_log_verbosity, 1);
|
||||
//set_comp_log(UE_LOG, ue_log_level, ue_log_verbosity, 1);
|
||||
|
||||
// vcd initialization
|
||||
/* vcd initialization */
|
||||
if (ouput_vcd) {
|
||||
vcd_signal_dumper_init("/tmp/openair_dump_rrh.vcd");
|
||||
|
||||
@@ -253,7 +257,7 @@ static void get_options(int argc, char *argv[]) {
|
||||
|
||||
int opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "xvhlte:n:u:g:r:w:i:")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "xvhlte:n:u:g:r:m:i:")) != -1) {
|
||||
|
||||
switch (opt) {
|
||||
case 'n':
|
||||
@@ -273,6 +277,9 @@ static void get_options(int argc, char *argv[]) {
|
||||
printf("RRH interface name is set to %s\n", if_name);
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
eth_mode=atoi(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
//rrh_log_level=atoi(optarg);
|
||||
break;
|
||||
@@ -293,16 +300,12 @@ static void get_options(int argc, char *argv[]) {
|
||||
loopback_flag=1;
|
||||
break;
|
||||
case 't':
|
||||
/*When measurements are enabled statistics related to TX/RX time are printed*/
|
||||
/* When measurements are enabled statistics related to TX/RX time are printed */
|
||||
measurements_flag=1;
|
||||
break;
|
||||
case 'w':
|
||||
/* force to use this target*/
|
||||
hardware_target=1;
|
||||
break;
|
||||
case 'h':
|
||||
print_help();
|
||||
exit(-1);
|
||||
break;
|
||||
case 'h':
|
||||
print_help();
|
||||
exit(-1);
|
||||
default: /* '?' */
|
||||
//fprintf(stderr, "Usage: \n", argv[0]);
|
||||
exit(-1);
|
||||
@@ -311,31 +314,34 @@ static void get_options(int argc, char *argv[]) {
|
||||
|
||||
}
|
||||
|
||||
static int get_ip_address(char* if_name) {
|
||||
static int get_address(char* if_name, uint8_t flag) {
|
||||
|
||||
int fd;
|
||||
struct ifreq ifr;
|
||||
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
|
||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
/* I want to get an IPv4 IP address */
|
||||
ifr.ifr_addr.sa_family = AF_INET;
|
||||
|
||||
ifr.ifr_addr.sa_family = AF_INET;
|
||||
/* I want IP address attached to "if_name" */
|
||||
strncpy(ifr.ifr_name, if_name, IFNAMSIZ-1);
|
||||
|
||||
if ( ioctl(fd, SIOCGIFADDR, &ifr)<0 ) {
|
||||
perror("IOCTL:");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (flag==ETH_UDP_MODE) {
|
||||
if ( ioctl(fd, SIOCGIFADDR, &ifr)<0 ) {
|
||||
perror("IOCTL:");
|
||||
exit(-1);
|
||||
}
|
||||
snprintf(&rrh_ip[0],20,"%s", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
|
||||
LOG_I(RRH,"%s: IP address: %s\n",if_name,rrh_ip);
|
||||
} else if (flag==ETH_RAW_MODE) {
|
||||
if ( ioctl(fd, SIOCGIFHWADDR, &ifr)<0 ) {
|
||||
perror("IOCTL:");
|
||||
exit(-1);
|
||||
}
|
||||
ether_ntoa_r ((unsigned char *)ifr.ifr_hwaddr.sa_data, rrh_mac);
|
||||
LOG_I(RRH,"%s: MAC address: %s\n",if_name,rrh_mac);
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
/* display result */
|
||||
snprintf(&rrh_ip[0],20,"%s", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
|
||||
LOG_I(RRH,"Got IP address %s from interface %s\n", rrh_ip,if_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -343,19 +349,19 @@ static int get_ip_address(char* if_name) {
|
||||
static void print_help(void) {
|
||||
|
||||
puts("Usage: \n");
|
||||
puts(" sudo -E chrt 99 ./rrh -n1 -g6 -v -t");
|
||||
puts(" sudo -E chrt 99 ./rrh -n1 -g6 -v -t -i lo -m1");
|
||||
puts("Options:\n");
|
||||
puts("\t -n create eNB module\n");
|
||||
puts("\t -u create UE module\n");
|
||||
puts("\t -g define global log level\n");
|
||||
puts("\t -i set the RRH interface (default lo)\n");
|
||||
puts("\t -m set ethernet mode to be used by RRH, valid options: (1:raw, 0:udp) \n");
|
||||
puts("\t -r define rrh log level\n");
|
||||
puts("\t -e define eNB log level\n");
|
||||
puts("\t -x enable real time bahaviour\n");
|
||||
puts("\t -v enable vcd dump\n");
|
||||
puts("\t -l enable loopback mode\n");
|
||||
puts("\t -t enable measurements\n");
|
||||
puts("\t -w force to use specified HW\n");
|
||||
puts("\t -h display info\n");
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user