1321936Shselasky/*
2321936Shselasky * Copyright (c) 2005-2009 Intel Corporation.  All rights reserved.
3321936Shselasky *
4321936Shselasky * This software is available to you under the OpenIB.org BSD license
5321936Shselasky * below:
6321936Shselasky *
7321936Shselasky *     Redistribution and use in source and binary forms, with or
8321936Shselasky *     without modification, are permitted provided that the following
9321936Shselasky *     conditions are met:
10321936Shselasky *
11321936Shselasky *      - Redistributions of source code must retain the above
12321936Shselasky *        copyright notice, this list of conditions and the following
13321936Shselasky *        disclaimer.
14321936Shselasky *
15321936Shselasky *      - Redistributions in binary form must reproduce the above
16321936Shselasky *        copyright notice, this list of conditions and the following
17321936Shselasky *        disclaimer in the documentation and/or other materials
18321936Shselasky *        provided with the distribution.
19321936Shselasky *
20321936Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21321936Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22321936Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
23321936Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24321936Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25321936Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26321936Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27321936Shselasky * SOFTWARE.
28321936Shselasky */
29321936Shselasky
30321936Shselasky#include <stdio.h>
31321936Shselasky#include <stdlib.h>
32321936Shselasky#include <string.h>
33321936Shselasky#include <errno.h>
34321936Shselasky#include <getopt.h>
35321936Shselasky#include <netdb.h>
36321936Shselasky#include <rdma/rdma_cma.h>
37321936Shselasky#include <rdma/rdma_verbs.h>
38321936Shselasky
39321936Shselaskystatic const char *port = "7471";
40321936Shselasky
41321936Shselaskystatic struct rdma_cm_id *listen_id, *id;
42321936Shselaskystatic struct ibv_mr *mr, *send_mr;
43321936Shselaskystatic int send_flags;
44321936Shselaskystatic uint8_t send_msg[16];
45321936Shselaskystatic uint8_t recv_msg[16];
46321936Shselasky
47321936Shselaskystatic int run(void)
48321936Shselasky{
49321936Shselasky	struct rdma_addrinfo hints, *res;
50321936Shselasky	struct ibv_qp_init_attr init_attr;
51321936Shselasky	struct ibv_qp_attr qp_attr;
52321936Shselasky	struct ibv_wc wc;
53321936Shselasky	int ret;
54321936Shselasky
55321936Shselasky	memset(&hints, 0, sizeof hints);
56321936Shselasky	hints.ai_flags = RAI_PASSIVE;
57321936Shselasky	hints.ai_port_space = RDMA_PS_TCP;
58321936Shselasky	ret = rdma_getaddrinfo(NULL, port, &hints, &res);
59321936Shselasky	if (ret) {
60321936Shselasky		printf("rdma_getaddrinfo: %s\n", gai_strerror(ret));
61321936Shselasky		return ret;
62321936Shselasky	}
63321936Shselasky
64321936Shselasky	memset(&init_attr, 0, sizeof init_attr);
65321936Shselasky	init_attr.cap.max_send_wr = init_attr.cap.max_recv_wr = 1;
66321936Shselasky	init_attr.cap.max_send_sge = init_attr.cap.max_recv_sge = 1;
67321936Shselasky	init_attr.cap.max_inline_data = 16;
68321936Shselasky	init_attr.sq_sig_all = 1;
69321936Shselasky	ret = rdma_create_ep(&listen_id, res, NULL, &init_attr);
70321936Shselasky	if (ret) {
71321936Shselasky		perror("rdma_create_ep");
72321936Shselasky		goto out_free_addrinfo;
73321936Shselasky	}
74321936Shselasky
75321936Shselasky	ret = rdma_listen(listen_id, 0);
76321936Shselasky	if (ret) {
77321936Shselasky		perror("rdma_listen");
78321936Shselasky		goto out_destroy_listen_ep;
79321936Shselasky	}
80321936Shselasky
81321936Shselasky	ret = rdma_get_request(listen_id, &id);
82321936Shselasky	if (ret) {
83321936Shselasky		perror("rdma_get_request");
84321936Shselasky		goto out_destroy_listen_ep;
85321936Shselasky	}
86321936Shselasky
87321936Shselasky	memset(&qp_attr, 0, sizeof qp_attr);
88321936Shselasky	memset(&init_attr, 0, sizeof init_attr);
89321936Shselasky	ret = ibv_query_qp(id->qp, &qp_attr, IBV_QP_CAP,
90321936Shselasky			   &init_attr);
91321936Shselasky	if (ret) {
92321936Shselasky		perror("ibv_query_qp");
93321936Shselasky		goto out_destroy_accept_ep;
94321936Shselasky	}
95321936Shselasky	if (init_attr.cap.max_inline_data >= 16)
96321936Shselasky		send_flags = IBV_SEND_INLINE;
97321936Shselasky	else
98321936Shselasky		printf("rdma_server: device doesn't support IBV_SEND_INLINE, "
99321936Shselasky		       "using sge sends\n");
100321936Shselasky
101321936Shselasky	mr = rdma_reg_msgs(id, recv_msg, 16);
102321936Shselasky	if (!mr) {
103321936Shselasky		ret = -1;
104321936Shselasky		perror("rdma_reg_msgs for recv_msg");
105321936Shselasky		goto out_destroy_accept_ep;
106321936Shselasky	}
107321936Shselasky	if ((send_flags & IBV_SEND_INLINE) == 0) {
108321936Shselasky		send_mr = rdma_reg_msgs(id, send_msg, 16);
109321936Shselasky		if (!send_mr) {
110321936Shselasky			ret = -1;
111321936Shselasky			perror("rdma_reg_msgs for send_msg");
112321936Shselasky			goto out_dereg_recv;
113321936Shselasky		}
114321936Shselasky	}
115321936Shselasky
116321936Shselasky	ret = rdma_post_recv(id, NULL, recv_msg, 16, mr);
117321936Shselasky	if (ret) {
118321936Shselasky		perror("rdma_post_recv");
119321936Shselasky		goto out_dereg_send;
120321936Shselasky	}
121321936Shselasky
122321936Shselasky	ret = rdma_accept(id, NULL);
123321936Shselasky	if (ret) {
124321936Shselasky		perror("rdma_accept");
125321936Shselasky		goto out_dereg_send;
126321936Shselasky	}
127321936Shselasky
128321936Shselasky	while ((ret = rdma_get_recv_comp(id, &wc)) == 0);
129321936Shselasky	if (ret < 0) {
130321936Shselasky		perror("rdma_get_recv_comp");
131321936Shselasky		goto out_disconnect;
132321936Shselasky	}
133321936Shselasky
134321936Shselasky	ret = rdma_post_send(id, NULL, send_msg, 16, send_mr, send_flags);
135321936Shselasky	if (ret) {
136321936Shselasky		perror("rdma_post_send");
137321936Shselasky		goto out_disconnect;
138321936Shselasky	}
139321936Shselasky
140321936Shselasky	while ((ret = rdma_get_send_comp(id, &wc)) == 0);
141321936Shselasky	if (ret < 0)
142321936Shselasky		perror("rdma_get_send_comp");
143321936Shselasky	else
144321936Shselasky		ret = 0;
145321936Shselasky
146321936Shselaskyout_disconnect:
147321936Shselasky	rdma_disconnect(id);
148321936Shselaskyout_dereg_send:
149321936Shselasky	if ((send_flags & IBV_SEND_INLINE) == 0)
150321936Shselasky		rdma_dereg_mr(send_mr);
151321936Shselaskyout_dereg_recv:
152321936Shselasky	rdma_dereg_mr(mr);
153321936Shselaskyout_destroy_accept_ep:
154321936Shselasky	rdma_destroy_ep(id);
155321936Shselaskyout_destroy_listen_ep:
156321936Shselasky	rdma_destroy_ep(listen_id);
157321936Shselaskyout_free_addrinfo:
158321936Shselasky	rdma_freeaddrinfo(res);
159321936Shselasky	return ret;
160321936Shselasky}
161321936Shselasky
162321936Shselaskyint main(int argc, char **argv)
163321936Shselasky{
164321936Shselasky	int op, ret;
165321936Shselasky
166321936Shselasky	while ((op = getopt(argc, argv, "p:")) != -1) {
167321936Shselasky		switch (op) {
168321936Shselasky		case 'p':
169321936Shselasky			port = optarg;
170321936Shselasky			break;
171321936Shselasky		default:
172321936Shselasky			printf("usage: %s\n", argv[0]);
173321936Shselasky			printf("\t[-p port_number]\n");
174321936Shselasky			exit(1);
175321936Shselasky		}
176321936Shselasky	}
177321936Shselasky
178321936Shselasky	printf("rdma_server: start\n");
179321936Shselasky	ret = run();
180321936Shselasky	printf("rdma_server: end %d\n", ret);
181321936Shselasky	return ret;
182321936Shselasky}
183