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
41static const char *port = "7471";
42
43static struct rdma_cm_id *listen_id, *id;
44static struct ibv_mr *mr;
45static struct rdma_addrinfo hints;
46
47static uint8_t recv_msg[16];
48static __be32 srqn;
49
50static 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
72static 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
148int 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
183err:
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