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 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(info->ops[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", info->ops[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 spdk_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 < SPDK_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 < SPDK_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_named_uint64(w, "retry_task", stats->retry.task); 449 spdk_json_write_named_uint64(w, "retry_sequence", stats->retry.sequence); 450 spdk_json_write_named_uint64(w, "retry_iobuf", stats->retry.iobuf); 451 spdk_json_write_named_uint64(w, "retry_bufdesc", stats->retry.bufdesc); 452 453 spdk_json_write_object_end(w); 454 spdk_jsonrpc_end_result(request, w); 455 } 456 457 static void 458 rpc_accel_get_stats(struct spdk_jsonrpc_request *request, const struct spdk_json_val *params) 459 { 460 int rc; 461 462 rc = accel_get_stats(rpc_accel_get_stats_done, request); 463 if (rc != 0) { 464 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 465 } 466 } 467 SPDK_RPC_REGISTER("accel_get_stats", rpc_accel_get_stats, SPDK_RPC_RUNTIME) 468