e5d79acdecba9bc0b6222e8d74643fefc0c207f0
[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_spinlock.h>\r
35 #include <complib/cl_debug.h>\r
36 \r
37 \r
38 enum ibsp_socket_state\r
39 {\r
40         IBSP_CREATE = 0,\r
41         IBSP_BIND,\r
42         IBSP_CONNECT,\r
43         IBSP_LISTEN,\r
44         IBSP_ACCEPT,\r
45         IBSP_CONNECTED,\r
46         IBSP_DUPLICATING_OLD,           /* duplicating socket on the original controlling process */\r
47         IBSP_DUPLICATING_NEW,           /* duplicating socket on the new controlling process */\r
48         IBSP_DUPLICATING_REMOTE,        /* duplicating socket on the remote side */\r
49         IBSP_DISCONNECTED,\r
50         IBSP_CLOSING,\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         /* For future growth if the hca needs a list of cqs */\r
187         cl_list_item_t item;\r
188 \r
189         cl_waitobj_handle_t cq_waitobj;\r
190         ib_cq_handle_t cq;\r
191 \r
192         cl_spinlock_t wr_mutex;\r
193         cl_qlist_t done_wr_list;\r
194 \r
195         /* Number of qp's using this cq */\r
196         atomic32_t qp_count;\r
197 \r
198         /* Current cqe size */\r
199         uint32_t cqe_size;\r
200 \r
201         HANDLE ib_cq_thread;\r
202         DWORD   ib_cq_thread_id;\r
203         BOOL ib_cq_thread_exit_wanted;\r
204 \r
205         struct ibsp_hca *hca;           /* HCA to which this cq belongs. */\r
206 };\r
207 \r
208 /* Structure representing the context information stored for each\r
209  * socket created */\r
210 struct ibsp_socket_info\r
211 {\r
212         cl_list_item_t item;            /* Link to next SOCKET_INFO in the global list */\r
213         cl_spinlock_t mutex;            /* protect this structure */\r
214 \r
215         /* Switch socket handle created by WPUCreateSocketHandle. */\r
216         SOCKET switch_socket;\r
217 \r
218         /* IP address and port this socket is bound to. Set by WSPBind */\r
219         struct sockaddr_in local_addr;\r
220 \r
221         /* Remote address of peer entity after connect/accept is complete */\r
222         struct sockaddr_in peer_addr;\r
223 \r
224         /* Back pointer to the port to which this socket is\r
225          * bound. It is NULL until the socket is bound, except if the listen\r
226          * binds to INADDR_ANY. */\r
227         struct ibsp_port *port;\r
228 \r
229         enum ibsp_socket_state socket_state;    /* represents current socket state */\r
230 \r
231         union\r
232         {\r
233                 struct\r
234                 {\r
235                         /* Listening socket */\r
236                         unsigned int backlog;   /* Maximum number of pending connections */\r
237                         cl_qlist_t list;        /* list of pending connections */\r
238                         ib_listen_handle_t handle;\r
239                         struct listen_req_param listen_req_param;\r
240                 } listen;\r
241 \r
242                 struct\r
243                 {\r
244                         /* Accepting socket */\r
245                         /* TODO: ib_cm_rep will be blocking with some flags. \r
246                          * Use that instead of this event. */\r
247                         HANDLE event;\r
248                 } accept;\r
249 \r
250                 struct\r
251                 {\r
252                         HANDLE event;\r
253                 } connect;\r
254 \r
255                 struct\r
256                 {\r
257                         HANDLE event;\r
258                 } disconnect;\r
259 \r
260         }       info;\r
261 \r
262         /* Variables associated with IBSPSelectEvent */\r
263         WSAEVENT event_select;          /* Handle to Event Object */\r
264         long event_mask;                        /* Events we care about */\r
265         long network_events;            /* Events that happenned */\r
266         int errno_connect;                      /* errno code (if any) returned by connect */\r
267 \r
268         struct ibsp_socket_options socket_options;      /* Socket Options */\r
269 \r
270         /* Infiniband ressources */\r
271         ib_pd_handle_t hca_pd;          /* Copy of the HCA PD, for faster access. */\r
272 \r
273         /* Pointer to completion queue and thread assigned to this socket */\r
274         struct cq_thread_info *cq_tinfo;\r
275 \r
276         ib_qp_handle_t          qp;\r
277         uint32_t                        max_inline;\r
278 \r
279         /* State on the QP. This is only valid when the socket state is IBSP_CONNECTED.\r
280          *   0  : good\r
281          *   <0 : an error occurred, contains a windoes error *ie WSAExxxx\r
282          *   -1 : disconected, for duplication process.\r
283          */\r
284         int qp_error;\r
285 \r
286         /* Send request processing. */\r
287         cl_spinlock_t   send_lock;\r
288         ib_send_opt_t   send_opt;\r
289         struct _wr              send_wr[QP_ATTRIB_SQ_DEPTH];\r
290         uint8_t                 send_idx;\r
291         atomic32_t              send_cnt;\r
292 \r
293         /* Receive request processing. */\r
294         cl_spinlock_t   recv_lock;\r
295         struct _recv_wr recv_wr[QP_ATTRIB_RQ_DEPTH];\r
296         uint8_t                 recv_idx;\r
297         atomic32_t              recv_cnt;\r
298 \r
299 #ifdef _DEBUG_\r
300         atomic32_t              send_comp;\r
301         atomic32_t              recv_comp;\r
302 #endif\r
303 \r
304         struct _recv_wr dup_wr[QP_ATTRIB_RQ_DEPTH];\r
305         uint8_t                 dup_idx;\r
306         atomic32_t              dup_cnt;\r
307 \r
308         /* Memory management. \r
309          * From what I saw, the regions registered through IBSPRegisterMemory will \r
310          * only be used by this socket. And there will be only one registration for \r
311          * send buffers and one for receive buffers for the whole life of the socket. \r
312          * Thus these won't be cached. A later optimization would be not to release \r
313          * those regions, but to store them in the HCA structure in case another socket\r
314          * binds the same area again. */\r
315         struct mr_list buf_mem_list;\r
316 \r
317         /* Stuff for socket duplication */\r
318         struct\r
319         {\r
320                 HANDLE mmap_handle;\r
321                 DWORD identifier;               /* Unique identifier */\r
322                 DWORD dwProcessId;\r
323         } duplicate;\r
324 };\r
325 \r
326 \r
327 inline void\r
328 ibsp_css(\r
329                                         char                                            *calling_func,\r
330                                         int                                                     line,\r
331                                         struct ibsp_socket_info         *s,\r
332                                         enum ibsp_socket_state          new_state )\r
333 {\r
334         enum ibsp_socket_state old_state;\r
335 \r
336         UNUSED_PARAM( calling_func );\r
337         UNUSED_PARAM( line );\r
338 \r
339         old_state = s->socket_state;\r
340 \r
341         if( old_state == new_state )\r
342         {\r
343                 /* Nothing to change */\r
344                 return;\r
345         }\r
346 \r
347         /* IBSP_CLOSED is a dead end state */\r
348         if( old_state == IBSP_CLOSED )\r
349         {\r
350                 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
351                 return;\r
352         }\r
353 \r
354         /* \r
355          * Once in IBSP_CLOSING state, the only allowed new state\r
356          * is IBSP_CLOSING.\r
357          */\r
358         if( (old_state == IBSP_CLOSING) && (new_state != IBSP_CLOSED) )\r
359         {\r
360                 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
361                 return;\r
362         }\r
363 \r
364         fzprint(("%s():0x%x:0x%x: socket=0x%p %s to %s, called by %s():%d\n", __FUNCTION__,\r
365                          GetCurrentProcessId(),\r
366                          GetCurrentThreadId(), s,\r
367                          IBSP_SOCKET_STATE_STR(old_state),\r
368                          IBSP_SOCKET_STATE_STR(new_state), calling_func, line));\r
369 \r
370         s->socket_state = new_state;\r
371 }\r
372 \r
373 #define IBSP_CHANGE_SOCKET_STATE(socket_info, new_state) \\r
374         ibsp_css(__FUNCTION__, __LINE__, socket_info, new_state)\r
375 \r
376 \r
377 /*--------------------------------------------------------------------------*/\r
378 \r
379 /* Describes an IP address */\r
380 struct ibsp_ip_addr\r
381 {\r
382         cl_fmap_item_t          item;                   /* next IP for that port */\r
383 \r
384         struct ibsp_port        *p_port;                /* port that owns this IP address */\r
385         struct in_addr          ip_addr;                /* IPv4 address */\r
386 };\r
387 \r
388 /* describes a port */\r
389 struct ibsp_port\r
390 {\r
391         cl_list_item_t item;\r
392         cl_spinlock_t mutex;\r
393 \r
394         struct ibsp_hca *hca;           /* HCA to which this port belong. */\r
395 \r
396         ib_net64_t guid;\r
397         uint8_t port_num;\r
398 };\r
399 \r
400 /* Describes a hca */\r
401 struct ibsp_hca\r
402 {\r
403         cl_list_item_t item;\r
404 \r
405         ib_net64_t guid;\r
406         uint16_t        dev_id; /* Device ID to selectively cap MTU to 1K for Tavor. */\r
407         ib_ca_handle_t hca_handle;\r
408 \r
409         ib_pd_handle_t pd;\r
410 \r
411         /* Memory management */\r
412         struct mr_list rdma_mem_list;   /* Regions registered through IBSPRegisterRdmaMemory */\r
413 \r
414         cl_spinlock_t   port_lock;\r
415         cl_qlist_t              port_list;\r
416 \r
417         /* TODO: Make this a dynamic list if we need more than one cq_tinfo per HCA */\r
418         struct cq_thread_info *cq_tinfo;\r
419 };\r
420 \r
421 /* There is only one instance of that structure. */\r
422 struct ibspdll_globals\r
423 {\r
424         /* Special values. Keep first and in this order. These are not reset\r
425          * between WSAStartupEx and WSACleanup calls. */\r
426         cl_spinlock_t mutex;\r
427         UINT entry_count;\r
428 \r
429         /* Provider */\r
430         WSPUPCALLTABLEEX up_call_table; /* MUST keep afetr entry_count */\r
431         HANDLE heap;\r
432         cl_qlist_t socket_info_list;    /* List of all the created sockets */\r
433         cl_spinlock_t socket_info_mutex;\r
434 \r
435         cl_qlist_t closed_socket_info_list;     /* List of sockets in IBSP_CLOSED state */\r
436         cl_spinlock_t closed_socket_info_mutex;\r
437 \r
438         WSAPROTOCOL_INFOW protocol_info;\r
439 \r
440         /* Infiniband */\r
441         ib_al_handle_t al_handle;\r
442         ib_pnp_handle_t pnp_handle_ca;\r
443         ib_pnp_handle_t pnp_handle_port;\r
444 \r
445         cl_qlist_t hca_list;\r
446         cl_spinlock_t hca_mutex;\r
447 \r
448         cl_fmap_t               ip_map;                 /* list of all IP addresses supported by all the ports. */\r
449         cl_spinlock_t   ip_mutex;\r
450 \r
451         /* IB resource cleanup thread */\r
452         HANDLE ib_cleanup_thread;\r
453         HANDLE ib_cleanup_event;\r
454         BOOL ib_cleanup_thread_exit_wanted;\r
455 \r
456 #ifdef _DEBUG_\r
457         /* Statistics */\r
458         atomic32_t qp_num;\r
459         atomic32_t cq_num;\r
460         atomic32_t pd_num;\r
461         atomic32_t al_num;\r
462         atomic32_t mr_num;\r
463         atomic32_t ca_num;\r
464         atomic32_t listen_num;\r
465         atomic32_t pnp_num;\r
466         atomic32_t thread_num;\r
467         atomic32_t wpusocket_num;\r
468 \r
469         atomic32_t overlap_h0_count;\r
470         atomic32_t overlap_h1_comp_count;\r
471         atomic32_t overlap_h1_count;\r
472         atomic32_t max_comp_count;\r
473         atomic32_t send_count;\r
474         atomic32_t recv_count;\r
475         atomic32_t CloseSocket_count;\r
476 #endif\r
477 };\r