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
41static const char *server = "127.0.0.1";
42static char port[6] = "7471";
43
44static struct rdma_cm_id *id;
45static struct ibv_mr *mr;
46static struct rdma_addrinfo hints;
47
48static uint8_t send_msg[16];
49static uint32_t srqn;
50
51static 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
76static 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
133int 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
170err:
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