2 * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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.
19 FILE_LICENCE ( GPL2_OR_LATER
);
27 #include <gpxe/errortab.h>
28 #include <gpxe/if_arp.h>
29 #include <gpxe/iobuf.h>
30 #include <gpxe/netdevice.h>
31 #include <gpxe/infiniband.h>
32 #include <gpxe/ib_pathrec.h>
33 #include <gpxe/ib_mcast.h>
34 #include <gpxe/ipoib.h>
41 /** Number of IPoIB send work queue entries */
42 #define IPOIB_NUM_SEND_WQES 2
44 /** Number of IPoIB receive work queue entries */
45 #define IPOIB_NUM_RECV_WQES 4
47 /** Number of IPoIB completion entries */
48 #define IPOIB_NUM_CQES 8
50 /** An IPoIB device */
53 struct net_device
*netdev
;
54 /** Underlying Infiniband device */
55 struct ib_device
*ibdev
;
56 /** Completion queue */
57 struct ib_completion_queue
*cq
;
59 struct ib_queue_pair
*qp
;
61 struct ipoib_mac broadcast
;
62 /** Joined to IPv4 broadcast multicast group
64 * This flag indicates whether or not we have initiated the
65 * join to the IPv4 broadcast multicast group.
68 /** IPv4 broadcast multicast group membership */
69 struct ib_mc_membership broadcast_membership
;
72 /** Broadcast IPoIB address */
73 static struct ipoib_mac ipoib_broadcast
= {
74 .flags__qpn
= htonl ( IB_QPN_BROADCAST
),
75 .gid
.u
.bytes
= { 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff },
79 /** Link status for "broadcast join in progress" */
80 #define EINPROGRESS_JOINING __einfo_error ( EINFO_EINPROGRESS_JOINING )
81 #define EINFO_EINPROGRESS_JOINING __einfo_uniqify \
82 ( EINFO_EINPROGRESS, 0x01, "Joining" )
84 /** Human-readable message for the link status */
85 struct errortab ipoib_errors
[] __errortab
= {
86 __einfo_errortab ( EINFO_EINPROGRESS_JOINING
),
89 /****************************************************************************
93 ****************************************************************************
99 * The IPoIB link-layer header is only four bytes long and so does not
100 * have sufficient room to store IPoIB MAC address(es). We therefore
101 * maintain a cache of MAC addresses identified by a single-byte key,
102 * and abuse the spare two bytes within the link-layer header to
103 * communicate these MAC addresses between the link-layer code and the
110 struct ipoib_mac mac
;
113 /** Number of IPoIB peer cache entries
115 * Must be a power of two.
117 #define IPOIB_NUM_CACHED_PEERS 4
119 /** IPoIB peer address cache */
120 static struct ipoib_peer ipoib_peer_cache
[IPOIB_NUM_CACHED_PEERS
];
122 /** Oldest IPoIB peer cache entry index */
123 static unsigned int ipoib_peer_cache_idx
= 1;
126 * Look up cached peer by key
128 * @v key Peer cache key
129 * @ret peer Peer cache entry, or NULL
131 static struct ipoib_peer
* ipoib_lookup_peer_by_key ( unsigned int key
) {
132 struct ipoib_peer
*peer
;
135 for ( i
= 0 ; i
< IPOIB_NUM_CACHED_PEERS
; i
++ ) {
136 peer
= &ipoib_peer_cache
[i
];
137 if ( peer
->key
== key
)
142 DBG ( "IPoIB warning: peer cache lost track of key %x while "
143 "still in use\n", key
);
149 * Store GID and QPN in peer cache
151 * @v mac Peer MAC address
152 * @ret peer Peer cache entry
154 static struct ipoib_peer
* ipoib_cache_peer ( const struct ipoib_mac
*mac
) {
155 struct ipoib_peer
*peer
;
159 /* Look for existing cache entry */
160 for ( i
= 0 ; i
< IPOIB_NUM_CACHED_PEERS
; i
++ ) {
161 peer
= &ipoib_peer_cache
[i
];
162 if ( memcmp ( &peer
->mac
, mac
, sizeof ( peer
->mac
) ) == 0 )
166 /* No entry found: create a new one */
167 key
= ipoib_peer_cache_idx
++;
168 peer
= &ipoib_peer_cache
[ key
% IPOIB_NUM_CACHED_PEERS
];
170 DBG ( "IPoIB peer %x evicted from cache\n", peer
->key
);
172 memset ( peer
, 0, sizeof ( *peer
) );
174 memcpy ( &peer
->mac
, mac
, sizeof ( peer
->mac
) );
175 DBG ( "IPoIB peer %x has MAC %s\n",
176 peer
->key
, ipoib_ntoa ( &peer
->mac
) );
180 /****************************************************************************
184 ****************************************************************************
188 * Add IPoIB link-layer header
190 * @v netdev Network device
191 * @v iobuf I/O buffer
192 * @v ll_dest Link-layer destination address
193 * @v ll_source Source link-layer address
194 * @v net_proto Network-layer protocol, in network-byte order
195 * @ret rc Return status code
197 static int ipoib_push ( struct net_device
*netdev __unused
,
198 struct io_buffer
*iobuf
, const void *ll_dest
,
199 const void *ll_source __unused
, uint16_t net_proto
) {
200 struct ipoib_hdr
*ipoib_hdr
=
201 iob_push ( iobuf
, sizeof ( *ipoib_hdr
) );
202 const struct ipoib_mac
*dest_mac
= ll_dest
;
203 const struct ipoib_mac
*src_mac
= ll_source
;
204 struct ipoib_peer
*dest
;
205 struct ipoib_peer
*src
;
207 /* Add link-layer addresses to cache */
208 dest
= ipoib_cache_peer ( dest_mac
);
209 src
= ipoib_cache_peer ( src_mac
);
211 /* Build IPoIB header */
212 ipoib_hdr
->proto
= net_proto
;
213 ipoib_hdr
->u
.peer
.dest
= dest
->key
;
214 ipoib_hdr
->u
.peer
.src
= src
->key
;
220 * Remove IPoIB link-layer header
222 * @v netdev Network device
223 * @v iobuf I/O buffer
224 * @ret ll_dest Link-layer destination address
225 * @ret ll_source Source link-layer address
226 * @ret net_proto Network-layer protocol, in network-byte order
227 * @ret rc Return status code
229 static int ipoib_pull ( struct net_device
*netdev
,
230 struct io_buffer
*iobuf
, const void **ll_dest
,
231 const void **ll_source
, uint16_t *net_proto
) {
232 struct ipoib_device
*ipoib
= netdev
->priv
;
233 struct ipoib_hdr
*ipoib_hdr
= iobuf
->data
;
234 struct ipoib_peer
*dest
;
235 struct ipoib_peer
*source
;
238 if ( iob_len ( iobuf
) < sizeof ( *ipoib_hdr
) ) {
239 DBG ( "IPoIB packet too short for link-layer header\n" );
240 DBG_HD ( iobuf
->data
, iob_len ( iobuf
) );
244 /* Strip off IPoIB header */
245 iob_pull ( iobuf
, sizeof ( *ipoib_hdr
) );
247 /* Identify source and destination addresses, and clear
248 * reserved word in IPoIB header
250 dest
= ipoib_lookup_peer_by_key ( ipoib_hdr
->u
.peer
.dest
);
251 source
= ipoib_lookup_peer_by_key ( ipoib_hdr
->u
.peer
.src
);
252 ipoib_hdr
->u
.reserved
= 0;
254 /* Fill in required fields */
255 *ll_dest
= ( dest
? &dest
->mac
: &ipoib
->broadcast
);
256 *ll_source
= ( source
? &source
->mac
: &ipoib
->broadcast
);
257 *net_proto
= ipoib_hdr
->proto
;
263 * Initialise IPoIB link-layer address
265 * @v hw_addr Hardware address
266 * @v ll_addr Link-layer address
268 static void ipoib_init_addr ( const void *hw_addr
, void *ll_addr
) {
269 const struct ib_gid_half
*guid
= hw_addr
;
270 struct ipoib_mac
*mac
= ll_addr
;
272 memset ( mac
, 0, sizeof ( *mac
) );
273 memcpy ( &mac
->gid
.u
.half
[1], guid
, sizeof ( mac
->gid
.u
.half
[1] ) );
277 * Transcribe IPoIB link-layer address
279 * @v ll_addr Link-layer address
280 * @ret string Link-layer address in human-readable format
282 const char * ipoib_ntoa ( const void *ll_addr
) {
284 const struct ipoib_mac
*mac
= ll_addr
;
286 snprintf ( buf
, sizeof ( buf
), "%08x:%08x:%08x:%08x:%08x",
287 htonl ( mac
->flags__qpn
), htonl ( mac
->gid
.u
.dwords
[0] ),
288 htonl ( mac
->gid
.u
.dwords
[1] ),
289 htonl ( mac
->gid
.u
.dwords
[2] ),
290 htonl ( mac
->gid
.u
.dwords
[3] ) );
295 * Hash multicast address
297 * @v af Address family
298 * @v net_addr Network-layer address
299 * @v ll_addr Link-layer address to fill in
300 * @ret rc Return status code
302 static int ipoib_mc_hash ( unsigned int af __unused
,
303 const void *net_addr __unused
,
304 void *ll_addr __unused
) {
310 * Generate Mellanox Ethernet-compatible compressed link-layer address
312 * @v ll_addr Link-layer address
313 * @v eth_addr Ethernet-compatible address to fill in
315 static int ipoib_mlx_eth_addr ( const struct ib_gid_half
*guid
,
316 uint8_t *eth_addr
) {
317 eth_addr
[0] = ( ( guid
->u
.bytes
[3] == 2 ) ? 0x00 : 0x02 );
318 eth_addr
[1] = guid
->u
.bytes
[1];
319 eth_addr
[2] = guid
->u
.bytes
[2];
320 eth_addr
[3] = guid
->u
.bytes
[5];
321 eth_addr
[4] = guid
->u
.bytes
[6];
322 eth_addr
[5] = guid
->u
.bytes
[7];
326 /** An IPoIB Ethernet-compatible compressed link-layer address generator */
327 struct ipoib_eth_addr_handler
{
333 int ( * eth_addr
) ( const struct ib_gid_half
*guid
,
337 /** IPoIB Ethernet-compatible compressed link-layer address generators */
338 static struct ipoib_eth_addr_handler ipoib_eth_addr_handlers
[] = {
339 { 0x02, 0xc9, ipoib_mlx_eth_addr
},
343 * Generate Ethernet-compatible compressed link-layer address
345 * @v ll_addr Link-layer address
346 * @v eth_addr Ethernet-compatible address to fill in
348 static int ipoib_eth_addr ( const void *ll_addr
, void *eth_addr
) {
349 const struct ipoib_mac
*ipoib_addr
= ll_addr
;
350 const struct ib_gid_half
*guid
= &ipoib_addr
->gid
.u
.half
[1];
351 struct ipoib_eth_addr_handler
*handler
;
354 for ( i
= 0 ; i
< ( sizeof ( ipoib_eth_addr_handlers
) /
355 sizeof ( ipoib_eth_addr_handlers
[0] ) ) ; i
++ ) {
356 handler
= &ipoib_eth_addr_handlers
[i
];
357 if ( ( handler
->byte1
== guid
->u
.bytes
[1] ) &&
358 ( handler
->byte2
== guid
->u
.bytes
[2] ) ) {
359 return handler
->eth_addr ( guid
, eth_addr
);
365 /** IPoIB protocol */
366 struct ll_protocol ipoib_protocol __ll_protocol
= {
368 .ll_proto
= htons ( ARPHRD_INFINIBAND
),
369 .hw_addr_len
= sizeof ( struct ib_gid_half
),
370 .ll_addr_len
= IPOIB_ALEN
,
371 .ll_header_len
= IPOIB_HLEN
,
374 .init_addr
= ipoib_init_addr
,
376 .mc_hash
= ipoib_mc_hash
,
377 .eth_addr
= ipoib_eth_addr
,
381 * Allocate IPoIB device
383 * @v priv_size Size of driver private data
384 * @ret netdev Network device, or NULL
386 struct net_device
* alloc_ipoibdev ( size_t priv_size
) {
387 struct net_device
*netdev
;
389 netdev
= alloc_netdev ( priv_size
);
391 netdev
->ll_protocol
= &ipoib_protocol
;
392 netdev
->ll_broadcast
= ( uint8_t * ) &ipoib_broadcast
;
393 netdev
->max_pkt_len
= IB_MAX_PAYLOAD_SIZE
;
398 /****************************************************************************
400 * IPoIB network device
402 ****************************************************************************
406 * Transmit packet via IPoIB network device
408 * @v netdev Network device
409 * @v iobuf I/O buffer
410 * @ret rc Return status code
412 static int ipoib_transmit ( struct net_device
*netdev
,
413 struct io_buffer
*iobuf
) {
414 struct ipoib_device
*ipoib
= netdev
->priv
;
415 struct ib_device
*ibdev
= ipoib
->ibdev
;
416 struct ipoib_hdr
*ipoib_hdr
;
417 struct ipoib_peer
*dest
;
418 struct ib_address_vector av
;
422 if ( iob_len ( iobuf
) < sizeof ( *ipoib_hdr
) ) {
423 DBGC ( ipoib
, "IPoIB %p buffer too short\n", ipoib
);
426 ipoib_hdr
= iobuf
->data
;
428 /* Attempting transmission while link is down will put the
429 * queue pair into an error state, so don't try it.
431 if ( ! ib_link_ok ( ibdev
) )
434 /* Identify destination address */
435 dest
= ipoib_lookup_peer_by_key ( ipoib_hdr
->u
.peer
.dest
);
438 ipoib_hdr
->u
.reserved
= 0;
440 /* Construct address vector */
441 memset ( &av
, 0, sizeof ( av
) );
442 av
.qpn
= ( ntohl ( dest
->mac
.flags__qpn
) & IB_QPN_MASK
);
444 memcpy ( &av
.gid
, &dest
->mac
.gid
, sizeof ( av
.gid
) );
445 if ( ( rc
= ib_resolve_path ( ibdev
, &av
) ) != 0 ) {
446 /* Path not resolved yet */
450 return ib_post_send ( ibdev
, ipoib
->qp
, &av
, iobuf
);
454 * Handle IPoIB send completion
456 * @v ibdev Infiniband device
458 * @v iobuf I/O buffer
459 * @v rc Completion status code
461 static void ipoib_complete_send ( struct ib_device
*ibdev __unused
,
462 struct ib_queue_pair
*qp
,
463 struct io_buffer
*iobuf
, int rc
) {
464 struct ipoib_device
*ipoib
= ib_qp_get_ownerdata ( qp
);
466 netdev_tx_complete_err ( ipoib
->netdev
, iobuf
, rc
);
470 * Handle IPoIB receive completion
472 * @v ibdev Infiniband device
474 * @v av Address vector, or NULL
475 * @v iobuf I/O buffer
476 * @v rc Completion status code
478 static void ipoib_complete_recv ( struct ib_device
*ibdev __unused
,
479 struct ib_queue_pair
*qp
,
480 struct ib_address_vector
*av
,
481 struct io_buffer
*iobuf
, int rc
) {
482 struct ipoib_device
*ipoib
= ib_qp_get_ownerdata ( qp
);
483 struct net_device
*netdev
= ipoib
->netdev
;
484 struct ipoib_hdr
*ipoib_hdr
;
485 struct ipoib_mac ll_src
;
486 struct ipoib_peer
*src
;
489 netdev_rx_err ( netdev
, iobuf
, rc
);
494 if ( iob_len ( iobuf
) < sizeof ( struct ipoib_hdr
) ) {
495 DBGC ( ipoib
, "IPoIB %p received packet too short to "
496 "contain IPoIB header\n", ipoib
);
497 DBGC_HD ( ipoib
, iobuf
->data
, iob_len ( iobuf
) );
498 netdev_rx_err ( netdev
, iobuf
, -EIO
);
501 ipoib_hdr
= iobuf
->data
;
503 /* Parse source address */
504 if ( av
->gid_present
) {
505 ll_src
.flags__qpn
= htonl ( av
->qpn
);
506 memcpy ( &ll_src
.gid
, &av
->gid
, sizeof ( ll_src
.gid
) );
507 src
= ipoib_cache_peer ( &ll_src
);
508 ipoib_hdr
->u
.peer
.src
= src
->key
;
511 /* Hand off to network layer */
512 netdev_rx ( netdev
, iobuf
);
515 /** IPoIB completion operations */
516 static struct ib_completion_queue_operations ipoib_cq_op
= {
517 .complete_send
= ipoib_complete_send
,
518 .complete_recv
= ipoib_complete_recv
,
522 * Poll IPoIB network device
524 * @v netdev Network device
526 static void ipoib_poll ( struct net_device
*netdev
) {
527 struct ipoib_device
*ipoib
= netdev
->priv
;
528 struct ib_device
*ibdev
= ipoib
->ibdev
;
530 ib_poll_eq ( ibdev
);
534 * Enable/disable interrupts on IPoIB network device
536 * @v netdev Network device
537 * @v enable Interrupts should be enabled
539 static void ipoib_irq ( struct net_device
*netdev __unused
,
540 int enable __unused
) {
541 /* No implementation */
545 * Handle IPv4 broadcast multicast group join completion
547 * @v ibdev Infiniband device
549 * @v membership Multicast group membership
551 * @v mad Response MAD (or NULL on error)
553 void ipoib_join_complete ( struct ib_device
*ibdev __unused
,
554 struct ib_queue_pair
*qp __unused
,
555 struct ib_mc_membership
*membership
, int rc
,
556 union ib_mad
*mad __unused
) {
557 struct ipoib_device
*ipoib
= container_of ( membership
,
558 struct ipoib_device
, broadcast_membership
);
560 /* Record join status as link status */
561 netdev_link_err ( ipoib
->netdev
, rc
);
565 * Join IPv4 broadcast multicast group
567 * @v ipoib IPoIB device
568 * @ret rc Return status code
570 static int ipoib_join_broadcast_group ( struct ipoib_device
*ipoib
) {
573 if ( ( rc
= ib_mcast_join ( ipoib
->ibdev
, ipoib
->qp
,
574 &ipoib
->broadcast_membership
,
575 &ipoib
->broadcast
.gid
,
576 ipoib_join_complete
) ) != 0 ) {
577 DBGC ( ipoib
, "IPoIB %p could not join broadcast group: %s\n",
578 ipoib
, strerror ( rc
) );
581 ipoib
->broadcast_joined
= 1;
587 * Leave IPv4 broadcast multicast group
589 * @v ipoib IPoIB device
591 static void ipoib_leave_broadcast_group ( struct ipoib_device
*ipoib
) {
593 if ( ipoib
->broadcast_joined
) {
594 ib_mcast_leave ( ipoib
->ibdev
, ipoib
->qp
,
595 &ipoib
->broadcast_membership
);
596 ipoib
->broadcast_joined
= 0;
601 * Open IPoIB network device
603 * @v netdev Network device
604 * @ret rc Return status code
606 static int ipoib_open ( struct net_device
*netdev
) {
607 struct ipoib_device
*ipoib
= netdev
->priv
;
608 struct ib_device
*ibdev
= ipoib
->ibdev
;
609 struct ipoib_mac
*mac
= ( ( struct ipoib_mac
* ) netdev
->ll_addr
);
613 if ( ( rc
= ib_open ( ibdev
) ) != 0 ) {
614 DBGC ( ipoib
, "IPoIB %p could not open device: %s\n",
615 ipoib
, strerror ( rc
) );
619 /* Allocate completion queue */
620 ipoib
->cq
= ib_create_cq ( ibdev
, IPOIB_NUM_CQES
, &ipoib_cq_op
);
622 DBGC ( ipoib
, "IPoIB %p could not allocate completion queue\n",
628 /* Allocate queue pair */
629 ipoib
->qp
= ib_create_qp ( ibdev
, IB_QPT_UD
,
630 IPOIB_NUM_SEND_WQES
, ipoib
->cq
,
631 IPOIB_NUM_RECV_WQES
, ipoib
->cq
);
633 DBGC ( ipoib
, "IPoIB %p could not allocate queue pair\n",
638 ib_qp_set_ownerdata ( ipoib
->qp
, ipoib
);
640 /* Update MAC address with QPN */
641 mac
->flags__qpn
= htonl ( ipoib
->qp
->qpn
);
643 /* Fill receive rings */
644 ib_refill_recv ( ibdev
, ipoib
->qp
);
646 /* Fake a link status change to join the broadcast group */
647 ipoib_link_state_changed ( ibdev
);
651 ib_destroy_qp ( ibdev
, ipoib
->qp
);
653 ib_destroy_cq ( ibdev
, ipoib
->cq
);
661 * Close IPoIB network device
663 * @v netdev Network device
665 static void ipoib_close ( struct net_device
*netdev
) {
666 struct ipoib_device
*ipoib
= netdev
->priv
;
667 struct ib_device
*ibdev
= ipoib
->ibdev
;
668 struct ipoib_mac
*mac
= ( ( struct ipoib_mac
* ) netdev
->ll_addr
);
670 /* Leave broadcast group */
671 ipoib_leave_broadcast_group ( ipoib
);
673 /* Remove QPN from MAC address */
676 /* Tear down the queues */
677 ib_destroy_qp ( ibdev
, ipoib
->qp
);
678 ib_destroy_cq ( ibdev
, ipoib
->cq
);
680 /* Close IB device */
684 /** IPoIB network device operations */
685 static struct net_device_operations ipoib_operations
= {
687 .close
= ipoib_close
,
688 .transmit
= ipoib_transmit
,
694 * Handle link status change
696 * @v ibdev Infiniband device
698 void ipoib_link_state_changed ( struct ib_device
*ibdev
) {
699 struct net_device
*netdev
= ib_get_ownerdata ( ibdev
);
700 struct ipoib_device
*ipoib
= netdev
->priv
;
701 struct ipoib_mac
*mac
= ( ( struct ipoib_mac
* ) netdev
->ll_addr
);
704 /* Leave existing broadcast group */
705 ipoib_leave_broadcast_group ( ipoib
);
707 /* Update MAC address based on potentially-new GID prefix */
708 memcpy ( &mac
->gid
.u
.half
[0], &ibdev
->gid
.u
.half
[0],
709 sizeof ( mac
->gid
.u
.half
[0] ) );
711 /* Update broadcast GID based on potentially-new partition key */
712 ipoib
->broadcast
.gid
.u
.words
[2] =
713 htons ( ibdev
->pkey
| IB_PKEY_FULL
);
715 /* Set net device link state to reflect Infiniband link state */
716 rc
= ib_link_rc ( ibdev
);
717 netdev_link_err ( netdev
, ( rc
? rc
: -EINPROGRESS_JOINING
) );
719 /* Join new broadcast group */
720 if ( ib_link_ok ( ibdev
) &&
721 ( ( rc
= ipoib_join_broadcast_group ( ipoib
) ) != 0 ) ) {
722 DBGC ( ipoib
, "IPoIB %p could not rejoin broadcast group: "
723 "%s\n", ipoib
, strerror ( rc
) );
724 netdev_link_err ( netdev
, rc
);
732 * @v ibdev Infiniband device
733 * @ret rc Return status code
735 int ipoib_probe ( struct ib_device
*ibdev
) {
736 struct net_device
*netdev
;
737 struct ipoib_device
*ipoib
;
740 /* Allocate network device */
741 netdev
= alloc_ipoibdev ( sizeof ( *ipoib
) );
744 netdev_init ( netdev
, &ipoib_operations
);
745 ipoib
= netdev
->priv
;
746 ib_set_ownerdata ( ibdev
, netdev
);
747 netdev
->dev
= ibdev
->dev
;
748 memset ( ipoib
, 0, sizeof ( *ipoib
) );
749 ipoib
->netdev
= netdev
;
750 ipoib
->ibdev
= ibdev
;
752 /* Extract hardware address */
753 memcpy ( netdev
->hw_addr
, &ibdev
->gid
.u
.half
[1],
754 sizeof ( ibdev
->gid
.u
.half
[1] ) );
756 /* Set default broadcast address */
757 memcpy ( &ipoib
->broadcast
, &ipoib_broadcast
,
758 sizeof ( ipoib
->broadcast
) );
759 netdev
->ll_broadcast
= ( ( uint8_t * ) &ipoib
->broadcast
);
761 /* Register network device */
762 if ( ( rc
= register_netdev ( netdev
) ) != 0 )
763 goto err_register_netdev
;
768 netdev_nullify ( netdev
);
769 netdev_put ( netdev
);
774 * Remove IPoIB device
776 * @v ibdev Infiniband device
778 void ipoib_remove ( struct ib_device
*ibdev
) {
779 struct net_device
*netdev
= ib_get_ownerdata ( ibdev
);
781 unregister_netdev ( netdev
);
782 netdev_nullify ( netdev
);
783 netdev_put ( netdev
);