diff --git a/common/utils/time_manager/tests/test_auto.c b/common/utils/time_manager/tests/test_auto.c index 73bf27af88..817a518c4a 100644 --- a/common/utils/time_manager/tests/test_auto.c +++ b/common/utils/time_manager/tests/test_auto.c @@ -41,12 +41,6 @@ void exit_function(const char *file, const char *function, const int line, const exit(1); } -int is_x2ap_enabled(void) -{ - /* we want x2ap ticks */ - return 1; -} - static int rlc_tick_count = 0; static int pdcp_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 */ 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); @@ -90,7 +90,13 @@ static int standalone_realtime(void) /* return 1 if ok, 0 if error */ 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 */ 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 */ 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_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); + /* 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) { /* 'iq_samples_time_source' is true only for server diff --git a/common/utils/time_manager/time_manager.c b/common/utils/time_manager/time_manager.c index a69ab503e8..bad8e2ccc4 100644 --- a/common/utils/time_manager/time_manager.c +++ b/common/utils/time_manager/time_manager.c @@ -19,9 +19,6 @@ * contact@openairinterface.org */ -#define _GNU_SOURCE -#include - #include "time_manager.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_client_t *time_client = NULL; -/* available tick functions in the executable - * found at startup time of the program using dlsym() - */ -static void (*pdcp_tick)(void) = NULL; -static void (*rlc_tick)(void) = NULL; -static void (*x2ap_tick)(void) = NULL; +/* tick functions registered at initialization of the time manager */ +static time_manager_tick_function_t *tick_functions; +static int tick_functions_count; /* tick callback, called by time_source every 'millisecond' (can be * actual millisecond or simulated millisecond) */ static void tick(void *unused) { - /* call x2ap_tick, pdcp_tick, rlc_tick (if they exist) */ - if (pdcp_tick != NULL) - pdcp_tick(); - - if (rlc_tick != NULL) - rlc_tick(); - - if (x2ap_tick != NULL) - x2ap_tick(); + for (int i = 0; i < tick_functions_count; i++) + tick_functions[i](); } #define TIME_SOURCE "time_source" @@ -92,10 +79,10 @@ static int get_param_int(char *name) return *config_parameters[idx].iptr; } -void time_manager_start(time_manager_client_t client_type, - time_manager_mode_t running_mode) +void time_manager_start(time_manager_tick_function_t *_tick_functions, + 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_client = false; 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; int server_port = -1; - /* retrieve, if applicable, available tick functions in the program */ - if (client_type == TIME_MANAGER_GNB_MONOLITHIC - || client_type == TIME_MANAGER_GNB_CU - || client_type == TIME_MANAGER_UE) - pdcp_tick = dlsym(RTLD_DEFAULT, "nr_pdcp_ms_tick"); + tick_functions_count = _tick_functions_count; + tick_functions = calloc_or_fail(tick_functions_count, sizeof(*tick_functions)); + memcpy(tick_functions, _tick_functions, tick_functions_count * sizeof(*tick_functions)); - if (client_type == TIME_MANAGER_GNB_MONOLITHIC - || 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 */ + /* retrieve configuration */ int ret = config_get(config_get_if(), config_parameters, sizeofArray(config_parameters), "time_management"); if (ret >= 0) { char *param; @@ -209,23 +160,19 @@ void time_manager_start(time_manager_client_t client_type, if (has_time_client) { 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, "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_client ? "client" : "standalone", server_ip, server_port, 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, @@ -251,4 +198,8 @@ void time_manager_finish(void) free_time_client(time_client); time_client = NULL; } + + free(tick_functions); + tick_functions = NULL; + tick_functions_count = 0; } diff --git a/common/utils/time_manager/time_manager.h b/common/utils/time_manager/time_manager.h index d1ed4ed0e1..23f4c6805f 100644 --- a/common/utils/time_manager/time_manager.h +++ b/common/utils/time_manager/time_manager.h @@ -24,21 +24,13 @@ #include -typedef enum { - TIME_MANAGER_GNB_MONOLITHIC, - TIME_MANAGER_GNB_CU, - TIME_MANAGER_GNB_DU, - TIME_MANAGER_UE, - TIME_MANAGER_SIMULATOR, -} time_manager_client_t; +#include "time_source.h" -typedef enum { - TIME_MANAGER_REALTIME, - TIME_MANAGER_IQ_SAMPLES -} time_manager_mode_t; +typedef void (*time_manager_tick_function_t)(void); -void time_manager_start(time_manager_client_t client_type, - time_manager_mode_t running_mode); +void time_manager_start(time_manager_tick_function_t *tick_functions, + int tick_functions_count, + time_source_type_t time_source); void time_manager_iq_samples(uint64_t iq_samples_count, uint64_t iq_samples_per_second); void time_manager_finish(void); diff --git a/doc/time_management.md b/doc/time_management.md index 79dbbcf372..c6424b3847 100644 --- a/doc/time_management.md +++ b/doc/time_management.md @@ -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). 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 -configuration, `time_manager_start()` initializes what is needed. +function, passing the callback functions to be called when a tick is generated +(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 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: ``` - void time_manager_start(time_manager_client_t client_type, - time_manager_mode_t running_mode) + void time_manager_start(time_manager_tick_function_t *tick_functions, + int tick_functions_count, + time_source_type_t time_source); ``` (for valid values of `client_type` and `running_mode` see in `time_manager.h`) diff --git a/executables/nr-cuup.c b/executables/nr-cuup.c index 4f5520d250..6467683cac 100644 --- a/executables/nr-cuup.c +++ b/executables/nr-cuup.c @@ -143,7 +143,12 @@ int main(int argc, char **argv) // start time manager with some reasonable default for the running mode // (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 LOG_I(HW, "Version: %s\n", strdup(OAI_PACKAGE_VERSION)); diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index f0068a8d4b..24df549243 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -631,15 +631,35 @@ int main( int argc, char **argv ) { // start time manager with some reasonable default for the running mode // (may be overwritten in configuration file or command line) - time_manager_start(NODE_IS_MONOLITHIC(node_type) ? TIME_MANAGER_GNB_MONOLITHIC - : NODE_IS_CU(node_type) ? TIME_MANAGER_GNB_CU - : TIME_MANAGER_GNB_DU, + void nr_pdcp_ms_tick(void); + void x2ap_ms_tick(); + 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, // realtime time source for other cases IS_SOFTMODEM_RFSIM && (NODE_IS_MONOLITHIC(node_type) || NODE_IS_DU(node_type)) - ? TIME_MANAGER_IQ_SAMPLES - : TIME_MANAGER_REALTIME); + ? TIME_SOURCE_IQ_SAMPLES + : TIME_SOURCE_REALTIME); // start the main threads number_of_cards = 1; diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index fa5e5ca259..0641a89ad9 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -464,11 +464,18 @@ int main(int argc, char **argv) // start time manager with some reasonable default for the running mode // (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, // realtime time source if not - IS_SOFTMODEM_RFSIM ? TIME_MANAGER_IQ_SAMPLES - : TIME_MANAGER_REALTIME); + IS_SOFTMODEM_RFSIM ? TIME_SOURCE_IQ_SAMPLES + : TIME_SOURCE_REALTIME); if (!get_softmodem_params()->nsa && get_softmodem_params()->emulate_l1) start_oai_nrue_threads();