lib/iscsi: Create portal group as public or private portal group

In SPDK iSCSI target, portal group works almost as identifier of
portal.

To support iSCSI login redirection, we need to have two types of
portal groups, public and private portal groups.

We need portals of public portal groups to redirect to a portal in
a private portal groups at login via temporary login redirection
funciton, and we need to make SendTargets return only portals in
public portal groups.

To do these simply, we mark primary or secondary portal group expicitly
at its creation by this patch.

Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Change-Id: Iccf87a4b9dd1f4a8fbb857a399b8f2dbc7c0b3ab
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/3491
Community-CI: Mellanox Build Bot
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
Shuhei Matsumoto 2020-07-21 21:53:06 +09:00 committed by Tomasz Zawadzki
parent 0f22282fc3
commit 10d6218444
8 changed files with 39 additions and 13 deletions

View File

@ -3868,7 +3868,8 @@ Example response:
"port": "3260" "port": "3260"
} }
], ],
"tag": 1 "tag": 1,
"private": false
} }
] ]
} }
@ -3884,6 +3885,7 @@ Name | Optional | Type | Description
--------------------------- | -------- | --------| ----------- --------------------------- | -------- | --------| -----------
tag | Required | number | Portal group tag tag | Required | number | Portal group tag
portals | Required | array | Not empty array of portals 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 Portal object

View File

@ -731,6 +731,7 @@ struct rpc_portal_list {
struct rpc_portal_group { struct rpc_portal_group {
int32_t tag; int32_t tag;
struct rpc_portal_list portal_list; struct rpc_portal_list portal_list;
bool is_private;
}; };
static void 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[] = { static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = {
{"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32}, {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32},
{"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list}, {"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 static void
@ -804,7 +806,7 @@ rpc_iscsi_create_portal_group(struct spdk_jsonrpc_request *request,
goto out; goto out;
} }
pg = iscsi_portal_grp_create(req.tag); pg = iscsi_portal_grp_create(req.tag, req.is_private);
if (pg == NULL) { if (pg == NULL) {
SPDK_ERRLOG("portal_grp_create failed\n"); SPDK_ERRLOG("portal_grp_create failed\n");
goto out; goto out;

View File

@ -306,7 +306,7 @@ iscsi_parse_redirect_addr(struct sockaddr_storage *sa,
} }
struct spdk_iscsi_portal_grp * 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)); struct spdk_iscsi_portal_grp *pg = malloc(sizeof(*pg));
@ -317,6 +317,7 @@ iscsi_portal_grp_create(int tag)
pg->ref = 0; pg->ref = 0;
pg->tag = tag; pg->tag = tag;
pg->is_private = is_private;
pthread_mutex_lock(&g_iscsi.mutex); pthread_mutex_lock(&g_iscsi.mutex);
pg->disable_chap = g_iscsi.disable_chap; 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); 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) { if (!pg) {
SPDK_ERRLOG("portal group malloc error (%s)\n", spdk_conf_section_get_name(sp)); SPDK_ERRLOG("portal group malloc error (%s)\n", spdk_conf_section_get_name(sp));
return -1; 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_array_end(w);
spdk_json_write_named_bool(w, "private", pg->is_private);
spdk_json_write_object_end(w); spdk_json_write_object_end(w);
} }

View File

@ -54,6 +54,16 @@ struct spdk_iscsi_portal {
struct spdk_iscsi_portal_grp { struct spdk_iscsi_portal_grp {
int ref; int ref;
int tag; 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 disable_chap;
bool require_chap; bool require_chap;
bool mutual_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); struct spdk_iscsi_portal *iscsi_portal_create(const char *host, const char *port);
void iscsi_portal_destroy(struct spdk_iscsi_portal *p); 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, void iscsi_portal_grp_add_portal(struct spdk_iscsi_portal_grp *pg,
struct spdk_iscsi_portal *p); struct spdk_iscsi_portal *p);
struct spdk_iscsi_portal *iscsi_portal_grp_find_portal_by_addr( struct spdk_iscsi_portal *iscsi_portal_grp_find_portal_by_addr(

View File

@ -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( rpc.iscsi.iscsi_create_portal_group(
args.client, args.client,
portals=portals, portals=portals,
tag=args.tag) tag=args.tag,
private=args.private)
p = subparsers.add_parser('iscsi_create_portal_group', aliases=['add_portal_group'], p = subparsers.add_parser('iscsi_create_portal_group', aliases=['add_portal_group'],
help='Add a 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) '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 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""") 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) p.set_defaults(func=iscsi_create_portal_group)
def iscsi_create_initiator_group(args): def iscsi_create_initiator_group(args):

View File

@ -375,17 +375,21 @@ def iscsi_target_node_add_pg_ig_maps(client, pg_ig_maps, name):
@deprecated_alias('add_portal_group') @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. """Add a portal group.
Args: Args:
portals: List of portals, e.g. [{'host': ip, 'port': port}] portals: List of portals, e.g. [{'host': ip, 'port': port}]
tag: Initiator group tag (unique, integer > 0) tag: Initiator group tag (unique, integer > 0)
private: Public (false) or private (true) portal group for login redirection.
Returns: Returns:
True or False True or False
""" """
params = {'tag': tag, 'portals': portals} params = {'tag': tag, 'portals': portals}
if private:
params['private'] = private
return client.call('iscsi_create_portal_group', params) return client.call('iscsi_create_portal_group', params)

View File

@ -315,7 +315,7 @@ class UIPortalGroups(UINode):
if cpumask: if cpumask:
print("WARNING: Specifying a CPU mask for portal groups is no longer supported. Ignoring.") print("WARNING: Specifying a CPU mask for portal groups is no longer supported. Ignoring.")
tag = self.ui_eval_param(tag, "number", None) 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): def ui_command_delete(self, tag):
"""Delete a portal group with given tag (unique, integer > 0))""" """Delete a portal group with given tag (unique, integer > 0))"""

View File

@ -223,7 +223,7 @@ portal_grp_register_unregister_case(void)
const char *host = "192.168.2.0"; const char *host = "192.168.2.0";
const char *port = "3260"; const char *port = "3260";
pg1 = iscsi_portal_grp_create(1); pg1 = iscsi_portal_grp_create(1, false);
CU_ASSERT(pg1 != NULL); CU_ASSERT(pg1 != NULL);
p = iscsi_portal_create(host, port); 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 *host = "192.168.2.0";
const char *port = "3260"; const char *port = "3260";
pg1 = iscsi_portal_grp_create(1); pg1 = iscsi_portal_grp_create(1, false);
CU_ASSERT(pg1 != NULL); CU_ASSERT(pg1 != NULL);
p = iscsi_portal_create(host, port); p = iscsi_portal_create(host, port);
@ -294,7 +294,7 @@ portal_grp_add_delete_case(void)
set_thread(0); set_thread(0);
/* internal of iscsi_create_portal_group */ /* internal of iscsi_create_portal_group */
pg1 = iscsi_portal_grp_create(1); pg1 = iscsi_portal_grp_create(1, false);
CU_ASSERT(pg1 != NULL); CU_ASSERT(pg1 != NULL);
p = iscsi_portal_create(host, port); p = iscsi_portal_create(host, port);
@ -340,7 +340,7 @@ portal_grp_add_delete_twice_case(void)
set_thread(0); set_thread(0);
/* internal of iscsi_create_portal_group related */ /* internal of iscsi_create_portal_group related */
pg1 = iscsi_portal_grp_create(1); pg1 = iscsi_portal_grp_create(1, false);
CU_ASSERT(pg1 != NULL); CU_ASSERT(pg1 != NULL);
p = iscsi_portal_create(host, port1); p = iscsi_portal_create(host, port1);
@ -356,7 +356,7 @@ portal_grp_add_delete_twice_case(void)
CU_ASSERT(rc == 0); CU_ASSERT(rc == 0);
/* internal of iscsi_create_portal_group related */ /* internal of iscsi_create_portal_group related */
pg2 = iscsi_portal_grp_create(2); pg2 = iscsi_portal_grp_create(2, false);
CU_ASSERT(pg2 != NULL); CU_ASSERT(pg2 != NULL);
p = iscsi_portal_create(host, port2); p = iscsi_portal_create(host, port2);