xref: /spdk/lib/accel/accel_rpc.c (revision f8abbede89d30584d2a4f8427b13896f8591b873)
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 spdk_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 < SPDK_ACCEL_OPC_LAST; opcode++) {
37 		name = spdk_accel_get_opcode_name(opcode);
38 		if (name != NULL) {
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 
66 	spdk_json_write_object_begin(w);
67 
68 	spdk_json_write_named_string(w, "module", info->name);
69 	spdk_json_write_named_array_begin(w, "supported ops");
70 
71 	for (i = 0; i < info->num_ops; i++) {
72 		name = spdk_accel_get_opcode_name(info->ops[i]);
73 		if (name != NULL) {
74 			spdk_json_write_string(w, name);
75 		} else {
76 			/* this should never happen */
77 			SPDK_ERRLOG("Invalid opcode (%d)).\n", info->ops[i]);
78 			assert(0);
79 		}
80 	}
81 
82 	spdk_json_write_array_end(w);
83 	spdk_json_write_object_end(w);
84 }
85 
86 static void
87 rpc_accel_get_module_info(struct spdk_jsonrpc_request *request,
88 			  const struct spdk_json_val *params)
89 {
90 	struct module_info info;
91 
92 	if (params != NULL) {
93 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
94 						 "accel_get_module_info requires no parameters");
95 		return;
96 	}
97 
98 	info.w = spdk_jsonrpc_begin_result(request);
99 	spdk_json_write_array_begin(info.w);
100 
101 	_accel_for_each_module(&info, rpc_dump_module_info);
102 
103 	spdk_json_write_array_end(info.w);
104 	spdk_jsonrpc_end_result(request, info.w);
105 }
106 SPDK_RPC_REGISTER("accel_get_module_info", rpc_accel_get_module_info, SPDK_RPC_RUNTIME)
107 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 free_accel_assign_opc(struct rpc_accel_assign_opc *r)
121 {
122 	free(r->opname);
123 	free(r->module);
124 }
125 
126 static void
127 rpc_accel_assign_opc(struct spdk_jsonrpc_request *request,
128 		     const struct spdk_json_val *params)
129 {
130 	struct rpc_accel_assign_opc req = {};
131 	const char *opcode_str;
132 	enum spdk_accel_opcode opcode;
133 	bool found = false;
134 	int rc;
135 
136 	if (spdk_json_decode_object(params, rpc_accel_assign_opc_decoders,
137 				    SPDK_COUNTOF(rpc_accel_assign_opc_decoders),
138 				    &req)) {
139 		SPDK_DEBUGLOG(accel, "spdk_json_decode_object failed\n");
140 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
141 						 "spdk_json_decode_object failed");
142 		goto cleanup;
143 	}
144 
145 	for (opcode = 0; opcode < SPDK_ACCEL_OPC_LAST; opcode++) {
146 		opcode_str = spdk_accel_get_opcode_name(opcode);
147 		assert(opcode_str != NULL);
148 		if (strcmp(opcode_str, req.opname) == 0) {
149 			found = true;
150 			break;
151 		}
152 	}
153 
154 	if (found == false) {
155 		SPDK_DEBUGLOG(accel, "Invalid operation name\n");
156 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
157 						 "spdk_json_decode_object failed");
158 		goto cleanup;
159 	}
160 
161 	rc = spdk_accel_assign_opc(opcode, req.module);
162 	if (rc) {
163 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
164 						 "error assigning opcode");
165 		goto cleanup;
166 	}
167 
168 	SPDK_NOTICELOG("Operation %s will be assigned to module %s\n", req.opname, req.module);
169 	spdk_jsonrpc_send_bool_response(request, true);
170 
171 cleanup:
172 	free_accel_assign_opc(&req);
173 
174 }
175 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 rpc_accel_crypto_key_create(struct spdk_jsonrpc_request *request,
191 			    const struct spdk_json_val *params)
192 {
193 	struct rpc_accel_crypto_key_create req = {};
194 	size_t key_size;
195 	int rc;
196 
197 	if (spdk_json_decode_object(params, rpc_accel_dek_create_decoders,
198 				    SPDK_COUNTOF(rpc_accel_dek_create_decoders),
199 				    &req)) {
200 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
201 						 "spdk_json_decode_object failed");
202 		goto cleanup;
203 	}
204 
205 	rc = spdk_accel_crypto_key_create(&req.param);
206 	if (rc) {
207 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
208 						     "failed to create DEK, rc %d", rc);
209 	} else {
210 		spdk_jsonrpc_send_bool_response(request, true);
211 	}
212 
213 cleanup:
214 	free(req.param.cipher);
215 	if (req.param.hex_key) {
216 		key_size = strnlen(req.param.hex_key, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH);
217 		spdk_memset_s(req.param.hex_key, key_size, 0, key_size);
218 		free(req.param.hex_key);
219 	}
220 	if (req.param.hex_key2) {
221 		key_size = strnlen(req.param.hex_key2, SPDK_ACCEL_CRYPTO_KEY_MAX_HEX_LENGTH);
222 		spdk_memset_s(req.param.hex_key2, key_size, 0, key_size);
223 		free(req.param.hex_key2);
224 	}
225 	free(req.param.tweak_mode);
226 	free(req.param.key_name);
227 }
228 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 rpc_accel_crypto_keys_get(struct spdk_jsonrpc_request *request,
240 			  const struct spdk_json_val *params)
241 {
242 	struct rpc_accel_crypto_keys_get_ctx req = {};
243 	struct spdk_accel_crypto_key *key = NULL;
244 	struct spdk_json_write_ctx *w;
245 
246 	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 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
250 						 "spdk_json_decode_object failed");
251 		free(req.key_name);
252 		return;
253 	}
254 
255 	if (req.key_name) {
256 		key = spdk_accel_crypto_key_get(req.key_name);
257 		free(req.key_name);
258 		if (!key) {
259 			spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "key was not found\n");
260 			return;
261 		}
262 	}
263 
264 	w = spdk_jsonrpc_begin_result(request);
265 	spdk_json_write_array_begin(w);
266 
267 	if (key) {
268 		_accel_crypto_key_dump_param(w, key);
269 	} else {
270 		_accel_crypto_keys_dump_param(w);
271 	}
272 
273 	spdk_json_write_array_end(w);
274 	spdk_jsonrpc_end_result(request, w);
275 }
276 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 rpc_accel_crypto_key_destroy(struct spdk_jsonrpc_request *request,
284 			     const struct spdk_json_val *params)
285 {
286 	struct rpc_accel_crypto_keys_get_ctx req = {};
287 	struct spdk_accel_crypto_key *key = NULL;
288 	int rc;
289 
290 	if (spdk_json_decode_object(params, rpc_accel_crypto_key_destroy_decoders,
291 				    SPDK_COUNTOF(rpc_accel_crypto_key_destroy_decoders),
292 				    &req)) {
293 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
294 						 "spdk_json_decode_object failed");
295 		free(req.key_name);
296 		return;
297 	}
298 
299 	key = spdk_accel_crypto_key_get(req.key_name);
300 	if (!key) {
301 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
302 						 "No key object found");
303 		free(req.key_name);
304 		return;
305 
306 	}
307 	rc = spdk_accel_crypto_key_destroy(key);
308 	if (rc) {
309 		spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
310 						     "Failed to destroy key, rc %d\n", rc);
311 	} else {
312 		spdk_jsonrpc_send_bool_response(request, true);
313 	}
314 
315 	free(req.key_name);
316 }
317 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 free_rpc_accel_set_driver(struct rpc_accel_set_driver *r)
329 {
330 	free(r->name);
331 }
332 
333 static void
334 rpc_accel_set_driver(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
335 {
336 	struct rpc_accel_set_driver req = {};
337 	int rc;
338 
339 	if (spdk_json_decode_object(params, rpc_accel_set_driver_decoders,
340 				    SPDK_COUNTOF(rpc_accel_set_driver_decoders), &req)) {
341 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
342 						 "spdk_json_decode_object failed");
343 		return;
344 	}
345 
346 	rc = spdk_accel_set_driver(req.name);
347 	if (rc != 0) {
348 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
349 		goto cleanup;
350 	}
351 
352 	SPDK_NOTICELOG("Using accel driver: %s\n", req.name);
353 	spdk_jsonrpc_send_bool_response(request, true);
354 cleanup:
355 	free_rpc_accel_set_driver(&req);
356 }
357 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 rpc_accel_set_options(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
377 {
378 	struct spdk_accel_opts opts = { .size = sizeof(opts) };
379 	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 	spdk_accel_get_opts(&opts);
385 	rpc_opts.small_cache_size = opts.small_cache_size;
386 	rpc_opts.large_cache_size = opts.large_cache_size;
387 	rpc_opts.task_count = opts.task_count;
388 	rpc_opts.sequence_count = opts.sequence_count;
389 	rpc_opts.buf_count = opts.buf_count;
390 
391 	if (spdk_json_decode_object(params, rpc_accel_set_options_decoders,
392 				    SPDK_COUNTOF(rpc_accel_set_options_decoders), &rpc_opts)) {
393 		spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR,
394 						 "spdk_json_decode_object failed");
395 		return;
396 	}
397 
398 	opts.small_cache_size = rpc_opts.small_cache_size;
399 	opts.large_cache_size = rpc_opts.large_cache_size;
400 	opts.task_count = rpc_opts.task_count;
401 	opts.sequence_count = rpc_opts.sequence_count;
402 	opts.buf_count = rpc_opts.buf_count;
403 
404 	rc = spdk_accel_set_opts(&opts);
405 	if (rc != 0) {
406 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
407 		return;
408 	}
409 
410 	spdk_jsonrpc_send_bool_response(request, true);
411 }
412 SPDK_RPC_REGISTER("accel_set_options", rpc_accel_set_options, SPDK_RPC_STARTUP)
413 
414 static void
415 rpc_accel_get_stats_done(struct accel_stats *stats, void *cb_arg)
416 {
417 	struct spdk_jsonrpc_request *request = cb_arg;
418 	struct spdk_json_write_ctx *w;
419 	const char *module_name;
420 	int i, rc;
421 
422 	w = spdk_jsonrpc_begin_result(request);
423 	spdk_json_write_object_begin(w);
424 
425 	spdk_json_write_named_uint64(w, "sequence_executed", stats->sequence_executed);
426 	spdk_json_write_named_uint64(w, "sequence_failed", stats->sequence_failed);
427 	spdk_json_write_named_array_begin(w, "operations");
428 	for (i = 0; i < SPDK_ACCEL_OPC_LAST; ++i) {
429 		if (stats->operations[i].executed + stats->operations[i].failed == 0) {
430 			continue;
431 		}
432 		rc = spdk_accel_get_opc_module_name(i, &module_name);
433 		if (rc) {
434 			continue;
435 		}
436 		spdk_json_write_object_begin(w);
437 		spdk_json_write_named_string(w, "opcode", spdk_accel_get_opcode_name(i));
438 		spdk_json_write_named_string(w, "module_name", module_name);
439 		spdk_json_write_named_uint64(w, "executed", stats->operations[i].executed);
440 		spdk_json_write_named_uint64(w, "failed", stats->operations[i].failed);
441 		spdk_json_write_named_uint64(w, "num_bytes", stats->operations[i].num_bytes);
442 		spdk_json_write_object_end(w);
443 	}
444 	spdk_json_write_array_end(w);
445 
446 	spdk_json_write_named_uint64(w, "retry_task", stats->retry.task);
447 	spdk_json_write_named_uint64(w, "retry_sequence", stats->retry.sequence);
448 	spdk_json_write_named_uint64(w, "retry_iobuf", stats->retry.iobuf);
449 	spdk_json_write_named_uint64(w, "retry_bufdesc", stats->retry.bufdesc);
450 
451 	spdk_json_write_object_end(w);
452 	spdk_jsonrpc_end_result(request, w);
453 }
454 
455 static void
456 rpc_accel_get_stats(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
457 {
458 	int rc;
459 
460 	rc = accel_get_stats(rpc_accel_get_stats_done, request);
461 	if (rc != 0) {
462 		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
463 	}
464 }
465 SPDK_RPC_REGISTER("accel_get_stats", rpc_accel_get_stats, SPDK_RPC_RUNTIME)
466