Skip to content

Commit

Permalink
[PATCH] RPC: allow RPC client's port range to be adjustable
Browse files Browse the repository at this point in the history
 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>
  • Loading branch information
Chuck Lever authored and Trond Myklebust committed Sep 23, 2005
1 parent 555ee3a commit 529b33c
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 18 deletions.
2 changes: 2 additions & 0 deletions include/linux/sunrpc/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ enum {
CTL_NLMDEBUG,
CTL_SLOTTABLE_UDP,
CTL_SLOTTABLE_TCP,
CTL_MIN_RESVPORT,
CTL_MAX_RESVPORT,
};

#endif /* _LINUX_SUNRPC_DEBUG_H_ */
17 changes: 14 additions & 3 deletions include/linux/sunrpc/xprt.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ extern unsigned int xprt_tcp_slot_table_entries;
#define RPC_CALLHDRSIZE 6
#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
*/
Expand All @@ -62,6 +73,9 @@ struct rpc_timeout {
unsigned char to_exponential;
};

struct rpc_task;
struct rpc_xprt;

/*
* This describes a complete RPC request
*/
Expand Down Expand Up @@ -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);
Expand Down
29 changes: 29 additions & 0 deletions net/sunrpc/sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,16 @@ proc_dodebug(ctl_table *table, int write, struct file *file,

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[] = {
{
Expand Down Expand Up @@ -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 }
};

Expand Down
23 changes: 8 additions & 15 deletions net/sunrpc/xprtsock.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@
#include <net/udp.h>
#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.
Expand Down Expand Up @@ -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,
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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. */
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 529b33c

Please sign in to comment.