Thread (23 messages) 23 messages, 6 authors, 2021-05-12

Re: [PATCH 1/1] Add 'Transport Interface' (triface) option. This can be used to specify the IP interface to use for the connection. The driver uses that to set SO_BINDTODEVICE on the socket before connecting.

From: Hannes Reinecke <hare@suse.de>
Date: 2021-05-01 11:34:53

On 4/15/21 9:28 PM, Martin Belanger wrote:
From: Martin Belanger <redacted>
Please fix up the subject and description.
quoted hunk ↗ jump to hunk
---
  drivers/nvme/host/core.c    |  5 +++++
  drivers/nvme/host/fabrics.c | 14 +++++++++++++
  drivers/nvme/host/fabrics.h |  6 +++++-
  drivers/nvme/host/tcp.c     | 41 ++++++++++++++++++++++++++++++++++---
  4 files changed, 62 insertions(+), 4 deletions(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 288ac47ff5b4..91ae11a1ae26 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -3961,6 +3961,11 @@ static int nvme_class_uevent(struct device *dev, struct kobj_uevent_env *env)
  
  		ret = add_uevent_var(env, "NVME_HOST_TRADDR=%s",
  				opts->host_traddr ?: "none");
+		if (ret)
+			return ret;
+
+		ret = add_uevent_var(env, "NVME_HOST_TRIFACE=%s",
+				opts->host_triface ?: "none");
  	}
  	return ret;
  }
Why not simply 'host_iface' ? 'triface' is a bit awkward.
quoted hunk ↗ jump to hunk
diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
index 604ab0e5a2ad..f5d0d760b53b 100644
--- a/drivers/nvme/host/fabrics.c
+++ b/drivers/nvme/host/fabrics.c
@@ -112,6 +112,9 @@ int nvmf_get_address(struct nvme_ctrl *ctrl, char *buf, int size)
  	if (ctrl->opts->mask & NVMF_OPT_HOST_TRADDR)
  		len += scnprintf(buf + len, size - len, "%shost_traddr=%s",
  				(len) ? "," : "", ctrl->opts->host_traddr);
+	if (ctrl->opts->mask & NVMF_OPT_HOST_TRIFACE)
+		len += scnprintf(buf + len, size - len, "%shost_triface=%s",
+				(len) ? "," : "", ctrl->opts->host_triface);
  	len += scnprintf(buf + len, size - len, "\n");
  
  	return len;
@@ -604,6 +607,7 @@ static const match_table_t opt_tokens = {
  	{ NVMF_OPT_KATO,		"keep_alive_tmo=%d"	},
  	{ NVMF_OPT_HOSTNQN,		"hostnqn=%s"		},
  	{ NVMF_OPT_HOST_TRADDR,		"host_traddr=%s"	},
+	{ NVMF_OPT_HOST_TRIFACE,	"host_triface=%s"	},
  	{ NVMF_OPT_HOST_ID,		"hostid=%s"		},
  	{ NVMF_OPT_DUP_CONNECT,		"duplicate_connect"	},
  	{ NVMF_OPT_DISABLE_SQFLOW,	"disable_sqflow"	},
@@ -813,6 +817,15 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
  			kfree(opts->host_traddr);
  			opts->host_traddr = p;
  			break;
+		case NVMF_OPT_HOST_TRIFACE:
+			p = match_strdup(args);
+			if (!p) {
+				ret = -ENOMEM;
+				goto out;
+			}
+			kfree(opts->host_triface);
+			opts->host_triface = p;
+			break;
  		case NVMF_OPT_HOST_ID:
  			p = match_strdup(args);
  			if (!p) {
@@ -997,6 +1010,7 @@ void nvmf_free_options(struct nvmf_ctrl_options *opts)
  	kfree(opts->trsvcid);
  	kfree(opts->subsysnqn);
  	kfree(opts->host_traddr);
+	kfree(opts->host_triface);
  	kfree(opts);
  }
  EXPORT_SYMBOL_GPL(nvmf_free_options);
diff --git a/drivers/nvme/host/fabrics.h b/drivers/nvme/host/fabrics.h
index 733010d2eafd..17c64ff4db8c 100644
--- a/drivers/nvme/host/fabrics.h
+++ b/drivers/nvme/host/fabrics.h
@@ -59,6 +59,7 @@ enum {
  	NVMF_OPT_NR_POLL_QUEUES = 1 << 18,
  	NVMF_OPT_TOS		= 1 << 19,
  	NVMF_OPT_FAIL_FAST_TMO	= 1 << 20,
+	NVMF_OPT_HOST_TRIFACE	= 1 << 21,
  };
  
  /**
@@ -76,7 +77,9 @@ enum {
   * @trsvcid:	The transport-specific TRSVCID field for a port on the
   *              subsystem which is adding a controller.
   * @host_traddr: A transport-specific field identifying the NVME host port
- *              to use for the connection to the controller.
+ *		to use for the connection to the controller.
+ * @host_triface: A transport-specific field identifying the NVME host
+ *		interface to use for the connection to the controller.
   * @queue_size: Number of IO queue elements.
   * @nr_io_queues: Number of controller IO queues that will be established.
   * @reconnect_delay: Time between two consecutive reconnect attempts.
@@ -101,6 +104,7 @@ struct nvmf_ctrl_options {
  	char			*traddr;
  	char			*trsvcid;
  	char			*host_traddr;
+	char			*host_triface;
  	size_t			queue_size;
  	unsigned int		nr_io_queues;
  	unsigned int		reconnect_delay;
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index 8e55d8bc0c50..28eb7f88b487 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -1447,6 +1447,20 @@ static int nvme_tcp_alloc_queue(struct nvme_ctrl *nctrl,
  		}
  	}
  
+	if (nctrl->opts->mask & NVMF_OPT_HOST_TRIFACE) {
+		char *iface = nctrl->opts->host_triface;
+		sockptr_t optval = KERNEL_SOCKPTR(iface);
+
+		ret = sock_setsockopt(queue->sock, SOL_SOCKET, SO_BINDTODEVICE,
+				      optval, strlen(iface));
+		if (ret) {
+			dev_err(nctrl->device,
+			  "failed to bind to interface %s queue %d err %d\n",
+			  iface, qid, ret);
+			goto err_sock;
+		}
+	}
+
  	queue->hdr_digest = nctrl->opts->hdr_digest;
  	queue->data_digest = nctrl->opts->data_digest;
  	if (queue->hdr_digest || queue->data_digest) {
Is this valid for all transports? I guess it would only work for 'tcp', 
and maybe 'rdma' if one would be running ROCE.
Shouldn't we error out on other transports like 'fc' or 'loop'?
quoted hunk ↗ jump to hunk
@@ -2457,6 +2471,10 @@ nvme_tcp_existing_controller(struct nvmf_ctrl_options *opts)
  static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev,
  		struct nvmf_ctrl_options *opts)
  {
+	const char *iface_key = "";
+	const char *iface_val = "";
+	const char *srce_key  = "";
+	const char *srce_val  = "";
  	struct nvme_tcp_ctrl *ctrl;
  	int ret;
  
@@ -2502,6 +2520,22 @@ static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev,
  			       opts->host_traddr);
  			goto out_free_ctrl;
  		}
+		srce_key = ", src-addr ";
+		srce_val = opts->host_traddr;
+	}
+
+	if (opts->mask & NVMF_OPT_HOST_TRIFACE) {
+		struct net_device *ndev;
+
+		ndev = dev_get_by_name(&init_net, opts->host_triface);
+		if (!ndev) {
+			pr_err("invalid interface passed: %s\n",
+			       opts->host_triface);
+			ret = -ENODEV;
+			goto out_free_ctrl;
+		}
+		iface_key = ", iface ";
+		iface_val = opts->host_triface;
  	}
  
  	if (!opts->duplicate_connect && nvme_tcp_existing_controller(opts)) {
Normally the options are just parts of the 'address' string; why didn't 
you use that approach here?
quoted hunk ↗ jump to hunk
@@ -2530,8 +2564,9 @@ static struct nvme_ctrl *nvme_tcp_create_ctrl(struct device *dev,
  	if (ret)
  		goto out_uninit_ctrl;
  
-	dev_info(ctrl->ctrl.device, "new ctrl: NQN \"%s\", addr %pISp\n",
-		ctrl->ctrl.opts->subsysnqn, &ctrl->addr);
+	dev_info(ctrl->ctrl.device, "new ctrl: NQN \"%s\", addr %pISp%s%s%s%s\n",
+		 ctrl->ctrl.opts->subsysnqn, &ctrl->addr,
+		 srce_key, srce_val, iface_key, iface_val);
  
  	mutex_lock(&nvme_tcp_ctrl_mutex);
  	list_add_tail(&ctrl->list, &nvme_tcp_ctrl_list);
@@ -2560,7 +2595,7 @@ static struct nvmf_transport_ops nvme_tcp_transport = {
  			  NVMF_OPT_HOST_TRADDR | NVMF_OPT_CTRL_LOSS_TMO |
  			  NVMF_OPT_HDR_DIGEST | NVMF_OPT_DATA_DIGEST |
  			  NVMF_OPT_NR_WRITE_QUEUES | NVMF_OPT_NR_POLL_QUEUES |
-			  NVMF_OPT_TOS,
+			  NVMF_OPT_TOS | NVMF_OPT_HOST_TRIFACE,
  	.create_ctrl	= nvme_tcp_create_ctrl,
  };
  
Cheers,

Hannes
-- 
Dr. Hannes Reinecke                Kernel Storage Architect
hare@suse.de                              +49 911 74053 688
SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg
HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer

_______________________________________________
Linux-nvme mailing list
Linux-nvme@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-nvme
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help