[vlc-devel] [PATCH] access/udp: reduce mtu amount on initial packets

Ilkka Ollakka ileoo at videolan.org
Tue Oct 16 20:16:19 CEST 2018


In this approach, mtu is setted to high on start, and if received data
is less than 1500 and mtu is higher than that, we adjust mtu on future
packets to be smaller. In majority of cases in UDP streaming, packet
size is usually quite constant, so it should work, even if it's not
generic solution to udp packet receiving.

Also in case of truncing packets on other than linux systems, use same
assumption and peek the next data amount to adjust mtu for future
packets. We don't call PEEK on all the cases, as it would be unnecessary
system call on majority of the calls.

ref #20952 and other similar tickets.
---
 modules/access/udp.c | 49 ++++++++++++++++++++++++++++++++++++--------
 1 file changed, 40 insertions(+), 9 deletions(-)

diff --git a/modules/access/udp.c b/modules/access/udp.c
index 654ecf83c3..1c844660ea 100644
--- a/modules/access/udp.c
+++ b/modules/access/udp.c
@@ -168,7 +168,7 @@ static int Open( vlc_object_t *p_this )
         return VLC_EGENERIC;
     }
 
-    sys->mtu = 7 * 188;
+    sys->mtu = 65536;
 
     sys->timeout = var_InheritInteger( p_access, "udp-timeout");
     if( sys->timeout > 0)
@@ -231,11 +231,6 @@ static block_t *BlockUDP(stream_t *access, bool *restrict eof)
         return NULL;
     }
 
-#ifdef __linux__
-    const int trunc_flag = MSG_TRUNC;
-#else
-    const int trunc_flag = 0;
-#endif
 
     struct iovec iov = {
         .iov_base = pkt->p_buffer,
@@ -244,7 +239,6 @@ static block_t *BlockUDP(stream_t *access, bool *restrict eof)
     struct msghdr msg = {
         .msg_iov = &iov,
         .msg_iovlen = 1,
-        .msg_flags = trunc_flag,
     };
 
     struct pollfd ufd[1];
@@ -262,6 +256,12 @@ static block_t *BlockUDP(stream_t *access, bool *restrict eof)
             goto skip;
      }
 
+#ifdef __linux__
+    const int trunc_flag = MSG_TRUNC;
+#else
+    const int trunc_flag = 0;
+#endif
+
     ssize_t len = recvmsg(sys->fd, &msg, trunc_flag);
 
     if (len < 0)
@@ -271,14 +271,45 @@ skip:
         return NULL;
     }
 
-    if (msg.msg_flags & trunc_flag)
+    /* Check if received amount is other side of ethernet mtu amount of 1500,
+       and reduce mtu if it's so. Failsafe to keep mtu still atleast 1000 bytes.
+       With this approach, we can start with way higher than needed mtu for 1 packet
+       and with first packets, it should adjust to reasonable size.
+       Assuming that most cases in real world the udp packet size don't fluctuate
+       huge amounts on size in streaming. And on those cases the MSG_TRUNC should
+       then readjust.
+     */
+
+    if (unlikely((sys->mtu > 1500) && (len > 1000) && (len < 1500)))
+    {
+        msg_Dbg(access, "adjusting MTU from %zd to %zu", sys->mtu, len);
+        sys->mtu = len;
+    }
+
+#ifdef MSG_TRUNC
+    if (msg.msg_flags & MSG_TRUNC)
     {
+        pkt->i_flags |= BLOCK_FLAG_CORRUPTED;
+        /* On linux systems MSG_TRUNC tells the available data,
+           on other cases, I think we need to use MSG_PEEK to get how much
+           there would be availabled in case of trunced message.
+           In MSG_PEEK case, assumption is also, that in real world
+           the size don't fluctuate huge amounts in streaming.
+         */
+# ifdef __linux__
         msg_Err(access, "%zd bytes packet truncated (MTU was %zu)",
                 len, sys->mtu);
-        pkt->i_flags |= BLOCK_FLAG_CORRUPTED;
         sys->mtu = len;
+# else
+        unsigned char peek_buffer[65536];
+        size_t old_mtu = sys->mtu;
+        sys->mtu = recv(sys->fd, peek_buffer, 65536, MSG_PEEK);
+        msg_Err(access, "%zd bytes packet truncated (MTU was %zu)",
+                sys->mtu, old_mtu);
+# endif
     }
     else
+#endif
         pkt->i_buffer = len;
 
     return pkt;
-- 
2.19.1



More information about the vlc-devel mailing list