rfsimulator: add support for providing different parameters to each instance

This commit is contained in:
Thomas Schlichter
2026-01-27 11:30:16 +01:00
parent ce83a78271
commit 4d215b5c95
3 changed files with 75 additions and 32 deletions
+1
View File
@@ -311,6 +311,7 @@ void nrue_init_openair0(void)
cfg->duplex_mode = duplex_mode_FDD;
cfg->Mod_id = 0;
cfg->ru_id = ru_id;
cfg->num_rb_dl = frame_parms->N_RB_DL;
cfg->tx_num_channels = min(4, frame_parms->nb_antennas_tx);
cfg->rx_num_channels = min(4, frame_parms->nb_antennas_rx);
+2
View File
@@ -212,6 +212,8 @@ typedef struct split7_config {
typedef struct openair0_config {
//! Module ID for this configuration
int Mod_id;
//! RU ID of this device
int ru_id;
//! duplexing mode
duplex_mode_t duplex_mode;
//! number of downlink resource blocks
+72 -32
View File
@@ -81,7 +81,19 @@ typedef enum { SIMU_ROLE_SERVER = 1, SIMU_ROLE_CLIENT } simuRole;
//
#define RFSIMU_SECTION "rfsimulator"
#define RFSIMU_SERVER_ADDR "serveraddr"
#define RFSIMU_SERVER_PORT "serverport"
#define RFSIMU_OPTIONS_PARAMNAME "options"
#define RFSIMU_IQFILE "IQfile"
#define RFSIMU_MODELNAME "modelname"
#define RFSIMU_PLOSS "ploss"
#define RFSIMU_FORGETFACT "forgetfact"
#define RFSIMU_OFFSET "offset"
#define RFSIMU_PROP_DELAY "prop_delay"
#define RFSIMU_WAIT_TIMEOUT "wait_timeout"
#define RFSIMU_ENABLE_BEAMS "enable_beams"
#define RFSIMU_NUM_CONCURRENT_BEAMS "num_concurrent_beams"
#define RFSIMU_BEAM_MAP "beam_map"
#define RFSIMU_BEAM_GAINS "beam_gains"
#define RFSIMU_BEAM_IDS "beam_ids"
@@ -98,19 +110,19 @@ typedef enum { SIMU_ROLE_SERVER = 1, SIMU_ROLE_CLIENT } simuRole;
/* optname helpstr paramflags XXXptr defXXXval */
/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
#define RFSIMULATOR_PARAMS_DESC { \
STRINGPARAM("serveraddr", "<ip address to connect to>\n", simOpt, &rfsimulator->ip, "127.0.0.1"), \
UINT16PARAM("serverport", "<port to connect to>\n", simOpt, &rfsimulator->port, PORT), \
STRINGPARAM(RFSIMU_SERVER_ADDR, "<ip address to connect to>\n", simOpt, NULL, "127.0.0.1"), \
UINT16PARAM(RFSIMU_SERVER_PORT, "<port to connect to>\n", simOpt, NULL, PORT), \
STRLISTPARAM(RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, simOpt, NULL, NULL), \
STRINGPARAM("IQfile", "<file path to use when saving IQs>\n", simOpt, &saveF, "/tmp/rfsimulator.iqs"),\
STRINGPARAM("modelname", "<channel model name>\n", simOpt, &modelname, "AWGN"), \
DOUBLEPARAM("ploss", "<channel path loss in dB>\n", simOpt, &rfsimulator->chan_pathloss, 0), \
DOUBLEPARAM("forgetfact", "<channel forget factor ((0 to 1)>\n", simOpt, &rfsimulator->chan_forgetfact, 0), \
UINT64PARAM("offset", "<channel offset in samps>\n", simOpt, &rfsimulator->chan_offset, 0L), \
DOUBLEPARAM("prop_delay", "<propagation delay in ms>\n", simOpt, &(rfsimulator->prop_delay_ms), 0.0), \
INTPARAM("wait_timeout", "<wait timeout if no UE connected>\n", simOpt, &rfsimulator->wait_timeout, 1), \
BOOLPARAM("enable_beams", "<enable simplified beam simulation>\n", simBool,&(beam_ctrl->enable_beams), 0), \
INTPARAM("num_concurrent_beams", "<number of concurrent beams supported>\n", simOpt, &beam_ctrl->num_concurrent_beams, 1), \
UINT64PARAM("beam_map", "<initial beam map>\n", simOpt, &beam_map, 1), \
STRINGPARAM(RFSIMU_IQFILE, "<file path to use when saving IQs>\n", simOpt, NULL, "/tmp/rfsimulator.iqs"),\
STRINGPARAM(RFSIMU_MODELNAME, "<channel model name>\n", simOpt, NULL, "AWGN"), \
DOUBLEPARAM(RFSIMU_PLOSS, "<channel path loss in dB>\n", simOpt, NULL, 0), \
DOUBLEPARAM(RFSIMU_FORGETFACT, "<channel forget factor ((0 to 1)>\n", simOpt, NULL, 0), \
UINT64PARAM(RFSIMU_OFFSET, "<channel offset in samps>\n", simOpt, NULL, 0L), \
DOUBLEPARAM(RFSIMU_PROP_DELAY, "<propagation delay in ms>\n", simOpt, NULL, 0.0), \
INTPARAM(RFSIMU_WAIT_TIMEOUT, "<wait timeout if no UE connected>\n", simOpt, NULL, 1), \
BOOLPARAM(RFSIMU_ENABLE_BEAMS, "<enable simplified beam simulation>\n", simBool,NULL, 0), \
INTPARAM(RFSIMU_NUM_CONCURRENT_BEAMS, "<number of concurrent beams supported>\n", simOpt, NULL, 1), \
UINT64PARAM(RFSIMU_BEAM_MAP, "<initial beam map>\n", simOpt, NULL, 1), \
STRINGPARAM(RFSIMU_BEAM_IDS, "<initial beam ids>\n", simOpt, NULL, NULL), \
STRINGPARAM(RFSIMU_BEAM_GAINS, "<beam gain matrix in toeplitz form>\n", simOpt, NULL, NULL), \
};
@@ -182,6 +194,7 @@ typedef struct {
typedef struct {
int listen_sock, epollfd;
pthread_mutex_t Sockmutex;
int ru_id;
unsigned int nb_cnx;
openair0_timestamp_t nextRxTstamp;
openair0_timestamp_t lastWroteTS;
@@ -354,7 +367,7 @@ static buffer_t *allocCirBuf(rfsimulator_state_t *bridge, int sock)
sizeofArray(modelname),
"rfsimu_channel_%s%d",
(bridge->role == SIMU_ROLE_SERVER) ? "ue" : "enB",
bridge->nb_cnx - 1);
(bridge->role == SIMU_ROLE_SERVER) ? bridge->nb_cnx - 1 : bridge->ru_id);
ptr->channel_model = find_channel_desc_fromname(modelname); // path_loss in dB
if (!ptr->channel_model) {
// Use legacy method to find channel model - this will use the same channel model for all clients
@@ -520,19 +533,45 @@ static void process_gains(char *str, rfsim_beam_ctrl_t *beam_ctrl)
static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator)
{
char *saveF = NULL;
char *modelname = NULL;
configmodule_interface_t *cfg = config_get_if();
paramdef_t *rfsimuParam;
paramdef_t rfsimuParams[] = RFSIMULATOR_PARAMS_DESC;
paramlist_def_t rfsimuParamList = {RFSIMU_SECTION, NULL, 0};
int ret = config_getlist(cfg, &rfsimuParamList, rfsimuParams, sizeofArray(rfsimuParams), NULL);
if (ret < 0 || rfsimuParamList.numelt <= 0) {
ret = config_get(cfg, rfsimuParams, sizeofArray(rfsimuParams), RFSIMU_SECTION);
AssertFatal(ret >= 0, "configuration couldn't be performed\n");
LOG_W(HW, "Warning: rfsimulator parameters should be provided as array elements!\n");
rfsimuParam = rfsimuParams;
} else {
int ru_id = rfsimulator->ru_id;
AssertFatal(rfsimuParamList.numelt > ru_id,
"no rfsimulator parameters (numelt %d) specified for card %d\n",
rfsimuParamList.numelt,
ru_id);
rfsimuParam = rfsimuParamList.paramarray[ru_id];
}
rfsimulator->ip = strdup(*(gpd(rfsimuParam, sizeofArray(rfsimuParams), RFSIMU_SERVER_ADDR)->strptr));
rfsimulator->port = *(gpd(rfsimuParam, sizeofArray(rfsimuParams), RFSIMU_SERVER_PORT)->u16ptr);
char *saveF = strdup(*(gpd(rfsimuParam, sizeofArray(rfsimuParams), RFSIMU_IQFILE)->strptr));
//char *modelname = strdup(*(gpd(rfsimuParam, sizeofArray(rfsimuParams), RFSIMU_MODELNAME)->strptr));
rfsimulator->chan_pathloss = *(gpd(rfsimuParam, sizeofArray(rfsimuParams), RFSIMU_PLOSS)->dblptr);
rfsimulator->chan_forgetfact = *(gpd(rfsimuParam, sizeofArray(rfsimuParams), RFSIMU_FORGETFACT)->dblptr);
rfsimulator->chan_offset = *(gpd(rfsimuParam, sizeofArray(rfsimuParams), RFSIMU_OFFSET)->u64ptr);
rfsimulator->prop_delay_ms = *(gpd(rfsimuParam, sizeofArray(rfsimuParams), RFSIMU_PROP_DELAY)->dblptr);
rfsimulator->wait_timeout = *(gpd(rfsimuParam, sizeofArray(rfsimuParams), RFSIMU_WAIT_TIMEOUT)->iptr);
rfsim_beam_ctrl_t *beam_ctrl = rfsimulator->beam_ctrl;
uint64_t beam_map = 1;
paramdef_t rfsimu_params[] = RFSIMULATOR_PARAMS_DESC;
int p = config_paramidx_fromname(rfsimu_params, sizeofArray(rfsimu_params), RFSIMU_OPTIONS_PARAMNAME);
int ret = config_get(config_get_if(), rfsimu_params, sizeofArray(rfsimu_params), RFSIMU_SECTION);
AssertFatal(ret >= 0, "configuration couldn't be performed\n");
beam_ctrl->enable_beams = *(gpd(rfsimuParam, sizeofArray(rfsimuParams), RFSIMU_ENABLE_BEAMS)->iptr);
beam_ctrl->num_concurrent_beams = *(gpd(rfsimuParam, sizeofArray(rfsimuParams), RFSIMU_NUM_CONCURRENT_BEAMS)->iptr);
uint64_t beam_map = *(gpd(rfsimuParam, sizeofArray(rfsimuParams), RFSIMU_BEAM_MAP)->u64ptr);
rfsimulator->saveIQfile = -1;
for (int i = 0; i < rfsimu_params[p].numelt; i++) {
if (strcmp(rfsimu_params[p].strlistptr[i], "saviq") == 0) {
int p = config_paramidx_fromname(rfsimuParams, sizeofArray(rfsimuParams), RFSIMU_OPTIONS_PARAMNAME);
for (int i = 0; i < rfsimuParam[p].numelt; i++) {
if (strcmp(rfsimuParam[p].strlistptr[i], "saviq") == 0) {
rfsimulator->saveIQfile = open(saveF, O_APPEND | O_CREAT | O_TRUNC | O_WRONLY, 0666);
if (rfsimulator->saveIQfile != -1)
@@ -543,7 +582,7 @@ static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator)
}
break;
} else if (strcmp(rfsimu_params[p].strlistptr[i], "chanmod") == 0) {
} else if (strcmp(rfsimuParam[p].strlistptr[i], "chanmod") == 0) {
init_channelmod();
load_channellist(rfsimulator->tx_num_channels,
rfsimulator->rx_num_channels,
@@ -552,24 +591,24 @@ static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator)
rfsimulator->tx_bw);
rfsimulator->channelmod = true;
} else {
fprintf(stderr, "unknown rfsimulator option: %s\n", rfsimu_params[p].strlistptr[i]);
fprintf(stderr, "unknown rfsimulator option: %s\n", rfsimuParam[p].strlistptr[i]);
exit(-1);
}
}
int beam_gains_param_index = config_paramidx_fromname(rfsimu_params, sizeofArray(rfsimu_params), RFSIMU_BEAM_GAINS);
if (rfsimu_params[beam_gains_param_index].strptr) {
process_gains(*rfsimu_params[beam_gains_param_index].strptr, beam_ctrl);
int beam_gains_param_index = config_paramidx_fromname(rfsimuParams, sizeofArray(rfsimuParams), RFSIMU_BEAM_GAINS);
if (rfsimuParam[beam_gains_param_index].strptr) {
process_gains(*rfsimuParam[beam_gains_param_index].strptr, beam_ctrl);
}
std::vector<int> initial_beams = beam_map_to_beams(beam_map);
beam_ctrl->rx.beams = initial_beams;
beam_ctrl->tx.beams = initial_beams;
int beam_ids_param_index = config_paramidx_fromname(rfsimu_params, sizeofArray(rfsimu_params), RFSIMU_BEAM_IDS);
if (rfsimu_params[beam_ids_param_index].strptr) {
int beam_ids_param_index = config_paramidx_fromname(rfsimuParams, sizeofArray(rfsimuParams), RFSIMU_BEAM_IDS);
if (rfsimuParam[beam_ids_param_index].strptr) {
std::vector<int> beam_ids;
std::stringstream ss(*rfsimu_params[beam_ids_param_index].strptr);
std::stringstream ss(*rfsimuParam[beam_ids_param_index].strptr);
std::string token;
while (std::getline(ss, token, ',')) {
beam_ids.push_back(std::stoi(token));
@@ -1563,6 +1602,7 @@ extern "C" __attribute__((__visibility__("default"))) int device_init(openair0_d
// --log_config.hw_log_level debug
rfsimulator_state_t *rfsimulator = static_cast<rfsimulator_state_t *>(calloc(sizeof(rfsimulator_state_t), 1));
// initialize channel simulation
rfsimulator->ru_id = openair0_cfg->ru_id;
rfsimulator->tx_num_channels = openair0_cfg->tx_num_channels;
rfsimulator->rx_num_channels = openair0_cfg->rx_num_channels;
rfsimulator->sample_rate = openair0_cfg->sample_rate;
@@ -1596,8 +1636,8 @@ extern "C" __attribute__((__visibility__("default"))) int device_init(openair0_d
}
/* let's pretend to be a b2x0 */
device->type = RFSIMULATOR;
openair0_cfg[0].rx_gain[0] = 0;
device->openair0_cfg = &openair0_cfg[0];
openair0_cfg->rx_gain[0] = 0;
device->openair0_cfg = openair0_cfg;
device->priv = rfsimulator;
device->trx_write_init = rfsimulator_write_init;
device->trx_set_beams = rfsimulator_set_beams;