[WSD] Use socket reference count to control destruction.
[mirror/winof/.git] / ulp / wsd / user / ibspstruct.h
1 /*\r
2  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
3  *\r
4  * This software is available to you under the OpenIB.org BSD license\r
5  * below:\r
6  *\r
7  *     Redistribution and use in source and binary forms, with or\r
8  *     without modification, are permitted provided that the following\r
9  *     conditions are met:\r
10  *\r
11  *      - Redistributions of source code must retain the above\r
12  *        copyright notice, this list of conditions and the following\r
13  *        disclaimer.\r
14  *\r
15  *      - Redistributions in binary form must reproduce the above\r
16  *        copyright notice, this list of conditions and the following\r
17  *        disclaimer in the documentation and/or other materials\r
18  *        provided with the distribution.\r
19  *\r
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
23  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
24  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
25  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
26  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
27  * SOFTWARE.\r
28  *\r
29  * $Id$\r
30  */\r
31 \r
32 #include <complib/cl_qlist.h>\r
33 #include <complib/cl_fleximap.h>\r
34 #include <complib/cl_rbmap.h>\r
35 #include <complib/cl_spinlock.h>\r
36 #include <complib/cl_debug.h>\r
37 \r
38 \r
39 enum ibsp_socket_state\r
40 {\r
41         IBSP_CREATE = 0,\r
42         IBSP_BIND,\r
43         IBSP_CONNECT,\r
44         IBSP_LISTEN,\r
45         IBSP_ACCEPT,\r
46         IBSP_CONNECTED,\r
47         IBSP_DUPLICATING_OLD,           /* duplicating socket on the original controlling process */\r
48         IBSP_DUPLICATING_NEW,           /* duplicating socket on the new controlling process */\r
49         IBSP_DUPLICATING_REMOTE,        /* duplicating socket on the remote side */\r
50         IBSP_DISCONNECTED,\r
51         IBSP_CLOSED,\r
52         IBSP_NUM_STATES\r
53 };\r
54 \r
55 extern char *ibsp_socket_state_str[IBSP_NUM_STATES];\r
56 \r
57 #define IBSP_SOCKET_STATE_STR(state) \\r
58         (state < IBSP_NUM_STATES)?ibsp_socket_state_str[state]:"INVALID"\r
59 \r
60 /* Socket Options structure */\r
61 struct ibsp_socket_options\r
62 {\r
63         BOOL debug;                                     /* SO_DEBUG */\r
64         GROUP group_id;                         /* SO_GROUP_ID */\r
65         int group_priority;                     /* SO_GROUP_PRIORITY */\r
66         unsigned int max_msg_size;      /* SO_MAX_MSG_SIZE */\r
67         int max_rdma_size;                      /* SO_MAX_RDMA_SIZE */\r
68         int rdma_threshold_size;        /* SO_RDMA_THRESHOLD_SIZE */\r
69 };\r
70 \r
71 /* Used to discriminate between various listen on the same ports. \r
72  * We need this for socket duplication. \r
73  * { 0, 0 } is a standard connection request. */\r
74 struct listen_req_param\r
75 {\r
76         DWORD dwProcessId;\r
77         DWORD identifier;\r
78 };\r
79 \r
80 /* Parameters given to establish a connection */\r
81 struct cm_req_params\r
82 {\r
83         struct listen_req_param listen_req_param;\r
84         struct sockaddr_in dest;\r
85         struct sockaddr_in source;      /* Source of connect() */\r
86 };\r
87 \r
88 /* Listen structure.\r
89  * Used to remember an incoming connection. */\r
90 struct listen_incoming\r
91 {\r
92         cl_list_item_t                  item;\r
93 \r
94         ib_cm_req_rec_t                 cm_req_received;\r
95         struct cm_req_params    params;\r
96 };\r
97 \r
98 \r
99 /* Keeps track of the posted WR */\r
100 struct _wr\r
101 {\r
102         LPWSAOVERLAPPED                         lpOverlapped;\r
103         struct ibsp_socket_info         *socket_info;\r
104 };\r
105 \r
106 \r
107 /* Keeps track of the posted WR */\r
108 struct _recv_wr\r
109 {\r
110         struct _wr              wr;\r
111         ib_recv_wr_t    recv;\r
112         ib_local_ds_t   ds_array[QP_ATTRIB_RQ_SGE];\r
113 };\r
114 \r
115 \r
116 /* Keeps track of the registered MRs */\r
117 struct mr_list\r
118 {\r
119         cl_qlist_t list;                        /* Regions registered through IBSPRegisterMemory */\r
120         cl_spinlock_t mutex;            /* Protects the list */\r
121 };\r
122 \r
123 /* Information necessary to duplicate sockets */\r
124 struct ibsp_duplicate_info\r
125 {\r
126         ib_net64_t port_guid;\r
127         struct ibsp_socket_options socket_options;\r
128         struct sockaddr_in local_addr;\r
129         struct sockaddr_in peer_addr;\r
130         DWORD dwProcessId;\r
131 };\r
132 \r
133 /* Give the reason for disconnections */\r
134 struct disconnect_reason\r
135 {\r
136         enum\r
137         {\r
138                 DISC_INVALID,\r
139                 DISC_SHUTDOWN,                  /* normal shutdown */\r
140                 DISC_DUPLICATING                /* socket duplication */\r
141         } type;\r
142 \r
143         struct _disconnect_reason_dup\r
144         {\r
145                 DWORD identifier;\r
146                 DWORD dwProcessId;\r
147 \r
148         }       duplicating;\r
149 };\r
150 \r
151 /* Internal node describing a registered region. */\r
152 struct memory_node\r
153 {\r
154 \r
155         cl_list_item_t item;\r
156 \r
157 #ifdef _DEBUG_\r
158 #define MR_NODE_MAGIC 0x7fba43ce\r
159         int magic;\r
160 #endif\r
161 \r
162         /* Everytime the same region is registered, this counter is\r
163          * increased. When it reaches 0, the memory can be released. */\r
164         int refcount;\r
165 \r
166         /* Characteristics of that region. */\r
167         ib_mr_create_t type;\r
168 \r
169         /* Memory registration parameters, returned by ib_reg_mem. */\r
170         uint32_t lkey;\r
171         uint32_t rkey;\r
172         ib_mr_handle_t mr_handle;\r
173 };\r
174 \r
175 /* Descriptor given back to WSPRegisterRdmaMemory */\r
176 struct rdma_memory_desc\r
177 {\r
178         uint64_t iova;\r
179         uint32_t lkey;\r
180         uint32_t rkey;\r
181         struct memory_node *node;       /* valid only on registering node */\r
182 };\r
183 \r
184 struct cq_thread_info\r
185 {\r
186         cl_list_item_t          list_item;\r
187 \r
188         cl_waitobj_handle_t cq_waitobj;\r
189         ib_cq_handle_t cq;\r
190 \r
191         /* Number of qp's using this cq */\r
192         atomic32_t qp_count;\r
193 \r
194         /* Current cqe size */\r
195         uint32_t cqe_size;\r
196 \r
197         HANDLE ib_cq_thread;\r
198         DWORD   ib_cq_thread_id;\r
199         BOOL ib_cq_thread_exit_wanted;\r
200 \r
201         struct ibsp_hca *hca;           /* HCA to which this cq belongs. */\r
202 };\r
203 \r
204 /* Structure representing the context information stored for each\r
205  * socket created */\r
206 struct ibsp_socket_info\r
207 {\r
208         cl_list_item_t item;            /* Link to next SOCKET_INFO in the global list */\r
209         cl_rbmap_item_t conn_item;\r
210         cl_spinlock_t mutex;            /* protect this structure */\r
211 \r
212         /* Switch socket handle created by WPUCreateSocketHandle. */\r
213         SOCKET switch_socket;\r
214 \r
215         /* IP address and port this socket is bound to. Set by WSPBind */\r
216         struct sockaddr_in local_addr;\r
217 \r
218         /* Remote address of peer entity after connect/accept is complete */\r
219         struct sockaddr_in peer_addr;\r
220 \r
221         /* Back pointer to the port to which this socket is\r
222          * bound. It is NULL until the socket is bound, except if the listen\r
223          * binds to INADDR_ANY. */\r
224         struct ibsp_port *port;\r
225 \r
226         enum ibsp_socket_state socket_state;    /* represents current socket state */\r
227 \r
228         struct\r
229         {\r
230                 /* Listening socket */\r
231                 unsigned int backlog;   /* Maximum number of pending connections */\r
232                 cl_qlist_t list;        /* list of pending connections */\r
233                 ib_listen_handle_t handle;\r
234                 struct listen_req_param listen_req_param;\r
235         } listen;\r
236 \r
237         /* Event for blocking accept, and connect */\r
238         HANDLE  h_event;\r
239 \r
240         /* Variables associated with IBSPSelectEvent */\r
241         WSAEVENT event_select;          /* Handle to Event Object */\r
242         long event_mask;                        /* Events we care about */\r
243         long network_events;            /* Events that happenned */\r
244         int errno_connect;                      /* errno code (if any) returned by connect */\r
245 \r
246         struct ibsp_socket_options socket_options;      /* Socket Options */\r
247 \r
248         /* Infiniband ressources */\r
249         ib_pd_handle_t hca_pd;          /* Copy of the HCA PD, for faster access. */\r
250 \r
251         /* Pointer to completion queue and thread assigned to this socket */\r
252         struct cq_thread_info *cq_tinfo;\r
253 \r
254         ib_qp_handle_t          qp;\r
255         uint32_t                        max_inline;\r
256 \r
257         /* State on the QP. This is only valid when the socket state is IBSP_CONNECTED.\r
258          *   0  : good\r
259          *   <0 : an error occurred, contains a windoes error *ie WSAExxxx\r
260          *   -1 : disconected, for duplication process.\r
261          */\r
262         int qp_error;\r
263 \r
264         /* Send request processing. */\r
265         cl_spinlock_t   send_lock;\r
266         ib_send_opt_t   send_opt;\r
267         struct _wr              send_wr[QP_ATTRIB_SQ_DEPTH];\r
268         uint8_t                 send_idx;\r
269         atomic32_t              send_cnt; /* Used to limit access to send_wr array. */\r
270 \r
271         /* Receive request processing. */\r
272         cl_spinlock_t   recv_lock;\r
273         struct _recv_wr recv_wr[QP_ATTRIB_RQ_DEPTH];\r
274         uint8_t                 recv_idx;\r
275         atomic32_t              recv_cnt; /* Used to limit access to recv_wr array. */\r
276 \r
277         /*\r
278          * Used to stall destruction of switch socket until all completion\r
279          * upcalls have unwound.\r
280          */\r
281         atomic32_t              ref_cnt;\r
282 \r
283 #ifdef _DEBUG_\r
284         atomic32_t              send_comp;\r
285         atomic32_t              recv_comp;\r
286 #endif\r
287 \r
288         struct _recv_wr dup_wr[QP_ATTRIB_RQ_DEPTH];\r
289         uint8_t                 dup_idx;\r
290         atomic32_t              dup_cnt;\r
291 \r
292         /* Memory management. \r
293          * From what I saw, the regions registered through IBSPRegisterMemory will \r
294          * only be used by this socket. And there will be only one registration for \r
295          * send buffers and one for receive buffers for the whole life of the socket. \r
296          * Thus these won't be cached. A later optimization would be not to release \r
297          * those regions, but to store them in the HCA structure in case another socket\r
298          * binds the same area again. */\r
299         struct mr_list buf_mem_list;\r
300 \r
301         /* Stuff for socket duplication */\r
302         struct\r
303         {\r
304                 HANDLE mmap_handle;\r
305                 DWORD identifier;               /* Unique identifier */\r
306                 DWORD dwProcessId;\r
307         } duplicate;\r
308 };\r
309 \r
310 \r
311 inline void\r
312 ibsp_css(\r
313                                         char                                            *calling_func,\r
314                                         int                                                     line,\r
315                                         struct ibsp_socket_info         *s,\r
316                                         enum ibsp_socket_state          new_state )\r
317 {\r
318         enum ibsp_socket_state old_state;\r
319 \r
320         UNUSED_PARAM( calling_func );\r
321         UNUSED_PARAM( line );\r
322 \r
323         old_state = s->socket_state;\r
324 \r
325         if( old_state == new_state )\r
326         {\r
327                 /* Nothing to change */\r
328                 return;\r
329         }\r
330 \r
331         /* IBSP_CLOSED is a dead end state */\r
332         if( old_state == IBSP_CLOSED )\r
333         {\r
334                 fzprint(("%s():0x%x:0x%x: socket=0x%p cannot change from %s to %s, called by %s():%d\n", __FUNCTION__, GetCurrentProcessId(), GetCurrentThreadId(), s, IBSP_SOCKET_STATE_STR(old_state), IBSP_SOCKET_STATE_STR(new_state), calling_func, line));\r
335                 return;\r
336         }\r
337 \r
338         fzprint(("%s():0x%x:0x%x: socket=0x%p %s to %s, called by %s():%d\n", __FUNCTION__,\r
339                          GetCurrentProcessId(),\r
340                          GetCurrentThreadId(), s,\r
341                          IBSP_SOCKET_STATE_STR(old_state),\r
342                          IBSP_SOCKET_STATE_STR(new_state), calling_func, line));\r
343 \r
344         s->socket_state = new_state;\r
345 }\r
346 \r
347 #define IBSP_CHANGE_SOCKET_STATE(socket_info, new_state) \\r
348         ibsp_css(__FUNCTION__, __LINE__, socket_info, new_state)\r
349 \r
350 \r
351 /*--------------------------------------------------------------------------*/\r
352 \r
353 /* Describes an IP address */\r
354 struct ibsp_ip_addr\r
355 {\r
356         cl_fmap_item_t          item;                   /* next IP for that port */\r
357 \r
358         struct ibsp_port        *p_port;                /* port that owns this IP address */\r
359         struct in_addr          ip_addr;                /* IPv4 address */\r
360 };\r
361 \r
362 /* describes a port */\r
363 struct ibsp_port\r
364 {\r
365         cl_list_item_t item;\r
366 \r
367         struct ibsp_hca *hca;           /* HCA to which this port belong. */\r
368 \r
369         ib_net64_t guid;\r
370         uint8_t port_num;\r
371 };\r
372 \r
373 /* Describes a hca */\r
374 struct ibsp_hca\r
375 {\r
376         cl_list_item_t item;\r
377 \r
378         ib_net64_t guid;\r
379         uint16_t        dev_id; /* Device ID to selectively cap MTU to 1K for Tavor. */\r
380         ib_ca_handle_t hca_handle;\r
381 \r
382         ib_pd_handle_t pd;\r
383 \r
384         /* Memory management */\r
385         struct mr_list rdma_mem_list;   /* Regions registered through IBSPRegisterRdmaMemory */\r
386 \r
387         cl_spinlock_t   port_lock;\r
388         cl_qlist_t              port_list;\r
389 \r
390         /*\r
391          * The CQ list is a circular list without an end.  The pointer here\r
392          * points to the entry that should be used for the next allocation.\r
393          */\r
394         cl_spinlock_t   cq_lock;\r
395         struct cq_thread_info *cq_tinfo;\r
396 };\r
397 \r
398 /* There is only one instance of that structure. */\r
399 struct ibspdll_globals\r
400 {\r
401         /* Special values. Keep first and in this order. These are not reset\r
402          * between WSAStartupEx and WSACleanup calls. */\r
403         cl_spinlock_t mutex;\r
404         UINT entry_count;\r
405 \r
406         /* Provider */\r
407         WSPUPCALLTABLEEX up_call_table; /* MUST keep afetr entry_count */\r
408         HANDLE heap;\r
409         cl_qlist_t socket_info_list;    /* List of all the created sockets */\r
410         cl_rbmap_t conn_map;    /* rb tree of all connections to ensure unique 4-tuple */\r
411         cl_spinlock_t socket_info_mutex;\r
412 \r
413         WSAPROTOCOL_INFOW protocol_info;\r
414 \r
415         /* Infiniband */\r
416         ib_al_handle_t al_handle;\r
417         ib_pnp_handle_t pnp_handle_ca;\r
418         ib_pnp_handle_t pnp_handle_port;\r
419 \r
420         cl_qlist_t hca_list;\r
421         cl_spinlock_t hca_mutex;\r
422 \r
423         cl_fmap_t               ip_map;                 /* list of all IP addresses supported by all the ports. */\r
424         cl_spinlock_t   ip_mutex;\r
425 \r
426 #ifdef _DEBUG_\r
427         /* Statistics */\r
428         atomic32_t qp_num;\r
429         atomic32_t cq_num;\r
430         atomic32_t pd_num;\r
431         atomic32_t al_num;\r
432         atomic32_t mr_num;\r
433         atomic32_t ca_num;\r
434         atomic32_t listen_num;\r
435         atomic32_t pnp_num;\r
436         atomic32_t thread_num;\r
437         atomic32_t wpusocket_num;\r
438 \r
439         atomic32_t overlap_h0_count;\r
440         atomic32_t overlap_h1_comp_count;\r
441         atomic32_t overlap_h1_count;\r
442         atomic32_t max_comp_count;\r
443         atomic32_t send_count;\r
444         atomic32_t recv_count;\r
445         atomic32_t CloseSocket_count;\r
446 #endif\r
447 };\r