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

Nick Briggs nicholas.h.briggs at gmail.com
Tue Oct 16 18:10:27 CEST 2018


> Date: Mon, 15 Oct 2018 21:30:53 +0300
> From: Ilkka Ollakka <ileoo at videolan.org>
> To: vlc-devel at videolan.org
> Subject: [vlc-devel] [PATCH 3/3] access/udp: reduce mtu amount on
> 	initial packets
> Message-ID: <20181015183053.27240-3-ileoo at videolan.org>
> 
> 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 | 40 +++++++++++++++++++++++++++++++++++++---
> 1 file changed, 37 insertions(+), 3 deletions(-)
> 
> diff --git a/modules/access/udp.c b/modules/access/udp.c
> index b5ba292e48..7648b2ebc6 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)
> @@ -262,6 +262,7 @@ static block_t *BlockUDP(stream_t *access, bool *restrict eof)
>             goto skip;
>      }
> 
> +
>     ssize_t len = recvmsg(sys->fd, &msg, trunc_flag);
> 
>     if (len < 0)
> @@ -271,14 +272,47 @@ 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 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
> +        sys->mtu = recv(sys->fd, pkt->p_buffer, sys->mtu, MSG_PEEK|MSG_TRUNC);

Perhaps I'm confused, but on a non-Linux system (MacOS, [Free|Open]BSD) MSG_TRUNC is not an input flag for a recv() call.
On those systems MSG_TRUNC is only ever an output flag returned in the msghdr.msg_flags.

> +        /* In this case, len is old mtu and max received amount, mtu is the
> +         * peeked value, that's why they are otherway around in this compared
> +         * to __linux__ case error
> +         */
> +        msg_Err(access, "%zd bytes packet truncated (MTU was %zu)",
> +                sys->mtu, len);
> +#endif
>     }
>     else
> +#endif
>         pkt->i_buffer = len;
> 
>     return pkt;
> -- 
> 2.19.0
> 
> 
> 
> ------------------------------
> 
> Message: 14
> Date: Mon, 15 Oct 2018 21:30:52 +0300
> From: Ilkka Ollakka <ileoo at videolan.org>
> To: vlc-devel at videolan.org
> Subject: [vlc-devel] [PATCH 2/3] access/udp: Define MSG_TRUNC on recv
> 	call
> Message-ID: <20181015183053.27240-2-ileoo at videolan.org>
> 
> recv() needs MSG_TRUNC flag so it will tell actual data-size if truncate
> would happen additional to setting flag for it.
For Linux, but not for MacOS/FreeBSD/OpenBSD

> 
> Tested adjustment of MTU by sending data to localhost via netcat:
> 
> cat ~/tmp/myfile.mp3|netcat -u 127.0.0.1 1234
> 
> and vlc -Idummy -vv udp://@127.0.0.1:1234 --sout="#stat"
> 
> without this patch the udp input constantly complains about trunced
> input and doesn't adjust the receiving amount.
> 
> udp fixup
> ---
> modules/access/udp.c | 17 ++++++++++-------
> 1 file changed, 10 insertions(+), 7 deletions(-)
> 
> diff --git a/modules/access/udp.c b/modules/access/udp.c
> index d84cb7b99a..b5ba292e48 100644
> --- a/modules/access/udp.c
> +++ b/modules/access/udp.c
> @@ -231,6 +231,12 @@ 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
> +

MacOS has the MSG_TRUNC flag, and if you do this you won't be able to check the msg.msg_flags returned value later -- is that what you intended?

>     struct iovec iov = {
>         .iov_base = pkt->p_buffer,
>         .iov_len = sys->mtu,
> @@ -238,9 +244,7 @@ static block_t *BlockUDP(stream_t *access, bool *restrict eof)
>     struct msghdr msg = {
>         .msg_iov = &iov,
>         .msg_iovlen = 1,
> -#ifdef __linux__
> -        .msg_flags = MSG_TRUNC,
> -#endif
> +        .msg_flags = trunc_flag,

Isn't this an output only field? At least that's what the documentation implies even on Linux.

>     };
> 
>     struct pollfd ufd[1];
> @@ -258,7 +262,8 @@ static block_t *BlockUDP(stream_t *access, bool *restrict eof)
>             goto skip;
>      }
> 
> -    ssize_t len = recvmsg(sys->fd, &msg, 0);
> +    ssize_t len = recvmsg(sys->fd, &msg, trunc_flag);
> +
>     if (len < 0)
>     {
> skip:
> @@ -266,8 +271,7 @@ skip:
>         return NULL;
>     }
> 
> -#ifdef MSG_TRUNC
> -    if (msg.msg_flags & MSG_TRUNC)
> +    if (msg.msg_flags & trunc_flag )
>     {
>         msg_Err(access, "%zd bytes packet truncated (MTU was %zu)",
>                 len, sys->mtu);
> @@ -275,7 +279,6 @@ skip:
>         sys->mtu = len;
>     }
>     else
> -#endif
>         pkt->i_buffer = len;
> 
>     return pkt;
> -- 
> 2.19.0
> 



More information about the vlc-devel mailing list