1 /*
2  * Copyright (c) 2010-2014 Intel Corporation.  All rights reserved.
3  *
4  * This software is available to you under the OpenIB.org BSD license
5  * below:
6  *
7  *     Redistribution and use in source and binary forms, with or
8  *     without modification, are permitted provided that the following
9  *     conditions are met:
10  *
11  *      - Redistributions of source code must retain the above
12  *        copyright notice, this list of conditions and the following
13  *        disclaimer.
14  *
15  *      - Redistributions in binary form must reproduce the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer in the documentation and/or other materials
18  *        provided with the distribution.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27  * SOFTWARE.
28  */
29 
30 #include <endian.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <netdb.h>
35 #include <errno.h>
36 #include <getopt.h>
37 #include <ctype.h>
38 #include <rdma/rdma_cma.h>
39 #include <rdma/rdma_verbs.h>
40 
41 static const char *server = "127.0.0.1";
42 static char port[6] = "7471";
43 
44 static struct rdma_cm_id *id;
45 static struct ibv_mr *mr;
46 static struct rdma_addrinfo hints;
47 
48 static uint8_t send_msg[16];
49 static uint32_t srqn;
50 
51 static int post_send(void)
52 {
53 	struct ibv_send_wr wr, *bad;
54 	struct ibv_sge sge;
55 	int ret;
56 
57 	sge.addr = (uint64_t) (uintptr_t) send_msg;
58 	sge.length = (uint32_t) sizeof send_msg;
59 	sge.lkey = 0;
60 	wr.wr_id = (uintptr_t) NULL;
61 	wr.next = NULL;
62 	wr.sg_list = &sge;
63 	wr.num_sge = 1;
64 	wr.opcode = IBV_WR_SEND;
65 	wr.send_flags = IBV_SEND_INLINE;
66 	if (hints.ai_qp_type == IBV_QPT_XRC_SEND)
67 		wr.qp_type.xrc.remote_srqn = srqn;
68 
69 	ret = ibv_post_send(id->qp, &wr, &bad);
70 	if (ret)
71 		perror("rdma_post_send");
72 
73 	return ret;
74 }
75 
76 static int test(void)
77 {
78 	struct rdma_addrinfo *res;
79 	struct ibv_qp_init_attr attr;
80 	struct ibv_wc wc;
81 	int ret;
82 
83 	ret = rdma_getaddrinfo(server, port, &hints, &res);
84 	if (ret) {
85 		printf("rdma_getaddrinfo: %s\n", gai_strerror(ret));
86 		return ret;
87 	}
88 
89 	memset(&attr, 0, sizeof attr);
90 	attr.cap.max_send_wr = attr.cap.max_recv_wr = 1;
91 	attr.cap.max_send_sge = attr.cap.max_recv_sge = 1;
92 	attr.sq_sig_all = 1;
93 	ret = rdma_create_ep(&id, res, NULL, &attr);
94 	rdma_freeaddrinfo(res);
95 	if (ret) {
96 		perror("rdma_create_ep");
97 		return ret;
98 	}
99 
100 	mr = rdma_reg_msgs(id, send_msg, sizeof send_msg);
101 	if (!mr) {
102 		perror("rdma_reg_msgs");
103 		return ret;
104 	}
105 
106 	ret = rdma_connect(id, NULL);
107 	if (ret) {
108 		perror("rdma_connect");
109 		return ret;
110 	}
111 
112 	if (hints.ai_qp_type == IBV_QPT_XRC_SEND)
113 		srqn = be32toh(*(__be32 *) id->event->param.conn.private_data);
114 
115 	ret = post_send();
116 	if (ret) {
117 		perror("post_send");
118 		return ret;
119 	}
120 
121 	ret = rdma_get_send_comp(id, &wc);
122 	if (ret <= 0) {
123 		perror("rdma_get_recv_comp");
124 		return ret;
125 	}
126 
127 	rdma_disconnect(id);
128 	rdma_dereg_mr(mr);
129 	rdma_destroy_ep(id);
130 	return 0;
131 }
132 
133 int main(int argc, char **argv)
134 {
135 	int op, ret;
136 
137 	hints.ai_port_space = RDMA_PS_TCP;
138 	hints.ai_qp_type = IBV_QPT_RC;
139 
140 	while ((op = getopt(argc, argv, "s:p:c:")) != -1) {
141 		switch (op) {
142 		case 's':
143 			server = optarg;
144 			break;
145 		case 'p':
146 			strncpy(port, optarg, sizeof port - 1);
147 			break;
148 		case 'c':
149 			switch (tolower(optarg[0])) {
150 			case 'r':
151 				break;
152 			case 'x':
153 				hints.ai_port_space = RDMA_PS_IB;
154 				hints.ai_qp_type = IBV_QPT_XRC_SEND;
155 				break;
156 			default:
157 				goto err;
158 			}
159 			break;
160 		default:
161 			goto err;
162 		}
163 	}
164 
165 	printf("%s: start\n", argv[0]);
166 	ret = test();
167 	printf("%s: end %d\n", argv[0], ret);
168 	return ret;
169 
170 err:
171 	printf("usage: %s\n", argv[0]);
172 	printf("\t[-s server]\n");
173 	printf("\t[-p port_number]\n");
174 	printf("\t[-c communication type]\n");
175 	printf("\t    r - RC: reliable-connected (default)\n");
176 	printf("\t    x - XRC: extended-reliable-connected\n");
177 	exit(1);
178 }
179