Commit 27aa036f authored by Robert Schmidt's avatar Robert Schmidt

Merge remote-tracking branch 'origin/iqreplay_bugfix' into integration_2022_wk08

parents a5fd5c3e cffb27b0
...@@ -58,10 +58,9 @@ int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_ ...@@ -58,10 +58,9 @@ int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_
// Use mmap for IQ files for systems with less than 6GB total RAM // Use mmap for IQ files for systems with less than 6GB total RAM
sysinfo(&systeminfo); sysinfo(&systeminfo);
if (systeminfo.totalram < 6144000000) { if (systeminfo.totalram < 6144000000 && ((*recplay_conf)->use_mmap == 1)) {
(*recplay_state)->use_mmap = 0; LOG_W(HW,"System with %f GB of mem (<6GB), mmap usage disabled\n",systeminfo.totalram/10E9);
} else { (*recplay_conf)->use_mmap = 0;
(*recplay_state)->use_mmap = 1;
} }
} else { /* record player enabled */ } else { /* record player enabled */
free(*recplay_conf); free(*recplay_conf);
......
...@@ -78,7 +78,7 @@ typedef struct { ...@@ -78,7 +78,7 @@ typedef struct {
#define CONFIG_HLP_SF_LOOPS "Number of loops to replay of the entire subframes file" #define CONFIG_HLP_SF_LOOPS "Number of loops to replay of the entire subframes file"
#define CONFIG_HLP_SF_RDELAY "Delay in microseconds to read a subframe in replay mode" #define CONFIG_HLP_SF_RDELAY "Delay in microseconds to read a subframe in replay mode"
#define CONFIG_HLP_SF_WDELAY "Delay in microseconds to write a subframe in replay mode" #define CONFIG_HLP_SF_WDELAY "Delay in microseconds to write a subframe in replay mode"
#define CONFIG_HLP_USE_MMAP "In replay mode, map iq file in memory before replaying"
/* keyword strings for config options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */ /* keyword strings for config options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */
#define CONFIG_OPT_SF_FILE "subframes-file" #define CONFIG_OPT_SF_FILE "subframes-file"
#define CONFIG_OPT_SF_REC "subframes-record" #define CONFIG_OPT_SF_REC "subframes-record"
...@@ -87,7 +87,7 @@ typedef struct { ...@@ -87,7 +87,7 @@ typedef struct {
#define CONFIG_OPT_SF_LOOPS "subframes-loops" #define CONFIG_OPT_SF_LOOPS "subframes-loops"
#define CONFIG_OPT_SF_RDELAY "subframes-read-delay" #define CONFIG_OPT_SF_RDELAY "subframes-read-delay"
#define CONFIG_OPT_SF_WDELAY "subframes-write-delay" #define CONFIG_OPT_SF_WDELAY "subframes-write-delay"
#define CONFIG_OPT_USE_MMAP "use-mmap"
#define DEVICE_RECPLAY_SECTION "device.recplay" #define DEVICE_RECPLAY_SECTION "device.recplay"
/* For information only - the macro is not usable in C++ */ /* For information only - the macro is not usable in C++ */
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
...@@ -102,6 +102,7 @@ typedef struct { ...@@ -102,6 +102,7 @@ typedef struct {
{CONFIG_OPT_SF_LOOPS, CONFIG_HLP_SF_LOOPS, 0, uptr:&((*recplay_conf)->u_sf_loops), defintval:DEF_SF_NB_LOOP, TYPE_UINT, 0}, \ {CONFIG_OPT_SF_LOOPS, CONFIG_HLP_SF_LOOPS, 0, uptr:&((*recplay_conf)->u_sf_loops), defintval:DEF_SF_NB_LOOP, TYPE_UINT, 0}, \
{CONFIG_OPT_SF_RDELAY, CONFIG_HLP_SF_RDELAY, 0, uptr:&((*recplay_conf)->u_sf_read_delay), defintval:DEF_SF_DELAY_READ, TYPE_UINT, 0}, \ {CONFIG_OPT_SF_RDELAY, CONFIG_HLP_SF_RDELAY, 0, uptr:&((*recplay_conf)->u_sf_read_delay), defintval:DEF_SF_DELAY_READ, TYPE_UINT, 0}, \
{CONFIG_OPT_SF_WDELAY, CONFIG_HLP_SF_WDELAY, 0, uptr:&((*recplay_conf)->u_sf_write_delay), defintval:DEF_SF_DELAY_WRITE, TYPE_UINT, 0}, \ {CONFIG_OPT_SF_WDELAY, CONFIG_HLP_SF_WDELAY, 0, uptr:&((*recplay_conf)->u_sf_write_delay), defintval:DEF_SF_DELAY_WRITE, TYPE_UINT, 0}, \
{CONFIG_OPT_USE_MMAP, CONFIG_HLP_USE_MMAP, PARAMFLAG_BOOL, uptr:&((*recplay_conf)->use_mmap), defuintval:1, TYPE_UINT, 0}, \
}/*! \brief Record Player Configuration and state */ }/*! \brief Record Player Configuration and state */
typedef struct { typedef struct {
char u_sf_filename[1024]; // subframes file path char u_sf_filename[1024]; // subframes file path
...@@ -109,10 +110,10 @@ typedef struct { ...@@ -109,10 +110,10 @@ typedef struct {
unsigned int u_sf_loops ; // number of loops in replay mode unsigned int u_sf_loops ; // number of loops in replay mode
unsigned int u_sf_read_delay; // read delay in replay mode unsigned int u_sf_read_delay; // read delay in replay mode
unsigned int u_sf_write_delay ; // write delay in replay mode unsigned int u_sf_write_delay ; // write delay in replay mode
unsigned int use_mmap; // default is to use mmap
} recplay_conf_t; } recplay_conf_t;
typedef struct { typedef struct {
int use_mmap; // default is to use mmap
size_t mapsize; size_t mapsize;
FILE *pFile; FILE *pFile;
int fd; int fd;
......
# I/Q record-playback # I/Q record-playback
## using the iq recorder or iq player ## using the iq recorder or iq player
This feature provides I/Q record-playback as presented in the 4th OAI workshop. Tests have only been performed with a eNB, but the implementation should allow any softmodem executable to use the iq's record/player. This feature provides I/Q record-playback as presented in the 4th OAI workshop. The implementation allows any softmodem executable to use the iq's record/player.
The I/Q record/playback feature is briefly described hereafter, it allows you to: The I/Q record/playback feature is briefly described hereafter, it allows you to:
* record subframes received by the USRP board in a file while the system is operating (for example you can record a full UE connection/traffic/ disconnection sequence). Today the oai USRP device is the only one supporting the recording feature. * record subframes received by the USRP board in a file while the system is operating (for example you can record a full UE connection/traffic/ disconnection sequence). Today the oai USRP device is the only one supporting the recording feature.
* replay subframes from a file to operate the system (possibly in multiple loops if the recorded sequence is convenient from the logical point of view). * replay subframes from a file to operate the system (possibly in multiple loops if the recorded sequence is convenient from the logical point of view).
...@@ -75,7 +75,7 @@ U[HW]I ru thread Writing file header to /tmp/iqfile ...@@ -75,7 +75,7 @@ U[HW]I ru thread Writing file header to /tmp/iqfile
``` ```
### Playback/replay mode ### Playback/replay mode
The option works only for 5MHz bandwidth because the information stored in the iq's file header regarding bandwidth is not yet properly processed. When replaying iq's received by eNB or gNB The option works only for 5MHz bandwidth because the information stored in the iq's file header regarding bandwidth is not yet properly processed.
In this version, mismatch between file content and run time parameters might lead to unpredictable results. In addition a file recorded on a AVX2-capable processor cannot be replayed on a non-AVX2-capable processor (this is to be further investigated). In this version, mismatch between file content and run time parameters might lead to unpredictable results. In addition a file recorded on a AVX2-capable processor cannot be replayed on a non-AVX2-capable processor (this is to be further investigated).
options for replay mode are: options for replay mode are:
* `subframes-replay` Activate replay mode * `subframes-replay` Activate replay mode
...@@ -83,6 +83,7 @@ options for replay mode are: ...@@ -83,6 +83,7 @@ options for replay mode are:
* `subframes-loops` Number of iterations to replay the entire subframes file (default is 5) * `subframes-loops` Number of iterations to replay the entire subframes file (default is 5)
* `subframes-read-delay` Delay in microseconds to read a subframe in replay mode (default 200) * `subframes-read-delay` Delay in microseconds to read a subframe in replay mode (default 200)
* `subframes-write-delay` Delay in milliseconds to write a subframe in replay mode (default 15) * `subframes-write-delay` Delay in milliseconds to write a subframe in replay mode (default 15)
* `use-mmap` Boolean, set to 1 (true) by default, iq file is map to memory if true, otherwise iq's are read from file.
>iq player session example: >iq player session example:
```bash ```bash
......
...@@ -68,19 +68,18 @@ static int iqplayer_loadfile(openair0_device *device, openair0_config_t *openair ...@@ -68,19 +68,18 @@ static int iqplayer_loadfile(openair0_device *device, openair0_config_t *openair
exit(-1); exit(-1);
} }
if (s->use_mmap) { if (c->use_mmap) {
// use mmap // use mmap
s->mapsize=sb.st_size; s->mapsize=sb.st_size;
LOG_I(HW,"Loading subframes using mmap() from %s size=%lu bytes ...\n",c->u_sf_filename, (uint64_t)sb.st_size ); LOG_I(HW,"Loading subframes using mmap() from %s size=%lu bytes ...\n",c->u_sf_filename, (uint64_t)sb.st_size );
void *mptr = mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, s->fd, 0) ; void *mptr = mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, s->fd, 0) ;
s->ms_sample = (iqrec_t *) ( mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, s->fd, 0) + sizeof(iqfile_header_t));
if (mptr != MAP_FAILED) { if (mptr != MAP_FAILED) {
s->ms_sample = (iqrec_t *) ( mptr + sizeof(iqfile_header_t));
parse_iqfile_header(device, (iqfile_header_t *)mptr); parse_iqfile_header(device, (iqfile_header_t *)mptr);
s->ms_sample = (iqrec_t *)((char *)mptr + sizeof(iqfile_header_t)); s->ms_sample = (iqrec_t *)((char *)mptr + sizeof(iqfile_header_t));
LOG_I(HW,"Loaded %u subframes.\n",s->nbSamplesBlocks ); LOG_I(HW,"Loaded %u subframes.\n",s->nbSamplesBlocks );
} else { } else {
LOG_E(HW,"Cannot mmap file, exiting.\n"); LOG_E(HW,"Cannot mmap file, exiting, errnor %s\n",strerror(errno));
close(s->fd); close(s->fd);
exit(-1); exit(-1);
} }
...@@ -108,7 +107,7 @@ static int iqplayer_loadfile(openair0_device *device, openair0_config_t *openair ...@@ -108,7 +107,7 @@ static int iqplayer_loadfile(openair0_device *device, openair0_config_t *openair
if (lseek(s->fd,sizeof(iqfile_header_t), SEEK_SET) == 0) { if (lseek(s->fd,sizeof(iqfile_header_t), SEEK_SET) == 0) {
LOG_I(HW,"Initial seek at beginning of the file\n" ); LOG_I(HW,"Initial seek at beginning of the file\n" );
} else { } else {
LOG_I(HW,"Problem initial seek at beginning of the file\n"); LOG_I(HW,"Problem initial seek at beginning of the file, %s\n",strerror(errno));
} }
} else { } else {
LOG_E(HW,"Cannot read header in %s exiting.\n",c->u_sf_filename ); LOG_E(HW,"Cannot read header in %s exiting.\n",c->u_sf_filename );
...@@ -134,11 +133,10 @@ static int trx_iqplayer_start(openair0_device *device) { ...@@ -134,11 +133,10 @@ static int trx_iqplayer_start(openair0_device *device) {
static void trx_iqplayer_end(openair0_device *device) { static void trx_iqplayer_end(openair0_device *device) {
if (device == NULL) if (device == NULL)
return; return;
if (device->recplay_state == NULL) if (device->recplay_state == NULL)
return; return;
if (device->recplay_state->use_mmap) { if (device->openair0_cfg->recplay_conf->use_mmap) {
if (device->recplay_state->ms_sample != MAP_FAILED) { if (device->recplay_state->ms_sample != MAP_FAILED) {
munmap(device->recplay_state->ms_sample, device->recplay_state->mapsize); munmap(device->recplay_state->ms_sample, device->recplay_state->mapsize);
} }
...@@ -201,21 +199,22 @@ static int trx_iqplayer_read(openair0_device *device, openair0_timestamp *ptimes ...@@ -201,21 +199,22 @@ static int trx_iqplayer_read(openair0_device *device, openair0_timestamp *ptimes
LOG_I(HW,"go back at the beginning of IQ file"); LOG_I(HW,"go back at the beginning of IQ file");
device->recplay_state->currentPtr=(uint8_t *)device->recplay_state->ms_sample; device->recplay_state->currentPtr=(uint8_t *)device->recplay_state->ms_sample;
if (!s->use_mmap) { if (!(device->openair0_cfg->recplay_conf->use_mmap) ) {
if (lseek(device->recplay_state->fd, 0, SEEK_SET) != 0) { close(device->recplay_state->fd);
LOG_E(HW, "Problem seeking at the beginning of IQ file"); iqplayer_loadfile(device, device->openair0_cfg);
} // LOG_E(HW, "Problem seeking at the beginning of IQ file %s\n",strerror(errno));
} }
} }
if (!s->use_mmap) { if (!(device->openair0_cfg->recplay_conf->use_mmap)) {
// read sample from file // read sample from file
if (read(s->fd, s->ms_sample, sizeof(iqrec_t)) != sizeof(iqrec_t)) { if (read(s->fd, s->ms_sample, sizeof(iqrec_t)) != sizeof(iqrec_t)) {
LOG_E(HW,"pb reading iqfile at index %lu\n",sizeof(iqrec_t)*s->curSamplesBlock ); LOG_E(HW,"pb reading iqfile at index %lu %s\n",sizeof(iqrec_t)*s->curSamplesBlock, strerror(errno) );
exit(-1); exit(-1);
} else { } else {
if (read(s->fd, s->ms_sample+1, s->ms_sample->nbBytes) != s->ms_sample->nbBytes) { if (read(s->fd, s->ms_sample+1, s->ms_sample->nbBytes) != s->ms_sample->nbBytes) {
LOG_E(HW,"pb reading iqfile at index %lu\n",sizeof(iqrec_t)*s->curSamplesBlock ); LOG_E(HW,"pb reading iqfile at index %lu %s\n",sizeof(iqrec_t)*s->curSamplesBlock, strerror(errno) );
exit(-1); exit(-1);
} }
} }
...@@ -225,7 +224,9 @@ static int trx_iqplayer_read(openair0_device *device, openair0_timestamp *ptimes ...@@ -225,7 +224,9 @@ static int trx_iqplayer_read(openair0_device *device, openair0_timestamp *ptimes
AssertFatal(curHeader->header==BELL_LABS_IQ_HEADER,"" ); AssertFatal(curHeader->header==BELL_LABS_IQ_HEADER,"" );
// the current timestamp is the stored timestamp until we wrap on input // the current timestamp is the stored timestamp until we wrap on input
// USRP shifts 1 sample time to time // USRP shifts 1 sample time to time
AssertFatal(s->wrap_count !=0 || abs(curHeader->ts-s->currentTs) < 5 ,""); if (s->wrap_count !=0 && device->openair0_cfg->recplay_conf->use_mmap)
AssertFatal( abs(curHeader->ts-s->currentTs) < 5 ,
"wrap_count=%li, ts %lu %lu",s->wrap_count,curHeader->ts,s->currentTs);
AssertFatal(nsamps*4==curHeader->nbBytes,""); AssertFatal(nsamps*4==curHeader->nbBytes,"");
*ptimestamp = s->currentTs; *ptimestamp = s->currentTs;
memcpy(buff[0], curHeader+1, nsamps*4); memcpy(buff[0], curHeader+1, nsamps*4);
...@@ -233,7 +234,7 @@ static int trx_iqplayer_read(openair0_device *device, openair0_timestamp *ptimes ...@@ -233,7 +234,7 @@ static int trx_iqplayer_read(openair0_device *device, openair0_timestamp *ptimes
// Prepare for next read // Prepare for next read
s->currentTs+=nsamps; s->currentTs+=nsamps;
if (s->use_mmap) if (device->openair0_cfg->recplay_conf->use_mmap)
s->currentPtr+=sizeof(iqrec_t)+s->ms_sample->nbBytes; s->currentPtr+=sizeof(iqrec_t)+s->ms_sample->nbBytes;
struct timespec req; struct timespec req;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment