From 29f31a90e137d1d0334e6af169579983925668f3 Mon Sep 17 00:00:00 2001 From: Evgeniy Kochetov Date: Tue, 14 Jul 2020 22:03:45 +0300 Subject: [PATCH] sock: Add sock_impl option to disable zero copy on send Zero copy send can cause performance degradation with small payloads. This patch adds an option to disable it if required. By default zero copy is enabled. Signed-off-by: Evgeniy Kochetov Change-Id: I14f2b21ad375e770cb08f850360898bac675b351 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/3344 Tested-by: SPDK CI Jenkins Community-CI: Mellanox Build Bot Reviewed-by: Jim Harris Reviewed-by: Shuhei Matsumoto --- CHANGELOG.md | 3 +++ doc/jsonrpc.md | 3 +++ include/spdk/sock.h | 5 +++++ lib/sock/sock.c | 1 + lib/sock/sock_rpc.c | 5 +++++ module/sock/posix/posix.c | 7 +++++-- scripts/rpc.py | 9 +++++++-- scripts/rpc/sock.py | 6 +++++- 8 files changed, 34 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffcb7bbc8..2839e8d05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -110,6 +110,9 @@ based socket tests for iSCSI target and also the tests for SPDK NVMe-oF tcp tran Added `enable_recv_pipe` socket layer option to allow disabling of double buffering on receive. New option is used only in posix implementation. +Added `enable_zerocopy_send` socket layer option to allow disabling of zero copy flow on send. +New option is used only in posix implementation. + ### vhost The function `spdk_vhost_blk_get_dev` has been removed. diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index b95348e1a..055c3b11a 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -6587,6 +6587,7 @@ Example response: "recv_buf_size": 2097152, "send_buf_size": 2097152, "enable_recv_pipe": true + "enable_zerocopy_send": true } } ~~~ @@ -6603,6 +6604,7 @@ impl_name | Required | string | Name of socket implementation recv_buf_size | Optional | number | Size of socket receive buffer in bytes send_buf_size | Optional | number | Size of socket send buffer in bytes enable_recv_pipe | Optional | boolean | Enable or disable receive pipe +enable_zerocopy_send | Optional | boolean | Enable or disable zero copy on send ### Response @@ -6622,6 +6624,7 @@ Example request: "recv_buf_size": 2097152, "send_buf_size": 2097152, "enable_recv_pipe": false + "enable_zerocopy_send": true } } ~~~ diff --git a/include/spdk/sock.h b/include/spdk/sock.h index 1b3fd72b0..f70a2ac39 100644 --- a/include/spdk/sock.h +++ b/include/spdk/sock.h @@ -102,6 +102,11 @@ struct spdk_sock_impl_opts { * Enable or disable receive pipe. Used by posix socket module. */ bool enable_recv_pipe; + + /** + * Enable or disable use of zero copy flow on send. Used by posix socket module. + */ + bool enable_zerocopy_send; }; /** diff --git a/lib/sock/sock.c b/lib/sock/sock.c index 81b55d625..5ea90385c 100644 --- a/lib/sock/sock.c +++ b/lib/sock/sock.c @@ -776,6 +776,7 @@ spdk_sock_write_config_json(struct spdk_json_write_ctx *w) spdk_json_write_named_uint32(w, "recv_buf_size", opts.recv_buf_size); spdk_json_write_named_uint32(w, "send_buf_size", opts.send_buf_size); spdk_json_write_named_bool(w, "enable_recv_pipe", opts.enable_recv_pipe); + spdk_json_write_named_bool(w, "enable_zerocopy_send", opts.enable_zerocopy_send); spdk_json_write_object_end(w); spdk_json_write_object_end(w); } else { diff --git a/lib/sock/sock_rpc.c b/lib/sock/sock_rpc.c index 8343fa2ec..c8686a068 100644 --- a/lib/sock/sock_rpc.c +++ b/lib/sock/sock_rpc.c @@ -74,6 +74,7 @@ rpc_sock_impl_get_options(struct spdk_jsonrpc_request *request, spdk_json_write_named_uint32(w, "recv_buf_size", sock_opts.recv_buf_size); spdk_json_write_named_uint32(w, "send_buf_size", sock_opts.send_buf_size); spdk_json_write_named_bool(w, "enable_recv_pipe", sock_opts.enable_recv_pipe); + spdk_json_write_named_bool(w, "enable_zerocopy_send", sock_opts.enable_zerocopy_send); spdk_json_write_object_end(w); spdk_jsonrpc_end_result(request, w); free(impl_name); @@ -103,6 +104,10 @@ static const struct spdk_json_object_decoder rpc_sock_impl_set_opts_decoders[] = "enable_recv_pipe", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.enable_recv_pipe), spdk_json_decode_bool, true }, + { + "enable_zerocopy_send", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.enable_zerocopy_send), + spdk_json_decode_bool, true + }, }; static void diff --git a/module/sock/posix/posix.c b/module/sock/posix/posix.c index 6e04c14ff..4eb1bf106 100644 --- a/module/sock/posix/posix.c +++ b/module/sock/posix/posix.c @@ -82,7 +82,8 @@ struct spdk_posix_sock_group_impl { static struct spdk_sock_impl_opts g_spdk_posix_sock_impl_opts = { .recv_buf_size = MIN_SO_RCVBUF_SIZE, .send_buf_size = MIN_SO_SNDBUF_SIZE, - .enable_recv_pipe = true + .enable_recv_pipe = true, + .enable_zerocopy_send = true }; static int @@ -326,7 +327,7 @@ posix_sock_alloc(int fd, bool enable_zero_copy) sock->fd = fd; #ifdef SPDK_ZEROCOPY - if (!enable_zero_copy) { + if (!enable_zero_copy || !g_spdk_posix_sock_impl_opts.enable_zerocopy_send) { return sock; } @@ -1336,6 +1337,7 @@ posix_sock_impl_get_opts(struct spdk_sock_impl_opts *opts, size_t *len) GET_FIELD(recv_buf_size); GET_FIELD(send_buf_size); GET_FIELD(enable_recv_pipe); + GET_FIELD(enable_zerocopy_send); #undef GET_FIELD #undef FIELD_OK @@ -1363,6 +1365,7 @@ posix_sock_impl_set_opts(const struct spdk_sock_impl_opts *opts, size_t len) SET_FIELD(recv_buf_size); SET_FIELD(send_buf_size); SET_FIELD(enable_recv_pipe); + SET_FIELD(enable_zerocopy_send); #undef SET_FIELD #undef FIELD_OK diff --git a/scripts/rpc.py b/scripts/rpc.py index b20b10d29..84c502fe6 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -2398,7 +2398,8 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse impl_name=args.impl, recv_buf_size=args.recv_buf_size, send_buf_size=args.send_buf_size, - enable_recv_pipe=args.enable_recv_pipe) + enable_recv_pipe=args.enable_recv_pipe, + enable_zerocopy_send=args.enable_zerocopy_send) p = subparsers.add_parser('sock_impl_set_options', help="""Set options of socket layer implementation""") p.add_argument('-i', '--impl', help='Socket implementation name, e.g. posix', required=True) @@ -2408,7 +2409,11 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse action='store_true', dest='enable_recv_pipe') p.add_argument('--disable-recv-pipe', help='Disable receive pipe', action='store_false', dest='enable_recv_pipe') - p.set_defaults(func=sock_impl_set_options, enable_recv_pipe=None) + p.add_argument('--enable-zerocopy-send', help='Enable zerocopy on send', + action='store_true', dest='enable_zerocopy_send') + p.add_argument('--disable-zerocopy-send', help='Disable zerocopy on send', + action='store_false', dest='enable_zerocopy_send') + p.set_defaults(func=sock_impl_set_options, enable_recv_pipe=None, enable_zerocopy_send=None) def check_called_name(name): if name in deprecated_aliases: diff --git a/scripts/rpc/sock.py b/scripts/rpc/sock.py index d56d25357..34d7f100d 100644 --- a/scripts/rpc/sock.py +++ b/scripts/rpc/sock.py @@ -15,7 +15,8 @@ def sock_impl_set_options(client, impl_name=None, recv_buf_size=None, send_buf_size=None, - enable_recv_pipe=None): + enable_recv_pipe=None, + enable_zerocopy_send=None): """Set parameters for the socket layer implementation. Args: @@ -23,6 +24,7 @@ def sock_impl_set_options(client, recv_buf_size: size of socket receive buffer in bytes (optional) send_buf_size: size of socket send buffer in bytes (optional) enable_recv_pipe: enable or disable receive pipe (optional) + enable_zerocopy_send: enable or disable zerocopy on send (optional) """ params = {} @@ -33,5 +35,7 @@ def sock_impl_set_options(client, params['send_buf_size'] = send_buf_size if enable_recv_pipe is not None: params['enable_recv_pipe'] = enable_recv_pipe + if enable_zerocopy_send is not None: + params['enable_zerocopy_send'] = enable_zerocopy_send return client.call('sock_impl_set_options', params)