1 /*
2  * Copyright (c) 2005-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 <errno.h>
35 #include <getopt.h>
36 #include <netdb.h>
37 #include <ctype.h>
38 #include <rdma/rdma_cma.h>
39 #include <rdma/rdma_verbs.h>
40 
41 static const char *port = "7471";
42 
43 static struct rdma_cm_id *listen_id, *id;
44 static struct ibv_mr *mr;
45 static struct rdma_addrinfo hints;
46 
47 static uint8_t recv_msg[16];
48 static __be32 srqn;
49 
50 static int create_srq(void)
51 {
52 	struct ibv_srq_init_attr attr;
53 	int ret;
54 	uint32_t tmp_srqn;
55 
56 	attr.attr.max_wr = 1;
57 	attr.attr.max_sge = 1;
58 	attr.attr.srq_limit = 0;
59 	attr.srq_context = id;
60 
61 	ret = rdma_create_srq(id, NULL, &attr);
62 	if (ret)
63 		perror("rdma_create_srq:");
64 
65 	if (id->srq) {
66 		ibv_get_srq_num(id->srq, &tmp_srqn);
67 		srqn = htobe32(tmp_srqn);
68 	}
69 	return ret;
70 }
71 
72 static int test(void)
73 {
74 	struct rdma_addrinfo *res;
75 	struct ibv_qp_init_attr attr;
76 	struct rdma_conn_param param;
77 	struct ibv_wc wc;
78 	int ret;
79 
80 	ret = rdma_getaddrinfo(NULL, port, &hints, &res);
81 	if (ret) {
82 		printf("rdma_getaddrinfo: %s\n", gai_strerror(ret));
83 		return ret;
84 	}
85 
86 	memset(&attr, 0, sizeof attr);
87 	attr.cap.max_send_wr = attr.cap.max_recv_wr = 1;
88 	attr.cap.max_send_sge = attr.cap.max_recv_sge = 1;
89 	ret = rdma_create_ep(&listen_id, res, NULL, &attr);
90 	rdma_freeaddrinfo(res);
91 	if (ret) {
92 		perror("rdma_create_ep");
93 		return ret;
94 	}
95 
96 	ret = rdma_listen(listen_id, 0);
97 	if (ret) {
98 		perror("rdma_listen");
99 		return ret;
100 	}
101 
102 	ret = rdma_get_request(listen_id, &id);
103 	if (ret) {
104 		perror("rdma_get_request");
105 		return ret;
106 	}
107 
108 	if (hints.ai_qp_type == IBV_QPT_XRC_RECV) {
109 		ret = create_srq();
110 		if (ret)
111 			return ret;
112 	}
113 
114 	mr = rdma_reg_msgs(id, recv_msg, sizeof recv_msg);
115 	if (!mr) {
116 		perror("rdma_reg_msgs");
117 		return ret;
118 	}
119 
120 	ret = rdma_post_recv(id, NULL, recv_msg, sizeof recv_msg, mr);
121 	if (ret) {
122 		perror("rdma_post_recv");
123 		return ret;
124 	}
125 
126 	memset(&param, 0, sizeof param);
127 	param.private_data = &srqn;
128 	param.private_data_len = sizeof srqn;
129 	ret = rdma_accept(id, &param);
130 	if (ret) {
131 		perror("rdma_accept");
132 		return ret;
133 	}
134 
135 	ret = rdma_get_recv_comp(id, &wc);
136 	if (ret <= 0) {
137 		perror("rdma_get_recv_comp");
138 		return ret;
139 	}
140 
141 	rdma_disconnect(id);
142 	rdma_dereg_mr(mr);
143 	rdma_destroy_ep(id);
144 	rdma_destroy_ep(listen_id);
145 	return 0;
146 }
147 
148 int main(int argc, char **argv)
149 {
150 	int op, ret;
151 
152 	hints.ai_flags = RAI_PASSIVE;
153 	hints.ai_port_space = RDMA_PS_TCP;
154 	hints.ai_qp_type = IBV_QPT_RC;
155 
156 	while ((op = getopt(argc, argv, "p:c:")) != -1) {
157 		switch (op) {
158 		case 'p':
159 			port = optarg;
160 			break;
161 		case 'c':
162 			switch (tolower(optarg[0])) {
163 			case 'r':
164 				break;
165 			case 'x':
166 				hints.ai_port_space = RDMA_PS_IB;
167 				hints.ai_qp_type = IBV_QPT_XRC_RECV;
168 				break;
169 			default:
170 				goto err;
171 			}
172 			break;
173 		default:
174 			goto err;
175 		}
176 	}
177 
178 	printf("%s: start\n", argv[0]);
179 	ret = test();
180 	printf("%s: end %d\n", argv[0], ret);
181 	return ret;
182 
183 err:
184 	printf("usage: %s\n", argv[0]);
185 	printf("\t[-p port_number]\n");
186 	printf("\t[-c communication type]\n");
187 	printf("\t    r - RC: reliable-connected (default)\n");
188 	printf("\t    x - XRC: extended-reliable-connected\n");
189 	exit(1);
190 }
191