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