Ejemplo n.º 1
0
ucs_status_t ucp_ep_create(ucp_worker_h worker, ucp_address_t *address,
                           ucp_ep_h *ep_p)
{
    uint64_t dest_uuid = ucp_address_uuid(address);
    char peer_name[UCP_PEER_NAME_MAX];
    ucs_status_t status;
    ucp_ep_h ep;

    UCS_ASYNC_BLOCK(&worker->async);

    ep = ucp_worker_ep_find(worker, dest_uuid);
    if (ep != NULL) {
        ucs_debug("returning existing ep %p which is already connected to %"PRIx64,
                  ep, ep->dest_uuid);
        goto out;
    }

    ucp_address_peer_name(address, peer_name);
    status = ucp_ep_new(worker, dest_uuid, peer_name, " from api call", &ep);
    if (status != UCS_OK) {
        goto err;
    }

    status = ucp_wireup_start(ep, address);
    if (status != UCS_OK) {
        goto err_free;
    }

out:
    UCS_ASYNC_UNBLOCK(&worker->async);
    *ep_p = ep;
    return UCS_OK;

err_free:
    ucs_free(ep);
err:
    UCS_ASYNC_UNBLOCK(&worker->async);
    return status;
}
Ejemplo n.º 2
0
ucs_status_t ucp_ep_wireup_start(ucp_ep_h ep, ucp_address_t *address)
{
    ucp_worker_h worker = ep->worker;
    struct sockaddr *am_short_addr;
    ucp_rsc_index_t wireup_rsc_index;
    struct sockaddr *wireup_addr;
    uct_iface_attr_t *iface_attr;
    uct_iface_h iface;
    ucp_rsc_index_t dst_rsc_index, wireup_dst_rsc_index;
    ucp_rsc_index_t wireup_dst_pd_index;
    ucs_status_t status;

    UCS_ASYNC_BLOCK(&worker->async);

    ep->dest_uuid = ucp_address_uuid(address);
    sglib_hashed_ucp_ep_t_add(worker->ep_hash, ep);

    ucs_debug("connecting 0x%"PRIx64"->0x%"PRIx64, worker->uuid, ep->dest_uuid);

    /*
     * Select best transport for active messages
     */
    status = ucp_pick_best_wireup(worker, address, ucp_am_short_score_func,
                                  &ep->uct.rsc_index, &dst_rsc_index,
                                  &ep->uct.dst_pd_index, &am_short_addr,
                                  &ep->uct.reachable_pds,
                                  "short_am");
    if (status != UCS_OK) {
        ucs_error("No transport for short active message");
        goto err;
    }

    iface      = worker->ifaces[ep->uct.rsc_index];
    iface_attr = &worker->iface_attrs[ep->uct.rsc_index];

    /*
     * If the selected transport can be connected directly, do it.
     */
    if (iface_attr->cap.flags & UCT_IFACE_FLAG_CONNECT_TO_IFACE) {
        status = uct_ep_create_connected(iface, am_short_addr, &ep->uct.next_ep);
        if (status != UCS_OK) {
            ucs_debug("failed to create ep");
            goto err;
        }

        ep->state |= UCP_EP_STATE_LOCAL_CONNECTED;
        ucp_ep_remote_connected(ep);
        goto out;
    }

    /*
     * If we cannot connect the selected transport directly, select another
     * transport for doing the wireup.
     */
    status = ucp_pick_best_wireup(worker, address, ucp_wireup_score_func,
                                  &wireup_rsc_index, &wireup_dst_rsc_index,
                                  &wireup_dst_pd_index, &wireup_addr,
                                  &ep->uct.reachable_pds,
                                  "wireup");
    if (status != UCS_OK) {
        goto err;
    }

    status = uct_ep_create_connected(worker->ifaces[wireup_rsc_index],
                                     wireup_addr, &ep->wireup_ep);
    if (status != UCS_OK) {
        goto err;
    }

    if (!(iface_attr->cap.flags & UCT_IFACE_FLAG_CONNECT_TO_EP)) {
        status = UCS_ERR_UNREACHABLE;
        goto err_destroy_wireup_ep;
    }

    /*
     * Until the transport is connected, send operations should return NO_RESOURCE.
     * Plant a dummy endpoint object which will do it.
     */
    status = UCS_CLASS_NEW(ucp_dummy_ep_t, &ep->uct.ep, ep);
    if (status != UCS_OK) {
        goto err_destroy_wireup_ep;
    }

    /*
     * Create endpoint for the transport we need to wire-up.
     */
    status = uct_ep_create(iface, &ep->uct.next_ep);
    if (status != UCS_OK) {
        goto err_destroy_uct_ep;
    }

    /*
     * Send initial connection request for wiring-up the transport.
     */
    status = ucp_ep_wireup_send(ep, ep->wireup_ep, UCP_AM_ID_CONN_REQ,
                                dst_rsc_index);
    if (status != UCS_OK) {
        goto err_destroy_next_ep;
    }

out:
    UCS_ASYNC_UNBLOCK(&worker->async);
    return UCS_OK;

err_destroy_next_ep:
    uct_ep_destroy(ep->uct.next_ep);
err_destroy_uct_ep:
    uct_ep_destroy(ep->uct.ep);
err_destroy_wireup_ep:
    uct_ep_destroy(ep->wireup_ep);
err:
    sglib_hashed_ucp_ep_t_delete(worker->ep_hash, ep);
    UCS_ASYNC_UNBLOCK(&worker->async);
    return status;
}