1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (C) 2020 Intel Corporation.
3 * Copyright (c) 2020, 2021 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5 */
6
7 #include "spdk/sock.h"
8
9 #include "spdk/rpc.h"
10 #include "spdk/util.h"
11 #include "spdk/string.h"
12
13 #include "spdk/log.h"
14
15
16 static const struct spdk_json_object_decoder rpc_sock_impl_get_opts_decoders[] = {
17 { "impl_name", 0, spdk_json_decode_string, false },
18 };
19
20 static void
rpc_sock_impl_get_options(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)21 rpc_sock_impl_get_options(struct spdk_jsonrpc_request *request,
22 const struct spdk_json_val *params)
23 {
24 char *impl_name = NULL;
25 struct spdk_sock_impl_opts sock_opts = {};
26 struct spdk_json_write_ctx *w;
27 size_t len;
28 int rc;
29
30 if (spdk_json_decode_object(params, rpc_sock_impl_get_opts_decoders,
31 SPDK_COUNTOF(rpc_sock_impl_get_opts_decoders), &impl_name)) {
32 SPDK_ERRLOG("spdk_json_decode_object() failed\n");
33 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
34 "Invalid parameters");
35 return;
36 }
37
38 len = sizeof(sock_opts);
39 rc = spdk_sock_impl_get_opts(impl_name, &sock_opts, &len);
40 if (rc) {
41 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
42 "Invalid parameters");
43 return;
44 }
45
46 w = spdk_jsonrpc_begin_result(request);
47 spdk_json_write_object_begin(w);
48 spdk_json_write_named_uint32(w, "recv_buf_size", sock_opts.recv_buf_size);
49 spdk_json_write_named_uint32(w, "send_buf_size", sock_opts.send_buf_size);
50 spdk_json_write_named_bool(w, "enable_recv_pipe", sock_opts.enable_recv_pipe);
51 spdk_json_write_named_bool(w, "enable_quickack", sock_opts.enable_quickack);
52 spdk_json_write_named_uint32(w, "enable_placement_id", sock_opts.enable_placement_id);
53 spdk_json_write_named_bool(w, "enable_zerocopy_send_server", sock_opts.enable_zerocopy_send_server);
54 spdk_json_write_named_bool(w, "enable_zerocopy_send_client", sock_opts.enable_zerocopy_send_client);
55 spdk_json_write_named_uint32(w, "zerocopy_threshold", sock_opts.zerocopy_threshold);
56 spdk_json_write_named_uint32(w, "tls_version", sock_opts.tls_version);
57 spdk_json_write_named_bool(w, "enable_ktls", sock_opts.enable_ktls);
58 spdk_json_write_object_end(w);
59 spdk_jsonrpc_end_result(request, w);
60 free(impl_name);
61 }
62 SPDK_RPC_REGISTER("sock_impl_get_options", rpc_sock_impl_get_options,
63 SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME)
64
65 struct spdk_rpc_sock_impl_set_opts {
66 char *impl_name;
67 struct spdk_sock_impl_opts sock_opts;
68 };
69
70 static const struct spdk_json_object_decoder rpc_sock_impl_set_opts_decoders[] = {
71 {
72 "impl_name", offsetof(struct spdk_rpc_sock_impl_set_opts, impl_name),
73 spdk_json_decode_string, false
74 },
75 {
76 "recv_buf_size", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.recv_buf_size),
77 spdk_json_decode_uint32, true
78 },
79 {
80 "send_buf_size", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.send_buf_size),
81 spdk_json_decode_uint32, true
82 },
83 {
84 "enable_recv_pipe", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.enable_recv_pipe),
85 spdk_json_decode_bool, true
86 },
87 {
88 "enable_quickack", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.enable_quickack),
89 spdk_json_decode_bool, true
90 },
91 {
92 "enable_placement_id", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.enable_placement_id),
93 spdk_json_decode_uint32, true
94 },
95 {
96 "enable_zerocopy_send_server", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.enable_zerocopy_send_server),
97 spdk_json_decode_bool, true
98 },
99 {
100 "enable_zerocopy_send_client", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.enable_zerocopy_send_client),
101 spdk_json_decode_bool, true
102 },
103 {
104 "zerocopy_threshold", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.zerocopy_threshold),
105 spdk_json_decode_uint32, true
106 },
107 {
108 "tls_version", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.tls_version),
109 spdk_json_decode_uint32, true
110 },
111 {
112 "enable_ktls", offsetof(struct spdk_rpc_sock_impl_set_opts, sock_opts.enable_ktls),
113 spdk_json_decode_bool, true
114 }
115 };
116
117 static void
rpc_sock_impl_set_options(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)118 rpc_sock_impl_set_options(struct spdk_jsonrpc_request *request,
119 const struct spdk_json_val *params)
120 {
121 struct spdk_rpc_sock_impl_set_opts opts = {};
122 size_t len;
123 int rc;
124
125 /* Get type */
126 if (spdk_json_decode_object(params, rpc_sock_impl_set_opts_decoders,
127 SPDK_COUNTOF(rpc_sock_impl_set_opts_decoders), &opts)) {
128 SPDK_ERRLOG("spdk_json_decode_object() failed\n");
129 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
130 "Invalid parameters");
131 return;
132 }
133
134 /* Retrieve default opts for requested socket implementation */
135 len = sizeof(opts.sock_opts);
136 rc = spdk_sock_impl_get_opts(opts.impl_name, &opts.sock_opts, &len);
137 if (rc) {
138 free(opts.impl_name);
139 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
140 "Invalid parameters");
141 return;
142 }
143
144 /* Decode opts */
145 if (spdk_json_decode_object(params, rpc_sock_impl_set_opts_decoders,
146 SPDK_COUNTOF(rpc_sock_impl_set_opts_decoders), &opts)) {
147 SPDK_ERRLOG("spdk_json_decode_object() failed\n");
148 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
149 "Invalid parameters");
150 return;
151 }
152
153 rc = spdk_sock_impl_set_opts(opts.impl_name, &opts.sock_opts, sizeof(opts.sock_opts));
154 if (rc != 0) {
155 free(opts.impl_name);
156 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
157 "Invalid parameters");
158 return;
159 }
160
161 spdk_jsonrpc_send_bool_response(request, true);
162 free(opts.impl_name);
163 }
164 SPDK_RPC_REGISTER("sock_impl_set_options", rpc_sock_impl_set_options, SPDK_RPC_STARTUP)
165
166 static void
rpc_sock_set_default_impl(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)167 rpc_sock_set_default_impl(struct spdk_jsonrpc_request *request,
168 const struct spdk_json_val *params)
169 {
170 char *impl_name = NULL;
171 int rc;
172
173 /* Reuse get_opts decoder */
174 if (spdk_json_decode_object(params, rpc_sock_impl_get_opts_decoders,
175 SPDK_COUNTOF(rpc_sock_impl_get_opts_decoders), &impl_name)) {
176 SPDK_ERRLOG("spdk_json_decode_object() failed\n");
177 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
178 "Invalid parameters");
179 return;
180 }
181
182 rc = spdk_sock_set_default_impl(impl_name);
183 if (rc) {
184 free(impl_name);
185 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
186 "Invalid parameters");
187 return;
188 }
189
190 spdk_jsonrpc_send_bool_response(request, true);
191 free(impl_name);
192 }
193 SPDK_RPC_REGISTER("sock_set_default_impl", rpc_sock_set_default_impl, SPDK_RPC_STARTUP)
194
195 static void
rpc_sock_get_default_impl(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)196 rpc_sock_get_default_impl(struct spdk_jsonrpc_request *request,
197 const struct spdk_json_val *params)
198 {
199 const char *impl_name = spdk_sock_get_default_impl();
200 struct spdk_json_write_ctx *w;
201
202 if (params) {
203 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
204 "sock_get_default_impl requires no parameters");
205 return;
206 }
207
208 if (!impl_name) {
209 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
210 "No registered socket implementations found");
211 return;
212 }
213
214 w = spdk_jsonrpc_begin_result(request);
215 spdk_json_write_object_begin(w);
216 spdk_json_write_named_string(w, "impl_name", impl_name);
217 spdk_json_write_object_end(w);
218 spdk_jsonrpc_end_result(request, w);
219 }
220 SPDK_RPC_REGISTER("sock_get_default_impl", rpc_sock_get_default_impl,
221 SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME)
222