helpGnuTLS - Support: sr #108715, DTLS send does not respect MTU

 
 

sr #108715: DTLS send does not respect MTU

Submitted by:  Andreas Schultz <roadrunnr>
Submitted on:  Mon 05 Jan 2015 02:31:23 PM UTC  
 
Category:  None Priority:  5 - Normal
Severity:  3 - Normal Status:  Done
Privacy:  Public Assigned to:  None
Open/Closed:  Closed Operating System:  None

Add a New Comment (Rich Markup)
   

You are not logged in

Please log in, so followups can be emailed to you.

 

Mon 05 Jan 2015 06:33:24 PM UTC, comment #5: 

>>   If there is a transport protocol indication (either via ICMP or via a
>>   refusal to send the datagram as in Section 14 of [DCCP]), then the
>>   DTLS record layer MUST inform the upper layer protocol of the error.
>That works only partially. The second part:
>>   or via a refusal to send the datagram
>does work, the push function would return the error and all is well.
>However with datagram sockets, sending an over sized datagram does not always result in an immediate EMSGSIZE error (at least under linux).


Correct. We rely on the OS for that.

> This ICMP error is not read nor handled in the DTLS layer. The only indication the caller gets is after the transmission timer expires and GNUTLS tries to send the packet again.


Indeed. I don't think we can do better than that though. Not with the standard sockets API at least. I'm open to suggestions on that.

> I might be wrong, but as far as I can see, there is no code that queries the underlying OS for the MTU (getsockopt IP_MTU under Linux) in case of a EMSGSIZE, nor does there seem to be any code to adjust the MTU. All of this is left to the application to handle.


You are correct. There is no generic or cross-platform API to handle that so the application is responsible to discover and set the MTU. Not sure how better we can do on that.

>>   -  If repeated retransmissions do not result in a response, and the
>>      PMTU is unknown, subsequent retransmissions SHOULD back off to a
>>      smaller record size, fragmenting the handshake message as
>>      appropriate.  This standard does not specify an exact number of
>>      retransmits to attempt before backing off, but 2-3 seems
>>      appropriate.
> It is arguable if this should be part of the library or not.


I would really have liked to include MTU handling as part of the library. However, it is very tricky to handle in all cases. There are real world scenarios where EMSGSIZE is never returned, from the OS because ICMP packets are blocked from the firewall. That, and the fact that MTU handling is restricted to handshake only, were the main reason it was not part of the library.

Having said that, I think it would be a nice idea to add a flag in gnutls_init() which makes MTU adjustment transparent, for the handshake at least.

Nikos Mavrogiannopoulos <nmav>
Project Administrator
Mon 05 Jan 2015 04:51:19 PM UTC, comment #4: 

ok, after reading the RFC again, if have to admit that "any" was way to strong. Most things are there and it just difficult from the documentation to understand what exactly the application has to implement and what is present in the library. The examples are also that helpful, as they don't adjust the MTU in the case or errors. So here is what I found surprising:

From RFC6347, Section 4.1.1.1:

>   If there is a transport protocol indication (either via ICMP or via a
>   refusal to send the datagram as in Section 14 of [DCCP]), then the
>   DTLS record layer MUST inform the upper layer protocol of the error.


That works only partially. The second part:

>   or via a refusal to send the datagram


does work, the push function would return the error and all is well.
However with datagram sockets, sending an over sized datagram does not always result in an immediate EMSGSIZE error (at least under linux).

At least under Linux, the EMSGSIZE is only returned if the datagram size exceeds the CACHED Path MTU. The Path MTU is initially assumed to be the same as the interface MTU (mostly 1500).

So GNUTLS will not report the proper error in the following scenario:

  • initial state: unknown peer, PMTU assumed to be YY
  • during handshake a datagram with YY bytes (minus header overhead) is sent, the writev call will not return an error
  • a ICMP Packet Too Big (max size XX bytes) is send from a router in the path and the packet is lost

This ICMP error is not read nor handled in the DTLS layer. The only indication the caller gets is after the transmission timer expires and GNUTLS tries to send the packet again.

>   discovery.  In order to allow connections under these circumstances,
>   DTLS implementations SHOULD follow the following rules:
>
>   -  If the DTLS record layer informs the DTLS handshake layer that a
>      message is too big, it SHOULD immediately attempt to fragment it,
>      using any existing information about the PMTU.


I might be wrong, but as far as I can see, there is no code that queries the underlying OS for the MTU (getsockopt IP_MTU under Linux) in case of a EMSGSIZE, nor does there seem to be any code to adjust the MTU. All of this is left to the application to handle.

>   -  If repeated retransmissions do not result in a response, and the
>      PMTU is unknown, subsequent retransmissions SHOULD back off to a
>      smaller record size, fragmenting the handshake message as
>      appropriate.  This standard does not specify an exact number of
>      retransmits to attempt before backing off, but 2-3 seems
>      appropriate.


It is arguable if this should be part of the library or not.

None of the above is an error, it just is a bit surprising. The manual does mention it briefly in chapter 6.5.2:

> The “correct” maximum transfer unit can be obtained through a path MTU discovery mechanism [RFC4821].

Andreas Schultz <roadrunnr>
Mon 05 Jan 2015 04:10:42 PM UTC, comment #3: 

Could you be more specific? What is missing?

Nikos Mavrogiannopoulos <nmav>
Project Administrator
Mon 05 Jan 2015 03:53:53 PM UTC, comment #2: 

mhh, yeah that fixes this specific MTU problem.

Maybe it should be documented that the GNUTLS DTLS network layer does not implemented any of the SHOULD's from RFC 6347 section 4.1.1.1. (https://tools.ietf.org/html/rfc6347#section-4.1.1.1)

Andreas Schultz <roadrunnr>
Mon 05 Jan 2015 03:34:00 PM UTC, comment #1: 
Nikos Mavrogiannopoulos <nmav>
Project Administrator
Mon 05 Jan 2015 02:31:23 PM UTC, original submission:  

The DTLS send function does not respect the MTU set via gnutls_dtls_set_mtu.

DTLS does fragment the record, but it passes all fragments on to writev, which will slap them all together into one datagram, ignoring the explicitly set MTU.

Test case for reproduction attached.

Andreas Schultz <roadrunnr>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #32762:  mini-dtls-mtu.c added by roadrunnr (8KiB - text/x-csrc)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by nmav (Posted a comment)
  • -email is unavailable- added by roadrunnr (Submitted the item)
  •  

    Do you think this task is very important?
    If so, you can add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.

     

     

     

    Follow 3 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2015-01-12 nmav StatusNone => Done
        Open/ClosedOpen => Closed
    2015-01-05 roadrunnr Attached File- => Added mini-dtls-mtu.c, #32762

    Back to the top


    Powered by Savane 3.5