iPXE
eoib.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016 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., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26#include <stdio.h>
27#include <string.h>
28#include <errno.h>
29#include <ipxe/errortab.h>
30#include <ipxe/malloc.h>
31#include <ipxe/iobuf.h>
32#include <ipxe/if_ether.h>
33#include <ipxe/netdevice.h>
34#include <ipxe/ethernet.h>
35#include <ipxe/infiniband.h>
36#include <ipxe/ib_mcast.h>
37#include <ipxe/ib_pathrec.h>
38#include <ipxe/eoib.h>
39
40/** @file
41 *
42 * Ethernet over Infiniband
43 *
44 */
45
46/** Number of EoIB send work queue entries */
47#define EOIB_NUM_SEND_WQES 8
48
49/** Number of EoIB receive work queue entries */
50#define EOIB_NUM_RECV_WQES 4
51
52/** Number of EoIB completion queue entries */
53#define EOIB_NUM_CQES 16
54
55/** Link status for "broadcast join in progress" */
56#define EINPROGRESS_JOINING __einfo_error ( EINFO_EINPROGRESS_JOINING )
57#define EINFO_EINPROGRESS_JOINING __einfo_uniqify \
58 ( EINFO_EINPROGRESS, 0x01, "Joining" )
59
60/** Human-readable message for the link status */
61struct errortab eoib_errors[] __errortab = {
63};
64
65/** List of EoIB devices */
66static LIST_HEAD ( eoib_devices );
67
69
70/****************************************************************************
71 *
72 * EoIB peer cache
73 *
74 ****************************************************************************
75 */
76
77/** An EoIB peer cache entry */
78struct eoib_peer {
79 /** List of EoIB peer cache entries */
81 /** Ethernet MAC */
83 /** Infiniband address vector */
85};
86
87/**
88 * Find EoIB peer cache entry
89 *
90 * @v eoib EoIB device
91 * @v mac Ethernet MAC
92 * @ret peer EoIB peer, or NULL if not found
93 */
94static struct eoib_peer * eoib_find_peer ( struct eoib_device *eoib,
95 const uint8_t *mac ) {
96 struct eoib_peer *peer;
97
98 /* Find peer cache entry */
99 list_for_each_entry ( peer, &eoib->peers, list ) {
100 if ( memcmp ( mac, peer->mac, sizeof ( peer->mac ) ) == 0 ) {
101 /* Move peer to start of list */
102 list_del ( &peer->list );
103 list_add ( &peer->list, &eoib->peers );
104 return peer;
105 }
106 }
107
108 return NULL;
109}
110
111/**
112 * Create EoIB peer cache entry
113 *
114 * @v eoib EoIB device
115 * @v mac Ethernet MAC
116 * @ret peer EoIB peer, or NULL on error
117 */
118static struct eoib_peer * eoib_create_peer ( struct eoib_device *eoib,
119 const uint8_t *mac ) {
120 struct eoib_peer *peer;
121
122 /* Allocate and initialise peer cache entry */
123 peer = zalloc ( sizeof ( *peer ) );
124 if ( peer ) {
125 memcpy ( peer->mac, mac, sizeof ( peer->mac ) );
126 list_add ( &peer->list, &eoib->peers );
127 }
128 return peer;
129}
130
131/**
132 * Flush EoIB peer cache
133 *
134 * @v eoib EoIB device
135 */
136static void eoib_flush_peers ( struct eoib_device *eoib ) {
137 struct eoib_peer *peer;
138 struct eoib_peer *tmp;
139
141 list_del ( &peer->list );
142 free ( peer );
143 }
144}
145
146/**
147 * Discard some entries from the peer cache
148 *
149 * @ret discarded Number of cached items discarded
150 */
151static unsigned int eoib_discard ( void ) {
152 struct net_device *netdev;
153 struct eoib_device *eoib;
154 struct eoib_peer *peer;
155 unsigned int discarded = 0;
156
157 /* Try to discard one cache entry for each EoIB device */
159
160 /* Skip non-EoIB devices */
161 if ( netdev->op != &eoib_operations )
162 continue;
163 eoib = netdev->priv;
164
165 /* Discard least recently used cache entry (if any) */
167 list_del ( &peer->list );
168 free ( peer );
169 discarded++;
170 break;
171 }
172 }
173
174 return discarded;
175}
176
177/** EoIB cache discarder */
179 .discard = eoib_discard,
180};
181
182/**
183 * Fill in destination address vector
184 *
185 * @v eoib EoIB device
186 * @v mac Ethernet MAC
187 * @v av Address vector to fill in
188 */
189static void eoib_tx_av ( struct eoib_device *eoib, const uint8_t *mac,
190 struct ib_address_vector *av ) {
191 struct ib_device *ibdev = eoib->ibdev;
192 struct eoib_peer *peer;
193 int rc;
194
195 /* If this is a broadcast or multicast MAC address, then send
196 * this packet as a broadcast.
197 */
198 if ( is_multicast_ether_addr ( mac ) ) {
199 DBGCP ( eoib, "EoIB %s %s TX multicast\n",
200 eoib->name, eth_ntoa ( mac ) );
201 goto multicast;
202 }
203
204 /* If we have no peer cache entry, then create one and send
205 * this packet as a broadcast.
206 */
207 peer = eoib_find_peer ( eoib, mac );
208 if ( ! peer ) {
209 DBGC ( eoib, "EoIB %s %s TX unknown\n",
210 eoib->name, eth_ntoa ( mac ) );
211 eoib_create_peer ( eoib, mac );
212 goto no_peer;
213 }
214
215 /* If we have not yet recorded a received GID and QPN for this
216 * peer cache entry, then send this packet as a broadcast.
217 */
218 if ( ! peer->av.gid_present ) {
219 DBGCP ( eoib, "EoIB %s %s TX not yet recorded\n",
220 eoib->name, eth_ntoa ( mac ) );
221 goto no_gid_qpn;
222 }
223
224 /* Peer cache entries may be freed by the cache discarder when
225 * we call a function that allocates memory. Create a local
226 * copy of the address vector.
227 */
228 memcpy ( av, &peer->av, sizeof ( *av ) );
229
230 /* If we have not yet resolved a path to this peer, then send
231 * this packet as a broadcast.
232 */
233 if ( ( rc = ib_resolve_path ( ibdev, av ) ) != 0 ) {
234 DBGCP ( eoib, "EoIB %s %s TX not yet resolved\n",
235 eoib->name, eth_ntoa ( mac ) );
236 goto not_resolved;
237 }
238
239 /* Force use of GRH even for local destinations */
240 av->gid_present = 1;
241
242 /* We have a fully resolved peer: send this packet as a
243 * unicast.
244 */
245 DBGCP ( eoib, "EoIB %s %s TX " IB_GID_FMT " QPN %#lx\n", eoib->name,
246 eth_ntoa ( mac ), IB_GID_ARGS ( &av->gid ), av->qpn );
247 return;
248
249 multicast:
250 no_peer:
251 no_gid_qpn:
252 not_resolved:
253 /* Send as broadcast */
254 memcpy ( av, &eoib->broadcast, sizeof ( *av ) );
255}
256
257/**
258 * Record source address vector
259 *
260 * @v eoib EoIB device
261 * @v mac Ethernet MAC
262 * @v av Address vector
263 */
264static void eoib_rx_av ( struct eoib_device *eoib, const uint8_t *mac,
265 const struct ib_address_vector *av ) {
266 const union ib_gid *gid = &av->gid;
267 unsigned long qpn = av->qpn;
268 struct eoib_peer *peer;
269
270 /* Sanity checks */
271 if ( ! av->gid_present ) {
272 DBGC ( eoib, "EoIB %s %s RX with no GID\n",
273 eoib->name, eth_ntoa ( mac ) );
274 return;
275 }
276
277 /* Find peer cache entry (if any) */
278 peer = eoib_find_peer ( eoib, mac );
279 if ( ! peer ) {
280 DBGCP ( eoib, "EoIB %s %s RX " IB_GID_FMT " (ignored)\n",
281 eoib->name, eth_ntoa ( mac ), IB_GID_ARGS ( gid ) );
282 return;
283 }
284
285 /* Some dubious EoIB implementations utilise an Ethernet-to-
286 * EoIB gateway that will send packets from the wrong QPN.
287 */
288 if ( eoib_has_gateway ( eoib ) &&
289 ( memcmp ( gid, &eoib->gateway.gid, sizeof ( *gid ) ) == 0 ) ) {
290 qpn = eoib->gateway.qpn;
291 }
292
293 /* Update peer cache entry */
294 if ( ( peer->av.qpn == qpn ) &&
295 ( memcmp ( &peer->av.gid, gid, sizeof ( *gid ) ) == 0 ) ) {
296 DBGCP ( eoib, "EoIB %s %s RX unchanged\n",
297 eoib->name, eth_ntoa ( mac ) );
298 } else {
299 DBGC ( eoib, "EoIB %s %s RX " IB_GID_FMT " QPN %#lx\n",
300 eoib->name, eth_ntoa ( mac ), IB_GID_ARGS ( gid ),
301 qpn );
302 }
303 peer->av.qpn = qpn;
304 peer->av.qkey = eoib->broadcast.qkey;
305 peer->av.gid_present = 1;
306 memcpy ( &peer->av.gid, gid, sizeof ( peer->av.gid ) );
307}
308
309/****************************************************************************
310 *
311 * EoIB network device
312 *
313 ****************************************************************************
314 */
315
316/**
317 * Transmit packet via EoIB network device
318 *
319 * @v netdev Network device
320 * @v iobuf I/O buffer
321 * @ret rc Return status code
322 */
323static int eoib_transmit ( struct net_device *netdev,
324 struct io_buffer *iobuf ) {
325 struct eoib_device *eoib = netdev->priv;
326 struct eoib_header *eoib_hdr;
327 struct ethhdr *ethhdr;
328 struct ib_address_vector av;
329 size_t zlen;
330
331 /* Sanity checks */
332 assert ( iob_len ( iobuf ) >= sizeof ( *ethhdr ) );
333 assert ( iob_headroom ( iobuf ) >= sizeof ( *eoib_hdr ) );
334
335 /* Look up destination address vector */
336 ethhdr = iobuf->data;
337 eoib_tx_av ( eoib, ethhdr->h_dest, &av );
338
339 /* Prepend EoIB header */
340 eoib_hdr = iob_push ( iobuf, sizeof ( *eoib_hdr ) );
341 eoib_hdr->magic = htons ( EOIB_MAGIC );
342 eoib_hdr->reserved = 0;
343
344 /* Pad buffer to minimum Ethernet frame size */
345 zlen = ( sizeof ( *eoib_hdr ) + ETH_ZLEN );
346 assert ( zlen <= IOB_ZLEN );
347 if ( iob_len ( iobuf ) < zlen )
348 iob_pad ( iobuf, zlen );
349
350 /* If this is being sent as a broadcast (for any reason), then
351 * send a duplicate to the gateway, if applicable
352 */
353 if ( ( av.qpn == IB_QPN_BROADCAST ) && eoib_has_gateway ( eoib ) )
354 eoib->duplicate ( eoib, iobuf );
355
356 /* Post send work queue entry */
357 return ib_post_send ( eoib->ibdev, eoib->qp, &av, iobuf );
358}
359
360/**
361 * Handle EoIB send completion
362 *
363 * @v ibdev Infiniband device
364 * @v qp Queue pair
365 * @v iobuf I/O buffer
366 * @v rc Completion status code
367 */
368static void eoib_complete_send ( struct ib_device *ibdev __unused,
369 struct ib_queue_pair *qp,
370 struct io_buffer *iobuf, int rc ) {
371 struct eoib_device *eoib = ib_qp_get_ownerdata ( qp );
372
373 netdev_tx_complete_err ( eoib->netdev, iobuf, rc );
374}
375
376/**
377 * Handle EoIB receive completion
378 *
379 * @v ibdev Infiniband device
380 * @v qp Queue pair
381 * @v dest Destination address vector, or NULL
382 * @v source Source address vector, or NULL
383 * @v iobuf I/O buffer
384 * @v rc Completion status code
385 */
387 struct ib_queue_pair *qp,
389 struct ib_address_vector *source,
390 struct io_buffer *iobuf, int rc ) {
391 struct eoib_device *eoib = ib_qp_get_ownerdata ( qp );
392 struct net_device *netdev = eoib->netdev;
393 struct eoib_header *eoib_hdr;
394 struct ethhdr *ethhdr;
395
396 /* Record errors */
397 if ( rc != 0 ) {
398 netdev_rx_err ( netdev, iobuf, rc );
399 return;
400 }
401
402 /* Sanity check */
403 if ( iob_len ( iobuf ) < ( sizeof ( *eoib_hdr ) + sizeof ( *ethhdr ) )){
404 DBGC ( eoib, "EoIB %s received packet too short to "
405 "contain EoIB and Ethernet headers\n", eoib->name );
406 DBGC_HD ( eoib, iobuf->data, iob_len ( iobuf ) );
407 netdev_rx_err ( netdev, iobuf, -EIO );
408 return;
409 }
410 if ( ! source ) {
411 DBGC ( eoib, "EoIB %s received packet without address "
412 "vector\n", eoib->name );
413 netdev_rx_err ( netdev, iobuf, -ENOTTY );
414 return;
415 }
416
417 /* Strip EoIB header */
418 iob_pull ( iobuf, sizeof ( *eoib_hdr ) );
419
420 /* Update neighbour cache entry, if any */
421 ethhdr = iobuf->data;
422 eoib_rx_av ( eoib, ethhdr->h_source, source );
423
424 /* Hand off to network layer */
425 netdev_rx ( netdev, iobuf );
426}
427
428/** EoIB completion operations */
430 .complete_send = eoib_complete_send,
431 .complete_recv = eoib_complete_recv,
432};
433
434/** EoIB queue pair operations */
436 .alloc_iob = alloc_iob,
437};
438
439/**
440 * Poll EoIB network device
441 *
442 * @v netdev Network device
443 */
444static void eoib_poll ( struct net_device *netdev ) {
445 struct eoib_device *eoib = netdev->priv;
446 struct ib_device *ibdev = eoib->ibdev;
447
448 /* Poll Infiniband device */
449 ib_poll_eq ( ibdev );
450
451 /* Poll the retry timers (required for EoIB multicast join) */
452 retry_poll();
453}
454
455/**
456 * Handle EoIB broadcast multicast group join completion
457 *
458 * @v membership Multicast group membership
459 * @v rc Status code
460 */
461static void eoib_join_complete ( struct ib_mc_membership *membership, int rc ) {
462 struct eoib_device *eoib =
464
465 /* Record join status as link status */
466 netdev_link_err ( eoib->netdev, rc );
467}
468
469/**
470 * Join EoIB broadcast multicast group
471 *
472 * @v eoib EoIB device
473 * @ret rc Return status code
474 */
475static int eoib_join_broadcast_group ( struct eoib_device *eoib ) {
476 int rc;
477
478 /* Join multicast group */
479 if ( ( rc = ib_mcast_join ( eoib->ibdev, eoib->qp,
480 &eoib->membership, &eoib->broadcast,
481 eoib->mask, eoib_join_complete ) ) != 0 ) {
482 DBGC ( eoib, "EoIB %s could not join broadcast group: %s\n",
483 eoib->name, strerror ( rc ) );
484 return rc;
485 }
486
487 return 0;
488}
489
490/**
491 * Leave EoIB broadcast multicast group
492 *
493 * @v eoib EoIB device
494 */
495static void eoib_leave_broadcast_group ( struct eoib_device *eoib ) {
496
497 /* Leave multicast group */
498 ib_mcast_leave ( eoib->ibdev, eoib->qp, &eoib->membership );
499}
500
501/**
502 * Handle link status change
503 *
504 * @v eoib EoIB device
505 */
506static void eoib_link_state_changed ( struct eoib_device *eoib ) {
507 struct net_device *netdev = eoib->netdev;
508 struct ib_device *ibdev = eoib->ibdev;
509 int rc;
510
511 /* Leave existing broadcast group */
512 if ( eoib->qp )
514
515 /* Update broadcast GID based on potentially-new partition key */
516 eoib->broadcast.gid.words[2] = htons ( ibdev->pkey | IB_PKEY_FULL );
517
518 /* Set net device link state to reflect Infiniband link state */
519 rc = ib_link_rc ( ibdev );
521
522 /* Join new broadcast group */
523 if ( ib_is_open ( ibdev ) && ib_link_ok ( ibdev ) && eoib->qp &&
524 ( ( rc = eoib_join_broadcast_group ( eoib ) ) != 0 ) ) {
525 DBGC ( eoib, "EoIB %s could not rejoin broadcast group: "
526 "%s\n", eoib->name, strerror ( rc ) );
528 return;
529 }
530}
531
532/**
533 * Open EoIB network device
534 *
535 * @v netdev Network device
536 * @ret rc Return status code
537 */
538static int eoib_open ( struct net_device *netdev ) {
539 struct eoib_device *eoib = netdev->priv;
540 struct ib_device *ibdev = eoib->ibdev;
541 int rc;
542
543 /* Open IB device */
544 if ( ( rc = ib_open ( ibdev ) ) != 0 ) {
545 DBGC ( eoib, "EoIB %s could not open %s: %s\n",
546 eoib->name, ibdev->name, strerror ( rc ) );
547 goto err_ib_open;
548 }
549
550 /* Allocate completion queue */
551 if ( ( rc = ib_create_cq ( ibdev, EOIB_NUM_CQES, &eoib_cq_op,
552 &eoib->cq ) ) != 0 ) {
553 DBGC ( eoib, "EoIB %s could not create completion queue: %s\n",
554 eoib->name, strerror ( rc ) );
555 goto err_create_cq;
556 }
557
558 /* Allocate queue pair */
559 if ( ( rc = ib_create_qp ( ibdev, IB_QPT_UD, EOIB_NUM_SEND_WQES,
560 eoib->cq, EOIB_NUM_RECV_WQES, eoib->cq,
561 &eoib_qp_op, netdev->name, &eoib->qp ) )!=0){
562 DBGC ( eoib, "EoIB %s could not create queue pair: %s\n",
563 eoib->name, strerror ( rc ) );
564 goto err_create_qp;
565 }
566 ib_qp_set_ownerdata ( eoib->qp, eoib );
567
568 /* Fill receive rings */
569 ib_refill_recv ( ibdev, eoib->qp );
570
571 /* Fake a link status change to join the broadcast group */
573
574 return 0;
575
576 ib_destroy_qp ( ibdev, eoib->qp );
577 eoib->qp = NULL;
578 err_create_qp:
579 ib_destroy_cq ( ibdev, eoib->cq );
580 eoib->cq = NULL;
581 err_create_cq:
582 ib_close ( ibdev );
583 err_ib_open:
584 return rc;
585}
586
587/**
588 * Close EoIB network device
589 *
590 * @v netdev Network device
591 */
592static void eoib_close ( struct net_device *netdev ) {
593 struct eoib_device *eoib = netdev->priv;
594 struct ib_device *ibdev = eoib->ibdev;
595
596 /* Flush peer cache */
597 eoib_flush_peers ( eoib );
598
599 /* Leave broadcast group */
601
602 /* Tear down the queues */
603 ib_destroy_qp ( ibdev, eoib->qp );
604 eoib->qp = NULL;
605 ib_destroy_cq ( ibdev, eoib->cq );
606 eoib->cq = NULL;
607
608 /* Close IB device */
609 ib_close ( ibdev );
610}
611
612/** EoIB network device operations */
614 .open = eoib_open,
615 .close = eoib_close,
616 .transmit = eoib_transmit,
617 .poll = eoib_poll,
618};
619
620/**
621 * Create EoIB device
622 *
623 * @v ibdev Infiniband device
624 * @v hw_addr Ethernet MAC
625 * @v broadcast Broadcast address vector
626 * @v name Interface name (or NULL to use default)
627 * @ret rc Return status code
628 */
629int eoib_create ( struct ib_device *ibdev, const uint8_t *hw_addr,
630 struct ib_address_vector *broadcast, const char *name ) {
631 struct net_device *netdev;
632 struct eoib_device *eoib;
633 int rc;
634
635 /* Allocate network device */
636 netdev = alloc_etherdev ( sizeof ( *eoib ) );
637 if ( ! netdev ) {
638 rc = -ENOMEM;
639 goto err_alloc;
640 }
642 eoib = netdev->priv;
643 netdev->dev = ibdev->dev;
644 eoib->netdev = netdev;
645 eoib->ibdev = ibdev_get ( ibdev );
646 memcpy ( &eoib->broadcast, broadcast, sizeof ( eoib->broadcast ) );
647 INIT_LIST_HEAD ( &eoib->peers );
648
649 /* Set MAC address */
650 memcpy ( netdev->hw_addr, hw_addr, ETH_ALEN );
651
652 /* Set interface name, if applicable */
653 if ( name )
654 snprintf ( netdev->name, sizeof ( netdev->name ), "%s", name );
655 eoib->name = netdev->name;
656
657 /* Add to list of EoIB devices */
658 list_add_tail ( &eoib->list, &eoib_devices );
659
660 /* Register network device */
661 if ( ( rc = register_netdev ( netdev ) ) != 0 )
662 goto err_register;
663
664 DBGC ( eoib, "EoIB %s created for %s MAC %s\n",
665 eoib->name, ibdev->name, eth_ntoa ( hw_addr ) );
666 DBGC ( eoib, "EoIB %s broadcast GID " IB_GID_FMT "\n",
667 eoib->name, IB_GID_ARGS ( &broadcast->gid ) );
668 return 0;
669
671 err_register:
672 list_del ( &eoib->list );
673 ibdev_put ( ibdev );
675 netdev_put ( netdev );
676 err_alloc:
677 return rc;
678}
679
680/**
681 * Find EoIB device
682 *
683 * @v ibdev Infiniband device
684 * @v hw_addr Original Ethernet MAC
685 * @ret eoib EoIB device
686 */
688 const uint8_t *hw_addr ) {
689 struct eoib_device *eoib;
690
691 list_for_each_entry ( eoib, &eoib_devices, list ) {
692 if ( ( eoib->ibdev == ibdev ) &&
693 ( memcmp ( eoib->netdev->hw_addr, hw_addr,
694 ETH_ALEN ) == 0 ) )
695 return eoib;
696 }
697 return NULL;
698}
699
700/**
701 * Remove EoIB device
702 *
703 * @v eoib EoIB device
704 */
705void eoib_destroy ( struct eoib_device *eoib ) {
706 struct net_device *netdev = eoib->netdev;
707
708 /* Unregister network device */
710
711 /* Remove from list of network devices */
712 list_del ( &eoib->list );
713
714 /* Drop reference to Infiniband device */
715 ibdev_put ( eoib->ibdev );
716
717 /* Free network device */
718 DBGC ( eoib, "EoIB %s destroyed\n", eoib->name );
720 netdev_put ( netdev );
721}
722
723/**
724 * Probe EoIB device
725 *
726 * @v ibdev Infiniband device
727 * @ret rc Return status code
728 */
729static int eoib_probe ( struct ib_device *ibdev __unused ) {
730
731 /* EoIB devices are not created automatically */
732 return 0;
733}
734
735/**
736 * Handle device or link status change
737 *
738 * @v ibdev Infiniband device
739 */
740static void eoib_notify ( struct ib_device *ibdev ) {
741 struct eoib_device *eoib;
742
743 /* Handle link status change for any attached EoIB devices */
744 list_for_each_entry ( eoib, &eoib_devices, list ) {
745 if ( eoib->ibdev != ibdev )
746 continue;
748 }
749}
750
751/**
752 * Remove EoIB device
753 *
754 * @v ibdev Infiniband device
755 */
756static void eoib_remove ( struct ib_device *ibdev ) {
757 struct eoib_device *eoib;
758 struct eoib_device *tmp;
759
760 /* Remove any attached EoIB devices */
761 list_for_each_entry_safe ( eoib, tmp, &eoib_devices, list ) {
762 if ( eoib->ibdev != ibdev )
763 continue;
764 eoib_destroy ( eoib );
765 }
766}
767
768/** EoIB driver */
769struct ib_driver eoib_driver __ib_driver = {
770 .name = "EoIB",
771 .probe = eoib_probe,
772 .notify = eoib_notify,
773 .remove = eoib_remove,
774};
775
776/****************************************************************************
777 *
778 * EoIB heartbeat packets
779 *
780 ****************************************************************************
781 */
782
783/**
784 * Silently ignore incoming EoIB heartbeat packets
785 *
786 * @v iobuf I/O buffer
787 * @v netdev Network device
788 * @v ll_source Link-layer source address
789 * @v flags Packet flags
790 * @ret rc Return status code
791 */
792static int eoib_heartbeat_rx ( struct io_buffer *iobuf,
793 struct net_device *netdev __unused,
794 const void *ll_dest __unused,
795 const void *ll_source __unused,
796 unsigned int flags __unused ) {
797 free_iob ( iobuf );
798 return 0;
799}
800
801/**
802 * Transcribe EoIB heartbeat address
803 *
804 * @v net_addr EoIB heartbeat address
805 * @ret string "<EoIB>"
806 *
807 * This operation is meaningless for the EoIB heartbeat protocol.
808 */
809static const char * eoib_heartbeat_ntoa ( const void *net_addr __unused ) {
810 return "<EoIB>";
811}
812
813/** EoIB heartbeat network protocol */
814struct net_protocol eoib_heartbeat_protocol __net_protocol = {
815 .name = "EoIB",
816 .net_proto = htons ( EOIB_MAGIC ),
817 .rx = eoib_heartbeat_rx,
818 .ntoa = eoib_heartbeat_ntoa,
819};
820
821/****************************************************************************
822 *
823 * EoIB gateway
824 *
825 ****************************************************************************
826 *
827 * Some dubious EoIB implementations require all broadcast traffic to
828 * be sent twice: once to the actual broadcast group, and once as a
829 * unicast to the EoIB-to-Ethernet gateway. This somewhat curious
830 * design arises since the EoIB-to-Ethernet gateway hardware lacks the
831 * ability to attach a queue pair to a multicast GID (or LID), and so
832 * cannot receive traffic sent to the broadcast group.
833 *
834 */
835
836/**
837 * Transmit duplicate packet to the EoIB gateway
838 *
839 * @v eoib EoIB device
840 * @v original Original I/O buffer
841 */
842static void eoib_duplicate ( struct eoib_device *eoib,
843 struct io_buffer *original ) {
844 struct net_device *netdev = eoib->netdev;
845 struct ib_device *ibdev = eoib->ibdev;
846 struct ib_address_vector *av = &eoib->gateway;
847 size_t len = iob_len ( original );
848 struct io_buffer *copy;
849 int rc;
850
851 /* Create copy of I/O buffer */
852 copy = alloc_iob ( len );
853 if ( ! copy ) {
854 rc = -ENOMEM;
855 goto err_alloc;
856 }
857 memcpy ( iob_put ( copy, len ), original->data, len );
858
859 /* Append to network device's transmit queue */
860 list_add_tail ( &copy->list, &original->list );
861
862 /* Resolve path to gateway */
863 if ( ( rc = ib_resolve_path ( ibdev, av ) ) != 0 ) {
864 DBGC ( eoib, "EoIB %s no path to gateway: %s\n",
865 eoib->name, strerror ( rc ) );
866 goto err_path;
867 }
868
869 /* Force use of GRH even for local destinations */
870 av->gid_present = 1;
871
872 /* Post send work queue entry */
873 if ( ( rc = ib_post_send ( eoib->ibdev, eoib->qp, av, copy ) ) != 0 )
874 goto err_post_send;
875
876 return;
877
878 err_post_send:
879 err_path:
880 list_del ( &copy->list );
881 err_alloc:
882 netdev_tx_err ( netdev, copy, rc );
883}
884
885/**
886 * Set EoIB gateway
887 *
888 * @v eoib EoIB device
889 * @v av Address vector, or NULL to clear gateway
890 */
891void eoib_set_gateway ( struct eoib_device *eoib,
892 struct ib_address_vector *av ) {
893
894 if ( av ) {
895 DBGC ( eoib, "EoIB %s using gateway " IB_GID_FMT "\n",
896 eoib->name, IB_GID_ARGS ( &av->gid ) );
897 memcpy ( &eoib->gateway, av, sizeof ( eoib->gateway ) );
899 } else {
900 DBGC ( eoib, "EoIB %s not using gateway\n", eoib->name );
901 eoib->duplicate = NULL;
902 }
903}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
u8 gid[16]
Definition CIB_PRM.h:3
__be32 qpn
Definition CIB_PRM.h:1
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
struct arbelprm_qp_db_record qp
Definition arbel.h:2
unsigned char uint8_t
Definition stdint.h:10
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
const char * name
Definition ath9k_hw.c:1986
ring len
Length.
Definition dwmac.h:226
uint8_t flags
Flags.
Definition ena.h:7
uint8_t mac[ETH_ALEN]
MAC address.
Definition ena.h:13
static int eoib_heartbeat_rx(struct io_buffer *iobuf, struct net_device *netdev __unused, const void *ll_dest __unused, const void *ll_source __unused, unsigned int flags __unused)
Silently ignore incoming EoIB heartbeat packets.
Definition eoib.c:792
static void eoib_complete_send(struct ib_device *ibdev __unused, struct ib_queue_pair *qp, struct io_buffer *iobuf, int rc)
Handle EoIB send completion.
Definition eoib.c:368
int eoib_create(struct ib_device *ibdev, const uint8_t *hw_addr, struct ib_address_vector *broadcast, const char *name)
Create EoIB device.
Definition eoib.c:629
static unsigned int eoib_discard(void)
Discard some entries from the peer cache.
Definition eoib.c:151
#define EINPROGRESS_JOINING
Link status for "broadcast join in progress".
Definition eoib.c:56
static void eoib_tx_av(struct eoib_device *eoib, const uint8_t *mac, struct ib_address_vector *av)
Fill in destination address vector.
Definition eoib.c:189
static void eoib_rx_av(struct eoib_device *eoib, const uint8_t *mac, const struct ib_address_vector *av)
Record source address vector.
Definition eoib.c:264
static void eoib_duplicate(struct eoib_device *eoib, struct io_buffer *original)
Transmit duplicate packet to the EoIB gateway.
Definition eoib.c:842
static void eoib_complete_recv(struct ib_device *ibdev __unused, struct ib_queue_pair *qp, struct ib_address_vector *dest __unused, struct ib_address_vector *source, struct io_buffer *iobuf, int rc)
Handle EoIB receive completion.
Definition eoib.c:386
#define EOIB_NUM_CQES
Number of EoIB completion queue entries.
Definition eoib.c:53
static const char * eoib_heartbeat_ntoa(const void *net_addr __unused)
Transcribe EoIB heartbeat address.
Definition eoib.c:809
static void eoib_link_state_changed(struct eoib_device *eoib)
Handle link status change.
Definition eoib.c:506
static void eoib_join_complete(struct ib_mc_membership *membership, int rc)
Handle EoIB broadcast multicast group join completion.
Definition eoib.c:461
static int eoib_transmit(struct net_device *netdev, struct io_buffer *iobuf)
Transmit packet via EoIB network device.
Definition eoib.c:323
static int eoib_probe(struct ib_device *ibdev __unused)
Probe EoIB device.
Definition eoib.c:729
struct eoib_device * eoib_find(struct ib_device *ibdev, const uint8_t *hw_addr)
Find EoIB device.
Definition eoib.c:687
static int eoib_join_broadcast_group(struct eoib_device *eoib)
Join EoIB broadcast multicast group.
Definition eoib.c:475
static struct eoib_peer * eoib_create_peer(struct eoib_device *eoib, const uint8_t *mac)
Create EoIB peer cache entry.
Definition eoib.c:118
static void eoib_poll(struct net_device *netdev)
Poll EoIB network device.
Definition eoib.c:444
static void eoib_leave_broadcast_group(struct eoib_device *eoib)
Leave EoIB broadcast multicast group.
Definition eoib.c:495
static struct eoib_peer * eoib_find_peer(struct eoib_device *eoib, const uint8_t *mac)
Find EoIB peer cache entry.
Definition eoib.c:94
static void eoib_flush_peers(struct eoib_device *eoib)
Flush EoIB peer cache.
Definition eoib.c:136
static void eoib_close(struct net_device *netdev)
Close EoIB network device.
Definition eoib.c:592
static struct ib_queue_pair_operations eoib_qp_op
EoIB queue pair operations.
Definition eoib.c:435
static void eoib_notify(struct ib_device *ibdev)
Handle device or link status change.
Definition eoib.c:740
static void eoib_remove(struct ib_device *ibdev)
Remove EoIB device.
Definition eoib.c:756
static struct net_device_operations eoib_operations
EoIB network device operations.
Definition eoib.c:68
#define EOIB_NUM_SEND_WQES
Number of EoIB send work queue entries.
Definition eoib.c:47
#define EINFO_EINPROGRESS_JOINING
Definition eoib.c:57
void eoib_set_gateway(struct eoib_device *eoib, struct ib_address_vector *av)
Set EoIB gateway.
Definition eoib.c:891
void eoib_destroy(struct eoib_device *eoib)
Remove EoIB device.
Definition eoib.c:705
#define EOIB_NUM_RECV_WQES
Number of EoIB receive work queue entries.
Definition eoib.c:50
static int eoib_open(struct net_device *netdev)
Open EoIB network device.
Definition eoib.c:538
static struct ib_completion_queue_operations eoib_cq_op
EoIB completion operations.
Definition eoib.c:429
Ethernet over Infiniband.
static int eoib_has_gateway(struct eoib_device *eoib)
Check if EoIB device uses a gateway.
Definition eoib.h:71
#define EOIB_MAGIC
EoIB magic signature.
Definition eoib.h:27
Error codes.
Error message tables.
#define __errortab
Definition errortab.h:22
#define __einfo_errortab(einfo)
Definition errortab.h:24
struct net_device * alloc_etherdev(size_t priv_size)
Allocate Ethernet device.
Definition ethernet.c:266
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition ethernet.c:177
Ethernet protocol.
static int is_multicast_ether_addr(const void *addr)
Check if Ethernet address is a multicast address.
Definition ethernet.h:38
static struct net_device * netdev
Definition gdbudp.c:53
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:598
#define CACHE_EXPENSIVE
Items with a high replacement cost.
Definition malloc.h:115
#define DBGCP(...)
Definition compiler.h:564
#define DBGC_HD(...)
Definition compiler.h:532
#define DBGC(...)
Definition compiler.h:530
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:921
#define ENOMEM
Not enough space.
Definition errno.h:578
#define EIO
Input/output error.
Definition errno.h:477
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:638
int ib_mcast_join(struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_mc_membership *membership, struct ib_address_vector *av, unsigned int mask, void(*complete)(struct ib_mc_membership *membership, int rc))
Join multicast group.
Definition ib_mcast.c:152
void ib_mcast_leave(struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_mc_membership *membership)
Leave multicast group.
Definition ib_mcast.c:209
Infiniband multicast groups.
#define IB_GID_ARGS(gid)
Infiniband Global Identifier debug message arguments.
Definition ib_packet.h:49
#define IB_GID_FMT
Infiniband Global Identifier debug message format.
Definition ib_packet.h:46
int ib_resolve_path(struct ib_device *ibdev, struct ib_address_vector *av)
Resolve path.
Definition ib_pathrec.c:249
Infiniband path records.
#define ETH_ZLEN
Definition if_ether.h:11
#define ETH_ALEN
Definition if_ether.h:9
#define htons(value)
Definition byteswap.h:136
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void ib_refill_recv(struct ib_device *ibdev, struct ib_queue_pair *qp)
Refill receive work queue.
Definition infiniband.c:556
void ib_destroy_cq(struct ib_device *ibdev, struct ib_completion_queue *cq)
Destroy completion queue.
Definition infiniband.c:145
int ib_create_cq(struct ib_device *ibdev, unsigned int num_cqes, struct ib_completion_queue_operations *op, struct ib_completion_queue **new_cq)
Create completion queue.
Definition infiniband.c:98
int ib_open(struct ib_device *ibdev)
Open port.
Definition infiniband.c:652
int ib_link_rc(struct ib_device *ibdev)
Get link state.
Definition infiniband.c:594
int ib_post_send(struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_address_vector *dest, struct io_buffer *iobuf)
Post send work queue entry.
Definition infiniband.c:416
void ib_poll_eq(struct ib_device *ibdev)
Poll event queue.
Definition infiniband.c:878
void ib_close(struct ib_device *ibdev)
Close port.
Definition infiniband.c:716
void ib_destroy_qp(struct ib_device *ibdev, struct ib_queue_pair *qp)
Destroy queue pair.
Definition infiniband.c:314
int ib_create_qp(struct ib_device *ibdev, enum ib_queue_pair_type type, unsigned int num_send_wqes, struct ib_completion_queue *send_cq, unsigned int num_recv_wqes, struct ib_completion_queue *recv_cq, struct ib_queue_pair_operations *op, const char *name, struct ib_queue_pair **new_qp)
Create queue pair.
Definition infiniband.c:199
Infiniband protocol.
#define IB_PKEY_FULL
Infiniband partition key full membership flag.
Definition infiniband.h:43
static __always_inline int ib_link_ok(struct ib_device *ibdev)
Check link state of Infiniband device.
Definition infiniband.h:566
#define __ib_driver
Declare an Infiniband driver.
Definition infiniband.h:497
static __always_inline void * ib_qp_get_ownerdata(struct ib_queue_pair *qp)
Get Infiniband queue pair owner-private data.
Definition infiniband.h:665
static __always_inline struct ib_device * ibdev_get(struct ib_device *ibdev)
Get reference to Infiniband device.
Definition infiniband.h:588
static __always_inline void ib_qp_set_ownerdata(struct ib_queue_pair *qp, void *priv)
Set Infiniband queue pair owner-private data.
Definition infiniband.h:654
#define IB_QPN_BROADCAST
Broadcast QPN.
Definition infiniband.h:34
@ IB_QPT_UD
Definition infiniband.h:142
static int ib_is_open(struct ib_device *ibdev)
Check whether or not Infiniband device is open.
Definition infiniband.h:577
static __always_inline void ibdev_put(struct ib_device *ibdev)
Drop reference to Infiniband device.
Definition infiniband.h:599
void iob_pad(struct io_buffer *iobuf, size_t min_len)
Pad I/O buffer.
Definition iobpad.c:50
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition iobuf.c:131
I/O buffers.
static size_t iob_headroom(struct io_buffer *iobuf)
Calculate available space at start of an I/O buffer.
Definition iobuf.h:230
#define iob_push(iobuf, len)
Definition iobuf.h:149
#define IOB_ZLEN
Minimum I/O buffer length and alignment.
Definition iobuf.h:29
#define iob_put(iobuf, len)
Definition iobuf.h:185
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:220
#define iob_pull(iobuf, len)
Definition iobuf.h:167
unsigned long tmp
Definition linux_pci.h:65
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
#define LIST_HEAD(list)
Declare a static list head.
Definition list.h:38
#define list_for_each_entry_reverse(pos, head, member)
Iterate over entries in a list in reverse order.
Definition list.h:445
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:718
Dynamic memory allocation.
#define __cache_discarder(cost)
Declare a cache discarder.
Definition malloc.h:106
struct mschapv2_challenge peer
Peer challenge.
Definition mschapv2.h:1
void netdev_link_err(struct net_device *netdev, int rc)
Mark network device as having a specific link state.
Definition netdevice.c:208
void netdev_rx(struct net_device *netdev, struct io_buffer *iobuf)
Add packet to receive queue.
Definition netdevice.c:549
void netdev_tx_err(struct net_device *netdev, struct io_buffer *iobuf, int rc)
Discard transmitted packet.
Definition netdevice.c:441
void unregister_netdev(struct net_device *netdev)
Unregister network device.
Definition netdevice.c:946
void netdev_tx_complete_err(struct net_device *netdev, struct io_buffer *iobuf, int rc)
Complete network transmission.
Definition netdevice.c:471
void netdev_rx_err(struct net_device *netdev, struct io_buffer *iobuf, int rc)
Discard received packet.
Definition netdevice.c:587
int register_netdev(struct net_device *netdev)
Register network device.
Definition netdevice.c:760
Network device management.
#define for_each_netdev(netdev)
Iterate over all network devices.
Definition netdevice.h:550
static void netdev_init(struct net_device *netdev, struct net_device_operations *op)
Initialise a network device.
Definition netdevice.h:522
static void netdev_nullify(struct net_device *netdev)
Stop using a network device.
Definition netdevice.h:535
static void netdev_put(struct net_device *netdev)
Drop reference to network device.
Definition netdevice.h:579
#define __net_protocol
Declare a network-layer protocol.
Definition netdevice.h:477
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
void retry_poll(void)
Poll the retry timer list.
Definition retry.c:198
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
A cache discarder.
Definition malloc.h:93
An EoIB device.
Definition eoib.h:30
struct list_head peers
Peer cache.
Definition eoib.h:50
unsigned int mask
Multicast group additional component mask.
Definition eoib.h:62
void(* duplicate)(struct eoib_device *eoib, struct io_buffer *original)
Send duplicate packet to gateway (or NULL).
Definition eoib.h:57
struct ib_address_vector broadcast
Broadcast address.
Definition eoib.h:40
struct ib_queue_pair * qp
Queue pair.
Definition eoib.h:45
struct ib_device * ibdev
Underlying Infiniband device.
Definition eoib.h:36
struct ib_address_vector gateway
Gateway (if any).
Definition eoib.h:60
const char * name
Name.
Definition eoib.h:32
struct list_head list
List of EoIB devices.
Definition eoib.h:38
struct ib_mc_membership membership
Broadcast group membership.
Definition eoib.h:47
struct ib_completion_queue * cq
Completion queue.
Definition eoib.h:43
struct net_device * netdev
Network device.
Definition eoib.h:34
An EoIB header.
Definition eoib.h:19
uint16_t reserved
Reserved.
Definition eoib.h:23
uint16_t magic
Signature.
Definition eoib.h:21
An EoIB peer cache entry.
Definition eoib.c:78
struct ib_address_vector av
Infiniband address vector.
Definition eoib.c:84
struct list_head list
List of EoIB peer cache entries.
Definition eoib.c:80
uint8_t mac[ETH_ALEN]
Ethernet MAC.
Definition eoib.c:82
An Ethernet link-layer header.
Definition if_ether.h:32
uint8_t h_dest[ETH_ALEN]
Destination MAC address.
Definition if_ether.h:34
uint8_t h_source[ETH_ALEN]
Source MAC address.
Definition if_ether.h:36
An Infiniband Address Vector.
Definition infiniband.h:73
unsigned long qkey
Queue key.
Definition infiniband.h:80
unsigned int gid_present
GID is present.
Definition infiniband.h:91
union ib_gid gid
GID, if present.
Definition infiniband.h:93
unsigned long qpn
Queue Pair Number.
Definition infiniband.h:75
Infiniband completion queue operations.
Definition infiniband.h:195
An Infiniband device.
Definition infiniband.h:399
char name[IBDEV_NAME_LEN]
Name of this Infiniband device.
Definition infiniband.h:409
uint16_t pkey
Partition key.
Definition infiniband.h:450
struct device * dev
Underlying device.
Definition infiniband.h:411
An Infiniband upper-layer driver.
Definition infiniband.h:472
An Infiniband multicast group membership.
Definition ib_mcast.h:17
Infiniband queue pair operations.
Definition infiniband.h:148
An Infiniband Queue Pair.
Definition infiniband.h:158
A persistent I/O buffer.
Definition iobuf.h:98
void * data
Start of data.
Definition iobuf.h:113
struct list_head list
List of which this buffer is a member.
Definition iobuf.h:105
A doubly-linked list entry (or list head).
Definition list.h:19
Network device operations.
Definition netdevice.h:214
A network device.
Definition netdevice.h:353
uint8_t hw_addr[MAX_HW_ADDR_LEN]
Hardware address.
Definition netdevice.h:382
A network-layer protocol.
Definition netdevice.h:65
An Infiniband Global Identifier.
Definition ib_packet.h:34
uint16_t words[8]
Definition ib_packet.h:36
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383