From 04da1892256999a9549775820758a187fcb19070 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 14 Aug 2018 13:22:10 +0100 Subject: [PATCH] Make datagram packing dynamically configurable This commit adds a public function `mbedtls_ssl_conf_datagram_packing()` that allows to allow / forbid the packing of multiple records within a single datagram. --- include/mbedtls/ssl.h | 37 +++++++++++++++++++++++++++++++++++++ library/ssl_tls.c | 16 +++++++++++++--- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index f27f6c02f..85ab72206 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -1102,6 +1102,11 @@ struct mbedtls_ssl_context int keep_current_message; /*!< drop or reuse current message on next call to record layer? */ +#if defined(MBEDTLS_SSL_PROTO_DTLS) + uint8_t disable_datagram_packing; /*!< Disable packing multiple records + * within a single datagram. */ +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + /* * Record layer (outgoing data) */ @@ -1763,6 +1768,38 @@ void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limi #endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */ #if defined(MBEDTLS_SSL_PROTO_DTLS) + +/** + * \brief Allow or disallow packing of multiple handshake records + * within a single datagram. + * + * \param ssl The SSL context to configure. + * \param allow_packing This determines whether datagram packing may + * be used or not. A value of \c 0 means that every + * record will be sent in a separate datagram; a + * value of \c 1 means that, if space permits, + * multiple handshake messages (including CCS) belonging to + * a single flight may be packed within a single datagram. + * + * \note This is enabled by default and should only be disabled + * for test purposes, or if datagram packing causes + * interoperability issues with peers that don't support it. + * + * \note Allowing datagram packing reduces the network load since + * there's less overhead if multiple messages share the same + * datagram. Also, it increases the handshake efficiency + * since messages belonging to a single datagram will not + * be reordered in transit, and so future message buffering + * or flight retransmission (if no buffering is used) as + * means to deal with reordering are needed less frequently. + * + * \note Application datagrams are not affected by this option and + * are currently always sent in separate datagrams. + * + */ +void mbedtls_ssl_conf_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ); + /** * \brief Set retransmit timeout values for the DTLS handshake. * (DTLS only, no effect on TLS.) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 98e508ec6..9b8f7fea3 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -2923,6 +2923,9 @@ int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) size_t max_frag_len; const mbedtls_ssl_flight_item * const cur = ssl->handshake->cur_msg; + uint8_t const force_flush = ssl->disable_datagram_packing == 1 ? + SSL_FORCE_FLUSH : SSL_DONT_FORCE_FLUSH; + /* Swap epochs before sending Finished: we can't do it after * sending ChangeCipherSpec, in case write returns WANT_READ. * Must be done before copying, may change out_msg pointer */ @@ -3030,8 +3033,7 @@ int mbedtls_ssl_flight_transmit( mbedtls_ssl_context *ssl ) } /* Actually send the message out */ - if( ( ret = mbedtls_ssl_write_record( ssl, - SSL_DONT_FORCE_FLUSH ) ) != 0 ) + if( ( ret = mbedtls_ssl_write_record( ssl, force_flush ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); return( ret ); @@ -6432,7 +6434,15 @@ void mbedtls_ssl_conf_dtls_badmac_limit( mbedtls_ssl_config *conf, unsigned limi #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) -void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, uint32_t min, uint32_t max ) + +void mbedtls_ssl_conf_datagram_packing( mbedtls_ssl_context *ssl, + unsigned allow_packing ) +{ + ssl->disable_datagram_packing = !allow_packing; +} + +void mbedtls_ssl_conf_handshake_timeout( mbedtls_ssl_config *conf, + uint32_t min, uint32_t max ) { conf->hs_timeout_min = min; conf->hs_timeout_max = max;