diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index ad0d60540..f850643d2 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -1496,6 +1496,57 @@ Example response: ## Acceleration Framework Layer {#jsonrpc_components_accel_fw} +### accel_get_engine_info {#accel_get_engine_info} + +Get a list of valid engine names and their supported operations. + +#### Parameters + +None + +#### Example + +Example request: + +~~~json +{ + "jsonrpc": "2.0", + "method": "accel_get_engine_info", + "id": 1 +} +~~~ + +Example response: + +~~~json +[ + { + "engine": "software", + "supported ops": [ + "copy", + "fill", + "dualcast", + "compare", + "crc32c", + "copy_crc32c", + "compress", + "decompress" + ] + }, + { + "engine": "dsa", + "supported ops": [ + "copy", + "fill", + "dualcast", + "compare", + "crc32c", + "copy_crc32c" + ] + } +] +~~~ + ### accel_get_opc_assignments {#rpc_accel_get_opc_assignments} Get a list of opcode names and their assigned accel_fw modules. diff --git a/include/spdk_internal/accel_engine.h b/include/spdk_internal/accel_engine.h index f1b0a541a..f27de3e2a 100644 --- a/include/spdk_internal/accel_engine.h +++ b/include/spdk_internal/accel_engine.h @@ -16,6 +16,16 @@ #include "../isa-l/include/igzip_lib.h" #endif +struct engine_info { + struct spdk_json_write_ctx *w; + const char *name; + enum accel_opcode ops[ACCEL_OPC_LAST]; + uint32_t num_ops; +}; + +typedef void (*_accel_for_each_engine_fn)(struct engine_info *info); +void _accel_for_each_engine(struct engine_info *info, _accel_for_each_engine_fn fn); + struct spdk_accel_task; void spdk_accel_task_complete(struct spdk_accel_task *task, int status); diff --git a/lib/accel/accel_engine.c b/lib/accel/accel_engine.c index 0f1db3797..03122f431 100644 --- a/lib/accel/accel_engine.c +++ b/lib/accel/accel_engine.c @@ -66,6 +66,27 @@ spdk_accel_get_opc_engine_name(enum accel_opcode opcode, const char **engine_nam return 0; } +void +_accel_for_each_engine(struct engine_info *info, _accel_for_each_engine_fn fn) +{ + struct spdk_accel_engine *accel_engine; + enum accel_opcode opcode; + int j = 0; + + TAILQ_FOREACH(accel_engine, &g_engine_list, tailq) { + for (opcode = 0; opcode < ACCEL_OPC_LAST; opcode++) { + if (accel_engine->supports_opcode(opcode)) { + info->ops[j] = opcode; + j++; + } + } + info->name = accel_engine->name; + info->num_ops = j; + fn(info); + j = 0; + } +} + static struct spdk_accel_engine * _engine_find_by_name(const char *name) { diff --git a/lib/accel/accel_engine_rpc.c b/lib/accel/accel_engine_rpc.c index 7a4b1c753..f4bb9f072 100644 --- a/lib/accel/accel_engine_rpc.c +++ b/lib/accel/accel_engine_rpc.c @@ -71,3 +71,54 @@ rpc_accel_get_opc_assignments(struct spdk_jsonrpc_request *request, } SPDK_RPC_REGISTER("accel_get_opc_assignments", rpc_accel_get_opc_assignments, SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME) + +static void +rpc_dump_engine_info(struct engine_info *info) +{ + struct spdk_json_write_ctx *w = info->w; + const char *name; + uint32_t i; + int rc; + + spdk_json_write_object_begin(w); + + spdk_json_write_named_string(w, "engine", info->name); + spdk_json_write_named_array_begin(w, "suppoerted ops"); + + for (i = 0; i < info->num_ops; i++) { + rc = _get_opc_name(i, &name); + if (rc == 0) { + spdk_json_write_string(w, name); + } else { + /* this should never happen */ + SPDK_ERRLOG("Invalid opcode (%d)).\n", i); + assert(0); + } + } + + spdk_json_write_array_end(w); + spdk_json_write_object_end(w); +} + +static void +rpc_accel_get_engine_info(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct engine_info info; + + if (params != NULL) { + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "accel_get_engine_info requires no parameters"); + return; + } + + info.w = spdk_jsonrpc_begin_result(request); + spdk_json_write_array_begin(info.w); + + _accel_for_each_engine(&info, rpc_dump_engine_info); + + spdk_json_write_array_end(info.w); + spdk_jsonrpc_end_result(request, info.w); +} +SPDK_RPC_REGISTER("accel_get_engine_info", rpc_accel_get_engine_info, + SPDK_RPC_RUNTIME) diff --git a/python/spdk/rpc/accel.py b/python/spdk/rpc/accel.py index bb1a53617..d04e41b05 100644 --- a/python/spdk/rpc/accel.py +++ b/python/spdk/rpc/accel.py @@ -2,3 +2,9 @@ def accel_get_opc_assignments(client): """Get list of opcode name to engine assignments. """ return client.call('accel_get_opc_assignments') + + +def accel_get_engine_info(client): + """Get list of valid engine names and their operations. + """ + return client.call('accel_get_engine_info') diff --git a/scripts/rpc.py b/scripts/rpc.py index f82bad886..d61211bf3 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -2569,6 +2569,12 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse p = subparsers.add_parser('accel_get_opc_assignments', help='Get list of opcode name to engine assignments.') p.set_defaults(func=accel_get_opc_assignments) + def accel_get_engine_info(args): + print_dict(rpc.accel.accel_get_engine_info(args.client)) + + p = subparsers.add_parser('accel_get_engine_info', help='Get list of valid engine names and their operations.') + p.set_defaults(func=accel_get_engine_info) + # ioat def ioat_scan_accel_engine(args): rpc.ioat.ioat_scan_accel_engine(args.client)