예제 #1
0
파일: ud_ep.c 프로젝트: andyw-lala/ucx
static void uct_ud_ep_rx_creq(uct_ud_iface_t *iface, uct_ud_neth_t *neth)
{
    uct_ud_ep_t *ep;
    uct_ud_ctl_hdr_t *ctl = (uct_ud_ctl_hdr_t *)(neth + 1);

    ucs_assert_always(ctl->type == UCT_UD_PACKET_CREQ);

    ep = uct_ud_iface_cep_lookup(iface, &ctl->conn_req.ib_addr, ctl->conn_req.conn_id);
    if (!ep) {
        ep = uct_ud_ep_create_passive(iface, ctl);
        ucs_assert_always(ep != NULL);
        ep->rx.ooo_pkts.head_sn = neth->psn;
    } else {
        if (ep->dest_ep_id == UCT_UD_EP_NULL_ID) {
            /* simultaniuos CREQ */
            ep->dest_ep_id = ctl->conn_req.ib_addr.id;
            ep->rx.ooo_pkts.head_sn = neth->psn;
            ucs_debug("created ep=%p (iface=%p conn_id=%d ep_id=%d, dest_ep_id=%d rx_psn=%u)", ep, iface, ep->conn_id, ep->ep_id, ep->dest_ep_id, ep->rx.ooo_pkts.head_sn);
        }
    }

    ucs_assert_always(ctl->conn_req.conn_id == ep->conn_id);
    ucs_assert_always(ctl->conn_req.ib_addr.id == ep->dest_ep_id);
    /* creq must always have same psn */
    ucs_assert_always(ep->rx.ooo_pkts.head_sn == neth->psn);
    /* scedule connection reply op */
    UCT_UD_EP_HOOK_CALL_RX(ep, neth);
    uct_ud_iface_queue_pending(iface, ep, UCT_UD_EP_OP_CREP);
}
예제 #2
0
파일: ud_ep.c 프로젝트: andyw-lala/ucx
ucs_status_t uct_ud_ep_create_connected_common(uct_ud_iface_t *iface, 
                                               const uct_sockaddr_ib_t *addr, 
                                               uct_ud_ep_t **new_ep_p, 
                                               uct_ud_send_skb_t **skb_p)
{
    ucs_status_t status;
    uct_ud_ep_t *ep;
    uct_ep_h new_ep_h;

    ep = uct_ud_iface_cep_lookup(iface, addr, UCT_UD_EP_CONN_ID_MAX);
    if (ep) {
        *new_ep_p = ep;
        *skb_p    = NULL;
        return UCS_OK;
    }

    status = uct_ep_create(&iface->super.super.super, &new_ep_h);
    if (status != UCS_OK) {
        return status;
    }
    ep = ucs_derived_of(new_ep_h, uct_ud_ep_t);

    status = uct_ud_ep_connect_to_iface(ep, addr);
    if (status != UCS_OK) {
        return status;
    }

    status = uct_ud_iface_cep_insert(iface, addr, ep, UCT_UD_EP_CONN_ID_MAX);
    if (status != UCS_OK) {
        goto err_cep_insert;
    }

    *skb_p = uct_ud_ep_prepare_creq(ep);
    if (!*skb_p) {
        status = UCS_ERR_NO_RESOURCE;
        goto err_creq;
    }

    *new_ep_p = ep;
    return UCS_OK;

err_creq:
    uct_ud_iface_cep_rollback(iface, addr, ep);
err_cep_insert:
    uct_ud_ep_disconnect_from_iface(&ep->super.super);
    return status;
}
예제 #3
0
파일: ud_verbs.c 프로젝트: biddisco/ucx
ucs_status_t uct_ud_verbs_ep_create_connected(uct_iface_h iface_h, const struct sockaddr *addr, uct_ep_h *new_ep_p)
{
    uct_ud_ep_t *ready_ep;
    uct_ud_verbs_ep_t *ep;
    uct_ud_verbs_iface_t *iface = ucs_derived_of(iface_h, uct_ud_verbs_iface_t);
    uct_sockaddr_ib_t *if_addr = (uct_sockaddr_ib_t *)addr;
    uct_ud_send_skb_t *skb;
    struct ibv_ah *ah;
    ucs_status_t status;


    /* check if we can reuse half duplex ep */
    ready_ep = uct_ud_iface_cep_lookup(&iface->super, if_addr, UCT_UD_EP_CONN_ID_MAX);
    if (ready_ep) {
        *new_ep_p = &ready_ep->super.super;
        return UCS_OK;
    }

    status = iface_h->ops.ep_create(iface_h, new_ep_p);
    if (status != UCS_OK) {
        return status;
    }
    ep = ucs_derived_of(*new_ep_p, uct_ud_verbs_ep_t);

    status = uct_ud_ep_connect_to_iface(&ep->super, addr);
    if (status != UCS_OK) {
        return status;
    }
    ucs_assert_always(ep->ah == NULL);
    ah = uct_ib_create_ah(&iface->super.super, if_addr->lid);
    if (ah == NULL) {
        ucs_error("failed to create address handle: %m");
        status = UCS_ERR_INVALID_ADDR;
        goto err1;
    }
    ep->ah = ah;
    
    status = uct_ud_iface_cep_insert(&iface->super, if_addr, &ep->super, UCT_UD_EP_CONN_ID_MAX);
    if (status != UCS_OK) {
        goto err2;
    }

    skb = uct_ud_ep_prepare_creq(&ep->super);
    if (!skb) {
        status = UCS_ERR_NO_RESOURCE;
        goto err3;
    }

    iface->tx.sge[0].addr   = (uintptr_t)skb->neth;
    iface->tx.sge[0].length = skb->len;
    uct_ud_verbs_iface_tx_ctl(iface, ep);
    ucs_trace_data("TX: CREQ (qp=%x lid=%d)", if_addr->qp_num, if_addr->lid);
    return UCS_OK;

err3:
    uct_ud_iface_cep_rollback(&iface->super, if_addr, &ep->super);
err2:
    ibv_destroy_ah(ep->ah);
    ep->ah = NULL;
err1:
    uct_ud_ep_disconnect_from_iface(*new_ep_p);
    *new_ep_p = NULL;
    return status;
}