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