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