xref: /freebsd/contrib/ofed/librdmacm/acm.c (revision 87181516ef48be852d5e5fee53c6e0dbfc62f21e)
1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky  * Copyright (c) 2010-2012 Intel Corporation.  All rights reserved.
3*d6b92ffaSHans Petter Selasky  *
4*d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
5*d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
6*d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
7*d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
8*d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
9*d6b92ffaSHans Petter Selasky  *
10*d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
11*d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
12*d6b92ffaSHans Petter Selasky  *     conditions are met:
13*d6b92ffaSHans Petter Selasky  *
14*d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
15*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
16*d6b92ffaSHans Petter Selasky  *        disclaimer.
17*d6b92ffaSHans Petter Selasky  *
18*d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
19*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
20*d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
21*d6b92ffaSHans Petter Selasky  *        provided with the distribution.
22*d6b92ffaSHans Petter Selasky  *
23*d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24*d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25*d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26*d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27*d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28*d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29*d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30*d6b92ffaSHans Petter Selasky  * SOFTWARE.
31*d6b92ffaSHans Petter Selasky  */
32*d6b92ffaSHans Petter Selasky 
33*d6b92ffaSHans Petter Selasky #include <config.h>
34*d6b92ffaSHans Petter Selasky 
35*d6b92ffaSHans Petter Selasky #include <stdio.h>
36*d6b92ffaSHans Petter Selasky #include <inttypes.h>
37*d6b92ffaSHans Petter Selasky #include <sys/types.h>
38*d6b92ffaSHans Petter Selasky #include <sys/socket.h>
39*d6b92ffaSHans Petter Selasky #include <netdb.h>
40*d6b92ffaSHans Petter Selasky #include <unistd.h>
41*d6b92ffaSHans Petter Selasky 
42*d6b92ffaSHans Petter Selasky #include "cma.h"
43*d6b92ffaSHans Petter Selasky #include <rdma/rdma_cma.h>
44*d6b92ffaSHans Petter Selasky #include <infiniband/ib.h>
45*d6b92ffaSHans Petter Selasky #include <infiniband/sa.h>
46*d6b92ffaSHans Petter Selasky 
47*d6b92ffaSHans Petter Selasky #define ACM_VERSION             1
48*d6b92ffaSHans Petter Selasky 
49*d6b92ffaSHans Petter Selasky #define ACM_OP_RESOLVE          0x01
50*d6b92ffaSHans Petter Selasky #define ACM_OP_ACK              0x80
51*d6b92ffaSHans Petter Selasky 
52*d6b92ffaSHans Petter Selasky #define ACM_STATUS_SUCCESS      0
53*d6b92ffaSHans Petter Selasky #define ACM_STATUS_ENOMEM       1
54*d6b92ffaSHans Petter Selasky #define ACM_STATUS_EINVAL       2
55*d6b92ffaSHans Petter Selasky #define ACM_STATUS_ENODATA      3
56*d6b92ffaSHans Petter Selasky #define ACM_STATUS_ENOTCONN     5
57*d6b92ffaSHans Petter Selasky #define ACM_STATUS_ETIMEDOUT    6
58*d6b92ffaSHans Petter Selasky #define ACM_STATUS_ESRCADDR     7
59*d6b92ffaSHans Petter Selasky #define ACM_STATUS_ESRCTYPE     8
60*d6b92ffaSHans Petter Selasky #define ACM_STATUS_EDESTADDR    9
61*d6b92ffaSHans Petter Selasky #define ACM_STATUS_EDESTTYPE    10
62*d6b92ffaSHans Petter Selasky 
63*d6b92ffaSHans Petter Selasky #define ACM_FLAGS_NODELAY	(1<<30)
64*d6b92ffaSHans Petter Selasky 
65*d6b92ffaSHans Petter Selasky #define ACM_MSG_HDR_LENGTH      16
66*d6b92ffaSHans Petter Selasky #define ACM_MAX_ADDRESS         64
67*d6b92ffaSHans Petter Selasky #define ACM_MSG_EP_LENGTH       72
68*d6b92ffaSHans Petter Selasky #define ACM_MSG_DATA_LENGTH     (ACM_MSG_EP_LENGTH * 8)
69*d6b92ffaSHans Petter Selasky 
70*d6b92ffaSHans Petter Selasky struct acm_hdr {
71*d6b92ffaSHans Petter Selasky 	uint8_t                 version;
72*d6b92ffaSHans Petter Selasky 	uint8_t                 opcode;
73*d6b92ffaSHans Petter Selasky 	uint8_t                 status;
74*d6b92ffaSHans Petter Selasky 	uint8_t		        data[3];
75*d6b92ffaSHans Petter Selasky 	uint16_t                length;
76*d6b92ffaSHans Petter Selasky 	uint64_t                tid;
77*d6b92ffaSHans Petter Selasky };
78*d6b92ffaSHans Petter Selasky 
79*d6b92ffaSHans Petter Selasky #define ACM_EP_INFO_NAME        0x0001
80*d6b92ffaSHans Petter Selasky #define ACM_EP_INFO_ADDRESS_IP  0x0002
81*d6b92ffaSHans Petter Selasky #define ACM_EP_INFO_ADDRESS_IP6 0x0003
82*d6b92ffaSHans Petter Selasky #define ACM_EP_INFO_PATH        0x0010
83*d6b92ffaSHans Petter Selasky 
84*d6b92ffaSHans Petter Selasky union acm_ep_info {
85*d6b92ffaSHans Petter Selasky 	uint8_t                 addr[ACM_MAX_ADDRESS];
86*d6b92ffaSHans Petter Selasky 	uint8_t                 name[ACM_MAX_ADDRESS];
87*d6b92ffaSHans Petter Selasky 	struct ibv_path_record  path;
88*d6b92ffaSHans Petter Selasky };
89*d6b92ffaSHans Petter Selasky 
90*d6b92ffaSHans Petter Selasky #define ACM_EP_FLAG_SOURCE      (1<<0)
91*d6b92ffaSHans Petter Selasky #define ACM_EP_FLAG_DEST        (1<<1)
92*d6b92ffaSHans Petter Selasky 
93*d6b92ffaSHans Petter Selasky struct acm_ep_addr_data {
94*d6b92ffaSHans Petter Selasky 	uint32_t                flags;
95*d6b92ffaSHans Petter Selasky 	uint16_t                type;
96*d6b92ffaSHans Petter Selasky 	uint16_t                reserved;
97*d6b92ffaSHans Petter Selasky 	union acm_ep_info       info;
98*d6b92ffaSHans Petter Selasky };
99*d6b92ffaSHans Petter Selasky 
100*d6b92ffaSHans Petter Selasky struct acm_resolve_msg {
101*d6b92ffaSHans Petter Selasky 	struct acm_hdr          hdr;
102*d6b92ffaSHans Petter Selasky 	struct acm_ep_addr_data data[0];
103*d6b92ffaSHans Petter Selasky };
104*d6b92ffaSHans Petter Selasky 
105*d6b92ffaSHans Petter Selasky struct acm_msg {
106*d6b92ffaSHans Petter Selasky 	struct acm_hdr                  hdr;
107*d6b92ffaSHans Petter Selasky 	union{
108*d6b92ffaSHans Petter Selasky 		uint8_t                 data[ACM_MSG_DATA_LENGTH];
109*d6b92ffaSHans Petter Selasky 		struct acm_ep_addr_data resolve_data[0];
110*d6b92ffaSHans Petter Selasky 	};
111*d6b92ffaSHans Petter Selasky };
112*d6b92ffaSHans Petter Selasky 
113*d6b92ffaSHans Petter Selasky static pthread_mutex_t acm_lock = PTHREAD_MUTEX_INITIALIZER;
114*d6b92ffaSHans Petter Selasky static int sock = -1;
115*d6b92ffaSHans Petter Selasky static uint16_t server_port;
116*d6b92ffaSHans Petter Selasky 
ucma_set_server_port(void)117*d6b92ffaSHans Petter Selasky static int ucma_set_server_port(void)
118*d6b92ffaSHans Petter Selasky {
119*d6b92ffaSHans Petter Selasky 	FILE *f;
120*d6b92ffaSHans Petter Selasky 
121*d6b92ffaSHans Petter Selasky 	if ((f = fopen(IBACM_PORT_FILE, "r" STREAM_CLOEXEC))) {
122*d6b92ffaSHans Petter Selasky 		if (fscanf(f, "%" SCNu16, &server_port) != 1)
123*d6b92ffaSHans Petter Selasky 			server_port = 0;
124*d6b92ffaSHans Petter Selasky 		fclose(f);
125*d6b92ffaSHans Petter Selasky 	}
126*d6b92ffaSHans Petter Selasky 	return server_port;
127*d6b92ffaSHans Petter Selasky }
128*d6b92ffaSHans Petter Selasky 
ucma_ib_init(void)129*d6b92ffaSHans Petter Selasky void ucma_ib_init(void)
130*d6b92ffaSHans Petter Selasky {
131*d6b92ffaSHans Petter Selasky 	struct sockaddr_in addr;
132*d6b92ffaSHans Petter Selasky 	static int init;
133*d6b92ffaSHans Petter Selasky 	int ret;
134*d6b92ffaSHans Petter Selasky 
135*d6b92ffaSHans Petter Selasky 	if (init)
136*d6b92ffaSHans Petter Selasky 		return;
137*d6b92ffaSHans Petter Selasky 
138*d6b92ffaSHans Petter Selasky 	pthread_mutex_lock(&acm_lock);
139*d6b92ffaSHans Petter Selasky 	if (init)
140*d6b92ffaSHans Petter Selasky 		goto unlock;
141*d6b92ffaSHans Petter Selasky 
142*d6b92ffaSHans Petter Selasky 	if (!ucma_set_server_port())
143*d6b92ffaSHans Petter Selasky 		goto out;
144*d6b92ffaSHans Petter Selasky 
145*d6b92ffaSHans Petter Selasky 	sock = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
146*d6b92ffaSHans Petter Selasky 	if (sock < 0)
147*d6b92ffaSHans Petter Selasky 		goto out;
148*d6b92ffaSHans Petter Selasky 
149*d6b92ffaSHans Petter Selasky 	memset(&addr, 0, sizeof addr);
150*d6b92ffaSHans Petter Selasky 	addr.sin_family = AF_INET;
151*d6b92ffaSHans Petter Selasky 	addr.sin_addr.s_addr = htobe32(INADDR_LOOPBACK);
152*d6b92ffaSHans Petter Selasky 	addr.sin_port = htobe16(server_port);
153*d6b92ffaSHans Petter Selasky 	ret = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
154*d6b92ffaSHans Petter Selasky 	if (ret) {
155*d6b92ffaSHans Petter Selasky 		close(sock);
156*d6b92ffaSHans Petter Selasky 		sock = -1;
157*d6b92ffaSHans Petter Selasky 	}
158*d6b92ffaSHans Petter Selasky out:
159*d6b92ffaSHans Petter Selasky 	init = 1;
160*d6b92ffaSHans Petter Selasky unlock:
161*d6b92ffaSHans Petter Selasky 	pthread_mutex_unlock(&acm_lock);
162*d6b92ffaSHans Petter Selasky }
163*d6b92ffaSHans Petter Selasky 
ucma_ib_cleanup(void)164*d6b92ffaSHans Petter Selasky void ucma_ib_cleanup(void)
165*d6b92ffaSHans Petter Selasky {
166*d6b92ffaSHans Petter Selasky 	if (sock >= 0) {
167*d6b92ffaSHans Petter Selasky 		shutdown(sock, SHUT_RDWR);
168*d6b92ffaSHans Petter Selasky 		close(sock);
169*d6b92ffaSHans Petter Selasky 	}
170*d6b92ffaSHans Petter Selasky }
171*d6b92ffaSHans Petter Selasky 
ucma_ib_set_addr(struct rdma_addrinfo * ib_rai,struct rdma_addrinfo * rai)172*d6b92ffaSHans Petter Selasky static int ucma_ib_set_addr(struct rdma_addrinfo *ib_rai,
173*d6b92ffaSHans Petter Selasky 			    struct rdma_addrinfo *rai)
174*d6b92ffaSHans Petter Selasky {
175*d6b92ffaSHans Petter Selasky 	struct sockaddr_ib *src, *dst;
176*d6b92ffaSHans Petter Selasky 	struct ibv_path_record *path;
177*d6b92ffaSHans Petter Selasky 
178*d6b92ffaSHans Petter Selasky 	src = calloc(1, sizeof(*src));
179*d6b92ffaSHans Petter Selasky 	if (!src)
180*d6b92ffaSHans Petter Selasky 		return ERR(ENOMEM);
181*d6b92ffaSHans Petter Selasky 
182*d6b92ffaSHans Petter Selasky 	dst = calloc(1, sizeof(*dst));
183*d6b92ffaSHans Petter Selasky 	if (!dst) {
184*d6b92ffaSHans Petter Selasky 		free(src);
185*d6b92ffaSHans Petter Selasky 		return ERR(ENOMEM);
186*d6b92ffaSHans Petter Selasky 	}
187*d6b92ffaSHans Petter Selasky 
188*d6b92ffaSHans Petter Selasky 	path = &((struct ibv_path_data *) ib_rai->ai_route)->path;
189*d6b92ffaSHans Petter Selasky 
190*d6b92ffaSHans Petter Selasky 	src->sib_family = AF_IB;
191*d6b92ffaSHans Petter Selasky 	src->sib_pkey = path->pkey;
192*d6b92ffaSHans Petter Selasky 	src->sib_flowinfo = htobe32(be32toh(path->flowlabel_hoplimit) >> 8);
193*d6b92ffaSHans Petter Selasky 	memcpy(&src->sib_addr, &path->sgid, 16);
194*d6b92ffaSHans Petter Selasky 	ucma_set_sid(ib_rai->ai_port_space, rai->ai_src_addr, src);
195*d6b92ffaSHans Petter Selasky 
196*d6b92ffaSHans Petter Selasky 	dst->sib_family = AF_IB;
197*d6b92ffaSHans Petter Selasky 	dst->sib_pkey = path->pkey;
198*d6b92ffaSHans Petter Selasky 	dst->sib_flowinfo = htobe32(be32toh(path->flowlabel_hoplimit) >> 8);
199*d6b92ffaSHans Petter Selasky 	memcpy(&dst->sib_addr, &path->dgid, 16);
200*d6b92ffaSHans Petter Selasky 	ucma_set_sid(ib_rai->ai_port_space, rai->ai_dst_addr, dst);
201*d6b92ffaSHans Petter Selasky 
202*d6b92ffaSHans Petter Selasky 	ib_rai->ai_src_addr = (struct sockaddr *) src;
203*d6b92ffaSHans Petter Selasky 	ib_rai->ai_src_len = sizeof(*src);
204*d6b92ffaSHans Petter Selasky 
205*d6b92ffaSHans Petter Selasky 	ib_rai->ai_dst_addr = (struct sockaddr *) dst;
206*d6b92ffaSHans Petter Selasky 	ib_rai->ai_dst_len = sizeof(*dst);
207*d6b92ffaSHans Petter Selasky 
208*d6b92ffaSHans Petter Selasky 	return 0;
209*d6b92ffaSHans Petter Selasky }
210*d6b92ffaSHans Petter Selasky 
ucma_ib_set_connect(struct rdma_addrinfo * ib_rai,struct rdma_addrinfo * rai)211*d6b92ffaSHans Petter Selasky static int ucma_ib_set_connect(struct rdma_addrinfo *ib_rai,
212*d6b92ffaSHans Petter Selasky 			       struct rdma_addrinfo *rai)
213*d6b92ffaSHans Petter Selasky {
214*d6b92ffaSHans Petter Selasky 	struct ib_connect_hdr *hdr;
215*d6b92ffaSHans Petter Selasky 
216*d6b92ffaSHans Petter Selasky 	if (rai->ai_family == AF_IB)
217*d6b92ffaSHans Petter Selasky 		return 0;
218*d6b92ffaSHans Petter Selasky 
219*d6b92ffaSHans Petter Selasky 	hdr = calloc(1, sizeof(*hdr));
220*d6b92ffaSHans Petter Selasky 	if (!hdr)
221*d6b92ffaSHans Petter Selasky 		return ERR(ENOMEM);
222*d6b92ffaSHans Petter Selasky 
223*d6b92ffaSHans Petter Selasky 	if (rai->ai_family == AF_INET) {
224*d6b92ffaSHans Petter Selasky 		hdr->ip_version = 4 << 4;
225*d6b92ffaSHans Petter Selasky 		memcpy(&hdr->cma_src_ip4,
226*d6b92ffaSHans Petter Selasky 		       &((struct sockaddr_in *) rai->ai_src_addr)->sin_addr, 4);
227*d6b92ffaSHans Petter Selasky 		memcpy(&hdr->cma_dst_ip4,
228*d6b92ffaSHans Petter Selasky 		       &((struct sockaddr_in *) rai->ai_dst_addr)->sin_addr, 4);
229*d6b92ffaSHans Petter Selasky 	} else {
230*d6b92ffaSHans Petter Selasky 		hdr->ip_version = 6 << 4;
231*d6b92ffaSHans Petter Selasky 		memcpy(&hdr->cma_src_ip6,
232*d6b92ffaSHans Petter Selasky 		       &((struct sockaddr_in6 *) rai->ai_src_addr)->sin6_addr, 16);
233*d6b92ffaSHans Petter Selasky 		memcpy(&hdr->cma_dst_ip6,
234*d6b92ffaSHans Petter Selasky 		       &((struct sockaddr_in6 *) rai->ai_dst_addr)->sin6_addr, 16);
235*d6b92ffaSHans Petter Selasky 	}
236*d6b92ffaSHans Petter Selasky 
237*d6b92ffaSHans Petter Selasky 	ib_rai->ai_connect = hdr;
238*d6b92ffaSHans Petter Selasky 	ib_rai->ai_connect_len = sizeof(*hdr);
239*d6b92ffaSHans Petter Selasky 	return 0;
240*d6b92ffaSHans Petter Selasky }
241*d6b92ffaSHans Petter Selasky 
ucma_resolve_af_ib(struct rdma_addrinfo ** rai)242*d6b92ffaSHans Petter Selasky static void ucma_resolve_af_ib(struct rdma_addrinfo **rai)
243*d6b92ffaSHans Petter Selasky {
244*d6b92ffaSHans Petter Selasky 	struct rdma_addrinfo *ib_rai;
245*d6b92ffaSHans Petter Selasky 
246*d6b92ffaSHans Petter Selasky 	ib_rai = calloc(1, sizeof(*ib_rai));
247*d6b92ffaSHans Petter Selasky 	if (!ib_rai)
248*d6b92ffaSHans Petter Selasky 		return;
249*d6b92ffaSHans Petter Selasky 
250*d6b92ffaSHans Petter Selasky 	ib_rai->ai_flags = (*rai)->ai_flags;
251*d6b92ffaSHans Petter Selasky 	ib_rai->ai_family = AF_IB;
252*d6b92ffaSHans Petter Selasky 	ib_rai->ai_qp_type = (*rai)->ai_qp_type;
253*d6b92ffaSHans Petter Selasky 	ib_rai->ai_port_space = (*rai)->ai_port_space;
254*d6b92ffaSHans Petter Selasky 
255*d6b92ffaSHans Petter Selasky 	ib_rai->ai_route = calloc(1, (*rai)->ai_route_len);
256*d6b92ffaSHans Petter Selasky 	if (!ib_rai->ai_route)
257*d6b92ffaSHans Petter Selasky 		goto err;
258*d6b92ffaSHans Petter Selasky 
259*d6b92ffaSHans Petter Selasky 	memcpy(ib_rai->ai_route, (*rai)->ai_route, (*rai)->ai_route_len);
260*d6b92ffaSHans Petter Selasky 	ib_rai->ai_route_len = (*rai)->ai_route_len;
261*d6b92ffaSHans Petter Selasky 
262*d6b92ffaSHans Petter Selasky 	if ((*rai)->ai_src_canonname) {
263*d6b92ffaSHans Petter Selasky 		ib_rai->ai_src_canonname = strdup((*rai)->ai_src_canonname);
264*d6b92ffaSHans Petter Selasky 		if (!ib_rai->ai_src_canonname)
265*d6b92ffaSHans Petter Selasky 			goto err;
266*d6b92ffaSHans Petter Selasky 	}
267*d6b92ffaSHans Petter Selasky 
268*d6b92ffaSHans Petter Selasky 	if ((*rai)->ai_dst_canonname) {
269*d6b92ffaSHans Petter Selasky 		ib_rai->ai_dst_canonname = strdup((*rai)->ai_dst_canonname);
270*d6b92ffaSHans Petter Selasky 		if (!ib_rai->ai_dst_canonname)
271*d6b92ffaSHans Petter Selasky 			goto err;
272*d6b92ffaSHans Petter Selasky 	}
273*d6b92ffaSHans Petter Selasky 
274*d6b92ffaSHans Petter Selasky 	if (ucma_ib_set_connect(ib_rai, *rai))
275*d6b92ffaSHans Petter Selasky 		goto err;
276*d6b92ffaSHans Petter Selasky 
277*d6b92ffaSHans Petter Selasky 	if (ucma_ib_set_addr(ib_rai, *rai))
278*d6b92ffaSHans Petter Selasky 		goto err;
279*d6b92ffaSHans Petter Selasky 
280*d6b92ffaSHans Petter Selasky 	ib_rai->ai_next = *rai;
281*d6b92ffaSHans Petter Selasky 	*rai = ib_rai;
282*d6b92ffaSHans Petter Selasky 	return;
283*d6b92ffaSHans Petter Selasky 
284*d6b92ffaSHans Petter Selasky err:
285*d6b92ffaSHans Petter Selasky 	rdma_freeaddrinfo(ib_rai);
286*d6b92ffaSHans Petter Selasky }
287*d6b92ffaSHans Petter Selasky 
ucma_ib_save_resp(struct rdma_addrinfo * rai,struct acm_msg * msg)288*d6b92ffaSHans Petter Selasky static void ucma_ib_save_resp(struct rdma_addrinfo *rai, struct acm_msg *msg)
289*d6b92ffaSHans Petter Selasky {
290*d6b92ffaSHans Petter Selasky 	struct acm_ep_addr_data *ep_data;
291*d6b92ffaSHans Petter Selasky 	struct ibv_path_data *path_data = NULL;
292*d6b92ffaSHans Petter Selasky 	struct sockaddr_in *sin;
293*d6b92ffaSHans Petter Selasky 	struct sockaddr_in6 *sin6;
294*d6b92ffaSHans Petter Selasky 	int i, cnt, path_cnt = 0;
295*d6b92ffaSHans Petter Selasky 
296*d6b92ffaSHans Petter Selasky 	cnt = (msg->hdr.length - ACM_MSG_HDR_LENGTH) / ACM_MSG_EP_LENGTH;
297*d6b92ffaSHans Petter Selasky 	for (i = 0; i < cnt; i++) {
298*d6b92ffaSHans Petter Selasky 		ep_data = &msg->resolve_data[i];
299*d6b92ffaSHans Petter Selasky 		switch (ep_data->type) {
300*d6b92ffaSHans Petter Selasky 		case ACM_EP_INFO_PATH:
301*d6b92ffaSHans Petter Selasky 			ep_data->type = 0;
302*d6b92ffaSHans Petter Selasky 			if (!path_data)
303*d6b92ffaSHans Petter Selasky 				path_data = (struct ibv_path_data *) ep_data;
304*d6b92ffaSHans Petter Selasky 			path_cnt++;
305*d6b92ffaSHans Petter Selasky 			break;
306*d6b92ffaSHans Petter Selasky 		case ACM_EP_INFO_ADDRESS_IP:
307*d6b92ffaSHans Petter Selasky 			if (!(ep_data->flags & ACM_EP_FLAG_SOURCE) || rai->ai_src_len)
308*d6b92ffaSHans Petter Selasky 				break;
309*d6b92ffaSHans Petter Selasky 
310*d6b92ffaSHans Petter Selasky 			sin = calloc(1, sizeof(*sin));
311*d6b92ffaSHans Petter Selasky 			if (!sin)
312*d6b92ffaSHans Petter Selasky 				break;
313*d6b92ffaSHans Petter Selasky 
314*d6b92ffaSHans Petter Selasky 			sin->sin_family = AF_INET;
315*d6b92ffaSHans Petter Selasky 			memcpy(&sin->sin_addr, &ep_data->info.addr, 4);
316*d6b92ffaSHans Petter Selasky 			rai->ai_src_len = sizeof(*sin);
317*d6b92ffaSHans Petter Selasky 			rai->ai_src_addr = (struct sockaddr *) sin;
318*d6b92ffaSHans Petter Selasky 			break;
319*d6b92ffaSHans Petter Selasky 		case ACM_EP_INFO_ADDRESS_IP6:
320*d6b92ffaSHans Petter Selasky 			if (!(ep_data->flags & ACM_EP_FLAG_SOURCE) || rai->ai_src_len)
321*d6b92ffaSHans Petter Selasky 				break;
322*d6b92ffaSHans Petter Selasky 
323*d6b92ffaSHans Petter Selasky 			sin6 = calloc(1, sizeof(*sin6));
324*d6b92ffaSHans Petter Selasky 			if (!sin6)
325*d6b92ffaSHans Petter Selasky 				break;
326*d6b92ffaSHans Petter Selasky 
327*d6b92ffaSHans Petter Selasky 			sin6->sin6_family = AF_INET6;
328*d6b92ffaSHans Petter Selasky 			memcpy(&sin6->sin6_addr, &ep_data->info.addr, 16);
329*d6b92ffaSHans Petter Selasky 			rai->ai_src_len = sizeof(*sin6);
330*d6b92ffaSHans Petter Selasky 			rai->ai_src_addr = (struct sockaddr *) sin6;
331*d6b92ffaSHans Petter Selasky 			break;
332*d6b92ffaSHans Petter Selasky 		default:
333*d6b92ffaSHans Petter Selasky 			break;
334*d6b92ffaSHans Petter Selasky 		}
335*d6b92ffaSHans Petter Selasky 	}
336*d6b92ffaSHans Petter Selasky 
337*d6b92ffaSHans Petter Selasky 	rai->ai_route = calloc(path_cnt, sizeof(*path_data));
338*d6b92ffaSHans Petter Selasky 	if (rai->ai_route) {
339*d6b92ffaSHans Petter Selasky 		memcpy(rai->ai_route, path_data, path_cnt * sizeof(*path_data));
340*d6b92ffaSHans Petter Selasky 		rai->ai_route_len = path_cnt * sizeof(*path_data);
341*d6b92ffaSHans Petter Selasky 	}
342*d6b92ffaSHans Petter Selasky }
343*d6b92ffaSHans Petter Selasky 
ucma_set_ep_addr(struct acm_ep_addr_data * data,struct sockaddr * addr)344*d6b92ffaSHans Petter Selasky static void ucma_set_ep_addr(struct acm_ep_addr_data *data, struct sockaddr *addr)
345*d6b92ffaSHans Petter Selasky {
346*d6b92ffaSHans Petter Selasky 	if (addr->sa_family == AF_INET) {
347*d6b92ffaSHans Petter Selasky 		data->type = ACM_EP_INFO_ADDRESS_IP;
348*d6b92ffaSHans Petter Selasky 		memcpy(data->info.addr, &((struct sockaddr_in *) addr)->sin_addr, 4);
349*d6b92ffaSHans Petter Selasky 	} else {
350*d6b92ffaSHans Petter Selasky 		data->type = ACM_EP_INFO_ADDRESS_IP6;
351*d6b92ffaSHans Petter Selasky 		memcpy(data->info.addr, &((struct sockaddr_in6 *) addr)->sin6_addr, 16);
352*d6b92ffaSHans Petter Selasky 	}
353*d6b92ffaSHans Petter Selasky }
354*d6b92ffaSHans Petter Selasky 
ucma_inet_addr(struct sockaddr * addr,socklen_t len)355*d6b92ffaSHans Petter Selasky static int ucma_inet_addr(struct sockaddr *addr, socklen_t len)
356*d6b92ffaSHans Petter Selasky {
357*d6b92ffaSHans Petter Selasky 	return len && addr && (addr->sa_family == AF_INET ||
358*d6b92ffaSHans Petter Selasky 			       addr->sa_family == AF_INET6);
359*d6b92ffaSHans Petter Selasky }
360*d6b92ffaSHans Petter Selasky 
ucma_ib_addr(struct sockaddr * addr,socklen_t len)361*d6b92ffaSHans Petter Selasky static int ucma_ib_addr(struct sockaddr *addr, socklen_t len)
362*d6b92ffaSHans Petter Selasky {
363*d6b92ffaSHans Petter Selasky 	return len && addr && (addr->sa_family == AF_IB);
364*d6b92ffaSHans Petter Selasky }
365*d6b92ffaSHans Petter Selasky 
ucma_ib_resolve(struct rdma_addrinfo ** rai,const struct rdma_addrinfo * hints)366*d6b92ffaSHans Petter Selasky void ucma_ib_resolve(struct rdma_addrinfo **rai,
367*d6b92ffaSHans Petter Selasky 		     const struct rdma_addrinfo *hints)
368*d6b92ffaSHans Petter Selasky {
369*d6b92ffaSHans Petter Selasky 	struct acm_msg msg;
370*d6b92ffaSHans Petter Selasky 	struct acm_ep_addr_data *data;
371*d6b92ffaSHans Petter Selasky 	int ret;
372*d6b92ffaSHans Petter Selasky 
373*d6b92ffaSHans Petter Selasky 	ucma_ib_init();
374*d6b92ffaSHans Petter Selasky 	if (sock < 0)
375*d6b92ffaSHans Petter Selasky 		return;
376*d6b92ffaSHans Petter Selasky 
377*d6b92ffaSHans Petter Selasky 	memset(&msg, 0, sizeof msg);
378*d6b92ffaSHans Petter Selasky 	msg.hdr.version = ACM_VERSION;
379*d6b92ffaSHans Petter Selasky 	msg.hdr.opcode = ACM_OP_RESOLVE;
380*d6b92ffaSHans Petter Selasky 	msg.hdr.length = ACM_MSG_HDR_LENGTH;
381*d6b92ffaSHans Petter Selasky 
382*d6b92ffaSHans Petter Selasky 	data = &msg.resolve_data[0];
383*d6b92ffaSHans Petter Selasky 	if (ucma_inet_addr((*rai)->ai_src_addr, (*rai)->ai_src_len)) {
384*d6b92ffaSHans Petter Selasky 		data->flags = ACM_EP_FLAG_SOURCE;
385*d6b92ffaSHans Petter Selasky 		ucma_set_ep_addr(data, (*rai)->ai_src_addr);
386*d6b92ffaSHans Petter Selasky 		data++;
387*d6b92ffaSHans Petter Selasky 		msg.hdr.length += ACM_MSG_EP_LENGTH;
388*d6b92ffaSHans Petter Selasky 	}
389*d6b92ffaSHans Petter Selasky 
390*d6b92ffaSHans Petter Selasky 	if (ucma_inet_addr((*rai)->ai_dst_addr, (*rai)->ai_dst_len)) {
391*d6b92ffaSHans Petter Selasky 		data->flags = ACM_EP_FLAG_DEST;
392*d6b92ffaSHans Petter Selasky 		if (hints->ai_flags & (RAI_NUMERICHOST | RAI_NOROUTE))
393*d6b92ffaSHans Petter Selasky 			data->flags |= ACM_FLAGS_NODELAY;
394*d6b92ffaSHans Petter Selasky 		ucma_set_ep_addr(data, (*rai)->ai_dst_addr);
395*d6b92ffaSHans Petter Selasky 		data++;
396*d6b92ffaSHans Petter Selasky 		msg.hdr.length += ACM_MSG_EP_LENGTH;
397*d6b92ffaSHans Petter Selasky 	}
398*d6b92ffaSHans Petter Selasky 
399*d6b92ffaSHans Petter Selasky 	if (hints->ai_route_len ||
400*d6b92ffaSHans Petter Selasky 	    ucma_ib_addr((*rai)->ai_src_addr, (*rai)->ai_src_len) ||
401*d6b92ffaSHans Petter Selasky 	    ucma_ib_addr((*rai)->ai_dst_addr, (*rai)->ai_dst_len)) {
402*d6b92ffaSHans Petter Selasky 		struct ibv_path_record *path;
403*d6b92ffaSHans Petter Selasky 
404*d6b92ffaSHans Petter Selasky 		if (hints->ai_route_len == sizeof(struct ibv_path_record))
405*d6b92ffaSHans Petter Selasky 			path = (struct ibv_path_record *) hints->ai_route;
406*d6b92ffaSHans Petter Selasky 		else if (hints->ai_route_len == sizeof(struct ibv_path_data))
407*d6b92ffaSHans Petter Selasky 			path = &((struct ibv_path_data *) hints->ai_route)->path;
408*d6b92ffaSHans Petter Selasky 		else
409*d6b92ffaSHans Petter Selasky 			path = NULL;
410*d6b92ffaSHans Petter Selasky 
411*d6b92ffaSHans Petter Selasky 		if (path)
412*d6b92ffaSHans Petter Selasky 			memcpy(&data->info.path, path, sizeof(*path));
413*d6b92ffaSHans Petter Selasky 
414*d6b92ffaSHans Petter Selasky 		if (ucma_ib_addr((*rai)->ai_src_addr, (*rai)->ai_src_len)) {
415*d6b92ffaSHans Petter Selasky 			memcpy(&data->info.path.sgid,
416*d6b92ffaSHans Petter Selasky 			       &((struct sockaddr_ib *) (*rai)->ai_src_addr)->sib_addr, 16);
417*d6b92ffaSHans Petter Selasky 		}
418*d6b92ffaSHans Petter Selasky 		if (ucma_ib_addr((*rai)->ai_dst_addr, (*rai)->ai_dst_len)) {
419*d6b92ffaSHans Petter Selasky 			memcpy(&data->info.path.dgid,
420*d6b92ffaSHans Petter Selasky 			       &((struct sockaddr_ib *) (*rai)->ai_dst_addr)->sib_addr, 16);
421*d6b92ffaSHans Petter Selasky 		}
422*d6b92ffaSHans Petter Selasky 		data->type = ACM_EP_INFO_PATH;
423*d6b92ffaSHans Petter Selasky 		data++;
424*d6b92ffaSHans Petter Selasky 		msg.hdr.length += ACM_MSG_EP_LENGTH;
425*d6b92ffaSHans Petter Selasky 	}
426*d6b92ffaSHans Petter Selasky 
427*d6b92ffaSHans Petter Selasky 	pthread_mutex_lock(&acm_lock);
428*d6b92ffaSHans Petter Selasky 	ret = send(sock, (char *) &msg, msg.hdr.length, 0);
429*d6b92ffaSHans Petter Selasky 	if (ret != msg.hdr.length) {
430*d6b92ffaSHans Petter Selasky 		pthread_mutex_unlock(&acm_lock);
431*d6b92ffaSHans Petter Selasky 		return;
432*d6b92ffaSHans Petter Selasky 	}
433*d6b92ffaSHans Petter Selasky 
434*d6b92ffaSHans Petter Selasky 	ret = recv(sock, (char *) &msg, sizeof msg, 0);
435*d6b92ffaSHans Petter Selasky 	pthread_mutex_unlock(&acm_lock);
436*d6b92ffaSHans Petter Selasky 	if (ret < ACM_MSG_HDR_LENGTH || ret != msg.hdr.length || msg.hdr.status)
437*d6b92ffaSHans Petter Selasky 		return;
438*d6b92ffaSHans Petter Selasky 
439*d6b92ffaSHans Petter Selasky 	ucma_ib_save_resp(*rai, &msg);
440*d6b92ffaSHans Petter Selasky 
441*d6b92ffaSHans Petter Selasky 	if (af_ib_support && !(hints->ai_flags & RAI_ROUTEONLY) && (*rai)->ai_route_len)
442*d6b92ffaSHans Petter Selasky 		ucma_resolve_af_ib(rai);
443*d6b92ffaSHans Petter Selasky }
444