[vlc-commits] access/udp: use overflow block on recvmsg() to adjust mtu

Nick Briggs git at videolan.org
Sun Nov 4 21:23:28 CET 2018


vlc | branch: master | Nick Briggs <nicholas.h.briggs at gmail.com> | Sat Nov  3 14:30:35 2018 +0200| [4f633b7ad7af54e3be2799b0e40580346e9feaba] | committer: Ilkka Ollakka

access/udp: use overflow block on recvmsg() to adjust mtu

Add second block on recvmsg() to check if we need to adjust mtu to be
higher. With this approach, we will do extra memcpy and allocation in
codepaths where mtu should be increased, but not on normal codepath.

Allocates the minimum sized overflow block to capture the maximum
sized datagram when combined with the normal (mtu sized) block.

This uses the same approach on all platforms and doesn't rely on
MSG_TRUNC in linux case and something else in other cases.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=4f633b7ad7af54e3be2799b0e40580346e9feaba
---

 modules/access/udp.c | 50 ++++++++++++++++++++++++++++++++++----------------
 1 file changed, 34 insertions(+), 16 deletions(-)

diff --git a/modules/access/udp.c b/modules/access/udp.c
index 654ecf83c3..a947bb2c1f 100644
--- a/modules/access/udp.c
+++ b/modules/access/udp.c
@@ -81,6 +81,7 @@ typedef struct
     int fd;
     int timeout;
     size_t mtu;
+    block_t *overflow_block;
 } access_sys_t;
 
 /*****************************************************************************
@@ -104,6 +105,15 @@ static int Open( vlc_object_t *p_this )
     if( unlikely( sys == NULL ) )
         return VLC_ENOMEM;
 
+    sys->mtu = 7 * 188;
+
+    /* Overflow can be max theoretical datagram content less anticipated MTU,
+     *  IPv6 headers are larger than IPv4, ignore IPv6 jumbograms
+     */
+    sys->overflow_block = block_Alloc(65507 - sys->mtu);
+    if( unlikely( sys->overflow_block == NULL ) )
+        return VLC_ENOMEM;
+
     p_access->p_sys = sys;
 
     /* Set up p_access */
@@ -168,8 +178,6 @@ static int Open( vlc_object_t *p_this )
         return VLC_EGENERIC;
     }
 
-    sys->mtu = 7 * 188;
-
     sys->timeout = var_InheritInteger( p_access, "udp-timeout");
     if( sys->timeout > 0)
         sys->timeout *= 1000;
@@ -184,6 +192,8 @@ static void Close( vlc_object_t *p_this )
 {
     stream_t     *p_access = (stream_t*)p_this;
     access_sys_t *sys = p_access->p_sys;
+    if( sys->overflow_block )
+        block_Release( sys->overflow_block );
 
     net_Close( sys->fd );
 }
@@ -231,20 +241,17 @@ 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 = {
+    struct iovec iov[] = {{
         .iov_base = pkt->p_buffer,
         .iov_len = sys->mtu,
-    };
+    },{
+        .iov_base = sys->overflow_block->p_buffer,
+        .iov_len = sys->overflow_block->i_buffer,
+    }};
     struct msghdr msg = {
-        .msg_iov = &iov,
-        .msg_iovlen = 1,
-        .msg_flags = trunc_flag,
+        .msg_iov = iov,
+        .msg_iovlen = 2,
     };
 
     struct pollfd ufd[1];
@@ -262,7 +269,7 @@ static block_t *BlockUDP(stream_t *access, bool *restrict eof)
             goto skip;
      }
 
-    ssize_t len = recvmsg(sys->fd, &msg, trunc_flag);
+    ssize_t len = recvmsg(sys->fd, &msg, 0);
 
     if (len < 0)
     {
@@ -271,11 +278,22 @@ skip:
         return NULL;
     }
 
-    if (msg.msg_flags & trunc_flag)
+    /* Received more than mtu amount,
+     * we should gather blocks and increase mtu
+     * and allocate new overflow block.  See Open()
+     */
+    if (unlikely(len > sys->mtu))
     {
-        msg_Err(access, "%zd bytes packet truncated (MTU was %zu)",
+        msg_Warn(access, "%zd bytes packet received (MTU was %zu), adjusting mtu",
                 len, sys->mtu);
-        pkt->i_flags |= BLOCK_FLAG_CORRUPTED;
+        block_t *gather_block = sys->overflow_block;
+
+        sys->overflow_block = block_Alloc(65507 - len);
+
+        gather_block->i_buffer = len - sys->mtu;
+        pkt->p_next = gather_block;
+        pkt = block_ChainGather( pkt );
+
         sys->mtu = len;
     }
     else



More information about the vlc-commits mailing list