[PATCH] RPC: allow RPC client's port range to be adjustable
authorChuck Lever <cel@netapp.com>
Thu, 25 Aug 2005 23:25:54 +0000 (16:25 -0700)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 23 Sep 2005 16:38:50 +0000 (12:38 -0400)
 Select an RPC client source port between 650 and 1023 instead of between
 1 and 800.  The old range conflicts with a number of network services.
 Provide sysctls to allow admins to select a different port range.

 Note that this doesn't affect user-level RPC library behavior, which
 still uses 1 to 800.

 Based on a suggestion by Olaf Kirch <okir@suse.de>.

 Test-plan:
 Repeated mount and unmount.  Destructive testing.  Idle timeouts.

Signed-off-by: Chuck Lever <cel@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
include/linux/sunrpc/debug.h
include/linux/sunrpc/xprt.h
net/sunrpc/sysctl.c
net/sunrpc/xprtsock.c

index 42d2997..1a42d90 100644 (file)
@@ -95,6 +95,8 @@ enum {
        CTL_NLMDEBUG,
        CTL_SLOTTABLE_UDP,
        CTL_SLOTTABLE_TCP,
+       CTL_MIN_RESVPORT,
+       CTL_MAX_RESVPORT,
 };
 
 #endif /* _LINUX_SUNRPC_DEBUG_H_ */
index dcf0326..9d9266c 100644 (file)
@@ -52,6 +52,17 @@ extern unsigned int xprt_tcp_slot_table_entries;
 #define RPC_REPHDRSIZE         4
 
 /*
+ * Parameters for choosing a free port
+ */
+extern unsigned int xprt_min_resvport;
+extern unsigned int xprt_max_resvport;
+
+#define RPC_MIN_RESVPORT       (1U)
+#define RPC_MAX_RESVPORT       (65535U)
+#define RPC_DEF_MIN_RESVPORT   (650U)
+#define RPC_DEF_MAX_RESVPORT   (1023U)
+
+/*
  * This describes a timeout strategy
  */
 struct rpc_timeout {
@@ -62,6 +73,9 @@ struct rpc_timeout {
        unsigned char           to_exponential;
 };
 
+struct rpc_task;
+struct rpc_xprt;
+
 /*
  * This describes a complete RPC request
  */
@@ -107,9 +121,6 @@ struct rpc_rqst {
 #define rq_svec                        rq_snd_buf.head
 #define rq_slen                        rq_snd_buf.len
 
-struct rpc_task;
-struct rpc_xprt;
-
 struct rpc_xprt_ops {
        void            (*set_buffer_size)(struct rpc_xprt *xprt);
        int             (*reserve_xprt)(struct rpc_task *task);
index ef48326..d0c9f46 100644 (file)
@@ -121,9 +121,16 @@ done:
 
 unsigned int xprt_udp_slot_table_entries = RPC_DEF_SLOT_TABLE;
 unsigned int xprt_tcp_slot_table_entries = RPC_DEF_SLOT_TABLE;
+unsigned int xprt_min_resvport = RPC_DEF_MIN_RESVPORT;
+EXPORT_SYMBOL(xprt_min_resvport);
+unsigned int xprt_max_resvport = RPC_DEF_MAX_RESVPORT;
+EXPORT_SYMBOL(xprt_max_resvport);
+
 
 static unsigned int min_slot_table_size = RPC_MIN_SLOT_TABLE;
 static unsigned int max_slot_table_size = RPC_MAX_SLOT_TABLE;
+static unsigned int xprt_min_resvport_limit = RPC_MIN_RESVPORT;
+static unsigned int xprt_max_resvport_limit = RPC_MAX_RESVPORT;
 
 static ctl_table debug_table[] = {
        {
@@ -180,6 +187,28 @@ static ctl_table debug_table[] = {
                .extra1         = &min_slot_table_size,
                .extra2         = &max_slot_table_size
        },
+       {
+               .ctl_name       = CTL_MIN_RESVPORT,
+               .procname       = "min_resvport",
+               .data           = &xprt_min_resvport,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &xprt_min_resvport_limit,
+               .extra2         = &xprt_max_resvport_limit
+       },
+       {
+               .ctl_name       = CTL_MAX_RESVPORT,
+               .procname       = "max_resvport",
+               .data           = &xprt_max_resvport,
+               .maxlen         = sizeof(unsigned int),
+               .mode           = 0644,
+               .proc_handler   = &proc_dointvec_minmax,
+               .strategy       = &sysctl_intvec,
+               .extra1         = &xprt_min_resvport_limit,
+               .extra2         = &xprt_max_resvport_limit
+       },
        { .ctl_name = 0 }
 };
 
index 26402c0..62c2e7c 100644 (file)
 #include <net/tcp.h>
 
 /*
- * Maximum port number to use when requesting a reserved port.
- */
-#define XS_MAX_RESVPORT                (800U)
-
-/*
  * How many times to try sending a request on a socket before waiting
  * for the socket buffer to clear.
  */
@@ -873,10 +868,9 @@ static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
        struct sockaddr_in myaddr = {
                .sin_family = AF_INET,
        };
-       int err, port;
+       int err;
+       unsigned short port = xprt->port;
 
-       /* Were we already bound to a given port? Try to reuse it */
-       port = xprt->port;
        do {
                myaddr.sin_port = htons(port);
                err = sock->ops->bind(sock, (struct sockaddr *) &myaddr,
@@ -887,8 +881,10 @@ static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock)
                                        port);
                        return 0;
                }
-               if (--port == 0)
-                       port = XS_MAX_RESVPORT;
+               if (port <= xprt_min_resvport)
+                       port = xprt_max_resvport;
+               else
+                       port--;
        } while (err == -EADDRINUSE && port != xprt->port);
 
        dprintk("RPC:      can't bind to reserved port (%d).\n", -err);
@@ -1075,9 +1071,6 @@ static struct rpc_xprt_ops xs_tcp_ops = {
        .destroy                = xs_destroy,
 };
 
-extern unsigned int xprt_udp_slot_table_entries;
-extern unsigned int xprt_tcp_slot_table_entries;
-
 /**
  * xs_setup_udp - Set up transport to use a UDP socket
  * @xprt: transport to set up
@@ -1098,7 +1091,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
        memset(xprt->slot, 0, slot_table_size);
 
        xprt->prot = IPPROTO_UDP;
-       xprt->port = XS_MAX_RESVPORT;
+       xprt->port = xprt_max_resvport;
        xprt->tsh_size = 0;
        xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
        /* XXX: header size can vary due to auth type, IPv6, etc. */
@@ -1136,7 +1129,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
        memset(xprt->slot, 0, slot_table_size);
 
        xprt->prot = IPPROTO_TCP;
-       xprt->port = XS_MAX_RESVPORT;
+       xprt->port = xprt_max_resvport;
        xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
        xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
        xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;