1 /*
2  * Copyright (c) 2005-2009 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 <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <getopt.h>
35 #include <netdb.h>
36 #include <rdma/rdma_cma.h>
37 #include <rdma/rdma_verbs.h>
38 
39 static const char *port = "7471";
40 
41 static struct rdma_cm_id *listen_id, *id;
42 static struct ibv_mr *mr, *send_mr;
43 static int send_flags;
44 static uint8_t send_msg[16];
45 static uint8_t recv_msg[16];
46 
run(void)47 static int run(void)
48 {
49 	struct rdma_addrinfo hints, *res;
50 	struct ibv_qp_init_attr init_attr;
51 	struct ibv_qp_attr qp_attr;
52 	struct ibv_wc wc;
53 	int ret;
54 
55 	memset(&hints, 0, sizeof hints);
56 	hints.ai_flags = RAI_PASSIVE;
57 	hints.ai_port_space = RDMA_PS_TCP;
58 	ret = rdma_getaddrinfo(NULL, port, &hints, &res);
59 	if (ret) {
60 		printf("rdma_getaddrinfo: %s\n", gai_strerror(ret));
61 		return ret;
62 	}
63 
64 	memset(&init_attr, 0, sizeof init_attr);
65 	init_attr.cap.max_send_wr = init_attr.cap.max_recv_wr = 1;
66 	init_attr.cap.max_send_sge = init_attr.cap.max_recv_sge = 1;
67 	init_attr.cap.max_inline_data = 16;
68 	init_attr.sq_sig_all = 1;
69 	ret = rdma_create_ep(&listen_id, res, NULL, &init_attr);
70 	if (ret) {
71 		perror("rdma_create_ep");
72 		goto out_free_addrinfo;
73 	}
74 
75 	ret = rdma_listen(listen_id, 0);
76 	if (ret) {
77 		perror("rdma_listen");
78 		goto out_destroy_listen_ep;
79 	}
80 
81 	ret = rdma_get_request(listen_id, &id);
82 	if (ret) {
83 		perror("rdma_get_request");
84 		goto out_destroy_listen_ep;
85 	}
86 
87 	memset(&qp_attr, 0, sizeof qp_attr);
88 	memset(&init_attr, 0, sizeof init_attr);
89 	ret = ibv_query_qp(id->qp, &qp_attr, IBV_QP_CAP,
90 			   &init_attr);
91 	if (ret) {
92 		perror("ibv_query_qp");
93 		goto out_destroy_accept_ep;
94 	}
95 	if (init_attr.cap.max_inline_data >= 16)
96 		send_flags = IBV_SEND_INLINE;
97 	else
98 		printf("rdma_server: device doesn't support IBV_SEND_INLINE, "
99 		       "using sge sends\n");
100 
101 	mr = rdma_reg_msgs(id, recv_msg, 16);
102 	if (!mr) {
103 		ret = -1;
104 		perror("rdma_reg_msgs for recv_msg");
105 		goto out_destroy_accept_ep;
106 	}
107 	if ((send_flags & IBV_SEND_INLINE) == 0) {
108 		send_mr = rdma_reg_msgs(id, send_msg, 16);
109 		if (!send_mr) {
110 			ret = -1;
111 			perror("rdma_reg_msgs for send_msg");
112 			goto out_dereg_recv;
113 		}
114 	}
115 
116 	ret = rdma_post_recv(id, NULL, recv_msg, 16, mr);
117 	if (ret) {
118 		perror("rdma_post_recv");
119 		goto out_dereg_send;
120 	}
121 
122 	ret = rdma_accept(id, NULL);
123 	if (ret) {
124 		perror("rdma_accept");
125 		goto out_dereg_send;
126 	}
127 
128 	while ((ret = rdma_get_recv_comp(id, &wc)) == 0);
129 	if (ret < 0) {
130 		perror("rdma_get_recv_comp");
131 		goto out_disconnect;
132 	}
133 
134 	ret = rdma_post_send(id, NULL, send_msg, 16, send_mr, send_flags);
135 	if (ret) {
136 		perror("rdma_post_send");
137 		goto out_disconnect;
138 	}
139 
140 	while ((ret = rdma_get_send_comp(id, &wc)) == 0);
141 	if (ret < 0)
142 		perror("rdma_get_send_comp");
143 	else
144 		ret = 0;
145 
146 out_disconnect:
147 	rdma_disconnect(id);
148 out_dereg_send:
149 	if ((send_flags & IBV_SEND_INLINE) == 0)
150 		rdma_dereg_mr(send_mr);
151 out_dereg_recv:
152 	rdma_dereg_mr(mr);
153 out_destroy_accept_ep:
154 	rdma_destroy_ep(id);
155 out_destroy_listen_ep:
156 	rdma_destroy_ep(listen_id);
157 out_free_addrinfo:
158 	rdma_freeaddrinfo(res);
159 	return ret;
160 }
161 
main(int argc,char ** argv)162 int main(int argc, char **argv)
163 {
164 	int op, ret;
165 
166 	while ((op = getopt(argc, argv, "p:")) != -1) {
167 		switch (op) {
168 		case 'p':
169 			port = optarg;
170 			break;
171 		default:
172 			printf("usage: %s\n", argv[0]);
173 			printf("\t[-p port_number]\n");
174 			exit(1);
175 		}
176 	}
177 
178 	printf("rdma_server: start\n");
179 	ret = run();
180 	printf("rdma_server: end %d\n", ret);
181 	return ret;
182 }
183