ib_cm.c File Reference

Infiniband communication management. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <byteswap.h>
#include <errno.h>
#include <assert.h>
#include <gpxe/infiniband.h>
#include <gpxe/ib_mi.h>
#include <gpxe/ib_pathrec.h>
#include <gpxe/ib_cm.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static LIST_HEAD (ib_cm_conns)
 List of connections.
static int ib_cm_send_rtu (struct ib_device *ibdev, struct ib_mad_interface *mi, struct ib_connection *conn, struct ib_address_vector *av)
 Send "ready to use" response.
static void ib_cm_connect_rep (struct ib_device *ibdev, struct ib_mad_interface *mi, union ib_mad *mad, struct ib_address_vector *av)
 Handle duplicate connection replies.
static int ib_cm_rejection_reason_to_rc (uint16_t reason)
 Convert connection rejection reason to return status code.
static void ib_cm_req_complete (struct ib_device *ibdev, struct ib_mad_interface *mi, struct ib_mad_transaction *madx, int rc, union ib_mad *mad, struct ib_address_vector *av)
 Handle connection request transaction completion.
static void ib_cm_path_complete (struct ib_device *ibdev, struct ib_path *path, int rc, struct ib_address_vector *av)
 Handle connection path transaction completion.
struct ib_connectionib_create_conn (struct ib_device *ibdev, struct ib_queue_pair *qp, struct ib_gid *dgid, struct ib_gid_half *service_id, void *private_data, size_t private_data_len, struct ib_connection_operations *op)
 Create connection to remote QP.
void ib_destroy_conn (struct ib_device *ibdev, struct ib_queue_pair *qp __unused, struct ib_connection *conn)
 Destroy connection to remote QP.

Variables

struct ib_mad_agent ib_cm_agent[] __ib_mad_agent
 Communication management agents.
static struct
ib_mad_transaction_operations 
ib_cm_req_op
 Connection request operations.
static struct ib_path_operations ib_cm_path_op
 Connection path operations.


Detailed Description

Infiniband communication management.

Definition in file ib_cm.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER   ) 

static LIST_HEAD ( ib_cm_conns   )  [static]

List of connections.

static int ib_cm_send_rtu ( struct ib_device ibdev,
struct ib_mad_interface mi,
struct ib_connection conn,
struct ib_address_vector av 
) [static]

Send "ready to use" response.

Parameters:
ibdev Infiniband device
mi Management interface
conn Connection
av Address vector
Return values:
rc Return status code

Definition at line 51 of file ib_cm.c.

References ib_mad_hdr::attr_id, ib_mad_hdr::class_version, ib_mad::cm, ib_mad_cm::cm_data, DBGC, ib_mad::hdr, htonl, htons, IB_CM_ATTR_READY_TO_USE, IB_CM_CLASS_VERSION, IB_MGMT_CLASS_CM, IB_MGMT_METHOD_SEND, ib_mi_send(), ib_connection::local_id, ib_cm_ready_to_use::local_id, memset(), ib_mad_hdr::method, ib_mad_hdr::mgmt_class, ib_cm_data::ready_to_use, ib_connection::remote_id, ib_cm_ready_to_use::remote_id, and strerror().

Referenced by ib_cm_connect_rep(), and ib_cm_req_complete().

00054                                                            {
00055         union ib_mad mad;
00056         struct ib_cm_ready_to_use *ready =
00057                 &mad.cm.cm_data.ready_to_use;
00058         int rc;
00059 
00060         /* Construct "ready to use" response */
00061         memset ( &mad, 0, sizeof ( mad ) );
00062         mad.hdr.mgmt_class = IB_MGMT_CLASS_CM;
00063         mad.hdr.class_version = IB_CM_CLASS_VERSION;
00064         mad.hdr.method = IB_MGMT_METHOD_SEND;
00065         mad.hdr.attr_id = htons ( IB_CM_ATTR_READY_TO_USE );
00066         ready->local_id = htonl ( conn->local_id );
00067         ready->remote_id = htonl ( conn->remote_id );
00068         if ( ( rc = ib_mi_send ( ibdev, mi, &mad, av ) ) != 0 ){
00069                 DBGC ( conn, "CM %p could not send RTU: %s\n",
00070                        conn, strerror ( rc ) );
00071                 return rc;
00072         }
00073 
00074         return 0;
00075 }

static void ib_cm_connect_rep ( struct ib_device ibdev,
struct ib_mad_interface mi,
union ib_mad mad,
struct ib_address_vector av 
) [static]

Handle duplicate connection replies.

Parameters:
ibdev Infiniband device
mi Management interface
mad Received MAD
av Source address vector
Return values:
rc Return status code
If a "ready to use" MAD is lost, the peer may resend the connection reply. We have to respond to these with duplicate "ready to use" MADs, otherwise the peer may time out and drop the connection.

Definition at line 90 of file ib_cm.c.

References ib_mad::cm, ib_mad_cm::cm_data, ib_cm_data::connect_reply, DBG, ib_cm_send_rtu(), ib_connection::list, list_for_each_entry, ib_connection::local_id, ntohl, and ib_cm_connect_reply::remote_id.

00093                                                                {
00094         struct ib_cm_connect_reply *connect_rep =
00095                 &mad->cm.cm_data.connect_reply;
00096         struct ib_connection *conn;
00097         int rc;
00098 
00099         /* Identify connection */
00100         list_for_each_entry ( conn, &ib_cm_conns, list ) {
00101                 if ( ntohl ( connect_rep->remote_id ) != conn->local_id )
00102                         continue;
00103                 /* Try to send "ready to use" reply */
00104                 if ( ( rc = ib_cm_send_rtu ( ibdev, mi, conn, av ) ) != 0 ) {
00105                         /* Ignore errors */
00106                         return;
00107                 }
00108                 return;
00109         }
00110 
00111         DBG ( "CM unidentified connection %08x\n",
00112               ntohl ( connect_rep->remote_id ) );
00113 }

static int ib_cm_rejection_reason_to_rc ( uint16_t  reason  )  [static]

Convert connection rejection reason to return status code.

Parameters:
reason Rejection reason (in network byte order)
Return values:
rc Return status code

Definition at line 131 of file ib_cm.c.

References EALREADY, ENODEV, ENOTTY, EPERM, htons, IB_CM_REJECT_BAD_SERVICE_ID, IB_CM_REJECT_CONSUMER, and IB_CM_REJECT_STALE_CONN.

Referenced by ib_cm_req_complete().

00131                                                             {
00132         switch ( reason ) {
00133         case htons ( IB_CM_REJECT_BAD_SERVICE_ID ) :
00134                 return -ENODEV;
00135         case htons ( IB_CM_REJECT_STALE_CONN ) :
00136                 return -EALREADY;
00137         case htons ( IB_CM_REJECT_CONSUMER ) :
00138                 return -ENOTTY;
00139         default:
00140                 return -EPERM;
00141         }
00142 }

static void ib_cm_req_complete ( struct ib_device ibdev,
struct ib_mad_interface mi,
struct ib_mad_transaction madx,
int  rc,
union ib_mad mad,
struct ib_address_vector av 
) [static]

Handle connection request transaction completion.

Parameters:
ibdev Infiniband device
mi Management interface
madx Management transaction
rc Status code
mad Received MAD (or NULL on error)
av Source address vector (or NULL on error)

Definition at line 154 of file ib_cm.c.

References ib_mad_hdr::attr_id, ib_queue_pair::av, ib_connection_operations::changed, ib_mad::cm, ib_mad_cm::cm_data, ib_cm_data::common, ib_cm_data::connect_reject, ib_cm_data::connect_reply, DBGC, EIO, ENOTSUP, ib_device::gsi, ib_mad::hdr, htons, IB_CM_ATTR_CONNECT_REJECT, IB_CM_ATTR_CONNECT_REPLY, IB_CM_REJECT_CONSUMER, ib_cm_rejection_reason_to_rc(), ib_cm_send_rtu(), ib_destroy_madx(), ib_madx_get_ownerdata(), IB_MGMT_STATUS_OK, ib_modify_qp(), ib_cm_common::local_id, ib_cm_connect_reply::local_qpn, ib_connection::madx, ntohl, ntohs, NULL, ib_connection::op, ib_cm_connect_reply::private_data, ib_cm_connect_reject::private_data, ib_work_queue::psn, ib_connection::qp, ib_address_vector::qpn, ib_cm_connect_reject::reason, ib_connection::remote_id, ib_queue_pair::send, ib_cm_connect_reply::starting_psn, ib_mad_hdr::status, and strerror().

00158                                                                 {
00159         struct ib_connection *conn = ib_madx_get_ownerdata ( madx );
00160         struct ib_queue_pair *qp = conn->qp;
00161         struct ib_cm_common *common = &mad->cm.cm_data.common;
00162         struct ib_cm_connect_reply *connect_rep =
00163                 &mad->cm.cm_data.connect_reply;
00164         struct ib_cm_connect_reject *connect_rej =
00165                 &mad->cm.cm_data.connect_reject;
00166         void *private_data = NULL;
00167         size_t private_data_len = 0;
00168 
00169         /* Report failures */
00170         if ( ( rc == 0 ) && ( mad->hdr.status != htons ( IB_MGMT_STATUS_OK ) ))
00171                 rc = -EIO;
00172         if ( rc != 0 ) {
00173                 DBGC ( conn, "CM %p connection request failed: %s\n",
00174                        conn, strerror ( rc ) );
00175                 goto out;
00176         }
00177 
00178         /* Record remote communication ID */
00179         conn->remote_id = ntohl ( common->local_id );
00180 
00181         /* Handle response */
00182         switch ( mad->hdr.attr_id ) {
00183 
00184         case htons ( IB_CM_ATTR_CONNECT_REPLY ) :
00185                 /* Extract fields */
00186                 qp->av.qpn = ( ntohl ( connect_rep->local_qpn ) >> 8 );
00187                 qp->send.psn = ( ntohl ( connect_rep->starting_psn ) >> 8 );
00188                 private_data = &connect_rep->private_data;
00189                 private_data_len = sizeof ( connect_rep->private_data );
00190                 DBGC ( conn, "CM %p connected to QPN %lx PSN %x\n",
00191                        conn, qp->av.qpn, qp->send.psn );
00192 
00193                 /* Modify queue pair */
00194                 if ( ( rc = ib_modify_qp ( ibdev, qp ) ) != 0 ) {
00195                         DBGC ( conn, "CM %p could not modify queue pair: %s\n",
00196                                conn, strerror ( rc ) );
00197                         goto out;
00198                 }
00199 
00200                 /* Send "ready to use" reply */
00201                 if ( ( rc = ib_cm_send_rtu ( ibdev, mi, conn, av ) ) != 0 ) {
00202                         /* Treat as non-fatal */
00203                         rc = 0;
00204                 }
00205                 break;
00206 
00207         case htons ( IB_CM_ATTR_CONNECT_REJECT ) :
00208                 /* Extract fields */
00209                 DBGC ( conn, "CM %p connection rejected (reason %d)\n",
00210                        conn, ntohs ( connect_rej->reason ) );
00211                 /* Private data is valid only for a Consumer Reject */
00212                 if ( connect_rej->reason == htons ( IB_CM_REJECT_CONSUMER ) ) {
00213                         private_data = &connect_rej->private_data;
00214                         private_data_len = sizeof (connect_rej->private_data);
00215                 }
00216                 rc = ib_cm_rejection_reason_to_rc ( connect_rej->reason );
00217                 break;
00218 
00219         default:
00220                 DBGC ( conn, "CM %p unexpected response (attribute %04x)\n",
00221                        conn, ntohs ( mad->hdr.attr_id ) );
00222                 rc = -ENOTSUP;
00223                 break;
00224         }
00225 
00226  out:
00227         /* Destroy the completed transaction */
00228         ib_destroy_madx ( ibdev, ibdev->gsi, madx );
00229         conn->madx = NULL;
00230 
00231         /* Hand off to the upper completion handler */
00232         conn->op->changed ( ibdev, qp, conn, rc, private_data,
00233                             private_data_len );
00234 }

static void ib_cm_path_complete ( struct ib_device ibdev,
struct ib_path path,
int  rc,
struct ib_address_vector av 
) [static]

Handle connection path transaction completion.

Parameters:
ibdev Infiniband device
path Path
rc Status code
av Address vector, or NULL on error

Definition at line 249 of file ib_cm.c.

References ib_mad_hdr::attr_id, ib_queue_pair::av, ib_connection_operations::changed, ib_mad_hdr::class_version, ib_mad::cm, ib_mad_cm::cm_data, ib_cm_data::connect_request, DBGC, ib_cm_path::flow_label__rate, ib_address_vector::gid, ib_device::gid, ib_device::gsi, ib_mad::hdr, ib_cm_path::hop_limit, htonl, htons, IB_CM_ATTR_CONNECT_REQUEST, IB_CM_CLASS_VERSION, IB_CM_TRANSPORT_RC, ib_create_madx(), ib_destroy_path(), ib_get_hca_info(), ib_madx_set_ownerdata(), IB_MGMT_CLASS_CM, IB_MGMT_METHOD_SEND, IB_MTU_2048, ib_path_get_ownerdata(), IB_QKEY_GSI, IB_QPN_GSI, ib_address_vector::lid, ib_device::lid, ib_cm_path::local_ack_timeout, ib_cm_connect_request::local_ca, ib_cm_connect_request::local_eecn__initiator_depth, ib_cm_path::local_gid, ib_connection::local_id, ib_cm_connect_request::local_id, ib_cm_path::local_lid, ib_cm_connect_request::local_qpn__responder_resources, ib_connection::madx, ib_cm_connect_request::max_cm_retries__srq, memcpy, memset(), ib_mad_hdr::method, ib_mad_hdr::mgmt_class, NULL, ib_connection::op, ib_connection::path, ib_cm_connect_request::payload_mtu__rdc_exists__rnr_retry, ib_device::pkey, ib_cm_connect_request::pkey, ib_cm_connect_request::primary, ib_connection::private_data, ib_cm_connect_request::private_data, ib_connection::private_data_len, ib_work_queue::psn, ib_address_vector::qkey, ib_connection::qp, ib_address_vector::qpn, ib_queue_pair::qpn, ib_address_vector::rate, ib_queue_pair::recv, ib_cm_connect_request::remote_eecn__remote_timeout__service_type__ee_flow_ctrl, ib_cm_path::remote_gid, ib_cm_path::remote_lid, ib_connection::service_id, ib_cm_connect_request::service_id, ib_address_vector::sl, ib_cm_path::sl__subnet_local, ib_cm_connect_request::starting_psn__local_timeout__retry_count, and strerror().

00251                                                                  {
00252         struct ib_connection *conn = ib_path_get_ownerdata ( path );
00253         struct ib_queue_pair *qp = conn->qp;
00254         union ib_mad mad;
00255         struct ib_cm_connect_request *connect_req =
00256                 &mad.cm.cm_data.connect_request;
00257         size_t private_data_len;
00258 
00259         /* Report failures */
00260         if ( rc != 0 ) {
00261                 DBGC ( conn, "CM %p path lookup failed: %s\n",
00262                        conn, strerror ( rc ) );
00263                 conn->op->changed ( ibdev, qp, conn, rc, NULL, 0 );
00264                 goto out;
00265         }
00266 
00267         /* Update queue pair peer path */
00268         memcpy ( &qp->av, av, sizeof ( qp->av ) );
00269 
00270         /* Construct connection request */
00271         memset ( &mad, 0, sizeof ( mad ) );
00272         mad.hdr.mgmt_class = IB_MGMT_CLASS_CM;
00273         mad.hdr.class_version = IB_CM_CLASS_VERSION;
00274         mad.hdr.method = IB_MGMT_METHOD_SEND;
00275         mad.hdr.attr_id = htons ( IB_CM_ATTR_CONNECT_REQUEST );
00276         connect_req->local_id = htonl ( conn->local_id );
00277         memcpy ( &connect_req->service_id, &conn->service_id,
00278                  sizeof ( connect_req->service_id ) );
00279         ib_get_hca_info ( ibdev, &connect_req->local_ca );
00280         connect_req->local_qpn__responder_resources =
00281                 htonl ( ( qp->qpn << 8 ) | 1 );
00282         connect_req->local_eecn__initiator_depth = htonl ( ( 0 << 8 ) | 1 );
00283         connect_req->remote_eecn__remote_timeout__service_type__ee_flow_ctrl =
00284                 htonl ( ( 0x14 << 3 ) | ( IB_CM_TRANSPORT_RC << 1 ) |
00285                         ( 0 << 0 ) );
00286         connect_req->starting_psn__local_timeout__retry_count =
00287                 htonl ( ( qp->recv.psn << 8 ) | ( 0x14 << 3 ) |
00288                         ( 0x07 << 0 ) );
00289         connect_req->pkey = htons ( ibdev->pkey );
00290         connect_req->payload_mtu__rdc_exists__rnr_retry =
00291                 ( ( IB_MTU_2048 << 4 ) | ( 1 << 3 ) | ( 0x07 << 0 ) );
00292         connect_req->max_cm_retries__srq =
00293                 ( ( 0x0f << 4 ) | ( 0 << 3 ) );
00294         connect_req->primary.local_lid = htons ( ibdev->lid );
00295         connect_req->primary.remote_lid = htons ( conn->qp->av.lid );
00296         memcpy ( &connect_req->primary.local_gid, &ibdev->gid,
00297                  sizeof ( connect_req->primary.local_gid ) );
00298         memcpy ( &connect_req->primary.remote_gid, &conn->qp->av.gid,
00299                  sizeof ( connect_req->primary.remote_gid ) );
00300         connect_req->primary.flow_label__rate =
00301                 htonl ( ( 0 << 12 ) | ( conn->qp->av.rate << 0 ) );
00302         connect_req->primary.hop_limit = 0;
00303         connect_req->primary.sl__subnet_local =
00304                 ( ( conn->qp->av.sl << 4 ) | ( 1 << 3 ) );
00305         connect_req->primary.local_ack_timeout = ( 0x13 << 3 );
00306         private_data_len = conn->private_data_len;
00307         if ( private_data_len > sizeof ( connect_req->private_data ) )
00308                 private_data_len = sizeof ( connect_req->private_data );
00309         memcpy ( &connect_req->private_data, &conn->private_data,
00310                  private_data_len );
00311 
00312         /* Create connection request */
00313         av->qpn = IB_QPN_GSI;
00314         av->qkey = IB_QKEY_GSI;
00315         conn->madx = ib_create_madx ( ibdev, ibdev->gsi, &mad, av,
00316                                       &ib_cm_req_op );
00317         if ( ! conn->madx ) {
00318                 DBGC ( conn, "CM %p could not create connection request\n",
00319                        conn );
00320                 conn->op->changed ( ibdev, qp, conn, rc, NULL, 0 );
00321                 goto out;
00322         }
00323         ib_madx_set_ownerdata ( conn->madx, conn );
00324 
00325  out:
00326         /* Destroy the completed transaction */
00327         ib_destroy_path ( ibdev, path );
00328         conn->path = NULL;
00329 }

struct ib_connection* ib_create_conn ( struct ib_device ibdev,
struct ib_queue_pair qp,
struct ib_gid dgid,
struct ib_gid_half service_id,
void *  private_data,
size_t  private_data_len,
struct ib_connection_operations op 
) [read]

Create connection to remote QP.

Parameters:
ibdev Infiniband device
qp Queue pair
dgid Target GID
service_id Target service ID
private_data Connection request private data
private_data_len Length of connection request private data
op Connection operations
Return values:
conn Connection

Definition at line 349 of file ib_cm.c.

References ib_queue_pair::av, DBGC, ib_gid_half::dwords, ib_gid::dwords, free(), ib_address_vector::gid, ib_address_vector::gid_present, ib_create_path(), ib_destroy_path(), ib_path_set_ownerdata(), ib_connection::ibdev, ib_connection::list, list_add, ib_connection::local_id, memcpy, memset(), ntohl, NULL, ib_connection::op, ib_connection::path, ib_connection::private_data, ib_connection::private_data_len, ib_connection::qp, ib_queue_pair::qpn, random(), ib_connection::service_id, ib_gid_half::u, ib_gid::u, and zalloc().

Referenced by ib_cmrc_xfer_deliver_iob().

00352                                                        {
00353         struct ib_connection *conn;
00354 
00355         /* Allocate and initialise request */
00356         conn = zalloc ( sizeof ( *conn ) + private_data_len );
00357         if ( ! conn )
00358                 goto err_alloc_conn;
00359         conn->ibdev = ibdev;
00360         conn->qp = qp;
00361         memset ( &qp->av, 0, sizeof ( qp->av ) );
00362         qp->av.gid_present = 1;
00363         memcpy ( &qp->av.gid, dgid, sizeof ( qp->av.gid ) );
00364         conn->local_id = random();
00365         memcpy ( &conn->service_id, service_id, sizeof ( conn->service_id ) );
00366         conn->op = op;
00367         conn->private_data_len = private_data_len;
00368         memcpy ( &conn->private_data, private_data, private_data_len );
00369 
00370         /* Create path */
00371         conn->path = ib_create_path ( ibdev, &qp->av, &ib_cm_path_op );
00372         if ( ! conn->path )
00373                 goto err_create_path;
00374         ib_path_set_ownerdata ( conn->path, conn );
00375 
00376         /* Add to list of connections */
00377         list_add ( &conn->list, &ib_cm_conns );
00378 
00379         DBGC ( conn, "CM %p created for IBDEV %p QPN %lx\n",
00380                conn, ibdev, qp->qpn );
00381         DBGC ( conn, "CM %p connecting to %08x:%08x:%08x:%08x %08x:%08x\n",
00382                conn, ntohl ( dgid->u.dwords[0] ), ntohl ( dgid->u.dwords[1] ),
00383                ntohl ( dgid->u.dwords[2] ), ntohl ( dgid->u.dwords[3] ),
00384                ntohl ( service_id->u.dwords[0] ),
00385                ntohl ( service_id->u.dwords[1] ) );
00386 
00387         return conn;
00388 
00389         ib_destroy_path ( ibdev, conn->path );
00390  err_create_path:
00391         free ( conn );
00392  err_alloc_conn:
00393         return NULL;
00394 }

void ib_destroy_conn ( struct ib_device ibdev,
struct ib_queue_pair *qp  __unused,
struct ib_connection conn 
)

Destroy connection to remote QP.

Parameters:
ibdev Infiniband device
qp Queue pair
conn Connection

Definition at line 403 of file ib_cm.c.

References free(), ib_device::gsi, ib_destroy_madx(), ib_destroy_path(), ib_connection::list, list_del, ib_connection::madx, and ib_connection::path.

Referenced by ib_cmrc_shutdown().

00405                                                     {
00406 
00407         list_del ( &conn->list );
00408         if ( conn->madx )
00409                 ib_destroy_madx ( ibdev, ibdev->gsi, conn->madx );
00410         if ( conn->path )
00411                 ib_destroy_path ( ibdev, conn->path );
00412         free ( conn );
00413 }


Variable Documentation

struct ib_mad_agent ib_cm_agent [] __ib_mad_agent

Initial value:

 {
        {
                .mgmt_class = IB_MGMT_CLASS_CM,
                .class_version = IB_CM_CLASS_VERSION,
                .attr_id = htons ( IB_CM_ATTR_CONNECT_REPLY ),
                .handle = ib_cm_connect_rep,
        },
}
Communication management agents.

Definition at line 116 of file ib_cm.c.

Initial value:

 {
        .complete = ib_cm_req_complete,
}
Connection request operations.

Definition at line 237 of file ib_cm.c.

Initial value:

 {
        .complete = ib_cm_path_complete,
}
Connection path operations.

Definition at line 332 of file ib_cm.c.


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