瀏覽代碼

[infiniband] Provide a general mechanism for multicast group joins

Generalise out the multicast group membership record code from IPoIB.
tags/v0.9.8
Michael Brown 15 年之前
父節點
當前提交
0fbf2f6bda
共有 6 個文件被更改,包括 274 次插入129 次删除
  1. 13
    129
      src/drivers/net/ipoib.c
  2. 1
    0
      src/include/gpxe/errfile.h
  3. 2
    0
      src/include/gpxe/ib_mad.h
  4. 19
    0
      src/include/gpxe/ib_mcast.h
  5. 4
    0
      src/net/infiniband.c
  6. 235
    0
      src/net/infiniband/ib_mcast.c

+ 13
- 129
src/drivers/net/ipoib.c 查看文件

@@ -30,6 +30,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
30 30
 #include <gpxe/infiniband.h>
31 31
 #include <gpxe/ib_qset.h>
32 32
 #include <gpxe/ib_pathrec.h>
33
+#include <gpxe/ib_mcast.h>
33 34
 #include <gpxe/ipoib.h>
34 35
 
35 36
 /** @file
@@ -67,20 +68,14 @@ struct ipoib_device {
67 68
 	struct ib_queue_set meta;
68 69
 	/** Broadcast MAC */
69 70
 	struct ipoib_mac broadcast;
70
-	/** Attached to multicast group
71
+	/** Joined to multicast group
71 72
 	 *
72
-	 * This flag indicates whether or not we have attached our
73
-	 * data queue pair to the broadcast multicast GID.
73
+	 * This flag indicates whether or not we have initiated the
74
+	 * join to the IPv4 multicast group.
74 75
 	 */
75
-	int broadcast_attached;
76
+	int broadcast_joined;
76 77
 };
77 78
 
78
-/** TID half used to identify multicast member record replies */
79
-#define IPOIB_TID_MC_MEMBER_REC 0x22222222UL
80
-
81
-/** IPoIB metadata TID */
82
-static uint32_t ipoib_meta_tid = 0;
83
-
84 79
 /** Broadcast IPoIB address */
85 80
 static struct ipoib_mac ipoib_broadcast = {
86 81
 	.qpn = htonl ( IB_QPN_BROADCAST ),
@@ -332,67 +327,6 @@ struct net_device * alloc_ipoibdev ( size_t priv_size ) {
332 327
  ****************************************************************************
333 328
  */
334 329
 
335
-/**
336
- * Transmit multicast group membership request
337
- *
338
- * @v ipoib		IPoIB device
339
- * @v gid		Multicast GID
340
- * @v join		Join (rather than leave) group
341
- * @ret rc		Return status code
342
- */
343
-static int ipoib_mc_member_record ( struct ipoib_device *ipoib,
344
-				    struct ib_gid *gid, int join ) {
345
-	struct ib_device *ibdev = ipoib->ibdev;
346
-	struct io_buffer *iobuf;
347
-	struct ib_mad_sa *sa;
348
-	struct ib_address_vector av;
349
-	int rc;
350
-
351
-	/* Allocate I/O buffer */
352
-	iobuf = alloc_iob ( sizeof ( *sa ) );
353
-	if ( ! iobuf )
354
-		return -ENOMEM;
355
-	iob_put ( iobuf, sizeof ( *sa ) );
356
-	sa = iobuf->data;
357
-	memset ( sa, 0, sizeof ( *sa ) );
358
-
359
-	/* Construct path record request */
360
-	sa->mad_hdr.base_version = IB_MGMT_BASE_VERSION;
361
-	sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
362
-	sa->mad_hdr.class_version = 2;
363
-	sa->mad_hdr.method =
364
-		( join ? IB_MGMT_METHOD_SET : IB_MGMT_METHOD_DELETE );
365
-	sa->mad_hdr.attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC );
366
-	sa->mad_hdr.tid[0] = IPOIB_TID_MC_MEMBER_REC;
367
-	sa->mad_hdr.tid[1] = ipoib_meta_tid++;
368
-	sa->sa_hdr.comp_mask[1] =
369
-		htonl ( IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
370
-			IB_SA_MCMEMBER_REC_JOIN_STATE );
371
-	sa->sa_data.mc_member_record.scope__join_state = 1;
372
-	memcpy ( &sa->sa_data.mc_member_record.mgid, gid,
373
-		 sizeof ( sa->sa_data.mc_member_record.mgid ) );
374
-	memcpy ( &sa->sa_data.mc_member_record.port_gid, &ibdev->gid,
375
-		 sizeof ( sa->sa_data.mc_member_record.port_gid ) );
376
-
377
-	/* Construct address vector */
378
-	memset ( &av, 0, sizeof ( av ) );
379
-	av.lid = ibdev->sm_lid;
380
-	av.sl = ibdev->sm_sl;
381
-	av.qpn = IB_QPN_GMA;
382
-	av.qkey = IB_QKEY_GMA;
383
-
384
-	/* Post send request */
385
-	if ( ( rc = ib_post_send ( ibdev, ipoib->meta.qp, &av,
386
-				   iobuf ) ) != 0 ) {
387
-		DBGC ( ipoib, "IPoIB %p could not send get path record: %s\n",
388
-		       ipoib, strerror ( rc ) );
389
-		free_iob ( iobuf );
390
-		return rc;
391
-	}
392
-
393
-	return 0;
394
-}
395
-
396 330
 /**
397 331
  * Transmit packet via IPoIB network device
398 332
  *
@@ -529,33 +463,6 @@ static void ipoib_meta_complete_send ( struct ib_device *ibdev __unused,
529 463
 	free_iob ( iobuf );
530 464
 }
531 465
 
532
-/**
533
- * Handle received IPoIB multicast membership record
534
- *
535
- * @v ipoib		IPoIB device
536
- * @v mc_member_record	Multicast membership record
537
- */
538
-static void ipoib_recv_mc_member_record ( struct ipoib_device *ipoib,
539
-			       struct ib_mc_member_record *mc_member_record ) {
540
-	unsigned long data_qkey;
541
-	int joined;
542
-	int rc;
543
-
544
-	/* Record parameters */
545
-	joined = ( mc_member_record->scope__join_state & 0x0f );
546
-	data_qkey = ntohl ( mc_member_record->qkey );
547
-	DBGC ( ipoib, "IPoIB %p %s broadcast group: qkey %lx\n",
548
-	       ipoib, ( joined ? "joined" : "left" ), data_qkey );
549
-
550
-	/* Update data queue pair qkey */
551
-	if ( ( rc = ib_modify_qp ( ipoib->ibdev, ipoib->data.qp,
552
-				   IB_MODIFY_QKEY, data_qkey ) ) != 0 ){
553
-		DBGC ( ipoib, "IPoIB %p could not update data qkey: %s\n",
554
-		       ipoib, strerror ( rc ) );
555
-		return;
556
-	}
557
-}
558
-
559 466
 /**
560 467
  * Handle IPoIB metadata receive completion
561 468
  *
@@ -594,10 +501,6 @@ ipoib_meta_complete_recv ( struct ib_device *ibdev __unused,
594 501
 	}
595 502
 
596 503
 	switch ( sa->mad_hdr.tid[0] ) {
597
-	case IPOIB_TID_MC_MEMBER_REC:
598
-		ipoib_recv_mc_member_record ( ipoib,
599
-					      &sa->sa_data.mc_member_record );
600
-		break;
601 504
 	default:
602 505
 		DBGC ( ipoib, "IPoIB %p unwanted response:\n",
603 506
 		       ipoib );
@@ -647,31 +550,13 @@ static void ipoib_irq ( struct net_device *netdev __unused,
647 550
 static int ipoib_join_broadcast_group ( struct ipoib_device *ipoib ) {
648 551
 	int rc;
649 552
 
650
-	/* Sanity check */
651
-	if ( ! ipoib->data.qp )
652
-		return 0;
653
-
654
-	/* Attach data queue to broadcast multicast GID */
655
-	assert ( ipoib->broadcast_attached == 0 );
656
-	if ( ( rc = ib_mcast_attach ( ipoib->ibdev, ipoib->data.qp,
657
-				      &ipoib->broadcast.gid ) ) != 0 ){
658
-		DBGC ( ipoib, "IPoIB %p could not attach to broadcast GID: "
659
-		       "%s\n", ipoib, strerror ( rc ) );
660
-		return rc;
661
-	}
662
-	ipoib->broadcast_attached = 1;
663
-
664
-	/* Initiate broadcast group join */
665
-	if ( ( rc = ipoib_mc_member_record ( ipoib, &ipoib->broadcast.gid,
666
-					     1 ) ) != 0 ) {
667
-		DBGC ( ipoib, "IPoIB %p could not send broadcast join: %s\n",
553
+	if ( ( rc = ib_mcast_join ( ipoib->ibdev, ipoib->data.qp,
554
+				    &ipoib->broadcast.gid ) ) != 0 ) {
555
+		DBGC ( ipoib, "IPoIB %p could not join broadcast group: %s\n",
668 556
 		       ipoib, strerror ( rc ) );
669 557
 		return rc;
670 558
 	}
671
-
672
-	/* We will set link up on the network device when we receive
673
-	 * the broadcast join response.
674
-	 */
559
+	ipoib->broadcast_joined = 1;
675 560
 
676 561
 	return 0;
677 562
 }
@@ -684,11 +569,10 @@ static int ipoib_join_broadcast_group ( struct ipoib_device *ipoib ) {
684 569
 static void ipoib_leave_broadcast_group ( struct ipoib_device *ipoib ) {
685 570
 
686 571
 	/* Detach data queue from broadcast multicast GID */
687
-	if ( ipoib->broadcast_attached ) {
688
-		assert ( ipoib->data.qp != NULL );
689
-		ib_mcast_detach ( ipoib->ibdev, ipoib->data.qp,
690
-				  &ipoib->broadcast.gid );
691
-		ipoib->broadcast_attached = 0;
572
+	if ( ipoib->broadcast_joined ) {
573
+		ib_mcast_leave ( ipoib->ibdev, ipoib->data.qp,
574
+				 &ipoib->broadcast.gid );
575
+		ipoib->broadcast_joined = 0;
692 576
 	}
693 577
 }
694 578
 

+ 1
- 0
src/include/gpxe/errfile.h 查看文件

@@ -146,6 +146,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
146 146
 #define ERRFILE_ib_qset			( ERRFILE_NET | 0x001a0000 )
147 147
 #define ERRFILE_ib_gma			( ERRFILE_NET | 0x001b0000 )
148 148
 #define ERRFILE_ib_pathrec		( ERRFILE_NET | 0x001c0000 )
149
+#define ERRFILE_ib_mcast		( ERRFILE_NET | 0x001d0000 )
149 150
 
150 151
 #define ERRFILE_image		      ( ERRFILE_IMAGE | 0x00000000 )
151 152
 #define ERRFILE_elf		      ( ERRFILE_IMAGE | 0x00010000 )

+ 2
- 0
src/include/gpxe/ib_mad.h 查看文件

@@ -203,6 +203,8 @@ struct ib_smp_class_specific {
203 203
 
204 204
 #define IB_SA_CLASS_VERSION			2
205 205
 
206
+#define IB_SA_METHOD_DELETE_RESP		0x95
207
+
206 208
 struct ib_rmpp_hdr {
207 209
 	uint32_t raw[3];
208 210
 } __attribute__ (( packed ));

+ 19
- 0
src/include/gpxe/ib_mcast.h 查看文件

@@ -0,0 +1,19 @@
1
+#ifndef _GPXE_IB_MCAST_H
2
+#define _GPXE_IB_MCAST_H
3
+
4
+/** @file
5
+ *
6
+ * Infiniband multicast groups
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+#include <gpxe/infiniband.h>
13
+
14
+extern int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp,
15
+			   struct ib_gid *gid );
16
+extern void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp,
17
+			     struct ib_gid *gid );
18
+
19
+#endif /* _GPXE_IB_MCAST_H */

+ 4
- 0
src/net/infiniband.c 查看文件

@@ -554,6 +554,10 @@ void ib_close ( struct ib_device *ibdev ) {
554 554
  * @v qp		Queue pair
555 555
  * @v gid		Multicast GID
556 556
  * @ret rc		Return status code
557
+ *
558
+ * Note that this function handles only the local device's attachment
559
+ * to the multicast GID; it does not issue the relevant MADs to join
560
+ * the multicast group on the subnet.
557 561
  */
558 562
 int ib_mcast_attach ( struct ib_device *ibdev, struct ib_queue_pair *qp,
559 563
 		      struct ib_gid *gid ) {

+ 235
- 0
src/net/infiniband/ib_mcast.c 查看文件

@@ -0,0 +1,235 @@
1
+/*
2
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+FILE_LICENCE ( GPL2_OR_LATER );
20
+
21
+#include <stdint.h>
22
+#include <string.h>
23
+#include <byteswap.h>
24
+#include <errno.h>
25
+#include <gpxe/list.h>
26
+#include <gpxe/infiniband.h>
27
+#include <gpxe/ib_gma.h>
28
+#include <gpxe/ib_mcast.h>
29
+
30
+/** @file
31
+ *
32
+ * Infiniband multicast groups
33
+ *
34
+ */
35
+
36
+/**
37
+ * Transmit multicast group membership request
38
+ *
39
+ * @v ibdev		Infiniband device
40
+ * @v gid		Multicast GID
41
+ * @v join		Join (rather than leave) group
42
+ * @ret rc		Return status code
43
+ */
44
+static int ib_mc_member_request ( struct ib_device *ibdev, struct ib_gid *gid,
45
+				  int join ) {
46
+	union ib_mad mad;
47
+	struct ib_mad_sa *sa = &mad.sa;
48
+	int rc;
49
+
50
+	/* Construct multicast membership record request */
51
+	memset ( sa, 0, sizeof ( *sa ) );
52
+	sa->mad_hdr.base_version = IB_MGMT_BASE_VERSION;
53
+	sa->mad_hdr.mgmt_class = IB_MGMT_CLASS_SUBN_ADM;
54
+	sa->mad_hdr.class_version = IB_SA_CLASS_VERSION;
55
+	sa->mad_hdr.method =
56
+		( join ? IB_MGMT_METHOD_SET : IB_MGMT_METHOD_DELETE );
57
+	sa->mad_hdr.attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC );
58
+	sa->sa_hdr.comp_mask[1] =
59
+		htonl ( IB_SA_MCMEMBER_REC_MGID | IB_SA_MCMEMBER_REC_PORT_GID |
60
+			IB_SA_MCMEMBER_REC_JOIN_STATE );
61
+	sa->sa_data.mc_member_record.scope__join_state = 1;
62
+	memcpy ( &sa->sa_data.mc_member_record.mgid, gid,
63
+		 sizeof ( sa->sa_data.mc_member_record.mgid ) );
64
+	memcpy ( &sa->sa_data.mc_member_record.port_gid, &ibdev->gid,
65
+		 sizeof ( sa->sa_data.mc_member_record.port_gid ) );
66
+
67
+	/* Issue multicast membership record request */
68
+	if ( ( rc = ib_gma_request ( &ibdev->gma, &mad, NULL,
69
+				     join ) ) != 0 ) {
70
+		DBGC ( ibdev, "IBDEV %p could not join group: %s\n",
71
+		       ibdev, strerror ( rc ) );
72
+		return rc;
73
+	}
74
+
75
+	return 0;
76
+}
77
+
78
+/**
79
+ * Join multicast group
80
+ *
81
+ * @v ibdev		Infiniband device
82
+ * @v qp		Queue pair
83
+ * @v gid		Multicast GID
84
+ * @ret rc		Return status code
85
+ */
86
+int ib_mcast_join ( struct ib_device *ibdev, struct ib_queue_pair *qp,
87
+		    struct ib_gid *gid ) {
88
+	int rc;
89
+
90
+	DBGC ( ibdev, "IBDEV %p QPN %lx joining %08x:%08x:%08x:%08x\n",
91
+	       ibdev, qp->qpn, ntohl ( gid->u.dwords[0] ),
92
+	       ntohl ( gid->u.dwords[1] ), ntohl ( gid->u.dwords[2] ),
93
+	       ntohl ( gid->u.dwords[3] ) );
94
+
95
+	/* Attach queue pair to multicast GID */
96
+	if ( ( rc = ib_mcast_attach ( ibdev, qp, gid ) ) != 0 ) {
97
+		DBGC ( ibdev, "IBDEV %p could not attach: %s\n",
98
+		       ibdev, strerror ( rc ) );
99
+		goto err_mcast_attach;
100
+	}
101
+
102
+	/* Initiate multicast membership join */
103
+	if ( ( rc = ib_mc_member_request ( ibdev, gid, 1 ) ) != 0 )
104
+		goto err_mc_member_record;
105
+
106
+	return 0;
107
+
108
+ err_mc_member_record:
109
+	ib_mcast_detach ( ibdev, qp, gid );
110
+ err_mcast_attach:
111
+	return rc;
112
+}
113
+
114
+/**
115
+ * Leave multicast group
116
+ *
117
+ * @v ibdev		Infiniband device
118
+ * @v qp		Queue pair
119
+ * @v gid		Multicast GID
120
+ */
121
+void ib_mcast_leave ( struct ib_device *ibdev, struct ib_queue_pair *qp,
122
+		      struct ib_gid *gid ) {
123
+
124
+	DBGC ( ibdev, "IBDEV %p QPN %lx leaving %08x:%08x:%08x:%08x\n",
125
+	       ibdev, qp->qpn, ntohl ( gid->u.dwords[0] ),
126
+	       ntohl ( gid->u.dwords[1] ), ntohl ( gid->u.dwords[2] ),
127
+	       ntohl ( gid->u.dwords[3] ) );
128
+
129
+	/* Detach queue pair from multicast GID */
130
+	ib_mcast_detach ( ibdev, qp, gid );
131
+
132
+	/* Initiate multicast membership leave */
133
+	ib_mc_member_request ( ibdev, gid, 0 );
134
+}
135
+
136
+/**
137
+ * Handle multicast membership record join response
138
+ *
139
+ * @v ibdev		Infiniband device
140
+ * @v mad		MAD
141
+ * @ret rc		Return status code
142
+ */
143
+static int ib_handle_mc_member_join ( struct ib_device *ibdev,
144
+				      union ib_mad *mad ) {
145
+	struct ib_mc_member_record *mc_member_record =
146
+		&mad->sa.sa_data.mc_member_record;
147
+	struct ib_queue_pair *qp;
148
+	struct ib_gid *gid;
149
+	unsigned long qkey;
150
+	int rc;
151
+
152
+	/* Ignore if not a success */
153
+	if ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ) {
154
+		DBGC ( ibdev, "IBDEV %p join failed with status %04x\n",
155
+		       ibdev, ntohs ( mad->hdr.status ) );
156
+		return -EINVAL;
157
+	}
158
+
159
+	/* Extract MAD parameters */
160
+	gid = &mc_member_record->mgid;
161
+	qkey = ntohl ( mc_member_record->qkey );
162
+
163
+	/* Locate matching queue pair */
164
+	qp = ib_find_qp_mgid ( ibdev, gid );
165
+	if ( ! qp ) {
166
+		DBGC ( ibdev, "IBDEV %p has no QP to join "
167
+		       "%08x:%08x:%08x:%08x\n", ibdev,
168
+		       ntohl ( gid->u.dwords[0] ),
169
+		       ntohl ( gid->u.dwords[1] ),
170
+		       ntohl ( gid->u.dwords[2] ),
171
+		       ntohl ( gid->u.dwords[3] ) );
172
+		return -ENOENT;
173
+	}
174
+	DBGC ( ibdev, "IBDEV %p QPN %lx joined %08x:%08x:%08x:%08x qkey "
175
+	       "%lx\n", ibdev, qp->qpn,
176
+	       ntohl ( gid->u.dwords[0] ), ntohl ( gid->u.dwords[1] ),
177
+	       ntohl ( gid->u.dwords[2] ), ntohl ( gid->u.dwords[3] ),
178
+	       qkey );
179
+
180
+	/* Set queue key */
181
+	if ( ( rc = ib_modify_qp ( ibdev, qp, IB_MODIFY_QKEY, qkey ) ) != 0 ) {
182
+		DBGC ( ibdev, "IBDEV %p QPN %lx could not modify qkey: %s\n",
183
+		       ibdev, qp->qpn, strerror ( rc ) );
184
+		return rc;
185
+	}
186
+
187
+	return 0;
188
+}
189
+
190
+/**
191
+ * Handle multicast membership record leave response
192
+ *
193
+ * @v ibdev		Infiniband device
194
+ * @v mad		MAD
195
+ * @ret rc		Return status code
196
+ */
197
+static int ib_handle_mc_member_leave ( struct ib_device *ibdev,
198
+				       union ib_mad *mad ) {
199
+	struct ib_mc_member_record *mc_member_record =
200
+		&mad->sa.sa_data.mc_member_record;
201
+	struct ib_gid *gid;
202
+
203
+	/* Ignore if not a success */
204
+	if ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ) {
205
+		DBGC ( ibdev, "IBDEV %p leave failed with status %04x\n",
206
+		       ibdev, ntohs ( mad->hdr.status ) );
207
+		return -EINVAL;
208
+	}
209
+
210
+	/* Extract MAD parameters */
211
+	gid = &mc_member_record->mgid;
212
+	DBGC ( ibdev, "IBDEV %p left %08x:%08x:%08x:%08x\n", ibdev,
213
+	       ntohl ( gid->u.dwords[0] ), ntohl ( gid->u.dwords[1] ),
214
+	       ntohl ( gid->u.dwords[2] ), ntohl ( gid->u.dwords[3] ) );
215
+
216
+	return 0;
217
+}
218
+
219
+/** Multicast membership record response handler */
220
+struct ib_mad_handler ib_mc_member_record_handlers[] __ib_mad_handler = {
221
+	{
222
+		.mgmt_class = IB_MGMT_CLASS_SUBN_ADM,
223
+		.class_version = IB_SA_CLASS_VERSION,
224
+		.method = IB_MGMT_METHOD_GET_RESP,
225
+		.attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC ),
226
+		.handle = ib_handle_mc_member_join,
227
+	},
228
+	{
229
+		.mgmt_class = IB_MGMT_CLASS_SUBN_ADM,
230
+		.class_version = IB_SA_CLASS_VERSION,
231
+		.method = IB_SA_METHOD_DELETE_RESP,
232
+		.attr_id = htons ( IB_SA_ATTR_MC_MEMBER_REC ),
233
+		.handle = ib_handle_mc_member_leave,
234
+	},
235
+};

Loading…
取消
儲存