Пример #1
0
static int
usdf_domain_bind(struct fid *fid, struct fid *bfid, uint64_t flags)
{
        struct usdf_domain *udp;

	USDF_TRACE_SYS(DOMAIN, "\n");

	if (flags & FI_REG_MR) {
		USDF_WARN_SYS(DOMAIN,
			"FI_REG_MR for EQs is not supported by the usnic provider");
		return -FI_EOPNOTSUPP;
	}

        udp = dom_fidtou(fid);

        switch (bfid->fclass) {
        case FI_CLASS_EQ:
                if (udp->dom_eq != NULL) {
                        return -FI_EINVAL;
                }
                udp->dom_eq = eq_fidtou(bfid);
                ofi_atomic_inc32(&udp->dom_eq->eq_refcnt);
                break;
        default:
                return -FI_EINVAL;
        }

        return 0;
}
Пример #2
0
static int
usdf_pep_reject(struct fid_pep *pep, fid_t handle,
		const void *param, size_t paramlen)
{
	USDF_TRACE_SYS(EP_CTRL, "\n");
	return -FI_ENOSYS;
}
Пример #3
0
static int
usdf_pep_listen(struct fid_pep *fpep)
{
	struct usdf_pep *pep;
	struct epoll_event ev;
	struct usdf_fabric *fp;
	int ret;

	USDF_TRACE_SYS(EP_CTRL, "\n");

	pep = pep_ftou(fpep);
	fp = pep->pep_fabric;

	ret = listen(pep->pep_sock, pep->pep_backlog);
	if (ret != 0) {
		return -errno;
	}

	pep->pep_pollitem.pi_rtn = usdf_pep_listen_cb;
	pep->pep_pollitem.pi_context = pep;
	ev.events = EPOLLIN;
	ev.data.ptr = &pep->pep_pollitem;
	ret = epoll_ctl(fp->fab_epollfd, EPOLL_CTL_ADD, pep->pep_sock, &ev);
	if (ret == -1) {
		return -errno;
	}

	return 0;
}
Пример #4
0
static ssize_t
usdf_cq_readerr_soft(struct fid_cq *fcq, struct fi_cq_err_entry *entry,
		uint64_t flags)
{
	struct usdf_cq *cq;
	struct usdf_cq_soft_entry *tail;

	USDF_TRACE_SYS(CQ, "\n");

	cq = container_of(fcq, struct usdf_cq, cq_fid);

	tail = cq->c.soft.cq_tail;

	entry->op_context = tail->cse_context;
	entry->flags = 0;
	entry->prov_errno = tail->cse_prov_errno;
	entry->err = entry->prov_errno;

	tail++;
	if (tail == cq->c.soft.cq_end) {
		tail = cq->c.soft.cq_comps;
	}
	cq->c.soft.cq_tail = tail;

	return 1;
}
Пример #5
0
static int
usdf_pep_bind(fid_t fid, fid_t bfid, uint64_t flags)
{
    struct usdf_pep *pep;

    USDF_TRACE_SYS(EP_CTRL, "\n");

    pep = pep_fidtou(fid);

    switch (bfid->fclass) {

    case FI_CLASS_EQ:
        if (pep->pep_eq != NULL) {
            return -FI_EINVAL;
        }
        pep->pep_eq = eq_fidtou(bfid);
        atomic_inc(&pep->pep_eq->eq_refcnt);
        break;

    default:
        return -FI_EINVAL;
    }

    return 0;
}
Пример #6
0
static int
usdf_domain_close(fid_t fid)
{
	struct usdf_domain *udp;
	int ret;

	USDF_TRACE_SYS(DOMAIN, "\n");

	udp = container_of(fid, struct usdf_domain, dom_fid.fid);
	if (ofi_atomic_get32(&udp->dom_refcnt) > 0) {
		return -FI_EBUSY;
	}

	if (udp->dom_dev != NULL) {
		ret = usd_close(udp->dom_dev);
		if (ret != 0) {
			return ret;
		}
	}
	usdf_dom_rdc_free_data(udp);

	if (udp->dom_eq != NULL) {
		ofi_atomic_dec32(&udp->dom_eq->eq_refcnt);
	}
	ofi_atomic_dec32(&udp->dom_fabric->fab_refcnt);
	LIST_REMOVE(udp, dom_link);
	fi_freeinfo(udp->dom_info);
	free(udp);

	return 0;
}
Пример #7
0
/*
 * Return local address of an EP
 */
int usdf_cm_rdm_getname(fid_t fid, void *addr, size_t *addrlen)
{
	struct usdf_ep *ep;
	struct usdf_rx *rx;
	struct sockaddr_in sin;
	size_t copylen;

	USDF_TRACE_SYS(EP_CTRL, "\n");

	ep = ep_fidtou(fid);
	rx = ep->ep_rx;

	copylen = sizeof(sin);
	if (copylen > *addrlen) {
		copylen = *addrlen;
	}
	*addrlen = sizeof(sin);

	memset(&sin, 0, sizeof(sin));
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr =
		ep->ep_domain->dom_fabric->fab_dev_attrs->uda_ipaddr_be;
	if (rx == NULL || rx->rx_qp == NULL) {
		sin.sin_port = 0;
	} else {
		sin.sin_port = to_qpi(rx->rx_qp)->uq_attrs.uqa_local_addr.ul_addr.ul_udp.u_addr.sin_port;
	}
	memcpy(addr, &sin, copylen);

	if (copylen < sizeof(sin)) {
		return -FI_ETOOSMALL;
	} else {
		return 0;
	}
}
Пример #8
0
ssize_t
usdf_dgram_senddata(struct fid_ep *fep, const void *buf, size_t len,
			void *desc, uint64_t data, fi_addr_t dest_addr,
			void *context)
{
	USDF_TRACE_SYS(EP_DATA, "\n"); /* XXX delete once implemented */
	return -FI_ENOSYS;
}
Пример #9
0
static int
usdf_pep_listen(struct fid_pep *fpep)
{
    struct usdf_pep *pep;
    struct epoll_event ev;
    struct usdf_fabric *fp;
    int ret;

    USDF_TRACE_SYS(EP_CTRL, "\n");

    pep = pep_ftou(fpep);
    fp = pep->pep_fabric;

    switch (pep->pep_state) {
    case USDF_PEP_UNBOUND:
    case USDF_PEP_BOUND:
        break;
    case USDF_PEP_LISTENING:
        USDF_WARN_SYS(EP_CTRL, "PEP already LISTENING!\n");
        return -FI_EOPBADSTATE;
    case USDF_PEP_ROBBED:
        USDF_WARN_SYS(EP_CTRL,
                      "PEP already consumed, you may only fi_close() now\n");
        return -FI_EOPBADSTATE;
    default:
        USDF_WARN_SYS(EP_CTRL, "unhandled case!\n");
        abort();
    }

    /* we could already be bound if the user called fi_setname() or if we
     * already did the bind in a previous call to usdf_pep_listen() and the
     * listen(2) call failed */
    if (pep->pep_state == USDF_PEP_UNBOUND) {
        ret = bind(pep->pep_sock, (struct sockaddr *)&pep->pep_src_addr,
                   sizeof(struct sockaddr_in));
        if (ret == -1) {
            return -errno;
        }
        pep->pep_state = USDF_PEP_BOUND;
    }

    ret = listen(pep->pep_sock, pep->pep_backlog);
    if (ret != 0) {
        return -errno;
    }
    pep->pep_state = USDF_PEP_LISTENING;

    pep->pep_pollitem.pi_rtn = usdf_pep_listen_cb;
    pep->pep_pollitem.pi_context = pep;
    ev.events = EPOLLIN;
    ev.data.ptr = &pep->pep_pollitem;
    ret = epoll_ctl(fp->fab_epollfd, EPOLL_CTL_ADD, pep->pep_sock, &ev);
    if (ret == -1) {
        return -errno;
    }

    return 0;
}
Пример #10
0
int
usdf_cq_open(struct fid_domain *domain, struct fi_cq_attr *attr,
	    struct fid_cq **cq_o, void *context)
{
	struct usdf_cq *cq;
	struct usdf_domain *udp;
	int ret;

	USDF_TRACE_SYS(CQ, "\n");

	udp = dom_ftou(domain);
	ret = usdf_cq_process_attr(attr, udp);
	if (ret != 0) {
		return ret;
	}

	cq = calloc(1, sizeof(*cq));
	if (cq == NULL) {
		return -FI_ENOMEM;
	}

	cq->cq_domain = udp;
	cq->cq_fid.fid.fclass = FI_CLASS_CQ;
	cq->cq_fid.fid.context = context;
	cq->cq_fid.fid.ops = &usdf_cq_fi_ops;
	atomic_initialize(&cq->cq_refcnt, 0);

	switch (attr->format) {
	case FI_CQ_FORMAT_CONTEXT:
		cq->cq_fid.ops = &usdf_cq_context_ops;
		break;
	case FI_CQ_FORMAT_MSG:
		cq->cq_fid.ops = &usdf_cq_msg_ops;
		break;
	case FI_CQ_FORMAT_DATA:
		cq->cq_fid.ops = &usdf_cq_data_ops;
		break;
	default:
		ret = -FI_ENOSYS;
		goto fail;
	}

	cq->cq_attr = *attr;
	*cq_o = &cq->cq_fid;
	return 0;

fail:
	if (cq != NULL) {
		if (cq->c.hard.cq_cq != NULL) {
			usd_destroy_cq(cq->c.hard.cq_cq);
		}
		free(cq);
	}
	return ret;
}
Пример #11
0
int
usdf_endpoint_open(struct fid_domain *domain, struct fi_info *info,
	    struct fid_ep **ep_o, void *context)
{
	USDF_TRACE_SYS(EP_CTRL, "\n");

	switch (info->ep_attr->type) {
	case FI_EP_DGRAM:
		return usdf_ep_dgram_open(domain, info, ep_o, context);
	case FI_EP_MSG:
		return usdf_ep_msg_open(domain, info, ep_o, context);
	case FI_EP_RDM:
		return usdf_ep_rdm_open(domain, info, ep_o, context);
	default:
		return -FI_ENODEV;
	}
}
Пример #12
0
int usdf_cm_msg_getname(fid_t fid, void *addr, size_t *addrlen)
{
	struct usdf_ep *ep;
	size_t copylen;

	USDF_TRACE_SYS(EP_CTRL, "\n");

	ep = ep_fidtou(fid);

	copylen = MIN(sizeof(ep->e.msg.ep_lcl_addr), *addrlen);
	*addrlen = sizeof(ep->e.msg.ep_lcl_addr);
	memcpy(addr, &ep->e.msg.ep_lcl_addr, copylen);

	if (copylen < sizeof(ep->e.msg.ep_lcl_addr))
		return -FI_ETOOSMALL;
	else
		return 0;
}
Пример #13
0
static int
usdf_cq_close(fid_t fid)
{
	struct usdf_cq *cq;
	struct usdf_cq_hard *hcq;
	int ret;

	USDF_TRACE_SYS(CQ, "\n");

	cq = container_of(fid, struct usdf_cq, cq_fid.fid);
	if (atomic_get(&cq->cq_refcnt) > 0) {
		return -FI_EBUSY;
	}

	if (usdf_cq_is_soft(cq)) {
		while (!TAILQ_EMPTY(&cq->c.soft.cq_list)) {
			hcq = TAILQ_FIRST(&cq->c.soft.cq_list);
			if (atomic_get(&hcq->cqh_refcnt) > 0) {
				return -FI_EBUSY;
			}
			TAILQ_REMOVE(&cq->c.soft.cq_list, hcq, cqh_link);
			if (hcq->cqh_ucq != NULL) {
				ret = usd_destroy_cq(hcq->cqh_ucq);
				if (ret != 0) {
					return ret;
				}
			}
			free(hcq);
		}
	} else {
		if (cq->c.hard.cq_cq) {
			ret = usd_destroy_cq(cq->c.hard.cq_cq);
			if (ret != 0) {
				return ret;
			}
		}
	}

	free(cq);
	return 0;
}
Пример #14
0
static ssize_t
usdf_cq_readerr(struct fid_cq *fcq, struct fi_cq_err_entry *entry,
	        uint64_t flags)
{
	struct usdf_cq *cq;

	USDF_TRACE_SYS(CQ, "\n");

	cq = container_of(fcq, struct usdf_cq, cq_fid);

	// The return values are analogous to sockets cq_readerr
	if (cq->cq_comp.uc_status == 0) {
		return -FI_EAGAIN;
	}

	entry->op_context = cq->cq_comp.uc_context;
	entry->flags = 0;
	switch (cq->cq_comp.uc_status) {
	case USD_COMPSTAT_SUCCESS:
		entry->prov_errno = FI_SUCCESS;
		break;
	case USD_COMPSTAT_ERROR_CRC:
		entry->prov_errno = FI_ECRC;
		break;
	case USD_COMPSTAT_ERROR_TRUNC:
		entry->prov_errno = FI_ETRUNC;
		break;
	case USD_COMPSTAT_ERROR_TIMEOUT:
		entry->prov_errno = FI_ETIMEDOUT;
		break;
	case USD_COMPSTAT_ERROR_INTERNAL:
	default:
		entry->prov_errno = FI_EOTHER;
		break;
	}
	entry->err = entry->prov_errno;

	cq->cq_comp.uc_status = 0;

	return 1;
}
Пример #15
0
static int usdf_pep_getname(fid_t fid, void *addr, size_t *addrlen)
{
    int ret;
    struct usdf_pep *pep;
    size_t copylen;

    USDF_TRACE_SYS(EP_CTRL, "\n");

    ret = FI_SUCCESS;
    pep = pep_fidtou(fid);

    copylen = sizeof(pep->pep_src_addr);
    memcpy(addr, &pep->pep_src_addr, MIN(copylen, *addrlen));

    if (*addrlen < copylen) {
        USDF_WARN_SYS(EP_CTRL, "*addrlen is too short\n");
        ret = -FI_ETOOSMALL;
    }

    *addrlen = copylen;
    return ret;
}
Пример #16
0
int usdf_cm_dgram_getname(fid_t fid, void *addr, size_t *addrlen)
{
	int ret;
	struct usdf_ep *ep;
	struct sockaddr_in sin;
	socklen_t slen;
	size_t copylen;

	USDF_TRACE_SYS(EP_CTRL, "\n");

	ep = ep_fidtou(fid);

	copylen = MIN(sizeof(sin), *addrlen);
	*addrlen = sizeof(sin);

	memset(&sin, 0, sizeof(sin));
	if (ep->e.dg.ep_qp == NULL) {
		sin.sin_family = AF_INET;
		sin.sin_addr.s_addr =
			ep->ep_domain->dom_fabric->fab_dev_attrs->uda_ipaddr_be;
		sin.sin_port = 0;
	} else {
		slen = sizeof(sin);
		ret = getsockname(ep->e.dg.ep_sock, (struct sockaddr *)&sin, &slen);
		if (ret == -1) {
			return -errno;
		}
		assert(((struct sockaddr *)&sin)->sa_family == AF_INET);
		assert(slen == sizeof(sin));
		assert(sin.sin_addr.s_addr ==
			ep->ep_domain->dom_fabric->fab_dev_attrs->uda_ipaddr_be);
	}
	memcpy(addr, &sin, copylen);

	if (copylen < sizeof(sin))
		return -FI_ETOOSMALL;
	else
		return 0;
}
Пример #17
0
static int
usdf_pep_close(fid_t fid)
{
	struct usdf_pep *pep;

	USDF_TRACE_SYS(EP_CTRL, "\n");

	pep = pep_fidtou(fid);
	if (atomic_get(&pep->pep_refcnt) > 0) {
		return -FI_EBUSY;
	}

	usdf_pep_free_cr_lists(pep);
	close(pep->pep_sock);
	if (pep->pep_eq != NULL) {
		atomic_dec(&pep->pep_eq->eq_refcnt);
	}
	atomic_dec(&pep->pep_fabric->fab_refcnt);
	free(pep);

	return 0;
}
Пример #18
0
static int
usdf_domain_bind(struct fid *fid, struct fid *bfid, uint64_t flags)
{
        struct usdf_domain *udp;

	USDF_TRACE_SYS(DOMAIN, "\n");

        udp = dom_fidtou(fid);

        switch (bfid->fclass) {
        case FI_CLASS_EQ:
                if (udp->dom_eq != NULL) {
                        return -FI_EINVAL;
                }
                udp->dom_eq = eq_fidtou(bfid);
                atomic_inc(&udp->dom_eq->eq_refcnt);
                break;
        default:
                return -FI_EINVAL;
        }

        return 0;
}
Пример #19
0
int
usdf_cm_msg_shutdown(struct fid_ep *ep, uint64_t flags)
{
	USDF_TRACE_SYS(EP_CTRL, "\n");
	return -FI_ENOSYS;
}
Пример #20
0
int
usdf_cm_msg_connect(struct fid_ep *fep, const void *addr,
		const void *param, size_t paramlen)
{
	struct usdf_connreq *crp;
	struct usdf_ep *ep;
	struct usdf_rx *rx;
	struct usdf_domain *udp;
	const struct sockaddr_in *sin;
	struct epoll_event ev;
	struct usdf_fabric *fp;
	struct usdf_connreq_msg *reqp;
	struct usd_qp_impl *qp;
	int ret;

	USDF_TRACE_SYS(EP_CTRL, "\n");

	if (paramlen > USDF_MAX_CONN_DATA)
		return -FI_EINVAL;

	ep = ep_ftou(fep);
	udp = ep->ep_domain;
	fp = udp->dom_fabric;
	sin = addr;
	crp = NULL;

	crp = calloc(1, sizeof(*crp) + sizeof(struct usdf_connreq_msg) +
			paramlen);
	if (crp == NULL) {
		ret = -errno;
		goto fail;
	}

	crp->handle.fclass = FI_CLASS_CONNREQ;
	crp->cr_sockfd = socket(AF_INET, SOCK_STREAM, 0);
	if (crp->cr_sockfd == -1) {
		ret = -errno;
		goto fail;
	}

	ret = fcntl(crp->cr_sockfd, F_GETFL, 0);
	if (ret == -1) {
		ret = -errno;
		goto fail;
	}
	ret = fcntl(crp->cr_sockfd, F_SETFL, ret | O_NONBLOCK);
	if (ret == -1) {
		ret = -errno;
		goto fail;
	}

	ret = usdf_ep_msg_get_queues(ep);
	if (ret != 0) {
		goto fail;
	}
	rx = ep->ep_rx;
	qp = to_qpi(rx->rx_qp);

	ret = connect(crp->cr_sockfd, (struct sockaddr *)sin, sizeof(*sin));
	if (ret != 0 && errno != EINPROGRESS) {
		ret = -errno;
		goto fail;
	}

	/* register for notification when connect completes */
	crp->cr_pollitem.pi_rtn = usdf_cm_msg_connect_cb_wr;
	crp->cr_pollitem.pi_context = crp;
	ev.events = EPOLLOUT;
	ev.data.ptr = &crp->cr_pollitem;
	ret = epoll_ctl(fp->fab_epollfd, EPOLL_CTL_ADD, crp->cr_sockfd, &ev);
	if (ret != 0) {
		crp->cr_pollitem.pi_rtn = NULL;
		ret = -errno;
		goto fail;
	}

	/* allocate remote peer ID */
	ep->e.msg.ep_rem_peer_id = udp->dom_next_peer;
	udp->dom_peer_tab[udp->dom_next_peer] = ep;
	++udp->dom_next_peer;

	crp->cr_ep = ep;
	reqp = (struct usdf_connreq_msg *)crp->cr_data;
	crp->cr_ptr = crp->cr_data;
	crp->cr_resid =  sizeof(*reqp) + paramlen;

	reqp->creq_peer_id = htons(ep->e.msg.ep_rem_peer_id);
	reqp->creq_ipaddr = fp->fab_dev_attrs->uda_ipaddr_be;
	reqp->creq_port =
		qp->uq_attrs.uqa_local_addr.ul_addr.ul_udp.u_addr.sin_port;
	memcpy(reqp->creq_mac, fp->fab_dev_attrs->uda_mac_addr, ETH_ALEN);
	reqp->creq_datalen = htonl(paramlen);
	memcpy(reqp->creq_data, param, paramlen);

	return 0;

fail:
	if (crp != NULL) {
		if (crp->cr_sockfd != -1) {
			close(crp->cr_sockfd);
		}
		free(crp);
	}
	usdf_ep_msg_release_queues(ep);
	return ret;
}
Пример #21
0
int
usdf_cm_msg_accept(struct fid_ep *fep, const void *param, size_t paramlen)
{
	struct usdf_ep *ep;
	struct usdf_rx *rx;
	struct usdf_domain *udp;
	struct usdf_fabric *fp;
	struct usdf_connreq *crp;
	struct usdf_connreq_msg *reqp;
	struct usd_qp_impl *qp;
	int ret;
	int n;

	USDF_TRACE_SYS(EP_CTRL, "\n");

	if (paramlen > USDF_MAX_CONN_DATA)
		return -FI_EINVAL;

	ep = ep_ftou(fep);
	udp = ep->ep_domain;
	fp = udp->dom_fabric;
	crp = ep->e.msg.ep_connreq;
	if (crp == NULL) {
		return -FI_ENOTCONN;
	}
	if (ep->ep_eq == NULL) {
		return -FI_ENOEQ;
	}
	crp->cr_ep = ep;
	reqp = (struct usdf_connreq_msg *)crp->cr_data;

	ep->e.msg.ep_lcl_peer_id = ntohs(reqp->creq_peer_id);

	/* start creating the dest early */
	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) {
		goto fail;
	}

	ret = usdf_ep_msg_get_queues(ep);
	if (ret != 0) {
		goto fail;
	}
	rx = ep->ep_rx;
	qp = to_qpi(rx->rx_qp);

	/* allocate a peer ID */
	ep->e.msg.ep_rem_peer_id = udp->dom_next_peer;
	udp->dom_peer_tab[udp->dom_next_peer] = ep;
	++udp->dom_next_peer;

	crp->cr_ptr = crp->cr_data;
	crp->cr_resid = sizeof(*reqp) + paramlen;

	reqp->creq_peer_id = htons(ep->e.msg.ep_rem_peer_id);
	reqp->creq_ipaddr = fp->fab_dev_attrs->uda_ipaddr_be;
	reqp->creq_port =
		qp->uq_attrs.uqa_local_addr.ul_addr.ul_udp.u_addr.sin_port;
	memcpy(reqp->creq_mac, fp->fab_dev_attrs->uda_mac_addr, ETH_ALEN);
	reqp->creq_result = htonl(0);
	reqp->creq_datalen = htonl(paramlen);
	memcpy(reqp->creq_data, param, paramlen);

	n = write(crp->cr_sockfd, crp->cr_ptr, crp->cr_resid);
	if (n == -1) {
		usdf_cm_msg_connreq_cleanup(crp);
		ret = -errno;
		goto fail;
	}

	crp->cr_resid -= n;
	if (crp->cr_resid == 0) {
		usdf_cm_msg_accept_complete(crp);
	} else {
		// XXX set up epoll junk to send rest
	}

	return 0;
fail:
	free(ep->e.msg.ep_dest);
	/* XXX release queues */
	return ret;
}
Пример #22
0
int
usdf_cm_msg_connect(struct fid_ep *fep, const void *addr,
		const void *param, size_t paramlen)
{
	struct usdf_connreq *crp;
	struct usdf_ep *ep;
	struct usdf_rx *rx;
	struct usdf_domain *udp;
	const struct sockaddr_in *sin;
	struct epoll_event ev;
	struct usdf_fabric *fp;
	struct usdf_connreq_msg *reqp;
	struct usd_qp_impl *qp;
	size_t request_size;
	int ret;

	USDF_TRACE_SYS(EP_CTRL, "\n");

	if (paramlen > USDF_MAX_CONN_DATA)
		return -FI_EINVAL;

	ep = ep_ftou(fep);
	udp = ep->ep_domain;
	fp = udp->dom_fabric;
	sin = addr;

	/* Although paramlen may be less than USDF_MAX_CONN_DATA, the same crp
	 * struct is used for receiving the accept and reject payload. The
	 * structure has to be prepared to receive the maximum allowable amount
	 * of data per transfer. The maximum size includes the connection
	 * request structure, the connection request message, and the maximum
	 * amount of data per connection request message.
	 */
	request_size = sizeof(*crp) + sizeof(*reqp) + USDF_MAX_CONN_DATA;
	crp = calloc(1, request_size);
	if (crp == NULL) {
		ret = -errno;
		goto fail;
	}
	ep->e.msg.ep_connreq = crp;

	crp->handle.fclass = FI_CLASS_CONNREQ;

	if (ep->e.msg.ep_cm_sock == -1) {
		crp->cr_sockfd = socket(AF_INET, SOCK_STREAM, 0);
		if (crp->cr_sockfd == -1) {
			ret = -errno;
			goto fail;
		}
	} else {
		crp->cr_sockfd = ep->e.msg.ep_cm_sock;
		ep->e.msg.ep_cm_sock = -1;
	}

	ret = fi_fd_nonblock(crp->cr_sockfd);
	if (ret) {
		ret = -errno;
		goto fail;
	}

	ret = usdf_ep_msg_get_queues(ep);
	if (ret != 0) {
		goto fail;
	}
	rx = ep->ep_rx;
	qp = to_qpi(rx->rx_qp);

	ret = connect(crp->cr_sockfd, (struct sockaddr *)sin, sizeof(*sin));
	if (ret != 0 && errno != EINPROGRESS) {
		ret = -errno;
		goto fail;
	}

	/* If cr_sockfd was previously unbound, connect(2) will do a a bind(2)
	 * for us.  Update our snapshot of the locally bound address. */
	ret = usdf_msg_upd_lcl_addr(ep);
	if (ret)
		goto fail;

	/* allocate remote peer ID */
	ep->e.msg.ep_rem_peer_id = udp->dom_next_peer;
	udp->dom_peer_tab[udp->dom_next_peer] = ep;
	++udp->dom_next_peer;

	crp->cr_ep = ep;
	reqp = (struct usdf_connreq_msg *)crp->cr_data;
	crp->cr_ptr = crp->cr_data;
	crp->cr_resid =  sizeof(*reqp) + paramlen;

	reqp->creq_peer_id = htons(ep->e.msg.ep_rem_peer_id);
	reqp->creq_ipaddr = fp->fab_dev_attrs->uda_ipaddr_be;
	reqp->creq_port =
		qp->uq_attrs.uqa_local_addr.ul_addr.ul_udp.u_addr.sin_port;
	reqp->creq_datalen = htonl(paramlen);
	memcpy(reqp->creq_data, param, paramlen);

	/* register for notification when connect completes */
	crp->cr_pollitem.pi_rtn = usdf_cm_msg_connect_cb_wr;
	crp->cr_pollitem.pi_context = crp;
	ev.events = EPOLLOUT;
	ev.data.ptr = &crp->cr_pollitem;
	ret = epoll_ctl(fp->fab_epollfd, EPOLL_CTL_ADD, crp->cr_sockfd, &ev);
	if (ret != 0) {
		crp->cr_pollitem.pi_rtn = NULL;
		ret = -errno;
		goto fail;
	}

	return 0;

fail:
	if (crp != NULL) {
		if (crp->cr_sockfd != -1) {
			close(crp->cr_sockfd);
		}
		free(crp);
		ep->e.msg.ep_connreq = NULL;
	}
	usdf_ep_msg_release_queues(ep);
	return ret;
}
Пример #23
0
int
usdf_pep_open(struct fid_fabric *fabric, struct fi_info *info,
              struct fid_pep **pep_o, void *context)
{
    struct usdf_pep *pep;
    struct usdf_fabric *fp;
    struct sockaddr_in *sin;
    int ret;
    int optval;

    USDF_TRACE_SYS(EP_CTRL, "\n");

    if (!info) {
        USDF_DBG_SYS(EP_CTRL, "null fi_info struct is invalid\n");
        return -FI_EINVAL;
    }

    if (info->ep_attr->type != FI_EP_MSG) {
        return -FI_ENODEV;
    }

    if ((info->caps & ~USDF_MSG_CAPS) != 0) {
        return -FI_EBADF;
    }

    switch (info->addr_format) {
    case FI_SOCKADDR:
        if (((struct sockaddr *)info->src_addr)->sa_family != AF_INET) {
            USDF_WARN_SYS(EP_CTRL, "non-AF_INET src_addr specified\n");
            return -FI_EINVAL;
        }
        break;
    case FI_SOCKADDR_IN:
        break;
    default:
        USDF_WARN_SYS(EP_CTRL, "unknown/unsupported addr_format\n");
        return -FI_EINVAL;
    }

    if (info->src_addrlen &&
            info->src_addrlen != sizeof(struct sockaddr_in)) {
        USDF_WARN_SYS(EP_CTRL, "unexpected src_addrlen\n");
        return -FI_EINVAL;
    }

    fp = fab_ftou(fabric);

    pep = calloc(1, sizeof(*pep));
    if (pep == NULL) {
        return -FI_ENOMEM;
    }

    pep->pep_fid.fid.fclass = FI_CLASS_PEP;
    pep->pep_fid.fid.context = context;
    pep->pep_fid.fid.ops = &usdf_pep_ops;
    pep->pep_fid.ops = &usdf_pep_base_ops;
    pep->pep_fid.cm = &usdf_pep_cm_ops;
    pep->pep_fabric = fp;

    pep->pep_state = USDF_PEP_UNBOUND;
    pep->pep_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (pep->pep_sock == -1) {
        ret = -errno;
        goto fail;
    }
    ret = fcntl(pep->pep_sock, F_GETFL, 0);
    if (ret == -1) {
        ret = -errno;
        goto fail;
    }
    ret = fcntl(pep->pep_sock, F_SETFL, ret | O_NONBLOCK);
    if (ret == -1) {
        ret = -errno;
        goto fail;
    }

    /* set SO_REUSEADDR to prevent annoying "Address already in use" errors
     * on successive runs of programs listening on a well known port */
    optval = 1;
    ret = setsockopt(pep->pep_sock, SOL_SOCKET, SO_REUSEADDR, &optval,
                     sizeof(optval));
    if (ret == -1) {
        ret = -errno;
        goto fail;
    }

    pep->pep_info = fi_dupinfo(info);
    if (!pep->pep_info) {
        ret = -FI_ENOMEM;
        goto fail;
    }

    if (info->src_addrlen == 0) {
        /* Copy the source address information from the device
         * attributes.
         */
        pep->pep_info->src_addrlen = sizeof(struct sockaddr_in);
        sin = calloc(1, pep->pep_info->src_addrlen);
        if (!sin) {
            USDF_WARN_SYS(EP_CTRL,
                          "calloc for src address failed\n");
            goto fail;
        }

        sin->sin_family = AF_INET;
        sin->sin_addr.s_addr = fp->fab_dev_attrs->uda_ipaddr_be;
        pep->pep_info->src_addr = sin;
    }

    memcpy(&pep->pep_src_addr, pep->pep_info->src_addr,
           pep->pep_info->src_addrlen);

    /* initialize connreq freelist */
    ret = pthread_spin_init(&pep->pep_cr_lock, PTHREAD_PROCESS_PRIVATE);
    if (ret != 0) {
        ret = -ret;
        goto fail;
    }
    TAILQ_INIT(&pep->pep_cr_free);
    TAILQ_INIT(&pep->pep_cr_pending);
    pep->pep_backlog = 10;
    ret = usdf_pep_grow_backlog(pep);
    if (ret != 0) {
        goto fail;
    }

    atomic_initialize(&pep->pep_refcnt, 0);
    atomic_inc(&fp->fab_refcnt);

    *pep_o = pep_utof(pep);
    return 0;

fail:
    if (pep != NULL) {
        usdf_pep_free_cr_lists(pep);
        if (pep->pep_sock != -1) {
            close(pep->pep_sock);
        }
        fi_freeinfo(pep->pep_info);
        free(pep);
    }
    return ret;
}
Пример #24
0
static int usdf_pep_setname(fid_t fid, void *addr, size_t addrlen)
{
    int ret;
    struct usdf_pep *pep;
    uint32_t req_addr_be;
    socklen_t socklen;
    char namebuf[INET_ADDRSTRLEN];
    char servbuf[INET_ADDRSTRLEN];

    USDF_TRACE_SYS(EP_CTRL, "\n");

    pep = pep_fidtou(fid);
    if (pep->pep_state != USDF_PEP_UNBOUND) {
        USDF_WARN_SYS(EP_CTRL, "PEP cannot be bound\n");
        return -FI_EOPBADSTATE;
    }
    if (((struct sockaddr *)addr)->sa_family != AF_INET) {
        USDF_WARN_SYS(EP_CTRL, "non-AF_INET address given\n");
        return -FI_EINVAL;
    }
    if (addrlen != sizeof(struct sockaddr_in)) {
        USDF_WARN_SYS(EP_CTRL, "unexpected src_addrlen\n");
        return -FI_EINVAL;
    }

    req_addr_be = ((struct sockaddr_in *)addr)->sin_addr.s_addr;

    namebuf[0] = '\0';
    servbuf[0] = '\0';
    ret = getnameinfo((struct sockaddr*)addr, addrlen,
                      namebuf, sizeof(namebuf),
                      servbuf, sizeof(servbuf),
                      NI_NUMERICHOST|NI_NUMERICSERV);
    if (ret != 0)
        USDF_WARN_SYS(EP_CTRL, "unable to getnameinfo(0x%x)\n",
                      req_addr_be);

    if (req_addr_be != pep->pep_fabric->fab_dev_attrs->uda_ipaddr_be) {
        USDF_WARN_SYS(EP_CTRL, "requested addr (%s:%s) does not match fabric addr\n",
                      namebuf, servbuf);
        return -FI_EADDRNOTAVAIL;
    }

    ret = bind(pep->pep_sock, (struct sockaddr *)addr,
               sizeof(struct sockaddr_in));
    if (ret == -1) {
        return -errno;
    }
    pep->pep_state = USDF_PEP_BOUND;

    /* store the resulting port so that can implement getname() properly */
    socklen = sizeof(pep->pep_src_addr);
    ret = getsockname(pep->pep_sock, &pep->pep_src_addr, &socklen);
    if (ret == -1) {
        ret = -errno;
        USDF_WARN_SYS(EP_CTRL, "getsockname failed %d (%s), PEP may be in bad state\n",
                      ret, strerror(-ret));
        return ret;
    }

    return 0;
}
Пример #25
0
static ssize_t
usdf_pep_cancel(fid_t fid, void *context)
{
	USDF_TRACE_SYS(EP_CTRL, "\n");
	return -FI_EINVAL;
}
Пример #26
0
int
usdf_pep_open(struct fid_fabric *fabric, struct fi_info *info,
	    struct fid_pep **pep_o, void *context)
{
	struct usdf_pep *pep;
	struct usdf_fabric *fp;
	int ret;
	int optval;

	USDF_TRACE_SYS(EP_CTRL, "\n");

	if (info->ep_attr->type != FI_EP_MSG) {
		return -FI_ENODEV;
	}

	if ((info->caps & ~USDF_MSG_CAPS) != 0) {
		return -FI_EBADF;
	}

	fp = fab_ftou(fabric);

	pep = calloc(1, sizeof(*pep));
	if (pep == NULL) {
		return -FI_ENOMEM;
	}

	pep->pep_fid.fid.fclass = FI_CLASS_PEP;
	pep->pep_fid.fid.context = context;
	pep->pep_fid.fid.ops = &usdf_pep_ops;
	pep->pep_fid.ops = &usdf_pep_base_ops;
	pep->pep_fid.cm = &usdf_pep_cm_ops;
	pep->pep_fabric = fp;

	pep->pep_sock = socket(AF_INET, SOCK_STREAM, 0);
	if (pep->pep_sock == -1) {
		ret = -errno;
		goto fail;
	}
        ret = fcntl(pep->pep_sock, F_GETFL, 0);
        if (ret == -1) {
                ret = -errno;
                goto fail;
        }
        ret = fcntl(pep->pep_sock, F_SETFL, ret | O_NONBLOCK);
        if (ret == -1) {
                ret = -errno;
                goto fail;
        }

	/* set SO_REUSEADDR to prevent annoying "Address already in use" errors
	 * on successive runs of programs listening on a well known port */
	optval = 1;
	ret = setsockopt(pep->pep_sock, SOL_SOCKET, SO_REUSEADDR, &optval,
				sizeof(optval));
	if (ret == -1) {
		ret = -errno;
		goto fail;
	}

	ret = bind(pep->pep_sock, (struct sockaddr *)info->src_addr,
			info->src_addrlen);
	if (ret == -1) {
		ret = -errno;
		goto fail;
	}

	/* initialize connreq freelist */
	ret = pthread_spin_init(&pep->pep_cr_lock, PTHREAD_PROCESS_PRIVATE);
	if (ret != 0) {
		ret = -ret;
		goto fail;
	}
	TAILQ_INIT(&pep->pep_cr_free);
	TAILQ_INIT(&pep->pep_cr_pending);
	pep->pep_backlog = 10;
	ret = usdf_pep_grow_backlog(pep);
	if (ret != 0) {
		goto fail;
	}

	atomic_initialize(&pep->pep_refcnt, 0);
	atomic_inc(&fp->fab_refcnt);

	*pep_o = pep_utof(pep);
	return 0;

fail:
	if (pep != NULL) {
		usdf_pep_free_cr_lists(pep);
		if (pep->pep_sock != -1) {
			close(pep->pep_sock);
		}
		free(pep);
	}
	return ret;
}
Пример #27
0
int
usdf_domain_open(struct fid_fabric *fabric, struct fi_info *info,
	   struct fid_domain **domain, void *context)
{
	struct usdf_fabric *fp;
	struct usdf_domain *udp;
	struct sockaddr_in *sin;
	size_t addrlen;
	int ret;
#if ENABLE_DEBUG
	char requested[INET_ADDRSTRLEN], actual[INET_ADDRSTRLEN];
#endif

	USDF_TRACE_SYS(DOMAIN, "\n");
	sin = NULL;

	fp = fab_fidtou(fabric);

	if (info->domain_attr != NULL) {
		/* No versioning information available here. */
		if (!usdf_domain_checkname(0, fp->fab_dev_attrs,
					   info->domain_attr->name)) {
			USDF_WARN_SYS(DOMAIN, "domain name mismatch\n");
			return -FI_ENODATA;
		}

		if (ofi_check_mr_mode(fabric->api_version,
				      OFI_MR_BASIC_MAP | FI_MR_LOCAL,
				      info->domain_attr->mr_mode)) {
			/* the caller ignored our fi_getinfo results */
			USDF_WARN_SYS(DOMAIN, "MR mode (%d) not supported\n",
				      info->domain_attr->mr_mode);
			return -FI_ENODATA;
		}
	}

	udp = calloc(1, sizeof *udp);
	if (udp == NULL) {
		USDF_DBG("unable to alloc mem for domain\n");
		ret = -FI_ENOMEM;
		goto fail;
	}

	USDF_DBG("uda_devname=%s\n", fp->fab_dev_attrs->uda_devname);

	/*
	 * Make sure address format is good and matches this fabric
	 */
	switch (info->addr_format) {
	case FI_SOCKADDR:
		addrlen = sizeof(struct sockaddr);
		sin = info->src_addr;
		break;
	case FI_SOCKADDR_IN:
		addrlen = sizeof(struct sockaddr_in);
		sin = info->src_addr;
		break;
	case FI_ADDR_STR:
		sin = usdf_format_to_sin(info, info->src_addr);
		goto skip_size_check;
	default:
		ret = -FI_EINVAL;
		goto fail;
	}

	if (info->src_addrlen != addrlen) {
		ret =  -FI_EINVAL;
		goto fail;
	}

skip_size_check:
	if (sin->sin_family != AF_INET ||
	    sin->sin_addr.s_addr != fp->fab_dev_attrs->uda_ipaddr_be) {
		USDF_DBG_SYS(DOMAIN, "requested src_addr (%s) != fabric addr (%s)\n",
			inet_ntop(AF_INET, &sin->sin_addr.s_addr,
				requested, sizeof(requested)),
			inet_ntop(AF_INET, &fp->fab_dev_attrs->uda_ipaddr_be,
				actual, sizeof(actual)));

		ret = -FI_EINVAL;
		usdf_free_sin_if_needed(info, sin);
		goto fail;
	}
	usdf_free_sin_if_needed(info, sin);

	ret = usd_open(fp->fab_dev_attrs->uda_devname, &udp->dom_dev);
	if (ret != 0) {
		goto fail;
	}

	udp->dom_fid.fid.fclass = FI_CLASS_DOMAIN;
	udp->dom_fid.fid.context = context;
	udp->dom_fid.fid.ops = &usdf_fid_ops;
	udp->dom_fid.ops = &usdf_domain_ops;
	udp->dom_fid.mr = &usdf_domain_mr_ops;

	ret = pthread_spin_init(&udp->dom_progress_lock,
			PTHREAD_PROCESS_PRIVATE);
	if (ret != 0) {
		ret = -ret;
		goto fail;
	}
	TAILQ_INIT(&udp->dom_tx_ready);
	TAILQ_INIT(&udp->dom_hcq_list);

	udp->dom_info = fi_dupinfo(info);
	if (udp->dom_info == NULL) {
		ret = -FI_ENOMEM;
		goto fail;
	}
	if (udp->dom_info->dest_addr != NULL) {
		free(udp->dom_info->dest_addr);
		udp->dom_info->dest_addr = NULL;
	}

	ret = usdf_dom_rdc_alloc_data(udp);
	if (ret != 0) {
		goto fail;
	}

	udp->dom_fabric = fp;
	LIST_INSERT_HEAD(&fp->fab_domain_list, udp, dom_link);
	ofi_atomic_initialize32(&udp->dom_refcnt, 0);
	ofi_atomic_inc32(&fp->fab_refcnt);

	*domain = &udp->dom_fid;
	return 0;

fail:
	if (udp != NULL) {
		if (udp->dom_info != NULL) {
			fi_freeinfo(udp->dom_info);
		}
		if (udp->dom_dev != NULL) {
			usd_close(udp->dom_dev);
		}
		usdf_dom_rdc_free_data(udp);
		free(udp);
	}
	return ret;
}