Skip to content

Commit

Permalink
RDMA/cma: Randomize local port allocation
Browse files Browse the repository at this point in the history
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: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Reviewed-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
  • Loading branch information
Tetsuo Handa authored and Roland Dreier committed Apr 21, 2010
1 parent 0eddb51 commit 5d7220e
Showing 1 changed file with 25 additions and 45 deletions.
70 changes: 25 additions & 45 deletions drivers/infiniband/core/cma.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ static DEFINE_IDR(sdp_ps);
static DEFINE_IDR(tcp_ps);
static DEFINE_IDR(udp_ps);
static DEFINE_IDR(ipoib_ps);
static int next_port;

struct cma_device {
struct list_head list;
Expand Down Expand Up @@ -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)
{
struct rdma_bind_list *bind_list;
int port, ret, low, high;

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;
static unsigned int last_used_port;
int low, high, remaining;
unsigned int rover;

inet_get_local_port_range(&low, &high);
if (port > high) {
if (next_port != low) {
idr_remove(ps, port);
next_port = low;
goto retry;
}
ret = -EADDRNOTAVAIL;
goto err2;
remaining = (high - low) + 1;
rover = net_random() % remaining + low;
retry:
if (last_used_port != rover &&
!idr_find(ps, (unsigned short) rover)) {
int ret = cma_alloc_port(ps, id_priv, rover);
/*
* 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 (port == high)
next_port = low;
else
next_port = port + 1;

bind_list->ps = ps;
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;
if (--remaining) {
rover++;
if ((rover < low) || (rover > high))
rover = low;
goto retry;
}
return -EADDRNOTAVAIL;
}

static int cma_use_port(struct idr *ps, struct rdma_id_private *id_priv)
Expand Down Expand Up @@ -2995,12 +2980,7 @@ static void cma_remove_one(struct ib_device *device)

static int __init cma_init(void)
{
int ret, low, high, remaining;

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;
int ret;

cma_wq = create_singlethread_workqueue("rdma_cm");
if (!cma_wq)
Expand Down

0 comments on commit 5d7220e

Please sign in to comment.