|
@@ -86,6 +86,32 @@ struct ipoib_device {
|
86
|
86
|
struct ipoib_queue_set meta;
|
87
|
87
|
};
|
88
|
88
|
|
|
89
|
+/**
|
|
90
|
+ * IPoIB path cache entry
|
|
91
|
+ *
|
|
92
|
+ * This serves a similar role to the ARP cache for Ethernet. (ARP
|
|
93
|
+ * *is* used on IPoIB; we have two caches to maintain.)
|
|
94
|
+ */
|
|
95
|
+struct ipoib_cached_path {
|
|
96
|
+ /** Destination GID */
|
|
97
|
+ struct ib_gid gid;
|
|
98
|
+ /** Destination LID */
|
|
99
|
+ unsigned int dlid;
|
|
100
|
+ /** Service level */
|
|
101
|
+ unsigned int sl;
|
|
102
|
+ /** Rate */
|
|
103
|
+ unsigned int rate;
|
|
104
|
+};
|
|
105
|
+
|
|
106
|
+/** Number of IPoIB path cache entries */
|
|
107
|
+#define IPOIB_NUM_CACHED_PATHS 2
|
|
108
|
+
|
|
109
|
+/** IPoIB path cache */
|
|
110
|
+static struct ipoib_cached_path ipoib_path_cache[IPOIB_NUM_CACHED_PATHS];
|
|
111
|
+
|
|
112
|
+/** Oldest IPoIB path cache entry index */
|
|
113
|
+static unsigned int ipoib_path_cache_idx = 0;
|
|
114
|
+
|
89
|
115
|
/****************************************************************************
|
90
|
116
|
*
|
91
|
117
|
* IPoIB link layer
|
|
@@ -165,15 +191,15 @@ static int ipoib_rx ( struct io_buffer *iobuf, struct net_device *netdev ) {
|
165
|
191
|
* @ret string Link-layer address in human-readable format
|
166
|
192
|
*/
|
167
|
193
|
const char * ipoib_ntoa ( const void *ll_addr ) {
|
168
|
|
- static char buf[61];
|
169
|
|
- const uint8_t *ipoib_addr = ll_addr;
|
170
|
|
- unsigned int i;
|
171
|
|
- char *p = buf;
|
172
|
|
-
|
173
|
|
- for ( i = 0 ; i < IPOIB_ALEN ; i++ ) {
|
174
|
|
- p += sprintf ( p, ":%02x", ipoib_addr[i] );
|
175
|
|
- }
|
176
|
|
- return ( buf + 1 );
|
|
194
|
+ static char buf[45];
|
|
195
|
+ const struct ipoib_mac *mac = ll_addr;
|
|
196
|
+
|
|
197
|
+ snprintf ( buf, sizeof ( buf ), "%08lx:%08lx:%08lx:%08lx:%08lx",
|
|
198
|
+ htonl ( mac->qpn ), htonl ( mac->gid.u.dwords[0] ),
|
|
199
|
+ htonl ( mac->gid.u.dwords[1] ),
|
|
200
|
+ htonl ( mac->gid.u.dwords[2] ),
|
|
201
|
+ htonl ( mac->gid.u.dwords[3] ) );
|
|
202
|
+ return buf;
|
177
|
203
|
}
|
178
|
204
|
|
179
|
205
|
/** IPoIB protocol */
|
|
@@ -258,6 +284,28 @@ static int ipoib_create_qset ( struct ipoib_device *ipoib,
|
258
|
284
|
return rc;
|
259
|
285
|
}
|
260
|
286
|
|
|
287
|
+/**
|
|
288
|
+ * Find path cache entry by GID
|
|
289
|
+ *
|
|
290
|
+ * @v gid GID
|
|
291
|
+ * @ret entry Path cache entry, or NULL
|
|
292
|
+ */
|
|
293
|
+static struct ipoib_cached_path *
|
|
294
|
+ipoib_find_cached_path ( struct ib_gid *gid ) {
|
|
295
|
+ struct ipoib_cached_path *path;
|
|
296
|
+ unsigned int i;
|
|
297
|
+
|
|
298
|
+ for ( i = 0 ; i < IPOIB_NUM_CACHED_PATHS ; i++ ) {
|
|
299
|
+ path = &ipoib_path_cache[i];
|
|
300
|
+ if ( memcmp ( &path->gid, gid, sizeof ( *gid ) ) == 0 )
|
|
301
|
+ return path;
|
|
302
|
+ }
|
|
303
|
+ DBG ( "IPoIB %08lx:%08lx:%08lx:%08lx cache miss\n",
|
|
304
|
+ htonl ( gid->u.dwords[0] ), htonl ( gid->u.dwords[1] ),
|
|
305
|
+ htonl ( gid->u.dwords[2] ), htonl ( gid->u.dwords[3] ) );
|
|
306
|
+ return NULL;
|
|
307
|
+}
|
|
308
|
+
|
261
|
309
|
/**
|
262
|
310
|
* Transmit path record request
|
263
|
311
|
*
|
|
@@ -274,17 +322,15 @@ static int ipoib_get_path_record ( struct ipoib_device *ipoib,
|
274
|
322
|
static uint32_t tid = 0;
|
275
|
323
|
int rc;
|
276
|
324
|
|
277
|
|
-#if 0
|
278
|
|
- DBG ( "get_path_record():\n" );
|
279
|
325
|
int get_path_record(struct ib_gid *dgid, uint16_t *dlid_p,
|
280
|
326
|
uint8_t *sl_p, uint8_t *rate_p);
|
281
|
327
|
uint16_t tmp_dlid;
|
282
|
328
|
uint8_t tmp_sl;
|
283
|
329
|
uint8_t tmp_rate;
|
284
|
330
|
get_path_record ( gid, &tmp_dlid, &tmp_sl, &tmp_rate );
|
|
331
|
+ DBG ( "get_path_record() gives dlid = %04x, sl = %02x, rate = %02x\n",
|
|
332
|
+ tmp_dlid, tmp_sl, tmp_rate );
|
285
|
333
|
|
286
|
|
- DBG ( "ipoib_get_path_record():\n" );
|
287
|
|
-#endif
|
288
|
334
|
|
289
|
335
|
/* Allocate I/O buffer */
|
290
|
336
|
iobuf = alloc_iob ( sizeof ( *path_record ) );
|
|
@@ -307,13 +353,11 @@ static int ipoib_get_path_record ( struct ipoib_device *ipoib,
|
307
|
353
|
memcpy ( &path_record->sgid, &ibdev->port_gid,
|
308
|
354
|
sizeof ( path_record->sgid ) );
|
309
|
355
|
|
310
|
|
- // DBG_HD ( path_record, sizeof ( *path_record ) );
|
311
|
|
-
|
312
|
356
|
/* Construct address vector */
|
313
|
357
|
memset ( &av, 0, sizeof ( av ) );
|
314
|
358
|
av.dlid = ibdev->sm_lid;
|
315
|
359
|
av.dest_qp = IB_SA_QPN;
|
316
|
|
- av.qkey = IB_SA_QKEY;
|
|
360
|
+ av.qkey = IB_GLOBAL_QKEY;
|
317
|
361
|
|
318
|
362
|
/* Post send request */
|
319
|
363
|
if ( ( rc = ib_post_send ( ibdev, ipoib->meta.qp, &av,
|
|
@@ -339,6 +383,8 @@ static int ipoib_transmit ( struct net_device *netdev,
|
339
|
383
|
struct ipoib_device *ipoib = netdev->priv;
|
340
|
384
|
struct ib_device *ibdev = ipoib->ibdev;
|
341
|
385
|
struct ipoib_pseudo_hdr *ipoib_pshdr = iobuf->data;
|
|
386
|
+ struct ib_address_vector av;
|
|
387
|
+ struct ipoib_cached_path *path;
|
342
|
388
|
int rc;
|
343
|
389
|
|
344
|
390
|
if ( iob_len ( iobuf ) < sizeof ( *ipoib_pshdr ) ) {
|
|
@@ -346,18 +392,32 @@ static int ipoib_transmit ( struct net_device *netdev,
|
346
|
392
|
return -EINVAL;
|
347
|
393
|
}
|
348
|
394
|
|
349
|
|
- DBG ( "TX pseudo-header:\n" );
|
350
|
|
- DBG_HD ( ipoib_pshdr, sizeof ( *ipoib_pshdr ) );
|
351
|
|
- if ( ipoib_pshdr->peer.qpn != htonl ( IPOIB_BROADCAST_QPN ) ) {
|
352
|
|
- DBG ( "Get path record\n" );
|
353
|
|
- rc = ipoib_get_path_record ( ipoib, &ipoib_pshdr->peer.gid );
|
354
|
|
- free_iob ( iobuf );
|
355
|
|
- return 0;
|
|
395
|
+ /* Construct address vector */
|
|
396
|
+ memset ( &av, 0, sizeof ( av ) );
|
|
397
|
+ if ( ipoib_pshdr->peer.qpn == htonl ( IPOIB_BROADCAST_QPN ) ) {
|
|
398
|
+ /* Broadcast address */
|
|
399
|
+ memcpy ( &av, &hack_ipoib_bcast_av, sizeof ( av ) );
|
|
400
|
+ } else {
|
|
401
|
+ /* Unicast - look in path cache */
|
|
402
|
+ path = ipoib_find_cached_path ( &ipoib_pshdr->peer.gid );
|
|
403
|
+ if ( ! path ) {
|
|
404
|
+ /* No path entry - get path record */
|
|
405
|
+ rc = ipoib_get_path_record ( ipoib,
|
|
406
|
+ &ipoib_pshdr->peer.gid );
|
|
407
|
+ free_iob ( iobuf );
|
|
408
|
+ return rc;
|
|
409
|
+ }
|
|
410
|
+ av.dest_qp = ntohl ( ipoib_pshdr->peer.qpn );
|
|
411
|
+ av.qkey = IB_GLOBAL_QKEY;
|
|
412
|
+ av.dlid = path->dlid;
|
|
413
|
+ av.rate = path->rate;
|
|
414
|
+ av.sl = path->sl;
|
|
415
|
+ av.gid_present = 1;
|
|
416
|
+ memcpy ( &av.gid, &ipoib_pshdr->peer.gid, sizeof ( av.gid ) );
|
356
|
417
|
}
|
357
|
418
|
|
358
|
419
|
iob_pull ( iobuf, ( sizeof ( *ipoib_pshdr ) ) );
|
359
|
|
- return ib_post_send ( ibdev, ipoib->data.qp,
|
360
|
|
- &hack_ipoib_bcast_av, iobuf );
|
|
420
|
+ return ib_post_send ( ibdev, ipoib->data.qp, &av, iobuf );
|
361
|
421
|
}
|
362
|
422
|
|
363
|
423
|
/**
|
|
@@ -392,14 +452,13 @@ static void ipoib_data_complete_recv ( struct ib_device *ibdev __unused,
|
392
|
452
|
struct io_buffer *iobuf ) {
|
393
|
453
|
struct net_device *netdev = qp->owner_priv;
|
394
|
454
|
struct ipoib_device *ipoib = netdev->priv;
|
395
|
|
- struct ib_global_route_header *grh = iobuf->data;
|
396
|
455
|
struct ipoib_pseudo_hdr *ipoib_pshdr;
|
397
|
456
|
|
398
|
457
|
if ( completion->syndrome ) {
|
399
|
458
|
netdev_rx_err ( netdev, iobuf, -EIO );
|
400
|
459
|
} else {
|
401
|
460
|
iob_put ( iobuf, completion->len );
|
402
|
|
- iob_pull ( iobuf, ( sizeof ( *grh ) -
|
|
461
|
+ iob_pull ( iobuf, ( sizeof ( struct ib_global_route_header ) -
|
403
|
462
|
sizeof ( *ipoib_pshdr ) ) );
|
404
|
463
|
/* FIXME: fill in a MAC address for the sake of AoE! */
|
405
|
464
|
netdev_rx ( netdev, iobuf );
|
|
@@ -444,16 +503,38 @@ static void ipoib_meta_complete_recv ( struct ib_device *ibdev __unused,
|
444
|
503
|
struct io_buffer *iobuf ) {
|
445
|
504
|
struct net_device *netdev = qp->owner_priv;
|
446
|
505
|
struct ipoib_device *ipoib = netdev->priv;
|
447
|
|
-
|
448
|
|
- DBG ( "***************** META RX!!!!!! ********\n" );
|
|
506
|
+ struct ib_mad_path_record *path_record;
|
|
507
|
+ struct ipoib_cached_path *path;
|
449
|
508
|
|
450
|
509
|
if ( completion->syndrome ) {
|
451
|
510
|
DBGC ( ipoib, "IPoIB %p metadata RX completion error %x\n",
|
452
|
511
|
ipoib, completion->syndrome );
|
453
|
512
|
} else {
|
|
513
|
+ /* Update path cache */
|
454
|
514
|
iob_put ( iobuf, completion->len );
|
|
515
|
+ iob_pull ( iobuf, sizeof ( struct ib_global_route_header ) );
|
|
516
|
+
|
455
|
517
|
DBG ( "Metadata RX:\n" );
|
456
|
518
|
DBG_HD ( iobuf->data, iob_len ( iobuf ) );
|
|
519
|
+
|
|
520
|
+ path_record = iobuf->data;
|
|
521
|
+ path = &ipoib_path_cache[ipoib_path_cache_idx];
|
|
522
|
+ memcpy ( &path->gid, &path_record->dgid,
|
|
523
|
+ sizeof ( path->gid ) );
|
|
524
|
+ path->dlid = ntohs ( path_record->dlid );
|
|
525
|
+ path->sl = ( path_record->reserved__sl & 0x0f );
|
|
526
|
+ path->rate = ( path_record->rate_selector__rate & 0x3f );
|
|
527
|
+ DBG ( "IPoIB %08lx:%08lx:%08lx:%08lx dlid %x sl %x rate %x\n",
|
|
528
|
+ htonl ( path->gid.u.dwords[0] ),
|
|
529
|
+ htonl ( path->gid.u.dwords[1] ),
|
|
530
|
+ htonl ( path->gid.u.dwords[2] ),
|
|
531
|
+ htonl ( path->gid.u.dwords[3] ),
|
|
532
|
+ path->dlid, path->sl, path->rate );
|
|
533
|
+
|
|
534
|
+ /* Update path cache index */
|
|
535
|
+ ipoib_path_cache_idx++;
|
|
536
|
+ if ( ipoib_path_cache_idx == IPOIB_NUM_CACHED_PATHS )
|
|
537
|
+ ipoib_path_cache_idx = 0;
|
457
|
538
|
}
|
458
|
539
|
|
459
|
540
|
ipoib->meta.recv_fill--;
|
|
@@ -590,7 +671,7 @@ int ipoib_probe ( struct ib_device *ibdev ) {
|
590
|
671
|
IPOIB_META_NUM_CQES,
|
591
|
672
|
IPOIB_META_NUM_SEND_WQES,
|
592
|
673
|
IPOIB_META_NUM_RECV_WQES,
|
593
|
|
- IB_SA_QKEY ) ) != 0 ) {
|
|
674
|
+ IB_GLOBAL_QKEY ) ) != 0 ) {
|
594
|
675
|
DBGC ( ipoib, "IPoIB %p could not allocate metadata QP: %s\n",
|
595
|
676
|
ipoib, strerror ( rc ) );
|
596
|
677
|
goto err_create_meta_qset;
|