This patch adds testing for a stale connection on the active side of
the connection protocol.  It also fixes a bug where a duplicate REP
would have been dropped, rather than forcing a resend of the RTU.

Signed-off-by: Sean Hefty <[EMAIL PROTECTED]>


Index: infiniband/core/cm.c
===================================================================
--- infiniband/core/cm.c        (revision 1818)
+++ infiniband/core/cm.c        (working copy)
@@ -1302,6 +1302,27 @@ static void cm_format_rep_event(struct c
        work->cm_event.private_data = &rep_msg->private_data;
 }
 
+static void cm_dup_rep_handler(struct cm_rep_msg *rep_msg)
+{
+       struct cm_id_private *cm_id_priv;
+       enum ib_cm_state state;
+       unsigned long flags;
+
+       cm_id_priv = cm_acquire_id(rep_msg->remote_comm_id,
+                                  rep_msg->local_comm_id);
+       if (!cm_id_priv)
+               return;
+
+       spin_lock_irqsave(&cm_id_priv->lock, flags);
+       state = cm_id_priv->id.state;
+       spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+       
+       /* RTU's received in an invalid state will be dropped. */
+       if (state == IB_CM_ESTABLISHED)
+               cm_resend_rtu(cm_id_priv);
+       cm_deref_id(cm_id_priv);
+}
+
 static int cm_rep_handler(struct cm_work *work)
 {
        struct cm_id_private *cm_id_priv;
@@ -1313,8 +1334,10 @@ static int cm_rep_handler(struct cm_work
 
        rep_msg = (struct cm_rep_msg *)work->mad_recv_wc->recv_buf.mad;
        cm_id_priv = cm_acquire_id(rep_msg->remote_comm_id, 0);
-       if (!cm_id_priv)
+       if (!cm_id_priv) {
+               cm_dup_rep_handler(rep_msg);
                return -EINVAL;
+       }
 
        timewait_info = cm_create_timewait_info(cm_id_priv->id.local_id,
                                                rep_msg->local_comm_id,
@@ -1324,6 +1347,22 @@ static int cm_rep_handler(struct cm_work
                ret = PTR_ERR(timewait_info);
                goto error1;
        }
+       spin_lock_irqsave(&cm.lock, flags);
+       /* Check for duplicate REP. */
+       if (cm_insert_remote_id(timewait_info)) {
+               spin_unlock_irqrestore(&cm.lock, flags);
+               ret = -EINVAL;
+               goto error2;
+       }
+       /* Check for a stale connection. */
+       if (cm_insert_remote_qpn(timewait_info)) {
+               spin_unlock_irqrestore(&cm.lock, flags);
+               /* todo: reject as stale */
+               ret = -EINVAL;
+               goto error2;
+       }
+       spin_unlock_irqrestore(&cm.lock, flags);
+
        cm_format_rep_event(work);
 
        spin_lock_irqsave(&cm_id_priv->lock, flags);
@@ -1331,11 +1370,6 @@ static int cm_rep_handler(struct cm_work
        case IB_CM_REQ_SENT:
        case IB_CM_MRA_REQ_RCVD:
                break;
-       case IB_CM_ESTABLISHED:
-               spin_unlock_irqrestore(&cm_id_priv->lock, flags);
-               cm_resend_rtu(cm_id_priv);
-               ret = -EINVAL;
-               goto error2;
        default:
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
                ret = -EINVAL;
@@ -1365,6 +1399,7 @@ static int cm_rep_handler(struct cm_work
                cm_deref_id(cm_id_priv);
        return 0;
 error2:
+       cm_cleanup_timewait(timewait_info);
        kfree(timewait_info);
 error1:
        cm_deref_id(cm_id_priv);
_______________________________________________
openib-general mailing list
openib-general@openib.org
http://openib.org/mailman/listinfo/openib-general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to