nvmf: Remove host.[ch] and port.[ch]
These can be simplified and merged into the subsystem. Remove the concept of mappings from subsystems and replace it with a list of hosts and ports. The host is optional - not specifying a host means any host can connect. Change-Id: Ib3786acb40a34b7e10935af55f4b6756d40cc906 Signed-off-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
parent
d38d299576
commit
2b9d85c448
@ -44,8 +44,6 @@
|
||||
|
||||
#include "spdk/event.h"
|
||||
|
||||
#include "nvmf/port.h"
|
||||
#include "nvmf/host.h"
|
||||
#include "nvmf/transport.h"
|
||||
|
||||
#include "spdk/log.h"
|
||||
|
@ -43,30 +43,6 @@
|
||||
# initiator having the opportunity to specify a smaller value.
|
||||
#MaxQueueDepth 128
|
||||
|
||||
# Users must change the Port section(s) to match the IP addresses
|
||||
# for their environment.
|
||||
# Port sections define which fabric network ports the NVMf server
|
||||
# will use to listen and accept incoming connections. A Port is
|
||||
# also used to control which ports will be used for each individual
|
||||
# NVM subsystem controller session, providing a means to distribute NVMf
|
||||
# traffic across all network ports.
|
||||
[Port1]
|
||||
Listen RDMA 15.15.15.2:4420
|
||||
|
||||
[Port2]
|
||||
Listen RDMA 192.168.2.21:4420
|
||||
|
||||
# Users must change the Host section(s) to match the IP
|
||||
# addresses of the clients that will connect to this target.
|
||||
# Netmask can be used to specify a single IP address or a range of IP addresses
|
||||
# Netmask 192.168.1.20 <== single IP address
|
||||
# Netmask 192.168.1.0/24 <== IP range 192.168.1.*
|
||||
[Host1]
|
||||
Netmask 15.15.15.0/24
|
||||
|
||||
[Host2]
|
||||
Netmask 192.168.2.0/24
|
||||
|
||||
# NVMe Device Whitelist
|
||||
# Users may specify which NVMe devices to claim by their PCI
|
||||
# domain, bus, device, and function. The format is dddd:bb:dd.f, which is
|
||||
@ -81,29 +57,15 @@
|
||||
BDF 0000:01:00.0 Nvme1
|
||||
# ClaimAllDevices Yes
|
||||
|
||||
# Users should change the Subsystem section(s) below to define the
|
||||
# set of local NVMe resources that will be accessible by specific groups
|
||||
# of hosts. These mappings will be inspected to approve
|
||||
# remote fabric transport and NVMf protocol connection requests.
|
||||
#
|
||||
# Each approved NVMf connection represents a specific virtual controller
|
||||
# session within the NVMf subsystem. Any such session is allowed access
|
||||
# to all NVMe namespaces within the subsystem.
|
||||
#
|
||||
# NQN, Mapping, Controller are minimum required.
|
||||
# The Mapping defines the local fabric network port to be used by remote
|
||||
# connecting initiator. Multiple mappings can be used to permit shared
|
||||
# access to the same subsystem.
|
||||
# Each Controller identifies a specific HW device from the Nvme whitelist
|
||||
# section above.
|
||||
[Subsystem1]
|
||||
NQN nqn.2016-06.io.spdk:cnode1
|
||||
Mapping Port1 Host1
|
||||
Listen RDMA 15.15.15.2:4420
|
||||
Host nqn.2016-06.io.spdk:init
|
||||
Controller Nvme0
|
||||
|
||||
[Subsystem2]
|
||||
NQN nqn.2016-06.io.spdk:cnode2
|
||||
Mapping Port2 Host2
|
||||
# Using NVME 1 namespace 1
|
||||
Listen RDMA 192.168.2.21:4420
|
||||
Host nqn.2016-06.io.spdk:init
|
||||
Controller Nvme1
|
||||
|
||||
|
@ -35,8 +35,8 @@ SPDK_ROOT_DIR := $(abspath $(CURDIR)/../..)
|
||||
|
||||
CFLAGS += $(DPDK_INC)
|
||||
LIBNAME = nvmf
|
||||
C_SRCS = port.c conn.c controller.c \
|
||||
host.c subsystem.c conf.c \
|
||||
C_SRCS = conn.c controller.c \
|
||||
subsystem.c conf.c \
|
||||
nvmf.c request.c session.c transport.c
|
||||
|
||||
C_SRCS-$(CONFIG_RDMA) += rdma.c
|
||||
|
226
lib/nvmf/conf.c
226
lib/nvmf/conf.c
@ -41,14 +41,15 @@
|
||||
|
||||
#include "conf.h"
|
||||
#include "controller.h"
|
||||
#include "host.h"
|
||||
#include "nvmf_internal.h"
|
||||
#include "port.h"
|
||||
#include "subsystem.h"
|
||||
#include "transport.h"
|
||||
#include "spdk/conf.h"
|
||||
#include "spdk/log.h"
|
||||
|
||||
#define MAX_LISTEN_ADDRESSES 255
|
||||
#define MAX_HOSTS 255
|
||||
|
||||
#define PORTNUMSTRLEN 32
|
||||
|
||||
static int
|
||||
@ -181,145 +182,6 @@ spdk_nvmf_parse_addr(char *listen_addr, char **host, char **port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_nvmf_parse_port(struct spdk_conf_section *sp)
|
||||
{
|
||||
struct spdk_nvmf_port *port;
|
||||
struct spdk_nvmf_fabric_intf *fabric_intf;
|
||||
char *transport_name, *listen_addr, *host, *listen_port;
|
||||
int i = 0, rc = 0;
|
||||
|
||||
/* Create the Subsystem Port */
|
||||
port = spdk_nvmf_port_create(sp->num);
|
||||
if (!port) {
|
||||
SPDK_ERRLOG("Port create failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Loop over the listen addresses and add them to the port */
|
||||
for (i = 0; ; i++) {
|
||||
const struct spdk_nvmf_transport *transport;
|
||||
|
||||
transport_name = spdk_conf_section_get_nmval(sp, "Listen", i, 0);
|
||||
if (transport_name == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
transport = spdk_nvmf_transport_get(transport_name);
|
||||
if (transport == NULL) {
|
||||
SPDK_ERRLOG("Unknown transport type '%s'\n", transport_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
listen_addr = spdk_conf_section_get_nmval(sp, "Listen", i, 1);
|
||||
if (listen_addr == NULL) {
|
||||
SPDK_ERRLOG("Missing address for Listen in Port%d\n", sp->num);
|
||||
break;
|
||||
}
|
||||
rc = spdk_nvmf_parse_addr(listen_addr, &host, &listen_port);
|
||||
if (rc < 0) {
|
||||
continue;
|
||||
}
|
||||
fabric_intf = spdk_nvmf_fabric_intf_create(transport, host, listen_port);
|
||||
if (!fabric_intf) {
|
||||
continue;
|
||||
}
|
||||
|
||||
spdk_nvmf_port_add_fabric_intf(port, fabric_intf);
|
||||
}
|
||||
|
||||
if (TAILQ_EMPTY(&port->head)) {
|
||||
SPDK_ERRLOG("No fabric interface found\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_nvmf_parse_ports(void)
|
||||
{
|
||||
int rc = 0;
|
||||
struct spdk_conf_section *sp;
|
||||
|
||||
sp = spdk_conf_first_section(NULL);
|
||||
while (sp != NULL) {
|
||||
if (spdk_conf_section_match_prefix(sp, "Port")) {
|
||||
rc = spdk_nvmf_parse_port(sp);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sp = spdk_conf_next_section(sp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_nvmf_parse_host(struct spdk_conf_section *sp)
|
||||
{
|
||||
int i;
|
||||
const char *mask;
|
||||
char **netmasks;
|
||||
int num_netmasks;
|
||||
struct spdk_nvmf_host *host;
|
||||
|
||||
|
||||
for (num_netmasks = 0; ; num_netmasks++) {
|
||||
mask = spdk_conf_section_get_nval(sp, "Netmask", num_netmasks);
|
||||
if (mask == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_netmasks == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
netmasks = calloc(num_netmasks, sizeof(char *));
|
||||
if (!netmasks) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_netmasks; i++) {
|
||||
mask = spdk_conf_section_get_nval(sp, "Netmask", i);
|
||||
netmasks[i] = strdup(mask);
|
||||
if (!netmasks[i]) {
|
||||
free(netmasks);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
host = spdk_nvmf_host_create(sp->num, num_netmasks, netmasks);
|
||||
|
||||
if (!host) {
|
||||
free(netmasks);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_nvmf_parse_hosts(void)
|
||||
{
|
||||
int rc = 0;
|
||||
struct spdk_conf_section *sp;
|
||||
|
||||
sp = spdk_conf_first_section(NULL);
|
||||
while (sp != NULL) {
|
||||
if (spdk_conf_section_match_prefix(sp, "Host")) {
|
||||
rc = spdk_nvmf_parse_host(sp);
|
||||
if (rc < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sp = spdk_conf_next_section(sp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_nvmf_parse_nvme(void)
|
||||
{
|
||||
@ -450,8 +312,6 @@ spdk_nvmf_parse_subsystem(struct spdk_conf_section *sp)
|
||||
{
|
||||
const char *val, *nqn;
|
||||
struct spdk_nvmf_subsystem *subsystem;
|
||||
const char *port_name, *host_name;
|
||||
int port_id, host_id;
|
||||
struct spdk_nvmf_ctrlr *nvmf_ctrlr;
|
||||
int i, ret;
|
||||
uint64_t mask;
|
||||
@ -467,8 +327,6 @@ spdk_nvmf_parse_subsystem(struct spdk_conf_section *sp)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Determine which core to assign to the subsystem using round robin */
|
||||
mask = spdk_app_get_core_mask();
|
||||
lcore = 0;
|
||||
@ -483,50 +341,44 @@ spdk_nvmf_parse_subsystem(struct spdk_conf_section *sp)
|
||||
return -1;
|
||||
}
|
||||
|
||||
val = spdk_conf_section_get_val(sp, "Mapping");
|
||||
if (val == NULL) {
|
||||
SPDK_ERRLOG("No Mapping entry in Subsystem %d\n", sp->num);
|
||||
nvmf_delete_subsystem(subsystem);
|
||||
return -1;
|
||||
}
|
||||
/* Parse Listen sections */
|
||||
for (i = 0; i < MAX_LISTEN_ADDRESSES; i++) {
|
||||
char *transport_name, *listen_addr;
|
||||
char *traddr, *trsvc;
|
||||
const struct spdk_nvmf_transport *transport;
|
||||
|
||||
for (i = 0; i < MAX_PER_SUBSYSTEM_ACCESS_MAP; i++) {
|
||||
val = spdk_conf_section_get_nmval(sp, "Mapping", i, 0);
|
||||
if (val == NULL) {
|
||||
transport_name = spdk_conf_section_get_nmval(sp, "Listen", i, 0);
|
||||
listen_addr = spdk_conf_section_get_nmval(sp, "Listen", i, 1);
|
||||
|
||||
if (!transport_name || !listen_addr) {
|
||||
break;
|
||||
}
|
||||
|
||||
port_name = spdk_conf_section_get_nmval(sp, "Mapping", i, 0);
|
||||
host_name = spdk_conf_section_get_nmval(sp, "Mapping", i, 1);
|
||||
if (port_name == NULL || host_name == NULL) {
|
||||
nvmf_delete_subsystem(subsystem);
|
||||
return -1;
|
||||
}
|
||||
if (strncasecmp(port_name, "Port",
|
||||
strlen("Port")) != 0
|
||||
|| sscanf(port_name, "%*[^0-9]%d", &port_id) != 1) {
|
||||
SPDK_ERRLOG("Invalid mapping for Subsystem %d\n", sp->num);
|
||||
nvmf_delete_subsystem(subsystem);
|
||||
return -1;
|
||||
}
|
||||
if (strncasecmp(host_name, "Host",
|
||||
strlen("Host")) != 0
|
||||
|| sscanf(host_name, "%*[^0-9]%d", &host_id) != 1) {
|
||||
SPDK_ERRLOG("Invalid mapping for Subsystem %d\n", sp->num);
|
||||
nvmf_delete_subsystem(subsystem);
|
||||
return -1;
|
||||
}
|
||||
if (port_id < 1 || host_id < 1) {
|
||||
SPDK_ERRLOG("Invalid mapping for Subsystem %d\n", sp->num);
|
||||
nvmf_delete_subsystem(subsystem);
|
||||
return -1;
|
||||
transport = spdk_nvmf_transport_get(transport_name);
|
||||
if (transport == NULL) {
|
||||
SPDK_ERRLOG("Unknown transport type '%s'\n", transport_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = spdk_nvmf_subsystem_add_map(subsystem, port_id, host_id);
|
||||
ret = spdk_nvmf_parse_addr(listen_addr, &traddr, &trsvc);
|
||||
if (ret < 0) {
|
||||
nvmf_delete_subsystem(subsystem);
|
||||
return -1;
|
||||
SPDK_ERRLOG("Unable to parse transport address '%s'\n", listen_addr);
|
||||
continue;
|
||||
}
|
||||
|
||||
spdk_nvmf_subsystem_add_listener(subsystem, transport, traddr, trsvc);
|
||||
}
|
||||
|
||||
/* Parse Host sections */
|
||||
for (i = 0; i < MAX_HOSTS; i++) {
|
||||
char *host_nqn;
|
||||
|
||||
host_nqn = spdk_conf_section_get_nval(sp, "Host", i);
|
||||
if (!host_nqn) {
|
||||
break;
|
||||
}
|
||||
|
||||
spdk_nvmf_subsystem_add_host(subsystem, host_nqn);
|
||||
}
|
||||
|
||||
val = spdk_conf_section_get_val(sp, "Controller");
|
||||
@ -587,18 +439,6 @@ spdk_nvmf_parse_conf(void)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Port sections */
|
||||
rc = spdk_nvmf_parse_ports();
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Host sections */
|
||||
rc = spdk_nvmf_parse_hosts();
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* NVMe sections */
|
||||
rc = spdk_nvmf_parse_nvme();
|
||||
if (rc < 0) {
|
||||
|
301
lib/nvmf/host.c
301
lib/nvmf/host.c
@ -1,301 +0,0 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "host.h"
|
||||
#include "nvmf_internal.h"
|
||||
#include "subsystem.h"
|
||||
#include "spdk/log.h"
|
||||
#include "spdk/trace.h"
|
||||
|
||||
#define MAX_MASKBUF 128
|
||||
#define MAX_INITIATOR 8
|
||||
#define MAX_INITIATOR_GROUP 32
|
||||
|
||||
#define MAX_ADDRBUF 64
|
||||
#define MAX_INITIATOR_ADDR (MAX_ADDRBUF)
|
||||
#define MAX_INITIATOR_NAME 256
|
||||
#define MAX_NETMASK 256
|
||||
|
||||
static TAILQ_HEAD(, spdk_nvmf_host) g_host_head = TAILQ_HEAD_INITIALIZER(g_host_head);
|
||||
|
||||
struct spdk_nvmf_host *
|
||||
spdk_nvmf_host_create(int tag,
|
||||
int num_netmasks,
|
||||
char **netmasks)
|
||||
{
|
||||
int i;
|
||||
struct spdk_nvmf_host *host = NULL;
|
||||
|
||||
/* Make sure there are no duplicate initiator group tags */
|
||||
if (spdk_nvmf_host_find_by_tag(tag)) {
|
||||
SPDK_ERRLOG("Initiator group creation failed due to duplicate initiator group tag (%d)\n",
|
||||
tag);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (num_netmasks > MAX_NETMASK) {
|
||||
SPDK_ERRLOG("%d > MAX_NETMASK\n", num_netmasks);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG,
|
||||
"add initiator group (from initiator list) tag=%d, #masks=%d\n",
|
||||
tag, num_netmasks);
|
||||
|
||||
host = calloc(1, sizeof(*host));
|
||||
if (!host) {
|
||||
SPDK_ERRLOG("Unable to allocate host (%d)\n", tag);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
host->tag = tag;
|
||||
|
||||
host->nnetmasks = num_netmasks;
|
||||
host->netmasks = netmasks;
|
||||
for (i = 0; i < num_netmasks; i++) {
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Netmask %s\n", host->netmasks[i]);
|
||||
}
|
||||
|
||||
host->state = GROUP_INIT;
|
||||
|
||||
pthread_mutex_lock(&g_nvmf_tgt.mutex);
|
||||
host->state = GROUP_READY;
|
||||
TAILQ_INSERT_TAIL(&g_host_head, host, tailq);
|
||||
pthread_mutex_unlock(&g_nvmf_tgt.mutex);
|
||||
|
||||
return host;
|
||||
}
|
||||
|
||||
static void
|
||||
nvmf_initiator_group_destroy(struct spdk_nvmf_host *host)
|
||||
{
|
||||
#if 0 // TODO: fix bogus scan-build warning about use-after-free
|
||||
int i;
|
||||
|
||||
if (!host) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < host->nnetmasks; i++) {
|
||||
free(host->netmasks[i]);
|
||||
}
|
||||
|
||||
free(host->netmasks);
|
||||
free(host);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
spdk_nvmf_allow_ipv6(const char *netmask, const char *addr)
|
||||
{
|
||||
struct in6_addr in6_mask;
|
||||
struct in6_addr in6_addr;
|
||||
char mask[MAX_MASKBUF];
|
||||
const char *p;
|
||||
size_t n;
|
||||
int bits, bmask;
|
||||
int i;
|
||||
|
||||
if (netmask[0] != '[')
|
||||
return 0;
|
||||
p = strchr(netmask, ']');
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
n = p - (netmask + 1);
|
||||
if (n + 1 > sizeof mask)
|
||||
return 0;
|
||||
|
||||
memcpy(mask, netmask + 1, n);
|
||||
mask[n] = '\0';
|
||||
p++;
|
||||
|
||||
if (p[0] == '/') {
|
||||
bits = (int) strtol(p + 1, NULL, 10);
|
||||
if (bits < 0 || bits > 128)
|
||||
return 0;
|
||||
} else {
|
||||
bits = 128;
|
||||
}
|
||||
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "input %s\n", addr);
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "mask %s / %d\n", mask, bits);
|
||||
|
||||
/* presentation to network order binary */
|
||||
if (inet_pton(AF_INET6, mask, &in6_mask) <= 0
|
||||
|| inet_pton(AF_INET6, addr, &in6_addr) <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check 128bits */
|
||||
for (i = 0; i < (bits / 8); i++) {
|
||||
if (in6_mask.s6_addr[i] != in6_addr.s6_addr[i])
|
||||
return 0;
|
||||
}
|
||||
if (bits % 8 && i < (MAX_MASKBUF / 8)) {
|
||||
bmask = (0xffU << (8 - (bits % 8))) & 0xffU;
|
||||
if ((in6_mask.s6_addr[i] & bmask) != (in6_addr.s6_addr[i] & bmask))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* match */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_nvmf_allow_ipv4(const char *netmask, const char *addr)
|
||||
{
|
||||
struct in_addr in4_mask;
|
||||
struct in_addr in4_addr;
|
||||
char mask[MAX_MASKBUF];
|
||||
const char *p;
|
||||
uint32_t bmask;
|
||||
size_t n;
|
||||
int bits;
|
||||
|
||||
p = strchr(netmask, '/');
|
||||
if (p == NULL) {
|
||||
p = netmask + strlen(netmask);
|
||||
}
|
||||
n = p - netmask;
|
||||
if (n + 1 > sizeof mask)
|
||||
return 0;
|
||||
|
||||
memcpy(mask, netmask, n);
|
||||
mask[n] = '\0';
|
||||
|
||||
if (p[0] == '/') {
|
||||
bits = (int) strtol(p + 1, NULL, 10);
|
||||
if (bits < 0 || bits > 32)
|
||||
return 0;
|
||||
} else {
|
||||
bits = 32;
|
||||
}
|
||||
|
||||
/* presentation to network order binary */
|
||||
if (inet_pton(AF_INET, mask, &in4_mask) <= 0
|
||||
|| inet_pton(AF_INET, addr, &in4_addr) <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check 32bits */
|
||||
bmask = (0xffffffffULL << (32 - bits)) & 0xffffffffU;
|
||||
if ((ntohl(in4_mask.s_addr) & bmask) != (ntohl(in4_addr.s_addr) & bmask))
|
||||
return 0;
|
||||
|
||||
/* match */
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
spdk_nvmf_allow_netmask(const char *netmask, const char *addr)
|
||||
{
|
||||
if (netmask == NULL || addr == NULL)
|
||||
return 0;
|
||||
if (strcasecmp(netmask, "ALL") == 0)
|
||||
return 1;
|
||||
if (netmask[0] == '[') {
|
||||
/* IPv6 */
|
||||
if (spdk_nvmf_allow_ipv6(netmask, addr))
|
||||
return 1;
|
||||
} else {
|
||||
/* IPv4 */
|
||||
if (spdk_nvmf_allow_ipv4(netmask, addr))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct spdk_nvmf_host *
|
||||
spdk_nvmf_host_find_by_addr(char *addr)
|
||||
{
|
||||
struct spdk_nvmf_host *host;
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
if (addr == NULL)
|
||||
return NULL;
|
||||
|
||||
TAILQ_FOREACH(host, &g_host_head, tailq) {
|
||||
/* check netmask of each group looking for permission */
|
||||
for (i = 0; i < host->nnetmasks; i++) {
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "netmask=%s, addr=%s\n",
|
||||
host->netmasks[i], addr);
|
||||
rc = spdk_nvmf_allow_netmask(host->netmasks[i], addr);
|
||||
if (rc > 0) {
|
||||
/* OK netmask */
|
||||
return host;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "No initiator group addr match for %s\n",
|
||||
addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct spdk_nvmf_host *
|
||||
spdk_nvmf_host_find_by_tag(int tag)
|
||||
{
|
||||
struct spdk_nvmf_host *host;
|
||||
|
||||
TAILQ_FOREACH(host, &g_host_head, tailq) {
|
||||
if (host->tag == tag) {
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, " found initiator group with tag: host %p\n", host);
|
||||
return host;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_nvmf_host_destroy_all(void)
|
||||
{
|
||||
struct spdk_nvmf_host *host;
|
||||
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Enter\n");
|
||||
pthread_mutex_lock(&g_nvmf_tgt.mutex);
|
||||
while (!TAILQ_EMPTY(&g_host_head)) {
|
||||
host = TAILQ_FIRST(&g_host_head);
|
||||
host->state = GROUP_DESTROY;
|
||||
TAILQ_REMOVE(&g_host_head, host, tailq);
|
||||
nvmf_initiator_group_destroy(host);
|
||||
}
|
||||
pthread_mutex_unlock(&g_nvmf_tgt.mutex);
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef NVMF_HOST_H
|
||||
#define NVMF_HOST_H
|
||||
|
||||
#include "spdk/queue.h"
|
||||
#include "port.h" // For enum group_state
|
||||
|
||||
struct spdk_nvmf_host {
|
||||
int nnetmasks;
|
||||
char **netmasks;
|
||||
int ref;
|
||||
int tag;
|
||||
enum group_state state;
|
||||
TAILQ_ENTRY(spdk_nvmf_host) tailq;
|
||||
};
|
||||
|
||||
/* NVMf Initiator Group management API */
|
||||
struct spdk_nvmf_host *
|
||||
spdk_nvmf_host_create(int tag,
|
||||
int num_netmasks,
|
||||
char **netmasks);
|
||||
|
||||
struct spdk_nvmf_host *
|
||||
spdk_nvmf_host_find_by_tag(int tag);
|
||||
|
||||
struct spdk_nvmf_host *
|
||||
spdk_nvmf_host_find_by_addr(char *addr);
|
||||
|
||||
void
|
||||
spdk_nvmf_host_destroy_all(void);
|
||||
|
||||
#endif
|
@ -41,8 +41,6 @@
|
||||
#include "conf.h"
|
||||
#include "conn.h"
|
||||
#include "controller.h"
|
||||
#include "port.h"
|
||||
#include "host.h"
|
||||
#include "subsystem.h"
|
||||
#include "transport.h"
|
||||
#include "spdk/trace.h"
|
||||
@ -185,8 +183,6 @@ nvmf_tgt_subsystem_fini(void)
|
||||
{
|
||||
spdk_shutdown_nvmf_subsystems();
|
||||
spdk_nvmf_shutdown_nvme();
|
||||
spdk_nvmf_host_destroy_all();
|
||||
spdk_nvmf_port_destroy_all();
|
||||
spdk_nvmf_transport_fini();
|
||||
|
||||
pthread_mutex_destroy(&g_nvmf_tgt.mutex);
|
||||
|
205
lib/nvmf/port.c
205
lib/nvmf/port.c
@ -1,205 +0,0 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <rte_config.h>
|
||||
#include <rte_debug.h>
|
||||
|
||||
#include "conn.h"
|
||||
#include "port.h"
|
||||
#include "transport.h"
|
||||
#include "spdk/log.h"
|
||||
#include "spdk/trace.h"
|
||||
#include "spdk/nvmf_spec.h"
|
||||
|
||||
static TAILQ_HEAD(, spdk_nvmf_port) g_port_head = TAILQ_HEAD_INITIALIZER(g_port_head);
|
||||
|
||||
/* Assumes caller allocated host and port strings on the heap */
|
||||
struct spdk_nvmf_fabric_intf *
|
||||
spdk_nvmf_fabric_intf_create(const struct spdk_nvmf_transport *transport, char *host,
|
||||
char *sin_port)
|
||||
{
|
||||
struct spdk_nvmf_fabric_intf *fabric_intf = NULL;
|
||||
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Creating fabric intf: host address %s, port %s\n",
|
||||
host, sin_port);
|
||||
|
||||
RTE_VERIFY(host != NULL);
|
||||
RTE_VERIFY(sin_port != NULL);
|
||||
|
||||
fabric_intf = calloc(1, sizeof(*fabric_intf));
|
||||
if (!fabric_intf) {
|
||||
SPDK_ERRLOG("fabric_intf calloc error\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fabric_intf->host = host;
|
||||
fabric_intf->sin_port = sin_port;
|
||||
fabric_intf->transport = transport;
|
||||
|
||||
return fabric_intf;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_nvmf_fabric_intf_destroy(struct spdk_nvmf_fabric_intf *fabric_intf)
|
||||
{
|
||||
RTE_VERIFY(fabric_intf != NULL);
|
||||
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Enter\n");
|
||||
free(fabric_intf);
|
||||
}
|
||||
|
||||
|
||||
struct spdk_nvmf_fabric_intf *
|
||||
spdk_nvmf_port_find_fabric_intf_by_addr(char *addr)
|
||||
{
|
||||
struct spdk_nvmf_port *port;
|
||||
struct spdk_nvmf_fabric_intf *fabric_intf;
|
||||
|
||||
if (addr == NULL)
|
||||
goto find_error;
|
||||
|
||||
TAILQ_FOREACH(port, &g_port_head, tailq) {
|
||||
TAILQ_FOREACH(fabric_intf, &port->head, tailq) {
|
||||
if (!strncasecmp(fabric_intf->host, addr, strlen(fabric_intf->host))) {
|
||||
return fabric_intf;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
find_error:
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "No device addr match for %s\n", addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct spdk_nvmf_port *
|
||||
spdk_nvmf_port_create(int tag)
|
||||
{
|
||||
struct spdk_nvmf_port *port;
|
||||
|
||||
if (tag <= 0) {
|
||||
SPDK_ERRLOG("invalid port tag (%d)\n", tag);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Make sure there are no duplicate port tags */
|
||||
if (spdk_nvmf_port_find_by_tag(tag)) {
|
||||
SPDK_ERRLOG("port creation failed. duplicate port tag (%d)\n", tag);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
port = calloc(1, sizeof(*port));
|
||||
if (!port) {
|
||||
SPDK_ERRLOG("port calloc error (%d)\n", tag);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
port->state = GROUP_INIT;
|
||||
port->tag = tag;
|
||||
|
||||
TAILQ_INIT(&port->head);
|
||||
|
||||
pthread_mutex_lock(&g_nvmf_tgt.mutex);
|
||||
port->state = GROUP_READY;
|
||||
TAILQ_INSERT_TAIL(&g_port_head, port, tailq);
|
||||
pthread_mutex_unlock(&g_nvmf_tgt.mutex);
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_nvmf_port_destroy(struct spdk_nvmf_port *port)
|
||||
{
|
||||
struct spdk_nvmf_fabric_intf *fabric_intf;
|
||||
|
||||
RTE_VERIFY(port != NULL);
|
||||
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Enter\n");
|
||||
while (!TAILQ_EMPTY(&port->head)) {
|
||||
fabric_intf = TAILQ_FIRST(&port->head);
|
||||
TAILQ_REMOVE(&port->head, fabric_intf, tailq);
|
||||
#if 0 // TODO: fix bogus scan-build warning about use-after-free
|
||||
spdk_nvmf_fabric_intf_destroy(fabric_intf);
|
||||
#endif
|
||||
}
|
||||
|
||||
TAILQ_REMOVE(&g_port_head, port, tailq);
|
||||
|
||||
#if 0 // TODO: fix bogus scan-build warning about use-after-free
|
||||
free(port);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
spdk_nvmf_port_add_fabric_intf(struct spdk_nvmf_port *port,
|
||||
struct spdk_nvmf_fabric_intf *fabric_intf)
|
||||
{
|
||||
RTE_VERIFY(port != NULL);
|
||||
RTE_VERIFY(fabric_intf != NULL);
|
||||
|
||||
fabric_intf->port = port;
|
||||
TAILQ_INSERT_TAIL(&port->head, fabric_intf, tailq);
|
||||
}
|
||||
|
||||
struct spdk_nvmf_port *
|
||||
spdk_nvmf_port_find_by_tag(int tag)
|
||||
{
|
||||
struct spdk_nvmf_port *port;
|
||||
|
||||
if (tag <= 0) {
|
||||
SPDK_ERRLOG("invalid port tag (%d)\n", tag);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(port, &g_port_head, tailq) {
|
||||
if (port->tag == tag) {
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, " found port with tag: port %p\n", port);
|
||||
return port;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
spdk_nvmf_port_destroy_all(void)
|
||||
{
|
||||
struct spdk_nvmf_port *port;
|
||||
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Enter\n");
|
||||
pthread_mutex_lock(&g_nvmf_tgt.mutex);
|
||||
while (!TAILQ_EMPTY(&g_port_head)) {
|
||||
port = TAILQ_FIRST(&g_port_head);
|
||||
spdk_nvmf_port_destroy(port);
|
||||
}
|
||||
pthread_mutex_unlock(&g_nvmf_tgt.mutex);
|
||||
}
|
103
lib/nvmf/port.h
103
lib/nvmf/port.h
@ -1,103 +0,0 @@
|
||||
/*-
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright (c) Intel Corporation.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef NVMF_PORT_H
|
||||
#define NVMF_PORT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "spdk/conf.h"
|
||||
#include "spdk/queue.h"
|
||||
#include "spdk/nvmf_spec.h"
|
||||
|
||||
/** \file
|
||||
* An NVMf subsystem port, referred to as simply "port" is defined by the
|
||||
* specification as follows:
|
||||
*
|
||||
* An NVM subsystem port (port) is a collection of one or more physical fabric
|
||||
* interfaces that together act as a single interface between the NVM subsystem
|
||||
* and a fabric. When link aggregation (e.g., Ethernet) is used, the physical
|
||||
* ports for the group of aggregated links constitute a single NVM subsystem port.
|
||||
*/
|
||||
|
||||
struct spdk_nvmf_transport;
|
||||
|
||||
enum group_state {
|
||||
GROUP_INIT = 0x0,
|
||||
GROUP_READY = 0x1,
|
||||
GROUP_DESTROY = 0x2,
|
||||
};
|
||||
|
||||
struct spdk_nvmf_fabric_intf {
|
||||
char *host;
|
||||
char *sin_port;
|
||||
struct spdk_nvmf_port *port;
|
||||
const struct spdk_nvmf_transport *transport;
|
||||
uint32_t num_sessions;
|
||||
TAILQ_ENTRY(spdk_nvmf_fabric_intf) tailq;
|
||||
};
|
||||
|
||||
struct spdk_nvmf_port {
|
||||
int tag;
|
||||
enum group_state state;
|
||||
TAILQ_HEAD(, spdk_nvmf_fabric_intf) head;
|
||||
TAILQ_ENTRY(spdk_nvmf_port) tailq;
|
||||
};
|
||||
|
||||
struct spdk_nvmf_fabric_intf *
|
||||
spdk_nvmf_fabric_intf_create(const struct spdk_nvmf_transport *transport, char *host,
|
||||
char *sin_port);
|
||||
|
||||
void
|
||||
spdk_nvmf_fabric_intf_destroy(struct spdk_nvmf_fabric_intf *fabric_intf);
|
||||
|
||||
struct spdk_nvmf_fabric_intf *
|
||||
spdk_nvmf_port_find_fabric_intf_by_addr(char *addr);
|
||||
|
||||
struct spdk_nvmf_port *
|
||||
spdk_nvmf_port_create(int tag);
|
||||
|
||||
void
|
||||
spdk_nvmf_port_destroy(struct spdk_nvmf_port *port);
|
||||
|
||||
struct spdk_nvmf_port *
|
||||
spdk_nvmf_port_find_by_tag(int tag);
|
||||
|
||||
void
|
||||
spdk_nvmf_port_add_fabric_intf(struct spdk_nvmf_port *port,
|
||||
struct spdk_nvmf_fabric_intf *fabric_intf);
|
||||
|
||||
void
|
||||
spdk_nvmf_port_destroy_all(void);
|
||||
|
||||
#endif
|
@ -48,8 +48,6 @@
|
||||
|
||||
#include "conn.h"
|
||||
#include "request.h"
|
||||
#include "port.h"
|
||||
#include "host.h"
|
||||
#include "session.h"
|
||||
#include "subsystem.h"
|
||||
#include "transport.h"
|
||||
@ -575,19 +573,15 @@ fail:
|
||||
static int
|
||||
nvmf_rdma_connect(struct rdma_cm_event *event)
|
||||
{
|
||||
struct spdk_nvmf_host *host;
|
||||
struct spdk_nvmf_fabric_intf *fabric_intf;
|
||||
struct rdma_cm_id *conn_id;
|
||||
struct spdk_nvmf_rdma_conn *rdma_conn = NULL;
|
||||
struct spdk_nvmf_conn *conn;
|
||||
struct spdk_nvmf_rdma_request *rdma_req;
|
||||
struct ibv_device_attr ibdev_attr;
|
||||
struct sockaddr_in *addr;
|
||||
struct rdma_conn_param *host_event_data = NULL;
|
||||
struct rdma_conn_param ctrlr_event_data;
|
||||
struct spdk_nvmf_rdma_accept_private_data accept_data;
|
||||
uint16_t sts = 0;
|
||||
char addr_str[INET_ADDRSTRLEN];
|
||||
int rc, qp_depth, rw_depth;
|
||||
|
||||
|
||||
@ -604,30 +598,6 @@ nvmf_rdma_connect(struct rdma_cm_event *event)
|
||||
}
|
||||
SPDK_TRACELOG(SPDK_TRACE_DEBUG, "Connect Recv on fabric intf name %s, dev_name %s\n",
|
||||
conn_id->verbs->device->name, conn_id->verbs->device->dev_name);
|
||||
addr = (struct sockaddr_in *)rdma_get_local_addr(conn_id);
|
||||
inet_ntop(AF_INET, &(addr->sin_addr), addr_str, INET_ADDRSTRLEN);
|
||||
SPDK_TRACELOG(SPDK_TRACE_RDMA, "Connect Route: local addr %s\n",
|
||||
addr_str);
|
||||
|
||||
fabric_intf = spdk_nvmf_port_find_fabric_intf_by_addr(addr_str);
|
||||
if (fabric_intf == NULL) {
|
||||
SPDK_ERRLOG("connect request: rdma device does not exist!\n");
|
||||
goto err1;
|
||||
}
|
||||
SPDK_TRACELOG(SPDK_TRACE_RDMA, "Found existing RDMA Device %p\n", fabric_intf);
|
||||
|
||||
/* validate remote address is within a provisioned initiator group */
|
||||
addr = (struct sockaddr_in *)rdma_get_peer_addr(conn_id);
|
||||
inet_ntop(AF_INET, &(addr->sin_addr), addr_str, INET_ADDRSTRLEN);
|
||||
SPDK_TRACELOG(SPDK_TRACE_RDMA, "Connect Route: peer addr %s\n",
|
||||
addr_str);
|
||||
|
||||
host = spdk_nvmf_host_find_by_addr(addr_str);
|
||||
if (host == NULL) {
|
||||
SPDK_ERRLOG("connect request: remote host addr not provisioned!\n");
|
||||
goto err1;
|
||||
}
|
||||
SPDK_TRACELOG(SPDK_TRACE_RDMA, "Found approved remote host %p\n", host);
|
||||
|
||||
/* Init the NVMf rdma transport connection */
|
||||
rdma_conn = allocate_rdma_conn();
|
||||
@ -1178,15 +1148,15 @@ nvmf_check_rdma_completions(struct spdk_nvmf_conn *conn)
|
||||
}
|
||||
|
||||
static void
|
||||
nvmf_rdma_discover(struct spdk_nvmf_fabric_intf *fabric_intf,
|
||||
nvmf_rdma_discover(struct spdk_nvmf_listen_addr *listen_addr,
|
||||
struct spdk_nvmf_discovery_log_page_entry *entry)
|
||||
{
|
||||
entry->trtype = SPDK_NVMF_TRANS_RDMA;
|
||||
entry->adrfam = SPDK_NVMF_ADDR_FAMILY_IPV4;
|
||||
entry->treq = SPDK_NVMF_TREQ_NOT_SPECIFIED;
|
||||
|
||||
snprintf(entry->trsvcid, sizeof(entry->trsvcid), "%s", fabric_intf->sin_port);
|
||||
snprintf(entry->traddr, sizeof(entry->traddr), "%s", fabric_intf->host);
|
||||
snprintf(entry->trsvcid, sizeof(entry->trsvcid), "%s", listen_addr->trsvc);
|
||||
snprintf(entry->traddr, sizeof(entry->traddr), "%s", listen_addr->traddr);
|
||||
|
||||
entry->tsas.rdma.rdma_qptype = SPDK_NVMF_QP_TYPE_RELIABLE_CONNECTED;
|
||||
entry->tsas.rdma.rdma_prtype = SPDK_NVMF_RDMA_NO_PROVIDER;
|
||||
@ -1206,7 +1176,7 @@ const struct spdk_nvmf_transport spdk_nvmf_transport_rdma = {
|
||||
.conn_fini = nvmf_rdma_conn_cleanup,
|
||||
.conn_poll = nvmf_check_rdma_completions,
|
||||
|
||||
.fabric_intf_discover = nvmf_rdma_discover,
|
||||
.listen_addr_discover = nvmf_rdma_discover,
|
||||
};
|
||||
|
||||
SPDK_LOG_REGISTER_TRACE_FLAG("rdma", SPDK_TRACE_RDMA)
|
||||
|
@ -443,7 +443,7 @@ nvmf_process_connect(struct spdk_nvmf_request *req)
|
||||
}
|
||||
|
||||
/* Look up the requested subsystem */
|
||||
subsystem = nvmf_find_subsystem(data->subnqn);
|
||||
subsystem = nvmf_find_subsystem(data->subnqn, data->hostnqn);
|
||||
if (subsystem == NULL) {
|
||||
SPDK_ERRLOG("Could not find subsystem '%s'\n", data->subnqn);
|
||||
INVALID_CONNECT_DATA(subnqn);
|
||||
|
@ -208,7 +208,7 @@ spdk_nvmf_session_connect(struct spdk_nvmf_conn *conn,
|
||||
SPDK_TRACELOG(SPDK_TRACE_NVMF, " subnqn: \"%s\"\n", data->subnqn);
|
||||
SPDK_TRACELOG(SPDK_TRACE_NVMF, " hostnqn: \"%s\"\n", data->hostnqn);
|
||||
|
||||
subsystem = nvmf_find_subsystem(data->subnqn);
|
||||
subsystem = nvmf_find_subsystem(data->subnqn, data->hostnqn);
|
||||
if (subsystem == NULL) {
|
||||
SPDK_ERRLOG("Could not find subsystem '%s'\n", data->subnqn);
|
||||
INVALID_CONNECT_DATA(subnqn);
|
||||
|
@ -34,8 +34,6 @@
|
||||
#include <ctype.h>
|
||||
|
||||
#include "controller.h"
|
||||
#include "port.h"
|
||||
#include "host.h"
|
||||
#include "nvmf_internal.h"
|
||||
#include "session.h"
|
||||
#include "subsystem.h"
|
||||
@ -48,22 +46,30 @@
|
||||
static TAILQ_HEAD(, spdk_nvmf_subsystem) g_subsystems = TAILQ_HEAD_INITIALIZER(g_subsystems);
|
||||
|
||||
struct spdk_nvmf_subsystem *
|
||||
nvmf_find_subsystem(const char *subnqn)
|
||||
nvmf_find_subsystem(const char *subnqn, const char *hostnqn)
|
||||
{
|
||||
struct spdk_nvmf_subsystem *subs;
|
||||
struct spdk_nvmf_subsystem *subsystem;
|
||||
struct spdk_nvmf_host *host;
|
||||
|
||||
if (subnqn == NULL)
|
||||
if (!subnqn || !hostnqn) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(subs, &g_subsystems, entries) {
|
||||
if (strcasecmp(subnqn, subs->subnqn) == 0) {
|
||||
SPDK_TRACELOG(SPDK_TRACE_NVMF, "found subsystem group with name: %s\n",
|
||||
subnqn);
|
||||
return subs;
|
||||
TAILQ_FOREACH(subsystem, &g_subsystems, entries) {
|
||||
if (strcasecmp(subnqn, subsystem->subnqn) == 0) {
|
||||
if (subsystem->num_hosts == 0) {
|
||||
/* No hosts means any host can connect */
|
||||
return subsystem;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH(host, &subsystem->hosts, link) {
|
||||
if (strcasecmp(hostnqn, host->nqn) == 0) {
|
||||
return subsystem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "can't find subsystem %s\n", subnqn);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -105,6 +111,8 @@ nvmf_create_subsystem(int num, const char *name,
|
||||
subsystem->num = num;
|
||||
subsystem->subtype = sub_type;
|
||||
snprintf(subsystem->subnqn, sizeof(subsystem->subnqn), "%s", name);
|
||||
TAILQ_INIT(&subsystem->listen_addrs);
|
||||
TAILQ_INIT(&subsystem->hosts);
|
||||
|
||||
subsystem->poller.fn = spdk_nvmf_subsystem_poller;
|
||||
subsystem->poller.arg = subsystem;
|
||||
@ -118,7 +126,8 @@ nvmf_create_subsystem(int num, const char *name,
|
||||
int
|
||||
nvmf_delete_subsystem(struct spdk_nvmf_subsystem *subsystem)
|
||||
{
|
||||
int i;
|
||||
struct spdk_nvmf_listen_addr *listen_addr, *listen_addr_tmp;
|
||||
struct spdk_nvmf_host *host, *host_tmp;
|
||||
|
||||
if (subsystem == NULL) {
|
||||
SPDK_TRACELOG(SPDK_TRACE_NVMF,
|
||||
@ -126,8 +135,19 @@ nvmf_delete_subsystem(struct spdk_nvmf_subsystem *subsystem)
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < subsystem->map_count; i++) {
|
||||
subsystem->map[i].host->ref--;
|
||||
TAILQ_FOREACH_SAFE(listen_addr, &subsystem->listen_addrs, link, listen_addr_tmp) {
|
||||
TAILQ_REMOVE(&subsystem->listen_addrs, listen_addr, link);
|
||||
free(listen_addr->traddr);
|
||||
free(listen_addr->trsvc);
|
||||
free(listen_addr);
|
||||
subsystem->num_listen_addrs--;
|
||||
}
|
||||
|
||||
TAILQ_FOREACH_SAFE(host, &subsystem->hosts, link, host_tmp) {
|
||||
TAILQ_REMOVE(&subsystem->hosts, host, link);
|
||||
free(host->nqn);
|
||||
free(host);
|
||||
subsystem->num_hosts--;
|
||||
}
|
||||
|
||||
if (subsystem->session) {
|
||||
@ -140,6 +160,38 @@ nvmf_delete_subsystem(struct spdk_nvmf_subsystem *subsystem)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem,
|
||||
const struct spdk_nvmf_transport *transport,
|
||||
char *traddr, char *trsvc)
|
||||
{
|
||||
struct spdk_nvmf_listen_addr *listen_addr;
|
||||
|
||||
listen_addr = calloc(1, sizeof(*listen_addr));
|
||||
listen_addr->traddr = strdup(traddr);
|
||||
listen_addr->trsvc = strdup(trsvc);
|
||||
listen_addr->transport = transport;
|
||||
|
||||
TAILQ_INSERT_HEAD(&subsystem->listen_addrs, listen_addr, link);
|
||||
subsystem->num_listen_addrs++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_nvmf_subsystem_add_host(struct spdk_nvmf_subsystem *subsystem, char *host_nqn)
|
||||
{
|
||||
struct spdk_nvmf_host *host;
|
||||
|
||||
host = calloc(1, sizeof(*host));
|
||||
host->nqn = strdup(host_nqn);
|
||||
|
||||
TAILQ_INSERT_HEAD(&subsystem->hosts, host, link);
|
||||
subsystem->num_hosts++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem,
|
||||
struct spdk_nvme_ctrlr *ctrlr)
|
||||
@ -156,41 +208,6 @@ nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_nvmf_subsystem_add_map(struct spdk_nvmf_subsystem *subsystem,
|
||||
int port_tag, int host_tag)
|
||||
{
|
||||
struct spdk_nvmf_access_map *map;
|
||||
struct spdk_nvmf_port *port;
|
||||
struct spdk_nvmf_host *host;
|
||||
|
||||
port = spdk_nvmf_port_find_by_tag(port_tag);
|
||||
if (port == NULL) {
|
||||
SPDK_ERRLOG("%s: Port%d not found\n", subsystem->subnqn, port_tag);
|
||||
return -1;
|
||||
}
|
||||
if (port->state != GROUP_READY) {
|
||||
SPDK_ERRLOG("%s: Port%d not active\n", subsystem->subnqn, port_tag);
|
||||
return -1;
|
||||
}
|
||||
host = spdk_nvmf_host_find_by_tag(host_tag);
|
||||
if (host == NULL) {
|
||||
SPDK_ERRLOG("%s: Host%d not found\n", subsystem->subnqn, host_tag);
|
||||
return -1;
|
||||
}
|
||||
if (host->state != GROUP_READY) {
|
||||
SPDK_ERRLOG("%s: Host%d not active\n", subsystem->subnqn, host_tag);
|
||||
return -1;
|
||||
}
|
||||
host->ref++;
|
||||
map = &subsystem->map[subsystem->map_count];
|
||||
map->port = port;
|
||||
map->host = host;
|
||||
subsystem->map_count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spdk_add_nvmf_discovery_subsystem(void)
|
||||
{
|
||||
@ -218,11 +235,9 @@ spdk_add_nvmf_discovery_subsystem(void)
|
||||
void
|
||||
spdk_format_discovery_log(struct spdk_nvmf_discovery_log_page *disc_log, uint32_t length)
|
||||
{
|
||||
int i, numrec = 0;
|
||||
int numrec = 0;
|
||||
struct spdk_nvmf_subsystem *subsystem;
|
||||
struct spdk_nvmf_access_map *map;
|
||||
struct spdk_nvmf_port *port;
|
||||
struct spdk_nvmf_fabric_intf *fabric_intf;
|
||||
struct spdk_nvmf_listen_addr *listen_addr;
|
||||
struct spdk_nvmf_discovery_log_page_entry *entry;
|
||||
|
||||
TAILQ_FOREACH(subsystem, &g_subsystems, entries) {
|
||||
@ -230,29 +245,22 @@ spdk_format_discovery_log(struct spdk_nvmf_discovery_log_page *disc_log, uint32_
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < subsystem->map_count; i++) {
|
||||
map = &subsystem->map[i];
|
||||
port = map->port;
|
||||
if (port != NULL) {
|
||||
TAILQ_FOREACH(fabric_intf, &port->head, tailq) {
|
||||
/* include the discovery log entry */
|
||||
if (length > sizeof(struct spdk_nvmf_discovery_log_page)) {
|
||||
if (sizeof(struct spdk_nvmf_discovery_log_page) + (numrec + 1) * sizeof(
|
||||
struct spdk_nvmf_discovery_log_page_entry) > length) {
|
||||
break;
|
||||
}
|
||||
entry = &disc_log->entries[numrec];
|
||||
entry->portid = port->tag;
|
||||
/* Dynamic controllers */
|
||||
entry->cntlid = 0xffff;
|
||||
entry->subtype = subsystem->subtype;
|
||||
snprintf(entry->subnqn, 256, "%s", subsystem->subnqn);
|
||||
|
||||
fabric_intf->transport->fabric_intf_discover(fabric_intf, entry);
|
||||
}
|
||||
numrec++;
|
||||
TAILQ_FOREACH(listen_addr, &subsystem->listen_addrs, link) {
|
||||
/* include the discovery log entry */
|
||||
if (length > sizeof(struct spdk_nvmf_discovery_log_page)) {
|
||||
if (sizeof(struct spdk_nvmf_discovery_log_page) + (numrec + 1) * sizeof(
|
||||
struct spdk_nvmf_discovery_log_page_entry) > length) {
|
||||
break;
|
||||
}
|
||||
entry = &disc_log->entries[numrec];
|
||||
entry->portid = subsystem->num;
|
||||
entry->cntlid = 0xffff;
|
||||
entry->subtype = subsystem->subtype;
|
||||
snprintf(entry->subnqn, sizeof(entry->subnqn), "%s", subsystem->subnqn);
|
||||
|
||||
listen_addr->transport->listen_addr_discover(listen_addr, entry);
|
||||
}
|
||||
numrec++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,12 +40,18 @@
|
||||
|
||||
struct spdk_nvmf_conn;
|
||||
|
||||
#define MAX_PER_SUBSYSTEM_ACCESS_MAP 2
|
||||
#define MAX_NQN_SIZE 255
|
||||
|
||||
struct spdk_nvmf_access_map {
|
||||
struct spdk_nvmf_port *port;
|
||||
struct spdk_nvmf_host *host;
|
||||
struct spdk_nvmf_listen_addr {
|
||||
char *traddr;
|
||||
char *trsvc; /* TODO: Change to trsvcid */
|
||||
const struct spdk_nvmf_transport *transport;
|
||||
TAILQ_ENTRY(spdk_nvmf_listen_addr) link;
|
||||
};
|
||||
|
||||
struct spdk_nvmf_host {
|
||||
char *nqn;
|
||||
TAILQ_ENTRY(spdk_nvmf_host) link;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -63,8 +69,11 @@ struct spdk_nvmf_subsystem {
|
||||
|
||||
struct spdk_poller poller;
|
||||
|
||||
int map_count;
|
||||
struct spdk_nvmf_access_map map[MAX_PER_SUBSYSTEM_ACCESS_MAP];
|
||||
TAILQ_HEAD(, spdk_nvmf_listen_addr) listen_addrs;
|
||||
uint32_t num_listen_addrs;
|
||||
|
||||
TAILQ_HEAD(, spdk_nvmf_host) hosts;
|
||||
uint32_t num_hosts;
|
||||
|
||||
TAILQ_ENTRY(spdk_nvmf_subsystem) entries;
|
||||
};
|
||||
@ -78,16 +87,21 @@ int
|
||||
nvmf_delete_subsystem(struct spdk_nvmf_subsystem *subsystem);
|
||||
|
||||
struct spdk_nvmf_subsystem *
|
||||
nvmf_find_subsystem(const char *subnqn);
|
||||
nvmf_find_subsystem(const char *subnqn, const char *hostnqn);
|
||||
|
||||
int
|
||||
spdk_nvmf_subsystem_add_listener(struct spdk_nvmf_subsystem *subsystem,
|
||||
const struct spdk_nvmf_transport *transport,
|
||||
char *traddr, char *trsvc);
|
||||
|
||||
int
|
||||
spdk_nvmf_subsystem_add_host(struct spdk_nvmf_subsystem *subsystem,
|
||||
char *host_nqn);
|
||||
|
||||
int
|
||||
nvmf_subsystem_add_ctrlr(struct spdk_nvmf_subsystem *subsystem,
|
||||
struct spdk_nvme_ctrlr *ctrlr);
|
||||
|
||||
int
|
||||
spdk_nvmf_subsystem_add_map(struct spdk_nvmf_subsystem *subsystem,
|
||||
int port_tag, int host_tag);
|
||||
|
||||
int
|
||||
spdk_shutdown_nvmf_subsystems(void);
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
struct spdk_nvmf_conn;
|
||||
struct spdk_nvmf_discovery_log_page_entry;
|
||||
struct spdk_nvmf_fabric_intf;
|
||||
struct spdk_nvmf_listen_addr;
|
||||
struct spdk_nvmf_request;
|
||||
|
||||
struct spdk_nvmf_transport {
|
||||
@ -86,9 +86,9 @@ struct spdk_nvmf_transport {
|
||||
int (*conn_poll)(struct spdk_nvmf_conn *conn);
|
||||
|
||||
/**
|
||||
* Fill out a discovery log entry for a specific fabric interface.
|
||||
* Fill out a discovery log entry for a specific listen address.
|
||||
*/
|
||||
void (*fabric_intf_discover)(struct spdk_nvmf_fabric_intf *fabric_intf,
|
||||
void (*listen_addr_discover)(struct spdk_nvmf_listen_addr *listen_addr,
|
||||
struct spdk_nvmf_discovery_log_page_entry *entry);
|
||||
};
|
||||
|
||||
|
@ -5,19 +5,12 @@
|
||||
[Nvmf]
|
||||
MaxConnectionsPerSession 4
|
||||
|
||||
[Port1]
|
||||
Comment "Test1"
|
||||
Listen RDMA 192.168.100.8:4420
|
||||
|
||||
[Host1]
|
||||
Netmask 192.168.100.0/24
|
||||
|
||||
[Nvme]
|
||||
ClaimAllDevices Yes
|
||||
UnbindFromKernel Yes
|
||||
|
||||
[Subsystem1]
|
||||
NQN "nqn.2016-06.io.spdk:cnode1"
|
||||
Mapping Port1 Host1
|
||||
Listen RDMA 192.168.100.8:4420
|
||||
QueueDepth 128
|
||||
Controller Nvme0
|
||||
|
Loading…
Reference in New Issue
Block a user