1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <strings.h>
28 
29 #include <dapl.h>
30 #include <dapl_adapter_util.h>
31 #include <dapl_evd_util.h>
32 #include <dapl_cr_util.h>
33 #include <dapl_lmr_util.h>
34 #include <dapl_rmr_util.h>
35 #include <dapl_cookie.h>
36 #include <dapl_name_service.h>
37 #include <dapl_tavor_ibtf_impl.h>
38 
39 /* Function prototypes */
40 extern DAT_RETURN dapls_tavor_wrid_init(ib_qp_handle_t);
41 extern void dapls_tavor_wrid_cleanup(DAPL_EP *, ib_qp_handle_t);
42 
43 int g_dapl_loopback_connection = 0;
44 
45 /*
46  * dapls_ib_connect
47  *
48  * Initiate a connection with the passive listener on another node
49  *
50  * Input:
51  *        ep_handle,
52  *        remote_ia_address,
53  *        remote_conn_qual,
54  *	  prd_size		size of private data and structure
55  *	  prd_prt		pointer to private data structure
56  *
57  * Output:
58  *        none
59  *
60  * Returns:
61  *        DAT_SUCCESS
62  *        DAT_INSUFFICIENT_RESOURCES
63  *        DAT_INVALID_PARAMETER
64  *
65  */
66 
67 DAT_RETURN
dapls_ib_connect(IN DAT_EP_HANDLE ep_handle,IN DAT_IA_ADDRESS_PTR remote_ia_address,IN DAT_CONN_QUAL remote_conn_qual,IN DAT_COUNT prd_size,IN DAPL_PRIVATE * prd_ptr,IN DAT_TIMEOUT timeout)68 dapls_ib_connect(IN DAT_EP_HANDLE ep_handle,
69     IN DAT_IA_ADDRESS_PTR remote_ia_address, IN DAT_CONN_QUAL remote_conn_qual,
70     IN DAT_COUNT prd_size, IN DAPL_PRIVATE *prd_ptr, IN DAT_TIMEOUT timeout)
71 {
72 	dapl_ep_connect_t args;
73 	DAPL_EP *ep_p = (DAPL_EP *)ep_handle;
74 	struct sockaddr *s;
75 	char addr_buf[64];
76 	ib_gid_t dgid;
77 	int retval;
78 	struct sockaddr_in6 *v6addr;
79 	struct sockaddr_in *v4addr;
80 	dapl_ia_addr_t *sap;
81 
82 	s = (struct sockaddr *)remote_ia_address;
83 	dapl_dbg_log(DAPL_DBG_TYPE_CM,
84 	    "dapls_ib_connect: ep 0x%p\n"
85 	    "                  addr %s, conn_qual %016llu, ep_hkey %016llx\n"
86 	    "                  prd_size %d, timeout 0x%x\n",
87 	    ep_p, dapls_inet_ntop(s, addr_buf, 64), remote_conn_qual,
88 	    ep_p->qp_handle->ep_hkey, prd_size, timeout);
89 	if (ep_p->qp_handle == NULL) {
90 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
91 		    "dapls_ib_connect: ep 0x%p, addr %s, conn_qual %016llu, "
92 		    "qp_handle == NULL\n", ep_p, dapls_inet_ntop(s,
93 		    addr_buf, 64), remote_conn_qual);
94 		return (DAT_INVALID_PARAMETER);
95 	}
96 	if (timeout == DAT_TIMEOUT_INFINITE) {
97 		args.epc_timeout = 0;
98 	} else {
99 		args.epc_timeout = timeout;
100 	}
101 	/* resolve remote address to dgid */
102 	retval = dapls_ns_lookup_address(ep_p->header.owner_ia,
103 	    remote_ia_address, timeout, &dgid);
104 	if (retval == DAT_SUCCESS) {
105 		args.epc_dgid = dgid;
106 	} else if ((retval & DAT_SUBTYPE_MASK) ==
107 	    DAT_INVALID_ADDRESS_UNREACHABLE) {
108 		/* let the kernel driver look up the dgid from ATS */
109 		args.epc_dgid.gid_guid = 0ULL;
110 		args.epc_dgid.gid_prefix = 0ULL;
111 	} else {
112 		return (retval);
113 	}
114 	args.epc_sid = remote_conn_qual;
115 	args.epc_hkey = ep_p->qp_handle->ep_hkey;
116 	sap = (dapl_ia_addr_t *)&args.epc_raddr_sadata;
117 	/*
118 	 * filled in the remote_ia_address for consistent though
119 	 * not necessary when dapls_ns_lookup_address has resolved the dgid
120 	 */
121 	switch (s->sa_family) {
122 	case AF_INET:
123 		/* LINTED: E_BAD_PTR_CAST_ALIGN */
124 		v4addr = (struct sockaddr_in *)s;
125 		sap->iad_v4pad[0] = 0;
126 		sap->iad_v4pad[1] = 0;
127 		sap->iad_v4pad[2] = 0;
128 		sap->iad_v4 = v4addr->sin_addr;
129 		break;
130 	case AF_INET6:
131 		/* LINTED: E_BAD_PTR_CAST_ALIGN */
132 		v6addr = (struct sockaddr_in6 *)s;
133 		sap->iad_v6 = v6addr->sin6_addr;
134 		break;
135 	}
136 
137 	/* establish the hello message */
138 	(void) dapl_os_memzero((void *)&prd_ptr->hello_msg,
139 	    sizeof (DAPL_HELLO_MSG));
140 	/* on ATS leave the msg blank to avoid confusion to 3rd parties */
141 	if ((args.epc_dgid.gid_guid | args.epc_dgid.gid_prefix)) {
142 		prd_ptr->hello_msg.hi_checksum = DAPL_CHECKSUM;
143 		prd_ptr->hello_msg.hi_clen = prd_size;
144 		prd_ptr->hello_msg.hi_mid = 0;
145 		prd_ptr->hello_msg.hi_vers = DAPL_HELLO_MSG_VERS;
146 
147 		/* fill in local address */
148 		s = (struct sockaddr *)
149 		    &ep_p->header.owner_ia->hca_ptr->hca_address;
150 		prd_ptr->hello_msg.hi_ipv = (uint8_t)s->sa_family;
151 		switch (s->sa_family) {
152 		case AF_INET:
153 			/* LINTED: E_BAD_PTR_CAST_ALIGN */
154 			v4addr = (struct sockaddr_in *)s;
155 			prd_ptr->hello_msg.hi_port = v4addr->sin_port;
156 			prd_ptr->hello_msg.hi_v4ipaddr = v4addr->sin_addr;
157 			break;
158 		case AF_INET6:
159 			/* LINTED: E_BAD_PTR_CAST_ALIGN */
160 			v6addr = (struct sockaddr_in6 *)s;
161 			prd_ptr->hello_msg.hi_port = v6addr->sin6_port;
162 			prd_ptr->hello_msg.hi_v6ipaddr = v6addr->sin6_addr;
163 			break;
164 		default:
165 			break; /* fall through */
166 		}
167 	}
168 	if (prd_size > 0) {
169 		(void) dapl_os_memcpy((void *)&args.epc_priv[0],
170 		    (void *)prd_ptr, sizeof (DAPL_PRIVATE));
171 	} else {
172 		(void) dapl_os_memcpy((void *)
173 		    &args.epc_priv[DAPL_CONSUMER_MAX_PRIVATE_DATA_SIZE],
174 		    (void *)&prd_ptr->hello_msg, sizeof (DAPL_HELLO_MSG));
175 	}
176 	args.epc_priv_sz = sizeof (DAPL_PRIVATE);
177 
178 	retval = ioctl(ep_p->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
179 	    DAPL_EP_CONNECT, &args);
180 	if (retval != 0) {
181 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
182 		    "dapls_ib_connect: connect failed %s, retval %d\n\n",
183 		    strerror(errno), retval);
184 		return (dapls_convert_error(errno, retval));
185 	}
186 
187 	dapl_dbg_log(DAPL_DBG_TYPE_CM,
188 	    "dapls_ib_connect: connected to %s\n\n",
189 	    dapls_inet_ntop(s, addr_buf, 64));
190 	return (DAT_SUCCESS);
191 }
192 
193 /*
194  * dapls_ib_disconnect
195  *
196  * Disconnect an EP
197  *
198  * Input:
199  *        ep_handle,
200  *        disconnect_flags
201  *
202  * Output:
203  *        none
204  *
205  * Returns:
206  *        DAT_SUCCESS
207  *        DAT_INSUFFICIENT_RESOURCES
208  *        DAT_INVALID_PARAMETER
209  *
210  */
211 /* ARGSUSED */
212 DAT_RETURN
dapls_ib_disconnect(IN DAPL_EP * ep_ptr,IN DAT_CLOSE_FLAGS close_flags)213 dapls_ib_disconnect(IN DAPL_EP *ep_ptr,
214     IN DAT_CLOSE_FLAGS close_flags)
215 {
216 	dapl_ep_disconnect_t args;
217 	struct sockaddr *s;
218 	char addr_buf[64];
219 	int retval;
220 
221 	if (ep_ptr->qp_handle == NULL) {
222 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
223 		    "dapls_ib_disconnect: qp_handle == NULL\n");
224 		return (DAT_INVALID_PARAMETER);
225 	}
226 	args.epd_hkey = ep_ptr->qp_handle->ep_hkey;
227 
228 	retval = ioctl(ep_ptr->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
229 	    DAPL_EP_DISCONNECT, &args);
230 	/* no reason for disconnect to fail so transition the state */
231 	ep_ptr->qp_state = IBT_STATE_ERROR;
232 
233 	if (retval != 0) {
234 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
235 		    "dapls_ib_disconnect: disconnect failed %s\n",
236 		    strerror(errno));
237 		return (dapls_convert_error(errno, retval));
238 	}
239 	s = (struct sockaddr *)ep_ptr->param.remote_ia_address_ptr;
240 	dapl_dbg_log(DAPL_DBG_TYPE_CM,
241 	    "dapls_ib_disconnect: disconnected from %s, conn_qual %016llu\n",
242 	    dapls_inet_ntop(s, addr_buf, 64), ep_ptr->param.remote_port_qual);
243 	return (DAT_SUCCESS);
244 }
245 
246 
247 /*
248  * dapls_ib_connected
249  *
250  * transition qp_state to IBT_STATE_RTS
251  *
252  */
253 void
dapls_ib_connected(IN DAPL_EP * ep_ptr)254 dapls_ib_connected(IN DAPL_EP *ep_ptr)
255 {
256 	ep_ptr->qp_state = IBT_STATE_RTS;
257 }
258 
259 
260 /*
261  * dapls_ib_disconnect_clean
262  *
263  * transition qp_state to IBT_STATE_ERROR.
264  * abort connection if necessary.
265  *
266  * Input:
267  *	ep_ptr		DAPL_EP
268  *
269  * Output:
270  * 	none
271  *
272  * Returns:
273  * 	void
274  *
275  */
276 /* ARGSUSED */
277 void
dapls_ib_disconnect_clean(IN DAPL_EP * ep_ptr,IN DAT_BOOLEAN active,IN const ib_cm_events_t ib_cm_event)278 dapls_ib_disconnect_clean(IN DAPL_EP *ep_ptr, IN DAT_BOOLEAN active,
279     IN const ib_cm_events_t ib_cm_event)
280 {
281 	switch (ib_cm_event) {
282 	case IB_CME_CONNECTED:
283 	case IB_CME_CONNECTION_REQUEST_PENDING:
284 	case IB_CME_CONNECTION_REQUEST_PENDING_PRIVATE_DATA:
285 		(void) dapls_ib_disconnect(ep_ptr, DAT_CLOSE_ABRUPT_FLAG);
286 		/* FALLTHROUGH */
287 	case IB_CME_DESTINATION_REJECT:
288 	case IB_CME_DESTINATION_REJECT_PRIVATE_DATA:
289 	case IB_CME_DESTINATION_UNREACHABLE:
290 	case IB_CME_TOO_MANY_CONNECTION_REQUESTS:
291 	case IB_CME_LOCAL_FAILURE:
292 	case IB_CME_TIMED_OUT:
293 	case IB_CME_DISCONNECTED_ON_LINK_DOWN:
294 		ep_ptr->qp_state = IBT_STATE_ERROR;
295 	}
296 }
297 
298 
299 /*
300  * dapls_ib_reinit_ep
301  *
302  * Move the QP to INIT state again.
303  *
304  * Input:
305  *	ep_ptr		DAPL_EP
306  *
307  * Output:
308  * 	none
309  *
310  * Returns:
311  * 	void
312  *
313  */
314 void
dapls_ib_reinit_ep(IN DAPL_EP * ep_ptr)315 dapls_ib_reinit_ep(IN DAPL_EP *ep_ptr)
316 {
317 	dapl_ep_reinit_t	reinit_args;
318 	ib_hca_handle_t		hca_hndl;
319 	ib_qp_handle_t		qp_p;
320 	char			addr_buf[64];
321 	int			retval;
322 
323 	hca_hndl = ep_ptr->header.owner_ia->hca_ptr->ib_hca_handle;
324 	qp_p = ep_ptr->qp_handle;
325 
326 	if (qp_p == NULL) {
327 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
328 		    "dapls_ib_reinit: qp_handle == NULL\n");
329 		return;
330 	}
331 	/*
332 	 * Do all the work request cleanup processing right away
333 	 * no one should really be doing any operation on this
334 	 * qp (we are not threadsafe)...
335 	 */
336 	dapls_tavor_wrid_cleanup(ep_ptr, qp_p);
337 
338 	reinit_args.epri_hkey = qp_p->ep_hkey;
339 	if (ioctl(hca_hndl->ia_fd, DAPL_EP_REINIT, &reinit_args) != 0) {
340 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
341 		    "dapls_ib_reinit: reinit failed %s\n",
342 		    strerror(errno));
343 		return;
344 	}
345 
346 	qp_p->qp_sq_lastwqeaddr = NULL;
347 	qp_p->qp_rq_lastwqeaddr = NULL;
348 
349 	/*
350 	 * Setup data structure for work request processing
351 	 */
352 	retval = dapls_tavor_wrid_init(qp_p);
353 	if (retval != DAT_SUCCESS) {
354 		/*
355 		 * we failed to create data structures for work request
356 		 * processing. Lets unmap and leave, the qp will get
357 		 * cleaned when ep gets destroyed - the ep is unusable
358 		 * in this state.
359 		 */
360 		if (munmap((void *)qp_p->qp_addr, qp_p->qp_map_len) < 0) {
361 			dapl_dbg_log(DAPL_DBG_TYPE_ERR,
362 			    "qp_free: munmap failed(%d)\n", errno);
363 		}
364 		qp_p->qp_addr = NULL;
365 		dapl_dbg_log(DAPL_DBG_TYPE_CM,
366 		    "dapls_ib_reinit: wrid_init failed %d\n", retval);
367 		return;
368 	}
369 
370 	/* we have a new ep and it is in the init state */
371 	ep_ptr->qp_state = IBT_STATE_INIT;
372 
373 	dapl_dbg_log(DAPL_DBG_TYPE_CM,
374 	    "dapls_ib_reinit: successful, ia_address %s, conn_qual %016llu\n",
375 	    dapls_inet_ntop((struct sockaddr *)ep_ptr->param.
376 	    remote_ia_address_ptr, addr_buf, 64),
377 	    ep_ptr->param.remote_port_qual);
378 }
379 
380 
381 /*
382  * dapl_ib_setup_conn_listener
383  *
384  * Have the CM set up a connection listener.
385  *
386  * Input:
387  *        ibm_hca_handle           HCA handle
388  *        qp_handle                QP handle
389  *
390  * Output:
391  *        none
392  *
393  * Returns:
394  *        DAT_SUCCESS
395  *        DAT_INSUFFICIENT_RESOURCES
396  *        DAT_INVALID_PARAMETER
397  *
398  */
399 DAT_RETURN
dapls_ib_setup_conn_listener(IN DAPL_IA * ia_ptr,IN DAT_UINT64 ServiceID,IN DAPL_SP * sp_ptr)400 dapls_ib_setup_conn_listener(IN DAPL_IA *ia_ptr,
401     IN DAT_UINT64 ServiceID, IN DAPL_SP *sp_ptr)
402 {
403 	ib_hca_handle_t hca_hdl = ia_ptr->hca_ptr->ib_hca_handle;
404 	struct dapls_ib_cm_srvc_handle *srvc_hdl;
405 	dapl_service_register_t args;
406 	struct sockaddr *s;
407 	char addr_buf[64];
408 	DAPL_EVD *evd_p = (DAPL_EVD *)sp_ptr->evd_handle;
409 	int retval;
410 
411 	if (hca_hdl == NULL) {
412 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
413 		    "setup_conn_listener: hca_handle == NULL\n");
414 		return (DAT_INVALID_PARAMETER);
415 	}
416 	if (evd_p == NULL) {
417 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
418 		    "setup_conn_listener: evd_p == NULL\n");
419 		return (DAT_INVALID_PARAMETER);
420 	}
421 	srvc_hdl = (struct dapls_ib_cm_srvc_handle *)
422 	    dapl_os_alloc(sizeof (*srvc_hdl));
423 	if (srvc_hdl == NULL) {
424 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
425 		    "setup_conn_listener: srvc_handle == NULL\n");
426 		return (DAT_INSUFFICIENT_RESOURCES);
427 	}
428 
429 	args.sr_sid = ServiceID;
430 	args.sr_evd_hkey = evd_p->ib_cq_handle->evd_hkey;
431 	args.sr_sp_cookie = (uintptr_t)sp_ptr;
432 
433 	retval = ioctl(hca_hdl->ia_fd, DAPL_SERVICE_REGISTER, &args);
434 	if (retval != 0) {
435 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
436 		    "setup_conn_listener: register failed %s\n",
437 		    strerror(errno));
438 		dapl_os_free(srvc_hdl, sizeof (*srvc_hdl));
439 		return (dapls_convert_error(errno, retval));
440 	}
441 	srvc_hdl->sv_sp_hkey = args.sr_sp_hkey;
442 	sp_ptr->cm_srvc_handle = srvc_hdl;
443 	sp_ptr->conn_qual = args.sr_retsid;
444 
445 	s = (struct sockaddr *)&ia_ptr->hca_ptr->hca_address;
446 	dapl_dbg_log(DAPL_DBG_TYPE_CM,
447 	    "setup_conn_listener: listening on ia_address %s, "
448 	    "conn_qual %016llu\n\n", dapls_inet_ntop(s, addr_buf, 64),
449 	    sp_ptr->conn_qual);
450 	return (DAT_SUCCESS);
451 }
452 
453 /*
454  * dapl_ib_remove_conn_listener
455  *
456  * Have the CM remove a connection listener.
457  *
458  * Input:
459  *      ia_handle               IA handle
460  *      ServiceID               IB Channel Service ID
461  *
462  * Output:
463  *      none
464  *
465  * Returns:
466  *      DAT_SUCCESS
467  *      DAT_INVALID_PARAMETER
468  *
469  */
470 DAT_RETURN
dapls_ib_remove_conn_listener(IN DAPL_IA * ia_ptr,IN DAPL_SP * sp_ptr)471 dapls_ib_remove_conn_listener(IN DAPL_IA *ia_ptr, IN DAPL_SP *sp_ptr)
472 {
473 	ib_hca_handle_t hca_hdl = ia_ptr->hca_ptr->ib_hca_handle;
474 	struct dapls_ib_cm_srvc_handle *srvc_hdl;
475 	dapl_service_deregister_t args;
476 	struct sockaddr *s;
477 	char addr_buf[64];
478 	int retval;
479 
480 	if (hca_hdl == NULL) {
481 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
482 		    "remove_conn_listener: hca_handle == NULL\n");
483 		return (DAT_INVALID_PARAMETER);
484 	}
485 	srvc_hdl = (struct dapls_ib_cm_srvc_handle *)sp_ptr->
486 	    cm_srvc_handle;
487 
488 	args.sdr_sp_hkey = srvc_hdl->sv_sp_hkey;
489 	retval = ioctl(hca_hdl->ia_fd, DAPL_SERVICE_DEREGISTER, &args);
490 	if (retval != 0) {
491 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
492 		    "remove_conn_listener: deregister failed %s\n",
493 		    strerror(errno));
494 		return (dapls_convert_error(errno, retval));
495 	}
496 	dapl_os_free(srvc_hdl, sizeof (*srvc_hdl));
497 	sp_ptr->cm_srvc_handle = NULL;
498 
499 	s = (struct sockaddr *)&ia_ptr->hca_ptr->hca_address;
500 	dapl_dbg_log(DAPL_DBG_TYPE_CM,
501 	    "remove_conn_listener: successful, ia_address %s, "
502 	    "conn_qual %016llu\n\n", dapls_inet_ntop(s, addr_buf, 64),
503 	    sp_ptr->conn_qual);
504 	return (DAT_SUCCESS);
505 }
506 
507 /*
508  * dapls_ib_reject_connection
509  *
510  * Perform necessary steps to reject a connection
511  *
512  * Input:
513  *        cr_handle
514  *
515  * Output:
516  *        none
517  *
518  * Returns:
519  *        DAT_SUCCESS
520  *        DAT_INSUFFICIENT_RESOURCES
521  *        DAT_INVALID_PARAMETER
522  *
523  */
524 DAT_RETURN
dapls_ib_reject_connection(IN ib_cm_handle_t cm_handle,IN int reject_reason,IN DAPL_SP * sp_ptr)525 dapls_ib_reject_connection(IN ib_cm_handle_t cm_handle,
526     IN int reject_reason, IN DAPL_SP *sp_ptr)
527 {
528 	dapl_cr_reject_t args;
529 	int retval;
530 
531 	args.crr_reason = reject_reason;
532 	args.crr_bkl_cookie = (uint64_t)cm_handle;
533 	args.crr_sp_hkey = sp_ptr->cm_srvc_handle->sv_sp_hkey;
534 
535 	dapl_dbg_log(DAPL_DBG_TYPE_CM,
536 	    "dapls_ib_reject: fd %d, sp_hkey %016llx, bkl_index 0x%llx\n",
537 	    sp_ptr->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
538 	    args.crr_sp_hkey, args.crr_bkl_cookie);
539 
540 	retval = ioctl(sp_ptr->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
541 	    DAPL_CR_REJECT, &args);
542 	if (retval != 0) {
543 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
544 		    "dapls_ib_reject: reject failed %s\n",
545 		    strerror(errno));
546 		return (dapls_convert_error(errno, retval));
547 	}
548 	return (DAT_SUCCESS);
549 }
550 
551 
552 /*
553  * dapls_ib_accept_connection
554  *
555  * Perform necessary steps to accept a connection
556  *
557  * Input:
558  *        cr_handle
559  *        ep_handle
560  *        private_data_size
561  *        private_data
562  *
563  * Output:
564  *        none
565  *
566  * Returns:
567  *        DAT_SUCCESS
568  *        DAT_INSUFFICIENT_RESOURCES
569  *        DAT_INVALID_PARAMETER
570  *
571  */
572 DAT_RETURN
dapls_ib_accept_connection(IN DAT_CR_HANDLE cr_handle,IN DAT_EP_HANDLE ep_handle,IN DAPL_PRIVATE * prd_ptr)573 dapls_ib_accept_connection(IN DAT_CR_HANDLE cr_handle,
574     IN DAT_EP_HANDLE ep_handle, IN DAPL_PRIVATE *prd_ptr)
575 {
576 	DAPL_EP		*ep_p = (DAPL_EP *)ep_handle;
577 	DAPL_CR		*cr_p = (DAPL_CR *)cr_handle;
578 	dapl_cr_accept_t	args;
579 	int			retval;
580 
581 	/* check if ep is valid */
582 	if (ep_p->qp_handle == NULL) {
583 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
584 		    "dapls_ib_accept: qp_handle == NULL\n");
585 		return (DAT_INVALID_PARAMETER);
586 	}
587 
588 	dapl_dbg_log(DAPL_DBG_TYPE_CM,
589 	    "dapls_ib_accept: fd %d, sp_hkey %016llx, "
590 	    "bkl_index 0x%llx, ep_hkey %016llx\n",
591 	    cr_p->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
592 	    cr_p->sp_ptr->cm_srvc_handle->sv_sp_hkey,
593 	    (uint64_t)cr_p->ib_cm_handle, ep_p->qp_handle->ep_hkey);
594 
595 	args.cra_bkl_cookie = (uint64_t)cr_p->ib_cm_handle;
596 	args.cra_sp_hkey = cr_p->sp_ptr->cm_srvc_handle->sv_sp_hkey;
597 	args.cra_ep_hkey = ep_p->qp_handle->ep_hkey;
598 
599 	args.cra_priv_sz = IB_MAX_REP_PDATA_SIZE;
600 	bcopy(prd_ptr, args.cra_priv, IB_MAX_REP_PDATA_SIZE);
601 
602 	retval = ioctl(cr_p->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
603 	    DAPL_CR_ACCEPT, &args);
604 	if (retval != 0) {
605 		ep_p->qp_state = IBT_STATE_ERROR;
606 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
607 		    "dapls_ib_accept: accept failed %s\n",
608 		    strerror(errno));
609 		return (dapls_convert_error(errno, retval));
610 	}
611 	return (DAT_SUCCESS);
612 }
613 /*
614  * dapls_ib_cm_remote_addr
615  *
616  * Obtain the remote IP address given a connection
617  *
618  * Input:
619  *      cr_handle
620  *      private data structure handle (only for IBHOSTS_NAMING)
621  *
622  * Output:
623  *      remote_ia_address: where to place the remote address
624  *
625  * Returns:
626  *      DAT_SUCCESS
627  *      DAT_INSUFFICIENT_RESOURCES
628  *      DAT_INVALID_PARAMETER
629  *
630  */
631 /* ARGSUSED */
632 DAT_RETURN
dapls_ib_cm_remote_addr(IN DAT_HANDLE dat_handle,IN DAPL_PRIVATE * prd_ptr,OUT DAT_SOCK_ADDR6 * remote_ia_address)633 dapls_ib_cm_remote_addr(
634 	IN DAT_HANDLE	dat_handle,
635 	IN DAPL_PRIVATE	*prd_ptr,
636 	OUT DAT_SOCK_ADDR6 *remote_ia_address)
637 {
638 	return (DAT_SUCCESS);
639 }
640 
641 
642 /*
643  * dapls_ib_handoff_connection
644  *
645  * handoff connection to a different qualifier
646  *
647  * Input:
648  *        cr_ptr
649  *        cr_handoff
650  *
651  * Output:
652  *        none
653  *
654  * Returns:
655  *        DAT_SUCCESS
656  *        DAT_INSUFFICIENT_RESOURCES
657  *        DAT_INVALID_PARAMETER
658  *
659  */
660 DAT_RETURN
dapls_ib_handoff_connection(IN DAPL_CR * cr_ptr,IN DAT_CONN_QUAL cr_handoff)661 dapls_ib_handoff_connection(IN DAPL_CR *cr_ptr, IN DAT_CONN_QUAL cr_handoff)
662 {
663 	dapl_cr_handoff_t args;
664 	int retval;
665 
666 	dapl_dbg_log(DAPL_DBG_TYPE_CM,
667 	    "dapls_ib_handoff: fd %d, sp_hkey %016llx, "
668 	    "bkl_index 0x%llx conn_qual %llu\n",
669 	    cr_ptr->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
670 	    cr_ptr->sp_ptr->cm_srvc_handle->sv_sp_hkey,
671 	    (uint64_t)cr_ptr->ib_cm_handle, cr_handoff);
672 
673 	args.crh_bkl_cookie = (uint64_t)cr_ptr->ib_cm_handle;
674 	args.crh_sp_hkey = cr_ptr->sp_ptr->cm_srvc_handle->sv_sp_hkey;
675 	args.crh_conn_qual = cr_handoff;
676 
677 	retval = ioctl(cr_ptr->header.owner_ia->hca_ptr->ib_hca_handle->ia_fd,
678 	    DAPL_CR_HANDOFF, &args);
679 	if (retval != 0) {
680 		dapl_dbg_log(DAPL_DBG_TYPE_ERR,
681 		    "dapls_ib_handoff: failed %s\n", strerror(errno));
682 		return (dapls_convert_error(errno, retval));
683 	}
684 	return (DAT_SUCCESS);
685 }
686