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