nvmf/fc: Add listen address support in FC transport

Enables access control to allow subsystem access on one or more FC ports.

If a subsystem definition does not have a single valid "Listen" directive,
then the subsystem will allow dynamic listen address binding. For such
subsystems,
   * When a FC port comes online, FC transport will add port's address
to subsystem's listen list.
   * When a FC port goes offline, FC transport will remove port's address
from subsystem's listen list.

If subsystem definition has 1 or more valid "Listen" directives then FC ports
coming online or going offline will not affect subsystem's listen address
whitelist.

Signed-off-by: Anil Veerabhadrappa <anil.veerabhadrappa@broadcom.com>
Change-Id: Ic7fed76e4bf8d1df0aeeae1d4fa5e6d207afccf3
Signed-off-by: Anil Veerabhadrappa <anil.veerabhadrappa@broadcom.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/471025
Community-CI: Broadcom SPDK FC-NVMe CI <spdk-ci.pdl@broadcom.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Alexey Marchuk <alexeymar@mellanox.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
Anil Veerabhadrappa 2019-10-11 00:12:43 -07:00 committed by Tomasz Zawadzki
parent c265fa18a8
commit 5e25bbdd49
6 changed files with 95 additions and 9 deletions

View File

@ -232,7 +232,7 @@
# - NQN is required and must be unique.
# - Between 1 and 255 Listen directives are allowed. This defines
# the addresses on which new connections may be accepted. The format
# is Listen <type> <address> where type can be RDMA or TCP.
# is Listen <type> <address> where type can be RDMA, TCP or FC.
# - Between 0 and 255 Host directives are allowed. This defines the
# NQNs of allowed hosts. If no Host directive is specified, all hosts
# are allowed to connect.
@ -273,3 +273,16 @@
Namespace Malloc1
Namespace AIO0
Namespace AIO1
# Subsystem with FC listen address directive
# - Listen option allows subsystem access on specific FC ports identified
# by WWNN-WWPN. Each subsystem allows 0 - 255 listen directives.
# If no listen directive is provided, subsystem can be accessed on all
# avialable FC links permitted by FC zoning rules.
#
# [Subsystem3]
#NQN nqn.2016-06.io.spdk:cnode3
#Listen FC "nn-0x20000090fac7ca5c:pn-0x10000090fac7ca5c"
#AllowAnyHost Yes
#SN SPDK00000000000003
#Namespace Malloc4

View File

@ -616,6 +616,29 @@ struct spdk_nvmf_listener *spdk_nvmf_subsystem_get_next_listener(
const struct spdk_nvme_transport_id *spdk_nvmf_listener_get_trid(
struct spdk_nvmf_listener *listener);
/**
* Set whether a subsystem should allow any listen address or only addresses in the allowed list.
*
* \param subsystem Subsystem to allow dynamic listener assignment.
* \param allow_any_listener true to allow dynamic listener assignment for
* this subsystem, or false to enforce the whitelist configured during
* subsystem setup.
*/
void spdk_nvmf_subsystem_allow_any_listener(
struct spdk_nvmf_subsystem *subsystem,
bool allow_any_listener);
/**
* Check whether a subsystem allows any listen address or only addresses in the allowed list.
*
* \param subsystem Subsystem to query.
*
* \return true if this subsystem allows dynamic management of listen address list,
* or false if only allows addresses in the whitelist configured during subsystem setup.
*/
bool spdk_nvmf_subsytem_any_listener_allowed(
struct spdk_nvmf_subsystem *subsystem);
/** NVMe-oF target namespace creation options */
struct spdk_nvmf_ns_opts {
/**

View File

@ -3003,16 +3003,23 @@ nvmf_fc_adm_add_rem_nport_listener(struct spdk_nvmf_fc_nport *nport, bool add)
while (subsystem) {
struct nvmf_fc_add_rem_listener_ctx *ctx;
ctx = calloc(1, sizeof(struct nvmf_fc_add_rem_listener_ctx));
if (ctx) {
ctx->add_listener = add;
spdk_nvmf_fc_create_trid(&ctx->trid, nport->fc_nodename.u.wwn,
nport->fc_portname.u.wwn);
if (spdk_nvmf_subsystem_pause(subsystem, nvmf_fc_adm_subsystem_paused_cb, ctx)) {
SPDK_ERRLOG("Failed to pause subsystem: %s\n", subsystem->subnqn);
free(ctx);
if (spdk_nvmf_subsytem_any_listener_allowed(subsystem) == true) {
ctx = calloc(1, sizeof(struct nvmf_fc_add_rem_listener_ctx));
if (ctx) {
ctx->add_listener = add;
spdk_nvmf_fc_create_trid(&ctx->trid,
nport->fc_nodename.u.wwn,
nport->fc_portname.u.wwn);
if (spdk_nvmf_subsystem_pause(subsystem,
nvmf_fc_adm_subsystem_paused_cb,
ctx)) {
SPDK_ERRLOG("Failed to pause subsystem: %s\n",
subsystem->subnqn);
free(ctx);
}
}
}
subsystem = spdk_nvmf_subsystem_get_next(subsystem);
}

View File

@ -350,6 +350,7 @@ struct spdk_nvmf_subsystem {
enum spdk_nvmf_subtype subtype;
uint16_t next_cntlid;
bool allow_any_host;
bool allow_any_listener ;
struct spdk_nvmf_tgt *tgt;

View File

@ -842,6 +842,20 @@ spdk_nvmf_listener_get_trid(struct spdk_nvmf_listener *listener)
return &listener->trid;
}
void
spdk_nvmf_subsystem_allow_any_listener(struct spdk_nvmf_subsystem *subsystem,
bool allow_any_listener)
{
subsystem->allow_any_listener = allow_any_listener;
}
bool
spdk_nvmf_subsytem_any_listener_allowed(struct spdk_nvmf_subsystem *subsystem)
{
return subsystem->allow_any_listener;
}
struct subsystem_update_ns_ctx {
struct spdk_nvmf_subsystem *subsystem;

View File

@ -266,6 +266,25 @@ spdk_nvmf_tgt_parse_listen_ip_addr(char *address,
return 0;
}
static int
spdk_nvmf_tgt_parse_listen_fc_addr(const char *address,
struct spdk_nvme_transport_id *trid)
{
/* transport address format and requirements,
* "nn-0xWWNN:pn-0xWWPN" - size equals 43 bytes and is required to
* contain 'nn' and 'pn'.
*/
if (strlen(address) != 43 || strncmp(address, "nn-0x", 5) ||
strncmp(&address[21], ":pn-0x", 6)) {
SPDK_ERRLOG("Unable to parse fc address '%s'\n", address);
return -1;
}
snprintf(trid->traddr, sizeof(trid->traddr), "%s", address);
return 0;
}
static int
spdk_nvmf_parse_subsystem(struct spdk_conf_section *sp)
{
@ -273,6 +292,7 @@ spdk_nvmf_parse_subsystem(struct spdk_conf_section *sp)
size_t i;
int lcore;
bool allow_any_host;
bool allow_any_listener = true;
const char *sn;
const char *mn;
struct spdk_nvmf_subsystem *subsystem;
@ -443,6 +463,11 @@ spdk_nvmf_parse_subsystem(struct spdk_conf_section *sp)
free(address_dup);
continue;
}
} else if (trid.trtype == SPDK_NVME_TRANSPORT_FC) {
if (spdk_nvmf_tgt_parse_listen_fc_addr(address_dup, &trid)) {
free(address_dup);
continue;
}
}
free(address_dup);
@ -450,8 +475,11 @@ spdk_nvmf_parse_subsystem(struct spdk_conf_section *sp)
spdk_nvmf_tgt_listen(g_spdk_nvmf_tgt, &trid, spdk_nvmf_tgt_listen_done, NULL);
spdk_nvmf_subsystem_add_listener(subsystem, &trid);
allow_any_listener = false;
}
spdk_nvmf_subsystem_allow_any_listener(subsystem, allow_any_listener);
/* Parse Host sections */
for (i = 0; ; i++) {
const char *host = spdk_conf_section_get_nval(sp, "Host", i);