Blob Blame History Raw
/**
* Copyright (C) Mellanox Technologies Ltd. 2019.  ALL RIGHTS RESERVED.
*
* See file LICENSE for terms.
*/

#include "uct_cm.h"

#include <ucs/sys/math.h>
#include <uct/base/uct_md.h>
#include <ucs/sys/string.h>


ucs_config_field_t uct_cm_config_table[] = {
  {NULL}
};

ucs_status_t uct_cm_open(uct_component_h component, uct_worker_h worker,
                         const uct_cm_config_t *config, uct_cm_h *cm_p)
{
    return component->cm_open(component, worker, config, cm_p);
}

void uct_cm_close(uct_cm_h cm)
{
    cm->ops->close(cm);
}

ucs_status_t uct_cm_query(uct_cm_h cm, uct_cm_attr_t *cm_attr)
{
    return cm->ops->cm_query(cm, cm_attr);
}

ucs_status_t uct_cm_config_read(uct_component_h component,
                                const char *env_prefix, const char *filename,
                                uct_cm_config_t **config_p)
{
    uct_config_bundle_t *bundle = NULL;
    ucs_status_t status;

    status = uct_config_read(&bundle, component->cm_config.table,
                             component->cm_config.size, env_prefix,
                             component->cm_config.prefix);
    if (status != UCS_OK) {
        ucs_error("failed to read CM configuration");
        return status;
    }

    *config_p = (uct_cm_config_t*) bundle->data;
    /* coverity[leaked_storage] */
    return UCS_OK;
}

void uct_cm_ep_client_connect_cb(uct_cm_base_ep_t *cep,
                                 uct_cm_remote_data_t *remote_data,
                                 ucs_status_t status)
{
    cep->client.connect_cb(&cep->super.super, cep->user_data, remote_data, status);
}

void uct_cm_ep_server_connect_cb(uct_cm_base_ep_t *cep, ucs_status_t status)
{
    cep->server.connect_cb(&cep->super.super, cep->user_data, status);
}

ucs_status_t uct_cm_check_ep_params(const uct_ep_params_t *params)
{
    if (!(params->field_mask & UCT_EP_PARAM_FIELD_CM)) {
        ucs_error("UCT_EP_PARAM_FIELD_CM is not set. field_mask 0x%lx",
                  params->field_mask);
        return UCS_ERR_INVALID_PARAM;
    }

    if (!(params->field_mask & UCT_EP_PARAM_FIELD_SOCKADDR_CB_FLAGS) ||
        !(params->sockaddr_cb_flags & UCT_CB_FLAG_ASYNC)) {
        ucs_error("UCT_EP_PARAM_FIELD_SOCKADDR_CB_FLAGS and UCT_CB_FLAG_ASYNC "
                  "should be set. field_mask 0x%lx, sockaddr_cb_flags 0x%x",
                  params->field_mask, params->sockaddr_cb_flags);
        return UCS_ERR_UNSUPPORTED;
    }

    if (!(params->field_mask & (UCT_EP_PARAM_FIELD_SOCKADDR |
                                UCT_EP_PARAM_FIELD_CONN_REQUEST))) {
        ucs_error("neither UCT_EP_PARAM_FIELD_SOCKADDR nor "
                  "UCT_EP_PARAM_FIELD_CONN_REQUEST is set. field_mask 0x%lx",
                  params->field_mask);
        return UCS_ERR_INVALID_PARAM;
    }

    return UCS_OK;
}

UCS_CLASS_INIT_FUNC(uct_cm_base_ep_t, const uct_ep_params_t *params)
{
    ucs_status_t status;

    status = uct_cm_check_ep_params(params);
    if (status != UCS_OK) {
        return status;
    }

    UCS_CLASS_CALL_SUPER_INIT(uct_base_ep_t, &params->cm->iface);

    self->priv_pack_cb      = (params->field_mask &
                               UCT_EP_PARAM_FIELD_SOCKADDR_PACK_CB) ?
                              params->sockaddr_pack_cb : NULL;
    self->disconnect_cb     = (params->field_mask &
                               UCT_EP_PARAM_FIELD_SOCKADDR_DISCONNECT_CB) ?
                              params->disconnect_cb : NULL;
    self->user_data         = (params->field_mask &
                               UCT_EP_PARAM_FIELD_USER_DATA) ?
                              params->user_data : NULL;

    return UCS_OK;
}

UCS_CLASS_CLEANUP_FUNC(uct_cm_base_ep_t){}

UCS_CLASS_DEFINE(uct_cm_base_ep_t, uct_base_ep_t);
UCS_CLASS_DEFINE_NEW_FUNC(uct_cm_base_ep_t, uct_base_ep_t, const uct_ep_params_t *);
UCS_CLASS_DEFINE_DELETE_FUNC(uct_cm_base_ep_t, uct_base_ep_t);


UCS_CLASS_INIT_FUNC(uct_listener_t, uct_cm_h cm)
{
    self->cm = cm;
    return UCS_OK;
}

UCS_CLASS_CLEANUP_FUNC(uct_listener_t){}

UCS_CLASS_DEFINE(uct_listener_t, void);
UCS_CLASS_DEFINE_NEW_FUNC(uct_listener_t, void, uct_cm_h);
UCS_CLASS_DEFINE_DELETE_FUNC(uct_listener_t, void);

ucs_status_t uct_listener_create(uct_cm_h cm, const struct sockaddr *saddr,
                                 socklen_t socklen, const uct_listener_params_t *params,
                                 uct_listener_h *listener_p)
{
    if (!(params->field_mask & UCT_LISTENER_PARAM_FIELD_CONN_REQUEST_CB)) {
        return UCS_ERR_INVALID_PARAM;
    }

    return cm->ops->listener_create(cm, saddr, socklen, params, listener_p);
}

void uct_listener_destroy(uct_listener_h listener)
{
    listener->cm->ops->listener_destroy(listener);
}

ucs_status_t uct_listener_query(uct_listener_h listener,
                                uct_listener_attr_t *listener_attr)
{
    return listener->cm->ops->listener_query(listener, listener_attr);
}

ucs_status_t uct_listener_reject(uct_listener_h listener,
                                 uct_conn_request_h conn_request)
{
    return listener->cm->ops->listener_reject(listener, conn_request);
}


#if ENABLE_STATS
static ucs_stats_class_t uct_cm_stats_class = {
    .name           = "rdmacm_cm",
    .num_counters   = 0
};
#endif

UCS_CLASS_INIT_FUNC(uct_cm_t, uct_cm_ops_t* ops, uct_iface_ops_t* iface_ops,
                    uct_worker_h worker, uct_component_h component)
{
    self->ops                     = ops;
    self->component               = component;
    self->iface.super.ops         = *iface_ops;
    self->iface.worker            = ucs_derived_of(worker, uct_priv_worker_t);

    self->iface.md                = NULL;
    self->iface.am->arg           = NULL;
    self->iface.am->flags         = 0;
    self->iface.am->cb            = (uct_am_callback_t)ucs_empty_function_return_unsupported;
    self->iface.am_tracer         = NULL;
    self->iface.am_tracer_arg     = NULL;
    self->iface.err_handler       = NULL;
    self->iface.err_handler_arg   = NULL;
    self->iface.err_handler_flags = 0;
    self->iface.prog.id           = UCS_CALLBACKQ_ID_NULL;
    self->iface.prog.refcount     = 0;
    self->iface.progress_flags    = 0;

    return UCS_STATS_NODE_ALLOC(&self->iface.stats, &uct_cm_stats_class,
                                ucs_stats_get_root(), "%s-%p", "iface",
                                self->iface);
}

UCS_CLASS_CLEANUP_FUNC(uct_cm_t)
{
    UCS_STATS_NODE_FREE(self->iface.stats);
}

UCS_CLASS_DEFINE(uct_cm_t, void);
UCS_CLASS_DEFINE_NEW_FUNC(uct_cm_t, void, uct_cm_ops_t*, uct_iface_ops_t*,
                          uct_worker_h, uct_component_h);
UCS_CLASS_DEFINE_DELETE_FUNC(uct_cm_t, void);