[openib-general] [PATCH] [CM] match received msgs against local and remote ID
Sean Hefty
mshefty at ichips.intel.com
Tue Feb 15 11:27:37 PST 2005
This patch matches received messages against local and remote IDs (versus
local ID only). It relocates a structure definition, and fixes a race
receiving a duplicate REQ.
These changes will be needed as part of timewait handling.
Signed-off-by: Sean Hefty <sean.hefty at intel.com>
Index: infiniband/core/cm.c
===================================================================
--- infiniband/core/cm.c (revision 1796)
+++ infiniband/core/cm.c (working copy)
@@ -95,6 +95,17 @@ struct cm_av {
u16 pkey_index;
};
+struct cm_work {
+ struct work_struct work;
+ struct list_head list;
+ struct cm_port *port;
+ struct ib_mad_recv_wc *mad_recv_wc; /* Received MADs */
+ u32 local_id; /* Established */
+ u32 remote_id;
+ struct ib_cm_event cm_event;
+ struct ib_sa_path_rec path[0];
+};
+
struct cm_id_private {
struct ib_cm_id id;
@@ -130,16 +141,6 @@ struct cm_id_private {
atomic_t work_count;
};
-struct cm_work {
- struct work_struct work;
- struct list_head list;
- struct cm_port *port;
- struct ib_mad_recv_wc *mad_recv_wc; /* Received MADs */
- u32 local_id; /* Established */
- struct ib_cm_event cm_event;
- struct ib_sa_path_rec path[0];
-};
-
static inline void cm_deref_id(struct cm_id_private *cm_id_priv)
{
if (atomic_dec_and_test(&cm_id_priv->refcount))
@@ -298,15 +299,19 @@ static void cm_free_id(u32 local_id)
spin_unlock_irqrestore(&cm.lock, flags);
}
-static struct cm_id_private * cm_acquire_id_by_local_id(u32 local_id)
+static struct cm_id_private * cm_acquire_id(u32 local_id, u32 remote_id)
{
struct cm_id_private *cm_id_priv;
unsigned long flags;
spin_lock_irqsave(&cm.lock, flags);
cm_id_priv = idr_find(&cm.local_id_table, (int) local_id);
- if (cm_id_priv)
- atomic_inc(&cm_id_priv->refcount);
+ if (cm_id_priv) {
+ if (cm_id_priv->id.remote_id == remote_id)
+ atomic_inc(&cm_id_priv->refcount);
+ else
+ cm_id_priv = NULL;
+ }
spin_unlock_irqrestore(&cm.lock, flags);
return cm_id_priv;
@@ -384,6 +389,8 @@ static struct cm_id_private * cm_insert_
return NULL;
}
+/*
+ * Call will be needed when implementing REJ handling.
static struct cm_id_private * cm_find_id_by_remote_id(u64 remote_ca_guid,
u32 remote_id)
{
@@ -405,6 +412,7 @@ static struct cm_id_private * cm_find_id
}
return NULL;
}
+*/
static void cm_remove_remote_id(struct cm_id_private *cm_id_priv)
{
@@ -1009,21 +1017,13 @@ out:
static int cm_req_handler(struct cm_work *work)
{
struct ib_cm_id *cm_id;
- struct cm_id_private *cm_id_priv, *listen_cm_id_priv;
+ struct cm_id_private *cm_id_priv, *listen_cm_id_priv, *cur_cm_id_priv;
struct cm_req_msg *req_msg;
unsigned long flags;
int ret;
req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
- /* Check for duplicate REQ. */
- spin_lock_irqsave(&cm.lock, flags);
- cm_id_priv = cm_find_id_by_remote_id(req_msg->local_ca_guid,
- req_msg->local_comm_id);
- spin_unlock_irqrestore(&cm.lock, flags);
- if (cm_id_priv)
- return -EINVAL;
-
/* Check for peer-to-peer connection. */
ret = cm_peer_req_handler(work);
if (ret != -ENOENT)
@@ -1038,20 +1038,26 @@ static int cm_req_handler(struct cm_work
cm_id_priv->id.remote_id = req_msg->local_comm_id;
cm_id_priv->passive = 1;
- /* Find matching listen request. */
spin_lock_irqsave(&cm.lock, flags);
+ /* Check for duplicate REQ. */
+ cur_cm_id_priv = cm_insert_remote_id(cm_id_priv);
+ if (cur_cm_id_priv) {
+ spin_unlock_irqrestore(&cm.lock, flags);
+ ret = -EINVAL;
+ goto error1;
+ }
+ /* Find matching listen request. */
listen_cm_id_priv = cm_find_listen(req_msg->service_id);
if (!listen_cm_id_priv) {
spin_unlock_irqrestore(&cm.lock, flags);
/* todo: reject with no match */
ret = -EINVAL;
- goto out;
+ goto error2;
}
atomic_inc(&listen_cm_id_priv->refcount);
atomic_inc(&cm_id_priv->refcount);
cm_id_priv->id.state = IB_CM_REQ_RCVD;
atomic_inc(&cm_id_priv->work_count);
- cm_insert_remote_id(cm_id_priv);
spin_unlock_irqrestore(&cm.lock, flags);
cm_id_priv->id.cm_handler = listen_cm_id_priv->id.cm_handler;
@@ -1063,12 +1069,12 @@ static int cm_req_handler(struct cm_work
ret = cm_init_av(work->port->mad_agent->device, &work->path[0],
&cm_id_priv->av);
if (ret)
- goto bad_req;
+ goto error3;
if (req_msg->alt_local_lid) {
ret = cm_init_av(work->port->mad_agent->device, &work->path[1],
&cm_id_priv->alt_av);
if (ret)
- goto bad_req;
+ goto error3;
}
cm_id_priv->timeout_ms = cm_convert_to_ms(
cm_req_get_local_resp_timeout(req_msg));
@@ -1087,9 +1093,11 @@ static int cm_req_handler(struct cm_work
cm_process_work(cm_id_priv, work);
cm_deref_id(listen_cm_id_priv);
return 0;
-bad_req:
+error3:
cm_deref_id(listen_cm_id_priv);
-out:
+error2:
+ cm_remove_remote_id(cm_id_priv);
+error1:
ib_destroy_cm_id(&cm_id_priv->id);
return ret;
}
@@ -1287,7 +1295,7 @@ static int cm_rep_handler(struct cm_work
int ret;
rep_msg = (struct cm_rep_msg *)work->mad_recv_wc->recv_buf.mad;
- cm_id_priv = cm_acquire_id_by_local_id(rep_msg->remote_comm_id);
+ cm_id_priv = cm_acquire_id(rep_msg->remote_comm_id, 0);
if (!cm_id_priv)
return -EINVAL;
@@ -1349,7 +1357,7 @@ static int cm_establish_handler(struct c
int ret;
/* See comment in ib_cm_establish about lookup. */
- cm_id_priv = cm_acquire_id_by_local_id(work->local_id);
+ cm_id_priv = cm_acquire_id(work->local_id, work->remote_id);
if (!cm_id_priv)
return -EINVAL;
@@ -1385,7 +1393,8 @@ static int cm_rtu_handler(struct cm_work
int ret;
rtu_msg = (struct cm_rtu_msg *)work->mad_recv_wc->recv_buf.mad;
- cm_id_priv = cm_acquire_id_by_local_id(rtu_msg->remote_comm_id);
+ cm_id_priv = cm_acquire_id(rtu_msg->remote_comm_id,
+ rtu_msg->local_comm_id);
if (!cm_id_priv)
return -EINVAL;
@@ -1560,7 +1569,8 @@ static int cm_dreq_handler(struct cm_wor
int ret;
dreq_msg = (struct cm_dreq_msg *)work->mad_recv_wc->recv_buf.mad;
- cm_id_priv = cm_acquire_id_by_local_id(dreq_msg->remote_comm_id);
+ cm_id_priv = cm_acquire_id(dreq_msg->remote_comm_id,
+ dreq_msg->local_comm_id);
if (!cm_id_priv)
return -EINVAL;
@@ -1610,7 +1620,8 @@ static int cm_drep_handler(struct cm_wor
int ret;
drep_msg = (struct cm_drep_msg *)work->mad_recv_wc->recv_buf.mad;
- cm_id_priv = cm_acquire_id_by_local_id(drep_msg->remote_comm_id);
+ cm_id_priv = cm_acquire_id(drep_msg->remote_comm_id,
+ drep_msg->local_comm_id);
if (!cm_id_priv)
return -EINVAL;
@@ -1961,7 +1972,8 @@ static int cm_lap_handler(struct cm_work
/* todo: verify LAP request and send reject APR if invalid. */
lap_msg = (struct cm_lap_msg *)work->mad_recv_wc->recv_buf.mad;
- cm_id_priv = cm_acquire_id_by_local_id(lap_msg->remote_comm_id);
+ cm_id_priv = cm_acquire_id(lap_msg->remote_comm_id,
+ lap_msg->local_comm_id);
if (!cm_id_priv)
return -EINVAL;
@@ -2071,7 +2083,8 @@ static int cm_apr_handler(struct cm_work
int ret;
apr_msg = (struct cm_apr_msg *)work->mad_recv_wc->recv_buf.mad;
- cm_id_priv = cm_acquire_id_by_local_id(apr_msg->remote_comm_id);
+ cm_id_priv = cm_acquire_id(apr_msg->remote_comm_id,
+ apr_msg->local_comm_id);
if (!cm_id_priv)
return -EINVAL; /* Unmatched reply. */
@@ -2343,7 +2356,7 @@ static int cm_sidr_rep_handler(struct cm
sidr_rep_msg = (struct cm_sidr_rep_msg *)
work->mad_recv_wc->recv_buf.mad;
- cm_id_priv = cm_acquire_id_by_local_id(sidr_rep_msg->request_id);
+ cm_id_priv = cm_acquire_id(sidr_rep_msg->request_id, 0);
if (!cm_id_priv)
return -EINVAL; /* Unmatched reply. */
@@ -2553,6 +2566,7 @@ int ib_cm_establish(struct ib_cm_id *cm_
*/
INIT_WORK(&work->work, cm_work_handler, work);
work->local_id = cm_id->local_id;
+ work->remote_id = cm_id->remote_id;
work->cm_event.event = IB_CM_USER_ESTABLISHED;
queue_work(cm.wq, &work->work);
out:
More information about the general
mailing list