API change: new arguments to time_manager_start()

This commit is contained in:
Cedric Roux
2025-04-18 09:05:39 +02:00
parent 4834d93006
commit b89b3abd13
7 changed files with 93 additions and 104 deletions
+22 -10
View File
@@ -41,12 +41,6 @@ void exit_function(const char *file, const char *function, const int line, const
exit(1); exit(1);
} }
int is_x2ap_enabled(void)
{
/* we want x2ap ticks */
return 1;
}
static int rlc_tick_count = 0; static int rlc_tick_count = 0;
static int pdcp_tick_count = 0; static int pdcp_tick_count = 0;
static int x2ap_tick_count = 0; static int x2ap_tick_count = 0;
@@ -69,7 +63,13 @@ void x2ap_ms_tick(void)
/* return 1 if ok, 0 if error */ /* return 1 if ok, 0 if error */
static int standalone_realtime(void) static int standalone_realtime(void)
{ {
time_manager_start(TIME_MANAGER_GNB_MONOLITHIC, TIME_MANAGER_REALTIME); time_manager_tick_function_t tick_functions[] = {
nr_pdcp_ms_tick,
nr_rlc_ms_tick,
x2ap_ms_tick
};
int tick_functions_count = sizeofArray(tick_functions);
time_manager_start(tick_functions, tick_functions_count, TIME_SOURCE_REALTIME);
sleep(1); sleep(1);
@@ -90,7 +90,13 @@ static int standalone_realtime(void)
/* return 1 if ok, 0 if error */ /* return 1 if ok, 0 if error */
static int standalone_iq_samples(void) static int standalone_iq_samples(void)
{ {
time_manager_start(TIME_MANAGER_GNB_MONOLITHIC, TIME_MANAGER_IQ_SAMPLES); time_manager_tick_function_t tick_functions[] = {
nr_pdcp_ms_tick,
nr_rlc_ms_tick,
x2ap_ms_tick
};
int tick_functions_count = sizeofArray(tick_functions);
time_manager_start(tick_functions, tick_functions_count, TIME_SOURCE_IQ_SAMPLES);
/* let's pretend we have 2000 samples per second */ /* let's pretend we have 2000 samples per second */
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
@@ -168,8 +174,14 @@ static int client_server(char *program_name, bool iq_samples_time_source)
/* return 1 if ok, 0 if error */ /* return 1 if ok, 0 if error */
static int run_sub_client_server(bool iq_samples_time_source) static int run_sub_client_server(bool iq_samples_time_source)
{ {
/* second argument doesn't matter, overwritten by args of execl in client_server() */ time_manager_tick_function_t tick_functions[] = {
time_manager_start(TIME_MANAGER_GNB_MONOLITHIC, TIME_MANAGER_REALTIME); nr_pdcp_ms_tick,
nr_rlc_ms_tick,
x2ap_ms_tick
};
int tick_functions_count = sizeofArray(tick_functions);
/* last argument doesn't matter, overwritten by args of execl in client_server() */
time_manager_start(tick_functions, tick_functions_count, TIME_SOURCE_REALTIME);
if (iq_samples_time_source) { if (iq_samples_time_source) {
/* 'iq_samples_time_source' is true only for server /* 'iq_samples_time_source' is true only for server
+19 -68
View File
@@ -19,9 +19,6 @@
* contact@openairinterface.org * contact@openairinterface.org
*/ */
#define _GNU_SOURCE
#include <dlfcn.h>
#include "time_manager.h" #include "time_manager.h"
#include "time_source.h" #include "time_source.h"
@@ -37,27 +34,17 @@ static time_source_t *time_source = NULL;
static time_server_t *time_server = NULL; static time_server_t *time_server = NULL;
static time_client_t *time_client = NULL; static time_client_t *time_client = NULL;
/* available tick functions in the executable /* tick functions registered at initialization of the time manager */
* found at startup time of the program using dlsym() static time_manager_tick_function_t *tick_functions;
*/ static int tick_functions_count;
static void (*pdcp_tick)(void) = NULL;
static void (*rlc_tick)(void) = NULL;
static void (*x2ap_tick)(void) = NULL;
/* tick callback, called by time_source every 'millisecond' (can be /* tick callback, called by time_source every 'millisecond' (can be
* actual millisecond or simulated millisecond) * actual millisecond or simulated millisecond)
*/ */
static void tick(void *unused) static void tick(void *unused)
{ {
/* call x2ap_tick, pdcp_tick, rlc_tick (if they exist) */ for (int i = 0; i < tick_functions_count; i++)
if (pdcp_tick != NULL) tick_functions[i]();
pdcp_tick();
if (rlc_tick != NULL)
rlc_tick();
if (x2ap_tick != NULL)
x2ap_tick();
} }
#define TIME_SOURCE "time_source" #define TIME_SOURCE "time_source"
@@ -92,10 +79,10 @@ static int get_param_int(char *name)
return *config_parameters[idx].iptr; return *config_parameters[idx].iptr;
} }
void time_manager_start(time_manager_client_t client_type, void time_manager_start(time_manager_tick_function_t *_tick_functions,
time_manager_mode_t running_mode) int _tick_functions_count,
time_source_type_t time_source_type)
{ {
time_source_type_t time_source_type = -1;
bool has_time_server = false; bool has_time_server = false;
bool has_time_client = false; bool has_time_client = false;
char *default_server_ip = "127.0.0.1"; char *default_server_ip = "127.0.0.1";
@@ -103,47 +90,11 @@ void time_manager_start(time_manager_client_t client_type,
char *server_ip = NULL; char *server_ip = NULL;
int server_port = -1; int server_port = -1;
/* retrieve, if applicable, available tick functions in the program */ tick_functions_count = _tick_functions_count;
if (client_type == TIME_MANAGER_GNB_MONOLITHIC tick_functions = calloc_or_fail(tick_functions_count, sizeof(*tick_functions));
|| client_type == TIME_MANAGER_GNB_CU memcpy(tick_functions, _tick_functions, tick_functions_count * sizeof(*tick_functions));
|| client_type == TIME_MANAGER_UE)
pdcp_tick = dlsym(RTLD_DEFAULT, "nr_pdcp_ms_tick");
if (client_type == TIME_MANAGER_GNB_MONOLITHIC /* retrieve configuration */
|| client_type == TIME_MANAGER_GNB_DU
|| client_type == TIME_MANAGER_UE)
rlc_tick = dlsym(RTLD_DEFAULT, "nr_rlc_ms_tick");
/* let's also retrieve is_x2ap_enabled() with dlsym to not force the
* application to define it (this logic may be changed if wanted)
*/
int (*is_x2ap_enabled)(void) = dlsym(RTLD_DEFAULT, "is_x2ap_enabled");
if ((client_type == TIME_MANAGER_GNB_MONOLITHIC
|| client_type == TIME_MANAGER_GNB_CU)
&& is_x2ap_enabled != NULL && is_x2ap_enabled())
x2ap_tick = dlsym(RTLD_DEFAULT, "x2ap_ms_tick");
/* get default configuration */
switch (client_type) {
case TIME_MANAGER_GNB_MONOLITHIC:
case TIME_MANAGER_GNB_DU:
case TIME_MANAGER_UE:
switch (running_mode) {
case TIME_MANAGER_REALTIME:
time_source_type = TIME_SOURCE_REALTIME;
break;
case TIME_MANAGER_IQ_SAMPLES:
time_source_type = TIME_SOURCE_IQ_SAMPLES;
break;
}
break;
case TIME_MANAGER_GNB_CU:
case TIME_MANAGER_SIMULATOR:
time_source_type = TIME_SOURCE_REALTIME;
break;
}
/* get values from configuration */
int ret = config_get(config_get_if(), config_parameters, sizeofArray(config_parameters), "time_management"); int ret = config_get(config_get_if(), config_parameters, sizeofArray(config_parameters), "time_management");
if (ret >= 0) { if (ret >= 0) {
char *param; char *param;
@@ -209,23 +160,19 @@ void time_manager_start(time_manager_client_t client_type,
if (has_time_client) { if (has_time_client) {
time_client = new_time_client(server_ip, server_port, tick, NULL); time_client = new_time_client(server_ip, server_port, tick, NULL);
/* for the log below, there is no time source, we want to print 'server' as time source */
time_source_type = 2;
} }
LOG_I(UTIL, LOG_I(UTIL,
"time manager configuration: [time source: %s] [mode: %s] [server IP: %s} [server port: %d]%s\n", "time manager configuration: [time source: %s] [mode: %s] [server IP: %s} [server port: %d]%s\n",
(char *[]){"reatime", "iq_samples"}[time_source_type], (char *[]){"reatime", "iq_samples", "server"}[time_source_type],
has_time_server ? "server" has_time_server ? "server"
: has_time_client ? "client" : has_time_client ? "client"
: "standalone", : "standalone",
server_ip, server_ip,
server_port, server_port,
has_time_server || has_time_client ? "" : " (server IP/port not used)"); has_time_server || has_time_client ? "" : " (server IP/port not used)");
LOG_I(UTIL,
"time manager: pdcp tick: %s, rlc tick: %s, x2ap tick: %s\n",
pdcp_tick == NULL ? "not activated" : "activated",
rlc_tick == NULL ? "not activated" : "activated",
x2ap_tick == NULL ? "not activated" : "activated");
} }
void time_manager_iq_samples(uint64_t iq_samples_count, void time_manager_iq_samples(uint64_t iq_samples_count,
@@ -251,4 +198,8 @@ void time_manager_finish(void)
free_time_client(time_client); free_time_client(time_client);
time_client = NULL; time_client = NULL;
} }
free(tick_functions);
tick_functions = NULL;
tick_functions_count = 0;
} }
+5 -13
View File
@@ -24,21 +24,13 @@
#include <stdint.h> #include <stdint.h>
typedef enum { #include "time_source.h"
TIME_MANAGER_GNB_MONOLITHIC,
TIME_MANAGER_GNB_CU,
TIME_MANAGER_GNB_DU,
TIME_MANAGER_UE,
TIME_MANAGER_SIMULATOR,
} time_manager_client_t;
typedef enum { typedef void (*time_manager_tick_function_t)(void);
TIME_MANAGER_REALTIME,
TIME_MANAGER_IQ_SAMPLES
} time_manager_mode_t;
void time_manager_start(time_manager_client_t client_type, void time_manager_start(time_manager_tick_function_t *tick_functions,
time_manager_mode_t running_mode); int tick_functions_count,
time_source_type_t time_source);
void time_manager_iq_samples(uint64_t iq_samples_count, void time_manager_iq_samples(uint64_t iq_samples_count,
uint64_t iq_samples_per_second); uint64_t iq_samples_per_second);
void time_manager_finish(void); void time_manager_finish(void);
+6 -4
View File
@@ -253,8 +253,9 @@ in `time_manager.c`, together with some global variables (so that there is no
need to pass objects around, to limit risks of misuse). need to pass objects around, to limit risks of misuse).
Each program (for example: gnb, ue, cu, du) calls the `time_manager_start()` Each program (for example: gnb, ue, cu, du) calls the `time_manager_start()`
function, passing the kind of program it is. Based on this type and the function, passing the callback functions to be called when a tick is generated
configuration, `time_manager_start()` initializes what is needed. (several callbacks can be passed) and a default time source. Based on this,
`time_manager_start()` initializes what is needed.
The function `time_manager_iq_samples()` is to be called by programs that The function `time_manager_iq_samples()` is to be called by programs that
read IQ samples. It is called unconditionally. It may do nothing if the read IQ samples. It is called unconditionally. It may do nothing if the
@@ -268,8 +269,9 @@ Here comes the API.
- init the time manager: - init the time manager:
``` ```
void time_manager_start(time_manager_client_t client_type, void time_manager_start(time_manager_tick_function_t *tick_functions,
time_manager_mode_t running_mode) int tick_functions_count,
time_source_type_t time_source);
``` ```
(for valid values of `client_type` and `running_mode` see in (for valid values of `client_type` and `running_mode` see in
`time_manager.h`) `time_manager.h`)
+6 -1
View File
@@ -143,7 +143,12 @@ int main(int argc, char **argv)
// start time manager with some reasonable default for the running mode // start time manager with some reasonable default for the running mode
// (may be overwritten in configuration file or command line) // (may be overwritten in configuration file or command line)
time_manager_start(TIME_MANAGER_GNB_CU, TIME_MANAGER_REALTIME); void nr_pdcp_ms_tick(void);
time_manager_tick_function_t tick_functions[] = {
nr_pdcp_ms_tick
};
int tick_functions_count = 1;
time_manager_start(tick_functions, tick_functions_count, TIME_SOURCE_REALTIME);
// strdup to put the sring in the core file for post mortem identification // strdup to put the sring in the core file for post mortem identification
LOG_I(HW, "Version: %s\n", strdup(OAI_PACKAGE_VERSION)); LOG_I(HW, "Version: %s\n", strdup(OAI_PACKAGE_VERSION));
+25 -5
View File
@@ -631,15 +631,35 @@ int main( int argc, char **argv ) {
// start time manager with some reasonable default for the running mode // start time manager with some reasonable default for the running mode
// (may be overwritten in configuration file or command line) // (may be overwritten in configuration file or command line)
time_manager_start(NODE_IS_MONOLITHIC(node_type) ? TIME_MANAGER_GNB_MONOLITHIC void nr_pdcp_ms_tick(void);
: NODE_IS_CU(node_type) ? TIME_MANAGER_GNB_CU void x2ap_ms_tick();
: TIME_MANAGER_GNB_DU, void nr_rlc_ms_tick(void);
time_manager_tick_function_t tick_functions[3];
int tick_functions_count = 0;
if (NODE_IS_MONOLITHIC(node_type)) {
/* monolithic */
tick_functions[tick_functions_count++] = nr_pdcp_ms_tick;
tick_functions[tick_functions_count++] = nr_rlc_ms_tick;
/* x2ap is enabled when in NSA mode */
if (get_softmodem_params()->nsa)
tick_functions[tick_functions_count++] = x2ap_ms_tick;
} else if (NODE_IS_CU(node_type)) {
/* CU */
tick_functions[tick_functions_count++] = nr_pdcp_ms_tick;
/* x2ap is enabled when in NSA mode */
if (get_softmodem_params()->nsa)
tick_functions[tick_functions_count++] = x2ap_ms_tick;
} else {
/* DU */
tick_functions[tick_functions_count++] = nr_rlc_ms_tick;
}
time_manager_start(tick_functions, tick_functions_count,
// iq_samples time source for monolithic/du with rfsim, // iq_samples time source for monolithic/du with rfsim,
// realtime time source for other cases // realtime time source for other cases
IS_SOFTMODEM_RFSIM IS_SOFTMODEM_RFSIM
&& (NODE_IS_MONOLITHIC(node_type) || NODE_IS_DU(node_type)) && (NODE_IS_MONOLITHIC(node_type) || NODE_IS_DU(node_type))
? TIME_MANAGER_IQ_SAMPLES ? TIME_SOURCE_IQ_SAMPLES
: TIME_MANAGER_REALTIME); : TIME_SOURCE_REALTIME);
// start the main threads // start the main threads
number_of_cards = 1; number_of_cards = 1;
+10 -3
View File
@@ -464,11 +464,18 @@ int main(int argc, char **argv)
// start time manager with some reasonable default for the running mode // start time manager with some reasonable default for the running mode
// (may be overwritten in configuration file or command line) // (may be overwritten in configuration file or command line)
time_manager_start(TIME_MANAGER_UE, void nr_pdcp_ms_tick(void);
void nr_rlc_ms_tick(void);
time_manager_tick_function_t tick_functions[] = {
nr_pdcp_ms_tick,
nr_rlc_ms_tick
};
int tick_functions_count = 2;
time_manager_start(tick_functions, tick_functions_count,
// iq_samples time source for rfsim, // iq_samples time source for rfsim,
// realtime time source if not // realtime time source if not
IS_SOFTMODEM_RFSIM ? TIME_MANAGER_IQ_SAMPLES IS_SOFTMODEM_RFSIM ? TIME_SOURCE_IQ_SAMPLES
: TIME_MANAGER_REALTIME); : TIME_SOURCE_REALTIME);
if (!get_softmodem_params()->nsa && get_softmodem_params()->emulate_l1) if (!get_softmodem_params()->nsa && get_softmodem_params()->emulate_l1)
start_oai_nrue_threads(); start_oai_nrue_threads();