aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorChuck Lever <cel@netapp.com>2006-05-25 01:40:49 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-06-09 09:34:05 -0400
commitb85d88068444ae5dcb1639bcef770ccbf085dd4e (patch)
treebcce3ef7e2f66465b09dc485fb1a280c111b2e31 /net/sunrpc
parent73a3d07c1082145a3b78407bb5252df290470c4c (diff)
SUNRPC: select privileged port numbers at random
Make the RPC client select privileged ephemeral source ports at random. This improves DRC behavior on the server by using the same port when reconnecting for the same mount point, but using a different port for fresh mounts. The Linux TCP implementation already does this for nonprivileged ports. Note that TCP sockets in TIME_WAIT will prevent quick reuse of a random ephemeral port number by leaving the port INUSE until the connection transitions out of TIME_WAIT. Test plan: Connectathon against every known server implementation using multiple mount points. Locking especially. Signed-off-by: Chuck Lever <cel@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/xprtsock.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 4b4e7dfdff14..21006b109101 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -930,6 +930,13 @@ static void xs_udp_timer(struct rpc_task *task)
930 xprt_adjust_cwnd(task, -ETIMEDOUT); 930 xprt_adjust_cwnd(task, -ETIMEDOUT);
931} 931}
932 932
933static unsigned short xs_get_random_port(void)
934{
935 unsigned short range = xprt_max_resvport - xprt_min_resvport;
936 unsigned short rand = (unsigned short) net_random() % range;
937 return rand + xprt_min_resvport;
938}
939
933/** 940/**
934 * xs_set_port - reset the port number in the remote endpoint address 941 * xs_set_port - reset the port number in the remote endpoint address
935 * @xprt: generic transport 942 * @xprt: generic transport
@@ -1275,7 +1282,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to)
1275 memset(xprt->slot, 0, slot_table_size); 1282 memset(xprt->slot, 0, slot_table_size);
1276 1283
1277 xprt->prot = IPPROTO_UDP; 1284 xprt->prot = IPPROTO_UDP;
1278 xprt->port = xprt_max_resvport; 1285 xprt->port = xs_get_random_port();
1279 xprt->tsh_size = 0; 1286 xprt->tsh_size = 0;
1280 xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0; 1287 xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
1281 /* XXX: header size can vary due to auth type, IPv6, etc. */ 1288 /* XXX: header size can vary due to auth type, IPv6, etc. */
@@ -1317,7 +1324,7 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to)
1317 memset(xprt->slot, 0, slot_table_size); 1324 memset(xprt->slot, 0, slot_table_size);
1318 1325
1319 xprt->prot = IPPROTO_TCP; 1326 xprt->prot = IPPROTO_TCP;
1320 xprt->port = xprt_max_resvport; 1327 xprt->port = xs_get_random_port();
1321 xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); 1328 xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32);
1322 xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0; 1329 xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
1323 xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; 1330 xprt->max_payload = RPC_MAX_FRAGMENT_SIZE;