From cd715b7e7fdd2aeb0fd80220d2df5187b291f87a Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Wed, 9 Nov 2022 11:26:11 +0200 Subject: Add support for KTLS zerocopy sendfile on Linux TLS device offload allows to perform zerocopy sendfile transmissions. FreeBSD provides this feature by default, and Linux 5.19 introduced it as an opt-in. Zerocopy improves the TX rate significantly, but has a side effect: if the underlying file is changed while being transmitted, and a TCP retransmission happens, the receiver may get a TLS record containing both new and old data, which leads to an authentication failure and termination of connection. This effect is the reason Linux makes a copy on sendfile by default. This commit adds support for TLS zerocopy sendfile on Linux disabled by default to avoid any unlikely backward compatibility issues on Linux, although sacrificing consistency in OpenSSL's behavior on Linux and FreeBSD. A new option called KTLSTxZerocopySendfile is added to enable the new zerocopy behavior on Linux. This option should be used when the the application guarantees that the file is not modified during transmission, or it doesn't care about breaking the connection. The related documentation is also added in this commit. The unit test added doesn't test the actual functionality (it would require specific hardware and a non-local peer), but solely checks that it's possible to set the new option flag. Signed-off-by: Maxim Mikityanskiy Reviewed-by: Tariq Toukan Reviewed-by: Boris Pismenny Reviewed-by: Matt Caswell Reviewed-by: Todd Short Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/18650) --- apps/s_server.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'apps') diff --git a/apps/s_server.c b/apps/s_server.c index f519505ade..46af6b87da 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -96,6 +96,7 @@ static int keymatexportlen = 20; static int async = 0; static int use_sendfile = 0; +static int use_zc_sendfile = 0; static const char *session_id_prefix = NULL; @@ -716,6 +717,7 @@ typedef enum OPTION_choice { OPT_KEYLOG_FILE, OPT_MAX_EARLY, OPT_RECV_MAX_EARLY, OPT_EARLY_DATA, OPT_S_NUM_TICKETS, OPT_ANTI_REPLAY, OPT_NO_ANTI_REPLAY, OPT_SCTP_LABEL_BUG, OPT_HTTP_SERVER_BINMODE, OPT_NOCANAMES, OPT_IGNORE_UNEXPECTED_EOF, OPT_KTLS, + OPT_USE_ZC_SENDFILE, OPT_TFO, OPT_CERT_COMP, OPT_R_ENUM, OPT_S_ENUM, @@ -966,6 +968,7 @@ const OPTIONS s_server_options[] = { #ifndef OPENSSL_NO_KTLS {"ktls", OPT_KTLS, '-', "Enable Kernel TLS for sending and receiving"}, {"sendfile", OPT_SENDFILE, '-', "Use sendfile to response file with -WWW"}, + {"zerocopy_sendfile", OPT_USE_ZC_SENDFILE, '-', "Use zerocopy mode of KTLS sendfile"}, #endif OPT_R_OPTIONS, @@ -1080,6 +1083,7 @@ int s_server_main(int argc, char *argv[]) s_brief = 0; async = 0; use_sendfile = 0; + use_zc_sendfile = 0; port = OPENSSL_strdup(PORT); cctx = SSL_CONF_CTX_new(); @@ -1654,6 +1658,11 @@ int s_server_main(int argc, char *argv[]) case OPT_SENDFILE: #ifndef OPENSSL_NO_KTLS use_sendfile = 1; +#endif + break; + case OPT_USE_ZC_SENDFILE: +#ifndef OPENSSL_NO_KTLS + use_zc_sendfile = 1; #endif break; case OPT_IGNORE_UNEXPECTED_EOF: @@ -1728,6 +1737,11 @@ int s_server_main(int argc, char *argv[]) #endif #ifndef OPENSSL_NO_KTLS + if (use_zc_sendfile && !use_sendfile) { + BIO_printf(bio_out, "Warning: -zerocopy_sendfile depends on -sendfile, enabling -sendfile now.\n"); + use_sendfile = 1; + } + if (use_sendfile && enable_ktls == 0) { BIO_printf(bio_out, "Warning: -sendfile depends on -ktls, enabling -ktls now.\n"); enable_ktls = 1; @@ -1933,6 +1947,8 @@ int s_server_main(int argc, char *argv[]) #ifndef OPENSSL_NO_KTLS if (enable_ktls) SSL_CTX_set_options(ctx, SSL_OP_ENABLE_KTLS); + if (use_zc_sendfile) + SSL_CTX_set_options(ctx, SSL_OP_ENABLE_KTLS_TX_ZEROCOPY_SENDFILE); #endif if (max_send_fragment > 0 -- cgit v1.2.3