1*9e39c5baSBill Taylor /*
2*9e39c5baSBill Taylor * CDDL HEADER START
3*9e39c5baSBill Taylor *
4*9e39c5baSBill Taylor * The contents of this file are subject to the terms of the
5*9e39c5baSBill Taylor * Common Development and Distribution License (the "License").
6*9e39c5baSBill Taylor * You may not use this file except in compliance with the License.
7*9e39c5baSBill Taylor *
8*9e39c5baSBill Taylor * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9e39c5baSBill Taylor * or http://www.opensolaris.org/os/licensing.
10*9e39c5baSBill Taylor * See the License for the specific language governing permissions
11*9e39c5baSBill Taylor * and limitations under the License.
12*9e39c5baSBill Taylor *
13*9e39c5baSBill Taylor * When distributing Covered Code, include this CDDL HEADER in each
14*9e39c5baSBill Taylor * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9e39c5baSBill Taylor * If applicable, add the following below this CDDL HEADER, with the
16*9e39c5baSBill Taylor * fields enclosed by brackets "[]" replaced with your own identifying
17*9e39c5baSBill Taylor * information: Portions Copyright [yyyy] [name of copyright owner]
18*9e39c5baSBill Taylor *
19*9e39c5baSBill Taylor * CDDL HEADER END
20*9e39c5baSBill Taylor */
21*9e39c5baSBill Taylor
22*9e39c5baSBill Taylor /*
23*9e39c5baSBill Taylor * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.
24*9e39c5baSBill Taylor */
25*9e39c5baSBill Taylor
26*9e39c5baSBill Taylor /*
27*9e39c5baSBill Taylor * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
28*9e39c5baSBill Taylor * Use is subject to license terms.
29*9e39c5baSBill Taylor */
30*9e39c5baSBill Taylor
31*9e39c5baSBill Taylor /*
32*9e39c5baSBill Taylor *
33*9e39c5baSBill Taylor * MODULE: dapl_ep_connect.c
34*9e39c5baSBill Taylor *
35*9e39c5baSBill Taylor * PURPOSE: Endpoint management
36*9e39c5baSBill Taylor * Description: Interfaces in this file are completely described in
37*9e39c5baSBill Taylor * the DAPL 1.1 API, Chapter 6, section 5
38*9e39c5baSBill Taylor *
39*9e39c5baSBill Taylor * $Id: dapl_ep_connect.c,v 1.23 2003/07/31 13:55:18 hobie16 Exp $
40*9e39c5baSBill Taylor */
41*9e39c5baSBill Taylor
42*9e39c5baSBill Taylor #include "dapl.h"
43*9e39c5baSBill Taylor #include "dapl_ep_util.h"
44*9e39c5baSBill Taylor #include "dapl_adapter_util.h"
45*9e39c5baSBill Taylor #include "dapl_evd_util.h"
46*9e39c5baSBill Taylor
47*9e39c5baSBill Taylor /*
48*9e39c5baSBill Taylor * dapl_ep_connect
49*9e39c5baSBill Taylor *
50*9e39c5baSBill Taylor * DAPL Requirements Version xxx, 6.5.7
51*9e39c5baSBill Taylor *
52*9e39c5baSBill Taylor * Request a connection be established between the local Endpoint
53*9e39c5baSBill Taylor * and a remote Endpoint. This operation is used by the active/client
54*9e39c5baSBill Taylor * side of a connection
55*9e39c5baSBill Taylor *
56*9e39c5baSBill Taylor * Input:
57*9e39c5baSBill Taylor * ep_handle
58*9e39c5baSBill Taylor * remote_ia_address
59*9e39c5baSBill Taylor * remote_conn_qual
60*9e39c5baSBill Taylor * timeout
61*9e39c5baSBill Taylor * private_data_size
62*9e39c5baSBill Taylor * privaet_data
63*9e39c5baSBill Taylor * qos
64*9e39c5baSBill Taylor * connect_flags
65*9e39c5baSBill Taylor *
66*9e39c5baSBill Taylor * Output:
67*9e39c5baSBill Taylor * None
68*9e39c5baSBill Taylor *
69*9e39c5baSBill Taylor * Returns:
70*9e39c5baSBill Taylor * DAT_SUCCESS
71*9e39c5baSBill Taylor * DAT_INSUFFICIENT_RESOUCRES
72*9e39c5baSBill Taylor * DAT_INVALID_PARAMETER
73*9e39c5baSBill Taylor * DAT_MODLE_NOT_SUPPORTED
74*9e39c5baSBill Taylor */
75*9e39c5baSBill Taylor DAT_RETURN
dapl_ep_connect(IN DAT_EP_HANDLE ep_handle,IN DAT_IA_ADDRESS_PTR remote_ia_address,IN DAT_CONN_QUAL remote_conn_qual,IN DAT_TIMEOUT timeout,IN DAT_COUNT private_data_size,IN const DAT_PVOID private_data,IN DAT_QOS qos,IN DAT_CONNECT_FLAGS connect_flags)76*9e39c5baSBill Taylor dapl_ep_connect(
77*9e39c5baSBill Taylor IN DAT_EP_HANDLE ep_handle,
78*9e39c5baSBill Taylor IN DAT_IA_ADDRESS_PTR remote_ia_address,
79*9e39c5baSBill Taylor IN DAT_CONN_QUAL remote_conn_qual,
80*9e39c5baSBill Taylor IN DAT_TIMEOUT timeout,
81*9e39c5baSBill Taylor IN DAT_COUNT private_data_size,
82*9e39c5baSBill Taylor IN const DAT_PVOID private_data,
83*9e39c5baSBill Taylor IN DAT_QOS qos,
84*9e39c5baSBill Taylor IN DAT_CONNECT_FLAGS connect_flags)
85*9e39c5baSBill Taylor {
86*9e39c5baSBill Taylor DAPL_EP *ep_ptr;
87*9e39c5baSBill Taylor DAPL_PRIVATE prd;
88*9e39c5baSBill Taylor DAPL_EP alloc_ep;
89*9e39c5baSBill Taylor DAT_RETURN dat_status;
90*9e39c5baSBill Taylor
91*9e39c5baSBill Taylor dapl_dbg_log(DAPL_DBG_TYPE_API | DAPL_DBG_TYPE_CM,
92*9e39c5baSBill Taylor "dapl_ep_connect (%p, {%u.%u.%u.%u}, %X, %d, %d, %p, %x, %x)\n",
93*9e39c5baSBill Taylor ep_handle,
94*9e39c5baSBill Taylor remote_ia_address->sa_data[2],
95*9e39c5baSBill Taylor remote_ia_address->sa_data[3],
96*9e39c5baSBill Taylor remote_ia_address->sa_data[4],
97*9e39c5baSBill Taylor remote_ia_address->sa_data[5],
98*9e39c5baSBill Taylor remote_conn_qual,
99*9e39c5baSBill Taylor timeout,
100*9e39c5baSBill Taylor private_data_size,
101*9e39c5baSBill Taylor private_data,
102*9e39c5baSBill Taylor qos,
103*9e39c5baSBill Taylor connect_flags);
104*9e39c5baSBill Taylor
105*9e39c5baSBill Taylor dat_status = DAT_SUCCESS;
106*9e39c5baSBill Taylor ep_ptr = (DAPL_EP *) ep_handle;
107*9e39c5baSBill Taylor
108*9e39c5baSBill Taylor /*
109*9e39c5baSBill Taylor * Verify parameter & state. The connection handle must be good
110*9e39c5baSBill Taylor * at this point.
111*9e39c5baSBill Taylor */
112*9e39c5baSBill Taylor if (DAPL_BAD_HANDLE(ep_ptr, DAPL_MAGIC_EP)) {
113*9e39c5baSBill Taylor dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
114*9e39c5baSBill Taylor DAT_INVALID_HANDLE_EP);
115*9e39c5baSBill Taylor goto bail;
116*9e39c5baSBill Taylor }
117*9e39c5baSBill Taylor
118*9e39c5baSBill Taylor if (DAPL_BAD_HANDLE(ep_ptr->param.connect_evd_handle, DAPL_MAGIC_EVD)) {
119*9e39c5baSBill Taylor dat_status = DAT_ERROR(DAT_INVALID_HANDLE,
120*9e39c5baSBill Taylor DAT_INVALID_HANDLE_EVD_CONN);
121*9e39c5baSBill Taylor goto bail;
122*9e39c5baSBill Taylor }
123*9e39c5baSBill Taylor
124*9e39c5baSBill Taylor /*
125*9e39c5baSBill Taylor * If the endpoint needs a QP, associated the QP with it.
126*9e39c5baSBill Taylor * This needs to be done carefully, in order to:
127*9e39c5baSBill Taylor * * Avoid allocating under a lock.
128*9e39c5baSBill Taylor * * Not step on data structures being altered by
129*9e39c5baSBill Taylor * routines with which we are racing.
130*9e39c5baSBill Taylor * So we:
131*9e39c5baSBill Taylor * * Confirm that a new QP is needed and is not forbidden by the
132*9e39c5baSBill Taylor * current state.
133*9e39c5baSBill Taylor * * Allocate it into a separate EP.
134*9e39c5baSBill Taylor * * Take the EP lock.
135*9e39c5baSBill Taylor * * Reconfirm that the EP is in a state where it needs a QP.
136*9e39c5baSBill Taylor * * Assign the QP and release the lock.
137*9e39c5baSBill Taylor */
138*9e39c5baSBill Taylor if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) {
139*9e39c5baSBill Taylor if (ep_ptr->param.pz_handle == NULL ||
140*9e39c5baSBill Taylor DAPL_BAD_HANDLE(ep_ptr->param.pz_handle, DAPL_MAGIC_PZ)) {
141*9e39c5baSBill Taylor dat_status = DAT_ERROR(DAT_INVALID_STATE,
142*9e39c5baSBill Taylor DAT_INVALID_STATE_EP_NOTREADY);
143*9e39c5baSBill Taylor goto bail;
144*9e39c5baSBill Taylor }
145*9e39c5baSBill Taylor alloc_ep = *ep_ptr;
146*9e39c5baSBill Taylor
147*9e39c5baSBill Taylor dat_status = dapls_ib_qp_alloc(ep_ptr->header.owner_ia,
148*9e39c5baSBill Taylor &alloc_ep, ep_ptr);
149*9e39c5baSBill Taylor if (dat_status != DAT_SUCCESS) {
150*9e39c5baSBill Taylor dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
151*9e39c5baSBill Taylor DAT_RESOURCE_MEMORY);
152*9e39c5baSBill Taylor goto bail;
153*9e39c5baSBill Taylor }
154*9e39c5baSBill Taylor
155*9e39c5baSBill Taylor dapl_os_lock(&ep_ptr->header.lock);
156*9e39c5baSBill Taylor /*
157*9e39c5baSBill Taylor * PZ shouldn't have changed since we're only racing with
158*9e39c5baSBill Taylor * dapl_cr_accept()
159*9e39c5baSBill Taylor */
160*9e39c5baSBill Taylor if (ep_ptr->qp_state != DAPL_QP_STATE_UNATTACHED) {
161*9e39c5baSBill Taylor /* Bail, cleaning up. */
162*9e39c5baSBill Taylor dapl_os_unlock(&ep_ptr->header.lock);
163*9e39c5baSBill Taylor dat_status = dapls_ib_qp_free(ep_ptr->header.owner_ia,
164*9e39c5baSBill Taylor &alloc_ep);
165*9e39c5baSBill Taylor if (dat_status != DAT_SUCCESS) {
166*9e39c5baSBill Taylor dapl_dbg_log(DAPL_DBG_TYPE_WARN,
167*9e39c5baSBill Taylor "ep_connect: ib_qp_free failed with %x\n",
168*9e39c5baSBill Taylor dat_status);
169*9e39c5baSBill Taylor }
170*9e39c5baSBill Taylor dat_status = DAT_ERROR(DAT_INVALID_STATE,
171*9e39c5baSBill Taylor dapls_ep_state_subtype(ep_ptr));
172*9e39c5baSBill Taylor goto bail;
173*9e39c5baSBill Taylor }
174*9e39c5baSBill Taylor ep_ptr->qp_handle = alloc_ep.qp_handle;
175*9e39c5baSBill Taylor ep_ptr->qpn = alloc_ep.qpn;
176*9e39c5baSBill Taylor ep_ptr->qp_state = alloc_ep.qp_state;
177*9e39c5baSBill Taylor
178*9e39c5baSBill Taylor dapl_os_unlock(&ep_ptr->header.lock);
179*9e39c5baSBill Taylor }
180*9e39c5baSBill Taylor
181*9e39c5baSBill Taylor /*
182*9e39c5baSBill Taylor * We do state checks and transitions under lock.
183*9e39c5baSBill Taylor * The only code we're racing against is dapl_cr_accept.
184*9e39c5baSBill Taylor */
185*9e39c5baSBill Taylor dapl_os_lock(&ep_ptr->header.lock);
186*9e39c5baSBill Taylor
187*9e39c5baSBill Taylor /*
188*9e39c5baSBill Taylor * Verify the attributes of the EP handle before we connect it. Test
189*9e39c5baSBill Taylor * all of the handles to make sure they are currently valid.
190*9e39c5baSBill Taylor * Specifically:
191*9e39c5baSBill Taylor * pz_handle required
192*9e39c5baSBill Taylor * recv_evd_handle optional, but must be valid
193*9e39c5baSBill Taylor * request_evd_handle optional, but must be valid
194*9e39c5baSBill Taylor * connect_evd_handle required
195*9e39c5baSBill Taylor */
196*9e39c5baSBill Taylor if (ep_ptr->param.pz_handle == NULL ||
197*9e39c5baSBill Taylor DAPL_BAD_HANDLE(ep_ptr->param.pz_handle, DAPL_MAGIC_PZ) ||
198*9e39c5baSBill Taylor ep_ptr->param.connect_evd_handle == NULL ||
199*9e39c5baSBill Taylor DAPL_BAD_HANDLE(ep_ptr->param.connect_evd_handle,
200*9e39c5baSBill Taylor DAPL_MAGIC_EVD) ||
201*9e39c5baSBill Taylor !(((DAPL_EVD *)ep_ptr->param.connect_evd_handle)->evd_flags &
202*9e39c5baSBill Taylor DAT_EVD_CONNECTION_FLAG) ||
203*9e39c5baSBill Taylor (ep_ptr->param.recv_evd_handle != DAT_HANDLE_NULL &&
204*9e39c5baSBill Taylor (DAPL_BAD_HANDLE(ep_ptr->param.recv_evd_handle,
205*9e39c5baSBill Taylor DAPL_MAGIC_EVD))) ||
206*9e39c5baSBill Taylor (ep_ptr->param.request_evd_handle != DAT_HANDLE_NULL &&
207*9e39c5baSBill Taylor (DAPL_BAD_HANDLE(ep_ptr->param.request_evd_handle,
208*9e39c5baSBill Taylor DAPL_MAGIC_EVD)))) {
209*9e39c5baSBill Taylor dapl_os_unlock(&ep_ptr->header.lock);
210*9e39c5baSBill Taylor dat_status = DAT_ERROR(DAT_INVALID_STATE,
211*9e39c5baSBill Taylor DAT_INVALID_STATE_EP_NOTREADY);
212*9e39c5baSBill Taylor goto bail;
213*9e39c5baSBill Taylor }
214*9e39c5baSBill Taylor
215*9e39c5baSBill Taylor /*
216*9e39c5baSBill Taylor * Check both the EP state and the QP state: if we don't have a QP
217*9e39c5baSBill Taylor * we need to attach one now.
218*9e39c5baSBill Taylor */
219*9e39c5baSBill Taylor if (ep_ptr->qp_state == DAPL_QP_STATE_UNATTACHED) {
220*9e39c5baSBill Taylor dat_status = dapls_ib_qp_alloc(ep_ptr->header.owner_ia,
221*9e39c5baSBill Taylor ep_ptr, ep_ptr);
222*9e39c5baSBill Taylor
223*9e39c5baSBill Taylor if (dat_status != DAT_SUCCESS) {
224*9e39c5baSBill Taylor dapl_os_unlock(&ep_ptr->header.lock);
225*9e39c5baSBill Taylor dat_status = DAT_ERROR(DAT_INSUFFICIENT_RESOURCES,
226*9e39c5baSBill Taylor DAT_RESOURCE_TEP);
227*9e39c5baSBill Taylor goto bail;
228*9e39c5baSBill Taylor }
229*9e39c5baSBill Taylor }
230*9e39c5baSBill Taylor
231*9e39c5baSBill Taylor if (ep_ptr->param.ep_state != DAT_EP_STATE_UNCONNECTED) {
232*9e39c5baSBill Taylor dapl_os_unlock(&ep_ptr->header.lock);
233*9e39c5baSBill Taylor dat_status = DAT_ERROR(DAT_INVALID_STATE,
234*9e39c5baSBill Taylor dapls_ep_state_subtype(ep_ptr));
235*9e39c5baSBill Taylor goto bail;
236*9e39c5baSBill Taylor }
237*9e39c5baSBill Taylor
238*9e39c5baSBill Taylor if (qos != DAT_QOS_BEST_EFFORT ||
239*9e39c5baSBill Taylor connect_flags != DAT_CONNECT_DEFAULT_FLAG) {
240*9e39c5baSBill Taylor /*
241*9e39c5baSBill Taylor * At this point we only support one QOS level
242*9e39c5baSBill Taylor */
243*9e39c5baSBill Taylor dapl_os_unlock(&ep_ptr->header.lock);
244*9e39c5baSBill Taylor dat_status = DAT_ERROR(DAT_MODEL_NOT_SUPPORTED, 0);
245*9e39c5baSBill Taylor goto bail;
246*9e39c5baSBill Taylor }
247*9e39c5baSBill Taylor
248*9e39c5baSBill Taylor /*
249*9e39c5baSBill Taylor * Verify the private data size doesn't exceed the max
250*9e39c5baSBill Taylor */
251*9e39c5baSBill Taylor if (private_data_size > DAPL_CONSUMER_MAX_PRIVATE_DATA_SIZE) {
252*9e39c5baSBill Taylor dapl_os_unlock(&ep_ptr->header.lock);
253*9e39c5baSBill Taylor dat_status = DAT_ERROR(DAT_INVALID_PARAMETER, DAT_INVALID_ARG5);
254*9e39c5baSBill Taylor goto bail;
255*9e39c5baSBill Taylor }
256*9e39c5baSBill Taylor
257*9e39c5baSBill Taylor /*
258*9e39c5baSBill Taylor * transition the state before requesting a connection to avoid
259*9e39c5baSBill Taylor * race conditions
260*9e39c5baSBill Taylor */
261*9e39c5baSBill Taylor ep_ptr->param.ep_state = DAT_EP_STATE_ACTIVE_CONNECTION_PENDING;
262*9e39c5baSBill Taylor
263*9e39c5baSBill Taylor /*
264*9e39c5baSBill Taylor * At this point we're committed, and done with the endpoint
265*9e39c5baSBill Taylor * except for the connect, so we can drop the lock.
266*9e39c5baSBill Taylor */
267*9e39c5baSBill Taylor dapl_os_unlock(&ep_ptr->header.lock);
268*9e39c5baSBill Taylor
269*9e39c5baSBill Taylor /*
270*9e39c5baSBill Taylor * fill in the private data
271*9e39c5baSBill Taylor */
272*9e39c5baSBill Taylor (void) dapl_os_memzero(&prd, sizeof (DAPL_PRIVATE));
273*9e39c5baSBill Taylor if (private_data_size > 0)
274*9e39c5baSBill Taylor (void) dapl_os_memcpy(prd.private_data, private_data,
275*9e39c5baSBill Taylor private_data_size);
276*9e39c5baSBill Taylor
277*9e39c5baSBill Taylor /* Copy the connection qualifiers */
278*9e39c5baSBill Taylor (void) dapl_os_memcpy(ep_ptr->param.remote_ia_address_ptr,
279*9e39c5baSBill Taylor remote_ia_address, sizeof (DAT_SOCK_ADDR6));
280*9e39c5baSBill Taylor ep_ptr->param.remote_port_qual = remote_conn_qual;
281*9e39c5baSBill Taylor
282*9e39c5baSBill Taylor dat_status = dapls_ib_connect(ep_handle,
283*9e39c5baSBill Taylor remote_ia_address, remote_conn_qual,
284*9e39c5baSBill Taylor private_data_size, &prd, timeout);
285*9e39c5baSBill Taylor
286*9e39c5baSBill Taylor if (dat_status != DAT_SUCCESS) {
287*9e39c5baSBill Taylor DAPL_EVD *evd_ptr;
288*9e39c5baSBill Taylor
289*9e39c5baSBill Taylor if (dat_status == DAT_ERROR(DAT_INVALID_ADDRESS,
290*9e39c5baSBill Taylor DAT_INVALID_ADDRESS_UNREACHABLE)) {
291*9e39c5baSBill Taylor /* Unreachable IP address */
292*9e39c5baSBill Taylor evd_ptr = (DAPL_EVD *)ep_ptr->param.connect_evd_handle;
293*9e39c5baSBill Taylor if (evd_ptr != NULL) {
294*9e39c5baSBill Taylor (void) dapls_evd_post_connection_event(evd_ptr,
295*9e39c5baSBill Taylor DAT_CONNECTION_EVENT_UNREACHABLE,
296*9e39c5baSBill Taylor (DAT_HANDLE) ep_ptr, 0, 0);
297*9e39c5baSBill Taylor }
298*9e39c5baSBill Taylor ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
299*9e39c5baSBill Taylor dat_status = DAT_SUCCESS;
300*9e39c5baSBill Taylor } else if (dat_status == DAT_ERROR(DAT_INVALID_PARAMETER,
301*9e39c5baSBill Taylor DAT_INVALID_ADDRESS_UNREACHABLE)) {
302*9e39c5baSBill Taylor /* Non-existant connection qualifier */
303*9e39c5baSBill Taylor evd_ptr = (DAPL_EVD *)ep_ptr->param.connect_evd_handle;
304*9e39c5baSBill Taylor if (evd_ptr != NULL) {
305*9e39c5baSBill Taylor (void) dapls_evd_post_connection_event(evd_ptr,
306*9e39c5baSBill Taylor DAT_CONNECTION_EVENT_NON_PEER_REJECTED,
307*9e39c5baSBill Taylor (DAT_HANDLE) ep_ptr, 0, 0);
308*9e39c5baSBill Taylor }
309*9e39c5baSBill Taylor ep_ptr->param.ep_state = DAT_EP_STATE_DISCONNECTED;
310*9e39c5baSBill Taylor dat_status = DAT_SUCCESS;
311*9e39c5baSBill Taylor } else {
312*9e39c5baSBill Taylor ep_ptr->param.ep_state = DAT_EP_STATE_UNCONNECTED;
313*9e39c5baSBill Taylor }
314*9e39c5baSBill Taylor }
315*9e39c5baSBill Taylor
316*9e39c5baSBill Taylor bail:
317*9e39c5baSBill Taylor dapl_dbg_log(DAPL_DBG_TYPE_RTN | DAPL_DBG_TYPE_CM,
318*9e39c5baSBill Taylor "dapl_ep_connect () returns 0x%x\n", dat_status);
319*9e39c5baSBill Taylor
320*9e39c5baSBill Taylor return (dat_status);
321*9e39c5baSBill Taylor }
322