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; }
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; }