diff --git a/doc/jsonrpc.md b/doc/jsonrpc.md index b018245c7..ee5031ddb 100644 --- a/doc/jsonrpc.md +++ b/doc/jsonrpc.md @@ -3868,7 +3868,8 @@ Example response: "port": "3260" } ], - "tag": 1 + "tag": 1, + "private": false } ] } @@ -3884,6 +3885,7 @@ Name | Optional | Type | Description --------------------------- | -------- | --------| ----------- tag | Required | number | Portal group tag portals | Required | array | Not empty array of portals +private | Optional | boolean | When true, portals in this group are not returned by a discovery session. Used for login redirection. (default: `false`) Portal object diff --git a/lib/iscsi/iscsi_rpc.c b/lib/iscsi/iscsi_rpc.c index 8ab43d31d..75fd004c4 100644 --- a/lib/iscsi/iscsi_rpc.c +++ b/lib/iscsi/iscsi_rpc.c @@ -731,6 +731,7 @@ struct rpc_portal_list { struct rpc_portal_group { int32_t tag; struct rpc_portal_list portal_list; + bool is_private; }; static void @@ -784,6 +785,7 @@ decode_rpc_portal_list(const struct spdk_json_val *val, void *out) static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = { {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32}, {"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list}, + {"private", offsetof(struct rpc_portal_group, is_private), spdk_json_decode_bool, true}, }; static void @@ -804,7 +806,7 @@ rpc_iscsi_create_portal_group(struct spdk_jsonrpc_request *request, goto out; } - pg = iscsi_portal_grp_create(req.tag); + pg = iscsi_portal_grp_create(req.tag, req.is_private); if (pg == NULL) { SPDK_ERRLOG("portal_grp_create failed\n"); goto out; diff --git a/lib/iscsi/portal_grp.c b/lib/iscsi/portal_grp.c index 43d8e21eb..3203832b4 100644 --- a/lib/iscsi/portal_grp.c +++ b/lib/iscsi/portal_grp.c @@ -306,7 +306,7 @@ iscsi_parse_redirect_addr(struct sockaddr_storage *sa, } struct spdk_iscsi_portal_grp * -iscsi_portal_grp_create(int tag) +iscsi_portal_grp_create(int tag, bool is_private) { struct spdk_iscsi_portal_grp *pg = malloc(sizeof(*pg)); @@ -317,6 +317,7 @@ iscsi_portal_grp_create(int tag) pg->ref = 0; pg->tag = tag; + pg->is_private = is_private; pthread_mutex_lock(&g_iscsi.mutex); pg->disable_chap = g_iscsi.disable_chap; @@ -425,7 +426,7 @@ iscsi_parse_portal_grp(struct spdk_conf_section *sp) SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "Comment %s\n", val); } - pg = iscsi_portal_grp_create(spdk_conf_section_get_num(sp)); + pg = iscsi_portal_grp_create(spdk_conf_section_get_num(sp), false); if (!pg) { SPDK_ERRLOG("portal group malloc error (%s)\n", spdk_conf_section_get_name(sp)); return -1; @@ -653,6 +654,8 @@ iscsi_portal_grp_info_json(struct spdk_iscsi_portal_grp *pg, } spdk_json_write_array_end(w); + spdk_json_write_named_bool(w, "private", pg->is_private); + spdk_json_write_object_end(w); } diff --git a/lib/iscsi/portal_grp.h b/lib/iscsi/portal_grp.h index 923e0d50e..07682edbc 100644 --- a/lib/iscsi/portal_grp.h +++ b/lib/iscsi/portal_grp.h @@ -54,6 +54,16 @@ struct spdk_iscsi_portal { struct spdk_iscsi_portal_grp { int ref; int tag; + + /* For login redirection, there are two types of portal groups, public and + * private portal groups. Public portal groups have their portals returned + * by a discovery session. Private portal groups do not have their portals + * returned by a discovery session. A public portal group may optionally + * specify a redirect portal for non-discovery logins. This redirect portal + * must be from a private portal group. + */ + bool is_private; + bool disable_chap; bool require_chap; bool mutual_chap; @@ -67,7 +77,7 @@ struct spdk_iscsi_portal_grp { struct spdk_iscsi_portal *iscsi_portal_create(const char *host, const char *port); void iscsi_portal_destroy(struct spdk_iscsi_portal *p); -struct spdk_iscsi_portal_grp *iscsi_portal_grp_create(int tag); +struct spdk_iscsi_portal_grp *iscsi_portal_grp_create(int tag, bool is_private); void iscsi_portal_grp_add_portal(struct spdk_iscsi_portal_grp *pg, struct spdk_iscsi_portal *p); struct spdk_iscsi_portal *iscsi_portal_grp_find_portal_by_addr( diff --git a/scripts/rpc.py b/scripts/rpc.py index 667fb26c2..419225236 100755 --- a/scripts/rpc.py +++ b/scripts/rpc.py @@ -1103,7 +1103,8 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse rpc.iscsi.iscsi_create_portal_group( args.client, portals=portals, - tag=args.tag) + tag=args.tag, + private=args.private) p = subparsers.add_parser('iscsi_create_portal_group', aliases=['add_portal_group'], help='Add a portal group') @@ -1111,6 +1112,10 @@ Format: 'user:u1 secret:s1 muser:mu1 msecret:ms1,user:u2 secret:s2 muser:mu2 mse 'tag', help='Portal group tag (unique, integer > 0)', type=int) p.add_argument('portal_list', help="""List of portals in host:port format, separated by whitespace Example: '192.168.100.100:3260 192.168.100.100:3261 192.168.100.100:3262""") + p.add_argument('-p', '--private', help="""Public (false) or private (true) portal group. + Private portal groups do not have their portals returned by a discovery session. A public + portal group may optionally specify a redirect portal for non-discovery logins. This redirect + portal must be from a private portal group.""", action='store_true') p.set_defaults(func=iscsi_create_portal_group) def iscsi_create_initiator_group(args): diff --git a/scripts/rpc/iscsi.py b/scripts/rpc/iscsi.py index 6d64b6185..06e639c5a 100644 --- a/scripts/rpc/iscsi.py +++ b/scripts/rpc/iscsi.py @@ -375,17 +375,21 @@ def iscsi_target_node_add_pg_ig_maps(client, pg_ig_maps, name): @deprecated_alias('add_portal_group') -def iscsi_create_portal_group(client, portals, tag): +def iscsi_create_portal_group(client, portals, tag, private): """Add a portal group. Args: portals: List of portals, e.g. [{'host': ip, 'port': port}] tag: Initiator group tag (unique, integer > 0) + private: Public (false) or private (true) portal group for login redirection. Returns: True or False """ params = {'tag': tag, 'portals': portals} + + if private: + params['private'] = private return client.call('iscsi_create_portal_group', params) diff --git a/scripts/spdkcli/ui_node_iscsi.py b/scripts/spdkcli/ui_node_iscsi.py index 938cb7ab4..6852670b3 100644 --- a/scripts/spdkcli/ui_node_iscsi.py +++ b/scripts/spdkcli/ui_node_iscsi.py @@ -315,7 +315,7 @@ class UIPortalGroups(UINode): if cpumask: print("WARNING: Specifying a CPU mask for portal groups is no longer supported. Ignoring.") tag = self.ui_eval_param(tag, "number", None) - self.get_root().construct_portal_group(tag=tag, portals=portals) + self.get_root().construct_portal_group(tag=tag, portals=portals, private=None) def ui_command_delete(self, tag): """Delete a portal group with given tag (unique, integer > 0))""" diff --git a/test/unit/lib/iscsi/portal_grp.c/portal_grp_ut.c b/test/unit/lib/iscsi/portal_grp.c/portal_grp_ut.c index a89a1567f..bedde06b1 100644 --- a/test/unit/lib/iscsi/portal_grp.c/portal_grp_ut.c +++ b/test/unit/lib/iscsi/portal_grp.c/portal_grp_ut.c @@ -223,7 +223,7 @@ portal_grp_register_unregister_case(void) const char *host = "192.168.2.0"; const char *port = "3260"; - pg1 = iscsi_portal_grp_create(1); + pg1 = iscsi_portal_grp_create(1, false); CU_ASSERT(pg1 != NULL); p = iscsi_portal_create(host, port); @@ -254,7 +254,7 @@ portal_grp_register_twice_case(void) const char *host = "192.168.2.0"; const char *port = "3260"; - pg1 = iscsi_portal_grp_create(1); + pg1 = iscsi_portal_grp_create(1, false); CU_ASSERT(pg1 != NULL); p = iscsi_portal_create(host, port); @@ -294,7 +294,7 @@ portal_grp_add_delete_case(void) set_thread(0); /* internal of iscsi_create_portal_group */ - pg1 = iscsi_portal_grp_create(1); + pg1 = iscsi_portal_grp_create(1, false); CU_ASSERT(pg1 != NULL); p = iscsi_portal_create(host, port); @@ -340,7 +340,7 @@ portal_grp_add_delete_twice_case(void) set_thread(0); /* internal of iscsi_create_portal_group related */ - pg1 = iscsi_portal_grp_create(1); + pg1 = iscsi_portal_grp_create(1, false); CU_ASSERT(pg1 != NULL); p = iscsi_portal_create(host, port1); @@ -356,7 +356,7 @@ portal_grp_add_delete_twice_case(void) CU_ASSERT(rc == 0); /* internal of iscsi_create_portal_group related */ - pg2 = iscsi_portal_grp_create(2); + pg2 = iscsi_portal_grp_create(2, false); CU_ASSERT(pg2 != NULL); p = iscsi_portal_create(host, port2);