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