Commit 5d7220e8 authored by Tetsuo Handa's avatar Tetsuo Handa Committed by Roland Dreier

RDMA/cma: Randomize local port allocation

Randomize local port allocation in the way sctp_get_port_local() does.
Update rover at the end of loop since we're likely to pick a valid port
on the first try.
Signed-off-by: default avatarTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Reviewed-by: default avatarSean Hefty <sean.hefty@intel.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 0eddb519
...@@ -79,7 +79,6 @@ static DEFINE_IDR(sdp_ps); ...@@ -79,7 +79,6 @@ static DEFINE_IDR(sdp_ps);
static DEFINE_IDR(tcp_ps); static DEFINE_IDR(tcp_ps);
static DEFINE_IDR(udp_ps); static DEFINE_IDR(udp_ps);
static DEFINE_IDR(ipoib_ps); static DEFINE_IDR(ipoib_ps);
static int next_port;
struct cma_device { struct cma_device {
struct list_head list; struct list_head list;
...@@ -1970,47 +1969,33 @@ static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv, ...@@ -1970,47 +1969,33 @@ static int cma_alloc_port(struct idr *ps, struct rdma_id_private *id_priv,
static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv) static int cma_alloc_any_port(struct idr *ps, struct rdma_id_private *id_priv)
{ {
struct rdma_bind_list *bind_list; static unsigned int last_used_port;
int port, ret, low, high; int low, high, remaining;
unsigned int rover;
bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
if (!bind_list)
return -ENOMEM;
retry:
/* FIXME: add proper port randomization per like inet_csk_get_port */
do {
ret = idr_get_new_above(ps, bind_list, next_port, &port);
} while ((ret == -EAGAIN) && idr_pre_get(ps, GFP_KERNEL));
if (ret)
goto err1;
inet_get_local_port_range(&low, &high); inet_get_local_port_range(&low, &high);
if (port > high) { remaining = (high - low) + 1;
if (next_port != low) { rover = net_random() % remaining + low;
idr_remove(ps, port); retry:
next_port = low; if (last_used_port != rover &&
goto retry; !idr_find(ps, (unsigned short) rover)) {
} int ret = cma_alloc_port(ps, id_priv, rover);
ret = -EADDRNOTAVAIL; /*
goto err2; * Remember previously used port number in order to avoid
* re-using same port immediately after it is closed.
*/
if (!ret)
last_used_port = rover;
if (ret != -EADDRNOTAVAIL)
return ret;
} }
if (--remaining) {
if (port == high) rover++;
next_port = low; if ((rover < low) || (rover > high))
else rover = low;
next_port = port + 1; goto retry;
}
bind_list->ps = ps; return -EADDRNOTAVAIL;
bind_list->port = (unsigned short) port;
cma_bind_port(bind_list, id_priv);
return 0;
err2:
idr_remove(ps, port);
err1:
kfree(bind_list);
return ret;
} }
static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv) static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv)
...@@ -2995,12 +2980,7 @@ static void cma_remove_one(struct ib_device *device) ...@@ -2995,12 +2980,7 @@ static void cma_remove_one(struct ib_device *device)
static int __init cma_init(void) static int __init cma_init(void)
{ {
int ret, low, high, remaining; int ret;
get_random_bytes(&next_port, sizeof next_port);
inet_get_local_port_range(&low, &high);
remaining = (high - low) + 1;
next_port = ((unsigned int) next_port % remaining) + low;
cma_wq = create_singlethread_workqueue("rdma_cm"); cma_wq = create_singlethread_workqueue("rdma_cm");
if (!cma_wq) if (!cma_wq)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment