Client (active) example

/* 
 * build: 
 * cc -o client client.c -lrdmacm -libverbs
 * 
 * usage: 
 * client <servername> <val1> <val2>
 *
 * connects to server, sends val1 via RDMA write and val2 via send, 
 * and receives val1+val2 back from the server. 
 */ 
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>

#include <rdma/rdma cma.h>
enum   { 
        RESOLVE TIMEOUT MS        = 5000, 
}; 
struct pdata { 
        uint64_t	buf va; 
        uint32_t	buf rkey;
}; 

int main(int argc, char   *argv[ ]) 
{ 
       struct pdata									server pdata; 
       struct rdma_event channel			*cm_channel; 
       struct rdma_cm_id							*cm_id; 
       struct rdma_cm_event					*event;  
       struct rdma_conn_param				conn_param = { };  
       struct ibv_pd								*pd; 
       struct ibv_comp_channel				*comp_chan; 
       struct ibv_cq								*cq; 
       struct ibv_cq								*evt_cq; 
       struct ibv_mr								*mr; 
       struct ibv_qp_init_attr				qp attr = { }; 
       struct ibv_sge								sge; 
       struct ibv_send_wr						send_wr = { }; 
       struct ibv_send_wr 						*bad send wr; 
       struct ibv_recv_wr						recv wr = { }; 
       struct ibv_recv_wr						*bad recv wr; 
       struct ibv_wc								wc; 
       void													*cq context; 
       struct addrinfo								*res, *t; 
       struct addrinfo								hints =   { 
       																			.ai_family    = AF INET, 
       																			.ai_socktype  = SOCK STREAM 
       														};  
			int													n; 
			uint32_t											*buf; 
			int													err; 
			/* Set up RDMA CM structures */ 
			cm_channel = rdma_create_event_channel(); 
			if (!cm_channel)  return 1; 
			err = rdma_create_id(cm_channel, &cm_id, NULL, RDMA_PS_TCP);
			if (err)
					return err;
			n = getaddrinfo(argv[1], "20079", &hints, &res);
			if (n < 0)
					return   1;

			/* Resolve server address and route */
			for (t = res; t; t = t->ai next) {
					err = rdma_resolve_addr(cm_id, NULL, t->ai_addr, RESOLVE_TIMEOUT_MS);
					if (!err)
							break;
			}
			if (err)
					return err;
			err = rdma_get_cm_event(cm_channel, &event);
			if (err)
					return err;
			if (event->event != RDMA_CM_EVENT_ADDR_RESOLVED)
					return 1;
			rdma_ack_cm_event(event);
			err = rdma_resolve_route(cm_id, RESOLVE_TIMEOUT_MS);
			if (err)
					return err;
			err = rdma_get_cm_event(cm_channel, &event);
			if (err)
					return err;
			if (event->event != RDMA_CM_EVENT_ROUTE_RESOLVED)
					return 1;
			rdma_ack_cm_event(event);

			/* Create verbs objects now that we know which device to use */ 
			pd = ibv_alloc_pd(cm_id->verbs); 
			if (!pd) 
					return 1; 
			comp chan = ibv_create_comp_channel(cm_id->verbs);              
			if (!comp_chan) 
					return 1; 
			cq = ibv_create_cq(cm_id->verbs, 2,NULL, comp_chan, 0); 
			if (!cq) 
					return 1; 
  
			if (ibv_req_notify_cq(cq,  0)) 
					return 1; 
 
			buf = calloc(2, sizeof (uint32_t)); 
			if (!buf) 
					return 1; 
			mr = ibv_reg_mr(pd, buf,2 * sizeof(uint32_t), IBV_ACCESS_LOCAL_ WRITE); 
			if (!mr) 
					return 1; 
			qp_attr.cap.max  send_wr = 2; 
			qp_attr.cap.max  send_sge = 1;                                                                            
			qp_attr.cap.max  recv_wr = 1; 
			qp_attr.cap.max  recv_sge = 1; 
			qp_attr.send_cq            = cq;
			qp_attr.recv_cq            = cq;
			qp_attr.qp_type            = IBV_QPT_RC; 
			err = rdma_create_qp(cm_id, pd, &qp_attr);
			if (err)                           
					return err;
			conn_param.initiator_depth = 1;
			conn_param.retry_count = 7;

			/* Connect to server */
			err = rdma_connect(cm_id, &conn_param);
			if (err)
					return err;
			err = rdma_get_cm_event(cm_channel,&event);
			if (err)
					return err;
			if (event->event != RDMA_CM_EVENT_ESTABLISHED)
					return 1;
			memcpy(&server_pdata, event->param.conn.private_data, sizeof server_pdata);
			rdma_ack_cm_event(event);

			/* Prepost receive */ 
			sge.addr    = (uintptr_t) buf; 
			sge.length  = sizeof (uint32_t); 
			sge.lkey    = mr->lkey; 
			recv_wr.wr_id = 0;                
			recv_wr.sg_list = &sge;
			recv_wr.num_sge = 1;
			if (ibv_post_recv(cm_id->qp, &recv_wr, &bad_recv_wr))
					return 1;

			/* Write/send two integers to be added */
			buf[0] = strtoul(argv[2], NULL, 0);
			buf[1] = strtoul(argv[3], NULL, 0);
			printf("%d + %d = ", buf[0], buf[1]);
			buf[0]  = htonl(buf[0]);
			buf[1]  = htonl(buf[1]);

			sge.addr    = (uintptr_t) buf;
			sge.length  = sizeof (uint32_t);
			sge.lkey    =  mr->lkey;
			send_wr.wr_id  = 1;
			sendwr.opcode  = IBV_WR_RDMA_WRITE;
			send _wr.sg_list   = &sge;
			send_wr.num_sge  = 1;
			send_wr.wr.rdma.rkey = ntohl(server_pdata.buf_rkey);
			send_wr.wr.rdma.remote_addr = ntohll(server_pdata.buf_va);
			if (ibv post send(cm id->qp, &send_wr,  &bad_send_wr))
					return 1;
			sge.addr    = (uintptr_t) buf + sizeof (uint32_t);
			sge.length  = sizeof (uint32_t);
			sge.lkey    = mr->lkey;
			send_wr.wr_id                = 2;
			send_wr.opcode                = IBV_WR_SEND;
			send_wr.send_flags            = IBV_SEND_SIGNALED;
			send_wr.sg_list               =&sge;
			send_wr.num_sge              = 1;
			if (ibv_post_send(cm_id->qp, &send_wr,&bad_send_wr))
					return 1;

			/* Wait for receive completion */
			while (1) {           if (ibv_get_cq_event(comp_chan,&evt_cq, &cq_context))
					return 1;
			if (ibv_req_notify_cq(cq, 0))
					return 1;
			if (ibv_poll_cq(cq, 1, &wc) != 1)
					return 1;
			if (wc.status != IBV_WC_SUCCESS)
					return 1;
			if (wc.wr_id == 0) {
					printf("%d\n", ntohl(buf[0]));
					return 0;
			}
    }
    return 0;
  }
[ Feedback ]