xref: /spdk/lib/accel/accel_rpc.c (revision 42fd001310188f0635a3953f3b0ea0b33a840902)
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  				 * cant 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\n");
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\n", 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},
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);
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 spdk_accel_opts opts = { .size = sizeof(opts) };
378  	struct rpc_accel_opts rpc_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 undefined behavior due to misaligned pointer access */
383  	spdk_accel_get_opts(&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_array_begin(w, "operations");
427  	for (i = 0; i < SPDK_ACCEL_OPC_LAST; ++i) {
428  		if (stats->operations[i].executed + stats->operations[i].failed == 0) {
429  			continue;
430  		}
431  		rc = spdk_accel_get_opc_module_name(i, &module_name);
432  		if (rc) {
433  			continue;
434  		}
435  		spdk_json_write_object_begin(w);
436  		spdk_json_write_named_string(w, "opcode", spdk_accel_get_opcode_name(i));
437  		spdk_json_write_named_string(w, "module_name", module_name);
438  		spdk_json_write_named_uint64(w, "executed", stats->operations[i].executed);
439  		spdk_json_write_named_uint64(w, "failed", stats->operations[i].failed);
440  		spdk_json_write_named_uint64(w, "num_bytes", stats->operations[i].num_bytes);
441  		spdk_json_write_object_end(w);
442  	}
443  	spdk_json_write_array_end(w);
444  
445  	spdk_json_write_named_uint64(w, "retry_task", stats->retry.task);
446  	spdk_json_write_named_uint64(w, "retry_sequence", stats->retry.sequence);
447  	spdk_json_write_named_uint64(w, "retry_iobuf", stats->retry.iobuf);
448  	spdk_json_write_named_uint64(w, "retry_bufdesc", stats->retry.bufdesc);
449  
450  	spdk_json_write_object_end(w);
451  	spdk_jsonrpc_end_result(request, w);
452  }
453  
454  static void
455  rpc_accel_get_stats(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params)
456  {
457  	int rc;
458  
459  	rc = accel_get_stats(rpc_accel_get_stats_done, request);
460  	if (rc != 0) {
461  		spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
462  	}
463  }
464  SPDK_RPC_REGISTER("accel_get_stats", rpc_accel_get_stats, SPDK_RPC_RUNTIME)
465