Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 26 Jul 2021 16:13:22 GMT
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 06307dd6e0df - stable/13 - ibcore: Issue DREQ when receiving REQ/REP for stale QP.
Message-ID:  <202107261613.16QGDM77005359@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by hselasky:

URL: https://cgit.FreeBSD.org/src/commit/?id=06307dd6e0df91a867a6a42bb4da121f89085b54

commit 06307dd6e0df91a867a6a42bb4da121f89085b54
Author:     Hans Petter Selasky <hselasky@FreeBSD.org>
AuthorDate: 2021-06-16 13:01:38 +0000
Commit:     Hans Petter Selasky <hselasky@FreeBSD.org>
CommitDate: 2021-07-26 16:04:29 +0000

    ibcore: Issue DREQ when receiving REQ/REP for stale QP.
    
    From "InfiBand Architecture Specifications Volume 1":
    
      A QP is said to have a stale connection when only one side has
      connection information. A stale connection may result if the remote CM
      had dropped the connection and sent a DREQ but the DREQ was never
      received by the local CM. Alternatively the remote CM may have lost
      all record of past connections because its node crashed and rebooted,
      while the local CM did not become aware of the remote node's reboot
      and therefore did not clean up stale connections.
    
    And:
    
      A local CM may receive a REQ/REP for a stale connection. It shall
      abort the connection issuing REJ to the REQ/REP. It shall then issue
      DREQ with "DREQ:remote QPN" set to the remote QPN from the REQ/REP.
    
    This patch solves a problem with reuse of QPN. Current codebase, that
    is IPoIB, relies on a REAP-mechanism to do cleanup of the structures
    in CM. A problem with this is the timeconstants governing this
    mechanism; they are up to 768 seconds and the interface may look
    inresponsive in that period.  Issuing a DREQ (and receiving a DREP)
    does the necessary cleanup and the interface comes up.
    
    Linux commit:
    9315bc9a133011fdb084f2626b86db3ebb64661f
    
    Reviewed by:    kib
    Sponsored by:   Mellanox Technologies // NVIDIA Networking
    
    (cherry picked from commit 12a913d207d287733da75784b3aa35f5e48d0cef)
---
 sys/ofed/drivers/infiniband/core/ib_cm.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/sys/ofed/drivers/infiniband/core/ib_cm.c b/sys/ofed/drivers/infiniband/core/ib_cm.c
index 7dea2620cb60..376dcb420f5b 100644
--- a/sys/ofed/drivers/infiniband/core/ib_cm.c
+++ b/sys/ofed/drivers/infiniband/core/ib_cm.c
@@ -1679,6 +1679,7 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
 	struct cm_id_private *listen_cm_id_priv, *cur_cm_id_priv;
 	struct cm_timewait_info *timewait_info;
 	struct cm_req_msg *req_msg;
+	struct ib_cm_id *cm_id;
 
 	req_msg = (struct cm_req_msg *)work->mad_recv_wc->recv_buf.mad;
 
@@ -1700,10 +1701,18 @@ static struct cm_id_private * cm_match_req(struct cm_work *work,
 	timewait_info = cm_insert_remote_qpn(cm_id_priv->timewait_info);
 	if (timewait_info) {
 		cm_cleanup_timewait(cm_id_priv->timewait_info);
+		cur_cm_id_priv = cm_get_id(timewait_info->work.local_id,
+					   timewait_info->work.remote_id);
+
 		spin_unlock_irq(&cm.lock);
 		cm_issue_rej(work->port, work->mad_recv_wc,
 			     IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REQ,
 			     NULL, 0);
+		if (cur_cm_id_priv) {
+			cm_id = &cur_cm_id_priv->id;
+			ib_send_cm_dreq(cm_id, NULL, 0);
+			cm_deref_id(cur_cm_id_priv);
+		}
 		return NULL;
 	}
 
@@ -2084,6 +2093,9 @@ static int cm_rep_handler(struct cm_work *work)
 	struct cm_id_private *cm_id_priv;
 	struct cm_rep_msg *rep_msg;
 	int ret;
+	struct cm_id_private *cur_cm_id_priv;
+	struct ib_cm_id *cm_id;
+	struct cm_timewait_info *timewait_info;
 
 	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);
@@ -2118,16 +2130,26 @@ static int cm_rep_handler(struct cm_work *work)
 		goto error;
 	}
 	/* Check for a stale connection. */
-	if (cm_insert_remote_qpn(cm_id_priv->timewait_info)) {
+	timewait_info = cm_insert_remote_qpn(cm_id_priv->timewait_info);
+	if (timewait_info) {
 		rb_erase(&cm_id_priv->timewait_info->remote_id_node,
 			 &cm.remote_id_table);
 		cm_id_priv->timewait_info->inserted_remote_id = 0;
+		cur_cm_id_priv = cm_get_id(timewait_info->work.local_id,
+					   timewait_info->work.remote_id);
+
 		spin_unlock(&cm.lock);
 		spin_unlock_irq(&cm_id_priv->lock);
 		cm_issue_rej(work->port, work->mad_recv_wc,
 			     IB_CM_REJ_STALE_CONN, CM_MSG_RESPONSE_REP,
 			     NULL, 0);
 		ret = -EINVAL;
+		if (cur_cm_id_priv) {
+			cm_id = &cur_cm_id_priv->id;
+			ib_send_cm_dreq(cm_id, NULL, 0);
+			cm_deref_id(cur_cm_id_priv);
+		}
+
 		goto error;
 	}
 	spin_unlock(&cm.lock);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202107261613.16QGDM77005359>