11/*
22 *
3- * Copyright 2021-2024 Software Radio Systems Limited
3+ * Copyright 2021-2025 Software Radio Systems Limited
44 *
55 * This file is part of srsRAN.
66 *
4141#include " srsran/e1ap/gateways/e1_local_connector_factory.h"
4242#include " srsran/e2/e2ap_config_translators.h"
4343#include " srsran/f1ap/gateways/f1c_network_server_factory.h"
44+ #include " srsran/f1u/cu_up/f1u_session_manager_factory.h"
4445#include " srsran/f1u/cu_up/split_connector/f1u_split_connector_factory.h"
4546#include " srsran/gateways/udp_network_gateway.h"
4647#include " srsran/gtpu/gtpu_config.h"
5455#include " srsran/support/io/io_broker_factory.h"
5556#include " srsran/support/io/io_timer_source.h"
5657#include " srsran/support/signal_handling.h"
58+ #include " srsran/support/signal_observer.h"
5759#include " srsran/support/sysinfo.h"
5860#include " srsran/support/timers.h"
5961#include " srsran/support/tracing/event_tracing.h"
@@ -89,14 +91,17 @@ static void populate_cli11_generic_args(CLI::App& app)
8991}
9092
9193// / Function to call when the application is interrupted.
92- static void interrupt_signal_handler ()
94+ static void interrupt_signal_handler (int signal )
9395{
9496 is_app_running = false ;
9597}
9698
99+ static signal_dispatcher cleanup_signal_dispatcher;
100+
97101// / Function to call when the application is going to be forcefully shutdown.
98- static void cleanup_signal_handler ()
102+ static void cleanup_signal_handler (int signal )
99103{
104+ cleanup_signal_dispatcher.notify_signal (signal);
100105 srslog::flush ();
101106}
102107
@@ -153,7 +158,8 @@ static void fill_cu_worker_manager_config(worker_manager_config& config, const c
153158 config.low_prio_sched_config = unit_cfg.expert_execution_cfg .affinities .low_priority_cpu_cfg ;
154159}
155160
156- static void autoderive_cu_up_parameters_after_parsing (o_cu_up_unit_config& o_cu_up_cfg,
161+ static void autoderive_cu_up_parameters_after_parsing (cu_appconfig& cu_config,
162+ o_cu_up_unit_config& o_cu_up_cfg,
157163 const cu_cp_unit_config& cu_cp_cfg)
158164{
159165 // If no UPF is configured, we set the UPF configuration from the CU-CP AMF configuration.
@@ -162,6 +168,11 @@ static void autoderive_cu_up_parameters_after_parsing(o_cu_up_unit_config& o
162168 sock_cfg.bind_addr = cu_cp_cfg.amf_config .amf .bind_addr ;
163169 o_cu_up_cfg.cu_up_cfg .ngu_cfg .ngu_socket_cfg .push_back (sock_cfg);
164170 }
171+ // If no F1-U socket configuration is derived, we set a default configuration.
172+ if (cu_config.f1u_cfg .f1u_socket_cfg .empty ()) {
173+ srs_cu::cu_f1u_socket_appconfig sock_cfg;
174+ cu_config.f1u_cfg .f1u_socket_cfg .push_back (sock_cfg);
175+ }
165176}
166177
167178int main (int argc, char ** argv)
@@ -197,12 +208,12 @@ int main(int argc, char** argv)
197208 o_cu_up_app_unit->on_parsing_configuration_registration (app);
198209
199210 // Set the callback for the app calling all the autoderivation functions.
200- app.callback ([&app, &o_cu_cp_app_unit, &o_cu_up_app_unit]() {
211+ app.callback ([&app, &cu_cfg, & o_cu_cp_app_unit, &o_cu_up_app_unit]() {
201212 o_cu_cp_app_unit->on_configuration_parameters_autoderivation (app);
202213 o_cu_up_app_unit->on_configuration_parameters_autoderivation (app);
203214
204- autoderive_cu_up_parameters_after_parsing (o_cu_up_app_unit-> get_o_cu_up_unit_config (),
205- o_cu_cp_app_unit->get_o_cu_cp_unit_config ().cucp_cfg );
215+ autoderive_cu_up_parameters_after_parsing (
216+ cu_cfg, o_cu_up_app_unit-> get_o_cu_up_unit_config (), o_cu_cp_app_unit->get_o_cu_cp_unit_config ().cucp_cfg );
206217 });
207218
208219 // Parse arguments.
@@ -261,18 +272,23 @@ int main(int argc, char** argv)
261272 check_cpu_governor (cu_logger);
262273 check_drm_kms_polling (cu_logger);
263274
275+ // Create manager of timers for CU-CP and CU-UP, which will be driven by the system timer slot ticks.
276+ timer_manager app_timers{256 };
277+ timer_manager* cu_timers = &app_timers;
278+
264279 // Create worker manager.
265280 worker_manager_config worker_manager_cfg;
266281 fill_cu_worker_manager_config (worker_manager_cfg, cu_cfg);
267282 o_cu_cp_app_unit->fill_worker_manager_config (worker_manager_cfg);
268283 o_cu_up_app_unit->fill_worker_manager_config (worker_manager_cfg);
284+ worker_manager_cfg.app_timers = &app_timers;
269285 worker_manager workers{worker_manager_cfg};
270286
271287 // Create layer specific PCAPs.
272- o_cu_cp_dlt_pcaps cu_cp_dlt_pcaps =
273- create_o_cu_cp_dlt_pcap ( o_cu_cp_app_unit->get_o_cu_cp_unit_config (), *workers.get_executor_getter ());
274- o_cu_up_dlt_pcaps cu_up_dlt_pcaps =
275- create_o_cu_up_dlt_pcaps ( o_cu_up_app_unit->get_o_cu_up_unit_config (), *workers.get_executor_getter ());
288+ o_cu_cp_dlt_pcaps cu_cp_dlt_pcaps = create_o_cu_cp_dlt_pcap (
289+ o_cu_cp_app_unit->get_o_cu_cp_unit_config (), *workers.get_executor_getter (), cleanup_signal_dispatcher );
290+ o_cu_up_dlt_pcaps cu_up_dlt_pcaps = create_o_cu_up_dlt_pcaps (
291+ o_cu_up_app_unit->get_o_cu_up_unit_config (), *workers.get_executor_getter (), cleanup_signal_dispatcher );
276292
277293 // Create IO broker.
278294 const auto & low_prio_cpu_mask = cu_cfg.expert_execution_cfg .affinities .low_priority_cpu_cfg .mask ;
@@ -289,29 +305,33 @@ int main(int argc, char** argv)
289305 {f1c_sctp_cfg, *epoll_broker, *workers.non_rt_hi_prio_exec , *cu_cp_dlt_pcaps.f1ap });
290306 std::unique_ptr<srs_cu_cp::f1c_connection_server> cu_f1c_gw = srsran::create_f1c_gateway_server (f1c_server_cfg);
291307
292- // Create F1-U GW (TODO factory and cleanup).
308+ // Create F1-U GW.
309+ // > Create GTP-U Demux.
293310 gtpu_demux_creation_request cu_f1u_gtpu_msg = {};
294311 cu_f1u_gtpu_msg.cfg .warn_on_drop = true ;
295312 cu_f1u_gtpu_msg.gtpu_pcap = cu_up_dlt_pcaps.f1u .get ();
296313 std::unique_ptr<gtpu_demux> cu_f1u_gtpu_demux = create_gtpu_demux (cu_f1u_gtpu_msg);
297- udp_network_gateway_config cu_f1u_gw_config = {};
298- cu_f1u_gw_config.bind_address = cu_cfg.nru_cfg .bind_addr ;
299- cu_f1u_gw_config.bind_port = GTPU_PORT;
300- cu_f1u_gw_config.reuse_addr = false ;
301- cu_f1u_gw_config.pool_occupancy_threshold = cu_cfg.nru_cfg .pool_occupancy_threshold ;
302- std::unique_ptr<gtpu_gateway> cu_f1u_gw = create_udp_gtpu_gateway (
303- cu_f1u_gw_config, *epoll_broker, workers.cu_up_exec_mapper ->io_ul_executor (), *workers.non_rt_low_prio_exec );
304- std::unique_ptr<f1u_cu_up_udp_gateway> cu_f1u_conn = srs_cu_up::create_split_f1u_gw (
305- {*cu_f1u_gw, *cu_f1u_gtpu_demux, *cu_up_dlt_pcaps.f1u , GTPU_PORT, cu_cfg.nru_cfg .ext_addr });
314+ // > Create UDP gateway(s).
315+ std::vector<std::unique_ptr<gtpu_gateway>> cu_f1u_gws;
316+ for (const srs_cu::cu_f1u_socket_appconfig& sock_cfg : cu_cfg.f1u_cfg .f1u_socket_cfg ) {
317+ udp_network_gateway_config cu_f1u_gw_config = {};
318+ cu_f1u_gw_config.bind_address = sock_cfg.bind_addr ;
319+ cu_f1u_gw_config.ext_bind_addr = sock_cfg.udp_config .ext_addr ;
320+ cu_f1u_gw_config.bind_port = GTPU_PORT;
321+ cu_f1u_gw_config.reuse_addr = false ;
322+ cu_f1u_gw_config.pool_occupancy_threshold = sock_cfg.udp_config .pool_threshold ;
323+ cu_f1u_gw_config.rx_max_mmsg = sock_cfg.udp_config .rx_max_msgs ;
324+ std::unique_ptr<gtpu_gateway> cu_f1u_gw = create_udp_gtpu_gateway (
325+ cu_f1u_gw_config, *epoll_broker, workers.cu_up_exec_mapper ->io_ul_executor (), *workers.non_rt_low_prio_exec );
326+ cu_f1u_gws.push_back (std::move (cu_f1u_gw));
327+ }
328+ std::unique_ptr<f1u_cu_up_udp_gateway> cu_f1u_conn =
329+ srs_cu_up::create_split_f1u_gw ({cu_f1u_gws, *cu_f1u_gtpu_demux, *cu_up_dlt_pcaps.f1u , GTPU_PORT});
306330
307331 // Create E1AP local connector
308332 std::unique_ptr<e1_local_connector> e1_gw =
309333 create_e1_local_connector (e1_local_connector_config{*cu_up_dlt_pcaps.e1ap });
310334
311- // Create manager of timers for CU-CP and CU-UP, which will be driven by the system timer slot ticks.
312- timer_manager app_timers{256 };
313- timer_manager* cu_timers = &app_timers;
314-
315335 // Create time source that ticks the timers.
316336 std::optional<io_timer_source> time_source (
317337 std::in_place_t {}, app_timers, *epoll_broker, *workers.non_rt_hi_prio_exec , std::chrono::milliseconds{1 });
@@ -409,8 +429,8 @@ int main(int argc, char** argv)
409429
410430 // Close PCAPs
411431 cu_logger.info (" Closing PCAP files..." );
412- cu_cp_dlt_pcaps.close ();
413- cu_up_dlt_pcaps.close ();
432+ cu_cp_dlt_pcaps.reset ();
433+ cu_up_dlt_pcaps.reset ();
414434 cu_logger.info (" PCAP files successfully closed." );
415435
416436 // Stop workers
0 commit comments