Remove stale HPC Pack 2008 Beta 1 objects
[mirror/winof/.git] / ulp / nd / user / NdListen.cpp
1 /*\r
2  * Copyright (c) 2008 Microsoft Corporation.  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 "NdListen.h"\r
33 #include "NdAdapter.h"\r
34 #include "NdEndpoint.h"\r
35 #include "NdConnector.h"\r
36 #include "al_dev.h"\r
37 #pragma warning( push, 3 )\r
38 #include "winternl.h"\r
39 #pragma warning( pop )\r
40 #include <complib/cl_byteswap.h>\r
41 #include <limits.h>\r
42 #include "nddebug.h"\r
43 \r
44 #if defined(EVENT_TRACING)\r
45 #ifdef offsetof\r
46 #undef offsetof\r
47 #endif\r
48 #include "NdListen.tmh"\r
49 #endif\r
50 \r
51 namespace NetworkDirect\r
52 {\r
53 \r
54 HRESULT GetPdataForPassive(\r
55     __in UINT8* pSrc,\r
56     __in SIZE_T SrcLength,\r
57     __out_bcount_part_opt(*pPrivateDataLength, *pPrivateDataLength) void* pPrivateData,\r
58     __inout SIZE_T* pPrivateDataLength\r
59     )\r
60 {\r
61     if( SrcLength != IB_REQ_PDATA_SIZE )\r
62     {\r
63         ND_PRINT( TRACE_LEVEL_ERROR, ND_DBG_NDI, \r
64             ("Connection aborted: incorrect pdata_len %d \n", (int)SrcLength ));\r
65         return ND_CONNECTION_ABORTED;\r
66     }\r
67 \r
68     if( pPrivateDataLength == NULL )\r
69         return S_OK;\r
70 \r
71     ib_cm_rdma_req_t* pIpData = (ib_cm_rdma_req_t*)pSrc;\r
72     CL_ASSERT( pIpData->maj_min_ver == 0 );\r
73     CL_ASSERT( pIpData->ipv == 0x40 || pIpData->ipv == 0x60 );\r
74 \r
75     if( *pPrivateDataLength == 0 )\r
76     {\r
77         *pPrivateDataLength = sizeof(pIpData->pdata);\r
78         return ND_BUFFER_OVERFLOW;\r
79     }\r
80 \r
81     CopyMemory(\r
82         pPrivateData,\r
83         pIpData->pdata,\r
84         min( *pPrivateDataLength, sizeof(pIpData->pdata) )\r
85         );\r
86 \r
87     HRESULT hr;\r
88     if( *pPrivateDataLength < sizeof(pIpData->pdata) )\r
89     {\r
90         hr = ND_BUFFER_OVERFLOW;\r
91     }\r
92     else\r
93     {\r
94         hr = S_OK;\r
95     }\r
96 \r
97     *pPrivateDataLength = sizeof(pIpData->pdata);\r
98     return hr;\r
99 }\r
100 \r
101 HRESULT GetPdataForActive(\r
102     __in UINT8* pSrc,\r
103     __in SIZE_T SrcLength,\r
104     __out_bcount_part_opt(*pPrivateDataLength, *pPrivateDataLength) void* pPrivateData,\r
105     __inout SIZE_T* pPrivateDataLength\r
106     )\r
107 {\r
108     if( pPrivateDataLength == NULL )\r
109         return S_OK;\r
110 \r
111     if( *pPrivateDataLength == 0 )\r
112     {\r
113         *pPrivateDataLength = SrcLength;\r
114         return ND_BUFFER_OVERFLOW;\r
115     }\r
116 \r
117     CopyMemory(\r
118         pPrivateData,\r
119         pSrc,\r
120         min( *pPrivateDataLength, SrcLength ) );\r
121 \r
122     HRESULT hr;\r
123     if( *pPrivateDataLength < IB_REJ_PDATA_SIZE )\r
124     {\r
125         hr = ND_BUFFER_OVERFLOW;\r
126     }\r
127     else\r
128     {\r
129         hr = S_OK;\r
130     }\r
131 \r
132     *pPrivateDataLength = SrcLength;\r
133     return hr;\r
134 }\r
135 \r
136     CListen::CListen(void) :\r
137         m_nRef( 1 ),\r
138         m_pParent( NULL ),\r
139         m_cid( 0 )\r
140     {\r
141     }\r
142 \r
143     CListen::~CListen(void)\r
144     {\r
145         if( m_cid != 0 )\r
146         {\r
147             DWORD bytes_ret;\r
148             DeviceIoControl(\r
149                 m_pParent->m_hSync,\r
150                 UAL_DESTROY_CEP,\r
151                 &m_cid,\r
152                 sizeof(m_cid),\r
153                 NULL,\r
154                 0,\r
155                 &bytes_ret,\r
156                 NULL );\r
157         }\r
158 \r
159         if( m_pParent )\r
160             m_pParent->Release();\r
161     }\r
162 \r
163     HRESULT CListen::Initialize(\r
164         __in CAdapter* pParent,\r
165         __in SIZE_T Backlog,\r
166         __in INT Protocol,\r
167         __in USHORT Port,\r
168         __out_opt USHORT* pAssignedPort\r
169         )\r
170     {\r
171         ND_ENTER( ND_DBG_NDI );\r
172 \r
173         m_pParent = pParent;\r
174         m_pParent->AddRef();\r
175 \r
176         UNREFERENCED_PARAMETER( Backlog );\r
177 \r
178         if( Port == 0 && pAssignedPort == NULL )\r
179             return ND_INVALID_PARAMETER_MIX;\r
180 \r
181         //\r
182         // IP Addressing Annex only supports a single byte for protocol.\r
183         //\r
184         if( Protocol > UCHAR_MAX || Protocol < 0 )\r
185             return ND_INVALID_PARAMETER_3;\r
186 \r
187         ual_cep_listen_ioctl_t listen;\r
188         listen.cid = 0;\r
189 \r
190         listen.cep_listen.svc_id = \r
191             0x0000000001000000 | Protocol << 16 | Port;\r
192 \r
193         listen.cep_listen.port_guid = m_pParent->m_PortGuid;\r
194 \r
195         switch( m_pParent->m_Addr.v4.sin_family )\r
196         {\r
197         case AF_INET:\r
198             ZeroMemory( listen.compare, ATS_IPV4_OFFSET );\r
199             CopyMemory( &listen.compare[ATS_IPV4_OFFSET],\r
200                 (uint8_t*)&m_pParent->m_Addr.v4.sin_addr,\r
201                 sizeof(m_pParent->m_Addr.v4.sin_addr) );\r
202             ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
203                 ("Listen for: IP %#x, port %#hx\n", \r
204                 cl_hton32(m_pParent->m_Addr.v4.sin_addr.S_un.S_addr), cl_hton16(m_pParent->m_Addr.v4.sin_port) ) );\r
205             break;\r
206         case AF_INET6:\r
207             CopyMemory( listen.compare,\r
208                 (uint8_t*)&m_pParent->m_Addr.v6.sin6_addr,\r
209                 sizeof(m_pParent->m_Addr.v6.sin6_addr) );\r
210             break;\r
211         }\r
212         listen.cep_listen.p_cmp_buf = listen.compare;\r
213         listen.cep_listen.cmp_len = 16;\r
214         listen.cep_listen.cmp_offset = FIELD_OFFSET( ib_cm_rdma_req_t, dst_ip_addr );\r
215 \r
216         IO_STATUS_BLOCK IoStatus;\r
217         IoStatus.Status = NtDeviceIoControlFile(\r
218             m_pParent->m_hSync,\r
219             NULL,\r
220             NULL,\r
221             NULL,\r
222             &IoStatus,\r
223             UAL_NDI_LISTEN_CM,\r
224             &listen,\r
225             sizeof(listen),\r
226             &m_cid,\r
227             sizeof(m_cid) );\r
228 \r
229         switch( IoStatus.Status )\r
230         {\r
231         case ND_SUCCESS:\r
232             ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
233                 ("Listen for: Guid %#I64x, sid %#I64x\n", \r
234                 m_pParent->m_PortGuid, listen.cep_listen.svc_id ) );\r
235             break;\r
236 \r
237         case IB_INVALID_SETTING:\r
238             return ND_ADDRESS_ALREADY_EXISTS;\r
239 \r
240         default:\r
241             return IoStatus.Status;\r
242         }\r
243 \r
244         ND_PRINT( TRACE_LEVEL_INFORMATION, ND_DBG_NDI,\r
245             ("Created listen CEP with cid %d \n", m_cid ) );\r
246 \r
247         // TODO: Come up with something better for port number.\r
248         if( Port == 0 )\r
249             Port = (USHORT)m_cid | (USHORT)(m_cid >> 16);\r
250 \r
251         if( pAssignedPort )\r
252             *pAssignedPort = Port;\r
253 \r
254         m_Protocol = (UINT8)Protocol;\r
255         return S_OK;\r
256     }\r
257 \r
258     HRESULT CListen::Create(\r
259         __in CAdapter* pParent,\r
260         __in SIZE_T Backlog,\r
261         __in INT Protocol,\r
262         __in USHORT Port,\r
263         __out_opt USHORT* pAssignedPort,\r
264         __deref_out INDListen** ppListen\r
265         )\r
266     {\r
267         CListen* pListen = new CListen();\r
268         if( pListen == NULL )\r
269             return ND_NO_MEMORY;\r
270 \r
271         HRESULT hr = pListen->Initialize(\r
272             pParent,\r
273             Backlog,\r
274             Protocol,\r
275             Port,\r
276             pAssignedPort );\r
277         if( FAILED( hr ) )\r
278         {\r
279             delete pListen;\r
280             return hr;\r
281         }\r
282 \r
283         *ppListen = pListen;\r
284         return S_OK;\r
285     }\r
286 \r
287     // *** IUnknown methods ***\r
288     HRESULT CListen::QueryInterface(\r
289         REFIID riid,\r
290         LPVOID FAR* ppvObj\r
291         )\r
292     {\r
293         if( IsEqualIID( riid, IID_IUnknown ) )\r
294         {\r
295             *ppvObj = this;\r
296             return S_OK;\r
297         }\r
298 \r
299         if( IsEqualIID( riid, IID_INDListen ) )\r
300         {\r
301             *ppvObj = this;\r
302             return S_OK;\r
303         }\r
304 \r
305         return E_NOINTERFACE;\r
306     }\r
307 \r
308     ULONG CListen::AddRef(void)\r
309     {\r
310         return InterlockedIncrement( &m_nRef );\r
311     }\r
312 \r
313     ULONG CListen::Release(void)\r
314     {\r
315         ULONG ref = InterlockedDecrement( &m_nRef );\r
316         if( ref == 0 )\r
317             delete this;\r
318 \r
319         return ref;\r
320     }\r
321 \r
322     // *** INDOverlapped methods ***\r
323     HRESULT CListen::CancelOverlappedRequests(void)\r
324     {\r
325         ND_ENTER( ND_DBG_NDI );\r
326 \r
327         DWORD bytes_ret;\r
328         BOOL ret = DeviceIoControl(\r
329             m_pParent->m_hSync,\r
330             UAL_NDI_CANCEL_CM_IRPS,\r
331             &m_cid,\r
332             sizeof(m_cid),\r
333             NULL,\r
334             0,\r
335             &bytes_ret,\r
336             NULL );\r
337 \r
338         if( ret )\r
339             return S_OK;\r
340         else\r
341             return ND_UNSUCCESSFUL;\r
342     }\r
343 \r
344     HRESULT CListen::GetOverlappedResult(\r
345         __inout OVERLAPPED *pOverlapped,\r
346         __out SIZE_T *pNumberOfBytesTransferred,\r
347         __in BOOL bWait\r
348         )\r
349     {\r
350         ND_ENTER( ND_DBG_NDI );\r
351 \r
352         *pNumberOfBytesTransferred = 0;\r
353         ::GetOverlappedResult(\r
354             m_pParent->GetFileHandle(),\r
355             pOverlapped,\r
356             (DWORD*)pNumberOfBytesTransferred,\r
357             bWait );\r
358         return (HRESULT)pOverlapped->Internal;\r
359     }\r
360 \r
361     // *** INDListen methods ***\r
362     HRESULT CListen::GetConnectionRequest(\r
363         __inout INDConnector* pConnector,\r
364         __inout OVERLAPPED* pOverlapped\r
365         )\r
366     {\r
367         ND_ENTER( ND_DBG_NDI );\r
368 \r
369         static_cast<CConnector*>(pConnector)->m_Protocol = m_Protocol;\r
370 \r
371         pOverlapped->Internal = ND_PENDING;\r
372         return NtDeviceIoControlFile(\r
373             m_pParent->GetFileHandle(),\r
374             pOverlapped->hEvent,\r
375             NULL,\r
376             (ULONG_PTR)pOverlapped->hEvent & 1 ? NULL : pOverlapped,\r
377             (IO_STATUS_BLOCK*)&pOverlapped->Internal,\r
378             UAL_NDI_GET_REQ_CM,\r
379             &m_cid,\r
380             sizeof(m_cid),\r
381             &static_cast<CConnector*>(pConnector)->m_cid,\r
382             sizeof(static_cast<CConnector*>(pConnector)->m_cid) );\r
383     }\r
384 \r
385 } // namespace\r