iPXE
Data Structures | Defines | Functions | Variables
eoib.c File Reference

Ethernet over Infiniband. More...

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ipxe/errortab.h>
#include <ipxe/malloc.h>
#include <ipxe/iobuf.h>
#include <ipxe/if_ether.h>
#include <ipxe/netdevice.h>
#include <ipxe/ethernet.h>
#include <ipxe/infiniband.h>
#include <ipxe/ib_mcast.h>
#include <ipxe/ib_pathrec.h>
#include <ipxe/eoib.h>

Go to the source code of this file.

Data Structures

struct  eoib_peer
 An EoIB peer cache entry. More...

Defines

#define EOIB_NUM_SEND_WQES   8
 Number of EoIB send work queue entries.
#define EOIB_NUM_RECV_WQES   4
 Number of EoIB receive work queue entries.
#define EOIB_NUM_CQES   16
 Number of EoIB completion queue entries.
#define EINPROGRESS_JOINING   __einfo_error ( EINFO_EINPROGRESS_JOINING )
 Link status for "broadcast join in progress".
#define EINFO_EINPROGRESS_JOINING

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static LIST_HEAD (eoib_devices)
 List of EoIB devices.
static struct eoib_peereoib_find_peer (struct eoib_device *eoib, const uint8_t *mac)
 Find EoIB peer cache entry.
static struct eoib_peereoib_create_peer (struct eoib_device *eoib, const uint8_t *mac)
 Create EoIB peer cache entry.
static void eoib_flush_peers (struct eoib_device *eoib)
 Flush EoIB peer cache.
static unsigned int eoib_discard (void)
 Discard some entries from the peer cache.
struct cache_discarder
eoib_discarder 
__cache_discarder (CACHE_EXPENSIVE)
 EoIB cache discarder.
static struct ib_address_vectoreoib_tx_av (struct eoib_device *eoib, const uint8_t *mac)
 Find destination address vector.
static void eoib_rx_av (struct eoib_device *eoib, const uint8_t *mac, const struct ib_address_vector *av)
 Record source address vector.
static int eoib_transmit (struct net_device *netdev, struct io_buffer *iobuf)
 Transmit packet via EoIB network device.
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.
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.
static void eoib_poll (struct net_device *netdev)
 Poll EoIB network device.
static void eoib_join_complete (struct ib_mc_membership *membership, int rc)
 Handle EoIB broadcast multicast group join completion.
static int eoib_join_broadcast_group (struct eoib_device *eoib)
 Join EoIB broadcast multicast group.
static void eoib_leave_broadcast_group (struct eoib_device *eoib)
 Leave EoIB broadcast multicast group.
static void eoib_link_state_changed (struct eoib_device *eoib)
 Handle link status change.
static int eoib_open (struct net_device *netdev)
 Open EoIB network device.
static void eoib_close (struct net_device *netdev)
 Close EoIB network device.
int eoib_create (struct ib_device *ibdev, const uint8_t *hw_addr, struct ib_address_vector *broadcast, const char *name)
 Create EoIB device.
struct eoib_deviceeoib_find (struct ib_device *ibdev, const uint8_t *hw_addr)
 Find EoIB device.
void eoib_destroy (struct eoib_device *eoib)
 Remove EoIB device.
static int eoib_probe (struct ib_device *ibdev __unused)
 Probe EoIB device.
static void eoib_notify (struct ib_device *ibdev)
 Handle device or link status change.
static void eoib_remove (struct ib_device *ibdev)
 Remove EoIB device.
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.
static const char * eoib_heartbeat_ntoa (const void *net_addr __unused)
 Transcribe EoIB heartbeat address.
static void eoib_duplicate (struct eoib_device *eoib, struct io_buffer *original)
 Transmit duplicate packet to the EoIB gateway.
void eoib_set_gateway (struct eoib_device *eoib, struct ib_address_vector *av)
 Set EoIB gateway.

Variables

struct errortab eoib_errors[] __errortab
 Human-readable message for the link status.
static struct net_device_operations eoib_operations
 EoIB network device operations.
static struct
ib_completion_queue_operations 
eoib_cq_op
 EoIB completion operations.
static struct
ib_queue_pair_operations 
eoib_qp_op
 EoIB queue pair operations.
struct ib_driver eoib_driver __ib_driver
 EoIB driver.
struct net_protocol
eoib_heartbeat_protocol 
__net_protocol
 EoIB heartbeat network protocol.

Detailed Description

Ethernet over Infiniband.

Definition in file eoib.c.


Define Documentation

#define EOIB_NUM_SEND_WQES   8

Number of EoIB send work queue entries.

Definition at line 47 of file eoib.c.

Referenced by eoib_open().

#define EOIB_NUM_RECV_WQES   4

Number of EoIB receive work queue entries.

Definition at line 50 of file eoib.c.

Referenced by eoib_open().

#define EOIB_NUM_CQES   16

Number of EoIB completion queue entries.

Definition at line 53 of file eoib.c.

Referenced by eoib_open().

Link status for "broadcast join in progress".

Definition at line 56 of file eoib.c.

Referenced by eoib_link_state_changed().

Value:
__einfo_uniqify \
        ( EINFO_EINPROGRESS, 0x01, "Joining" )

Definition at line 57 of file eoib.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static LIST_HEAD ( eoib_devices  ) [static]

List of EoIB devices.

static struct eoib_peer* eoib_find_peer ( struct eoib_device eoib,
const uint8_t mac 
) [static, read]

Find EoIB peer cache entry.

Parameters:
eoibEoIB device
macEthernet MAC
Return values:
peerEoIB peer, or NULL if not found

Definition at line 94 of file eoib.c.

References eoib_peer::list, list_add, list_del, list_for_each_entry, eoib_peer::mac, memcmp(), NULL, and eoib_device::peers.

Referenced by eoib_rx_av(), and eoib_tx_av().

                                                                {
        struct eoib_peer *peer;

        /* Find peer cache entry */
        list_for_each_entry ( peer, &eoib->peers, list ) {
                if ( memcmp ( mac, peer->mac, sizeof ( peer->mac ) ) == 0 ) {
                        /* Move peer to start of list */
                        list_del ( &peer->list );
                        list_add ( &peer->list, &eoib->peers );
                        return peer;
                }
        }

        return NULL;
}
static struct eoib_peer* eoib_create_peer ( struct eoib_device eoib,
const uint8_t mac 
) [static, read]

Create EoIB peer cache entry.

Parameters:
eoibEoIB device
macEthernet MAC
Return values:
peerEoIB peer, or NULL on error

Definition at line 118 of file eoib.c.

References eoib_peer::list, list_add, eoib_peer::mac, memcpy(), eoib_device::peers, and zalloc().

Referenced by eoib_tx_av().

                                                                  {
        struct eoib_peer *peer;

        /* Allocate and initialise peer cache entry */
        peer = zalloc ( sizeof ( *peer ) );
        if ( peer ) {
                memcpy ( peer->mac, mac, sizeof ( peer->mac ) );
                list_add ( &peer->list, &eoib->peers );
        }
        return peer;
}
static void eoib_flush_peers ( struct eoib_device eoib) [static]

Flush EoIB peer cache.

Parameters:
eoibEoIB device

Definition at line 136 of file eoib.c.

References free, eoib_peer::list, list_del, list_for_each_entry_safe, and eoib_device::peers.

Referenced by eoib_close().

                                                          {
        struct eoib_peer *peer;
        struct eoib_peer *tmp;

        list_for_each_entry_safe ( peer, tmp, &eoib->peers, list ) {
                list_del ( &peer->list );
                free ( peer );
        }
}
static unsigned int eoib_discard ( void  ) [static]

Discard some entries from the peer cache.

Return values:
discardedNumber of cached items discarded

Definition at line 151 of file eoib.c.

References eoib_operations, for_each_netdev, free, eoib_peer::list, list_del, list_for_each_entry_reverse, netdev, net_device::op, eoib_device::peers, and net_device::priv.

                                          {
        struct net_device *netdev;
        struct eoib_device *eoib;
        struct eoib_peer *peer;
        unsigned int discarded = 0;

        /* Try to discard one cache entry for each EoIB device */
        for_each_netdev ( netdev ) {

                /* Skip non-EoIB devices */
                if ( netdev->op != &eoib_operations )
                        continue;
                eoib = netdev->priv;

                /* Discard least recently used cache entry (if any) */
                list_for_each_entry_reverse ( peer, &eoib->peers, list ) {
                        list_del ( &peer->list );
                        free ( peer );
                        discarded++;
                        break;
                }
        }

        return discarded;
}
struct cache_discarder eoib_discarder __cache_discarder ( CACHE_EXPENSIVE  ) [read]

EoIB cache discarder.

static struct ib_address_vector* eoib_tx_av ( struct eoib_device eoib,
const uint8_t mac 
) [static, read]

Find destination address vector.

Parameters:
eoibEoIB device
macEthernet MAC
Return values:
avAddress vector, or NULL to send as broadcast

Definition at line 189 of file eoib.c.

References eoib_peer::av, DBGC, DBGCP, eoib_create_peer(), eoib_find_peer(), eth_ntoa(), ib_address_vector::gid, ib_address_vector::gid_present, IB_GID_ARGS, IB_GID_FMT, ib_resolve_path(), eoib_device::ibdev, is_multicast_ether_addr(), eoib_device::name, NULL, ib_address_vector::qpn, and rc.

Referenced by eoib_transmit().

                                                                    {
        struct ib_device *ibdev = eoib->ibdev;
        struct eoib_peer *peer;
        int rc;

        /* If this is a broadcast or multicast MAC address, then send
         * this packet as a broadcast.
         */
        if ( is_multicast_ether_addr ( mac ) ) {
                DBGCP ( eoib, "EoIB %s %s TX multicast\n",
                        eoib->name, eth_ntoa ( mac ) );
                return NULL;
        }

        /* If we have no peer cache entry, then create one and send
         * this packet as a broadcast.
         */
        peer = eoib_find_peer ( eoib, mac );
        if ( ! peer ) {
                DBGC ( eoib, "EoIB %s %s TX unknown\n",
                       eoib->name, eth_ntoa ( mac ) );
                eoib_create_peer ( eoib, mac );
                return NULL;
        }

        /* If we have not yet recorded a received GID and QPN for this
         * peer cache entry, then send this packet as a broadcast.
         */
        if ( ! peer->av.gid_present ) {
                DBGCP ( eoib, "EoIB %s %s TX not yet recorded\n",
                        eoib->name, eth_ntoa ( mac ) );
                return NULL;
        }

        /* If we have not yet resolved a path to this peer, then send
         * this packet as a broadcast.
         */
        if ( ( rc = ib_resolve_path ( ibdev, &peer->av ) ) != 0 ) {
                DBGCP ( eoib, "EoIB %s %s TX not yet resolved\n",
                        eoib->name, eth_ntoa ( mac ) );
                return NULL;
        }

        /* Force use of GRH even for local destinations */
        peer->av.gid_present = 1;

        /* We have a fully resolved peer: send this packet as a
         * unicast.
         */
        DBGCP ( eoib, "EoIB %s %s TX " IB_GID_FMT " QPN %#lx\n", eoib->name,
                eth_ntoa ( mac ), IB_GID_ARGS ( &peer->av.gid ), peer->av.qpn );
        return &peer->av;
}
static void eoib_rx_av ( struct eoib_device eoib,
const uint8_t mac,
const struct ib_address_vector av 
) [static]

Record source address vector.

Parameters:
eoibEoIB device
macEthernet MAC
lidInfiniband LID

Definition at line 251 of file eoib.c.

References eoib_peer::av, eoib_device::broadcast, DBGC, DBGCP, eoib_find_peer(), eoib_has_gateway(), eth_ntoa(), eoib_device::gateway, ib_address_vector::gid, gid, ib_address_vector::gid_present, IB_GID_ARGS, IB_GID_FMT, ib_address_vector::lid, memcmp(), memcpy(), eoib_device::name, ib_address_vector::qkey, ib_address_vector::qpn, and qpn.

Referenced by eoib_complete_recv().

                                                              {
        const union ib_gid *gid = &av->gid;
        unsigned long qpn = av->qpn;
        struct eoib_peer *peer;

        /* Sanity checks */
        if ( ! av->gid_present ) {
                DBGC ( eoib, "EoIB %s %s RX with no GID\n",
                       eoib->name, eth_ntoa ( mac ) );
                return;
        }

        /* Find peer cache entry (if any) */
        peer = eoib_find_peer ( eoib, mac );
        if ( ! peer ) {
                DBGCP ( eoib, "EoIB %s %s RX " IB_GID_FMT " (ignored)\n",
                        eoib->name, eth_ntoa ( mac ), IB_GID_ARGS ( gid ) );
                return;
        }

        /* Some dubious EoIB implementations utilise an Ethernet-to-
         * EoIB gateway that will send packets from the wrong QPN.
         */
        if ( eoib_has_gateway ( eoib ) &&
             ( memcmp ( gid, &eoib->gateway.gid, sizeof ( *gid ) ) == 0 ) ) {
                qpn = eoib->gateway.qpn;
        }

        /* Do nothing if peer cache entry is complete and correct */
        if ( ( peer->av.lid == av->lid ) && ( peer->av.qpn == qpn ) ) {
                DBGCP ( eoib, "EoIB %s %s RX unchanged\n",
                        eoib->name, eth_ntoa ( mac ) );
                return;
        }

        /* Update peer cache entry */
        peer->av.qpn = qpn;
        peer->av.qkey = eoib->broadcast.qkey;
        peer->av.gid_present = 1;
        memcpy ( &peer->av.gid, gid, sizeof ( peer->av.gid ) );
        DBGC ( eoib, "EoIB %s %s RX " IB_GID_FMT " QPN %#lx\n", eoib->name,
               eth_ntoa ( mac ), IB_GID_ARGS ( &peer->av.gid ), peer->av.qpn );
}
static int eoib_transmit ( struct net_device netdev,
struct io_buffer iobuf 
) [static]

Transmit packet via EoIB network device.

Parameters:
netdevNetwork device
iobufI/O buffer
Return values:
rcReturn status code

Definition at line 310 of file eoib.c.

References assert, eoib_device::broadcast, io_buffer::data, eoib_device::duplicate, eoib_has_gateway(), EOIB_MAGIC, eoib_tx_av(), ETH_ZLEN, ethhdr::h_dest, htons, ib_post_send(), eoib_device::ibdev, iob_headroom(), iob_len(), iob_pad(), iob_push, IOB_ZLEN, eoib_header::magic, net_device::priv, eoib_device::qp, and eoib_header::reserved.

                                                     {
        struct eoib_device *eoib = netdev->priv;
        struct eoib_header *eoib_hdr;
        struct ethhdr *ethhdr;
        struct ib_address_vector *av;
        size_t zlen;

        /* Sanity checks */
        assert ( iob_len ( iobuf ) >= sizeof ( *ethhdr ) );
        assert ( iob_headroom ( iobuf ) >= sizeof ( *eoib_hdr ) );

        /* Look up destination address vector */
        ethhdr = iobuf->data;
        av = eoib_tx_av ( eoib, ethhdr->h_dest );

        /* Prepend EoIB header */
        eoib_hdr = iob_push ( iobuf, sizeof ( *eoib_hdr ) );
        eoib_hdr->magic = htons ( EOIB_MAGIC );
        eoib_hdr->reserved = 0;

        /* Pad buffer to minimum Ethernet frame size */
        zlen = ( sizeof ( *eoib_hdr ) + ETH_ZLEN );
        assert ( zlen <= IOB_ZLEN );
        if ( iob_len ( iobuf ) < zlen )
                iob_pad ( iobuf, zlen );

        /* If we have no unicast address then send as a broadcast,
         * with a duplicate sent to the gateway if applicable.
         */
        if ( ! av ) {
                av = &eoib->broadcast;
                if ( eoib_has_gateway ( eoib ) )
                        eoib->duplicate ( eoib, iobuf );
        }

        /* Post send work queue entry */
        return ib_post_send ( eoib->ibdev, eoib->qp, av, iobuf );
}
static void eoib_complete_send ( struct ib_device *ibdev  __unused,
struct ib_queue_pair qp,
struct io_buffer iobuf,
int  rc 
) [static]

Handle EoIB send completion.

Parameters:
ibdevInfiniband device
qpQueue pair
iobufI/O buffer
rcCompletion status code

Definition at line 358 of file eoib.c.

References ib_qp_get_ownerdata(), eoib_device::netdev, and netdev_tx_complete_err().

                                                                   {
        struct eoib_device *eoib = ib_qp_get_ownerdata ( qp );

        netdev_tx_complete_err ( eoib->netdev, iobuf, rc );
}
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 
) [static]

Handle EoIB receive completion.

Parameters:
ibdevInfiniband device
qpQueue pair
destDestination address vector, or NULL
sourceSource address vector, or NULL
iobufI/O buffer
rcCompletion status code

Definition at line 376 of file eoib.c.

References io_buffer::data, DBGC, DBGC_HD, EIO, ENOTTY, eoib_rx_av(), ethhdr::h_source, ib_qp_get_ownerdata(), iob_len(), iob_pull, eoib_device::name, eoib_device::netdev, netdev, netdev_rx(), and netdev_rx_err().

                                                                   {
        struct eoib_device *eoib = ib_qp_get_ownerdata ( qp );
        struct net_device *netdev = eoib->netdev;
        struct eoib_header *eoib_hdr;
        struct ethhdr *ethhdr;

        /* Record errors */
        if ( rc != 0 ) {
                netdev_rx_err ( netdev, iobuf, rc );
                return;
        }

        /* Sanity check */
        if ( iob_len ( iobuf ) < ( sizeof ( *eoib_hdr ) + sizeof ( *ethhdr ) )){
                DBGC ( eoib, "EoIB %s received packet too short to "
                       "contain EoIB and Ethernet headers\n", eoib->name );
                DBGC_HD ( eoib, iobuf->data, iob_len ( iobuf ) );
                netdev_rx_err ( netdev, iobuf, -EIO );
                return;
        }
        if ( ! source ) {
                DBGC ( eoib, "EoIB %s received packet without address "
                       "vector\n", eoib->name );
                netdev_rx_err ( netdev, iobuf, -ENOTTY );
                return;
        }

        /* Strip EoIB header */
        iob_pull ( iobuf, sizeof ( *eoib_hdr ) );

        /* Update neighbour cache entry, if any */
        ethhdr = iobuf->data;
        eoib_rx_av ( eoib, ethhdr->h_source, source );

        /* Hand off to network layer */
        netdev_rx ( netdev, iobuf );
}
static void eoib_poll ( struct net_device netdev) [static]

Poll EoIB network device.

Parameters:
netdevNetwork device

Definition at line 434 of file eoib.c.

References ib_poll_eq(), eoib_device::ibdev, net_device::priv, and retry_poll().

                                                    {
        struct eoib_device *eoib = netdev->priv;
        struct ib_device *ibdev = eoib->ibdev;

        /* Poll Infiniband device */
        ib_poll_eq ( ibdev );

        /* Poll the retry timers (required for EoIB multicast join) */
        retry_poll();
}
static void eoib_join_complete ( struct ib_mc_membership membership,
int  rc 
) [static]

Handle EoIB broadcast multicast group join completion.

Parameters:
membershipMulticast group membership
rcStatus code

Definition at line 451 of file eoib.c.

References container_of, eoib_device::netdev, and netdev_link_err().

Referenced by eoib_join_broadcast_group().

                                                                               {
        struct eoib_device *eoib =
                container_of ( membership, struct eoib_device, membership );

        /* Record join status as link status */
        netdev_link_err ( eoib->netdev, rc );
}
static int eoib_join_broadcast_group ( struct eoib_device eoib) [static]

Join EoIB broadcast multicast group.

Parameters:
eoibEoIB device
Return values:
rcReturn status code

Definition at line 465 of file eoib.c.

References eoib_device::broadcast, DBGC, eoib_join_complete(), ib_mcast_join(), eoib_device::ibdev, eoib_device::mask, eoib_device::membership, eoib_device::name, eoib_device::qp, rc, and strerror().

Referenced by eoib_link_state_changed().

                                                                  {
        int rc;

        /* Join multicast group */
        if ( ( rc = ib_mcast_join ( eoib->ibdev, eoib->qp,
                                    &eoib->membership, &eoib->broadcast,
                                    eoib->mask, eoib_join_complete ) ) != 0 ) {
                DBGC ( eoib, "EoIB %s could not join broadcast group: %s\n",
                       eoib->name, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static void eoib_leave_broadcast_group ( struct eoib_device eoib) [static]

Leave EoIB broadcast multicast group.

Parameters:
eoibEoIB device

Definition at line 485 of file eoib.c.

References ib_mcast_leave(), eoib_device::ibdev, eoib_device::membership, and eoib_device::qp.

Referenced by eoib_close(), and eoib_link_state_changed().

                                                                    {

        /* Leave multicast group */
        ib_mcast_leave ( eoib->ibdev, eoib->qp, &eoib->membership );
}
static void eoib_link_state_changed ( struct eoib_device eoib) [static]

Handle link status change.

Parameters:
eoibEoIB device

Definition at line 496 of file eoib.c.

References eoib_device::broadcast, DBGC, EINPROGRESS_JOINING, eoib_join_broadcast_group(), eoib_leave_broadcast_group(), ib_address_vector::gid, htons, ib_is_open(), ib_link_ok(), ib_link_rc(), IB_PKEY_FULL, eoib_device::ibdev, eoib_device::name, eoib_device::netdev, netdev, netdev_link_err(), ib_device::pkey, eoib_device::qp, rc, strerror(), and ib_gid::words.

Referenced by eoib_notify(), and eoib_open().

                                                                 {
        struct net_device *netdev = eoib->netdev;
        struct ib_device *ibdev = eoib->ibdev;
        int rc;

        /* Leave existing broadcast group */
        if ( eoib->qp )
                eoib_leave_broadcast_group ( eoib );

        /* Update broadcast GID based on potentially-new partition key */
        eoib->broadcast.gid.words[2] = htons ( ibdev->pkey | IB_PKEY_FULL );

        /* Set net device link state to reflect Infiniband link state */
        rc = ib_link_rc ( ibdev );
        netdev_link_err ( netdev, ( rc ? rc : -EINPROGRESS_JOINING ) );

        /* Join new broadcast group */
        if ( ib_is_open ( ibdev ) && ib_link_ok ( ibdev ) && eoib->qp &&
             ( ( rc = eoib_join_broadcast_group ( eoib ) ) != 0 ) ) {
                DBGC ( eoib, "EoIB %s could not rejoin broadcast group: "
                       "%s\n", eoib->name, strerror ( rc ) );
                netdev_link_err ( netdev, rc );
                return;
        }
}
static int eoib_open ( struct net_device netdev) [static]

Open EoIB network device.

Parameters:
netdevNetwork device
Return values:
rcReturn status code

Definition at line 528 of file eoib.c.

References eoib_device::cq, DBGC, eoib_link_state_changed(), EOIB_NUM_CQES, EOIB_NUM_RECV_WQES, EOIB_NUM_SEND_WQES, ib_close(), ib_create_cq(), ib_create_qp(), ib_destroy_cq(), ib_destroy_qp(), ib_open(), ib_qp_set_ownerdata(), IB_QPT_UD, ib_refill_recv(), eoib_device::ibdev, eoib_device::name, net_device::name, ib_device::name, NULL, net_device::priv, eoib_device::qp, rc, and strerror().

                                                   {
        struct eoib_device *eoib = netdev->priv;
        struct ib_device *ibdev = eoib->ibdev;
        int rc;

        /* Open IB device */
        if ( ( rc = ib_open ( ibdev ) ) != 0 ) {
                DBGC ( eoib, "EoIB %s could not open %s: %s\n",
                       eoib->name, ibdev->name, strerror ( rc ) );
                goto err_ib_open;
        }

        /* Allocate completion queue */
        if ( ( rc = ib_create_cq ( ibdev, EOIB_NUM_CQES, &eoib_cq_op,
                                   &eoib->cq ) ) != 0 ) {
                DBGC ( eoib, "EoIB %s could not create completion queue: %s\n",
                       eoib->name, strerror ( rc ) );
                goto err_create_cq;
        }

        /* Allocate queue pair */
        if ( ( rc = ib_create_qp ( ibdev, IB_QPT_UD, EOIB_NUM_SEND_WQES,
                                   eoib->cq, EOIB_NUM_RECV_WQES, eoib->cq,
                                   &eoib_qp_op, netdev->name, &eoib->qp ) )!=0){
                DBGC ( eoib, "EoIB %s could not create queue pair: %s\n",
                       eoib->name, strerror ( rc ) );
                goto err_create_qp;
        }
        ib_qp_set_ownerdata ( eoib->qp, eoib );

        /* Fill receive rings */
        ib_refill_recv ( ibdev, eoib->qp );

        /* Fake a link status change to join the broadcast group */
        eoib_link_state_changed ( eoib );

        return 0;

        ib_destroy_qp ( ibdev, eoib->qp );
        eoib->qp = NULL;
 err_create_qp:
        ib_destroy_cq ( ibdev, eoib->cq );
        eoib->cq = NULL;
 err_create_cq:
        ib_close ( ibdev );
 err_ib_open:
        return rc;
}
static void eoib_close ( struct net_device netdev) [static]

Close EoIB network device.

Parameters:
netdevNetwork device

Definition at line 582 of file eoib.c.

References eoib_device::cq, eoib_flush_peers(), eoib_leave_broadcast_group(), ib_close(), ib_destroy_cq(), ib_destroy_qp(), eoib_device::ibdev, NULL, net_device::priv, and eoib_device::qp.

                                                     {
        struct eoib_device *eoib = netdev->priv;
        struct ib_device *ibdev = eoib->ibdev;

        /* Flush peer cache */
        eoib_flush_peers ( eoib );

        /* Leave broadcast group */
        eoib_leave_broadcast_group ( eoib );

        /* Tear down the queues */
        ib_destroy_qp ( ibdev, eoib->qp );
        eoib->qp = NULL;
        ib_destroy_cq ( ibdev, eoib->cq );
        eoib->cq = NULL;

        /* Close IB device */
        ib_close ( ibdev );
}
int eoib_create ( struct ib_device ibdev,
const uint8_t hw_addr,
struct ib_address_vector broadcast,
const char *  name 
)

Create EoIB device.

Parameters:
ibdevInfiniband device
hw_addrEthernet MAC
broadcastBroadcast address vector
nameInterface name (or NULL to use default)
Return values:
rcReturn status code

Definition at line 619 of file eoib.c.

References alloc_etherdev(), eoib_device::broadcast, DBGC, net_device::dev, ib_device::dev, ENOMEM, ETH_ALEN, eth_ntoa(), ib_address_vector::gid, net_device::hw_addr, IB_GID_ARGS, IB_GID_FMT, eoib_device::ibdev, ibdev_get(), ibdev_put(), INIT_LIST_HEAD, eoib_device::list, list_add_tail, list_del, memcpy(), eoib_device::name, net_device::name, ib_device::name, eoib_device::netdev, netdev, netdev_init(), netdev_nullify(), netdev_put(), eoib_device::peers, net_device::priv, rc, register_netdev(), snprintf(), and unregister_netdev().

Referenced by xve_create().

                                                                          {
        struct net_device *netdev;
        struct eoib_device *eoib;
        int rc;

        /* Allocate network device */
        netdev = alloc_etherdev ( sizeof ( *eoib ) );
        if ( ! netdev ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        netdev_init ( netdev, &eoib_operations );
        eoib = netdev->priv;
        netdev->dev = ibdev->dev;
        eoib->netdev = netdev;
        eoib->ibdev = ibdev_get ( ibdev );
        memcpy ( &eoib->broadcast, broadcast, sizeof ( eoib->broadcast ) );
        INIT_LIST_HEAD ( &eoib->peers );

        /* Set MAC address */
        memcpy ( netdev->hw_addr, hw_addr, ETH_ALEN );

        /* Set interface name, if applicable */
        if ( name )
                snprintf ( netdev->name, sizeof ( netdev->name ), "%s", name );
        eoib->name = netdev->name;

        /* Add to list of EoIB devices */
        list_add_tail ( &eoib->list, &eoib_devices );

        /* Register network device */
        if ( ( rc = register_netdev ( netdev ) ) != 0 )
                goto err_register;

        DBGC ( eoib, "EoIB %s created for %s MAC %s\n",
               eoib->name, ibdev->name, eth_ntoa ( hw_addr ) );
        DBGC ( eoib, "EoIB %s broadcast GID " IB_GID_FMT "\n",
               eoib->name, IB_GID_ARGS ( &broadcast->gid ) );
        return 0;

        unregister_netdev ( netdev );
 err_register:
        list_del ( &eoib->list );
        ibdev_put ( ibdev );
        netdev_nullify ( netdev );
        netdev_put ( netdev );
 err_alloc:
        return rc;
}
struct eoib_device* eoib_find ( struct ib_device ibdev,
const uint8_t hw_addr 
) [read]

Find EoIB device.

Parameters:
ibdevInfiniband device
hw_addrOriginal Ethernet MAC
Return values:
eoibEoIB device

Definition at line 677 of file eoib.c.

References ETH_ALEN, net_device::hw_addr, eoib_device::ibdev, eoib_device::list, list_for_each_entry, memcmp(), eoib_device::netdev, and NULL.

Referenced by xsigo_net_notify(), xsmp_rx_xve_modify(), and xve_destroy().

                                                          {
        struct eoib_device *eoib;

        list_for_each_entry ( eoib, &eoib_devices, list ) {
                if ( ( eoib->ibdev == ibdev ) &&
                     ( memcmp ( eoib->netdev->hw_addr, hw_addr,
                                ETH_ALEN ) == 0 ) )
                        return eoib;
        }
        return NULL;
}
void eoib_destroy ( struct eoib_device eoib)

Remove EoIB device.

Parameters:
eoibEoIB device

Definition at line 695 of file eoib.c.

References DBGC, eoib_device::ibdev, ibdev_put(), eoib_device::list, list_del, eoib_device::name, eoib_device::netdev, netdev, netdev_nullify(), netdev_put(), and unregister_netdev().

Referenced by eoib_remove(), and xve_destroy().

                                               {
        struct net_device *netdev = eoib->netdev;

        /* Unregister network device */
        unregister_netdev ( netdev );

        /* Remove from list of network devices */
        list_del ( &eoib->list );

        /* Drop reference to Infiniband device */
        ibdev_put ( eoib->ibdev );

        /* Free network device */
        DBGC ( eoib, "EoIB %s destroyed\n", eoib->name );
        netdev_nullify ( netdev );
        netdev_put ( netdev );
}
static int eoib_probe ( struct ib_device *ibdev  __unused) [static]

Probe EoIB device.

Parameters:
ibdevInfiniband device
Return values:
rcReturn status code

Definition at line 719 of file eoib.c.

                                                           {

        /* EoIB devices are not created automatically */
        return 0;
}
static void eoib_notify ( struct ib_device ibdev) [static]

Handle device or link status change.

Parameters:
ibdevInfiniband device

Definition at line 730 of file eoib.c.

References eoib_link_state_changed(), eoib_device::ibdev, eoib_device::list, and list_for_each_entry.

                                                    {
        struct eoib_device *eoib;

        /* Handle link status change for any attached EoIB devices */
        list_for_each_entry ( eoib, &eoib_devices, list ) {
                if ( eoib->ibdev != ibdev )
                        continue;
                eoib_link_state_changed ( eoib );
        }
}
static void eoib_remove ( struct ib_device ibdev) [static]

Remove EoIB device.

Parameters:
ibdevInfiniband device

Definition at line 746 of file eoib.c.

References eoib_destroy(), eoib_device::ibdev, eoib_device::list, and list_for_each_entry_safe.

                                                    {
        struct eoib_device *eoib;
        struct eoib_device *tmp;

        /* Remove any attached EoIB devices */
        list_for_each_entry_safe ( eoib, tmp, &eoib_devices, list ) {
                if ( eoib->ibdev != ibdev )
                        continue;
                eoib_destroy ( eoib );
        }
}
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 
) [static]

Silently ignore incoming EoIB heartbeat packets.

Parameters:
iobufI/O buffer
netdevNetwork device
ll_sourceLink-layer source address
flagsPacket flags
Return values:
rcReturn status code

Definition at line 782 of file eoib.c.

References free_iob().

                                                             {
        free_iob ( iobuf );
        return 0;
}
static const char* eoib_heartbeat_ntoa ( const void *net_addr  __unused) [static]

Transcribe EoIB heartbeat address.

Parameters:
net_addrEoIB heartbeat address
Return values:
string"<EoIB>"

This operation is meaningless for the EoIB heartbeat protocol.

Definition at line 799 of file eoib.c.

                                                                          {
        return "<EoIB>";
}
static void eoib_duplicate ( struct eoib_device eoib,
struct io_buffer original 
) [static]

Transmit duplicate packet to the EoIB gateway.

Parameters:
eoibEoIB device
originalOriginal I/O buffer

Definition at line 832 of file eoib.c.

References alloc_iob(), io_buffer::data, DBGC, ENOMEM, eoib_device::gateway, ib_address_vector::gid_present, ib_post_send(), ib_resolve_path(), eoib_device::ibdev, iob_len(), iob_put, len, io_buffer::list, list_add_tail, list_del, memcpy(), eoib_device::name, eoib_device::netdev, netdev, netdev_tx_err(), eoib_device::qp, rc, and strerror().

Referenced by eoib_set_gateway().

                                                          {
        struct net_device *netdev = eoib->netdev;
        struct ib_device *ibdev = eoib->ibdev;
        struct ib_address_vector *av = &eoib->gateway;
        size_t len = iob_len ( original );
        struct io_buffer *copy;
        int rc;

        /* Create copy of I/O buffer */
        copy = alloc_iob ( len );
        if ( ! copy ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        memcpy ( iob_put ( copy, len ), original->data, len );

        /* Append to network device's transmit queue */
        list_add_tail ( &copy->list, &original->list );

        /* Resolve path to gateway */
        if ( ( rc = ib_resolve_path ( ibdev, av ) ) != 0 ) {
                DBGC ( eoib, "EoIB %s no path to gateway: %s\n",
                       eoib->name, strerror ( rc ) );
                goto err_path;
        }

        /* Force use of GRH even for local destinations */
        av->gid_present = 1;

        /* Post send work queue entry */
        if ( ( rc = ib_post_send ( eoib->ibdev, eoib->qp, av, copy ) ) != 0 )
                goto err_post_send;

        return;

 err_post_send:
 err_path:
        list_del ( &copy->list );
 err_alloc:
        netdev_tx_err ( netdev, copy, rc );
}
void eoib_set_gateway ( struct eoib_device eoib,
struct ib_address_vector av 
)

Set EoIB gateway.

Parameters:
eoibEoIB device
avAddress vector, or NULL to clear gateway

Definition at line 881 of file eoib.c.

References DBGC, eoib_device::duplicate, eoib_duplicate(), eoib_device::gateway, ib_address_vector::gid, IB_GID_ARGS, IB_GID_FMT, memcpy(), eoib_device::name, and NULL.

Referenced by xve_update_tca().

                                                       {

        if ( av ) {
                DBGC ( eoib, "EoIB %s using gateway " IB_GID_FMT "\n",
                       eoib->name, IB_GID_ARGS ( &av->gid ) );
                memcpy ( &eoib->gateway, av, sizeof ( eoib->gateway ) );
                eoib->duplicate = eoib_duplicate;
        } else {
                DBGC ( eoib, "EoIB %s not using gateway\n", eoib->name );
                eoib->duplicate = NULL;
        }
}

Variable Documentation

struct errortab eoib_errors [] __errortab
Initial value:

Human-readable message for the link status.

Definition at line 61 of file eoib.c.

static struct net_device_operations eoib_operations [static]
Initial value:
 {
        .open           = eoib_open,
        .close          = eoib_close,
        .transmit       = eoib_transmit,
        .poll           = eoib_poll,
}

EoIB network device operations.

Definition at line 68 of file eoib.c.

Referenced by eoib_discard().

Initial value:
 {
        .complete_send = eoib_complete_send,
        .complete_recv = eoib_complete_recv,
}

EoIB completion operations.

Definition at line 419 of file eoib.c.

Initial value:
 {
        .alloc_iob = alloc_iob,
}

EoIB queue pair operations.

Definition at line 425 of file eoib.c.

struct ib_driver eoib_driver __ib_driver
Initial value:
 {
        .name = "EoIB",
        .probe = eoib_probe,
        .notify = eoib_notify,
        .remove = eoib_remove,
}

EoIB driver.

Definition at line 759 of file eoib.c.

struct net_protocol eoib_heartbeat_protocol __net_protocol
Initial value:
 {
        .name = "EoIB",
        .net_proto = htons ( EOIB_MAGIC ),
        .rx = eoib_heartbeat_rx,
        .ntoa = eoib_heartbeat_ntoa,
}

EoIB heartbeat network protocol.

AoE protocol.

Definition at line 804 of file eoib.c.