All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dan Aloni <dan@kernelim.com>
To: linux-nfs@vger.kernel.org
Cc: Trond Myklebust <trond.myklebust@hammerspace.com>,
	Anna Schumaker <anna.schumaker@netapp.com>
Subject: [PATCH v1 1/5] sunrpc: Allow specifying a vector of IP addresses for nconnect
Date: Thu, 21 Jan 2021 21:10:16 +0200	[thread overview]
Message-ID: <20210121191020.3144948-2-dan@kernelim.com> (raw)
In-Reply-To: <20210121191020.3144948-1-dan@kernelim.com>

This adds an `rpc_portgroup` structure to describe a group of IP
addresses comprising one logical server with multiple ports. The remote
endpoint can be in a single server exposing multiple network interfaces,
or multiple remote machines implementing a distributed server architecture.

Combined with nconnect, the multiple transports try to make use of the
multiple addresses given so that the connections are spread across the
ports.

Signed-off-by: Dan Aloni <dan@kernelim.com>
---
 include/linux/sunrpc/clnt.h |  9 +++++++
 net/sunrpc/clnt.c           | 47 +++++++++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 02e7a5863d28..f8c0c33281a8 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -115,12 +115,21 @@ struct rpc_procinfo {
 	const char *		p_name;		/* name of procedure */
 };
 
+#define RPC_MAX_PORTS 64
+
+struct rpc_portgroup {
+	int nr;
+	struct sockaddr_storage addrs[RPC_MAX_PORTS];
+};
+
 struct rpc_create_args {
 	struct net		*net;
 	int			protocol;
 	struct sockaddr		*address;
 	size_t			addrsize;
 	struct sockaddr		*saddress;
+	struct rpc_portgroup    *localports;    /* additional local addresses */
+	struct rpc_portgroup    *remoteports;   /* additional remote addresses */
 	const struct rpc_timeout *timeout;
 	const char		*servername;
 	const char		*nodename;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 612f0a641f4c..5f335a873f03 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -500,6 +500,44 @@ static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
 	return clnt;
 }
 
+struct rpc_clnt_portgroup_iter {
+	struct rpc_portgroup *pg;
+	int idx;
+};
+
+static void take_iter_portgroup_addr(struct rpc_clnt_portgroup_iter *iter,
+				struct sockaddr	**address)
+{
+	struct rpc_portgroup *pg = iter->pg;
+	struct sockaddr	*existing = *address;
+	struct sockaddr	*new;
+
+	if (!pg || pg->nr == 0)
+		return;
+	if (iter->idx >= pg->nr)
+		iter->idx = 0;
+
+	/* Take port from existing address, or use autobind (0) */
+	new = (struct sockaddr *)&pg->addrs[iter->idx++];
+
+	switch (new->sa_family) {
+	case AF_INET:
+		((struct sockaddr_in *)new)->sin_port =
+			existing ? ((struct sockaddr_in *)existing)->sin_port
+			         : 0;
+		break;
+	case AF_INET6:
+		((struct sockaddr_in6 *)new)->sin6_port =
+			existing ? ((struct sockaddr_in6 *)existing)->sin6_port
+			         : 0;
+		break;
+	default:
+		return;
+	}
+
+	*address = new;
+}
+
 /**
  * rpc_create - create an RPC client and transport with one call
  * @args: rpc_clnt create argument structure
@@ -522,6 +560,8 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
 		.servername = args->servername,
 		.bc_xprt = args->bc_xprt,
 	};
+	struct rpc_clnt_portgroup_iter iter_localports = { .pg = args->localports };
+	struct rpc_clnt_portgroup_iter iter_remoteports = { .pg = args->remoteports };
 	char servername[48];
 	struct rpc_clnt *clnt;
 	int i;
@@ -573,6 +613,10 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
 		xprtargs.servername = servername;
 	}
 
+	/* If localports or remoteports are specified, first entry overrides */
+	take_iter_portgroup_addr(&iter_localports, &xprtargs.srcaddr);
+	take_iter_portgroup_addr(&iter_remoteports, &xprtargs.dstaddr);
+
 	xprt = xprt_create_transport(&xprtargs);
 	if (IS_ERR(xprt))
 		return (struct rpc_clnt *)xprt;
@@ -595,6 +639,9 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
 		return clnt;
 
 	for (i = 0; i < args->nconnect - 1; i++) {
+		take_iter_portgroup_addr(&iter_localports, &xprtargs.srcaddr);
+		take_iter_portgroup_addr(&iter_remoteports, &xprtargs.dstaddr);
+
 		if (rpc_clnt_add_xprt(clnt, &xprtargs, NULL, NULL) < 0)
 			break;
 	}
-- 
2.26.2


  reply	other threads:[~2021-01-21 19:11 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-01-21 19:10 [PATCH v1 0/5] NFSv3 client RDMA multipath enhancements Dan Aloni
2021-01-21 19:10 ` Dan Aloni [this message]
2021-01-21 19:10 ` [PATCH v1 2/5] xprtrdma: Bind to a local address if requested Dan Aloni
2021-01-21 19:10 ` [PATCH v1 3/5] nfs: Extend nconnect with remoteports and localports mount params Dan Aloni
2021-01-21 19:10 ` [PATCH v1 4/5] sunrpc: Add srcaddr to xprt sysfs debug Dan Aloni
2021-01-21 19:10 ` [PATCH v1 5/5] nfs: Increase NFS_MAX_CONNECTIONS Dan Aloni
2021-01-21 19:50 ` [PATCH v1 0/5] NFSv3 client RDMA multipath enhancements Chuck Lever
2021-01-24 17:37   ` Dan Aloni

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210121191020.3144948-2-dan@kernelim.com \
    --to=dan@kernelim.com \
    --cc=anna.schumaker@netapp.com \
    --cc=linux-nfs@vger.kernel.org \
    --cc=trond.myklebust@hammerspace.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.