#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_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) |
| 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. | |
Definition in file ib_cm.c.
| 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.
| 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.
| ibdev | Infiniband device | |
| mi | Management interface | |
| mad | Received MAD | |
| av | Source address vector |
| rc | Return status code |
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.
| reason | Rejection reason (in network byte order) |
| 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.
| 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.
| 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.
| 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 |
| 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.
| 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 }
| 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,
},
}
struct ib_mad_transaction_operations ib_cm_req_op [static] |
struct ib_path_operations ib_cm_path_op [static] |
1.5.7.1