From 63c5e51ebc055d09166d58ce6e8d26d42914c6bf Mon Sep 17 00:00:00 2001 From: Evgeniy Kochetov Date: Tue, 14 Jul 2020 16:28:30 +0300 Subject: [PATCH] sock: Add sock_impl option to disable receive pipe Receive pipe reduces number of system calls and gives significant performance improvement with kernel TCP stack and relatively small IO sizes. With user space TCP/IP implementations there are no system calls and double buffering introduced by pipe has negative impact on performance. Receive pipe remains enabled by default. Signed-off-by: Evgeniy Kochetov Change-Id: Ic5ddee42293df2c233ba7ffbe6662de7917ac586 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/3343 Tested-by: SPDK CI Jenkins Community-CI: Mellanox Build Bot Reviewed-by: Jim Harris Reviewed-by: Shuhei Matsumoto --- CHANGELOG.md | 3 +++ doc/jsonrpc.md | 7 +++++-- include/spdk/sock.h | 5 +++++ lib/sock/sock.c | 1 + lib/sock/sock_rpc.c | 5 +++++ module/sock/posix/posix.c | 13 +++++++++---- scripts/rpc.py | 9 +++++++-- scripts/rpc/sock.py | 9 ++++++++- 8 files changed, 43 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23c49924c..ffcb7bbc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -107,6 +107,9 @@ Added `uring` based socket implementation, the code is located in module/sock/ur available in Linux which requires kernel version is greater than 5.4.3. Currently, our CI pool added the uring based socket tests for iSCSI target and also the tests for SPDK NVMe-oF tcp transport. +Added `enable_recv_pipe` socket layer option to allow disabling of double buffering on receive. +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 28e42a652..b95348e1a 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -6585,7 +6585,8 @@ Example response: "id": 1, "result": { "recv_buf_size": 2097152, - "send_buf_size": 2097152 + "send_buf_size": 2097152, + "enable_recv_pipe": true } } ~~~ @@ -6601,6 +6602,7 @@ Name | Optional | Type | Description impl_name | Required | string | Name of socket implementation, e.g. posix 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 ### Response @@ -6618,7 +6620,8 @@ Example request: "params": { "impl_name": "posix", "recv_buf_size": 2097152, - "send_buf_size": 2097152 + "send_buf_size": 2097152, + "enable_recv_pipe": false } } ~~~ diff --git a/include/spdk/sock.h b/include/spdk/sock.h index 3111f2ba3..1b3fd72b0 100644 --- a/include/spdk/sock.h +++ b/include/spdk/sock.h @@ -97,6 +97,11 @@ struct spdk_sock_impl_opts { * Size of sock send buffer. Used by posix socket module. */ uint32_t send_buf_size; + + /** + * Enable or disable receive pipe. Used by posix socket module. + */ + bool enable_recv_pipe; }; /** diff --git a/lib/sock/sock.c b/lib/sock/sock.c index 2551202f3..81b55d625 100644 --- a/lib/sock/sock.c +++ b/lib/sock/sock.c @@ -775,6 +775,7 @@ spdk_sock_write_config_json(struct spdk_json_write_ctx *w) spdk_json_write_named_string(w, "impl_name", impl->name); 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_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 f13817383..8343fa2ec 100644 --- a/lib/sock/sock_rpc.c +++ b/lib/sock/sock_rpc.c @@ -73,6 +73,7 @@ rpc_sock_impl_get_options(struct spdk_jsonrpc_request *request, spdk_json_write_object_begin(w); 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_object_end(w); spdk_jsonrpc_end_result(request, w); free(impl_name); @@ -98,6 +99,10 @@ static const struct spdk_json_object_decoder rpc_sock_impl_set_opts_decoders[] = "send_buf_size", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.send_buf_size), spdk_json_decode_uint32, true }, + { + "enable_recv_pipe", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.enable_recv_pipe), + spdk_json_decode_bool, true + }, }; static void diff --git a/module/sock/posix/posix.c b/module/sock/posix/posix.c index 6e56f2b9d..6e04c14ff 100644 --- a/module/sock/posix/posix.c +++ b/module/sock/posix/posix.c @@ -81,7 +81,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 + .send_buf_size = MIN_SO_SNDBUF_SIZE, + .enable_recv_pipe = true }; static int @@ -267,9 +268,11 @@ posix_sock_set_recvbuf(struct spdk_sock *_sock, int sz) assert(sock != NULL); - rc = posix_sock_alloc_pipe(sock, sz); - if (rc) { - return rc; + if (g_spdk_posix_sock_impl_opts.enable_recv_pipe) { + rc = posix_sock_alloc_pipe(sock, sz); + if (rc) { + return rc; + } } /* Set kernel buffer size to be at least MIN_SO_RCVBUF_SIZE */ @@ -1332,6 +1335,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); #undef GET_FIELD #undef FIELD_OK @@ -1358,6 +1362,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); #undef SET_FIELD #undef FIELD_OK diff --git a/scripts/rpc.py b/scripts/rpc.py index 941108b64..b20b10d29 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -2397,13 +2397,18 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse rpc.sock.sock_impl_set_options(args.client, impl_name=args.impl, recv_buf_size=args.recv_buf_size, - send_buf_size=args.send_buf_size) + send_buf_size=args.send_buf_size, + enable_recv_pipe=args.enable_recv_pipe) 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) p.add_argument('-r', '--recv-buf-size', help='Size of receive buffer on socket in bytes', type=int) p.add_argument('-s', '--send-buf-size', help='Size of send buffer on socket in bytes', type=int) - p.set_defaults(func=sock_impl_set_options) + p.add_argument('--enable-recv-pipe', help='Enable receive pipe', + 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) def check_called_name(name): if name in deprecated_aliases: diff --git a/scripts/rpc/sock.py b/scripts/rpc/sock.py index b73244e5a..d56d25357 100644 --- a/scripts/rpc/sock.py +++ b/scripts/rpc/sock.py @@ -11,13 +11,18 @@ def sock_impl_get_options(client, impl_name=None): return client.call('sock_impl_get_options', params) -def sock_impl_set_options(client, impl_name=None, recv_buf_size=None, send_buf_size=None): +def sock_impl_set_options(client, + impl_name=None, + recv_buf_size=None, + send_buf_size=None, + enable_recv_pipe=None): """Set parameters for the socket layer implementation. Args: impl_name: name of socket implementation, e.g. posix 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) """ params = {} @@ -26,5 +31,7 @@ def sock_impl_set_options(client, impl_name=None, recv_buf_size=None, send_buf_s params['recv_buf_size'] = recv_buf_size if send_buf_size is not None: params['send_buf_size'] = send_buf_size + if enable_recv_pipe is not None: + params['enable_recv_pipe'] = enable_recv_pipe return client.call('sock_impl_set_options', params)