ib_packet.c File Reference

Infiniband Packet Formats. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <gpxe/iobuf.h>
#include <gpxe/infiniband.h>
#include <gpxe/ib_packet.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
int ib_push (struct ib_device *ibdev, struct io_buffer *iobuf, struct ib_queue_pair *qp, size_t payload_len, const struct ib_address_vector *av)
 Add IB headers.
int ib_pull (struct ib_device *ibdev, struct io_buffer *iobuf, struct ib_queue_pair **qp, size_t *payload_len, struct ib_address_vector *av)
 Remove IB headers.


Detailed Description

Infiniband Packet Formats.

Definition in file ib_packet.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER   ) 

int ib_push ( struct ib_device ibdev,
struct io_buffer iobuf,
struct ib_queue_pair qp,
size_t  payload_len,
const struct ib_address_vector av 
)

Add IB headers.

Parameters:
ibdev Infiniband device
iobuf I/O buffer to contain headers
qp Queue pair
payload_len Payload length
av Address vector

Definition at line 46 of file ib_packet.c.

References ib_base_transport_header::ack__psn, BTH_OPCODE_UD_SEND, io_buffer::data, DBGC2, DBGCP_HDA, ib_base_transport_header::dest_qp, ib_global_route_header::dgid, ib_local_route_header::dlid, ib_queue_pair::ext_qpn, ib_address_vector::gid, ib_device::gid, ib_address_vector::gid_present, ib_global_route_header::hoplmt, htonl, htons, IB_GRH_IPVER_IPv6, IB_GRH_NXTHDR_IBA, IB_LNH_BTH, IB_LNH_GRH, IB_QPN_SMI, IB_VL_DEFAULT, IB_VL_SMP, iob_len(), iob_push, ib_global_route_header::ipver__tclass__flowlabel, ib_local_route_header::length, ib_address_vector::lid, ib_device::lid, memcpy, NULL, ib_global_route_header::nxthdr, ib_base_transport_header::opcode, ib_global_route_header::paylen, ib_device::pkey, ib_base_transport_header::pkey, ib_work_queue::psn, ib_datagram_extended_transport_header::qkey, ib_address_vector::qkey, ib_address_vector::qpn, ib_base_transport_header::se__m__padcnt__tver, ib_queue_pair::send, ib_global_route_header::sgid, ib_address_vector::sl, ib_local_route_header::sl__lnh, ib_local_route_header::slid, ib_datagram_extended_transport_header::src_qp, and ib_local_route_header::vl__lver.

Referenced by hermon_fill_mlx_send_wqe(), and linda_post_send().

00048                                                    {
00049         struct ib_local_route_header *lrh;
00050         struct ib_global_route_header *grh;
00051         struct ib_base_transport_header *bth;
00052         struct ib_datagram_extended_transport_header *deth;
00053         size_t orig_iob_len = iob_len ( iobuf );
00054         size_t pad_len;
00055         size_t lrh_len;
00056         size_t grh_len;
00057         unsigned int vl;
00058         unsigned int lnh;
00059 
00060         DBGC2 ( ibdev, "IBDEV %p TX %04x:%08lx => %04x:%08lx (key %08lx)\n",
00061                 ibdev, ibdev->lid, qp->ext_qpn, av->lid, av->qpn, av->qkey );
00062 
00063         /* Calculate packet length */
00064         pad_len = ( (-payload_len) & 0x3 );
00065         payload_len += pad_len;
00066         payload_len += 4; /* ICRC */
00067 
00068         /* Reserve space for headers */
00069         orig_iob_len = iob_len ( iobuf );
00070         deth = iob_push ( iobuf, sizeof ( *deth ) );
00071         bth = iob_push ( iobuf, sizeof ( *bth ) );
00072         grh_len = ( payload_len + iob_len ( iobuf ) - orig_iob_len );
00073         grh = ( av->gid_present ?
00074                 iob_push ( iobuf, sizeof ( *grh ) ) : NULL );
00075         lrh = iob_push ( iobuf, sizeof ( *lrh ) );
00076         lrh_len = ( payload_len + iob_len ( iobuf ) - orig_iob_len );
00077 
00078         /* Construct LRH */
00079         vl = ( ( qp->ext_qpn == IB_QPN_SMI ) ? IB_VL_SMP : IB_VL_DEFAULT );
00080         lrh->vl__lver = ( vl << 4 );
00081         lnh = ( grh ? IB_LNH_GRH : IB_LNH_BTH );
00082         lrh->sl__lnh = ( ( av->sl << 4 ) | lnh );
00083         lrh->dlid = htons ( av->lid );
00084         lrh->length = htons ( lrh_len >> 2 );
00085         lrh->slid = htons ( ibdev->lid );
00086 
00087         /* Construct GRH, if required */
00088         if ( grh ) {
00089                 grh->ipver__tclass__flowlabel =
00090                         htonl ( IB_GRH_IPVER_IPv6 << 28 );
00091                 grh->paylen = htons ( grh_len );
00092                 grh->nxthdr = IB_GRH_NXTHDR_IBA;
00093                 grh->hoplmt = 0;
00094                 memcpy ( &grh->sgid, &ibdev->gid, sizeof ( grh->sgid ) );
00095                 memcpy ( &grh->dgid, &av->gid, sizeof ( grh->dgid ) );
00096         }
00097 
00098         /* Construct BTH */
00099         bth->opcode = BTH_OPCODE_UD_SEND;
00100         bth->se__m__padcnt__tver = ( pad_len << 4 );
00101         bth->pkey = htons ( ibdev->pkey );
00102         bth->dest_qp = htonl ( av->qpn );
00103         bth->ack__psn = htonl ( ( qp->send.psn++ ) & 0xffffffUL );
00104 
00105         /* Construct DETH */
00106         deth->qkey = htonl ( av->qkey );
00107         deth->src_qp = htonl ( qp->ext_qpn );
00108 
00109         DBGCP_HDA ( ibdev, 0, iobuf->data,
00110                     ( iob_len ( iobuf ) - orig_iob_len ) );
00111 
00112         return 0;
00113 }

int ib_pull ( struct ib_device ibdev,
struct io_buffer iobuf,
struct ib_queue_pair **  qp,
size_t payload_len,
struct ib_address_vector av 
)

Remove IB headers.

Parameters:
ibdev Infiniband device
iobuf I/O buffer containing headers
qp Queue pair to fill in, or NULL
payload_len Payload length to fill in, or NULL
av Address vector to fill in

Definition at line 124 of file ib_packet.c.

References assert, BTH_OPCODE_UD_SEND, io_buffer::data, DBGC, DBGC2, DBGCP_HDA, ib_base_transport_header::dest_qp, ib_global_route_header::dgid, ib_local_route_header::dlid, ib_gid::dwords, EINVAL, ENODEV, ENOTSUP, ib_queue_pair::ext_qpn, ib_address_vector::gid, ib_address_vector::gid_present, ib_find_qp_mgid(), ib_find_qp_qpn(), IB_LID_MULTICAST, IB_LNH_BTH, IB_LNH_GRH, iob_len(), iob_pull, ib_local_route_header::length, ib_address_vector::lid, memcpy, memset(), ntohl, ntohs, NULL, ib_base_transport_header::opcode, ib_datagram_extended_transport_header::qkey, ib_address_vector::qkey, ib_address_vector::qpn, ib_base_transport_header::se__m__padcnt__tver, ib_global_route_header::sgid, ib_address_vector::sl, ib_local_route_header::sl__lnh, ib_local_route_header::slid, ib_datagram_extended_transport_header::src_qp, and ib_gid::u.

Referenced by linda_complete_recv().

00126                                              {
00127         struct ib_local_route_header *lrh;
00128         struct ib_global_route_header *grh;
00129         struct ib_base_transport_header *bth;
00130         struct ib_datagram_extended_transport_header *deth;
00131         size_t orig_iob_len = iob_len ( iobuf );
00132         unsigned int lnh;
00133         size_t pad_len;
00134         unsigned long qpn;
00135         unsigned int lid;
00136 
00137         /* Clear return values */
00138         if ( qp )
00139                 *qp = NULL;
00140         if ( payload_len )
00141                 *payload_len = 0;
00142         memset ( av, 0, sizeof ( *av ) );
00143 
00144         /* Extract LRH */
00145         if ( iob_len ( iobuf ) < sizeof ( *lrh ) ) {
00146                 DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) for LRH\n",
00147                        ibdev, iob_len ( iobuf ) );
00148                 return -EINVAL;
00149         }
00150         lrh = iobuf->data;
00151         iob_pull ( iobuf, sizeof ( *lrh ) );
00152         av->lid = ntohs ( lrh->slid );
00153         av->sl = ( lrh->sl__lnh >> 4 );
00154         lnh = ( lrh->sl__lnh & 0x3 );
00155         lid = ntohs ( lrh->dlid );
00156 
00157         /* Reject unsupported packets */
00158         if ( ! ( ( lnh == IB_LNH_BTH ) || ( lnh == IB_LNH_GRH ) ) ) {
00159                 DBGC ( ibdev, "IBDEV %p RX unsupported LNH %x\n",
00160                        ibdev, lnh );
00161                 return -ENOTSUP;
00162         }
00163 
00164         /* Extract GRH, if present */
00165         if ( lnh == IB_LNH_GRH ) {
00166                 if ( iob_len ( iobuf ) < sizeof ( *grh ) ) {
00167                         DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) "
00168                                "for GRH\n", ibdev, iob_len ( iobuf ) );
00169                         return -EINVAL;
00170                 }
00171                 grh = iobuf->data;
00172                 iob_pull ( iobuf, sizeof ( *grh ) );
00173                 av->gid_present = 1;
00174                 memcpy ( &av->gid, &grh->sgid, sizeof ( av->gid ) );
00175         } else {
00176                 grh = NULL;
00177         }
00178 
00179         /* Extract BTH */
00180         if ( iob_len ( iobuf ) < sizeof ( *bth ) ) {
00181                 DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) for BTH\n",
00182                        ibdev, iob_len ( iobuf ) );
00183                 return -EINVAL;
00184         }
00185         bth = iobuf->data;
00186         iob_pull ( iobuf, sizeof ( *bth ) );
00187         if ( bth->opcode != BTH_OPCODE_UD_SEND ) {
00188                 DBGC ( ibdev, "IBDEV %p unsupported BTH opcode %x\n",
00189                        ibdev, bth->opcode );
00190                 return -ENOTSUP;
00191         }
00192         qpn = ntohl ( bth->dest_qp );
00193 
00194         /* Extract DETH */
00195         if ( iob_len ( iobuf ) < sizeof ( *deth ) ) {
00196                 DBGC ( ibdev, "IBDEV %p RX too short (%zd bytes) for DETH\n",
00197                        ibdev, iob_len ( iobuf ) );
00198                 return -EINVAL;
00199         }
00200         deth = iobuf->data;
00201         iob_pull ( iobuf, sizeof ( *deth ) );
00202         av->qpn = ntohl ( deth->src_qp );
00203         av->qkey = ntohl ( deth->qkey );
00204 
00205         /* Calculate payload length, if applicable */
00206         if ( payload_len ) {
00207                 pad_len = ( ( bth->se__m__padcnt__tver >> 4 ) & 0x3 );
00208                 *payload_len = ( ( ntohs ( lrh->length ) << 2 )
00209                                  - ( orig_iob_len - iob_len ( iobuf ) )
00210                                  - pad_len - 4 /* ICRC */ );
00211         }
00212 
00213         /* Determine destination QP, if applicable */
00214         if ( qp ) {
00215                 if ( IB_LID_MULTICAST ( lid ) && grh ) {
00216                         if ( ! ( *qp = ib_find_qp_mgid ( ibdev, &grh->dgid ))){
00217                                 DBGC ( ibdev, "IBDEV %p RX for unknown MGID "
00218                                        "%08x:%08x:%08x:%08x\n", ibdev,
00219                                        ntohl ( grh->dgid.u.dwords[0] ),
00220                                        ntohl ( grh->dgid.u.dwords[1] ),
00221                                        ntohl ( grh->dgid.u.dwords[2] ),
00222                                        ntohl ( grh->dgid.u.dwords[3] ) );
00223                                 return -ENODEV;
00224                         }
00225                 } else {
00226                         if ( ! ( *qp = ib_find_qp_qpn ( ibdev, qpn ) ) ) {
00227                                 DBGC ( ibdev, "IBDEV %p RX for nonexistent "
00228                                        "QPN %lx\n", ibdev, qpn );
00229                                 return -ENODEV;
00230                         }
00231                 }
00232                 assert ( *qp );
00233         }
00234 
00235         DBGC2 ( ibdev, "IBDEV %p RX %04x:%08lx <= %04x:%08lx (key %08x)\n",
00236                 ibdev, lid, ( IB_LID_MULTICAST( lid ) ?
00237                               ( qp ? (*qp)->ext_qpn : -1UL ) : qpn ),
00238                 av->lid, av->qpn, ntohl ( deth->qkey ) );
00239         DBGCP_HDA ( ibdev, 0,
00240                     ( iobuf->data - ( orig_iob_len - iob_len ( iobuf ) ) ),
00241                     ( orig_iob_len - iob_len ( iobuf ) ) );
00242 
00243         return 0;
00244 }


Generated on Tue Apr 6 20:01:55 2010 for gPXE by  doxygen 1.5.7.1