mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-15 13:40:29 +00:00
Compare commits
7 Commits
develop
...
nr-ue-rest
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb71140665 | ||
|
|
d8d2832141 | ||
|
|
36b0f09652 | ||
|
|
2b3d555059 | ||
|
|
0a0a784afb | ||
|
|
7ee1647e2f | ||
|
|
071d084e9d |
@@ -299,6 +299,7 @@ message(STATUS "Selected KPM Version: ${KPM_VERSION}")
|
||||
|
||||
|
||||
add_boolean_option(ENABLE_IMSCOPE OFF "Enable phy scope based on imgui" OFF)
|
||||
add_boolean_option(ENABLE_RESTAPI OFF "Build the REST API modules" OFF)
|
||||
|
||||
##################################################
|
||||
# ASN.1 grammar C code generation & dependencies #
|
||||
@@ -2371,6 +2372,24 @@ if(ENABLE_TESTS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
if (ENABLE_RESTAPI)
|
||||
# Find package defined here as the order of execution of cmake commands matters: this needs to happen before any
|
||||
find_package(nlohmann_json)
|
||||
if (NOT nlohmann_json_FOUND)
|
||||
message(STATUS "nlohmann_json is not found, will be downloaded automatically. To prevent that install nlohmann_json on your system (nlohmann-json3-dev)")
|
||||
CPMAddPackage("gh:nlohmann/json@3.11.3")
|
||||
else()
|
||||
if (NOT TARGET nlohmann_json::nlohmann_json)
|
||||
if (TARGET nlohman_json)
|
||||
add_library(nlohmann_json::nlohmann_json ALIAS nlohmann_json)
|
||||
else()
|
||||
message(FATAL_ERROR "Your nlohmann_json installation is faulty as it doesn't define any of the expected targets")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(common)
|
||||
add_subdirectory(doc)
|
||||
add_subdirectory(nfapi)
|
||||
@@ -2378,3 +2397,4 @@ add_subdirectory(openair1)
|
||||
add_subdirectory(openair2)
|
||||
add_subdirectory(openair3)
|
||||
add_subdirectory(radio)
|
||||
|
||||
|
||||
@@ -21,3 +21,6 @@ if (ENABLE_TESTS)
|
||||
endif()
|
||||
add_subdirectory(barrier)
|
||||
add_subdirectory(actor)
|
||||
if (ENABLE_RESTAPI)
|
||||
add_subdirectory(rest_api)
|
||||
endif()
|
||||
|
||||
21
common/utils/rest_api/CMakeLists.txt
Normal file
21
common/utils/rest_api/CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
CPMAddPackage("gh:chriskohlhoff/asio#asio-1-18-1@1.18.1")
|
||||
if (asio_ADDED)
|
||||
# asio has no CMake support, so we create our own target
|
||||
add_library(asio INTERFACE)
|
||||
add_library(asio::asio ALIAS asio)
|
||||
target_include_directories(asio SYSTEM INTERFACE ${asio_SOURCE_DIR}/asio/include)
|
||||
target_compile_definitions(asio INTERFACE ASIO_STANDALONE)
|
||||
endif()
|
||||
|
||||
CPMAddPackage(
|
||||
NAME Crow
|
||||
GIT_REPOSITORY https://github.com/CrowCpp/Crow.git
|
||||
GIT_TAG v1.2.0
|
||||
OPTIONS
|
||||
"CROW_INSTALL OFF"
|
||||
)
|
||||
|
||||
add_library(nr_ue_rest_api MODULE nr_ue_rest_api.cpp)
|
||||
target_include_directories(nr_ue_rest_api PUBLIC ./)
|
||||
target_link_libraries(nr_ue_rest_api PUBLIC Crow::Crow nr_ue_phy_rest_api_module shlib_loader nlohmann_json::nlohmann_json)
|
||||
set_target_properties(nr_ue_rest_api PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
63
common/utils/rest_api/nr_ue_rest_api.cpp
Normal file
63
common/utils/rest_api/nr_ue_rest_api.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <crow.h>
|
||||
#include "nr_ue_phy_rest_api_module.h"
|
||||
#include "system.h"
|
||||
#define PORT 11101
|
||||
|
||||
void* api_run(void*);
|
||||
|
||||
extern "C" {
|
||||
#include "common/utils/load_module_shlib.h"
|
||||
void nr_ue_rest_api_autoinit(void* arg)
|
||||
{
|
||||
char thread_name[] = "nr_ue_rest_api";
|
||||
pthread_t rest_api_thread;
|
||||
threadCreate(&rest_api_thread, api_run, arg, thread_name, -1, OAI_PRIORITY_RT_LOW);
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*regsiter_routes_ftype)(crow::Blueprint* bp);
|
||||
|
||||
void* api_run(void*)
|
||||
{
|
||||
crow::SimpleApp ue_rest_api;
|
||||
ue_rest_api.loglevel(crow::LogLevel::Warning);
|
||||
|
||||
CROW_ROUTE(ue_rest_api, "/healthcheck")([]() { return "OK"; });
|
||||
|
||||
crow::Blueprint phy_bp("phy");
|
||||
nr_ue::rest_api::phy::register_routes(&phy_bp);
|
||||
ue_rest_api.register_blueprint(phy_bp);
|
||||
|
||||
char rfsim[] = "rfsimulator";
|
||||
char register_routes[] = "register_routes";
|
||||
regsiter_routes_ftype rfsim_register_routes = (regsiter_routes_ftype)get_shlibmodule_fptr(rfsim, register_routes);
|
||||
crow::Blueprint rfsim_bp("rfsimulator");
|
||||
if (rfsim_register_routes) {
|
||||
rfsim_register_routes(&rfsim_bp);
|
||||
ue_rest_api.register_blueprint(rfsim_bp);
|
||||
}
|
||||
|
||||
ue_rest_api.port(PORT).run();
|
||||
return NULL;
|
||||
}
|
||||
@@ -539,6 +539,10 @@ int main(int argc, char **argv)
|
||||
printf("UE threads created by %ld\n", gettid());
|
||||
}
|
||||
|
||||
if (IS_SOFTMODEM_RESTAPI_ENABLED) {
|
||||
load_module_shlib("nr_ue_rest_api",NULL,0,NULL);
|
||||
}
|
||||
|
||||
// wait for end of program
|
||||
printf("TYPE <CTRL-C> TO TERMINATE\n");
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#define BIT_23 (1 << 23)
|
||||
#define BIT_24 (1 << 24)
|
||||
#define BIT_25 (1 << 25)
|
||||
#define BIT_26 (1 << 26)
|
||||
|
||||
#define SOFTMODEM_NOS1_BIT BIT_0
|
||||
#define SOFTMODEM_NOKRNMOD_BIT BIT_1
|
||||
@@ -56,6 +57,7 @@
|
||||
#define SOFTMODEM_5GUE_BIT BIT_23
|
||||
#define SOFTMODEM_NOSTATS_BIT BIT_24
|
||||
#define SOFTMODEM_IMSCOPE_BIT BIT_25
|
||||
#define SOFTMODEM_RESTAPI_BIT BIT_26
|
||||
// clang-format on
|
||||
|
||||
#endif // SOFTMODEM_BITS_H
|
||||
|
||||
@@ -100,6 +100,7 @@ void get_common_options(configmodule_interface_t *cfg, uint32_t execmask)
|
||||
uint32_t noS1 = 0, nonbiot = 0;
|
||||
uint32_t rfsim = 0, do_forms = 0;
|
||||
uint32_t enable_imscope = 0;
|
||||
uint32_t enable_rest_api = 0;
|
||||
int nfapi_index = 0;
|
||||
char *logmem_filename = NULL;
|
||||
check_execmask(execmask);
|
||||
@@ -163,6 +164,10 @@ void get_common_options(configmodule_interface_t *cfg, uint32_t execmask)
|
||||
set_softmodem_optmask(SOFTMODEM_IMSCOPE_BIT);
|
||||
}
|
||||
|
||||
if (enable_rest_api) {
|
||||
set_softmodem_optmask(SOFTMODEM_RESTAPI_BIT);
|
||||
}
|
||||
|
||||
if (start_websrv) {
|
||||
load_module_shlib("websrv", NULL, 0, NULL);
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ extern "C"
|
||||
#define CONFIG_HLP_CHESTFREQ "Set channel estimation type in frequency domain. 0-Linear interpolation (default). 1-PRB based averaging of channel estimates in frequency. \n"
|
||||
#define CONFIG_HLP_CHESTTIME "Set channel estimation type in time domain. 0-Symbols take estimates of the last preceding DMRS symbol (default). 1-Symbol based averaging of channel estimates in time. \n"
|
||||
#define CONFIG_HLP_IMSCOPE "Enable phy scope based on imgui and implot"
|
||||
#define CONFIG_HLP_RESTAPI "Enable REST API"
|
||||
|
||||
#define CONFIG_HLP_NONSTOP "Go back to frame sync mode after 100 consecutive PBCH failures\n"
|
||||
//#define CONFIG_HLP_NUMUES "Set the number of UEs for the emulation"
|
||||
@@ -187,6 +188,7 @@ extern int usrp_tx_thread;
|
||||
{"A" , CONFIG_HLP_TADV, 0, .iptr=&softmodem_params.command_line_sample_advance,.defintval=0, TYPE_INT, 0}, \
|
||||
{"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, .iptr=&softmodem_params.threequarter_fs, .defintval=0, TYPE_INT, 0}, \
|
||||
{"imscope" , CONFIG_HLP_IMSCOPE, PARAMFLAG_BOOL, .uptr=&enable_imscope, .defintval=0, TYPE_UINT, 0}, \
|
||||
{"rest-api" , CONFIG_HLP_RESTAPI, PARAMFLAG_BOOL, .uptr=&enable_rest_api, .defintval=0, TYPE_UINT, 0}, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -233,6 +235,7 @@ extern int usrp_tx_thread;
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
{ .s5 = { NULL } }, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
@@ -291,6 +294,7 @@ extern int usrp_tx_thread;
|
||||
#define IS_SOFTMODEM_5GUE_BIT ( get_softmodem_optmask() & SOFTMODEM_5GUE_BIT)
|
||||
#define IS_SOFTMODEM_NOSTATS_BIT ( get_softmodem_optmask() & SOFTMODEM_NOSTATS_BIT)
|
||||
#define IS_SOFTMODEM_IMSCOPE_ENABLED ( get_softmodem_optmask() & SOFTMODEM_IMSCOPE_BIT)
|
||||
#define IS_SOFTMODEM_RESTAPI_ENABLED ( get_softmodem_optmask() & SOFTMODEM_RESTAPI_BIT)
|
||||
|
||||
typedef struct {
|
||||
uint64_t optmask;
|
||||
|
||||
@@ -5,3 +5,9 @@ target_include_directories(nr_phy_common PUBLIC inc/)
|
||||
add_library(nr_ue_phy_meas src/nr_ue_phy_meas.c)
|
||||
target_include_directories(nr_ue_phy_meas PUBLIC inc/)
|
||||
target_link_libraries(nr_ue_phy_meas PUBLIC utils)
|
||||
|
||||
if (ENABLE_RESTAPI)
|
||||
add_library(nr_ue_phy_rest_api_module src/nr_ue_phy_rest_api_module.cpp)
|
||||
target_include_directories(nr_ue_phy_rest_api_module PUBLIC ./)
|
||||
target_link_libraries(nr_ue_phy_rest_api_module PUBLIC Crow::Crow nr_ue_phy_meas UTIL nlohmann_json::nlohmann_json)
|
||||
endif()
|
||||
|
||||
33
openair1/PHY/nr_phy_common/inc/nr_ue_phy_rest_api_module.h
Normal file
33
openair1/PHY/nr_phy_common/inc/nr_ue_phy_rest_api_module.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef NR_UE_PHY_REST_API_MODULE_H
|
||||
#define NR_UE_PHY_REST_API_MODULE_H
|
||||
|
||||
#include <crow.h>
|
||||
#include <string>
|
||||
|
||||
namespace nr_ue::rest_api::phy
|
||||
{
|
||||
void register_routes(crow::Blueprint* bp);
|
||||
}
|
||||
|
||||
#endif
|
||||
80
openair1/PHY/nr_phy_common/src/nr_ue_phy_rest_api_module.cpp
Normal file
80
openair1/PHY/nr_phy_common/src/nr_ue_phy_rest_api_module.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
#include <crow.h>
|
||||
#include <vector>
|
||||
#include "nr_ue_phy_rest_api_module.h"
|
||||
#include "nr_ue_phy_meas.h"
|
||||
#include "PHY/defs_nr_UE.h"
|
||||
#include "time_meas.h"
|
||||
|
||||
extern "C" {
|
||||
extern PHY_VARS_NR_UE ***PHY_vars_UE_g;
|
||||
}
|
||||
namespace nr_ue::rest_api::phy {
|
||||
nlohmann::json generate_meas_json(time_stats_t *stat)
|
||||
{
|
||||
return nlohmann::json({{"name", std::string(stat->meas_name)},
|
||||
{"count", std::uint64_t(stat->trials)},
|
||||
{"uS", (float)(stat->diff / (cpu_freq_GHz * 1000))}});
|
||||
}
|
||||
|
||||
void register_routes(crow::Blueprint *bp)
|
||||
{
|
||||
bp->new_rule_dynamic("/healthcheck")([]() { return crow::response(crow::status::OK, std::string("OK")); });
|
||||
bp->new_rule_dynamic("/cpumeas/<int>")([](int ue_index) {
|
||||
if (ue_index != 0) {
|
||||
return crow::response(crow::status::BAD_REQUEST);
|
||||
}
|
||||
nlohmann::json response_data = nlohmann::json::array();
|
||||
PHY_VARS_NR_UE *phy_vars_nr_ue = PHY_vars_UE_g[ue_index][0];
|
||||
nr_ue_phy_cpu_stat_t *phy_cpu_stats = &phy_vars_nr_ue->phy_cpu_stats;
|
||||
for (auto meas_index = 0; meas_index < MAX_CPU_STAT_TYPE; meas_index++) {
|
||||
response_data.push_back(generate_meas_json(&phy_cpu_stats->cpu_time_stats[meas_index]));
|
||||
}
|
||||
return crow::response(crow::status::OK, response_data.dump());
|
||||
});
|
||||
|
||||
bp->new_rule_dynamic("/cpumeas/<int>/<int>")([](int ue_index, int meas_index) {
|
||||
if (ue_index != 0) {
|
||||
return crow::response(crow::status::BAD_REQUEST);
|
||||
}
|
||||
if (meas_index < 0 || meas_index >= MAX_CPU_STAT_TYPE) {
|
||||
return crow::response(crow::status::BAD_REQUEST);
|
||||
}
|
||||
PHY_VARS_NR_UE *phy_vars_nr_ue = PHY_vars_UE_g[ue_index][0];
|
||||
nr_ue_phy_cpu_stat_t *phy_cpu_stats = &phy_vars_nr_ue->phy_cpu_stats;
|
||||
return crow::response(generate_meas_json(&phy_cpu_stats->cpu_time_stats[meas_index]).dump());
|
||||
});
|
||||
|
||||
bp->new_rule_dynamic("/cpumeas/enable")([]() {
|
||||
cpumeas(CPUMEAS_ENABLE);
|
||||
return crow::response(crow::status::OK, std::string("OK"));
|
||||
});
|
||||
|
||||
bp->new_rule_dynamic("/cpumeas/disable")([]() {
|
||||
cpumeas(CPUMEAS_DISABLE);
|
||||
return crow::response(crow::status::OK, std::string("OK"));
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace nr_ue::rest_api::phy
|
||||
@@ -94,12 +94,12 @@ int load_lib(openair0_device *device,
|
||||
eth_params_t *cfg,
|
||||
uint8_t flag)
|
||||
{
|
||||
loader_shlibfunc_t shlib_fdesc[1];
|
||||
loader_shlibfunc_t shlib_fdesc[2];
|
||||
int num_fdesc = 1;
|
||||
int ret=0;
|
||||
char *deflibname=OAI_RF_LIBNAME;
|
||||
openair0_cfg->command_line_sample_advance = get_softmodem_params()->command_line_sample_advance;
|
||||
openair0_cfg->recplay_mode = read_recplayconfig(&(openair0_cfg->recplay_conf),&(device->recplay_state));
|
||||
|
||||
if (openair0_cfg->recplay_mode == RECPLAY_RECORDMODE) {
|
||||
set_softmodem_optmask(SOFTMODEM_RECRECORD_BIT); // softmodem has to know we use the iqrecorder to workaround randomized algorithms
|
||||
}
|
||||
@@ -110,6 +110,8 @@ int load_lib(openair0_device *device,
|
||||
} else if (IS_SOFTMODEM_RFSIM && flag == RAU_LOCAL_RADIO_HEAD) {
|
||||
deflibname=OAI_RFSIM_LIBNAME;
|
||||
shlib_fdesc[0].fname="device_init";
|
||||
shlib_fdesc[1].fname = "register_routes";
|
||||
num_fdesc = 2;
|
||||
} else if (flag == RAU_LOCAL_RADIO_HEAD) {
|
||||
if (IS_SOFTMODEM_RFSIM)
|
||||
deflibname="rfsimulator";
|
||||
@@ -132,7 +134,7 @@ int load_lib(openair0_device *device,
|
||||
|
||||
config_get(config_get_if(), device_params, numparams, DEVICE_SECTION);
|
||||
|
||||
ret=load_module_shlib(devname,shlib_fdesc,1,NULL);
|
||||
ret=load_module_shlib(devname,shlib_fdesc,num_fdesc,NULL);
|
||||
AssertFatal( (ret >= 0),
|
||||
"Library %s couldn't be loaded\n",devname);
|
||||
|
||||
|
||||
@@ -1,9 +1,17 @@
|
||||
add_library(rfsimulator MODULE
|
||||
simulator.c
|
||||
apply_channelmod.c
|
||||
../../openair1/PHY/TOOLS/signal_energy.c
|
||||
set(rfsimulator_sources
|
||||
simulator.c
|
||||
apply_channelmod.c
|
||||
../../openair1/PHY/TOOLS/signal_energy.c
|
||||
)
|
||||
if (ENABLE_RESTAPI)
|
||||
list(APPEND rfsimulator_sources simulator_rest_api.cpp)
|
||||
endif()
|
||||
add_library(rfsimulator MODULE ${rfsimulator_sources})
|
||||
|
||||
target_link_libraries(rfsimulator PRIVATE SIMU HASHTABLE)
|
||||
if (ENABLE_RESTAPI)
|
||||
target_link_libraries(rfsimulator PRIVATE Crow::Crow nlohmann_json::nlohmann_json)
|
||||
endif()
|
||||
set_target_properties(rfsimulator PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
add_executable(replay_node stored_node.c)
|
||||
|
||||
@@ -1,35 +1,114 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Author and copyright: Laurent Thomas, open-cells.com
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Author and copyright: Laurent Thomas, open-cells.com
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#ifndef __RFSIMULATOR_H
|
||||
#define __RFSIMULATOR_H
|
||||
void rxAddInput( const c16_t *input_sig,
|
||||
c16_t *after_channel_sig,
|
||||
int rxAnt,
|
||||
channel_desc_t *channelDesc,
|
||||
int nbSamples,
|
||||
uint64_t TS,
|
||||
uint32_t CirSize
|
||||
);
|
||||
#ifndef RFSIMULATOR_H
|
||||
#define RFSIMULATOR_H
|
||||
|
||||
#include <common/utils/telnetsrv/telnetsrv.h>
|
||||
#include <openair1/SIMULATION/TOOLS/sim.h>
|
||||
#include "hashtable.h"
|
||||
|
||||
// This needs to be re-architected in the future
|
||||
//
|
||||
// File Descriptors management in rfsimulator is not optimized
|
||||
// Relying on FD_SETSIZE (actually 1024) is not appropriated
|
||||
// Also the use of fd value as returned by Linux as an index for buf[] structure is not appropriated
|
||||
// especially for client (UE) side since only 1 fd per connection to a gNB is needed. On the server
|
||||
// side the value should be tuned to the maximum number of connections with UE's which corresponds
|
||||
// to the maximum number of UEs hosted by a gNB which is unlikely to be in the order of thousands
|
||||
// since all I/Q's would flow through the same TCP transport.
|
||||
// Until a convenient management is implemented, the MAX_FD_RFSIMU is used everywhere (instead of
|
||||
// FD_SETSIE) and reduced to 125. This should allow for around 20 simultaeous UEs.
|
||||
//
|
||||
// #define MAX_FD_RFSIMU FD_SETSIZE
|
||||
#define MAX_FD_RFSIMU 250
|
||||
|
||||
typedef c16_t sample_t; // 2*16 bits complex number
|
||||
|
||||
// Simulator role
|
||||
typedef enum { SIMU_ROLE_SERVER = 1, SIMU_ROLE_CLIENT } simuRole;
|
||||
|
||||
typedef struct buffer_s {
|
||||
int conn_sock;
|
||||
openair0_timestamp lastReceivedTS;
|
||||
bool headerMode;
|
||||
bool trashingPacket;
|
||||
samplesBlockHeader_t th;
|
||||
char *transferPtr;
|
||||
uint64_t remainToTransfer;
|
||||
char *circularBufEnd;
|
||||
sample_t *circularBuf;
|
||||
channel_desc_t *channel_model;
|
||||
} buffer_t;
|
||||
|
||||
typedef struct {
|
||||
int listen_sock, epollfd;
|
||||
openair0_timestamp nextRxTstamp;
|
||||
openair0_timestamp lastWroteTS;
|
||||
simuRole role;
|
||||
char *ip;
|
||||
uint16_t port;
|
||||
int saveIQfile;
|
||||
buffer_t buf[MAX_FD_RFSIMU];
|
||||
int next_buf;
|
||||
// Hashtable used as an indirection level between file descriptor and the buf array
|
||||
hash_table_t *fd_to_buf_map;
|
||||
int rx_num_channels;
|
||||
int tx_num_channels;
|
||||
double sample_rate;
|
||||
double rx_freq;
|
||||
double tx_bw;
|
||||
int channelmod;
|
||||
double chan_pathloss;
|
||||
double chan_forgetfact;
|
||||
uint64_t chan_offset;
|
||||
float noise_power_dB;
|
||||
void *telnetcmd_qid;
|
||||
poll_telnetcmdq_func_t poll_telnetcmdq;
|
||||
int wait_timeout;
|
||||
double prop_delay_ms;
|
||||
} rfsimulator_state_t;
|
||||
|
||||
//
|
||||
// CirSize defines the number of samples inquired for a read cycle
|
||||
// It is bounded by a slot read capability (which depends on bandwidth and numerology)
|
||||
// up to multiple slots read to allow I/Q buffering of the I/Q TCP stream
|
||||
//
|
||||
// As a rule of thumb:
|
||||
// -it can't be less than the number of samples for a slot
|
||||
// -it can range up to multiple slots
|
||||
//
|
||||
// The default value is chosen for 10ms buffering which makes 23040*20 = 460800 samples
|
||||
// The previous value is kept below in comment it was computed for 100ms 1x 20MHz
|
||||
// #define CirSize 6144000 // 100ms SiSo 20MHz LTE
|
||||
#define minCirSize 460800 // 10ms SiSo 40Mhz 3/4 sampling NR78 FR1
|
||||
|
||||
void rxAddInput(const c16_t *input_sig,
|
||||
c16_t *after_channel_sig,
|
||||
int rxAnt,
|
||||
channel_desc_t *channelDesc,
|
||||
int nbSamples,
|
||||
uint64_t TS,
|
||||
uint32_t CirSize);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -44,28 +44,12 @@
|
||||
#include <common/utils/assertions.h>
|
||||
#include <common/utils/LOG/log.h>
|
||||
#include <common/utils/load_module_shlib.h>
|
||||
#include <common/utils/telnetsrv/telnetsrv.h>
|
||||
#include <common/config/config_userapi.h>
|
||||
#include "common_lib.h"
|
||||
#define CHANNELMOD_DYNAMICLOAD
|
||||
#include <openair1/SIMULATION/TOOLS/sim.h>
|
||||
#include "rfsimulator.h"
|
||||
#include "hashtable.h"
|
||||
|
||||
#define PORT 4043 //default TCP port for this simulator
|
||||
//
|
||||
// CirSize defines the number of samples inquired for a read cycle
|
||||
// It is bounded by a slot read capability (which depends on bandwidth and numerology)
|
||||
// up to multiple slots read to allow I/Q buffering of the I/Q TCP stream
|
||||
//
|
||||
// As a rule of thumb:
|
||||
// -it can't be less than the number of samples for a slot
|
||||
// -it can range up to multiple slots
|
||||
//
|
||||
// The default value is chosen for 10ms buffering which makes 23040*20 = 460800 samples
|
||||
// The previous value is kept below in comment it was computed for 100ms 1x 20MHz
|
||||
// #define CirSize 6144000 // 100ms SiSo 20MHz LTE
|
||||
#define minCirSize 460800 // 10ms SiSo 40Mhz 3/4 sampling NR78 FR1
|
||||
|
||||
#define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t))
|
||||
#define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b)))
|
||||
|
||||
@@ -89,11 +73,6 @@
|
||||
#define MAX_FD_RFSIMU 250
|
||||
#define SEND_BUFF_SIZE 100000000 // Socket buffer size
|
||||
|
||||
// Simulator role
|
||||
typedef enum { SIMU_ROLE_SERVER = 1, SIMU_ROLE_CLIENT } simuRole;
|
||||
|
||||
//
|
||||
|
||||
#define RFSIMU_SECTION "rfsimulator"
|
||||
#define RFSIMU_OPTIONS_PARAMNAME "options"
|
||||
|
||||
@@ -138,51 +117,8 @@ static telnetshell_cmddef_t *setmodel_cmddef = &(rfsimu_cmdarray[1]);
|
||||
static telnetshell_vardef_t rfsimu_vardef[] = {{"", 0, 0, NULL}};
|
||||
pthread_mutex_t Sockmutex;
|
||||
unsigned int nb_ue = 0;
|
||||
|
||||
static uint64_t CirSize = minCirSize;
|
||||
|
||||
typedef c16_t sample_t; // 2*16 bits complex number
|
||||
|
||||
typedef struct buffer_s {
|
||||
int conn_sock;
|
||||
openair0_timestamp lastReceivedTS;
|
||||
bool headerMode;
|
||||
bool trashingPacket;
|
||||
samplesBlockHeader_t th;
|
||||
char *transferPtr;
|
||||
uint64_t remainToTransfer;
|
||||
char *circularBufEnd;
|
||||
sample_t *circularBuf;
|
||||
channel_desc_t *channel_model;
|
||||
} buffer_t;
|
||||
|
||||
typedef struct {
|
||||
int listen_sock, epollfd;
|
||||
openair0_timestamp nextRxTstamp;
|
||||
openair0_timestamp lastWroteTS;
|
||||
simuRole role;
|
||||
char *ip;
|
||||
uint16_t port;
|
||||
int saveIQfile;
|
||||
buffer_t buf[MAX_FD_RFSIMU];
|
||||
int next_buf;
|
||||
// Hashtable used as an indirection level between file descriptor and the buf array
|
||||
hash_table_t *fd_to_buf_map;
|
||||
int rx_num_channels;
|
||||
int tx_num_channels;
|
||||
double sample_rate;
|
||||
double rx_freq;
|
||||
double tx_bw;
|
||||
int channelmod;
|
||||
double chan_pathloss;
|
||||
double chan_forgetfact;
|
||||
uint64_t chan_offset;
|
||||
float noise_power_dB;
|
||||
void *telnetcmd_qid;
|
||||
poll_telnetcmdq_func_t poll_telnetcmdq;
|
||||
int wait_timeout;
|
||||
double prop_delay_ms;
|
||||
} rfsimulator_state_t;
|
||||
rfsimulator_state_t *rfsimulator_state = NULL;
|
||||
|
||||
|
||||
static buffer_t *get_buff_from_socket(rfsimulator_state_t *simulator_state, int socket)
|
||||
@@ -1179,5 +1115,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rfsimulator_state = rfsimulator;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
86
radio/rfsimulator/simulator_rest_api.cpp
Normal file
86
radio/rfsimulator/simulator_rest_api.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <crow.h>
|
||||
#include <vector>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
extern "C" {
|
||||
#include "rfsimulator.h"
|
||||
extern rfsimulator_state_t *rfsimulator_state;
|
||||
}
|
||||
namespace rfsimulator::rest_api {
|
||||
nlohmann::json generate_channel_json(channel_desc_t *channel_model, int conn_sock)
|
||||
{
|
||||
return nlohmann::json({{"name", std::string(channel_model->model_name)},
|
||||
{"conn_sock", conn_sock},
|
||||
{"path_loss_dB", channel_model->path_loss_dB},
|
||||
{"noise_power_dB", channel_model->noise_power_dB},
|
||||
{"nb_tx", channel_model->nb_tx},
|
||||
{"nb_rx", channel_model->nb_rx}});
|
||||
}
|
||||
|
||||
extern "C" void register_routes(crow::Blueprint *bp)
|
||||
{
|
||||
bp->new_rule_dynamic("/healthcheck/")([]() { return crow::response(crow::status::OK, std::string("OK")); });
|
||||
|
||||
bp->new_rule_dynamic("/channel/")([]() {
|
||||
nlohmann::json response_data = nlohmann::json::array();
|
||||
for (auto buffer_index = 0; buffer_index < MAX_FD_RFSIMU; buffer_index++) {
|
||||
auto buf = &rfsimulator_state->buf[buffer_index];
|
||||
if (buf->conn_sock != -1 && buf->channel_model != nullptr) {
|
||||
response_data.push_back(generate_channel_json(buf->channel_model, buffer_index));
|
||||
}
|
||||
}
|
||||
return crow::response(crow::status::OK, response_data.dump());
|
||||
});
|
||||
|
||||
bp->new_rule_dynamic("/channel/<string>/")
|
||||
.methods(crow::HTTPMethod::POST, crow::HTTPMethod::GET)([](const crow::request &req, std::string channel_name) {
|
||||
nlohmann::json req_json;
|
||||
try {
|
||||
req_json = nlohmann::json::parse(req.body);
|
||||
} catch (const nlohmann::json::exception &e) {
|
||||
std::cerr << "Exception: " << e.what() << std::endl;
|
||||
return crow::response(crow::status::BAD_REQUEST, std::string(e.what()));
|
||||
}
|
||||
|
||||
for (auto buffer_index = 0; buffer_index < MAX_FD_RFSIMU; buffer_index++) {
|
||||
auto buf = &rfsimulator_state->buf[buffer_index];
|
||||
if (buf->conn_sock != -1 && buf->channel_model != nullptr) {
|
||||
if (channel_name.compare(buf->channel_model->model_name) == 0) {
|
||||
if (req.method == crow::HTTPMethod::GET) {
|
||||
return crow::response(generate_channel_json(buf->channel_model, buf->conn_sock).dump());
|
||||
} else {
|
||||
const char path_loss_db[] = "path_loss_dB";
|
||||
if (req_json.contains(path_loss_db)) {
|
||||
buf->channel_model->path_loss_dB = req_json[path_loss_db];
|
||||
}
|
||||
return crow::response(crow::status::OK, std::string("OK"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return crow::response(crow::status::BAD_REQUEST, std::string("Channel not found"));
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace rfsimulator::rest_api
|
||||
@@ -215,3 +215,26 @@ e2_agent:
|
||||
near_ric_ip_addr: 127.0.0.1
|
||||
#sm_dir = /path/where/the/SMs/are/located/
|
||||
sm_dir: /usr/local/lib/flexric/
|
||||
|
||||
|
||||
#/* configuration for channel modelisation */
|
||||
#/* To be included in main config file when */
|
||||
#/* channel modelisation is used (rfsimulator with chanmod options enabled) */
|
||||
channelmod:
|
||||
max_chan: 10
|
||||
modellist: modellist_rfsimu_1
|
||||
modellist_rfsimu_1:
|
||||
- model_name: rfsimu_channel_enB0
|
||||
type: AWGN
|
||||
ploss_dB: 20
|
||||
noise_power_dB: -4
|
||||
forgetfact: 0
|
||||
offset: 0
|
||||
ds_tdl: 0
|
||||
- model_name: rfsimu_channel_ue0
|
||||
type: AWGN
|
||||
ploss_dB: 20
|
||||
nose_power_dB: -2
|
||||
forgetfact: 0
|
||||
offset: 0
|
||||
ds_tdl: 0
|
||||
|
||||
Reference in New Issue
Block a user