diff --git a/lib/iscsi/iscsi_rpc.c b/lib/iscsi/iscsi_rpc.c index 735ab4dbd8..0e89a105b9 100644 --- a/lib/iscsi/iscsi_rpc.c +++ b/lib/iscsi/iscsi_rpc.c @@ -515,6 +515,120 @@ invalid: } SPDK_RPC_REGISTER("construct_target_node", spdk_rpc_construct_target_node) +struct rpc_pg_ig_maps { + char *name; + struct rpc_pg_tags pg_tags; + struct rpc_ig_tags ig_tags; +}; + +static const struct spdk_json_object_decoder rpc_pg_ig_maps_decoders[] = { + {"name", offsetof(struct rpc_pg_ig_maps, name), spdk_json_decode_string}, + {"pg_tags", offsetof(struct rpc_pg_ig_maps, pg_tags), decode_rpc_pg_tags}, + {"ig_tags", offsetof(struct rpc_pg_ig_maps, ig_tags), decode_rpc_ig_tags}, +}; + +static void +spdk_rpc_add_pg_ig_maps(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_pg_ig_maps req = {}; + struct spdk_json_write_ctx *w; + struct spdk_iscsi_tgt_node *target; + int rc; + + if (spdk_json_decode_object(params, rpc_pg_ig_maps_decoders, + SPDK_COUNTOF(rpc_pg_ig_maps_decoders), + &req)) { + SPDK_ERRLOG("spdk_json_decode_object failed\n"); + goto invalid; + } + + if (req.pg_tags.num_tags != req.ig_tags.num_tags) { + SPDK_ERRLOG("pg_tags/ig_tags count mismatch\n"); + goto invalid; + } + + target = spdk_iscsi_find_tgt_node(req.name); + if (target == NULL) { + SPDK_ERRLOG("target is not found\n"); + goto invalid; + } + + rc = spdk_iscsi_tgt_node_add_pg_ig_maps(target, req.pg_tags.tags, + req.ig_tags.tags, + req.pg_tags.num_tags); + if (rc < 0) { + SPDK_ERRLOG("add pg-ig maps failed\n"); + goto invalid; + } + + free(req.name); + + w = spdk_jsonrpc_begin_result(request); + if (w != NULL) { + spdk_json_write_bool(w, true); + spdk_jsonrpc_end_result(request, w); + } + return; + +invalid: + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "Invalid parameters"); + free(req.name); +} +SPDK_RPC_REGISTER("add_pg_ig_maps", spdk_rpc_add_pg_ig_maps) + +static void +spdk_rpc_delete_pg_ig_maps(struct spdk_jsonrpc_request *request, + const struct spdk_json_val *params) +{ + struct rpc_pg_ig_maps req = {}; + struct spdk_json_write_ctx *w; + struct spdk_iscsi_tgt_node *target; + int rc; + + if (spdk_json_decode_object(params, rpc_pg_ig_maps_decoders, + SPDK_COUNTOF(rpc_pg_ig_maps_decoders), + &req)) { + SPDK_ERRLOG("spdk_json_decode_object failed\n"); + goto invalid; + } + + if (req.pg_tags.num_tags != req.ig_tags.num_tags) { + SPDK_ERRLOG("pg_tags/ig_tags count mismatch\n"); + goto invalid; + } + + target = spdk_iscsi_find_tgt_node(req.name); + if (target == NULL) { + SPDK_ERRLOG("target is not found\n"); + goto invalid; + } + + rc = spdk_iscsi_tgt_node_delete_pg_ig_maps(target, req.pg_tags.tags, + req.ig_tags.tags, + req.pg_tags.num_tags); + if (rc < 0) { + SPDK_ERRLOG("remove pg-ig maps failed\n"); + goto invalid; + } + + free(req.name); + + w = spdk_jsonrpc_begin_result(request); + if (w != NULL) { + spdk_json_write_bool(w, true); + spdk_jsonrpc_end_result(request, w); + } + return; + +invalid: + spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, + "Invalid parameters"); + free(req.name); +} +SPDK_RPC_REGISTER("delete_pg_ig_maps", spdk_rpc_delete_pg_ig_maps) + struct rpc_delete_target_node { char *name; }; diff --git a/scripts/rpc.py b/scripts/rpc.py index d6bc832f09..8eec206a1e 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -163,6 +163,56 @@ p.add_argument('chap_auth_group', help="""Authentication group ID for this targe p.set_defaults(func=construct_target_node) +def add_pg_ig_maps(args): + pg_tags = [] + ig_tags = [] + for u in args.pg_ig_mappings.strip().split(" "): + pg, ig = u.split(":") + pg_tags.append(int(pg)) + ig_tags.append(int(ig)) + + params = { + 'name': args.name, + 'pg_tags': pg_tags, + 'ig_tags': ig_tags, + } + jsonrpc_call('add_pg_ig_maps', params) + +p = subparsers.add_parser('add_pg_ig_maps', help='Add PG-IG maps to the target node') +p.add_argument('name', help='Target node name (ASCII)') +p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings +Whitespace separated, quoted, mapping defined with colon +separated list of "tags" (int > 0) +Example: '1:1 2:2 2:1' +*** The Portal/Initiator Groups must be precreated ***""") +p.set_defaults(func=add_pg_ig_maps) + + +def delete_pg_ig_maps(args): + pg_tags = [] + ig_tags = [] + for u in args.pg_ig_mappings.strip().split(" "): + pg, ig = u.split(":") + pg_tags.append(int(pg)) + ig_tags.append(int(ig)) + + params = { + 'name': args.name, + 'pg_tags': pg_tags, + 'ig_tags': ig_tags, + } + jsonrpc_call('delete_pg_ig_maps', params) + +p = subparsers.add_parser('delete_pg_ig_maps', help='Delete PG-IG maps from the target node') +p.add_argument('name', help='Target node name (ASCII)') +p.add_argument('pg_ig_mappings', help="""List of (Portal_Group_Tag:Initiator_Group_Tag) mappings +Whitespace separated, quoted, mapping defined with colon +separated list of "tags" (int > 0) +Example: '1:1 2:2 2:1' +*** The Portal/Initiator Groups must be precreated ***""") +p.set_defaults(func=delete_pg_ig_maps) + + def construct_malloc_bdev(args): num_blocks = (args.total_size * 1024 * 1024) / args.block_size params = {'num_blocks': num_blocks, 'block_size': args.block_size}