diff options
author | Sean Hefty <sean.hefty@intel.com> | 2006-08-28 18:15:18 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2006-09-22 18:22:45 -0400 |
commit | f06d26537559113207e4b73af6a22eaa5c5e9dc3 (patch) | |
tree | d5d33db61adc4070a4b4b0d4f903d3223299db7b /drivers | |
parent | 2b3e258e5dd1938e2708eb5354ad8ba056fe8154 (diff) |
IB/cm: Randomize starting comm ID
Randomize the starting local comm ID to avoid getting a rejected
connection due to a stale connection after a system reboot or
reloading of the ib_cm.
Signed-off-by: Sean Hefty <sean.hefty@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/infiniband/core/cm.c | 24 |
1 files changed, 16 insertions, 8 deletions
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 1aad33e03528..c8982b02d9b6 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004, 2005 Intel Corporation. All rights reserved. | 2 | * Copyright (c) 2004-2006 Intel Corporation. All rights reserved. |
3 | * Copyright (c) 2004 Topspin Corporation. All rights reserved. | 3 | * Copyright (c) 2004 Topspin Corporation. All rights reserved. |
4 | * Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved. | 4 | * Copyright (c) 2004, 2005 Voltaire Corporation. All rights reserved. |
5 | * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. | 5 | * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. |
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/idr.h> | 41 | #include <linux/idr.h> |
42 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
43 | #include <linux/pci.h> | 43 | #include <linux/pci.h> |
44 | #include <linux/random.h> | ||
44 | #include <linux/rbtree.h> | 45 | #include <linux/rbtree.h> |
45 | #include <linux/spinlock.h> | 46 | #include <linux/spinlock.h> |
46 | #include <linux/workqueue.h> | 47 | #include <linux/workqueue.h> |
@@ -73,6 +74,7 @@ static struct ib_cm { | |||
73 | struct rb_root remote_id_table; | 74 | struct rb_root remote_id_table; |
74 | struct rb_root remote_sidr_table; | 75 | struct rb_root remote_sidr_table; |
75 | struct idr local_id_table; | 76 | struct idr local_id_table; |
77 | __be32 random_id_operand; | ||
76 | struct workqueue_struct *wq; | 78 | struct workqueue_struct *wq; |
77 | } cm; | 79 | } cm; |
78 | 80 | ||
@@ -299,15 +301,17 @@ static int cm_init_av_by_path(struct ib_sa_path_rec *path, struct cm_av *av) | |||
299 | static int cm_alloc_id(struct cm_id_private *cm_id_priv) | 301 | static int cm_alloc_id(struct cm_id_private *cm_id_priv) |
300 | { | 302 | { |
301 | unsigned long flags; | 303 | unsigned long flags; |
302 | int ret; | 304 | int ret, id; |
303 | static int next_id; | 305 | static int next_id; |
304 | 306 | ||
305 | do { | 307 | do { |
306 | spin_lock_irqsave(&cm.lock, flags); | 308 | spin_lock_irqsave(&cm.lock, flags); |
307 | ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, next_id++, | 309 | ret = idr_get_new_above(&cm.local_id_table, cm_id_priv, |
308 | (__force int *) &cm_id_priv->id.local_id); | 310 | next_id++, &id); |
309 | spin_unlock_irqrestore(&cm.lock, flags); | 311 | spin_unlock_irqrestore(&cm.lock, flags); |
310 | } while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) ); | 312 | } while( (ret == -EAGAIN) && idr_pre_get(&cm.local_id_table, GFP_KERNEL) ); |
313 | |||
314 | cm_id_priv->id.local_id = (__force __be32) (id ^ cm.random_id_operand); | ||
311 | return ret; | 315 | return ret; |
312 | } | 316 | } |
313 | 317 | ||
@@ -316,7 +320,8 @@ static void cm_free_id(__be32 local_id) | |||
316 | unsigned long flags; | 320 | unsigned long flags; |
317 | 321 | ||
318 | spin_lock_irqsave(&cm.lock, flags); | 322 | spin_lock_irqsave(&cm.lock, flags); |
319 | idr_remove(&cm.local_id_table, (__force int) local_id); | 323 | idr_remove(&cm.local_id_table, |
324 | (__force int) (local_id ^ cm.random_id_operand)); | ||
320 | spin_unlock_irqrestore(&cm.lock, flags); | 325 | spin_unlock_irqrestore(&cm.lock, flags); |
321 | } | 326 | } |
322 | 327 | ||
@@ -324,7 +329,8 @@ static struct cm_id_private * cm_get_id(__be32 local_id, __be32 remote_id) | |||
324 | { | 329 | { |
325 | struct cm_id_private *cm_id_priv; | 330 | struct cm_id_private *cm_id_priv; |
326 | 331 | ||
327 | cm_id_priv = idr_find(&cm.local_id_table, (__force int) local_id); | 332 | cm_id_priv = idr_find(&cm.local_id_table, |
333 | (__force int) (local_id ^ cm.random_id_operand)); | ||
328 | if (cm_id_priv) { | 334 | if (cm_id_priv) { |
329 | if (cm_id_priv->id.remote_id == remote_id) | 335 | if (cm_id_priv->id.remote_id == remote_id) |
330 | atomic_inc(&cm_id_priv->refcount); | 336 | atomic_inc(&cm_id_priv->refcount); |
@@ -2082,8 +2088,9 @@ static struct cm_id_private * cm_acquire_rejected_id(struct cm_rej_msg *rej_msg) | |||
2082 | spin_unlock_irqrestore(&cm.lock, flags); | 2088 | spin_unlock_irqrestore(&cm.lock, flags); |
2083 | return NULL; | 2089 | return NULL; |
2084 | } | 2090 | } |
2085 | cm_id_priv = idr_find(&cm.local_id_table, | 2091 | cm_id_priv = idr_find(&cm.local_id_table, (__force int) |
2086 | (__force int) timewait_info->work.local_id); | 2092 | (timewait_info->work.local_id ^ |
2093 | cm.random_id_operand)); | ||
2087 | if (cm_id_priv) { | 2094 | if (cm_id_priv) { |
2088 | if (cm_id_priv->id.remote_id == remote_id) | 2095 | if (cm_id_priv->id.remote_id == remote_id) |
2089 | atomic_inc(&cm_id_priv->refcount); | 2096 | atomic_inc(&cm_id_priv->refcount); |
@@ -3360,6 +3367,7 @@ static int __init ib_cm_init(void) | |||
3360 | cm.remote_qp_table = RB_ROOT; | 3367 | cm.remote_qp_table = RB_ROOT; |
3361 | cm.remote_sidr_table = RB_ROOT; | 3368 | cm.remote_sidr_table = RB_ROOT; |
3362 | idr_init(&cm.local_id_table); | 3369 | idr_init(&cm.local_id_table); |
3370 | get_random_bytes(&cm.random_id_operand, sizeof cm.random_id_operand); | ||
3363 | idr_pre_get(&cm.local_id_table, GFP_KERNEL); | 3371 | idr_pre_get(&cm.local_id_table, GFP_KERNEL); |
3364 | 3372 | ||
3365 | cm.wq = create_workqueue("ib_cm"); | 3373 | cm.wq = create_workqueue("ib_cm"); |