/**
* Copyright (C) Mellanox Technologies Ltd. 2001-2019. ALL RIGHTS RESERVED.
*
* See file LICENSE for terms.
*/
#ifndef UCT_IB_CM_H_
#define UCT_IB_CM_H_
#include <uct/base/uct_worker.h>
#include <uct/ib/base/ib_iface.h>
#include <ucs/datastruct/queue.h>
#include <ucs/sys/compiler.h>
#include <ucs/type/class.h>
#include <infiniband/cm.h>
/**
* IB CM configuration
*/
typedef struct uct_cm_iface_config {
uct_ib_iface_config_t super;
double timeout;
unsigned retry_count;
unsigned max_outstanding;
} uct_cm_iface_config_t;
/**
* Outstanding operation - can be either a send or flush request.
*/
typedef struct uct_cm_iface_op {
ucs_queue_elem_t queue; /* queue element */
int is_id; /* 1: id field is valid. 0: comp field is valid */
union {
struct ib_cm_id *id; /* send operation: cm id */
uct_completion_t *comp; /* flush request: user completion */
};
} uct_cm_iface_op_t;
/**
* IB CM interface/
*/
typedef struct uct_cm_iface {
uct_ib_iface_t super;
uint32_t service_id; /* Service ID we're listening to */
struct ib_cm_device *cmdev; /* CM device */
struct ib_cm_id *listen_id; /* Listening "socket" */
ucs_queue_head_t notify_q; /* Notification queue */
uint32_t num_outstanding; /* Number of outstanding sends */
uint32_t num_completions; /* Number of completed sends */
ucs_queue_head_t outstanding_q; /* Outstanding operations queue */
uct_worker_cb_id_t slow_prog_id; /* Callback id for slowpath progress */
struct {
int timeout_ms;
uint32_t max_outstanding;
uint8_t retry_count;
} config;
} uct_cm_iface_t;
/**
* CM endpoint - container for destination address
*/
typedef struct uct_cm_ep {
uct_base_ep_t super;
uint16_t dlid;
uint32_t dest_service_id;
union ibv_gid dgid;
} uct_cm_ep_t;
/**
* CM network header
*/
typedef struct uct_cm_hdr {
uint8_t am_id; /* Active message ID */
uint8_t length; /* Payload length */
} UCS_S_PACKED uct_cm_hdr_t;
/**
* CM pending request private data
*/
typedef struct {
uct_pending_req_priv_queue_t base;
uct_cm_ep_t *ep;
} uct_cm_pending_req_priv_t;
UCS_CLASS_DECLARE_NEW_FUNC(uct_cm_ep_t, uct_ep_t, const uct_ep_params_t *);
UCS_CLASS_DECLARE_DELETE_FUNC(uct_cm_ep_t, uct_ep_t);
ucs_status_t uct_cm_ep_connect_to_iface(uct_ep_h ep, const uct_iface_addr_t *iface_addr);
ucs_status_t uct_cm_iface_flush(uct_iface_h tl_iface, unsigned flags,
uct_completion_t *comp);
ucs_status_t uct_cm_iface_flush_do(uct_cm_iface_t *iface, uct_completion_t *comp);
ssize_t uct_cm_ep_am_bcopy(uct_ep_h tl_ep, uint8_t id, uct_pack_callback_t pack_cb,
void *arg, unsigned flags);
ucs_status_t uct_cm_ep_pending_add(uct_ep_h ep, uct_pending_req_t *req,
unsigned flags);
void uct_cm_ep_pending_purge(uct_ep_h ep, uct_pending_purge_callback_t cb,
void *arg);
ucs_status_t uct_cm_ep_flush(uct_ep_h tl_ep, unsigned flags,
uct_completion_t *comp);
static inline int uct_cm_iface_has_tx_resources(uct_cm_iface_t *iface)
{
return iface->num_outstanding < iface->config.max_outstanding;
}
static UCS_F_ALWAYS_INLINE uct_cm_pending_req_priv_t *
uct_cm_pending_req_priv(uct_pending_req_t *req)
{
return (uct_cm_pending_req_priv_t *)&req->priv;
}
#define uct_cm_iface_trace_data(_iface, _type, _hdr, _fmt, ...) \
uct_iface_trace_am(&(_iface)->super.super, _type, (_hdr)->am_id, \
(_hdr) + 1, (_hdr)->length, _fmt, ## __VA_ARGS__)
#define uct_cm_iface_worker(_iface) \
((_iface)->super.super.worker)
#define uct_cm_enter(_iface) \
UCS_ASYNC_BLOCK(uct_cm_iface_worker(_iface)->async);
#define uct_cm_leave(_iface) \
UCS_ASYNC_UNBLOCK(uct_cm_iface_worker(_iface)->async); \
ucs_async_check_miss(uct_cm_iface_worker(_iface)->async);
#endif