[PATCH 2/2] iser: add portals support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This adds IPv6 support for iser.

Signed-off-by: Roi Dayan <roid@xxxxxxxxxxxx>
---
 usr/iscsi/iser.c |  110 ++++++++++++++++++++++++++++++++++++++++++------------
 usr/iscsi/iser.h |    8 ++++
 2 files changed, 94 insertions(+), 24 deletions(-)

diff --git a/usr/iscsi/iser.c b/usr/iscsi/iser.c
index 35c6faa..ace8da3 100644
--- a/usr/iscsi/iser.c
+++ b/usr/iscsi/iser.c
@@ -51,7 +51,8 @@ static struct iscsi_transport iscsi_iser;
 
 /* global, across all devices */
 static struct rdma_event_channel *rdma_evt_channel;
-static struct rdma_cm_id *cma_listen_id;
+
+LIST_HEAD(iser_portals_list);
 
 /* accepted at RDMA layer, but not yet established */
 static LIST_HEAD(temp_conn);
@@ -3338,19 +3339,31 @@ static void iser_device_release(struct iser_device *dev)
 		eprintf("ibv_dealloc_pd failed: (errno=%d %m)\n", errno);
 }
 
-/*
- * Init entire iscsi transport.  Begin listening for connections.
- */
-static int iser_ib_init(void)
+static int iser_add_portal(struct addrinfo *res, short int port)
 {
 	int err;
-	struct sockaddr_in sock_addr;
-	short int port = iser_listen_port;
+	int afonly = 1;
+	struct sockaddr_storage sock_addr;
+	struct rdma_cm_id *cma_listen_id;
+	struct iser_portal *portal = NULL;
 
-	rdma_evt_channel = rdma_create_event_channel();
-	if (!rdma_evt_channel) {
-		eprintf("Failed to initialize RDMA; load kernel modules?\n");
-		return -1;
+	portal = zalloc(sizeof(struct iser_portal));
+	if (!portal) {
+	    eprintf("zalloc failed.\n");
+	    return -1;
+	}
+	portal->af = res->ai_family;
+	portal->port = port;
+
+	memset(&sock_addr, 0, sizeof(sock_addr));
+	if (res->ai_family == AF_INET6) {
+		((struct sockaddr_in6 *) &sock_addr)->sin6_family = AF_INET6;
+		((struct sockaddr_in6 *) &sock_addr)->sin6_port = htons(port);
+		((struct sockaddr_in6 *) &sock_addr)->sin6_addr = in6addr_any;
+	} else {
+		((struct sockaddr_in *) &sock_addr)->sin_family = AF_INET;
+		((struct sockaddr_in *) &sock_addr)->sin_port = htons(port);
+		((struct sockaddr_in *) &sock_addr)->sin_addr.s_addr = INADDR_ANY;
 	}
 
 	err = rdma_create_id(rdma_evt_channel, &cma_listen_id, NULL,
@@ -3359,11 +3372,11 @@ static int iser_ib_init(void)
 		eprintf("rdma_create_id failed, %m\n");
 		return -1;
 	}
+	portal->cma_listen_id = cma_listen_id;
+
+	rdma_set_option(cma_listen_id, RDMA_OPTION_ID,
+			RDMA_OPTION_ID_AFONLY, &afonly, sizeof(afonly));
 
-	memset(&sock_addr, 0, sizeof(sock_addr));
-	sock_addr.sin_family = AF_INET;
-	sock_addr.sin_port = htons(port);
-	sock_addr.sin_addr.s_addr = INADDR_ANY;
 	err =
 	    rdma_bind_addr(cma_listen_id, (struct sockaddr *) &sock_addr);
 	if (err) {
@@ -3384,8 +3397,47 @@ static int iser_ib_init(void)
 		return -1;
 	}
 
+        list_add(&portal->iser_portal_siblings, &iser_portals_list);
+	return err;
+}
+
+/*
+ * Init entire iscsi transport.  Begin listening for connections.
+ */
+static int iser_ib_init(void)
+{
+	int err;
+	short int port = iser_listen_port;
+	struct addrinfo hints, *res, *res0;
+	char servname[64];
+
+	rdma_evt_channel = rdma_create_event_channel();
+	if (!rdma_evt_channel) {
+		eprintf("Failed to initialize RDMA; load kernel modules?\n");
+		return -1;
+	}
+
+	memset(servname, 0, sizeof(servname));
+	snprintf(servname, sizeof(servname), "%d", port);
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_flags = AI_PASSIVE;
+
+	err = getaddrinfo(NULL, servname, &hints, &res0);
+	if (err) {
+		eprintf("unable to get address info, %m\n");
+		return -errno;
+	}
+
+	for (res = res0; res; res = res->ai_next) {
+		err = iser_add_portal(res, port);
+		if (err)
+		    return err;
+	}
+
 	dprintf("listening for iser connections on port %d\n", port);
-	err = tgt_event_add(cma_listen_id->channel->fd, EPOLLIN,
+	err = tgt_event_add(rdma_evt_channel->fd, EPOLLIN,
 			    iser_handle_rdmacm, NULL);
 	if (err)
 		return err;
@@ -3393,9 +3445,23 @@ static int iser_ib_init(void)
 	return err;
 }
 
-static void iser_ib_release(void)
+void iser_delete_portals(void)
 {
 	int err;
+	struct iser_portal *portal, *ptmp;
+
+	list_for_each_entry_safe(portal, ptmp, &iser_portals_list,
+				 iser_portal_siblings) {
+		err = rdma_destroy_id(portal->cma_listen_id);
+		if (err)
+			eprintf("rdma_destroy_id failed: (errno=%d %m)\n", errno);
+		list_del(&portal->iser_portal_siblings);
+		free(portal);
+	}
+}
+
+static void iser_ib_release(void)
+{
 	struct iser_device *dev, *tdev;
 
 	assert(list_empty(&iser_conn_list));
@@ -3405,13 +3471,9 @@ static void iser_ib_release(void)
 		free(dev);
 	}
 
-	if (cma_listen_id) {
-		tgt_event_del(cma_listen_id->channel->fd);
-
-		err = rdma_destroy_id(cma_listen_id);
-		if (err)
-			eprintf("rdma_destroy_id failed: (errno=%d %m)\n", errno);
-
+	if (!list_empty(&iser_portals_list)) {
+		tgt_event_del(rdma_evt_channel->fd);
+		iser_delete_portals();
 		rdma_destroy_event_channel(rdma_evt_channel);
 	}
 }
diff --git a/usr/iscsi/iser.h b/usr/iscsi/iser.h
index 48d0a8c..5f1fb69 100644
--- a/usr/iscsi/iser.h
+++ b/usr/iscsi/iser.h
@@ -30,6 +30,14 @@
 
 extern short control_port;
 
+struct iser_portal {
+	struct list_head iser_portal_siblings;
+	int port;
+	int af;
+	struct rdma_cm_id *cma_listen_id;
+};
+
+
 /*
  * The IB-extended version from the kernel.  Stags and VAs are in
  * big-endian format.
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux SCSI]     [Linux RAID]     [Linux Clusters]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]

  Powered by Linux