[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