Merge remote-tracking branch 'origin/develop' into eMTC-testing

Signed-off-by: Raphael Defosseux <raphael.defosseux@eurecom.fr>
This commit is contained in:
Raphael Defosseux
2019-03-13 14:17:24 +01:00
70 changed files with 4033 additions and 2999 deletions
+84 -68
View File
@@ -19,8 +19,8 @@
* contact@openairinterface.org
*/
/*! \file common_lib.c
* \brief common APIs for different RF frontend device
/*! \file common_lib.c
* \brief common APIs for different RF frontend device
* \author HongliangXU, Navid Nikaein
* \date 2015
* \version 0.2
@@ -37,108 +37,124 @@
#include "common_lib.h"
#include "common/utils/load_module_shlib.h"
#include "targets/RT/USER/lte-softmodem.h"
int set_device(openair0_device *device) {
switch (device->type) {
case EXMIMO_DEV:
printf("[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case USRP_B200_DEV:
printf("[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case USRP_X300_DEV:
printf("[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case BLADERF_DEV:
printf("[%s] has loaded BLADERF device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case LMSSDR_DEV:
printf("[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case IRIS_DEV:
printf("[%s] has loaded Iris device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case NONE_DEV:
printf("[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
default:
printf("[%s] invalid HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
return -1;
case EXMIMO_DEV:
printf("[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case USRP_B200_DEV:
printf("[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case USRP_X300_DEV:
printf("[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case BLADERF_DEV:
printf("[%s] has loaded BLADERF device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case LMSSDR_DEV:
printf("[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case IRIS_DEV:
printf("[%s] has loaded Iris device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
case NONE_DEV:
printf("[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
break;
default:
printf("[%s] invalid HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
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 == RAU_HOST) ? "RAU": "RRU"));
return 0;
break;
case NONE_TP:
printf("[%s] has not loaded a transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
return 0;
break;
default:
printf("[%s] invalid transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
return -1;
break;
case ETHERNET_TP:
printf("[%s] has loaded ETHERNET trasport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
return 0;
break;
case NONE_TP:
printf("[%s] has not loaded a transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
return 0;
break;
default:
printf("[%s] invalid transport protocol.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
return -1;
break;
}
}
typedef int(*devfunc_t)(openair0_device *, openair0_config_t *, eth_params_t *);
/* 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) {
int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t *cfg, uint8_t flag) {
loader_shlibfunc_t shlib_fdesc[1];
int ret=0;
char *libname;
if (flag == RAU_LOCAL_RADIO_HEAD) {
libname=OAI_RF_LIBNAME;
shlib_fdesc[0].fname="device_init";
} else {
libname=OAI_TP_LIBNAME;
shlib_fdesc[0].fname="transport_init";
}
ret=load_module_shlib(libname,shlib_fdesc,1,NULL);
if (ret < 0) {
fprintf(stderr,"Library %s couldn't be loaded\n",libname);
if ( IS_SOFTMODEM_BASICSIM ) {
libname=OAI_BASICSIM_LIBNAME;
shlib_fdesc[0].fname="device_init";
} else if ( IS_SOFTMODEM_RFSIM ) {
libname=OAI_RFSIM_LIBNAME;
shlib_fdesc[0].fname="device_init";
} else if (flag == RAU_LOCAL_RADIO_HEAD) {
libname=OAI_RF_LIBNAME;
shlib_fdesc[0].fname="device_init";
} else {
ret=((devfunc_t)shlib_fdesc[0].fptr)(device,openair0_cfg,cfg);
}
return ret;
libname=OAI_TP_LIBNAME;
shlib_fdesc[0].fname="transport_init";
}
ret=load_module_shlib(libname,shlib_fdesc,1,NULL);
if (ret < 0) {
fprintf(stderr,"Library %s couldn't be loaded\n",libname);
} else {
ret=((devfunc_t)shlib_fdesc[0].fptr)(device,openair0_cfg,cfg);
}
return ret;
}
int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg) {
int rc=0;
rc=load_lib(device, openair0_cfg, NULL,RAU_LOCAL_RADIO_HEAD );
if ( rc >= 0) {
if ( set_device(device) < 0) {
if ( rc >= 0) {
if ( set_device(device) < 0) {
fprintf(stderr, "%s %d:Unsupported radio head\n",__FILE__, __LINE__);
return -1;
}
return -1;
}
}
return rc;
}
int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params) {
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, RAU_REMOTE_RADIO_HEAD);
if ( rc >= 0) {
if ( rc >= 0) {
if ( set_transport(device) < 0) {
fprintf(stderr, "%s %d:Unsupported transport protocol\n",__FILE__, __LINE__);
return -1;
}
return -1;
}
}
return rc;
return rc;
}
+57 -54
View File
@@ -19,8 +19,8 @@
* contact@openairinterface.org
*/
/*! \file common_lib.h
* \brief common APIs for different RF frontend device
/*! \file common_lib.h
* \brief common APIs for different RF frontend device
* \author HongliangXU, Navid Nikaein
* \date 2015
* \version 0.2
@@ -39,19 +39,22 @@
#define OAI_RF_LIBNAME "oai_device"
/* name of shared library implementing the transport */
#define OAI_TP_LIBNAME "oai_transpro"
/* name of shared library implementing the basic/rf simulator */
#define OAI_RFSIM_LIBNAME "rfsimulator"
/* name of shared library implementing the basic/rf simulator */
#define OAI_BASICSIM_LIBNAME "tcp_bridge_oai"
/* flags for BBU to determine whether the attached radio head is local or remote */
#define RAU_LOCAL_RADIO_HEAD 0
#define RAU_REMOTE_RADIO_HEAD 1
#ifndef MAX_CARDS
#define MAX_CARDS 8
#define MAX_CARDS 8
#endif
typedef int64_t openair0_timestamp;
typedef volatile int64_t openair0_vtimestamp;
/*!\brief structrue holds the parameters to configure USRP devices*/
typedef struct openair0_device_t openair0_device;
@@ -120,16 +123,16 @@ typedef enum {
/*!\brief openair0 device host type */
typedef enum {
MIN_HOST_TYPE = 0,
/*!\brief device functions within a RAU */
/*!\brief device functions within a RAU */
RAU_HOST,
/*!\brief device functions within a RRU */
/*!\brief device functions within a RRU */
RRU_HOST,
MAX_HOST_TYPE
}host_type_t;
} host_type_t;
/*! \brief RF Gain clibration */
/*! \brief RF Gain clibration */
typedef struct {
//! Frequency for which RX chain was calibrated
double freq;
@@ -157,7 +160,7 @@ typedef struct {
duplex_mode_t duplex_mode;
//! number of downlink resource blocks
int num_rb_dl;
//! number of samples per frame
//! number of samples per frame
unsigned int samples_per_frame;
//! the sample rate for both transmit and receive.
double sample_rate;
@@ -172,9 +175,9 @@ typedef struct {
//! number of TX channels (=TX antennas)
int tx_num_channels;
//! \brief RX base addresses for mmapped_dma
int32_t* rxbase[4];
int32_t *rxbase[4];
//! \brief TX base addresses for mmapped_dma
int32_t* txbase[4];
int32_t *txbase[4];
//! \brief Center frequency in Hz for RX.
//! index: [0..rx_num_channels[
double rx_freq[4];
@@ -185,7 +188,7 @@ typedef struct {
//! \brief Pointer to Calibration table for RX gains
rx_gain_calib_table_t *rx_gain_calib_table;
//! mode for rxgain (ExpressMIMO2)
//! mode for rxgain (ExpressMIMO2)
rx_gain_t rxg_mode[4];
//! \brief Gain for RX in dB.
//! index: [0..rx_num_channels]
@@ -199,14 +202,14 @@ typedef struct {
double rx_bw;
//! TX bandwidth in Hz
double tx_bw;
//! clock source
//! clock source
clock_source_t clock_source;
//! Manual SDR IP address
char *sdr_addrs;
//! Auto calibration flag
int autocal[4];
//! rf devices work with x bits iqs when oai have its own iq format
//! the two following parameters are used to convert iqs
//! the two following parameters are used to convert iqs
int iq_txshift;
int iq_rxrescale;
//! Configuration file for LMS7002M
@@ -219,10 +222,10 @@ typedef struct {
unsigned int sf_read_delay; // read delay in replay mode
unsigned int sf_write_delay; // write delay in replay mode
unsigned int eth_mtu; // ethernet MTU
#endif
#endif
} openair0_config_t;
/*! \brief RF mapping */
/*! \brief RF mapping */
typedef struct {
//! card id
int card;
@@ -269,14 +272,14 @@ struct openair0_device_t {
/*!brief Component Carrier ID of this device */
int CC_id;
/*!brief Type of this device */
dev_type_t type;
/*!brief Transport protocol type that the device suppports (in case I/Q samples need to be transported) */
transport_type_t transp_type;
/*!brief Type of the device's host (RAU/RRU) */
/*!brief Type of the device's host (RAU/RRU) */
host_type_t host_type;
/* !brief RF frontend parameters set by application */
@@ -298,25 +301,25 @@ struct openair0_device_t {
/*! \brief Called to send a request message between RAU-RRU on control port
@param device pointer to the device structure specific to the RF hardware target
@param msg pointer to the message structure passed between RAU-RRU
@param msg_len length of the message
*/
@param msg_len length of the message
*/
int (*trx_ctlsend_func)(openair0_device *device, void *msg, ssize_t msg_len);
/*! \brief Called to receive a reply message between RAU-RRU on control port
@param device pointer to the device structure specific to the RF hardware target
@param msg pointer to the message structure passed between RAU-RRU
@param msg_len length of the message
*/
@param msg_len length of the message
*/
int (*trx_ctlrecv_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
@param timestamp The timestamp at whicch the first sample MUST be sent
@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
*/
*/
int (*trx_write_func)(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int antenna_id, int flags);
/*! \brief Receive samples from hardware.
@@ -332,55 +335,55 @@ struct openair0_device_t {
*/
int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int antenna_id);
/*! \brief print the device statistics
/*! \brief print the device statistics
* \param device the hardware to use
* \returns 0 on success
*/
int (*trx_get_stats_func)(openair0_device *device);
/*! \brief Reset device statistics
/*! \brief Reset device statistics
* \param device the hardware to use
* \returns 0 in success
* \returns 0 in success
*/
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);
/*! \brief Stop operation of the transceiver
/*! \brief Stop operation of the transceiver
*/
int (*trx_stop_func)(openair0_device *device);
/* Functions API related to UE*/
/*! \brief Set RX feaquencies
/*! \brief Set RX feaquencies
* \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
* \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);
int (*trx_set_freq_func)(openair0_device *device, openair0_config_t *openair0_cfg,int exmimo_dump_config);
/*! \brief Set gains
* \param device the hardware to use
* \param openair0_cfg RF frontend parameters set by application
* \returns 0 in success
* \returns 0 in success
*/
int (*trx_set_gains_func)(openair0_device* device, openair0_config_t *openair0_cfg);
int (*trx_set_gains_func)(openair0_device *device, openair0_config_t *openair0_cfg);
/*! \brief RRU Configuration callback
* \param idx RU index
* \param arg pointer to capabilities or configuration
*/
void (*configure_rru)(int idx, void* arg);
void (*configure_rru)(int idx, void *arg);
};
/* 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);
typedef int(*oai_transport_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t *eth_params);
#ifdef __cplusplus
extern "C"
@@ -388,23 +391,23 @@ extern "C"
#endif
/*! \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);
/*! \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);
/*! \brief Get current timestamp of USRP
* \param device the hardware to use
*/
openair0_timestamp get_usrp_time(openair0_device *device);
/*! \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);
/*! \brief Get current timestamp of USRP
* \param device the hardware to use
*/
openair0_timestamp get_usrp_time(openair0_device *device);
/*! \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);
/*@}*/
+13 -25
View File
@@ -138,7 +138,7 @@ int eth_socket_init_raw(openair0_device *device) {
return 0;
}
/* 09/03/2019: fix obvious inconsistencies, but this code hasn't be tested for sure */
int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) {
int bytes_sent=0;
@@ -148,7 +148,12 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi
//sendto_flag|=flags;
eth->tx_nsamps=nsamps;
int pktsize;
if (eth->compression == ALAW_COMPRESS) {
pktsize = RAW_PACKET_SIZE_BYTES_ALAW(nsamps);
} else {
pktsize = RAW_PACKET_SIZE_BYTES(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 */
@@ -162,44 +167,27 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi
bytes_sent = 0;
memcpy(buff2,(void*)&eth->ehd,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;
int sent_byte;
*(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)) = timestamp;
/*printf("[RRU]write mod_%d %d , len %d, buff %p \n",
Mod_id,eth->sockfd[Mod_id],RAW_PACKET_SIZE_BYTES(nsamps), buff2);*/
while(bytes_sent < sent_byte) {
#if DEBUG
printf("------- TX ------: buff2 current position=%d remaining_bytes=%d bytes_sent=%d \n",
(void *)(buff2+bytes_sent),
sent_byte - bytes_sent,
bytes_sent);
#endif
while(bytes_sent < pktsize) {
/* Send packet */
bytes_sent += send(eth->sockfdd,
buff2,
sent_byte,
pktsize,
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 == RAU_HOST)? "RAU":"RRU", buff2, sent_byte, TX_FLAG);
#endif
eth->tx_actual_nsamps=bytes_sent>>2;
eth->tx_count++;
eth->tx_actual_nsamps=bytes_sent>>2;
eth->tx_count++;
}
}
+68
View File
@@ -0,0 +1,68 @@
#General
This is a RF simulator that allows to test OAI without a RF board.
It replaces a actual RF board driver.
As much as possible, it works like a RF board, but not in realtime: it can run faster than realtime if there is enough CPU or slower (it is CPU bound instead of real time RF sampling bound)
#build
## From build_oai
You can build it the same way, and together with actual RF driver
Example:
```bash
./build_oai --ue-nas-use-tun --UE --eNB -w SIMU
```
It is also possible to build actual RF and use choose on each run:
```bash
./build_oai --ue-nas-use-tun --UE --eNB -w USRP --rfsimulator
```
Will build both the eNB (lte-softmodem) and the UE (lte-uesoftmodem)
We recommend to use the option --ue-nas-use-tun that is much simpler to use than the OAI kernel driver.
## Add the rfsimulator after initial build
After any regular build, you can compile the driver
```bash
cd <the_compilation_dir_from_bouild_oai_script>/build
make rfsimulator
```
Then, you can use it freely
# Usage
Setting the env variable RFSIMULATOR enables the RF board simulator
It should the set to "enb" in the eNB
## 4G case
For the UE, it should be set to the IP address of the eNB
example:
```bash
sudo RFSIMULATOR=192.168.2.200 ./lte-uesoftmodem -C 2685000000 -r 50
```
Except this, the UE and the eNB can be used as it the RF is real
If you reach 'RA not active' on UE, be careful to generate a valid SIM
```bash
$OPENAIR_DIR/targets/bin/conf2uedata -c $OPENAIR_DIR/openair3/NAS/TOOLS/ue_eurecom_test_sfr.conf -o .
```
## 5G case
After regular build, add the simulation driver
(don't use ./build_oai -w SIMU until we merge 4G and 5G branches)
```bash
cd ran_build/build
make rfsimulator
```
### Launch gNB in one window
```bash
sudo RFSIMULATOR=enb ./nr-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf --parallel-config PARALLEL_SINGLE_THREAD
```
### Launch UE in another window
```bash
sudo RFSIMULATOR=127.0.0.1 ./nr-uesoftmodem --numerology 1 -r 106 -C 3510000000
```
Of course, set the gNB machine IP address if the UE and the gNB are not on the same machine
In UE, you can add "-d" to get the softscope
#Caveacts
Still issues in power control: txgain, rxgain are not used
no S1 mode is currently broken, so we were not able to test the simulator in noS1 mode
+475
View File
@@ -0,0 +1,475 @@
/*
Author: Laurent THOMAS, Open Cells for Nokia
copyleft: OpenAirInterface Software Alliance and it's licence
*/
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
#include <errno.h>
#include <sys/epoll.h>
#include <string.h>
#include <common/utils/assertions.h>
#include <common/utils/LOG/log.h>
#include "common_lib.h"
#include <openair1/PHY/defs_eNB.h>
#include "openair1/PHY/defs_UE.h"
#define PORT 4043 //TCP port for this simulator
#define CirSize 3072000 // 100ms is enough
#define sample_t uint32_t // 2*16 bits complex number
#define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t))
#define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b)))
#define MAGICeNB 0xA5A5A5A5A5A5A5A5
#define MAGICUE 0x5A5A5A5A5A5A5A5A
typedef struct {
uint64_t magic;
uint32_t size;
uint32_t nbAnt;
uint64_t timestamp;
} transferHeader;
typedef struct buffer_s {
int conn_sock;
bool alreadyRead;
uint64_t lastReceivedTS;
bool headerMode;
transferHeader th;
char *transferPtr;
uint64_t remainToTransfer;
char *circularBufEnd;
sample_t *circularBuf;
} buffer_t;
typedef struct {
int listen_sock, epollfd;
uint64_t nextTimestamp;
uint64_t typeStamp;
uint64_t initialAhead;
char *ip;
buffer_t buf[FD_SETSIZE];
} rfsimulator_state_t;
void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
buffer_t *ptr=&bridge->buf[sock];
AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, "");
ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1);
ptr->conn_sock=sock;
ptr->headerMode=true;
ptr->transferPtr=(char *)&ptr->th;
ptr->remainToTransfer=sizeof(transferHeader);
int sendbuff=1000*1000*10;
AssertFatal ( setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)) == 0, "");
struct epoll_event ev= {0};
ev.events = EPOLLIN | EPOLLRDHUP;
ev.data.fd = sock;
AssertFatal(epoll_ctl(bridge->epollfd, EPOLL_CTL_ADD, sock, &ev) != -1, "");
}
void removeCirBuf(rfsimulator_state_t *bridge, int sock) {
AssertFatal( epoll_ctl(bridge->epollfd, EPOLL_CTL_DEL, sock, NULL) != -1, "");
close(sock);
free(bridge->buf[sock].circularBuf);
memset(&bridge->buf[sock], 0, sizeof(buffer_t));
bridge->buf[sock].conn_sock=-1;
}
void socketError(rfsimulator_state_t *bridge, int sock) {
if (bridge->buf[sock].conn_sock!=-1) {
LOG_W(HW,"Lost socket \n");
removeCirBuf(bridge, sock);
if (bridge->typeStamp==MAGICUE)
exit(1);
}
}
#define helpTxt "\
\x1b[31m\
rfsimulator: error: you have to run one UE and one eNB\n\
For this, export RFSIMULATOR=enb (eNB case) or \n\
RFSIMULATOR=<an ip address> (UE case)\n\
\x1b[m"
enum blocking_t {
notBlocking,
blocking
};
void setblocking(int sock, enum blocking_t active) {
int opts;
AssertFatal( (opts = fcntl(sock, F_GETFL)) >= 0,"");
if (active==blocking)
opts = opts & ~O_NONBLOCK;
else
opts = opts | O_NONBLOCK;
AssertFatal(fcntl(sock, F_SETFL, opts) >= 0, "");
}
static bool flushInput(rfsimulator_state_t *t);
void fullwrite(int fd, void *_buf, int count, rfsimulator_state_t *t) {
char *buf = _buf;
int l;
setblocking(fd, notBlocking);
while (count) {
l = write(fd, buf, count);
if (l <= 0) {
if (errno==EINTR)
continue;
if(errno==EAGAIN) {
flushInput(t);
continue;
} else
return;
}
count -= l;
buf += l;
}
}
int server_start(openair0_device *device) {
rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv;
t->typeStamp=MAGICeNB;
AssertFatal((t->listen_sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
int enable = 1;
AssertFatal(setsockopt(t->listen_sock, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) == 0, "");
struct sockaddr_in addr = {
sin_family:
AF_INET,
sin_port:
htons(PORT),
sin_addr:
{ s_addr: INADDR_ANY }
};
bind(t->listen_sock, (struct sockaddr *)&addr, sizeof(addr));
AssertFatal(listen(t->listen_sock, 5) == 0, "");
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = t->listen_sock;
AssertFatal(epoll_ctl(t->epollfd, EPOLL_CTL_ADD, t->listen_sock, &ev) != -1, "");
return 0;
}
int start_ue(openair0_device *device) {
rfsimulator_state_t *t = device->priv;
t->typeStamp=MAGICUE;
int sock;
AssertFatal((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0, "");
struct sockaddr_in addr = {
sin_family:
AF_INET,
sin_port:
htons(PORT),
sin_addr:
{ s_addr: INADDR_ANY }
};
addr.sin_addr.s_addr = inet_addr(t->ip);
bool connected=false;
while(!connected) {
LOG_I(HW,"rfsimulator: trying to connect to %s:%d\n", t->ip, PORT);
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
LOG_I(HW,"rfsimulator: connection established\n");
connected=true;
}
perror("rfsimulator");
sleep(1);
}
setblocking(sock, notBlocking);
allocCirBuf(t, sock);
t->buf[sock].alreadyRead=true; // UE will start blocking on read
return 0;
}
int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) {
rfsimulator_state_t *t = device->priv;
for (int i=0; i<FD_SETSIZE; i++) {
buffer_t *ptr=&t->buf[i];
if (ptr->conn_sock >= 0 ) {
transferHeader header= {t->typeStamp, nsamps, nbAnt, timestamp};
fullwrite(ptr->conn_sock,&header, sizeof(header), t);
sample_t tmpSamples[nsamps][nbAnt];
for(int a=0; a<nbAnt; a++) {
sample_t *in=(sample_t *)samplesVoid[a];
for(int s=0; s<nsamps; s++)
tmpSamples[s][a]=in[s];
}
if (ptr->conn_sock >= 0 )
fullwrite(ptr->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t);
}
}
LOG_D(HW,"sent %d samples at time: %ld->%ld, energy in first antenna: %d\n",
nsamps, timestamp, timestamp+nsamps, signal_energy(samplesVoid[0], nsamps) );
return nsamps;
}
static bool flushInput(rfsimulator_state_t *t) {
// Process all incoming events on sockets
// store the data in lists
struct epoll_event events[FD_SETSIZE]= {0};
int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, 200);
if ( nfds==-1 ) {
if ( errno==EINTR || errno==EAGAIN )
return false;
else
AssertFatal(false,"error in epoll_wait\n");
}
for (int nbEv = 0; nbEv < nfds; ++nbEv) {
int fd=events[nbEv].data.fd;
if (events[nbEv].events & EPOLLIN && fd == t->listen_sock) {
int conn_sock;
AssertFatal( (conn_sock = accept(t->listen_sock,NULL,NULL)) != -1, "");
setblocking(conn_sock, notBlocking);
allocCirBuf(t, conn_sock);
LOG_I(HW,"A ue connected\n");
} else {
if ( events[nbEv].events & (EPOLLHUP | EPOLLERR | EPOLLRDHUP) ) {
socketError(t,fd);
continue;
}
buffer_t *b=&t->buf[fd];
if ( b->circularBuf == NULL ) {
LOG_E(HW, "received data on not connected socket %d\n", events[nbEv].data.fd);
continue;
}
int blockSz;
if ( b->headerMode)
blockSz=b->remainToTransfer;
else
blockSz= b->transferPtr+b->remainToTransfer < b->circularBufEnd ?
b->remainToTransfer :
b->circularBufEnd - 1 - b->transferPtr ;
int sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT);
if ( sz < 0 ) {
if ( errno != EAGAIN ) {
LOG_E(HW,"socket failed %s\n", strerror(errno));
abort();
}
} else if ( sz == 0 )
continue;
AssertFatal((b->remainToTransfer-=sz) >= 0, "");
b->transferPtr+=sz;
if (b->transferPtr==b->circularBufEnd - 1)
b->transferPtr=(char *)b->circularBuf;
// check the header and start block transfer
if ( b->headerMode==true && b->remainToTransfer==0) {
AssertFatal( (t->typeStamp == MAGICUE && b->th.magic==MAGICeNB) ||
(t->typeStamp == MAGICeNB && b->th.magic==MAGICUE), "Socket Error in protocol");
b->headerMode=false;
b->alreadyRead=true;
if ( b->lastReceivedTS != b->th.timestamp) {
int nbAnt= b->th.nbAnt;
for (uint64_t index=b->lastReceivedTS; index < b->th.timestamp; index++ )
for (int a=0; a < nbAnt; a++)
b->circularBuf[(index*nbAnt+a)%CirSize]=0;
LOG_W(HW,"gap of: %ld in reception\n", b->th.timestamp-b->lastReceivedTS );
}
b->lastReceivedTS=b->th.timestamp;
b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize];
b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt);
}
if ( b->headerMode==false ) {
b->lastReceivedTS=b->th.timestamp+b->th.size-byteToSample(b->remainToTransfer,b->th.nbAnt);
if ( b->remainToTransfer==0) {
LOG_D(HW,"Completed block reception: %ld\n", b->lastReceivedTS);
// First block in UE, resync with the eNB current TS
if ( t->nextTimestamp == 0 )
t->nextTimestamp=b->lastReceivedTS-b->th.size;
b->headerMode=true;
b->transferPtr=(char *)&b->th;
b->remainToTransfer=sizeof(transferHeader);
b->th.magic=-1;
}
}
}
}
return nfds>0;
}
int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt) {
if (nbAnt != 1) {
LOG_E(HW, "rfsimulator: only 1 antenna tested\n");
exit(1);
}
rfsimulator_state_t *t = device->priv;
LOG_D(HW, "Enter rfsimulator_read, expect %d samples, will release at TS: %ld\n", nsamps, t->nextTimestamp+nsamps);
// deliver data from received data
// check if a UE is connected
int first_sock;
for (first_sock=0; first_sock<FD_SETSIZE; first_sock++)
if (t->buf[first_sock].circularBuf != NULL )
break;
if ( first_sock == FD_SETSIZE ) {
// no connected device (we are eNB, no UE is connected)
if (!flushInput(t)) {
for (int x=0; x < nbAnt; x++)
memset(samplesVoid[x],0,sampleToByte(nsamps,1));
t->nextTimestamp+=nsamps;
LOG_W(HW,"Generated void samples for Rx: %ld\n", t->nextTimestamp);
*ptimestamp = t->nextTimestamp-nsamps;
return nsamps;
}
} else {
bool have_to_wait;
do {
have_to_wait=false;
for ( int sock=0; sock<FD_SETSIZE; sock++)
if ( t->buf[sock].circularBuf &&
t->buf[sock].alreadyRead && //>= t->initialAhead &&
(t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) {
have_to_wait=true;
break;
}
if (have_to_wait)
/*printf("Waiting on socket, current last ts: %ld, expected at least : %ld\n",
ptr->lastReceivedTS,
t->nextTimestamp+nsamps);
*/
flushInput(t);
} while (have_to_wait);
}
// Clear the output buffer
for (int a=0; a<nbAnt; a++)
memset(samplesVoid[a],0,sampleToByte(nsamps,1));
// Add all input signal in the output buffer
for (int sock=0; sock<FD_SETSIZE; sock++) {
buffer_t *ptr=&t->buf[sock];
if ( ptr->circularBuf && ptr->alreadyRead ) {
for (int a=0; a<nbAnt; a++) {
sample_t *out=(sample_t *)samplesVoid[a];
for ( int i=0; i < nsamps; i++ )
out[i]+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt+a)%CirSize]<<1;
}
}
}
*ptimestamp = t->nextTimestamp; // return the time of the first sample
t->nextTimestamp+=nsamps;
LOG_D(HW,"Rx to upper layer: %d from %ld to %ld, energy in first antenna %d\n",
nsamps,
*ptimestamp, t->nextTimestamp,
signal_energy(samplesVoid[0], nsamps));
return nsamps;
}
int rfsimulator_request(openair0_device *device, void *msg, ssize_t msg_len) {
abort();
return 0;
}
int rfsimulator_reply(openair0_device *device, void *msg, ssize_t msg_len) {
abort();
return 0;
}
int rfsimulator_get_stats(openair0_device *device) {
return 0;
}
int rfsimulator_reset_stats(openair0_device *device) {
return 0;
}
void rfsimulator_end(openair0_device *device) {}
int rfsimulator_stop(openair0_device *device) {
return 0;
}
int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cfg,int exmimo_dump_config) {
return 0;
}
int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
return 0;
}
__attribute__((__visibility__("default")))
int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
//set_log(HW,OAILOG_DEBUG);
rfsimulator_state_t *rfsimulator = (rfsimulator_state_t *)calloc(sizeof(rfsimulator_state_t),1);
if ((rfsimulator->ip=getenv("RFSIMULATOR")) == NULL ) {
LOG_E(HW,helpTxt);
exit(1);
}
rfsimulator->typeStamp = strncasecmp(rfsimulator->ip,"enb",3) == 0 ?
MAGICeNB:
MAGICUE;
LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == MAGICeNB ? "eNB" : "UE");
device->trx_start_func = rfsimulator->typeStamp == MAGICeNB ?
server_start :
start_ue;
device->trx_get_stats_func = rfsimulator_get_stats;
device->trx_reset_stats_func = rfsimulator_reset_stats;
device->trx_end_func = rfsimulator_end;
device->trx_stop_func = rfsimulator_stop;
device->trx_set_freq_func = rfsimulator_set_freq;
device->trx_set_gains_func = rfsimulator_set_gains;
device->trx_write_func = rfsimulator_write;
device->trx_read_func = rfsimulator_read;
/* let's pretend to be a b2x0 */
device->type = USRP_B200_DEV;
device->openair0_cfg=&openair0_cfg[0];
device->priv = rfsimulator;
for (int i=0; i<FD_SETSIZE; i++)
rfsimulator->buf[i].conn_sock=-1;
AssertFatal((rfsimulator->epollfd = epoll_create1(0)) != -1,"");
rfsimulator->initialAhead=openair0_cfg[0].sample_rate/1000; // One sub frame
return 0;
}
@@ -13,7 +13,7 @@ eNBs =
eNB_name = "eNB_Eurecom_LTEBox";
// Tracking area code, 0x0000 and 0xfffe are reserved values
tracking_area_code = "1";
tracking_area_code = 1;
plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2;} );
+5 -6
View File
@@ -1381,12 +1381,11 @@ int setup_RU_buffers(RU_t *ru) {
else if (frame_parms->N_RB_DL == 50) ru->N_TA_offset = 624/2;
else if (frame_parms->N_RB_DL == 25) ru->N_TA_offset = 624/4;
#if BASIC_SIMULATOR
/* this is required for the basic simulator in TDD mode
* TODO: find a proper cleaner solution
*/
ru->N_TA_offset = 0;
#endif
if(IS_SOFTMODEM_BASICSIM)
/* this is required for the basic simulator in TDD mode
* TODO: find a proper cleaner solution
*/
ru->N_TA_offset = 0;
}
if (ru->openair0_cfg.mmapped_dma == 1) {
+14
View File
@@ -58,6 +58,8 @@ void get_common_options(void) {
uint32_t noS1;
uint32_t nokrnmod;
uint32_t nonbiot;
uint32_t rfsim;
uint32_t basicsim;
paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
checkedparam_t cmdline_log_CheckParams[] = CMDLINE_LOGPARAMS_CHECK_DESC;
@@ -90,6 +92,18 @@ void get_common_options(void) {
set_softmodem_optmask(SOFTMODEM_NONBIOT_BIT);
}
if (rfsim) {
set_softmodem_optmask(SOFTMODEM_RFSIM_BIT);
}
if (basicsim) {
set_softmodem_optmask(SOFTMODEM_BASICSIM_BIT);
}
#if BASIC_SIMULATOR
set_softmodem_optmask(SOFTMODEM_BASICSIM_BIT);
#endif
if(parallel_config != NULL) set_parallel_conf(parallel_config);
if(worker_config != NULL) set_worker_conf(worker_config);
+6 -1
View File
@@ -653,9 +653,14 @@ int main( int argc, char **argv ) {
LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
printf("Runtime table\n");
fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
pdcp_module_init( ( IS_SOFTMODEM_NOS1 && !(IS_SOFTMODEM_NOKRNMOD))? (PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT);
uint32_t pdcp_initmask = ( IS_SOFTMODEM_NOS1 )? ( PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT) : LINK_ENB_PDCP_TO_GTPV1U_BIT;
#
if ( IS_SOFTMODEM_NOS1)
pdcp_initmask = pdcp_initmask | ENB_NAS_USE_TUN_BIT | SOFTMODEM_NOKRNMOD_BIT ;
pdcp_module_init(pdcp_initmask);
if (RC.nb_inst > 0) {
// don't create if node doesn't connect to RRC/S1/GTP
if (create_tasks(1) < 0) {
+7 -3
View File
@@ -87,6 +87,7 @@
#define CONFIG_HLP_PARALLEL_CMD "three config for level of parallelism 'PARALLEL_SINGLE_THREAD', 'PARALLEL_RU_L1_SPLIT', or 'PARALLEL_RU_L1_TRX_SPLIT'\n"
#define CONFIG_HLP_WORKER_CMD "two option for worker 'WORKER_DISABLE' or 'WORKER_ENABLE'\n"
#define CONFIG_HLP_NOS1 "Disable s1 interface\n"
#define CONFIG_HLP_RFSIM "Run in rf simulator mode (also known as basic simulator)\n"
#define CONFIG_HLP_NOKRNMOD "(noS1 only): Use tun instead of namesh module \n"
#define CONFIG_HLP_DISABLNBIOT "disable nb-iot, even if defined in config\n"
@@ -199,7 +200,9 @@
{"numerology" , CONFIG_HLP_NUMEROLOGY, PARAMFLAG_BOOL, iptr:&NUMEROLOGY, defintval:0, TYPE_INT, 0}, \
{"parallel-config", CONFIG_HLP_PARALLEL_CMD,0, strptr:(char **)&parallel_config, defstrval:NULL, TYPE_STRING, 0}, \
{"worker-config", CONFIG_HLP_WORKER_CMD, 0, strptr:(char **)&worker_config, defstrval:NULL, TYPE_STRING, 0}, \
{"noS1", CONFIG_HLP_NOS1, PARAMFLAG_BOOL, uptr:&noS1, defintval:0, TYPE_INT, 0}, \
{"noS1", CONFIG_HLP_NOS1, PARAMFLAG_BOOL, uptr:&noS1, defintval:0, TYPE_INT, 0}, \
{"rfsim", CONFIG_HLP_RFSIM, PARAMFLAG_BOOL, uptr:&rfsim, defintval:0, TYPE_INT, 0}, \
{"basicsim", CONFIG_HLP_RFSIM, PARAMFLAG_BOOL, uptr:&basicsim, defintval:0, TYPE_INT, 0}, \
{"nokrnmod", CONFIG_HLP_NOKRNMOD, PARAMFLAG_BOOL, uptr:&nokrnmod, defintval:0, TYPE_INT, 0}, \
{"nbiot-disable", CONFIG_HLP_DISABLNBIOT, PARAMFLAG_BOOL, uptr:&nonbiot, defuintval:0, TYPE_INT, 0}, \
}
@@ -238,8 +241,8 @@
#define SOFTMODEM_NOS1_BIT (1<<0)
#define SOFTMODEM_NOKRNMOD_BIT (1<<1)
#define SOFTMODEM_NONBIOT_BIT (1<<2)
#define SOFTMODEM_BASICSIM_BIT (1<<10)
#define SOFTMODEM_RFSIM_BIT (1<<10)
#define SOFTMODEM_BASICSIM_BIT (1<<11)
typedef struct {
uint64_t optmask;
THREAD_STRUCT thread_struct;
@@ -260,6 +263,7 @@ typedef struct {
#define IS_SOFTMODEM_NOS1 ( get_softmodem_optmask() & SOFTMODEM_NOS1_BIT)
#define IS_SOFTMODEM_NOKRNMOD ( get_softmodem_optmask() & SOFTMODEM_NOKRNMOD_BIT)
#define IS_SOFTMODEM_NONBIOT ( get_softmodem_optmask() & SOFTMODEM_NONBIOT_BIT)
#define IS_SOFTMODEM_RFSIM ( get_softmodem_optmask() & SOFTMODEM_RFSIM_BIT)
#define IS_SOFTMODEM_BASICSIM ( get_softmodem_optmask() & SOFTMODEM_BASICSIM_BIT)
extern uint64_t get_softmodem_optmask(void);
extern uint64_t set_softmodem_optmask(uint64_t bitmask);
+1066 -1091
View File
File diff suppressed because it is too large Load Diff
+5 -10
View File
@@ -441,10 +441,6 @@ static void get_options(void) {
if (dumpframe > 0) mode = rx_dump_frame;
# if BASIC_SIMULATOR
set_softmodem_optmask(SOFTMODEM_BASICSIM_BIT); //this BASIC_SIMULATOR should be a config option
# endif
for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0];
}
@@ -755,7 +751,6 @@ int main( int argc, char **argv ) {
cpuf=get_cpu_freq_GHz();
pthread_cond_init(&sync_cond,NULL);
pthread_mutex_init(&sync_mutex, NULL);
#if defined(ENABLE_ITTI)
printf("ITTI init\n");
itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
@@ -765,22 +760,22 @@ int main( int argc, char **argv ) {
}
MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
#endif
init_opt();
uint32_t pdcp_initmask = ((!IS_SOFTMODEM_NOS1) || IS_SOFTMODEM_NOKRNMOD)? LINK_ENB_PDCP_TO_GTPV1U_BIT : (LINK_ENB_PDCP_TO_GTPV1U_BIT | PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT);
uint32_t pdcp_initmask = (!IS_SOFTMODEM_NOS1 )? LINK_ENB_PDCP_TO_GTPV1U_BIT : (LINK_ENB_PDCP_TO_GTPV1U_BIT | PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT);
if ( IS_SOFTMODEM_BASICSIM || (nfapi_mode == 3) ) {
if ( IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM || (nfapi_mode == 3) ) {
pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;
}
if ( IS_SOFTMODEM_NOKRNMOD)
pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;
pdcp_module_init( pdcp_initmask );
//TTN for D2D
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
printf ("RRC control socket\n");
rrc_control_socket_init();
printf ("PDCP PC5S socket\n");
pdcp_pc5_socket_init();
#endif
// to make a graceful exit when ctrl-c is pressed
signal(SIGSEGV, signal_handler);
signal(SIGINT, signal_handler);