Browse Source

[infiniband] Respond to CM disconnection requests

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
ef8452a642
2 changed files with 183 additions and 68 deletions
  1. 30
    0
      src/include/ipxe/ib_mad.h
  2. 153
    68
      src/net/infiniband/ib_cm.c

+ 30
- 0
src/include/ipxe/ib_mad.h View File

@@ -451,6 +451,34 @@ struct ib_cm_ready_to_use {
451 451
 	uint8_t private_data[224];
452 452
 } __attribute__ (( packed ));
453 453
 
454
+/** A communication management disconnection request
455
+ *
456
+ * Defined in section 12.6.10 of the IBA.
457
+ */
458
+struct ib_cm_disconnect_request {
459
+	/** Local communication ID */
460
+	uint32_t local_id;
461
+	/** Remote communication ID */
462
+	uint32_t remote_id;
463
+	/** Remote QPN/EECN */
464
+	uint32_t remote_qpn_eecn;
465
+	/** Private data */
466
+	uint8_t private_data[220];
467
+} __attribute__ (( packed ));
468
+
469
+/** A communication management disconnection reply
470
+ *
471
+ * Defined in section 12.6.11 of the IBA.
472
+ */
473
+struct ib_cm_disconnect_reply {
474
+	/** Local communication ID */
475
+	uint32_t local_id;
476
+	/** Remote communication ID */
477
+	uint32_t remote_id;
478
+	/** Private data */
479
+	uint8_t private_data[224];
480
+} __attribute__ (( packed ));
481
+
454 482
 /** A communication management attribute */
455 483
 union ib_cm_data {
456 484
 	struct ib_cm_common common;
@@ -458,6 +486,8 @@ union ib_cm_data {
458 486
 	struct ib_cm_connect_reject connect_reject;
459 487
 	struct ib_cm_connect_reply connect_reply;
460 488
 	struct ib_cm_ready_to_use ready_to_use;
489
+	struct ib_cm_disconnect_request disconnect_request;
490
+	struct ib_cm_disconnect_reply disconnect_reply;
461 491
 	uint8_t bytes[232];
462 492
 } __attribute__ (( packed ));
463 493
 

+ 153
- 68
src/net/infiniband/ib_cm.c View File

@@ -39,22 +39,38 @@ FILE_LICENCE ( GPL2_OR_LATER );
39 39
 /** List of connections */
40 40
 static LIST_HEAD ( ib_cm_conns );
41 41
 
42
+/**
43
+ * Find connection by local communication ID
44
+ *
45
+ * @v local_id		Local communication ID
46
+ * @ret conn		Connection, or NULL
47
+ */
48
+static struct ib_connection * ib_cm_find ( uint32_t local_id ) {
49
+	struct ib_connection *conn;
50
+
51
+	list_for_each_entry ( conn, &ib_cm_conns, list ) {
52
+		if ( conn->local_id == local_id )
53
+			return conn;
54
+	}
55
+	return NULL;
56
+}
57
+
42 58
 /**
43 59
  * Send "ready to use" response
44 60
  *
45 61
  * @v ibdev		Infiniband device
46 62
  * @v mi		Management interface
47
- * @v conn		Connection
48 63
  * @v av		Address vector
64
+ * @v local_id		Local communication ID
65
+ * @v remote_id		Remote communication ID
49 66
  * @ret rc		Return status code
50 67
  */
51 68
 static int ib_cm_send_rtu ( struct ib_device *ibdev,
52 69
 			    struct ib_mad_interface *mi,
53
-			    struct ib_connection *conn,
54
-			    struct ib_address_vector *av ) {
70
+			    struct ib_address_vector *av,
71
+			    uint32_t local_id, uint32_t remote_id ) {
55 72
 	union ib_mad mad;
56
-	struct ib_cm_ready_to_use *ready =
57
-		&mad.cm.cm_data.ready_to_use;
73
+	struct ib_cm_ready_to_use *rtu = &mad.cm.cm_data.ready_to_use;
58 74
 	int rc;
59 75
 
60 76
 	/* Construct "ready to use" response */
@@ -63,11 +79,10 @@ static int ib_cm_send_rtu ( struct ib_device *ibdev,
63 79
 	mad.hdr.class_version = IB_CM_CLASS_VERSION;
64 80
 	mad.hdr.method = IB_MGMT_METHOD_SEND;
65 81
 	mad.hdr.attr_id = htons ( IB_CM_ATTR_READY_TO_USE );
66
-	ready->local_id = htonl ( conn->local_id );
67
-	ready->remote_id = htonl ( conn->remote_id );
82
+	rtu->local_id = htonl ( local_id );
83
+	rtu->remote_id = htonl ( remote_id );
68 84
 	if ( ( rc = ib_mi_send ( ibdev, mi, &mad, av ) ) != 0 ){
69
-		DBGC ( conn, "CM %p could not send RTU: %s\n",
70
-		       conn, strerror ( rc ) );
85
+		DBG ( "CM could not send RTU: %s\n", strerror ( rc ) );
71 86
 		return rc;
72 87
 	}
73 88
 
@@ -87,38 +102,113 @@ static int ib_cm_send_rtu ( struct ib_device *ibdev,
87 102
  * reply.  We have to respond to these with duplicate "ready to use"
88 103
  * MADs, otherwise the peer may time out and drop the connection.
89 104
  */
90
-static void ib_cm_connect_rep ( struct ib_device *ibdev,
91
-				struct ib_mad_interface *mi,
92
-				union ib_mad *mad,
93
-				struct ib_address_vector *av ) {
94
-	struct ib_cm_connect_reply *connect_rep =
95
-		&mad->cm.cm_data.connect_reply;
105
+static void ib_cm_recv_rep ( struct ib_device *ibdev,
106
+			     struct ib_mad_interface *mi,
107
+			     union ib_mad *mad,
108
+			     struct ib_address_vector *av ) {
109
+	struct ib_cm_connect_reply *rep = &mad->cm.cm_data.connect_reply;
96 110
 	struct ib_connection *conn;
111
+	uint32_t local_id = ntohl ( rep->remote_id );
97 112
 	int rc;
98 113
 
99 114
 	/* Identify connection */
100
-	list_for_each_entry ( conn, &ib_cm_conns, list ) {
101
-		if ( ntohl ( connect_rep->remote_id ) != conn->local_id )
102
-			continue;
115
+	conn = ib_cm_find ( local_id );
116
+	if ( conn ) {
103 117
 		/* Try to send "ready to use" reply */
104
-		if ( ( rc = ib_cm_send_rtu ( ibdev, mi, conn, av ) ) != 0 ) {
105
-			/* Ignore errors */
106
-			return;
118
+		if ( ( rc = ib_cm_send_rtu ( ibdev, mi, av, conn->local_id,
119
+					     conn->remote_id ) ) != 0 ) {
120
+			/* Ignore errors; the remote end will retry */
107 121
 		}
108
-		return;
122
+	} else {
123
+		DBG ( "CM unidentified connection %08x\n", local_id );
124
+	}
125
+}
126
+
127
+/**
128
+ * Send reply to disconnection request
129
+ *
130
+ * @v ibdev		Infiniband device
131
+ * @v mi		Management interface
132
+ * @v av		Address vector
133
+ * @v local_id		Local communication ID
134
+ * @v remote_id		Remote communication ID
135
+ * @ret rc		Return status code
136
+ */
137
+static int ib_cm_send_drep ( struct ib_device *ibdev,
138
+			     struct ib_mad_interface *mi,
139
+			     struct ib_address_vector *av,
140
+			     uint32_t local_id, uint32_t remote_id ) {
141
+	union ib_mad mad;
142
+	struct ib_cm_disconnect_reply *drep = &mad.cm.cm_data.disconnect_reply;
143
+	int rc;
144
+
145
+	/* Construct reply to disconnection request */
146
+	memset ( &mad, 0, sizeof ( mad ) );
147
+	mad.hdr.mgmt_class = IB_MGMT_CLASS_CM;
148
+	mad.hdr.class_version = IB_CM_CLASS_VERSION;
149
+	mad.hdr.method = IB_MGMT_METHOD_SEND;
150
+	mad.hdr.attr_id = htons ( IB_CM_ATTR_DISCONNECT_REPLY );
151
+	drep->local_id = htonl ( local_id );
152
+	drep->remote_id = htonl ( remote_id );
153
+	if ( ( rc = ib_mi_send ( ibdev, mi, &mad, av ) ) != 0 ){
154
+		DBG ( "CM could not send DREP: %s\n", strerror ( rc ) );
155
+		return rc;
109 156
 	}
110 157
 
111
-	DBG ( "CM unidentified connection %08x\n",
112
-	      ntohl ( connect_rep->remote_id ) );
158
+	return 0;
113 159
 }
114 160
 
161
+/**
162
+ * Handle disconnection requests
163
+ *
164
+ * @v ibdev		Infiniband device
165
+ * @v mi		Management interface
166
+ * @v mad		Received MAD
167
+ * @v av		Source address vector
168
+ * @ret rc		Return status code
169
+ */
170
+static void ib_cm_recv_dreq ( struct ib_device *ibdev,
171
+			      struct ib_mad_interface *mi,
172
+			      union ib_mad *mad,
173
+			      struct ib_address_vector *av ) {
174
+	struct ib_cm_disconnect_request *dreq =
175
+		&mad->cm.cm_data.disconnect_request;
176
+	struct ib_connection *conn;
177
+	uint32_t local_id = ntohl ( dreq->remote_id );
178
+	uint32_t remote_id = ntohl ( dreq->local_id );
179
+	int rc;
180
+
181
+	/* Identify connection */
182
+	conn = ib_cm_find ( local_id );
183
+	if ( conn ) {
184
+		/* Notify upper layer */
185
+		conn->op->changed ( ibdev, conn->qp, conn, -ENOTCONN,
186
+				    &dreq->private_data,
187
+				    sizeof ( dreq->private_data ) );
188
+	} else {
189
+		DBG ( "CM unidentified connection %08x\n", local_id );
190
+	}
191
+
192
+	/* Send reply */
193
+	if ( ( rc = ib_cm_send_drep ( ibdev, mi, av, local_id,
194
+				      remote_id ) ) != 0 ) {
195
+		/* Ignore errors; the remote end will retry */
196
+	}
197
+};
198
+
115 199
 /** Communication management agents */
116 200
 struct ib_mad_agent ib_cm_agent[] __ib_mad_agent = {
117 201
 	{
118 202
 		.mgmt_class = IB_MGMT_CLASS_CM,
119 203
 		.class_version = IB_CM_CLASS_VERSION,
120 204
 		.attr_id = htons ( IB_CM_ATTR_CONNECT_REPLY ),
121
-		.handle = ib_cm_connect_rep,
205
+		.handle = ib_cm_recv_rep,
206
+	},
207
+	{
208
+		.mgmt_class = IB_MGMT_CLASS_CM,
209
+		.class_version = IB_CM_CLASS_VERSION,
210
+		.attr_id = htons ( IB_CM_ATTR_DISCONNECT_REQUEST ),
211
+		.handle = ib_cm_recv_dreq,
122 212
 	},
123 213
 };
124 214
 
@@ -159,10 +249,8 @@ static void ib_cm_req_complete ( struct ib_device *ibdev,
159 249
 	struct ib_connection *conn = ib_madx_get_ownerdata ( madx );
160 250
 	struct ib_queue_pair *qp = conn->qp;
161 251
 	struct ib_cm_common *common = &mad->cm.cm_data.common;
162
-	struct ib_cm_connect_reply *connect_rep =
163
-		&mad->cm.cm_data.connect_reply;
164
-	struct ib_cm_connect_reject *connect_rej =
165
-		&mad->cm.cm_data.connect_reject;
252
+	struct ib_cm_connect_reply *rep = &mad->cm.cm_data.connect_reply;
253
+	struct ib_cm_connect_reject *rej = &mad->cm.cm_data.connect_reject;
166 254
 	void *private_data = NULL;
167 255
 	size_t private_data_len = 0;
168 256
 
@@ -183,10 +271,10 @@ static void ib_cm_req_complete ( struct ib_device *ibdev,
183 271
 
184 272
 	case htons ( IB_CM_ATTR_CONNECT_REPLY ) :
185 273
 		/* Extract fields */
186
-		qp->av.qpn = ( ntohl ( connect_rep->local_qpn ) >> 8 );
187
-		qp->send.psn = ( ntohl ( connect_rep->starting_psn ) >> 8 );
188
-		private_data = &connect_rep->private_data;
189
-		private_data_len = sizeof ( connect_rep->private_data );
274
+		qp->av.qpn = ( ntohl ( rep->local_qpn ) >> 8 );
275
+		qp->send.psn = ( ntohl ( rep->starting_psn ) >> 8 );
276
+		private_data = &rep->private_data;
277
+		private_data_len = sizeof ( rep->private_data );
190 278
 		DBGC ( conn, "CM %p connected to QPN %lx PSN %x\n",
191 279
 		       conn, qp->av.qpn, qp->send.psn );
192 280
 
@@ -198,7 +286,8 @@ static void ib_cm_req_complete ( struct ib_device *ibdev,
198 286
 		}
199 287
 
200 288
 		/* Send "ready to use" reply */
201
-		if ( ( rc = ib_cm_send_rtu ( ibdev, mi, conn, av ) ) != 0 ) {
289
+		if ( ( rc = ib_cm_send_rtu ( ibdev, mi, av, conn->local_id,
290
+					     conn->remote_id ) ) != 0 ) {
202 291
 			/* Treat as non-fatal */
203 292
 			rc = 0;
204 293
 		}
@@ -207,13 +296,13 @@ static void ib_cm_req_complete ( struct ib_device *ibdev,
207 296
 	case htons ( IB_CM_ATTR_CONNECT_REJECT ) :
208 297
 		/* Extract fields */
209 298
 		DBGC ( conn, "CM %p connection rejected (reason %d)\n",
210
-		       conn, ntohs ( connect_rej->reason ) );
299
+		       conn, ntohs ( rej->reason ) );
211 300
 		/* Private data is valid only for a Consumer Reject */
212
-		if ( connect_rej->reason == htons ( IB_CM_REJECT_CONSUMER ) ) {
213
-			private_data = &connect_rej->private_data;
214
-			private_data_len = sizeof (connect_rej->private_data);
301
+		if ( rej->reason == htons ( IB_CM_REJECT_CONSUMER ) ) {
302
+			private_data = &rej->private_data;
303
+			private_data_len = sizeof ( rej->private_data );
215 304
 		}
216
-		rc = ib_cm_rejection_reason_to_rc ( connect_rej->reason );
305
+		rc = ib_cm_rejection_reason_to_rc ( rej->reason );
217 306
 		break;
218 307
 
219 308
 	default:
@@ -252,8 +341,7 @@ static void ib_cm_path_complete ( struct ib_device *ibdev,
252 341
 	struct ib_connection *conn = ib_path_get_ownerdata ( path );
253 342
 	struct ib_queue_pair *qp = conn->qp;
254 343
 	union ib_mad mad;
255
-	struct ib_cm_connect_request *connect_req =
256
-		&mad.cm.cm_data.connect_request;
344
+	struct ib_cm_connect_request *req = &mad.cm.cm_data.connect_request;
257 345
 	size_t private_data_len;
258 346
 
259 347
 	/* Report failures */
@@ -273,41 +361,38 @@ static void ib_cm_path_complete ( struct ib_device *ibdev,
273 361
 	mad.hdr.class_version = IB_CM_CLASS_VERSION;
274 362
 	mad.hdr.method = IB_MGMT_METHOD_SEND;
275 363
 	mad.hdr.attr_id = htons ( IB_CM_ATTR_CONNECT_REQUEST );
276
-	connect_req->local_id = htonl ( conn->local_id );
277
-	memcpy ( &connect_req->service_id, &conn->service_id,
278
-		 sizeof ( connect_req->service_id ) );
279
-	ib_get_hca_info ( ibdev, &connect_req->local_ca );
280
-	connect_req->local_qpn__responder_resources =
281
-		htonl ( ( qp->qpn << 8 ) | 1 );
282
-	connect_req->local_eecn__initiator_depth = htonl ( ( 0 << 8 ) | 1 );
283
-	connect_req->remote_eecn__remote_timeout__service_type__ee_flow_ctrl =
364
+	req->local_id = htonl ( conn->local_id );
365
+	memcpy ( &req->service_id, &conn->service_id,
366
+		 sizeof ( req->service_id ) );
367
+	ib_get_hca_info ( ibdev, &req->local_ca );
368
+	req->local_qpn__responder_resources = htonl ( ( qp->qpn << 8 ) | 1 );
369
+	req->local_eecn__initiator_depth = htonl ( ( 0 << 8 ) | 1 );
370
+	req->remote_eecn__remote_timeout__service_type__ee_flow_ctrl =
284 371
 		htonl ( ( 0x14 << 3 ) | ( IB_CM_TRANSPORT_RC << 1 ) |
285 372
 			( 0 << 0 ) );
286
-	connect_req->starting_psn__local_timeout__retry_count =
373
+	req->starting_psn__local_timeout__retry_count =
287 374
 		htonl ( ( qp->recv.psn << 8 ) | ( 0x14 << 3 ) |
288 375
 			( 0x07 << 0 ) );
289
-	connect_req->pkey = htons ( ibdev->pkey );
290
-	connect_req->payload_mtu__rdc_exists__rnr_retry =
376
+	req->pkey = htons ( ibdev->pkey );
377
+	req->payload_mtu__rdc_exists__rnr_retry =
291 378
 		( ( IB_MTU_2048 << 4 ) | ( 1 << 3 ) | ( 0x07 << 0 ) );
292
-	connect_req->max_cm_retries__srq =
293
-		( ( 0x0f << 4 ) | ( 0 << 3 ) );
294
-	connect_req->primary.local_lid = htons ( ibdev->lid );
295
-	connect_req->primary.remote_lid = htons ( conn->qp->av.lid );
296
-	memcpy ( &connect_req->primary.local_gid, &ibdev->gid,
297
-		 sizeof ( connect_req->primary.local_gid ) );
298
-	memcpy ( &connect_req->primary.remote_gid, &conn->qp->av.gid,
299
-		 sizeof ( connect_req->primary.remote_gid ) );
300
-	connect_req->primary.flow_label__rate =
379
+	req->max_cm_retries__srq = ( ( 0x0f << 4 ) | ( 0 << 3 ) );
380
+	req->primary.local_lid = htons ( ibdev->lid );
381
+	req->primary.remote_lid = htons ( conn->qp->av.lid );
382
+	memcpy ( &req->primary.local_gid, &ibdev->gid,
383
+		 sizeof ( req->primary.local_gid ) );
384
+	memcpy ( &req->primary.remote_gid, &conn->qp->av.gid,
385
+		 sizeof ( req->primary.remote_gid ) );
386
+	req->primary.flow_label__rate =
301 387
 		htonl ( ( 0 << 12 ) | ( conn->qp->av.rate << 0 ) );
302
-	connect_req->primary.hop_limit = 0;
303
-	connect_req->primary.sl__subnet_local =
388
+	req->primary.hop_limit = 0;
389
+	req->primary.sl__subnet_local =
304 390
 		( ( conn->qp->av.sl << 4 ) | ( 1 << 3 ) );
305
-	connect_req->primary.local_ack_timeout = ( 0x13 << 3 );
391
+	req->primary.local_ack_timeout = ( 0x13 << 3 );
306 392
 	private_data_len = conn->private_data_len;
307
-	if ( private_data_len > sizeof ( connect_req->private_data ) )
308
-		private_data_len = sizeof ( connect_req->private_data );
309
-	memcpy ( &connect_req->private_data, &conn->private_data,
310
-		 private_data_len );
393
+	if ( private_data_len > sizeof ( req->private_data ) )
394
+		private_data_len = sizeof ( req->private_data );
395
+	memcpy ( &req->private_data, &conn->private_data, private_data_len );
311 396
 
312 397
 	/* Create connection request */
313 398
 	av->qpn = IB_QPN_GSI;

Loading…
Cancel
Save