/* * Connection request attempt failed */ void usdf_cm_msg_connreq_failed(struct usdf_connreq *crp, int error) { struct usdf_pep *pep; struct usdf_ep *ep; struct usdf_eq *eq; fid_t fid; struct fi_eq_err_entry err; pep = crp->cr_pep; ep = crp->cr_ep; if (ep != NULL) { fid = ep_utofid(ep); eq = ep->ep_eq; ep->ep_domain->dom_peer_tab[ep->e.msg.ep_rem_peer_id] = NULL; } else { fid = pep_utofid(pep); eq = pep->pep_eq; } err.fid = fid; err.context = NULL; err.data = 0; err.err = -error; err.prov_errno = 0; err.err_data = NULL; err.err_data_size = 0; usdf_eq_write_internal(eq, 0, &err, sizeof(err), USDF_EVENT_FLAG_ERROR); usdf_cm_msg_connreq_cleanup(crp); }
/* Report a connection management related failure. Sometimes there is connection * event data that should be copied into the generated event. If the copy_data * parameter evaluates to true, then the data will be copied. * * If data is to be generated for the error entry, then the connection request * is assumed to have the data size in host order. If something fails during * processing of the error data, then the EQ entry will still be generated * without the error data. */ void usdf_cm_report_failure(struct usdf_connreq *crp, int error, bool copy_data) { struct fi_eq_err_entry err = {0}; struct usdf_pep *pep; struct usdf_ep *ep; struct usdf_eq *eq; fid_t fid; int ret; USDF_DBG_SYS(EP_CTRL, "error=%d (%s)\n", error, fi_strerror(error)); pep = crp->cr_pep; ep = crp->cr_ep; if (ep != NULL) { fid = ep_utofid(ep); eq = ep->ep_eq; ep->ep_domain->dom_peer_tab[ep->e.msg.ep_rem_peer_id] = NULL; } else { fid = pep_utofid(pep); eq = pep->pep_eq; } /* Try to generate the space necessary for the error data. If the * function returns a number greater than or equal to 0, then it was a * success. The return value is the size of the data. */ if (copy_data) { ret = usdf_cm_generate_err_data(eq, crp, &err.err_data); if (ret >= 0) err.err_data_size = ret; } err.fid = fid; err.err = -error; usdf_eq_write_internal(eq, 0, &err, sizeof(err), USDF_EVENT_FLAG_ERROR); usdf_cm_msg_connreq_cleanup(crp); }
static int usdf_cm_msg_accept_complete(struct usdf_connreq *crp) { struct usdf_ep *ep; struct fi_eq_cm_entry entry; int ret; ep = crp->cr_ep; /* post EQ entry */ entry.fid = ep_utofid(ep); entry.info = NULL; ret = usdf_eq_write_internal(ep->ep_eq, FI_CONNECTED, &entry, sizeof(entry), 0); if (ret != sizeof(entry)) { usdf_cm_msg_connreq_failed(crp, ret); return 0; } usdf_cm_msg_connreq_cleanup(crp); return 0; }
/* * read connection request response from the listener */ static int usdf_cm_msg_connect_cb_rd(void *v) { struct usdf_connreq *crp; struct usdf_ep *ep; struct usdf_fabric *fp; struct usdf_domain *udp; struct usdf_connreq_msg *reqp; struct fi_eq_cm_entry *entry; size_t entry_len; int ret; crp = v; ep = crp->cr_ep; fp = ep->ep_domain->dom_fabric; ret = read(crp->cr_sockfd, crp->cr_ptr, crp->cr_resid); if (ret == -1) { usdf_cm_msg_connreq_failed(crp, -errno); return 0; } crp->cr_resid -= ret; reqp = (struct usdf_connreq_msg *)crp->cr_data; if (crp->cr_resid == 0 && crp->cr_ptr == crp->cr_data + sizeof(*reqp)) { reqp->creq_datalen = ntohl(reqp->creq_datalen); crp->cr_resid = reqp->creq_datalen; } /* if resid is 0 now, completely done */ if (crp->cr_resid == 0) { ret = epoll_ctl(fp->fab_epollfd, EPOLL_CTL_DEL, crp->cr_sockfd, NULL); close(crp->cr_sockfd); crp->cr_sockfd = -1; entry_len = sizeof(*entry) + reqp->creq_datalen; entry = malloc(entry_len); if (entry == NULL) { usdf_cm_msg_connreq_failed(crp, -errno); return 0; } udp = ep->ep_domain; ep->e.msg.ep_lcl_peer_id = ntohs(reqp->creq_peer_id); ret = usd_create_dest_with_mac(udp->dom_dev, reqp->creq_ipaddr, reqp->creq_port, reqp->creq_mac, &ep->e.msg.ep_dest); if (ret != 0) { free(entry); usdf_cm_msg_connreq_failed(crp, ret); return 0; } entry->fid = ep_utofid(ep); entry->info = NULL; memcpy(entry->data, reqp->creq_data, reqp->creq_datalen); ret = usdf_eq_write_internal(ep->ep_eq, FI_CONNECTED, entry, entry_len, 0); free(entry); if (ret != entry_len) { free(ep->e.msg.ep_dest); ep->e.msg.ep_dest = NULL; usdf_cm_msg_connreq_failed(crp, ret); return 0; } usdf_cm_msg_connreq_cleanup(crp); } return 0; }
static int usdf_pep_read_connreq(void *v) { struct usdf_connreq *crp; struct usdf_pep *pep; struct usdf_connreq_msg *reqp; struct fi_eq_cm_entry *entry; size_t entry_len; int ret; int n; crp = v; pep = crp->cr_pep; n = read(crp->cr_sockfd, crp->cr_ptr, crp->cr_resid); if (n == -1) { usdf_cm_msg_connreq_failed(crp, -errno); return 0; } crp->cr_ptr += n; crp->cr_resid -= n; reqp = (struct usdf_connreq_msg *)crp->cr_data; if (crp->cr_resid == 0 && crp->cr_ptr == crp->cr_data + sizeof(*reqp)) { reqp->creq_datalen = ntohl(reqp->creq_datalen); crp->cr_resid = reqp->creq_datalen; } /* if resid is 0 now, completely done */ if (crp->cr_resid == 0) { ret = usdf_pep_creq_epoll_del(crp); if (ret != 0) { usdf_cm_msg_connreq_failed(crp, ret); return 0; } /* create CONNREQ EQ entry */ entry_len = sizeof(*entry) + reqp->creq_datalen; entry = malloc(entry_len); if (entry == NULL) { usdf_cm_msg_connreq_failed(crp, -errno); return 0; } entry->fid = &pep->pep_fid.fid; entry->info = usdf_pep_conn_info(crp); if (entry->info == NULL) { free(entry); usdf_cm_msg_connreq_failed(crp, -FI_ENOMEM); return 0; } memcpy(entry->data, reqp->creq_data, reqp->creq_datalen); ret = usdf_eq_write_internal(pep->pep_eq, FI_CONNREQ, entry, entry_len, 0); free(entry); if (ret != (int)entry_len) { usdf_cm_msg_connreq_failed(crp, ret); return 0; } } return 0; }
/* * read connection request response from the listener */ static int usdf_cm_msg_connect_cb_rd(void *v) { struct usdf_connreq *crp; struct usdf_ep *ep; struct usdf_fabric *fp; struct usdf_domain *udp; struct usdf_connreq_msg *reqp; struct fi_eq_cm_entry *entry; size_t entry_len; int ret; crp = v; ep = crp->cr_ep; fp = ep->ep_domain->dom_fabric; ret = read(crp->cr_sockfd, crp->cr_ptr, crp->cr_resid); if (ret == -1) goto report_failure_skip_data; crp->cr_ptr += ret; crp->cr_resid -= ret; reqp = (struct usdf_connreq_msg *)crp->cr_data; if (crp->cr_resid == 0 && crp->cr_ptr == crp->cr_data + sizeof(*reqp)) { reqp->creq_datalen = ntohl(reqp->creq_datalen); crp->cr_resid = reqp->creq_datalen; } /* if resid is 0 now, completely done */ if (crp->cr_resid == 0) { reqp->creq_result = ntohl(reqp->creq_result); ret = epoll_ctl(fp->fab_epollfd, EPOLL_CTL_DEL, crp->cr_sockfd, NULL); close(crp->cr_sockfd); crp->cr_sockfd = -1; if (reqp->creq_result != FI_SUCCESS) { /* Copy the data since this was an explicit rejection. */ usdf_cm_report_failure(crp, reqp->creq_result, true); return 0; } entry_len = sizeof(*entry) + reqp->creq_datalen; entry = malloc(entry_len); if (entry == NULL) goto report_failure_skip_data; udp = ep->ep_domain; ep->e.msg.ep_lcl_peer_id = ntohs(reqp->creq_peer_id); ret = usd_create_dest(udp->dom_dev, reqp->creq_ipaddr, reqp->creq_port, &ep->e.msg.ep_dest); if (ret != 0) goto free_entry_and_report_failure; ep->e.msg.ep_dest->ds_dest.ds_udp.u_hdr.uh_ip.frag_off |= htons(IP_DF); entry->fid = ep_utofid(ep); entry->info = NULL; memcpy(entry->data, reqp->creq_data, reqp->creq_datalen); ret = usdf_eq_write_internal(ep->ep_eq, FI_CONNECTED, entry, entry_len, 0); if (ret != (int)entry_len) { free(ep->e.msg.ep_dest); ep->e.msg.ep_dest = NULL; goto free_entry_and_report_failure; } free(entry); usdf_cm_msg_connreq_cleanup(crp); } return 0; free_entry_and_report_failure: free(entry); report_failure_skip_data: usdf_cm_report_failure(crp, ret, false); return 0; }