282 строки
8.2 KiB
C
282 строки
8.2 KiB
C
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */
|
|
/*
|
|
* Copyright (c) 2011-2015 Los Alamos National Security, LLC. All rights
|
|
* reserved.
|
|
* 2014 Mellanox Technologies, Inc.
|
|
* All rights reserved.
|
|
* Copyright (c) 2015 Intel, Inc. All rights reserved.
|
|
* $COPYRIGHT$
|
|
*
|
|
* Additional copyrights may follow
|
|
*
|
|
* $HEADER$
|
|
*
|
|
*/
|
|
|
|
#if !defined(MCA_OOB_UD_REQ_H)
|
|
#define MCA_OOB_UD_REQ_H
|
|
|
|
#include "oob_ud_peer.h"
|
|
|
|
#include "orte_config.h"
|
|
#include "orte/types.h"
|
|
#include "opal/threads/condition.h"
|
|
#include "opal/mca/event/event.h"
|
|
#include "opal/class/opal_free_list.h"
|
|
#include "orte/mca/rml/rml.h"
|
|
|
|
#include <infiniband/verbs.h>
|
|
|
|
#include "oob_ud_qp.h"
|
|
|
|
struct mca_oob_ud_peer_t;
|
|
|
|
enum mca_oob_ud_req_type_t {
|
|
MCA_OOB_UD_REQ_RECV,
|
|
MCA_OOB_UD_REQ_SEND
|
|
};
|
|
typedef enum mca_oob_ud_req_type_t mca_oob_ud_req_type_t;
|
|
|
|
enum mca_oob_ud_req_state_t {
|
|
MCA_OOB_UD_REQ_ACTIVE,
|
|
MCA_OOB_UD_REQ_PENDING,
|
|
MCA_OOB_UD_REQ_COMPLETE
|
|
};
|
|
typedef enum mca_oob_ud_req_state_t mca_oob_ud_req_state_t;
|
|
|
|
enum mca_oob_ud_req_data_type_t {
|
|
MCA_OOB_UD_REQ_IOV,
|
|
MCA_OOB_UD_REQ_BUF,
|
|
MCA_OOB_UD_REQ_TR
|
|
};
|
|
typedef enum mca_oob_ud_req_data_type_t mca_oob_ud_req_data_type_t;
|
|
|
|
enum mca_oob_ud_msg_type_t {
|
|
MCA_OOB_UD_MSG_REQUEST = 37,
|
|
MCA_OOB_UD_MSG_REPLY = 38,
|
|
MCA_OOB_UD_MSG_COMPLETE = 39,
|
|
MCA_OOB_UD_MSG_PING = 40,
|
|
MCA_OOB_UD_MSG_ACK = 41,
|
|
MCA_OOB_UD_MSG_NACK = 42,
|
|
MCA_OOB_UD_MSG_DATA_OK = 43,
|
|
MCA_OOB_UD_MSG_END = 44
|
|
};
|
|
typedef enum mca_oob_ud_msg_type_t mca_oob_ud_msg_type_t;
|
|
|
|
struct mca_oob_ud_msg_hdr_t {
|
|
mca_oob_ud_msg_type_t msg_type;
|
|
|
|
void *msg_rem_ctx;
|
|
void *msg_lcl_ctx;
|
|
|
|
orte_process_name_t msg_origin;
|
|
orte_process_name_t msg_target;
|
|
int msg_channel;
|
|
int msg_seq_num;
|
|
|
|
uint64_t msg_id;
|
|
|
|
struct {
|
|
/* the receiver can get the qpn and lid from the work completion */
|
|
uint32_t qkey;
|
|
orte_process_name_t name;
|
|
uint8_t port_num;
|
|
} ra;
|
|
|
|
union {
|
|
struct {
|
|
int tag;
|
|
int data_len;
|
|
int mtu;
|
|
bool data_follows;
|
|
bool data_iovec_used;
|
|
} req;
|
|
struct {
|
|
uint32_t qpn;
|
|
int data_len;
|
|
int tag;
|
|
int mtu;
|
|
} rep;
|
|
} msg_data;
|
|
};
|
|
typedef struct mca_oob_ud_msg_hdr_t mca_oob_ud_msg_hdr_t;
|
|
|
|
struct mca_oob_ud_req_t {
|
|
opal_list_item_t super;
|
|
|
|
mca_oob_ud_req_type_t type;
|
|
mca_oob_ud_req_state_t state;
|
|
|
|
union {
|
|
struct ibv_send_wr *send;
|
|
struct ibv_recv_wr *recv;
|
|
} req_wr;
|
|
|
|
/* storage for ib grh */
|
|
struct ibv_grh *req_grh;
|
|
struct ibv_mr *req_grh_mr;
|
|
|
|
struct ibv_sge *req_sge;
|
|
|
|
/* negotiated mtu */
|
|
int req_mtu;
|
|
uint32_t req_rem_qpn;
|
|
int req_rem_data_len;
|
|
|
|
int req_packet_count;
|
|
|
|
struct mca_oob_ud_peer_t *req_peer;
|
|
struct mca_oob_ud_port_t *req_port;
|
|
struct mca_oob_ud_qp_t *req_qp;
|
|
|
|
/* remote context (request or response) */
|
|
void *req_rem_ctx;
|
|
|
|
/* retry timer */
|
|
struct {
|
|
opal_event_t event;
|
|
struct timeval value;
|
|
} timer;
|
|
|
|
/* user request */
|
|
orte_process_name_t req_target;
|
|
orte_process_name_t req_origin;
|
|
|
|
mca_oob_ud_req_data_type_t req_data_type;
|
|
union {
|
|
struct {
|
|
struct ibv_mr **mr;
|
|
struct iovec *uiov;
|
|
int count;
|
|
}iov;
|
|
struct {
|
|
struct ibv_mr *mr;
|
|
char *p;
|
|
int size;
|
|
}buf;
|
|
}req_data;
|
|
|
|
int req_tag;
|
|
int req_channel;
|
|
int req_seq_num;
|
|
int req_rc;
|
|
|
|
void *req_cbdata;
|
|
|
|
/* what list is this request in */
|
|
opal_list_t *req_list;
|
|
|
|
bool req_is_eager;
|
|
|
|
orte_rml_send_t *rml_msg;
|
|
};
|
|
|
|
typedef struct mca_oob_ud_req_t mca_oob_ud_req_t;
|
|
OBJ_CLASS_DECLARATION(mca_oob_ud_req_t);
|
|
|
|
enum mca_oob_ud_status_t {
|
|
/* message posted */
|
|
MCA_OOB_UD_MSG_STATUS_POSTED,
|
|
/* remote side receive the message (ack'd) */
|
|
MCA_OOB_UD_MSG_STATUS_COMPLETE,
|
|
/* request message timed out */
|
|
MCA_OOB_UD_MSG_STATUS_TIMEOUT,
|
|
/* other failure */
|
|
MCA_OOB_UD_MSG_STATUS_ERROR
|
|
};
|
|
typedef enum mca_oob_ud_status_t mca_oob_ud_status_t;
|
|
|
|
struct mca_oob_ud_msg_t {
|
|
opal_free_list_item_t super;
|
|
|
|
struct ibv_send_wr wr;
|
|
struct ibv_sge sge;
|
|
mca_oob_ud_msg_hdr_t *hdr;
|
|
struct ibv_mr *mr;
|
|
|
|
/* qp this request was sent over */
|
|
struct mca_oob_ud_qp_t *qp;
|
|
struct mca_oob_ud_port_t *port;
|
|
|
|
opal_mutex_t lock;
|
|
opal_condition_t status_changed;
|
|
mca_oob_ud_status_t status;
|
|
|
|
bool persist;
|
|
mca_oob_ud_req_t *req;
|
|
|
|
void (*cbfunc) (struct mca_oob_ud_msg_t *, int);
|
|
|
|
struct mca_oob_ud_peer_t *peer;
|
|
};
|
|
typedef struct mca_oob_ud_msg_t mca_oob_ud_msg_t;
|
|
OBJ_CLASS_DECLARATION(mca_oob_ud_msg_t);
|
|
|
|
static inline int mca_oob_ud_recv_alloc (mca_oob_ud_req_t *recv_req)
|
|
{
|
|
int iov_index;
|
|
|
|
size_t alloc_size = recv_req->req_rem_data_len;
|
|
if (MCA_OOB_UD_REQ_IOV == recv_req->req_data_type) {
|
|
for (iov_index = 0 ; iov_index < recv_req->req_data.iov.count - 1 ; ++iov_index) {
|
|
alloc_size -= recv_req->req_data.iov.uiov[iov_index].iov_len;
|
|
}
|
|
|
|
recv_req->req_data.iov.uiov[iov_index].iov_len = alloc_size;
|
|
recv_req->req_data.iov.uiov[iov_index].iov_base = calloc (alloc_size, 1);
|
|
|
|
if (NULL == recv_req->req_data.iov.uiov[iov_index].iov_base) {
|
|
return ORTE_ERROR;
|
|
}
|
|
} else {
|
|
recv_req->req_data.buf.p = (char *)calloc(recv_req->req_rem_data_len, sizeof(char));
|
|
if (NULL == recv_req->req_data.buf.p) {
|
|
return ORTE_ERROR;
|
|
}
|
|
recv_req->req_data.buf.size = recv_req->req_rem_data_len;
|
|
}
|
|
return ORTE_SUCCESS;
|
|
}
|
|
|
|
#define MCA_OOB_UD_REQ_DEREG_MR(req) \
|
|
if (MCA_OOB_UD_REQ_IOV == req->req_data_type) { \
|
|
if (req->req_data.iov.mr) { \
|
|
for (i = 0 ; i < req->req_data.iov.count ; ++i) { \
|
|
if (req->req_data.iov.mr[i]) { \
|
|
(void) ibv_dereg_mr (req->req_data.iov.mr[i]); \
|
|
req->req_data.iov.mr[i] = NULL; \
|
|
} \
|
|
} \
|
|
free (req->req_data.iov.mr); \
|
|
req->req_data.iov.mr = NULL; \
|
|
} \
|
|
} else { \
|
|
if (req->req_data.buf.mr) { \
|
|
(void) ibv_dereg_mr (req->req_data.buf.mr); \
|
|
req->req_data.buf.mr = NULL; \
|
|
} \
|
|
}
|
|
|
|
int mca_oob_ud_msg_get (struct mca_oob_ud_port_t *port, mca_oob_ud_req_t *req,
|
|
mca_oob_ud_qp_t *qp, mca_oob_ud_peer_t *peer, bool persist,
|
|
mca_oob_ud_msg_t **msgp);
|
|
int mca_oob_ud_msg_init (opal_free_list_item_t *item, void *context);
|
|
void mca_oob_ud_msg_return (mca_oob_ud_msg_t *msg);
|
|
|
|
|
|
void mca_oob_ud_req_timer_set (mca_oob_ud_req_t *req, const struct timeval *timeout,
|
|
int max_tries, void (*cb)(evutil_socket_t, short, void *));
|
|
|
|
int mca_oob_ud_msg_post_send (mca_oob_ud_msg_t *msg);
|
|
int mca_oob_ud_msg_wait (mca_oob_ud_msg_t *msg);
|
|
|
|
int mca_oob_ud_msg_status_update (mca_oob_ud_msg_t *msg, mca_oob_ud_status_t status);
|
|
|
|
void mca_oob_ud_req_complete (mca_oob_ud_req_t *req, int rc);
|
|
void mca_oob_ud_req_abort (mca_oob_ud_req_t *req);
|
|
|
|
void mca_oob_ud_req_append_to_list (mca_oob_ud_req_t *req, opal_list_t *list);
|
|
bool mca_oob_ud_req_is_in_list (mca_oob_ud_req_t *req, opal_list_t *list);
|
|
|
|
#endif
|