[DAPL2] DAPL Counters & 2.0.3 extensions to support counter retrieval.
[mirror/winof/.git] / ulp / dapl2 / dapl / common / dapl_evd_connection_callb.c
1 /*\r
2  * Copyright (c) 2002-2003, Network Appliance, Inc. All rights reserved.\r
3  *\r
4  * This Software is licensed under one of the following licenses:\r
5  *\r
6  * 1) under the terms of the "Common Public License 1.0" a copy of which is\r
7  *    available from the Open Source Initiative, see\r
8  *    http://www.opensource.org/licenses/cpl.php.\r
9  *\r
10  * 2) under the terms of the "The BSD License" a copy of which is\r
11  *    available from the Open Source Initiative, see\r
12  *    http://www.opensource.org/licenses/bsd-license.php.\r
13  *\r
14  * 3) under the terms of the "GNU General Public License (GPL) Version 2" a\r
15  *    copy of which is available from the Open Source Initiative, see\r
16  *    http://www.opensource.org/licenses/gpl-license.php.\r
17  *\r
18  * Licensee has the right to choose one of the above licenses.\r
19  *\r
20  * Redistributions of source code must retain the above copyright\r
21  * notice and one of the license notices.\r
22  *\r
23  * Redistributions in binary form must reproduce both the above copyright\r
24  * notice, one of the license notices in the documentation\r
25  * and/or other materials provided with the distribution.\r
26  */\r
27 \r
28 /**********************************************************************\r
29  *\r
30  * MODULE: dapl_evd_connection_callback.c\r
31  *\r
32  * PURPOSE: implements connection callbacks\r
33  *\r
34  * Description: Accepts asynchronous callbacks from the Communications Manager\r
35  *              for EVDs that have been specified as the connection_evd.\r
36  *\r
37  * $Id:$\r
38  **********************************************************************/\r
39 \r
40 #include "dapl.h"\r
41 #include "dapl_evd_util.h"\r
42 #include "dapl_ep_util.h"\r
43 #include "dapl_timer_util.h"\r
44 \r
45 \r
46 /*\r
47  * dapl_evd_connection_callback\r
48  *\r
49  * Connection callback function for ACTIVE connection requests; callbacks\r
50  * generated by the Connection Manager in response to issuing a\r
51  * connect call.\r
52  *\r
53  * Input:\r
54  *      ib_cm_handle,\r
55  *      ib_cm_event\r
56  *      private_data_ptr\r
57  *      context (evd)\r
58  *      cr_pp\r
59  *\r
60  * Output:\r
61  *      None\r
62  *\r
63  */\r
64 \r
65 void\r
66 dapl_evd_connection_callback (\r
67     IN    dp_ib_cm_handle_t     ib_cm_handle,\r
68     IN    const ib_cm_events_t  ib_cm_event,\r
69     IN    const void            *private_data_ptr,\r
70     IN    const void            *context)\r
71 {\r
72     DAPL_EP             *ep_ptr;\r
73     DAPL_EVD            *evd_ptr;\r
74     DAPL_PRIVATE        *prd_ptr;\r
75     DAT_EVENT_NUMBER    dat_event_num;\r
76     DAT_RETURN          dat_status;\r
77     int                 private_data_size;\r
78 \r
79 \r
80     dapl_dbg_log (\r
81         DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,\r
82         "--> dapl_evd_connection_callback: ctxt: %p event: %x cm_handle %p\n",\r
83         context,\r
84         ib_cm_event,\r
85         (void *) ib_cm_handle );\r
86 \r
87     /*\r
88      * Determine the type of handle passed back to us in the context\r
89      * and sort out key parameters.\r
90      */\r
91     if ( context == NULL || ((DAPL_HEADER *)context)->magic != DAPL_MAGIC_EP)\r
92     {\r
93         return;\r
94     }\r
95 \r
96     /*\r
97      * Active side of the connection, context is an EP and\r
98      * PSP is irrelevant.\r
99      */\r
100     ep_ptr  = (DAPL_EP *) context;\r
101     evd_ptr = (DAPL_EVD *) ep_ptr->param.connect_evd_handle;\r
102     DAPL_CNTR(evd_ptr, DCNT_EVD_CONN_CALLBACK);\r
103 \r
104     prd_ptr = (DAPL_PRIVATE *)private_data_ptr;\r
105     private_data_size = 0;\r
106     /*\r
107      * All operations effect the EP, so lock it once and unlock\r
108      * when necessary\r
109      */\r
110     dapl_os_lock (&ep_ptr->header.lock);\r
111 \r
112     /*\r
113      * If a connection timer has been set up on this EP, cancel it now\r
114      */\r
115     if ( ep_ptr->cxn_timer != NULL )\r
116     {\r
117         dapls_timer_cancel ( ep_ptr->cxn_timer );\r
118         dapl_os_free ( ep_ptr->cxn_timer, sizeof ( DAPL_OS_TIMER ) );\r
119         ep_ptr->cxn_timer = NULL;\r
120     }\r
121 \r
122     /* Obtain the event number from the provider layer */\r
123     dat_event_num = dapls_ib_get_dat_event (ib_cm_event, DAT_FALSE);\r
124 \r
125     switch (dat_event_num)\r
126     {\r
127         case DAT_CONNECTION_EVENT_ESTABLISHED:\r
128         {\r
129             /* If we don't have an EP at this point we are very screwed\r
130              * up\r
131              */\r
132             if ( ep_ptr->param.ep_state != DAT_EP_STATE_ACTIVE_CONNECTION_PENDING)\r
133             {\r
134                 /* If someone pulled the plug on the connection, just\r
135                  * exit\r
136                  */\r
137                 dapl_os_unlock ( &ep_ptr->header.lock );\r
138                 dat_status = DAT_SUCCESS;\r
139                 break;\r
140             }\r
141             ep_ptr->param.ep_state = DAT_EP_STATE_CONNECTED;\r
142             ep_ptr->cm_handle      = ib_cm_handle;\r
143             if (prd_ptr == NULL)\r
144             {\r
145                 private_data_size  = 0;\r
146             }\r
147             else\r
148             {\r
149                 private_data_size  = \r
150                     dapls_ib_private_data_size(\r
151                                         prd_ptr, DAPL_PDATA_CONN_REP,\r
152                                         ep_ptr->header.owner_ia->hca_ptr);\r
153             }\r
154 \r
155             if (private_data_size > 0)\r
156             {\r
157                 /* copy in the private data */\r
158                 dapl_os_memcpy ( ep_ptr->private.private_data,\r
159                                  prd_ptr->private_data,\r
160                                  DAPL_MIN (private_data_size, DAPL_MAX_PRIVATE_DATA_SIZE));\r
161             }\r
162             dapl_os_unlock (&ep_ptr->header.lock);\r
163 \r
164             break;\r
165         }\r
166         case DAT_CONNECTION_EVENT_PEER_REJECTED:\r
167         {\r
168             /* peer reject may include private data */\r
169             if (prd_ptr != NULL) \r
170                 private_data_size  = \r
171                     dapls_ib_private_data_size(\r
172                                         prd_ptr, DAPL_PDATA_CONN_REJ,\r
173                                         ep_ptr->header.owner_ia->hca_ptr);\r
174 \r
175             if (private_data_size > 0) \r
176                 dapl_os_memcpy (ep_ptr->private.private_data,\r
177                                 prd_ptr->private_data,\r
178                                 DAPL_MIN (private_data_size, \r
179                                           DAPL_MAX_PRIVATE_DATA_SIZE));\r
180 \r
181             dapl_dbg_log(DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,\r
182                          "dapl_evd_connection_callback PEER REJ pd=%p sz=%d\n",\r
183                          prd_ptr, private_data_size);\r
184         }\r
185         case DAT_CONNECTION_EVENT_DISCONNECTED:\r
186         case DAT_CONNECTION_EVENT_UNREACHABLE:\r
187         case DAT_CONNECTION_EVENT_NON_PEER_REJECTED:\r
188         {\r
189             ep_ptr->param.ep_state  = DAT_EP_STATE_DISCONNECTED;\r
190             dapls_ib_disconnect_clean (ep_ptr, DAT_TRUE, ib_cm_event);\r
191             dapl_os_unlock (&ep_ptr->header.lock);\r
192 \r
193             break;\r
194         }\r
195         case DAT_CONNECTION_EVENT_BROKEN:\r
196         case DAT_CONNECTION_EVENT_TIMED_OUT:\r
197         {\r
198             ep_ptr->param.ep_state  = DAT_EP_STATE_DISCONNECTED;\r
199             dapls_ib_disconnect_clean (ep_ptr, DAT_FALSE, ib_cm_event);\r
200             dapl_os_unlock ( &ep_ptr->header.lock );\r
201 \r
202             break;\r
203         }\r
204         case DAT_CONNECTION_REQUEST_EVENT:\r
205         default:\r
206         {\r
207             dapl_os_unlock (&ep_ptr->header.lock);\r
208             evd_ptr = NULL;\r
209 \r
210             dapl_os_assert (0);         /* shouldn't happen */\r
211             break;\r
212         }\r
213     }\r
214 \r
215     /*\r
216      * Post the event\r
217      * If the EP has been freed, the evd_ptr will be NULL\r
218      */\r
219     if ( evd_ptr != NULL )\r
220     {\r
221         dat_status = dapls_evd_post_connection_event (\r
222                         evd_ptr,\r
223                         dat_event_num,\r
224                         (DAT_HANDLE) ep_ptr,\r
225                         private_data_size, /* CONNECTED or REJECT */\r
226                         ep_ptr->private.private_data );\r
227 \r
228         if (dat_status != DAT_SUCCESS && \r
229             dat_event_num == DAT_CONNECTION_EVENT_ESTABLISHED)\r
230         {\r
231             /* We can't tell the user we are connected, something\r
232              * is wrong locally. Just kill the connection and\r
233              * reset the state to DISCONNECTED as we don't\r
234              * expect a callback on an ABRUPT disconnect.\r
235              */\r
236             dapls_ib_disconnect (ep_ptr, DAT_CLOSE_ABRUPT_FLAG);\r
237             dapl_os_lock (&ep_ptr->header.lock);\r
238             ep_ptr->param.ep_state  = DAT_EP_STATE_DISCONNECTED;\r
239             dapl_os_unlock (&ep_ptr->header.lock);\r
240         }\r
241     }\r
242 \r
243     dapl_dbg_log (DAPL_DBG_TYPE_CM | DAPL_DBG_TYPE_CALLBACK,\r
244                   "dapl_evd_connection_callback () returns\n");\r
245 \r
246 }\r
247 \r
248 \r
249 /*\r
250  * Local variables:\r
251  *  c-indent-level: 4\r
252  *  c-basic-offset: 4\r
253  *  tab-width: 8\r
254  * End:\r
255  */\r