From f2527c47bd48415ce2316d6457b2c5fe9162e815 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 7 Mar 2023 09:12:31 -0500 Subject: [PATCH] MT#55283 add "control-pmtu" option Change-Id: I4c7319f69dc5242bd6a35ab13a9aa72f394b5d5c --- daemon/control_ng.c | 4 ++++ daemon/main.c | 13 +++++++++++++ daemon/rtpengine.pod | 14 ++++++++++++++ etc/rtpengine.conf | 1 + include/main.h | 5 +++++ lib/socket.c | 6 ++++++ lib/socket.h | 5 +++++ 7 files changed, 48 insertions(+) diff --git a/daemon/control_ng.c b/daemon/control_ng.c index 3a297b5c8..461b008c2 100644 --- a/daemon/control_ng.c +++ b/daemon/control_ng.c @@ -21,6 +21,7 @@ #include "streambuf.h" #include "str.h" #include "tcp_listener.h" +#include "main.h" mutex_t rtpe_cngs_lock; mutex_t tcp_connections_lock; @@ -544,6 +545,9 @@ struct control_ng *control_ng_new(struct poller *p, endpoint_t *ep, unsigned cha goto fail2; if (tos) set_tos(&c->udp_listener, tos); + if (rtpe_config.control_pmtu) + set_pmtu_disc(&c->udp_listener, + rtpe_config.control_pmtu == PMTU_DISC_WANT ? IP_PMTUDISC_WANT : IP_PMTUDISC_DONT); return c; fail2: diff --git a/daemon/main.c b/daemon/main.c index 542f01815..68d569750 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -451,6 +451,7 @@ static void options(int *argc, char ***argv) { AUTO_CLEANUP_GBUF(mos); AUTO_CLEANUP_GBUF(dcc); AUTO_CLEANUP_GBUF(use_audio_player); + AUTO_CLEANUP_GBUF(control_pmtu); rwlock_lock_w(&rtpe_config.config_lock); @@ -471,6 +472,7 @@ static void options(int *argc, char ***argv) { { "graphite-timeout", 0, 0, G_OPTION_ARG_INT, &rtpe_config.graphite_timeout, "Graphite socket timeout interval in seconds", "INT" }, { "tos", 'T', 0, G_OPTION_ARG_INT, &rtpe_config.default_tos, "Default TOS value to set on streams", "INT" }, { "control-tos",0 , 0, G_OPTION_ARG_INT, &rtpe_config.control_tos, "Default TOS value to set on control-ng", "INT" }, + { "control-pmtu", 0,0, G_OPTION_ARG_STRING, &control_pmtu, "Path MTU discovery behaviour on UDP control sockets", "want|dont" }, { "timeout", 'o', 0, G_OPTION_ARG_INT, &rtpe_config.timeout, "RTP timeout", "SECS" }, { "silent-timeout",'s',0,G_OPTION_ARG_INT, &rtpe_config.silent_timeout,"RTP timeout for muted", "SECS" }, { "final-timeout",'a',0,G_OPTION_ARG_INT, &rtpe_config.final_timeout, "Call timeout", "SECS" }, @@ -903,6 +905,17 @@ static void options(int *argc, char ***argv) { die("Invalid --dtls-cert-cipher option ('%s')", dcc); } + if (control_pmtu) { + if (!strcasecmp(control_pmtu, "want")) + rtpe_config.control_pmtu = PMTU_DISC_WANT; + else if (!strcasecmp(control_pmtu, "dont")) + rtpe_config.control_pmtu = PMTU_DISC_DONT; + else if (!strcasecmp(control_pmtu, "don't")) + rtpe_config.control_pmtu = PMTU_DISC_DONT; + else + die("Invalid --control-pmtu option ('%s')", control_pmtu); + } + rwlock_unlock_w(&rtpe_config.config_lock); } diff --git a/daemon/rtpengine.pod b/daemon/rtpengine.pod index 6e8adc8c6..cfc1f2664 100644 --- a/daemon/rtpengine.pod +++ b/daemon/rtpengine.pod @@ -162,6 +162,20 @@ should be set in the control-ng interface packets. The default is to leave the TOS field untouched. This parameter can also be set or listed via B. +=item B<--control-pmtu=>B|B + +Forces a specific PMTU discovery behaviour on IPv4 UDP control sockets, +overriding the system-wide default. If set to B then path MTU discovery +is performed, initially enabling the DF (don't fragment) bit on outgoing IPv4 +packets until the path MTU has been discovered through reception of a +"fragmentation needed" ICMP packet. If set to B then path MTU discovery +is disabled, leaving the DF bit unset, and relying on the routers within the +network path to perform any necessary fragmentation. + +The setting of B is useful in broken IPv4 environments without +functioning PMTU discovery, for example in networks which unconditionally block +all ICMP. + =item B<-o>, B<--timeout=>I Takes the number of seconds as argument after which a media stream should diff --git a/etc/rtpengine.conf b/etc/rtpengine.conf index 202a19fd5..cfcc88d76 100644 --- a/etc/rtpengine.conf +++ b/etc/rtpengine.conf @@ -34,6 +34,7 @@ timeout = 60 silent-timeout = 3600 tos = 184 # control-tos = 184 +# control-pmtu = dont # delete-delay = 30 # final-timeout = 10800 # endpoint-learning = heuristic diff --git a/include/main.h b/include/main.h index 900b43c7d..5b569854c 100644 --- a/include/main.h +++ b/include/main.h @@ -45,6 +45,11 @@ struct rtpengine_config { char *b2b_url; int default_tos; int control_tos; + enum { + PMTU_DISC_DEFAULT = 0, + PMTU_DISC_WANT, + PMTU_DISC_DONT, + } control_pmtu; enum xmlrpc_format fmt; enum log_format log_format; endpoint_t graphite_ep; diff --git a/lib/socket.c b/lib/socket.c index a740840c5..3dd769aeb 100644 --- a/lib/socket.c +++ b/lib/socket.c @@ -40,6 +40,7 @@ static ssize_t __ip_sendto(socket_t *s, const void *buf, size_t len, const endpo static int __ip4_tos(socket_t *, unsigned int); static int __ip6_tos(socket_t *, unsigned int); static int __ip_error(socket_t *s); +static void __ip4_pmtu_disc(socket_t *, int); static void __ip4_endpoint2kernel(struct re_address *, const endpoint_t *); static void __ip6_endpoint2kernel(struct re_address *, const endpoint_t *); static void __ip4_kernel2endpoint(endpoint_t *ep, const struct re_address *ra); @@ -86,6 +87,7 @@ static struct socket_family __socket_families[__SF_LAST] = { .sendto = __ip_sendto, .tos = __ip4_tos, .error = __ip_error, + .pmtu_disc = __ip4_pmtu_disc, .endpoint2kernel = __ip4_endpoint2kernel, .kernel2endpoint = __ip4_kernel2endpoint, .packet_header = __ip4_packet_header, @@ -379,6 +381,10 @@ static int __ip_error(socket_t *s) { return -1; return optval; } +static void __ip4_pmtu_disc(socket_t *s, int opt) { + if (setsockopt(s->fd, IPPROTO_IP, IP_MTU_DISCOVER, &opt, sizeof(opt))) + ilog(LOG_ERR, "Failed to set PMTU discovery option on IPv4 socket: %s", strerror(errno)); +} static int __ip_timestamping(socket_t *s) { int one = 1; if (setsockopt(s->fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one))) diff --git a/lib/socket.h b/lib/socket.h index d57b30b31..2548179fe 100644 --- a/lib/socket.h +++ b/lib/socket.h @@ -77,6 +77,7 @@ struct socket_family { ssize_t (*sendmsg)(socket_t *, struct msghdr *, const endpoint_t *); ssize_t (*sendto)(socket_t *, const void *, size_t, const endpoint_t *); int (*tos)(socket_t *, unsigned int); + void (*pmtu_disc)(socket_t *, int); int (*error)(socket_t *); void (*endpoint2kernel)(struct re_address *, const endpoint_t *); void (*kernel2endpoint)(endpoint_t *, const struct re_address *); @@ -294,6 +295,10 @@ INLINE int ipv46_any_convert(endpoint_t *ep) { INLINE void set_tos(socket_t *s, unsigned int tos) { s->family->tos(s, tos); } +INLINE void set_pmtu_disc(socket_t *s, int opt) { + if (s->family->pmtu_disc) + s->family->pmtu_disc(s, opt); +} socktype_t *get_socket_type(const str *s); socktype_t *get_socket_type_c(const char *s);