]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[infiniband] Disambiguate CM connection rejection reasons
authorMichael Brown <mcb30@etherboot.org>
Sun, 9 Aug 2009 20:00:48 +0000 (21:00 +0100)
committerMichael Brown <mcb30@etherboot.org>
Mon, 10 Aug 2009 21:31:55 +0000 (22:31 +0100)
There is diagnostic value in being able to disambiguate between the
various reasons why an IB CM has rejected a connection attempt.  In
particular, reason 8 "invalid service ID" can be used to identify an
incorrect SRP service_id root-path component, and reason 28 "consumer
reject" corresponds to a genuine SRP login rejection IU, which can be
passed up to the SRP layer.

For rejection reasons other than "consumer reject", we should not pass
through the private data, since it is most likely generated by the CM
without any protocol-specific knowledge.

src/include/gpxe/ib_mad.h
src/net/infiniband/ib_cm.c
src/net/infiniband/ib_cmrc.c

index 54d0a2afda650bd14aa549e7552582e36afd224c..8b49718351ce0ec89e5e45b7320257e583a29a19 100644 (file)
@@ -402,6 +402,11 @@ struct ib_cm_connect_reject {
        uint8_t private_data[148];
 } __attribute__ (( packed ));
 
+/** CM rejection reasons */
+#define IB_CM_REJECT_BAD_SERVICE_ID    8
+#define IB_CM_REJECT_STALE_CONN                10
+#define IB_CM_REJECT_CONSUMER          28
+
 /** A communication management connection reply
  *
  * Defined in section 12.6.8 of the IBA.
index 859d56f20cfb7a9ac479c200b417e8905391471a..30a3691fe7cead048589c1604878e8f6e8fdcb5a 100644 (file)
@@ -122,6 +122,25 @@ struct ib_mad_agent ib_cm_agent[] __ib_mad_agent = {
        },
 };
 
+/**
+ * Convert connection rejection reason to return status code
+ *
+ * @v reason           Rejection reason (in network byte order)
+ * @ret rc             Return status code
+ */
+static int ib_cm_rejection_reason_to_rc ( uint16_t reason ) {
+       switch ( reason ) {
+       case htons ( IB_CM_REJECT_BAD_SERVICE_ID ) :
+               return -ENODEV;
+       case htons ( IB_CM_REJECT_STALE_CONN ) :
+               return -EALREADY;
+       case htons ( IB_CM_REJECT_CONSUMER ) :
+               return -ENOTTY;
+       default:
+               return -EPERM;
+       }
+}
+
 /**
  * Handle connection request transaction completion
  *
@@ -189,9 +208,12 @@ static void ib_cm_req_complete ( struct ib_device *ibdev,
                /* Extract fields */
                DBGC ( conn, "CM %p connection rejected (reason %d)\n",
                       conn, ntohs ( connect_rej->reason ) );
-               private_data = &connect_rej->private_data;
-               private_data_len = sizeof ( connect_rej->private_data );
-               rc = -ENOTCONN;
+               /* Private data is valid only for a Consumer Reject */
+               if ( connect_rej->reason == htons ( IB_CM_REJECT_CONSUMER ) ) {
+                       private_data = &connect_rej->private_data;
+                       private_data_len = sizeof (connect_rej->private_data);
+               }
+               rc = ib_cm_rejection_reason_to_rc ( connect_rej->reason );
                break;
 
        default:
index 7ec96313542f14e136b09d34d99773446164701a..2d64811583d4d6fa8f8a3821e797e69a58cf0bd0 100644 (file)
@@ -172,7 +172,8 @@ static void ib_cmrc_changed ( struct ib_device *ibdev __unused,
        /* Pass up any private data */
        DBGC2 ( cmrc, "CMRC %p received private data:\n", cmrc );
        DBGC2_HDA ( cmrc, 0, private_data, private_data_len );
-       if ( ( rc_xfer = xfer_deliver_raw ( &cmrc->xfer, private_data,
+       if ( private_data &&
+            ( rc_xfer = xfer_deliver_raw ( &cmrc->xfer, private_data,
                                            private_data_len ) ) != 0 ) {
                DBGC ( cmrc, "CMRC %p could not deliver private data: %s\n",
                       cmrc, strerror ( rc_xfer ) );