[WSD] Update to CM interaction. Added tracking of connections by
[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_CLOSING,\r
52         IBSP_CLOSED,\r
53         IBSP_NUM_STATES\r
54 };\r
55 \r
56 extern char *ibsp_socket_state_str[IBSP_NUM_STATES];\r
57 \r
58 #define IBSP_SOCKET_STATE_STR(state) \\r
59         (state < IBSP_NUM_STATES)?ibsp_socket_state_str[state]:"INVALID"\r
60 \r
61 /* Socket Options structure */\r
62 struct ibsp_socket_options\r
63 {\r
64         BOOL debug;                                     /* SO_DEBUG */\r
65         GROUP group_id;                         /* SO_GROUP_ID */\r
66         int group_priority;                     /* SO_GROUP_PRIORITY */\r
67         unsigned int max_msg_size;      /* SO_MAX_MSG_SIZE */\r
68         int max_rdma_size;                      /* SO_MAX_RDMA_SIZE */\r
69         int rdma_threshold_size;        /* SO_RDMA_THRESHOLD_SIZE */\r
70 };\r
71 \r
72 /* Used to discriminate between various listen on the same ports. \r
73  * We need this for socket duplication. \r
74  * { 0, 0 } is a standard connection request. */\r
75 struct listen_req_param\r
76 {\r
77         DWORD dwProcessId;\r
78         DWORD identifier;\r
79 };\r
80 \r
81 /* Parameters given to establish a connection */\r
82 struct cm_req_params\r
83 {\r
84         struct listen_req_param listen_req_param;\r
85         struct sockaddr_in dest;\r
86         struct sockaddr_in source;      /* Source of connect() */\r
87 };\r
88 \r
89 /* Listen structure.\r
90  * Used to remember an incoming connection. */\r
91 struct listen_incoming\r
92 {\r
93         cl_list_item_t                  item;\r
94 \r
95         ib_cm_req_rec_t                 cm_req_received;\r
96         struct cm_req_params    params;\r
97 };\r
98 \r
99 \r
100 /* Keeps track of the posted WR */\r
101 struct _wr\r
102 {\r
103         LPWSAOVERLAPPED                         lpOverlapped;\r
104         struct ibsp_socket_info         *socket_info;\r
105 };\r
106 \r
107 \r
108 /* Keeps track of the posted WR */\r
109 struct _recv_wr\r
110 {\r
111         struct _wr              wr;\r
112         ib_recv_wr_t    recv;\r
113         ib_local_ds_t   ds_array[QP_ATTRIB_RQ_SGE];\r
114 };\r
115 \r
116 \r
117 /* Keeps track of the registered MRs */\r
118 struct mr_list\r
119 {\r
120         cl_qlist_t list;                        /* Regions registered through IBSPRegisterMemory */\r
121         cl_spinlock_t mutex;            /* Protects the list */\r
122 };\r
123 \r
124 /* Information necessary to duplicate sockets */\r
125 struct ibsp_duplicate_info\r
126 {\r
127         ib_net64_t port_guid;\r
128         struct ibsp_socket_options socket_options;\r
129         struct sockaddr_in local_addr;\r
130         struct sockaddr_in peer_addr;\r
131         DWORD dwProcessId;\r
132 };\r
133 \r
134 /* Give the reason for disconnections */\r
135 struct disconnect_reason\r
136 {\r
137         enum\r
138         {\r
139                 DISC_INVALID,\r
140                 DISC_SHUTDOWN,                  /* normal shutdown */\r
141                 DISC_DUPLICATING                /* socket duplication */\r
142         } type;\r
143 \r
144         struct _disconnect_reason_dup\r
145         {\r
146                 DWORD identifier;\r
147                 DWORD dwProcessId;\r
148 \r
149         }       duplicating;\r
150 };\r
151 \r
152 /* Internal node describing a registered region. */\r
153 struct memory_node\r
154 {\r
155 \r
156         cl_list_item_t item;\r
157 \r
158 #ifdef _DEBUG_\r
159 #define MR_NODE_MAGIC 0x7fba43ce\r
160         int magic;\r
161 #endif\r
162 \r
163         /* Everytime the same region is registered, this counter is\r
164          * increased. When it reaches 0, the memory can be released. */\r
165         int refcount;\r
166 \r
167         /* Characteristics of that region. */\r
168         ib_mr_create_t type;\r
169 \r
170         /* Memory registration parameters, returned by ib_reg_mem. */\r
171         uint32_t lkey;\r
172         uint32_t rkey;\r
173         ib_mr_handle_t mr_handle;\r
174 };\r
175 \r
176 /* Descriptor given back to WSPRegisterRdmaMemory */\r
177 struct rdma_memory_desc\r
178 {\r
179         uint64_t iova;\r
180         uint32_t lkey;\r
181         uint32_t rkey;\r
182         struct memory_node *node;       /* valid only on registering node */\r
183 };\r
184 \r
185 struct cq_thread_info\r
186 {\r
187         /* For future growth if the hca needs a list of cqs */\r
188         cl_list_item_t item;\r
189 \r
190         cl_waitobj_handle_t cq_waitobj;\r
191         ib_cq_handle_t cq;\r
192 \r
193         cl_spinlock_t wr_mutex;\r
194         cl_qlist_t done_wr_list;\r
195 \r
196         /* Number of qp's using this cq */\r
197         atomic32_t qp_count;\r
198 \r
199         /* Current cqe size */\r
200         uint32_t cqe_size;\r
201 \r
202         HANDLE ib_cq_thread;\r
203         DWORD   ib_cq_thread_id;\r
204         BOOL ib_cq_thread_exit_wanted;\r
205 \r
206         struct ibsp_hca *hca;           /* HCA to which this cq belongs. */\r
207 };\r
208 \r
209 /* Structure representing the context information stored for each\r
210  * socket created */\r
211 struct ibsp_socket_info\r
212 {\r
213         cl_list_item_t item;            /* Link to next SOCKET_INFO in the global list */\r
214         cl_rbmap_item_t conn_item;\r
215         cl_spinlock_t mutex;            /* protect this structure */\r
216 \r
217         /* Switch socket handle created by WPUCreateSocketHandle. */\r
218         SOCKET switch_socket;\r
219 \r
220         /* IP address and port this socket is bound to. Set by WSPBind */\r
221         struct sockaddr_in local_addr;\r
222 \r
223         /* Remote address of peer entity after connect/accept is complete */\r
224         struct sockaddr_in peer_addr;\r
225 \r
226         /* Back pointer to the port to which this socket is\r
227          * bound. It is NULL until the socket is bound, except if the listen\r
228          * binds to INADDR_ANY. */\r
229         struct ibsp_port *port;\r
230 \r
231         enum ibsp_socket_state socket_state;    /* represents current socket state */\r
232 \r
233         union\r
234         {\r
235                 struct\r
236                 {\r
237                         /* Listening socket */\r
238                         unsigned int backlog;   /* Maximum number of pending connections */\r
239                         cl_qlist_t list;        /* list of pending connections */\r
240                         ib_listen_handle_t handle;\r
241                         struct listen_req_param listen_req_param;\r
242                 } listen;\r
243 \r
244                 struct\r
245                 {\r
246                         /* Accepting socket */\r
247                         /* TODO: ib_cm_rep will be blocking with some flags. \r
248                          * Use that instead of this event. */\r
249                         HANDLE event;\r
250                 } accept;\r
251 \r
252                 struct\r
253                 {\r
254                         HANDLE event;\r
255                 } connect;\r
256 \r
257                 struct\r
258                 {\r
259                         HANDLE event;\r
260                 } disconnect;\r
261 \r
262         }       info;\r
263 \r
264         /* Variables associated with IBSPSelectEvent */\r
265         WSAEVENT event_select;          /* Handle to Event Object */\r
266         long event_mask;                        /* Events we care about */\r
267         long network_events;            /* Events that happenned */\r
268         int errno_connect;                      /* errno code (if any) returned by connect */\r
269 \r
270         struct ibsp_socket_options socket_options;      /* Socket Options */\r
271 \r
272         /* Infiniband ressources */\r
273         ib_pd_handle_t hca_pd;          /* Copy of the HCA PD, for faster access. */\r
274 \r
275         /* Pointer to completion queue and thread assigned to this socket */\r
276         struct cq_thread_info *cq_tinfo;\r
277 \r
278         ib_qp_handle_t          qp;\r
279         uint32_t                        max_inline;\r
280 \r
281         /* State on the QP. This is only valid when the socket state is IBSP_CONNECTED.\r
282          *   0  : good\r
283          *   <0 : an error occurred, contains a windoes error *ie WSAExxxx\r
284          *   -1 : disconected, for duplication process.\r
285          */\r
286         int qp_error;\r
287 \r
288         /* Send request processing. */\r
289         cl_spinlock_t   send_lock;\r
290         ib_send_opt_t   send_opt;\r
291         struct _wr              send_wr[QP_ATTRIB_SQ_DEPTH];\r
292         uint8_t                 send_idx;\r
293         atomic32_t              send_cnt;\r
294 \r
295         /* Receive request processing. */\r
296         cl_spinlock_t   recv_lock;\r
297         struct _recv_wr recv_wr[QP_ATTRIB_RQ_DEPTH];\r
298         uint8_t                 recv_idx;\r
299         atomic32_t              recv_cnt;\r
300 \r
301 #ifdef _DEBUG_\r
302         atomic32_t              send_comp;\r
303         atomic32_t              recv_comp;\r
304 #endif\r
305 \r
306         struct _recv_wr dup_wr[QP_ATTRIB_RQ_DEPTH];\r
307         uint8_t                 dup_idx;\r
308         atomic32_t              dup_cnt;\r
309 \r
310         /* Memory management. \r
311          * From what I saw, the regions registered through IBSPRegisterMemory will \r
312          * only be used by this socket. And there will be only one registration for \r
313          * send buffers and one for receive buffers for the whole life of the socket. \r
314          * Thus these won't be cached. A later optimization would be not to release \r
315          * those regions, but to store them in the HCA structure in case another socket\r
316          * binds the same area again. */\r
317         struct mr_list buf_mem_list;\r
318 \r
319         /* Stuff for socket duplication */\r
320         struct\r
321         {\r
322                 HANDLE mmap_handle;\r
323                 DWORD identifier;               /* Unique identifier */\r
324                 DWORD dwProcessId;\r
325         } duplicate;\r
326 };\r
327 \r
328 \r
329 inline void\r
330 ibsp_css(\r
331                                         char                                            *calling_func,\r
332                                         int                                                     line,\r
333                                         struct ibsp_socket_info         *s,\r
334                                         enum ibsp_socket_state          new_state )\r
335 {\r
336         enum ibsp_socket_state old_state;\r
337 \r
338         UNUSED_PARAM( calling_func );\r
339         UNUSED_PARAM( line );\r
340 \r
341         old_state = s->socket_state;\r
342 \r
343         if( old_state == new_state )\r
344         {\r
345                 /* Nothing to change */\r
346                 return;\r
347         }\r
348 \r
349         /* IBSP_CLOSED is a dead end state */\r
350         if( old_state == IBSP_CLOSED )\r
351         {\r
352                 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
353                 return;\r
354         }\r
355 \r
356         /* \r
357          * Once in IBSP_CLOSING state, the only allowed new state\r
358          * is IBSP_CLOSING.\r
359          */\r
360         if( (old_state == IBSP_CLOSING) && (new_state != IBSP_CLOSED) )\r
361         {\r
362                 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
363                 return;\r
364         }\r
365 \r
366         fzprint(("%s():0x%x:0x%x: socket=0x%p %s to %s, called by %s():%d\n", __FUNCTION__,\r
367                          GetCurrentProcessId(),\r
368                          GetCurrentThreadId(), s,\r
369                          IBSP_SOCKET_STATE_STR(old_state),\r
370                          IBSP_SOCKET_STATE_STR(new_state), calling_func, line));\r
371 \r
372         s->socket_state = new_state;\r
373 }\r
374 \r
375 #define IBSP_CHANGE_SOCKET_STATE(socket_info, new_state) \\r
376         ibsp_css(__FUNCTION__, __LINE__, socket_info, new_state)\r
377 \r
378 \r
379 /*--------------------------------------------------------------------------*/\r
380 \r
381 /* Describes an IP address */\r
382 struct ibsp_ip_addr\r
383 {\r
384         cl_fmap_item_t          item;                   /* next IP for that port */\r
385 \r
386         struct ibsp_port        *p_port;                /* port that owns this IP address */\r
387         struct in_addr          ip_addr;                /* IPv4 address */\r
388 };\r
389 \r
390 /* describes a port */\r
391 struct ibsp_port\r
392 {\r
393         cl_list_item_t item;\r
394         cl_spinlock_t mutex;\r
395 \r
396         struct ibsp_hca *hca;           /* HCA to which this port belong. */\r
397 \r
398         ib_net64_t guid;\r
399         uint8_t port_num;\r
400 };\r
401 \r
402 /* Describes a hca */\r
403 struct ibsp_hca\r
404 {\r
405         cl_list_item_t item;\r
406 \r
407         ib_net64_t guid;\r
408         uint16_t        dev_id; /* Device ID to selectively cap MTU to 1K for Tavor. */\r
409         ib_ca_handle_t hca_handle;\r
410 \r
411         ib_pd_handle_t pd;\r
412 \r
413         /* Memory management */\r
414         struct mr_list rdma_mem_list;   /* Regions registered through IBSPRegisterRdmaMemory */\r
415 \r
416         cl_spinlock_t   port_lock;\r
417         cl_qlist_t              port_list;\r
418 \r
419         /* TODO: Make this a dynamic list if we need more than one cq_tinfo per HCA */\r
420         struct cq_thread_info *cq_tinfo;\r
421 };\r
422 \r
423 /* There is only one instance of that structure. */\r
424 struct ibspdll_globals\r
425 {\r
426         /* Special values. Keep first and in this order. These are not reset\r
427          * between WSAStartupEx and WSACleanup calls. */\r
428         cl_spinlock_t mutex;\r
429         UINT entry_count;\r
430 \r
431         /* Provider */\r
432         WSPUPCALLTABLEEX up_call_table; /* MUST keep afetr entry_count */\r
433         HANDLE heap;\r
434         cl_qlist_t socket_info_list;    /* List of all the created sockets */\r
435         cl_rbmap_t conn_map;    /* rb tree of all connections to ensure unique 4-tuple */\r
436         cl_spinlock_t socket_info_mutex;\r
437 \r
438         cl_qlist_t closed_socket_info_list;     /* List of sockets in IBSP_CLOSED state */\r
439         cl_spinlock_t closed_socket_info_mutex;\r
440 \r
441         WSAPROTOCOL_INFOW protocol_info;\r
442 \r
443         /* Infiniband */\r
444         ib_al_handle_t al_handle;\r
445         ib_pnp_handle_t pnp_handle_ca;\r
446         ib_pnp_handle_t pnp_handle_port;\r
447 \r
448         cl_qlist_t hca_list;\r
449         cl_spinlock_t hca_mutex;\r
450 \r
451         cl_fmap_t               ip_map;                 /* list of all IP addresses supported by all the ports. */\r
452         cl_spinlock_t   ip_mutex;\r
453 \r
454         /* IB resource cleanup thread */\r
455         HANDLE ib_cleanup_thread;\r
456         HANDLE ib_cleanup_event;\r
457         BOOL ib_cleanup_thread_exit_wanted;\r
458 \r
459 #ifdef _DEBUG_\r
460         /* Statistics */\r
461         atomic32_t qp_num;\r
462         atomic32_t cq_num;\r
463         atomic32_t pd_num;\r
464         atomic32_t al_num;\r
465         atomic32_t mr_num;\r
466         atomic32_t ca_num;\r
467         atomic32_t listen_num;\r
468         atomic32_t pnp_num;\r
469         atomic32_t thread_num;\r
470         atomic32_t wpusocket_num;\r
471 \r
472         atomic32_t overlap_h0_count;\r
473         atomic32_t overlap_h1_comp_count;\r
474         atomic32_t overlap_h1_count;\r
475         atomic32_t max_comp_count;\r
476         atomic32_t send_count;\r
477         atomic32_t recv_count;\r
478         atomic32_t CloseSocket_count;\r
479 #endif\r
480 };\r