From ba5684d0d777f593d4ece87582f2acc54521d760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 13 Nov 2023 16:27:48 +0200 Subject: [PATCH] ptp: Add `ttl` configuration to gst_ptp_init_full() This allows configuring the TTL that is used for multicast packets sent out on the sockets, and is defaulting to 1 as before. The default might change at some point. In some networks multiple hops are needed to reach the PTP clock and this allows to configure GStreamer in a way that works in such networks. At a later time, per-domain or per-interface TTL configurations might be added when needed. Part-of: --- .../gstreamer/libs/gst/helpers/ptp/args.rs | 8 ++++++++ .../gstreamer/libs/gst/helpers/ptp/main.rs | 16 +++++++++------- subprojects/gstreamer/libs/gst/net/gstptpclock.c | 11 ++++++++++- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/subprojects/gstreamer/libs/gst/helpers/ptp/args.rs b/subprojects/gstreamer/libs/gst/helpers/ptp/args.rs index 75a497c1ac..fa62c5fe7c 100644 --- a/subprojects/gstreamer/libs/gst/helpers/ptp/args.rs +++ b/subprojects/gstreamer/libs/gst/helpers/ptp/args.rs @@ -21,6 +21,7 @@ pub struct Args { pub interfaces: Vec, pub verbose: bool, pub clock_id: u64, + pub ttl: u32, } /// Parse the command-line arguments. @@ -28,6 +29,7 @@ pub fn parse_args() -> Result { let mut interfaces = Vec::new(); let mut verbose = false; let mut clock_id = 0; + let mut ttl = 1; let mut args = env::args(); // Skip executable name @@ -50,6 +52,11 @@ pub fn parse_args() -> Result { clock_id = u64::from_str_radix(&clock_id_arg[2..], 16).context("Invalid clock ID")?; } + "--ttl" => { + let ttl_arg = args.next().context("No TTL following --ttl")?; + ttl = ttl_arg.parse::().context("Invalid TTL value")?; + } + arg => { bail!("Unknown command-line argument {}", arg); } @@ -60,6 +67,7 @@ pub fn parse_args() -> Result { interfaces, verbose, clock_id, + ttl, }; info!("Running with arguments {:#?}", args); diff --git a/subprojects/gstreamer/libs/gst/helpers/ptp/main.rs b/subprojects/gstreamer/libs/gst/helpers/ptp/main.rs index ece3329589..f230198418 100644 --- a/subprojects/gstreamer/libs/gst/helpers/ptp/main.rs +++ b/subprojects/gstreamer/libs/gst/helpers/ptp/main.rs @@ -58,16 +58,18 @@ const MSG_TYPE_CLOCK_ID: u8 = 2; const MSG_TYPE_SEND_TIME_ACK: u8 = 3; /// Create a new `UdpSocket` for the given port and configure it for PTP. -fn create_socket(port: u16, iface: &net::InterfaceInfo) -> Result { +fn create_socket(port: u16, iface: &net::InterfaceInfo, ttl: u32) -> Result { let socket = net::create_udp_socket(&Ipv4Addr::UNSPECIFIED, port, Some(iface)) .with_context(|| format!("Failed to bind socket to port {}", port))?; socket .set_nonblocking(true) .context("Failed setting socket non-blocking")?; - socket.set_ttl(1).context("Failed setting TTL on socket")?; socket - .set_multicast_ttl_v4(1) + .set_ttl(ttl) + .context("Failed setting TTL on socket")?; + socket + .set_multicast_ttl_v4(ttl) .context("Failed to set multicast TTL on socket")?; Ok(socket) @@ -123,10 +125,10 @@ fn run() -> Result<(), Error> { for iface in &ifaces { info!("Binding to interface {}", iface.name); - let event_socket = - create_socket(PTP_EVENT_PORT, iface).context("Failed creating event socket")?; - let general_socket = - create_socket(PTP_GENERAL_PORT, iface).context("Failed creating general socket")?; + let event_socket = create_socket(PTP_EVENT_PORT, iface, args.ttl) + .context("Failed creating event socket")?; + let general_socket = create_socket(PTP_GENERAL_PORT, iface, args.ttl) + .context("Failed creating general socket")?; for socket in [&event_socket, &general_socket].iter() { net::join_multicast_v4(socket, &PTP_MULTICAST_ADDR, iface) diff --git a/subprojects/gstreamer/libs/gst/net/gstptpclock.c b/subprojects/gstreamer/libs/gst/net/gstptpclock.c index 0c3c252813..09f482ecd1 100644 --- a/subprojects/gstreamer/libs/gst/net/gstptpclock.c +++ b/subprojects/gstreamer/libs/gst/net/gstptpclock.c @@ -2680,6 +2680,8 @@ count_directories (const char *filepath) * interface. * * #GStrv `interfaces`: The interface names to listen on for PTP packets. If * none are provided then all compatible interfaces will be used. + * * #guint `ttl`: The TTL to use for multicast packets sent out by GStreamer. + * This defaults to 1, i.e. packets will not leave the local network. * * This function is automatically called by gst_ptp_clock_new() with default * parameters if it wasn't called before. @@ -2698,6 +2700,7 @@ gst_ptp_init_full (const GstStructure * config) guint64 clock_id = GST_CLOCK_TIME_NONE; const GValue *v; gchar **interfaces = NULL; + guint ttl = 1; GError *err = NULL; GST_DEBUG_CATEGORY_INIT (ptp_debug, "ptp", 0, "PTP clock"); @@ -2726,7 +2729,7 @@ gst_ptp_init_full (const GstStructure * config) } argc = 1; - gst_structure_get_uint64(config, "clock-id", &clock_id); + gst_structure_get_uint64 (config, "clock-id", &clock_id); if (clock_id != GST_PTP_CLOCK_ID_NONE) argc += 2; v = gst_structure_get_value (config, "interfaces"); @@ -2734,7 +2737,10 @@ gst_ptp_init_full (const GstStructure * config) interfaces = g_value_get_boxed (v); if (interfaces != NULL) argc += 2 * g_strv_length (interfaces); + gst_structure_get_uint (config, "ttl", &ttl); + argc += 2; + // 3 for: executable, -v and NULL argv = g_new0 (gchar *, argc + 3); argc_c = 0; @@ -2814,6 +2820,9 @@ gst_ptp_init_full (const GstStructure * config) } } + argv[argc_c++] = g_strdup ("--ttl"); + argv[argc_c++] = g_strdup_printf ("%u", ttl); + /* Check if the helper process should be verbose */ env = g_getenv ("GST_PTP_HELPER_VERBOSE"); if (env && g_ascii_strcasecmp (env, "no") != 0) {