Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2020 Intel Corporation.
3 : : * Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES.
4 : : * All rights reserved.
5 : : */
6 : :
7 : : #include "accel_internal.h"
8 : : #include "spdk/accel_module.h"
9 : :
10 : : #include "spdk/rpc.h"
11 : : #include "spdk/util.h"
12 : : #include "spdk/event.h"
13 : : #include "spdk/stdinc.h"
14 : : #include "spdk/string.h"
15 : : #include "spdk/env.h"
16 : : #include "spdk/util.h"
17 : :
18 : : static void
19 : 41 : rpc_accel_get_opc_assignments(struct spdk_jsonrpc_request *request,
20 : : const struct spdk_json_val *params)
21 : : {
22 : : struct spdk_json_write_ctx *w;
23 : : enum spdk_accel_opcode opcode;
24 : 41 : const char *name, *module_name = NULL;
25 : : int rc;
26 : :
27 [ - + ]: 41 : if (params != NULL) {
28 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
29 : : "accel_get_opc_assignments requires no parameters");
30 : 0 : return;
31 : : }
32 : :
33 : 41 : w = spdk_jsonrpc_begin_result(request);
34 : :
35 : 41 : spdk_json_write_object_begin(w);
36 [ + + ]: 615 : for (opcode = 0; opcode < SPDK_ACCEL_OPC_LAST; opcode++) {
37 : 574 : name = spdk_accel_get_opcode_name(opcode);
38 [ + - ]: 574 : if (name != NULL) {
39 : 574 : rc = spdk_accel_get_opc_module_name(opcode, &module_name);
40 [ + - ]: 574 : if (rc == 0) {
41 : 574 : spdk_json_write_named_string(w, name, module_name);
42 : : } else {
43 : : /* This isn't fatal but throw an informational message if we
44 : : * cant get an module name right now */
45 : 0 : SPDK_NOTICELOG("FYI error (%d) getting module name.\n", rc);
46 : : }
47 : : } else {
48 : : /* this should never happen */
49 : 0 : SPDK_ERRLOG("Invalid opcode (%d)).\n", opcode);
50 : 0 : assert(0);
51 : : }
52 : : }
53 : 41 : spdk_json_write_object_end(w);
54 : :
55 : 41 : spdk_jsonrpc_end_result(request, w);
56 : : }
57 : 2874 : SPDK_RPC_REGISTER("accel_get_opc_assignments", rpc_accel_get_opc_assignments, SPDK_RPC_RUNTIME)
58 : :
59 : : static void
60 : 0 : rpc_dump_module_info(struct module_info *info)
61 : : {
62 : 0 : struct spdk_json_write_ctx *w = info->w;
63 : : const char *name;
64 : : uint32_t i;
65 : :
66 : 0 : spdk_json_write_object_begin(w);
67 : :
68 : 0 : spdk_json_write_named_string(w, "module", info->name);
69 : 0 : spdk_json_write_named_array_begin(w, "supported ops");
70 : :
71 [ # # ]: 0 : for (i = 0; i < info->num_ops; i++) {
72 : 0 : name = spdk_accel_get_opcode_name(info->ops[i]);
73 [ # # ]: 0 : if (name != NULL) {
74 : 0 : spdk_json_write_string(w, name);
75 : : } else {
76 : : /* this should never happen */
77 : 0 : SPDK_ERRLOG("Invalid opcode (%d)).\n", info->ops[i]);
78 : 0 : assert(0);
79 : : }
80 : : }
81 : :
82 : 0 : spdk_json_write_array_end(w);
83 : 0 : spdk_json_write_object_end(w);
84 : 0 : }
85 : :
86 : : static void
87 : 0 : rpc_accel_get_module_info(struct spdk_jsonrpc_request *request,
88 : : const struct spdk_json_val *params)
89 : : {
90 : 0 : struct module_info info;
91 : :
92 [ # # ]: 0 : if (params != NULL) {
93 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
94 : : "accel_get_module_info requires no parameters");
95 : 0 : return;
96 : : }
97 : :
98 : 0 : info.w = spdk_jsonrpc_begin_result(request);
99 : 0 : spdk_json_write_array_begin(info.w);
100 : :
101 : 0 : _accel_for_each_module(&info, rpc_dump_module_info);
102 : :
103 : 0 : spdk_json_write_array_end(info.w);
104 : 0 : spdk_jsonrpc_end_result(request, info.w);
105 : : }
106 : 2874 : SPDK_RPC_REGISTER("accel_get_module_info", rpc_accel_get_module_info, SPDK_RPC_RUNTIME)
107 : 2874 : SPDK_RPC_REGISTER_ALIAS_DEPRECATED(accel_get_module_info, accel_get_engine_info)
108 : :
109 : : struct rpc_accel_assign_opc {
110 : : char *opname;
111 : : char *module;
112 : : };
113 : :
114 : : static const struct spdk_json_object_decoder rpc_accel_assign_opc_decoders[] = {
115 : : {"opname", offsetof(struct rpc_accel_assign_opc, opname), spdk_json_decode_string},
116 : : {"module", offsetof(struct rpc_accel_assign_opc, module), spdk_json_decode_string},
117 : : };
118 : :
119 : : static void
120 : 89 : free_accel_assign_opc(struct rpc_accel_assign_opc *r)
121 : : {
122 : 89 : free(r->opname);
123 : 89 : free(r->module);
124 : 89 : }
125 : :
126 : : static void
127 : 89 : rpc_accel_assign_opc(struct spdk_jsonrpc_request *request,
128 : : const struct spdk_json_val *params)
129 : : {
130 : 89 : struct rpc_accel_assign_opc req = {};
131 : : const char *opcode_str;
132 : : enum spdk_accel_opcode opcode;
133 : 89 : bool found = false;
134 : : int rc;
135 : :
136 [ - + ]: 89 : if (spdk_json_decode_object(params, rpc_accel_assign_opc_decoders,
137 : : SPDK_COUNTOF(rpc_accel_assign_opc_decoders),
138 : : &req)) {
139 [ # # # # ]: 0 : SPDK_DEBUGLOG(accel, "spdk_json_decode_object failed\n");
140 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
141 : : "spdk_json_decode_object failed");
142 : 0 : goto cleanup;
143 : : }
144 : :
145 [ + - ]: 492 : for (opcode = 0; opcode < SPDK_ACCEL_OPC_LAST; opcode++) {
146 : 492 : opcode_str = spdk_accel_get_opcode_name(opcode);
147 [ - + ]: 492 : assert(opcode_str != NULL);
148 [ + + - + : 492 : if (strcmp(opcode_str, req.opname) == 0) {
+ + ]
149 : 89 : found = true;
150 : 89 : break;
151 : : }
152 : : }
153 : :
154 [ - + ]: 89 : if (found == false) {
155 [ # # # # ]: 0 : SPDK_DEBUGLOG(accel, "Invalid operation name\n");
156 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
157 : : "spdk_json_decode_object failed");
158 : 0 : goto cleanup;
159 : : }
160 : :
161 : 89 : rc = spdk_accel_assign_opc(opcode, req.module);
162 [ - + ]: 89 : if (rc) {
163 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
164 : : "error assigning opcode");
165 : 0 : goto cleanup;
166 : : }
167 : :
168 : 89 : SPDK_NOTICELOG("Operation %s will be assigned to module %s\n", req.opname, req.module);
169 : 89 : spdk_jsonrpc_send_bool_response(request, true);
170 : :
171 : 89 : cleanup:
172 : 89 : free_accel_assign_opc(&req);
173 : :
174 : 89 : }
175 : 2874 : SPDK_RPC_REGISTER("accel_assign_opc", rpc_accel_assign_opc, SPDK_RPC_STARTUP)
176 : :
177 : : struct rpc_accel_crypto_key_create {
178 : : struct spdk_accel_crypto_key_create_param param;
179 : : };
180 : :
181 : : static const struct spdk_json_object_decoder rpc_accel_dek_create_decoders[] = {
182 : : {"cipher", offsetof(struct rpc_accel_crypto_key_create, param.cipher), spdk_json_decode_string},
183 : : {"key", offsetof(struct rpc_accel_crypto_key_create, param.hex_key), spdk_json_decode_string},
184 : : {"key2", offsetof(struct rpc_accel_crypto_key_create, param.hex_key2), spdk_json_decode_string, true},
185 : : {"tweak_mode", offsetof(struct rpc_accel_crypto_key_create, param.tweak_mode), spdk_json_decode_string, true},
186 : : {"name", offsetof(struct rpc_accel_crypto_key_create, param.key_name), spdk_json_decode_string},
187 : : };
188 : :
189 : : static void
190 : 109 : rpc_accel_crypto_key_create(struct spdk_jsonrpc_request *request,
191 : : const struct spdk_json_val *params)
192 : : {
193 : 109 : struct rpc_accel_crypto_key_create req = {};
194 : : size_t key_size;
195 : : int rc;
196 : :
197 [ - + ]: 109 : if (spdk_json_decode_object(params, rpc_accel_dek_create_decoders,
198 : : SPDK_COUNTOF(rpc_accel_dek_create_decoders),
199 : : &req)) {
200 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
201 : : "spdk_json_decode_object failed");
202 : 0 : goto cleanup;
203 : : }
204 : :
205 : 109 : rc = spdk_accel_crypto_key_create(&req.param);
206 [ - + ]: 109 : if (rc) {
207 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
208 : : "failed to create DEK, rc %d", rc);
209 : : } else {
210 : 109 : spdk_jsonrpc_send_bool_response(request, true);
211 : : }
212 : :
213 : 109 : cleanup:
214 : 109 : free(req.param.cipher);
215 [ + - ]: 109 : if (req.param.hex_key) {
216 [ - + ]: 109 : key_size = strnlen(req.param.hex_key, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH);
217 : 109 : spdk_memset_s(req.param.hex_key, key_size, 0, key_size);
218 : 109 : free(req.param.hex_key);
219 : : }
220 [ + + ]: 109 : if (req.param.hex_key2) {
221 [ - + ]: 54 : key_size = strnlen(req.param.hex_key2, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH);
222 : 54 : spdk_memset_s(req.param.hex_key2, key_size, 0, key_size);
223 : 54 : free(req.param.hex_key2);
224 : : }
225 : 109 : free(req.param.tweak_mode);
226 : 109 : free(req.param.key_name);
227 : 109 : }
228 : 2874 : SPDK_RPC_REGISTER("accel_crypto_key_create", rpc_accel_crypto_key_create, SPDK_RPC_RUNTIME)
229 : :
230 : : struct rpc_accel_crypto_keys_get_ctx {
231 : : char *key_name;
232 : : };
233 : :
234 : : static const struct spdk_json_object_decoder rpc_accel_crypto_keys_get_decoders[] = {
235 : : {"key_name", offsetof(struct rpc_accel_crypto_keys_get_ctx, key_name), spdk_json_decode_string, true},
236 : : };
237 : :
238 : : static void
239 : 9 : rpc_accel_crypto_keys_get(struct spdk_jsonrpc_request *request,
240 : : const struct spdk_json_val *params)
241 : : {
242 : 9 : struct rpc_accel_crypto_keys_get_ctx req = {};
243 : 9 : struct spdk_accel_crypto_key *key = NULL;
244 : : struct spdk_json_write_ctx *w;
245 : :
246 [ + - - + ]: 9 : if (params && spdk_json_decode_object(params, rpc_accel_crypto_keys_get_decoders,
247 : : SPDK_COUNTOF(rpc_accel_crypto_keys_get_decoders),
248 : : &req)) {
249 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
250 : : "spdk_json_decode_object failed");
251 : 0 : free(req.key_name);
252 : 0 : return;
253 : : }
254 : :
255 [ + - ]: 9 : if (req.key_name) {
256 : 9 : key = spdk_accel_crypto_key_get(req.key_name);
257 : 9 : free(req.key_name);
258 [ - + ]: 9 : if (!key) {
259 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "key was not found\n");
260 : 0 : return;
261 : : }
262 : : }
263 : :
264 : 9 : w = spdk_jsonrpc_begin_result(request);
265 : 9 : spdk_json_write_array_begin(w);
266 : :
267 [ + - ]: 9 : if (key) {
268 : 9 : _accel_crypto_key_dump_param(w, key);
269 : : } else {
270 : 0 : _accel_crypto_keys_dump_param(w);
271 : : }
272 : :
273 : 9 : spdk_json_write_array_end(w);
274 : 9 : spdk_jsonrpc_end_result(request, w);
275 : : }
276 : 2874 : SPDK_RPC_REGISTER("accel_crypto_keys_get", rpc_accel_crypto_keys_get, SPDK_RPC_RUNTIME)
277 : :
278 : : static const struct spdk_json_object_decoder rpc_accel_crypto_key_destroy_decoders[] = {
279 : : {"key_name", offsetof(struct rpc_accel_crypto_keys_get_ctx, key_name), spdk_json_decode_string},
280 : : };
281 : :
282 : : static void
283 : 0 : rpc_accel_crypto_key_destroy(struct spdk_jsonrpc_request *request,
284 : : const struct spdk_json_val *params)
285 : : {
286 : 0 : struct rpc_accel_crypto_keys_get_ctx req = {};
287 : 0 : struct spdk_accel_crypto_key *key = NULL;
288 : : int rc;
289 : :
290 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_accel_crypto_key_destroy_decoders,
291 : : SPDK_COUNTOF(rpc_accel_crypto_key_destroy_decoders),
292 : : &req)) {
293 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
294 : : "spdk_json_decode_object failed");
295 : 0 : free(req.key_name);
296 : 0 : return;
297 : : }
298 : :
299 : 0 : key = spdk_accel_crypto_key_get(req.key_name);
300 [ # # ]: 0 : if (!key) {
301 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
302 : : "No key object found");
303 : 0 : free(req.key_name);
304 : 0 : return;
305 : :
306 : : }
307 : 0 : rc = spdk_accel_crypto_key_destroy(key);
308 [ # # ]: 0 : if (rc) {
309 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
310 : : "Failed to destroy key, rc %d\n", rc);
311 : : } else {
312 : 0 : spdk_jsonrpc_send_bool_response(request, true);
313 : : }
314 : :
315 : 0 : free(req.key_name);
316 : : }
317 : 2874 : SPDK_RPC_REGISTER("accel_crypto_key_destroy", rpc_accel_crypto_key_destroy, SPDK_RPC_RUNTIME)
318 : :
319 : : struct rpc_accel_set_driver {
320 : : char *name;
321 : : };
322 : :
323 : : static const struct spdk_json_object_decoder rpc_accel_set_driver_decoders[] = {
324 : : {"name", offsetof(struct rpc_accel_set_driver, name), spdk_json_decode_string},
325 : : };
326 : :
327 : : static void
328 : 0 : free_rpc_accel_set_driver(struct rpc_accel_set_driver *r)
329 : : {
330 : 0 : free(r->name);
331 : 0 : }
332 : :
333 : : static void
334 : 0 : rpc_accel_set_driver(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
335 : : {
336 : 0 : struct rpc_accel_set_driver req = {};
337 : : int rc;
338 : :
339 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_accel_set_driver_decoders,
340 : : SPDK_COUNTOF(rpc_accel_set_driver_decoders), &req)) {
341 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
342 : : "spdk_json_decode_object failed");
343 : 0 : return;
344 : : }
345 : :
346 : 0 : rc = spdk_accel_set_driver(req.name);
347 [ # # ]: 0 : if (rc != 0) {
348 : 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
349 : 0 : goto cleanup;
350 : : }
351 : :
352 : 0 : SPDK_NOTICELOG("Using accel driver: %s\n", req.name);
353 : 0 : spdk_jsonrpc_send_bool_response(request, true);
354 : 0 : cleanup:
355 : 0 : free_rpc_accel_set_driver(&req);
356 : : }
357 : 2874 : SPDK_RPC_REGISTER("accel_set_driver", rpc_accel_set_driver, SPDK_RPC_STARTUP)
358 : :
359 : : struct rpc_accel_opts {
360 : : uint32_t small_cache_size;
361 : : uint32_t large_cache_size;
362 : : uint32_t task_count;
363 : : uint32_t sequence_count;
364 : : uint32_t buf_count;
365 : : };
366 : :
367 : : static const struct spdk_json_object_decoder rpc_accel_set_options_decoders[] = {
368 : : {"small_cache_size", offsetof(struct rpc_accel_opts, small_cache_size), spdk_json_decode_uint32, true},
369 : : {"large_cache_size", offsetof(struct rpc_accel_opts, large_cache_size), spdk_json_decode_uint32, true},
370 : : {"task_count", offsetof(struct rpc_accel_opts, task_count), spdk_json_decode_uint32, true},
371 : : {"sequence_count", offsetof(struct rpc_accel_opts, sequence_count), spdk_json_decode_uint32, true},
372 : : {"buf_count", offsetof(struct rpc_accel_opts, buf_count), spdk_json_decode_uint32, true},
373 : : };
374 : :
375 : : static void
376 : 177 : rpc_accel_set_options(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
377 : : {
378 : 177 : struct spdk_accel_opts opts = { .size = sizeof(opts) };
379 : 83 : struct rpc_accel_opts rpc_opts;
380 : : int rc;
381 : :
382 : : /* We can't pass spdk_accel_opts directly to spdk_json_decode_object(), because that
383 : : * structure is packed, leading undefined behavior due to misaligned pointer access */
384 : 177 : spdk_accel_get_opts(&opts);
385 : 177 : rpc_opts.small_cache_size = opts.small_cache_size;
386 : 177 : rpc_opts.large_cache_size = opts.large_cache_size;
387 : 177 : rpc_opts.task_count = opts.task_count;
388 : 177 : rpc_opts.sequence_count = opts.sequence_count;
389 : 177 : rpc_opts.buf_count = opts.buf_count;
390 : :
391 [ - + ]: 177 : if (spdk_json_decode_object(params, rpc_accel_set_options_decoders,
392 : : SPDK_COUNTOF(rpc_accel_set_options_decoders), &rpc_opts)) {
393 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
394 : : "spdk_json_decode_object failed");
395 : 0 : return;
396 : : }
397 : :
398 : 177 : opts.small_cache_size = rpc_opts.small_cache_size;
399 : 177 : opts.large_cache_size = rpc_opts.large_cache_size;
400 : 177 : opts.task_count = rpc_opts.task_count;
401 : 177 : opts.sequence_count = rpc_opts.sequence_count;
402 : 177 : opts.buf_count = rpc_opts.buf_count;
403 : :
404 : 177 : rc = spdk_accel_set_opts(&opts);
405 [ - + ]: 177 : if (rc != 0) {
406 : 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
407 : 0 : return;
408 : : }
409 : :
410 : 177 : spdk_jsonrpc_send_bool_response(request, true);
411 : : }
412 : 2874 : SPDK_RPC_REGISTER("accel_set_options", rpc_accel_set_options, SPDK_RPC_STARTUP)
413 : :
414 : : static void
415 : 52 : rpc_accel_get_stats_done(struct accel_stats *stats, void *cb_arg)
416 : : {
417 : 52 : struct spdk_jsonrpc_request *request = cb_arg;
418 : : struct spdk_json_write_ctx *w;
419 : 0 : const char *module_name;
420 : : int i, rc;
421 : :
422 : 52 : w = spdk_jsonrpc_begin_result(request);
423 : 52 : spdk_json_write_object_begin(w);
424 : :
425 : 52 : spdk_json_write_named_uint64(w, "sequence_executed", stats->sequence_executed);
426 : 52 : spdk_json_write_named_uint64(w, "sequence_failed", stats->sequence_failed);
427 : 52 : spdk_json_write_named_array_begin(w, "operations");
428 [ + + ]: 780 : for (i = 0; i < SPDK_ACCEL_OPC_LAST; ++i) {
429 [ + + ]: 728 : if (stats->operations[i].executed + stats->operations[i].failed == 0) {
430 : 600 : continue;
431 : : }
432 : 128 : rc = spdk_accel_get_opc_module_name(i, &module_name);
433 [ - + ]: 128 : if (rc) {
434 : 0 : continue;
435 : : }
436 : 128 : spdk_json_write_object_begin(w);
437 : 128 : spdk_json_write_named_string(w, "opcode", spdk_accel_get_opcode_name(i));
438 : 128 : spdk_json_write_named_string(w, "module_name", module_name);
439 : 128 : spdk_json_write_named_uint64(w, "executed", stats->operations[i].executed);
440 : 128 : spdk_json_write_named_uint64(w, "failed", stats->operations[i].failed);
441 : 128 : spdk_json_write_named_uint64(w, "num_bytes", stats->operations[i].num_bytes);
442 : 128 : spdk_json_write_object_end(w);
443 : : }
444 : 52 : spdk_json_write_array_end(w);
445 : :
446 : 52 : spdk_json_write_named_uint64(w, "retry_task", stats->retry.task);
447 : 52 : spdk_json_write_named_uint64(w, "retry_sequence", stats->retry.sequence);
448 : 52 : spdk_json_write_named_uint64(w, "retry_iobuf", stats->retry.iobuf);
449 : 52 : spdk_json_write_named_uint64(w, "retry_bufdesc", stats->retry.bufdesc);
450 : :
451 : 52 : spdk_json_write_object_end(w);
452 : 52 : spdk_jsonrpc_end_result(request, w);
453 : 52 : }
454 : :
455 : : static void
456 : 52 : rpc_accel_get_stats(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
457 : : {
458 : : int rc;
459 : :
460 : 52 : rc = accel_get_stats(rpc_accel_get_stats_done, request);
461 [ - + ]: 52 : if (rc != 0) {
462 : 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
463 : : }
464 : 52 : }
465 : 2874 : SPDK_RPC_REGISTER("accel_get_stats", rpc_accel_get_stats, SPDK_RPC_RUNTIME)
|