Exemplo n.º 1
0
void rdma_backend_fini(RdmaBackendDev *backend_dev)
{
    mad_fini(backend_dev);
    g_hash_table_destroy(ah_hash);
    ibv_destroy_comp_channel(backend_dev->channel);
    ibv_close_device(backend_dev->context);
}
Exemplo n.º 2
0
static void
rdma_trans_destroy(void *a)
{
	Rdmatrans *rdma;
	struct ibv_qp_attr attr;

	rdma = a;
	if (rdma->connected)
		rdma_disconnect(rdma->cm_id);
	if (rdma->qp) {
		attr.qp_state = IBV_QPS_ERR;
		ibv_modify_qp(rdma->qp, &attr, IBV_QP_STATE);
		ibv_destroy_qp(rdma->qp);
	}
	if (rdma->cq)
		ibv_destroy_cq(rdma->cq);
	if (rdma->ch)
		ibv_destroy_comp_channel(rdma->ch);
	if (rdma->snd_mr)
		ibv_dereg_mr(rdma->snd_mr);
	if (rdma->snd_buf)
		free(rdma->snd_buf);
	if (rdma->rcv_mr)
		ibv_dereg_mr(rdma->rcv_mr);
	if (rdma->rcv_buf)
		free(rdma->rcv_buf);
	if (rdma->pd)
		ibv_dealloc_pd(rdma->pd);
	if (rdma->cm_id)
		rdma_destroy_id(rdma->cm_id);
}
Exemplo n.º 3
0
Arquivo: rping.c Projeto: hkimura/pib
static void rping_free_qp(struct rping_cb *cb)
{
	ibv_destroy_qp(cb->qp);
	ibv_destroy_cq(cb->cq);
	ibv_destroy_comp_channel(cb->channel);
	ibv_dealloc_pd(cb->pd);
}
Exemplo n.º 4
0
RDMAAdapter::~RDMAAdapter() {
  StopInternalThread();

  CHECK(!ibv_destroy_cq(cq_)) << "Failed to destroy CQ";
  CHECK(!ibv_destroy_comp_channel(channel_)) << "Failed to destroy channel";
  CHECK(!ibv_dealloc_pd(pd_)) << "Failed to deallocate PD";
  CHECK(!ibv_close_device(context_)) << "Failed to release context";
}
Exemplo n.º 5
0
void xfer_rdma_destroy_ctx(struct xfer_context *ctx) {
	rdma_destroy_qp(ctx->cm_id);
	ibv_destroy_cq(ctx->cq);
	ibv_destroy_comp_channel(ctx->ch);
	ibv_dereg_mr(ctx->send_mr);
	ibv_dereg_mr(ctx->recv_mr);
	ibv_dealloc_pd(ctx->pd);
	free(ctx);
}
Exemplo n.º 6
0
CompletionChannel& CompletionChannel::operator=(CompletionChannel&& other) {
    if (mChannel != nullptr && ibv_destroy_comp_channel(mChannel)) {
        throw std::system_error(errno, std::generic_category());
    }

    mChannel = other.mChannel;
    other.mChannel = nullptr;
    return *this;
}
void network_release() {
    ibv_dereg_mr(mr_data);
    
    rdma_destroy_qp(cm_id);
    ibv_destroy_cq(cq);
    ibv_destroy_comp_channel(comp_chan);
    rdma_destroy_id(cm_id);
    rdma_destroy_event_channel(cm_channel);
}
Exemplo n.º 8
0
static int fio_rdmaio_close_file(struct thread_data *td, struct fio_file *f)
{
	struct rdmaio_data *rd = td->io_ops->data;
	struct ibv_send_wr *bad_wr;

	/* unregister rdma buffer */

	/*
	 * Client sends notification to the server side
	 */
	/* refer to: http://linux.die.net/man/7/rdma_cm */
	if ((rd->is_client == 1) && ((rd->rdma_protocol == FIO_RDMA_MEM_WRITE)
				     || (rd->rdma_protocol ==
					 FIO_RDMA_MEM_READ))) {
		if (ibv_post_send(rd->qp, &rd->sq_wr, &bad_wr) != 0) {
			log_err("fio: ibv_post_send fail");
			return 1;
		}

		dprint(FD_IO, "fio: close information sent success\n");
		rdma_poll_wait(td, IBV_WC_SEND);
	}

	if (rd->is_client == 1)
		rdma_disconnect(rd->cm_id);
	else {
		rdma_disconnect(rd->child_cm_id);
#if 0
		rdma_disconnect(rd->cm_id);
#endif
	}

#if 0
	if (get_next_channel_event(td, rd->cm_channel, RDMA_CM_EVENT_DISCONNECTED) != 0) {
		log_err("fio: wait for RDMA_CM_EVENT_DISCONNECTED\n");
		return 1;
	}
#endif

	ibv_destroy_cq(rd->cq);
	ibv_destroy_qp(rd->qp);

	if (rd->is_client == 1)
		rdma_destroy_id(rd->cm_id);
	else {
		rdma_destroy_id(rd->child_cm_id);
		rdma_destroy_id(rd->cm_id);
	}

	ibv_destroy_comp_channel(rd->channel);
	ibv_dealloc_pd(rd->pd);

	return 0;
}
Exemplo n.º 9
0
Arquivo: rping.c Projeto: hkimura/pib
static int rping_setup_qp(struct rping_cb *cb, struct rdma_cm_id *cm_id)
{
	int ret;

	cb->pd = ibv_alloc_pd(cm_id->verbs);
	if (!cb->pd) {
		fprintf(stderr, "ibv_alloc_pd failed\n");
		return errno;
	}
	DEBUG_LOG("created pd %p\n", cb->pd);

	cb->channel = ibv_create_comp_channel(cm_id->verbs);
	if (!cb->channel) {
		fprintf(stderr, "ibv_create_comp_channel failed\n");
		ret = errno;
		goto err1;
	}
	DEBUG_LOG("created channel %p\n", cb->channel);

	cb->cq = ibv_create_cq(cm_id->verbs, RPING_SQ_DEPTH * 2, cb,
				cb->channel, 0);
	if (!cb->cq) {
		fprintf(stderr, "ibv_create_cq failed\n");
		ret = errno;
		goto err2;
	}
	DEBUG_LOG("created cq %p\n", cb->cq);

	ret = ibv_req_notify_cq(cb->cq, 0);
	if (ret) {
		fprintf(stderr, "ibv_create_cq failed\n");
		ret = errno;
		goto err3;
	}

	ret = rping_create_qp(cb);
	if (ret) {
		perror("rdma_create_qp");
		goto err3;
	}
	DEBUG_LOG("created qp %p\n", cb->qp);
	return 0;

err3:
	ibv_destroy_cq(cb->cq);
err2:
	ibv_destroy_comp_channel(cb->channel);
err1:
	ibv_dealloc_pd(cb->pd);
	return ret;
}
Exemplo n.º 10
0
/** ========================================================================= */
static void destroy_sa_qp(struct oib_port *port)
{
    int i;

    // if the user just unregistered trap messages those messages may still
    // be on this list, wait 5 seconds for the thread to handle the response.
    for (i = 0; i < 5000; i++) {    
        if (!LIST_EMPTY(&port->pending_reg_msg_head)) {
            usleep(1000);
        }
        else {
            DBGPRINT("destroy_sa_qp: wait %d ms for LIST_EMPTY\n", i);
            break;
        }
    }

    stop_ud_cq_monitor(port);

    join_port_thread(port);

    /* Free any remaining unregistration messages */
    if (!LIST_EMPTY(&port->pending_reg_msg_head)) {
        OUTPUT_ERROR("Ignoring Pending Notice un-registation requests\n");
        oib_sa_remove_all_pending_reg_msgs(port);
    }

    if (port->sa_ah)
       ibv_destroy_ah(port->sa_ah);

    if (port->sa_qp)
        ibv_destroy_qp(port->sa_qp);

    for (i = 0; i<port->num_userspace_recv_buf; i++)
    	if (port->recv_bufs)
            ibv_dereg_mr(port->recv_bufs[i].mr);

    if (port->sa_qp_pd)
        ibv_dealloc_pd(port->sa_qp_pd);

    if (port->sa_qp_cq)
        ibv_destroy_cq(port->sa_qp_cq);

    if (port->recv_bufs) {
        free(port->recv_bufs);
        port->recv_bufs = NULL;
    }

    if (port->sa_qp_comp_channel)
        ibv_destroy_comp_channel(port->sa_qp_comp_channel);
}
Exemplo n.º 11
0
static void
rdmasniff_cleanup(pcap_t *handle)
{
	struct pcap_rdmasniff *priv = handle->priv;

	ibv_dereg_mr(priv->mr);
	ibv_destroy_flow(priv->flow);
	ibv_destroy_qp(priv->qp);
	ibv_destroy_cq(priv->cq);
	ibv_dealloc_pd(priv->pd);
	ibv_destroy_comp_channel(priv->channel);
	ibv_close_device(priv->context);
	free(priv->oneshot_buffer);

	pcap_cleanup_live_common(handle);
}
Exemplo n.º 12
0
static int ibw_conn_priv_destruct(struct ibw_conn_priv *pconn)
{
	DEBUG(DEBUG_DEBUG, ("ibw_conn_priv_destruct(%p, cmid: %p)\n",
		pconn, pconn->cm_id));

	/* pconn->wr_index is freed by talloc */
	/* pconn->wr_index[i] are freed by talloc */

	/*
	 * tevent_fd must be removed before the fd is closed
	 */
	TALLOC_FREE(pconn->verbs_channel_event);

	/* destroy verbs */
	if (pconn->cm_id!=NULL && pconn->cm_id->qp!=NULL) {
		rdma_destroy_qp(pconn->cm_id);
		pconn->cm_id->qp = NULL;
	}

	if (pconn->cq!=NULL) {
		ibv_destroy_cq(pconn->cq);
		pconn->cq = NULL;
	}

	if (pconn->verbs_channel!=NULL) {
		ibv_destroy_comp_channel(pconn->verbs_channel);
		pconn->verbs_channel = NULL;
	}

	/* free memory regions */
	ibw_free_mr(&pconn->buf_send, &pconn->mr_send);
	ibw_free_mr(&pconn->buf_recv, &pconn->mr_recv);

	if (pconn->pd) {
		ibv_dealloc_pd(pconn->pd);
		pconn->pd = NULL;
		DEBUG(DEBUG_DEBUG, ("pconn=%p pd deallocated\n", pconn));
	}

	if (pconn->cm_id) {
		rdma_destroy_id(pconn->cm_id);
		pconn->cm_id = NULL;
		DEBUG(DEBUG_DEBUG, ("pconn=%p cm_id destroyed\n", pconn));
	}

	return 0;
}
Exemplo n.º 13
0
int
rd_close_2(DEVICE *dev)
{
    if (dev->pd)
        ibv_dealloc_pd(dev->pd);
    if (dev->channel)
        ibv_destroy_comp_channel(dev->channel);

#if 0
    if (!Req.use_cm)
#endif
        ib_close2(dev);

    memset(dev, 0, sizeof(*dev));

    return 0;
}
Exemplo n.º 14
0
int
resource_destroy(resource_t *res)
{
    int rc = 0;

    // Delete QP
    if (res->qp && ibv_destroy_qp(res->qp)){
	fprintf(stderr, "failed to destroy QP\n");
	rc = 1;
    }
    // Deregister MR
    if(res->mr_list && res->mr_size > 0){
	int i;
	for(i=0; i<res->mr_size; i++){
	    ibv_dereg_mr(res->mr_list[i]);
	}
	free(res->mr_list);
    }
    if(res->buf){
	free(res->buf);
    }
    // Delete CQ
    if (res->scq && ibv_destroy_cq(res->scq)){
	fprintf(stderr, "failed to destroy SCQ\n");
	rc = 1;
    }
    if (res->rcq && ibv_destroy_cq(res->rcq)){
	fprintf(stderr, "failed to destroy RCQ\n");
	rc = 1;
    }
    if(res->comp_ch && ibv_destroy_comp_channel(res->comp_ch)){
	fprintf(stderr, "failed to destroy Complete CH\n");
	rc = 1;
    }
    // Deallocate PD
    if (res->pd && ibv_dealloc_pd(res->pd)){
	fprintf(stderr, "failed to deallocate PD\n");
	rc = 1;
    }
    if (res->ib_ctx && ibv_close_device(res->ib_ctx)){
	fprintf(stderr, "failed to close device context\n");
	rc = 1;
    }
    return rc;
}
Exemplo n.º 15
0
static int destroy_ctx_resources(struct pingpong_context *ctx)  {

	int test_result = 0;

	if (ibv_destroy_qp(ctx->qp)) {
		fprintf(stderr, "failed to destroy QP\n");
		test_result = 1;
	}
	
	if (ibv_destroy_cq(ctx->cq)) {
		fprintf(stderr, "failed to destroy CQ\n");
		test_result = 1;
	}
	
	if (ibv_dereg_mr(ctx->mr)) {
		fprintf(stderr, "failed to deregister MR\n");
		test_result = 1;
	}

	if (ctx->channel) {
		if (ibv_destroy_comp_channel(ctx->channel)) {
			fprintf(stderr, "failed to destroy channel \n");
			test_result = 1;
		}
	}
	
	if (ibv_dealloc_pd(ctx->pd)) {
		fprintf(stderr, "failed to deallocate PD\n");
		test_result = 1;
	}

	if (ibv_close_device(ctx->context)) {
		fprintf(stderr, "failed to close device context\n");
		test_result = 1;
	}

	free(ctx->buf);
	free(ctx);
	free(tstamp);

	return test_result;
}
Exemplo n.º 16
0
static UCS_CLASS_CLEANUP_FUNC(uct_ib_iface_t)
{
    int ret;

    ret = ibv_destroy_cq(self->recv_cq);
    if (ret != 0) {
        ucs_warn("ibv_destroy_cq(recv_cq) returned %d: %m", ret);
    }

    ret = ibv_destroy_cq(self->send_cq);
    if (ret != 0) {
        ucs_warn("ibv_destroy_cq(send_cq) returned %d: %m", ret);
    }

    ret = ibv_destroy_comp_channel(self->comp_channel);
    if (ret != 0) {
        ucs_warn("ibv_destroy_comp_channel(comp_channel) returned %d: %m", ret);
    }

    ucs_free(self->path_bits);
}
Exemplo n.º 17
0
static int pp_close_ctx(void)
{
	int i;

	for (i = 0; i < ctx.num_clients; ++i) {

		if (ibv_destroy_qp(ctx.send_qp[i])) {
			fprintf(stderr, "Couldn't destroy INI QP[%d]\n", i);
			return 1;
		}

		if (ibv_destroy_qp(ctx.recv_qp[i])) {
			fprintf(stderr, "Couldn't destroy TGT QP[%d]\n", i);
			return 1;
		}

		if (ctx.rem_dest[i].sockfd)
			close(ctx.rem_dest[i].sockfd);
	}

	if (ibv_destroy_srq(ctx.srq)) {
		fprintf(stderr, "Couldn't destroy SRQ\n");
		return 1;
	}

	if (ctx.xrcd && ibv_close_xrcd(ctx.xrcd)) {
		fprintf(stderr, "Couldn't close the XRC Domain\n");
		return 1;
	}
	if (ctx.fd >= 0 && close(ctx.fd)) {
		fprintf(stderr, "Couldn't close the file for the XRC Domain\n");
		return 1;
	}

	if (ibv_destroy_cq(ctx.send_cq)) {
		fprintf(stderr, "Couldn't destroy send CQ\n");
		return 1;
	}

	if (ibv_destroy_cq(ctx.recv_cq)) {
		fprintf(stderr, "Couldn't destroy recv CQ\n");
		return 1;
	}

	if (ibv_dereg_mr(ctx.mr)) {
		fprintf(stderr, "Couldn't deregister MR\n");
		return 1;
	}

	if (ibv_dealloc_pd(ctx.pd)) {
		fprintf(stderr, "Couldn't deallocate PD\n");
		return 1;
	}

	if (ctx.channel) {
		if (ibv_destroy_comp_channel(ctx.channel)) {
			fprintf(stderr,
				"Couldn't destroy completion channel\n");
			return 1;
		}
	}

	if (ibv_close_device(ctx.context)) {
		fprintf(stderr, "Couldn't release context\n");
		return 1;
	}

	free(ctx.buf);
	free(ctx.rem_dest);
	free(ctx.send_qp);
	free(ctx.recv_qp);
	return 0;
}
Exemplo n.º 18
0
/*****************************************
* Function: resources_destroy
*****************************************/
static int resources_destroy(
	struct resources *res)
{
	int test_result = 0;


	if (res->qp) {
		if (ibv_destroy_qp(res->qp)) {
			fprintf(stderr, "failed to destroy QP\n");
			test_result = 1;
		}
	}

	if (res->mr) {
		if (ibv_dereg_mr(res->mr)) {
			fprintf(stderr, "failed to deregister MR\n");
			test_result = 1;
		}
	}

	if (res->buf)
		free(res->buf);

	if (res->cq) {
		if (ibv_destroy_cq(res->cq)) {
			fprintf(stderr, "failed to destroy CQ\n");
			test_result = 1;
		}
	}

	if (res->comp_channel) {
		if (ibv_destroy_comp_channel(res->comp_channel)) {
			fprintf(stderr, "failed to destroy completion channel\n");
			test_result = 1;
		}
	}

	if (res->pd) {
		if (ibv_dealloc_pd(res->pd)) {
			fprintf(stderr, "failed to deallocate PD\n");
			test_result = 1;
		}
	}

	if (res->ib_ctx) {
		if (ibv_close_device(res->ib_ctx)) {
			fprintf(stderr, "failed to close device context\n");
			test_result = 1;
		}
	}

	if (res->dev_list)
		ibv_free_device_list(res->dev_list);

	if (res->sock >= 0) {
		if (close(res->sock)) {
			fprintf(stderr, "failed to close socket\n");
			test_result = 1;
		}
	}

	return test_result;
}
Exemplo n.º 19
0
CompletionChannel::~CompletionChannel() {
    if (mChannel != nullptr && ibv_destroy_comp_channel(mChannel)) {
        std::error_code ec(errno, std::generic_category());
        LOG_ERROR("Failed to destroy completion channel [error = %1% %2%]", ec, ec.message());
    }
}
Exemplo n.º 20
0
static int
rdmasniff_activate(pcap_t *handle)
{
	struct pcap_rdmasniff *priv = handle->priv;
	struct ibv_qp_init_attr qp_init_attr;
	struct ibv_qp_attr qp_attr;
	struct ibv_flow_attr flow_attr;
	struct ibv_port_attr port_attr;
	int i;

	priv->context = ibv_open_device(priv->rdma_device);
	if (!priv->context) {
		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
			      "Failed to open device %s", handle->opt.device);
		goto error;
	}

	priv->pd = ibv_alloc_pd(priv->context);
	if (!priv->pd) {
		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
			      "Failed to alloc PD for device %s", handle->opt.device);
		goto error;
	}

	priv->channel = ibv_create_comp_channel(priv->context);
	if (!priv->channel) {
		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
			      "Failed to create comp channel for device %s", handle->opt.device);
		goto error;
	}

	priv->cq = ibv_create_cq(priv->context, RDMASNIFF_NUM_RECEIVES,
				 NULL, priv->channel, 0);
	if (!priv->cq) {
		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
			      "Failed to create CQ for device %s", handle->opt.device);
		goto error;
	}

	ibv_req_notify_cq(priv->cq, 0);

	memset(&qp_init_attr, 0, sizeof qp_init_attr);
	qp_init_attr.send_cq = qp_init_attr.recv_cq = priv->cq;
	qp_init_attr.cap.max_recv_wr = RDMASNIFF_NUM_RECEIVES;
	qp_init_attr.cap.max_recv_sge = 1;
	qp_init_attr.qp_type = IBV_QPT_RAW_PACKET;
	priv->qp = ibv_create_qp(priv->pd, &qp_init_attr);
	if (!priv->qp) {
		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
			      "Failed to create QP for device %s", handle->opt.device);
		goto error;
	}

	memset(&qp_attr, 0, sizeof qp_attr);
	qp_attr.qp_state = IBV_QPS_INIT;
	qp_attr.port_num = priv->port_num;
	if (ibv_modify_qp(priv->qp, &qp_attr, IBV_QP_STATE | IBV_QP_PORT)) {
		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
			      "Failed to modify QP to INIT for device %s", handle->opt.device);
		goto error;
	}

	memset(&qp_attr, 0, sizeof qp_attr);
	qp_attr.qp_state = IBV_QPS_RTR;
	if (ibv_modify_qp(priv->qp, &qp_attr, IBV_QP_STATE)) {
		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
			      "Failed to modify QP to RTR for device %s", handle->opt.device);
		goto error;
	}

	memset(&flow_attr, 0, sizeof flow_attr);
	flow_attr.type = IBV_FLOW_ATTR_SNIFFER;
	flow_attr.size = sizeof flow_attr;
	flow_attr.port = priv->port_num;
	priv->flow = ibv_create_flow(priv->qp, &flow_attr);
	if (!priv->flow) {
		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
			      "Failed to create flow for device %s", handle->opt.device);
		goto error;
	}

	handle->bufsize = RDMASNIFF_NUM_RECEIVES * RDMASNIFF_RECEIVE_SIZE;
	handle->buffer = malloc(handle->bufsize);
	if (!handle->buffer) {
		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
			      "Failed to allocate receive buffer for device %s", handle->opt.device);
		goto error;
	}

	priv->oneshot_buffer = malloc(RDMASNIFF_RECEIVE_SIZE);
	if (!priv->oneshot_buffer) {
		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
			      "Failed to allocate oneshot buffer for device %s", handle->opt.device);
		goto error;
	}

	priv->mr = ibv_reg_mr(priv->pd, handle->buffer, handle->bufsize, IBV_ACCESS_LOCAL_WRITE);
	if (!priv->mr) {
		pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
			      "Failed to register MR for device %s", handle->opt.device);
		goto error;
	}


	for (i = 0; i < RDMASNIFF_NUM_RECEIVES; ++i) {
		rdmasniff_post_recv(handle, i);
	}

	if (!ibv_query_port(priv->context, priv->port_num, &port_attr) &&
	    port_attr.link_layer == IBV_LINK_LAYER_INFINIBAND) {
		handle->linktype = DLT_INFINIBAND;
	} else {
		handle->linktype = DLT_EN10MB;
	}

	if (handle->snapshot <= 0 || handle->snapshot > RDMASNIFF_RECEIVE_SIZE)
		handle->snapshot = RDMASNIFF_RECEIVE_SIZE;

	handle->offset = 0;
	handle->read_op = rdmasniff_read;
	handle->stats_op = rdmasniff_stats;
	handle->cleanup_op = rdmasniff_cleanup;
	handle->setfilter_op = install_bpf_program;
	handle->setdirection_op = NULL;
	handle->set_datalink_op = NULL;
	handle->getnonblock_op = pcap_getnonblock_fd;
	handle->setnonblock_op = pcap_setnonblock_fd;
	handle->oneshot_callback = rdmasniff_oneshot;
	handle->selectable_fd = priv->channel->fd;

	return 0;

error:
	if (priv->mr) {
		ibv_dereg_mr(priv->mr);
	}

	if (priv->flow) {
		ibv_destroy_flow(priv->flow);
	}

	if (priv->qp) {
		ibv_destroy_qp(priv->qp);
	}

	if (priv->cq) {
		ibv_destroy_cq(priv->cq);
	}

	if (priv->channel) {
		ibv_destroy_comp_channel(priv->channel);
	}

	if (priv->pd) {
		ibv_dealloc_pd(priv->pd);
	}

	if (priv->context) {
		ibv_close_device(priv->context);
	}

	if (priv->oneshot_buffer) {
		free(priv->oneshot_buffer);
	}

	return PCAP_ERROR;
}
Exemplo n.º 21
0
/**
 * @param rx_headroom   Headroom requested by the user.
 * @param rx_priv_len   Length of transport private data to reserve (0 if unused)
 * @param rx_hdr_len    Length of transport network header.
 * @param mss           Maximal segment size (transport limit).
 */
UCS_CLASS_INIT_FUNC(uct_ib_iface_t, uct_ib_iface_ops_t *ops, uct_md_h md,
                    uct_worker_h worker, const char *dev_name, unsigned rx_headroom,
                    unsigned rx_priv_len, unsigned rx_hdr_len, unsigned tx_cq_len,
                    size_t mss, uct_ib_iface_config_t *config)
{
    uct_ib_device_t *dev = &ucs_derived_of(md, uct_ib_md_t)->dev;
    ucs_status_t status;
    uint8_t port_num;

    UCS_CLASS_CALL_SUPER_INIT(uct_base_iface_t, &ops->super, md, worker,
                              &config->super UCS_STATS_ARG(dev->stats));

    status = uct_ib_device_find_port(dev, dev_name, &port_num);
    if (status != UCS_OK) {
        goto err;
    }

    self->port_num                 = port_num;
    self->sl                       = config->sl;
    self->config.rx_payload_offset = sizeof(uct_ib_iface_recv_desc_t) +
                                     ucs_max(sizeof(uct_am_recv_desc_t) + rx_headroom,
                                             rx_priv_len + rx_hdr_len);
    self->config.rx_hdr_offset     = self->config.rx_payload_offset - rx_hdr_len;
    self->config.rx_headroom_offset= self->config.rx_payload_offset - rx_headroom;
    self->config.seg_size          = ucs_min(mss, config->super.max_bcopy);
    self->config.tx_max_poll       = config->tx.max_poll;
    self->config.rx_max_poll       = config->rx.max_poll;
    self->config.rx_max_batch      = ucs_min(config->rx.max_batch,
                                     config->rx.queue_len / 4);
    self->ops                      = ops;

    status = uct_ib_iface_init_pkey(self, config);
    if (status != UCS_OK) {
        goto err;
    }

    status = uct_ib_iface_init_gid(self, config);
    if (status != UCS_OK) {
        goto err;
    }

    status = uct_ib_iface_init_lmc(self, config);
    if (status != UCS_OK) {
        goto err;
    }

    self->comp_channel = ibv_create_comp_channel(dev->ibv_context);
    if (self->comp_channel == NULL) {
        ucs_error("Failed to create completion channel: %m");
        status = UCS_ERR_IO_ERROR;
        goto err_free_path_bits;
    }

    status = ucs_sys_fcntl_modfl(self->comp_channel->fd, O_NONBLOCK, 0);
    if (status != UCS_OK) {
        goto err_destroy_comp_channel;
    }

    /* TODO inline scatter for send SQ */
    self->send_cq = ibv_create_cq(dev->ibv_context, tx_cq_len,
                                  NULL, self->comp_channel, 0);
    if (self->send_cq == NULL) {
        ucs_error("Failed to create send cq: %m");
        status = UCS_ERR_IO_ERROR;
        goto err_destroy_comp_channel;
    }

    if (config->rx.inl > 32 /*UCT_IB_MLX5_CQE64_MAX_INL*/) {
        ibv_exp_setenv(dev->ibv_context, "MLX5_CQE_SIZE", "128", 1);
    }

    self->recv_cq = ibv_create_cq(dev->ibv_context, config->rx.queue_len,
                                  NULL, self->comp_channel, 0);
    ibv_exp_setenv(dev->ibv_context, "MLX5_CQE_SIZE", "64", 1);

    if (self->recv_cq == NULL) {
        ucs_error("Failed to create recv cq: %m");
        status = UCS_ERR_IO_ERROR;
        goto err_destroy_send_cq;
    }

    if (!uct_ib_device_is_port_ib(dev, self->port_num)) {
        ucs_error("Unsupported link layer");
        status = UCS_ERR_UNSUPPORTED;
        goto err_destroy_recv_cq;
    }

    /* Address scope and size */
    self->addr_scope = uct_ib_address_scope(self->gid.global.subnet_prefix);
    self->addr_size  = uct_ib_address_size(self->addr_scope);

    ucs_debug("created uct_ib_iface_t headroom_ofs %d payload_ofs %d hdr_ofs %d data_sz %d",
              self->config.rx_headroom_offset, self->config.rx_payload_offset,
              self->config.rx_hdr_offset, self->config.seg_size);

    return UCS_OK;

err_destroy_recv_cq:
    ibv_destroy_cq(self->recv_cq);
err_destroy_send_cq:
    ibv_destroy_cq(self->send_cq);
err_destroy_comp_channel:
    ibv_destroy_comp_channel(self->comp_channel);
err_free_path_bits:
    ucs_free(self->path_bits);
err:
    return status;
}
Exemplo n.º 22
0
static int
mlx5_glue_destroy_comp_channel(struct ibv_comp_channel *channel)
{
	return ibv_destroy_comp_channel(channel);
}
Exemplo n.º 23
0
struct pingpong_context *pp_init_ctx(struct ibv_device *ib_dev, int size,
                                     int rx_depth, int port, int use_event,
                                     enum pp_wr_calc_op   calc_op,
                                     enum pp_wr_data_type calc_data_type,
                                     char *calc_operands_str)
{
    struct pingpong_context *ctx;
    int rc;

    ctx = malloc(sizeof *ctx);
    if (!ctx)
        return NULL;
    memset(ctx, 0, sizeof *ctx);

    ctx->size	= size;
    ctx->rx_depth	= rx_depth;

    ctx->calc_op.opcode	= IBV_EXP_CALC_OP_NUMBER;
    ctx->calc_op.data_type	= IBV_EXP_CALC_DATA_TYPE_NUMBER;
    ctx->calc_op.data_size	= IBV_EXP_CALC_DATA_SIZE_NUMBER;

    ctx->buf = memalign(page_size, size);
    if (!ctx->buf) {
        fprintf(stderr, "Couldn't allocate work buf.\n");
        goto clean_ctx;
    }

    memset(ctx->buf, 0, size);

    ctx->net_buf = memalign(page_size, size);
    if (!ctx->net_buf) {
        fprintf(stderr, "Couldn't allocate work buf.\n");
        goto clean_buffer;
    }
    memset(ctx->net_buf, 0, size);

    ctx->context = ibv_open_device(ib_dev);
    if (!ctx->context) {
        fprintf(stderr, "Couldn't get context for %s\n",
                ibv_get_device_name(ib_dev));
        goto clean_net_buf;
    }

    if (use_event) {
        ctx->channel = ibv_create_comp_channel(ctx->context);
        if (!ctx->channel) {
            fprintf(stderr, "Couldn't create completion channel\n");
            goto clean_device;
        }
    } else
        ctx->channel = NULL;

    ctx->pd = ibv_alloc_pd(ctx->context);
    if (!ctx->pd) {
        fprintf(stderr, "Couldn't allocate PD\n");
        goto clean_comp_channel;
    }

    ctx->mr = ibv_reg_mr(ctx->pd, ctx->net_buf, size, IBV_ACCESS_LOCAL_WRITE);
    if (!ctx->mr) {
        fprintf(stderr, "Couldn't register MR\n");
        goto clean_pd;
    }

    if (calc_op != PP_CALC_INVALID) {
        int op_per_gather, num_op, max_num_op;

        ctx->calc_op.opcode	= IBV_EXP_CALC_OP_NUMBER;
        ctx->calc_op.data_type	= IBV_EXP_CALC_DATA_TYPE_NUMBER;
        ctx->calc_op.data_size	= IBV_EXP_CALC_DATA_SIZE_NUMBER;

        num_op = pp_parse_calc_to_gather(calc_operands_str, calc_op, calc_data_type,
                                         &ctx->calc_op, ctx->context, ctx->buf, ctx->net_buf);
        if (num_op < 0) {
            fprintf(stderr, "-E- failed parsing calc operators\n");
            goto clean_mr;
        }

        rc = pp_query_calc_cap(ctx->context,
                               ctx->calc_op.opcode,
                               ctx->calc_op.data_type,
                               ctx->calc_op.data_size,
                               &op_per_gather, &max_num_op);
        if (rc) {
            fprintf(stderr, "-E- operation not supported on %s. valid ops are:\n",
                    ibv_get_device_name(ib_dev));

            pp_print_dev_calc_ops(ctx->context);
            goto clean_mr;
        }

        if (pp_prepare_sg_list(op_per_gather, num_op, ctx->mr->lkey, &ctx->calc_op, ctx->net_buf)) {
            fprintf(stderr, "-failed to prepare the sg list\n");
            goto clean_mr;
        }
    }

    ctx->cq = ibv_create_cq(ctx->context, rx_depth + 1, NULL,
                            ctx->channel, 0);
    if (!ctx->cq) {
        fprintf(stderr, "Couldn't create CQ\n");
        goto clean_mr;
    }

    {
        struct ibv_exp_qp_init_attr attr = {
            .send_cq = ctx->cq,
            .recv_cq = ctx->cq,
            .cap	 = {
                .max_send_wr  = 16,
                .max_recv_wr  = rx_depth,
                .max_send_sge = 16,
                .max_recv_sge = 16
            },
            .qp_type = IBV_QPT_RC,
            .pd = ctx->pd
        };

        attr.comp_mask |= IBV_EXP_QP_INIT_ATTR_CREATE_FLAGS | IBV_EXP_QP_INIT_ATTR_PD;
        attr.exp_create_flags = IBV_EXP_QP_CREATE_CROSS_CHANNEL;

        ctx->qp = ibv_exp_create_qp(ctx->context, &attr);
        if (!ctx->qp)  {
            fprintf(stderr, "Couldn't create QP\n");
            goto clean_cq;
        }
    }

    {
        struct ibv_qp_attr attr = {
            .qp_state		= IBV_QPS_INIT,
            .pkey_index		= 0,
            .port_num		= port,
            .qp_access_flags	= 0
        };

        if (ibv_modify_qp(ctx->qp, &attr,
                          IBV_QP_STATE		|
                          IBV_QP_PKEY_INDEX	|
                          IBV_QP_PORT		|
                          IBV_QP_ACCESS_FLAGS)) {
            fprintf(stderr, "Failed to modify QP to INIT\n");
            goto clean_qp;
        }

    }

    ctx->mcq = ibv_create_cq(ctx->context, rx_depth + 1, NULL,
                             ctx->channel, 0);
    if (!ctx->mcq) {
        fprintf(stderr, "Couldn't create CQ for MQP\n");
        goto clean_qp;
    }

    {
        struct ibv_exp_qp_init_attr mattr = {
            .send_cq = ctx->mcq,
            .recv_cq = ctx->mcq,
            .cap	 = {
                .max_send_wr  = 1,
                .max_recv_wr  = rx_depth,
                .max_send_sge = 16,
                .max_recv_sge = 16
            },
            .qp_type = IBV_QPT_RC,
            .pd = ctx->pd
        };

        mattr.comp_mask |= IBV_EXP_QP_INIT_ATTR_CREATE_FLAGS | IBV_EXP_QP_INIT_ATTR_PD;
        mattr.exp_create_flags = IBV_EXP_QP_CREATE_CROSS_CHANNEL;

        ctx->mqp = ibv_exp_create_qp(ctx->context, &mattr);
        if (!ctx->qp)  {
            fprintf(stderr, "Couldn't create MQP\n");
            goto clean_mcq;
        }
    }

    {
        struct ibv_qp_attr mattr = {
            .qp_state		= IBV_QPS_INIT,
            .pkey_index		= 0,
            .port_num		= port,
            .qp_access_flags	= 0
        };

        if (ibv_modify_qp(ctx->mqp, &mattr,
                          IBV_QP_STATE		|
                          IBV_QP_PKEY_INDEX	|
                          IBV_QP_PORT		|
                          IBV_QP_ACCESS_FLAGS)) {
            fprintf(stderr, "Failed to modify MQP to INIT\n");
            goto clean_mqp;
        }
    }

    return ctx;

clean_mqp:
    ibv_destroy_qp(ctx->mqp);

clean_mcq:
    ibv_destroy_cq(ctx->mcq);

clean_qp:
    ibv_destroy_qp(ctx->qp);

clean_cq:
    ibv_destroy_cq(ctx->cq);

clean_mr:
    ibv_dereg_mr(ctx->mr);

clean_pd:
    ibv_dealloc_pd(ctx->pd);

clean_comp_channel:
    if (ctx->channel)
        ibv_destroy_comp_channel(ctx->channel);

clean_device:
    ibv_close_device(ctx->context);

clean_net_buf:
    free(ctx->net_buf);

clean_buffer:
    free(ctx->buf);

clean_ctx:
    free(ctx);

    return NULL;
}

int pp_close_ctx(struct pingpong_context *ctx)
{
    if (ibv_destroy_qp(ctx->qp)) {
        fprintf(stderr, "Couldn't destroy QP\n");
        return 1;
    }


    if (ibv_destroy_qp(ctx->mqp)) {
        fprintf(stderr, "Couldn't destroy MQP\n");
        return 1;
    }


    if (ibv_destroy_cq(ctx->cq)) {
        fprintf(stderr, "Couldn't destroy CQ\n");
        return 1;
    }

    if (ibv_destroy_cq(ctx->mcq)) {
        fprintf(stderr, "Couldn't destroy MCQ\n");
        return 1;
    }

    if (ibv_dereg_mr(ctx->mr)) {
        fprintf(stderr, "Couldn't deregister MR\n");
        return 1;
    }

    if (ibv_dealloc_pd(ctx->pd)) {
        fprintf(stderr, "Couldn't deallocate PD\n");
        return 1;
    }

    if (ctx->channel) {
        if (ibv_destroy_comp_channel(ctx->channel)) {
            fprintf(stderr, "Couldn't destroy completion channel\n");
            return 1;
        }
    }

    if (ibv_close_device(ctx->context)) {
        fprintf(stderr, "Couldn't release context\n");
        return 1;
    }

    free(ctx->buf);
    free(ctx->net_buf);
    free(ctx);

    return 0;
}

static int pp_post_recv(struct pingpong_context *ctx, int n)
{
    int rc;

    struct ibv_sge list = {
        .addr	= (uintptr_t) ctx->net_buf,
        .length = ctx->size,
        .lkey	= ctx->mr->lkey
    };
    struct ibv_recv_wr wr = {
        .wr_id		= PP_RECV_WRID,
        .sg_list	= &list,
        .num_sge	= 1,
    };
    struct ibv_recv_wr *bad_wr;
    int i;

    for (i = 0; i < n; ++i) {
        rc = ibv_post_recv(ctx->qp, &wr, &bad_wr);
        if (rc)
            return rc;
    }

    return i;
}

static int pp_post_send(struct pingpong_context *ctx)
{
    int ret;

    struct ibv_sge list = {
        .addr	= (uintptr_t) ctx->net_buf,
        .length = ctx->size,
        .lkey	= ctx->mr->lkey
    };
    struct ibv_exp_send_wr wr = {
        .wr_id		= PP_SEND_WRID,
        .sg_list	= &list,
        .num_sge	= 1,
        .exp_opcode	= IBV_EXP_WR_SEND,
        .exp_send_flags	= IBV_EXP_SEND_SIGNALED,
    };
    struct ibv_exp_send_wr *bad_wr;
    /* If this is a calc operation - set the required params in the wr */
    if (ctx->calc_op.opcode != IBV_EXP_CALC_OP_NUMBER) {
        wr.exp_opcode  = IBV_EXP_WR_SEND;
        wr.exp_send_flags |= IBV_EXP_SEND_WITH_CALC;
        wr.sg_list = ctx->calc_op.gather_list;
        wr.num_sge = ctx->calc_op.gather_list_size;

        wr.op.calc.calc_op   = ctx->calc_op.opcode;
        wr.op.calc.data_type = ctx->calc_op.data_type;
        wr.op.calc.data_size = ctx->calc_op.data_size;

    }

    ret = ibv_exp_post_send(ctx->qp, &wr, &bad_wr);

    return ret;
}

int pp_post_ext_wqe(struct pingpong_context *ctx, enum ibv_exp_wr_opcode op)
{
    int ret;
    struct ibv_exp_send_wr wr = {
        .wr_id		= PP_CQE_WAIT,
        .sg_list	= NULL,
        .num_sge	= 0,
        .exp_opcode	= op,
        .exp_send_flags	= IBV_EXP_SEND_SIGNALED,
    };
    struct ibv_exp_send_wr *bad_wr;

    switch (op) {
    case IBV_EXP_WR_RECV_ENABLE:
    case IBV_EXP_WR_SEND_ENABLE:

        wr.task.wqe_enable.qp = ctx->qp;
        wr.task.wqe_enable.wqe_count = 0;

        wr.exp_send_flags |= IBV_EXP_SEND_WAIT_EN_LAST;

        break;

    case IBV_EXP_WR_CQE_WAIT:
        wr.task.cqe_wait.cq = ctx->cq;
        wr.task.cqe_wait.cq_count = 1;

        wr.exp_send_flags |=  IBV_EXP_SEND_WAIT_EN_LAST;

        break;

    default:
        fprintf(stderr, "-E- unsupported m_wqe opcode %d\n", op);
        return -1;
    }

    ret = ibv_exp_post_send(ctx->mqp, &wr, &bad_wr);

    return ret;
}

int pp_poll_mcq(struct ibv_cq *cq, int num_cqe)
{
    int ne;
    int i;
    struct ibv_wc wc[2];

    if (num_cqe > 2) {
        fprintf(stderr, "-E- max num cqe exceeded\n");
        return -1;
    }

    do {
        ne = ibv_poll_cq(cq, num_cqe, wc);
        if (ne < 0) {
            fprintf(stderr, "poll CQ failed %d\n", ne);
            return 1;
        }
    } while (ne < 1);

    for (i = 0; i < ne; ++i) {
        if (wc[i].status != IBV_WC_SUCCESS) {
            fprintf(stderr, "Failed %s status %s (%d)\n",
                    wr_id_str[(int)wc[i].wr_id],
                    ibv_wc_status_str(wc[i].status),
                    wc[i].status);
            return 1;
        }

        if ((int) wc[i].wr_id != PP_CQE_WAIT) {
            fprintf(stderr, "invalid wr_id %" PRIx64 "\n", wc[i].wr_id);
            return -1;
        }
    }

    return 0;
}

static int pp_calc_verify(struct pingpong_context *ctx,
                          enum pp_wr_data_type calc_data_type,
                          enum pp_wr_calc_op calc_opcode)
{
    uint64_t *op1 = &(ctx->last_result);
    uint64_t *op2 = (uint64_t *)ctx->buf + 2;
    uint64_t *res = (uint64_t *)ctx->buf;

    return !EXEC_VERIFY(calc_data_type, calc_opcode, 1, op1, op2, res);
}

static int pp_update_last_result(struct pingpong_context *ctx,
                                 enum pp_wr_data_type calc_data_type,
                                 enum pp_wr_calc_op calc_opcode)
{
    /* EXEC_VERIFY derefence result parameter */
    uint64_t *dummy;

    uint64_t *op1 = (uint64_t *)ctx->buf;
    uint64_t *op2 = (uint64_t *)ctx->buf + 2;
    uint64_t res = (uint64_t)EXEC_VERIFY(calc_data_type, calc_opcode, 0, op1, op2, dummy);

    ctx->last_result = res;
    return 0;
}


static void usage(const char *argv0)
{
    printf("Usage:\n");
    printf("  %s				start a server and wait for connection\n", argv0);
    printf("  %s <host>			connect to server at <host>\n", argv0);
    printf("\n");
    printf("Options:\n");
    printf("  -p, --port=<port>		listen on/connect to port <port> (default 18515)\n");
    printf("  -d, --ib-dev=<dev>		use IB device <dev> (default first device found)\n");
    printf("  -i, --ib-port=<port>		use port <port> of IB device (default 1)\n");
    printf("  -s, --size=<size>		size of message to exchange (default 4096 minimum 16)\n");
    printf("  -m, --mtu=<size>		path MTU (default 1024)\n");
    printf("  -r, --rx-depth=<dep>		number of receives to post at a time (default 500)\n");
    printf("  -n, --iters=<iters>		number of exchanges (default 1000)\n");
    printf("  -l, --sl=<sl>			service level value\n");
    printf("  -e, --events			sleep on CQ events (default poll)\n");
    printf("  -c, --calc=<operation>	calc operation\n");
    printf("  -t, --op_type=<type>		calc operands type\n");
    printf("  -o, --operands=<o1,o2,...>	comma separated list of operands\n");
    printf("  -w, --wait_cq=cqn		wait for entries on cq\n");
    printf("  -v, --verbose			print verbose information\n");
    printf("  -V, --verify			verify calc operations\n");
}
Exemplo n.º 24
0
static int fio_rdmaio_setup_qp(struct thread_data *td)
{
	struct rdmaio_data *rd = td->io_ops->data;
	struct ibv_qp_init_attr init_attr;
	int qp_depth = td->o.iodepth * 2;	/* 2 times of io depth */

	if (rd->is_client == 0)
		rd->pd = ibv_alloc_pd(rd->child_cm_id->verbs);
	else
		rd->pd = ibv_alloc_pd(rd->cm_id->verbs);

	if (rd->pd == NULL) {
		log_err("fio: ibv_alloc_pd fail\n");
		return 1;
	}

	if (rd->is_client == 0)
		rd->channel = ibv_create_comp_channel(rd->child_cm_id->verbs);
	else
		rd->channel = ibv_create_comp_channel(rd->cm_id->verbs);
	if (rd->channel == NULL) {
		log_err("fio: ibv_create_comp_channel fail\n");
		goto err1;
	}

	if (qp_depth < 16)
		qp_depth = 16;

	if (rd->is_client == 0)
		rd->cq = ibv_create_cq(rd->child_cm_id->verbs,
				       qp_depth, rd, rd->channel, 0);
	else
		rd->cq = ibv_create_cq(rd->cm_id->verbs,
				       qp_depth, rd, rd->channel, 0);
	if (rd->cq == NULL) {
		log_err("fio: ibv_create_cq failed\n");
		goto err2;
	}

	if (ibv_req_notify_cq(rd->cq, 0) != 0) {
		log_err("fio: ibv_create_cq failed\n");
		goto err3;
	}

	/* create queue pair */
	memset(&init_attr, 0, sizeof(init_attr));
	init_attr.cap.max_send_wr = qp_depth;
	init_attr.cap.max_recv_wr = qp_depth;
	init_attr.cap.max_recv_sge = 1;
	init_attr.cap.max_send_sge = 1;
	init_attr.qp_type = IBV_QPT_RC;
	init_attr.send_cq = rd->cq;
	init_attr.recv_cq = rd->cq;

	if (rd->is_client == 0) {
		if (rdma_create_qp(rd->child_cm_id, rd->pd, &init_attr) != 0) {
			log_err("fio: rdma_create_qp failed\n");
			goto err3;
		}
		rd->qp = rd->child_cm_id->qp;
	} else {
		if (rdma_create_qp(rd->cm_id, rd->pd, &init_attr) != 0) {
			log_err("fio: rdma_create_qp failed\n");
			goto err3;
		}
		rd->qp = rd->cm_id->qp;
	}

	return 0;

err3:
	ibv_destroy_cq(rd->cq);
err2:
	ibv_destroy_comp_channel(rd->channel);
err1:
	ibv_dealloc_pd(rd->pd);

	return 1;
}
Exemplo n.º 25
0
int
resource_create(resource_t *res, int ib_port, int myrank)
{
    struct ibv_device		**dev_list = NULL;
    struct ibv_qp_init_attr	qp_init_attr;
    struct ibv_device		*ib_dev = NULL;
    char	*dev_name = NULL;
    size_t	size;
    int		i;
    int		mr_flags = 0;
    int		cq_size = 0;
    int		dev_numm;
    int		rc = 0;

    /* Init structure */
    memset(res, 0, sizeof(resource_t));
    /* Get the device list */
    dev_list = ibv_get_device_list(&dev_numm);
    if(!dev_list) {
	fprintf(stderr, "[%d] failed to get IB devices list\n", myrank);
	return 1;
    }
    // if no device
    if(!dev_numm) {
	fprintf(stderr, "[%d] No IB device is found\n", myrank);
	rc = 1;
	goto err_exit;
    }
    DEBUG { printf("[%d] found %d IB device(s)\n", myrank, dev_numm); }
    /* Open the requested device */
    for(i = 0; i < dev_numm; i ++){
	dev_name = strdup(ibv_get_device_name(dev_list[i]));
	DEBUG { printf("[%d] IB device name: %s\n", myrank, dev_name); }
	ib_dev = dev_list[i];
	break;
    }
    if (!ib_dev){
	fprintf(stderr, "[%d] IB device %s wasn't found\n", myrank, dev_name);
	rc = 1;
	goto err_exit;
    }
    res->ib_ctx = ibv_open_device(ib_dev);
    DEBUG { printf("[%d] IB context = %lx\n", myrank, (uintptr_t)res->ib_ctx); }
    if(!res->ib_ctx){
	fprintf(stderr, "[%d] failed to open device %s\n", myrank, dev_name);
	rc = 1;
	goto err_exit;
    }
    // free device list
    ibv_free_device_list(dev_list);
    dev_list = NULL;
    ib_dev = NULL;
    // query prot properties
    if(ibv_query_port(res->ib_ctx, ib_port, &res->port_attr)){
	fprintf(stderr, "[%d] ibv_query_port on port %u failed\n", myrank, ib_port);
	rc = 1;
	goto err_exit;
    }

    /* Create a PD */
    res->pd = ibv_alloc_pd(res->ib_ctx);
    if (!res->pd){
	fprintf(stderr, "[%d] ibv_alloc_pd failed\n", myrank);
	rc = 1;
	goto err_exit;
    }

    /* Create send/recv CQ
     *  inputs:
     *		device handle
     *		CQ capacity
     *  Output:
     *		CQ handle
     */
    res->scq = ibv_create_cq(res->ib_ctx, MAX_CQ_CAPACITY, NULL, NULL, 0);
    res->rcq = ibv_create_cq(res->ib_ctx, MAX_CQ_CAPACITY, NULL, NULL, 0);
    if (!res->scq){
	fprintf(stderr, "[%d] failed to create SCQ with %u entries\n", myrank, cq_size);
	rc = 1;
	goto err_exit;
    }
    if (!res->rcq){
	fprintf(stderr, "[%d] failed to create SCQ with %u entries\n", myrank, cq_size);
	rc = 1;
	goto err_exit;
    }

    /* Allocate fix buffer */
    size = MAX_FIX_BUF_SIZE;
    res->buf_size = size;
    res->buf = (char *)malloc(size * sizeof(char));
    if (!res->buf ){
	fprintf(stderr, "[%d] failed to malloc %Zu bytes to memory buffer\n", myrank, size);
	rc = 1;
	goto err_exit;
    }
    memset(res->buf, 0 , size);

    /* Memory Region
     *	inputs:
     *		device handle
     *		PD
     *		Virtual Addr(addr of MR)
     *		Access Ctrl: LocalWrite, RemoteRead, RemoteWrite, RemoteAtomicOp, MemWindowBinding
     *	outputs:
     *		MR handle
     *		L_Key
     *		R_Key
     */
    res->mr_list = malloc(sizeof(struct ibv_mr*) * MAX_MR_NUM);
    res->mr_size = 1;

    mr_flags = IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_READ |
		IBV_ACCESS_REMOTE_WRITE ;
    res->mr_list[0] = ibv_reg_mr(res->pd, res->buf, size, mr_flags);
    if (!res->mr_list[0]){
	fprintf(stderr, "[%d] ibv_reg_mr failed with mr_flags=0x%x\n", myrank, mr_flags);
	rc = 1;
	goto err_exit;
    }
    DEBUG { printf("[%d] fixed MR was registered with addr=%p, lkey=0x%x, rkey=0x%x, flags=0x%x\n", myrank, res->buf, res->mr_list[0]->lkey, res->mr_list[0]->rkey, mr_flags); }

    /* Create QP */
    // inputs:
    //	PD
    //	CQs for SQ,RQ
    //	capacity of SQ,RQ
    // Outputs:
    //	QP handle
    memset(&qp_init_attr, 0, sizeof(qp_init_attr));
    qp_init_attr.qp_type = IBV_QPT_RC;
    qp_init_attr.sq_sig_all = 1;
    qp_init_attr.send_cq = res->scq;
    qp_init_attr.recv_cq = res->rcq;
    // max SR/RR num in SQ/RQ
    qp_init_attr.cap.max_send_wr = MAX_SQ_CAPACITY ;
    qp_init_attr.cap.max_recv_wr = MAX_RQ_CAPACITY;
    // max SGE num
    qp_init_attr.cap.max_send_sge = MAX_SGE_CAPACITY;
    qp_init_attr.cap.max_recv_sge = MAX_SGE_CAPACITY;
    qp_init_attr.cap.max_inline_data = 256;

    res->qp = ibv_create_qp(res->pd, &qp_init_attr);
    if (!res->qp){
	fprintf(stderr, "failed to create QP\n");
	rc = 1;
	goto err_exit;
    }
    DEBUG { printf("[%d] QP was created, QP number=0x%x\n", myrank, res->qp->qp_num); }

    /* EXIT */
err_exit:
    if(rc){
	/* Error encountered, cleanup */
	if(res->qp){
	    ibv_destroy_qp(res->qp);
	    res->qp = NULL;
	}
	if(res->mr_list && res->mr_size > 0){
	    int i;
	    for(i=0; i<res->mr_size; i++){
		ibv_dereg_mr(res->mr_list[i]);
		res->mr_list[i] = NULL;
	    }
	    free(res->mr_list);
	}
	if(res->buf){
	    free(res->buf);
	    res->buf = NULL;
	}
	if(res->scq){
	    ibv_destroy_cq(res->scq);
	    res->scq = NULL;
	}
	if(res->rcq){
	    ibv_destroy_cq(res->rcq);
	    res->rcq = NULL;
	}
	if(res->comp_ch){
	    ibv_destroy_comp_channel(res->comp_ch);
	    res->comp_ch = NULL;
	}
	if(res->pd){
	    ibv_dealloc_pd(res->pd);
	    res->pd = NULL;
	}
	if (res->ib_ctx) {
	    ibv_close_device(res->ib_ctx);
	    res->ib_ctx = NULL;
	}
	if (dev_list) {
	    ibv_free_device_list(dev_list);
	    dev_list = NULL;
	}
    }
    return rc;
}
Exemplo n.º 26
0
int rdma_backend_init(RdmaBackendDev *backend_dev, PCIDevice *pdev,
                      RdmaDeviceResources *rdma_dev_res,
                      const char *backend_device_name, uint8_t port_num,
                      struct ibv_device_attr *dev_attr, CharBackend *mad_chr_be)
{
    int i;
    int ret = 0;
    int num_ibv_devices;
    struct ibv_device **dev_list;

    memset(backend_dev, 0, sizeof(*backend_dev));

    backend_dev->dev = pdev;
    backend_dev->port_num = port_num;
    backend_dev->rdma_dev_res = rdma_dev_res;

    rdma_backend_register_comp_handler(dummy_comp_handler);

    dev_list = ibv_get_device_list(&num_ibv_devices);
    if (!dev_list) {
        rdma_error_report("Failed to get IB devices list");
        return -EIO;
    }

    if (num_ibv_devices == 0) {
        rdma_error_report("No IB devices were found");
        ret = -ENXIO;
        goto out_free_dev_list;
    }

    if (backend_device_name) {
        for (i = 0; dev_list[i]; ++i) {
            if (!strcmp(ibv_get_device_name(dev_list[i]),
                        backend_device_name)) {
                break;
            }
        }

        backend_dev->ib_dev = dev_list[i];
        if (!backend_dev->ib_dev) {
            rdma_error_report("Failed to find IB device %s",
                              backend_device_name);
            ret = -EIO;
            goto out_free_dev_list;
        }
    } else {
        backend_dev->ib_dev = *dev_list;
    }

    rdma_info_report("uverb device %s", backend_dev->ib_dev->dev_name);

    backend_dev->context = ibv_open_device(backend_dev->ib_dev);
    if (!backend_dev->context) {
        rdma_error_report("Failed to open IB device %s",
                          ibv_get_device_name(backend_dev->ib_dev));
        ret = -EIO;
        goto out;
    }

    backend_dev->channel = ibv_create_comp_channel(backend_dev->context);
    if (!backend_dev->channel) {
        rdma_error_report("Failed to create IB communication channel");
        ret = -EIO;
        goto out_close_device;
    }

    ret = init_device_caps(backend_dev, dev_attr);
    if (ret) {
        rdma_error_report("Failed to initialize device capabilities");
        ret = -EIO;
        goto out_destroy_comm_channel;
    }


    ret = mad_init(backend_dev, mad_chr_be);
    if (ret) {
        rdma_error_report("Failed to initialize mad");
        ret = -EIO;
        goto out_destroy_comm_channel;
    }

    backend_dev->comp_thread.run = false;
    backend_dev->comp_thread.is_running = false;

    ah_cache_init();

    goto out_free_dev_list;

out_destroy_comm_channel:
    ibv_destroy_comp_channel(backend_dev->channel);

out_close_device:
    ibv_close_device(backend_dev->context);

out_free_dev_list:
    ibv_free_device_list(dev_list);

out:
    return ret;
}
Exemplo n.º 27
0
/**
 * @param rx_headroom   Headroom requested by the user.
 * @param rx_priv_len   Length of transport private data to reserve (0 if unused)
 * @param rx_hdr_len    Length of transport network header.
 * @param mss           Maximal segment size (transport limit).
 */
UCS_CLASS_INIT_FUNC(uct_ib_iface_t, uct_ib_iface_ops_t *ops, uct_md_h md,
                    uct_worker_h worker, const uct_iface_params_t *params,
                    unsigned rx_priv_len, unsigned rx_hdr_len, unsigned tx_cq_len,
                    size_t mss, const uct_ib_iface_config_t *config)
{
    uct_ib_device_t *dev = &ucs_derived_of(md, uct_ib_md_t)->dev;
    ucs_status_t status;
    uint8_t port_num;

    UCS_CLASS_CALL_SUPER_INIT(uct_base_iface_t, &ops->super, md, worker,
                              &config->super UCS_STATS_ARG(dev->stats));

    status = uct_ib_device_find_port(dev, params->dev_name, &port_num);
    if (status != UCS_OK) {
        goto err;
    }

    self->ops                      = ops;

    self->config.rx_payload_offset = sizeof(uct_ib_iface_recv_desc_t) +
                                     ucs_max(sizeof(uct_am_recv_desc_t) +
                                             params->rx_headroom,
                                             rx_priv_len + rx_hdr_len);
    self->config.rx_hdr_offset     = self->config.rx_payload_offset - rx_hdr_len;
    self->config.rx_headroom_offset= self->config.rx_payload_offset -
                                     params->rx_headroom;
    self->config.seg_size          = ucs_min(mss, config->super.max_bcopy);
    self->config.tx_max_poll       = config->tx.max_poll;
    self->config.rx_max_poll       = config->rx.max_poll;
    self->config.rx_max_batch      = ucs_min(config->rx.max_batch,
                                             config->rx.queue_len / 4);
    self->config.port_num          = port_num;
    self->config.sl                = config->sl;
    self->config.gid_index         = config->gid_index;

    status = uct_ib_iface_init_pkey(self, config);
    if (status != UCS_OK) {
        goto err;
    }

    status = uct_ib_device_query_gid(dev, self->config.port_num,
                                     self->config.gid_index, &self->gid);
    if (status != UCS_OK) {
        goto err;
    }

    status = uct_ib_iface_init_lmc(self, config);
    if (status != UCS_OK) {
        goto err;
    }

    self->comp_channel = ibv_create_comp_channel(dev->ibv_context);
    if (self->comp_channel == NULL) {
        ucs_error("ibv_create_comp_channel() failed: %m");
        status = UCS_ERR_IO_ERROR;
        goto err_free_path_bits;
    }

    status = ucs_sys_fcntl_modfl(self->comp_channel->fd, O_NONBLOCK, 0);
    if (status != UCS_OK) {
        goto err_destroy_comp_channel;
    }

    status = uct_ib_iface_create_cq(self, tx_cq_len, 0, &self->send_cq);
    if (status != UCS_OK) {
        goto err_destroy_comp_channel;
    }

    status = uct_ib_iface_create_cq(self, config->rx.queue_len, config->rx.inl,
                                    &self->recv_cq);
    if (status != UCS_OK) {
        goto err_destroy_send_cq;
    }

    /* Address scope and size */
    if (config->addr_type == UCT_IB_IFACE_ADDRESS_TYPE_AUTO) {
        if (IBV_PORT_IS_LINK_LAYER_ETHERNET(uct_ib_iface_port_attr(self))) {
            self->addr_type = UCT_IB_ADDRESS_TYPE_ETH;
        } else {
            self->addr_type = uct_ib_address_scope(self->gid.global.subnet_prefix);
        }
    } else {
        ucs_assert(config->addr_type < UCT_IB_ADDRESS_TYPE_LAST);
        self->addr_type = config->addr_type;
    }

    self->addr_size  = uct_ib_address_size(self->addr_type);

    ucs_debug("created uct_ib_iface_t headroom_ofs %d payload_ofs %d hdr_ofs %d data_sz %d",
              self->config.rx_headroom_offset, self->config.rx_payload_offset,
              self->config.rx_hdr_offset, self->config.seg_size);

    return UCS_OK;

err_destroy_send_cq:
    ibv_destroy_cq(self->send_cq);
err_destroy_comp_channel:
    ibv_destroy_comp_channel(self->comp_channel);
err_free_path_bits:
    ucs_free(self->path_bits);
err:
    return status;
}