summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2009-08-09 22:00:48 +0200
committerMichael Brown2009-08-10 23:31:55 +0200
commit0ff5c456cb1ad38c3300a214799478101a3540a6 (patch)
tree4827eb2eb1af8a07afd4c304957c06b9513f006a
parent[infiniband] Allow SRP reconnection attempts even after reporting failures (diff)
downloadipxe-0ff5c456cb1ad38c3300a214799478101a3540a6.tar.gz
ipxe-0ff5c456cb1ad38c3300a214799478101a3540a6.tar.xz
ipxe-0ff5c456cb1ad38c3300a214799478101a3540a6.zip
[infiniband] Disambiguate CM connection rejection reasons
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.
-rw-r--r--src/include/gpxe/ib_mad.h5
-rw-r--r--src/net/infiniband/ib_cm.c28
-rw-r--r--src/net/infiniband/ib_cmrc.c3
3 files changed, 32 insertions, 4 deletions
diff --git a/src/include/gpxe/ib_mad.h b/src/include/gpxe/ib_mad.h
index 54d0a2af..8b497183 100644
--- a/src/include/gpxe/ib_mad.h
+++ b/src/include/gpxe/ib_mad.h
@@ -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.
diff --git a/src/net/infiniband/ib_cm.c b/src/net/infiniband/ib_cm.c
index 859d56f2..30a3691f 100644
--- a/src/net/infiniband/ib_cm.c
+++ b/src/net/infiniband/ib_cm.c
@@ -123,6 +123,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
*
* @v ibdev Infiniband device
@@ -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:
diff --git a/src/net/infiniband/ib_cmrc.c b/src/net/infiniband/ib_cmrc.c
index 7ec96313..2d648115 100644
--- a/src/net/infiniband/ib_cmrc.c
+++ b/src/net/infiniband/ib_cmrc.c
@@ -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 ) );