+++ /dev/null
-dirs = \\r
-kernel \\r
-tests \\r
-\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-/*\r
- This file includes two classes: One is used as a full refcount implmentation.\r
-\r
- The second class is only the ref count interface. It should be used by abstract \r
- classes.\r
- \r
-*/\r
-\r
-\r
-class RefCountImpl {\r
-public :\r
-\r
- RefCountImpl() {\r
- m_ref = 1;\r
- }\r
-\r
- ULONG AddRef(void) {\r
- ASSERT(m_ref > 0); \r
- LONG result = InterlockedIncrement(&m_ref);\r
- return (ULONG)result;\r
- }\r
-\r
- ULONG Release(void) { \r
- ASSERT(m_ref > 0);\r
- LONG result = InterlockedDecrement(&m_ref);\r
- if ( result == 0 ) {\r
- delete this;\r
- }\r
- return (ULONG)result; \r
- }\r
-\r
- virtual ~RefCountImpl() {};\r
-private :\r
- long m_ref;\r
-};\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-#ifndef _SDP_SHARED_H\r
-#define _SDP_SHARED_H\r
-\r
-#define ProviderName L"SdpDriver"\r
-\r
-#define SDP_DEVICE_NAME L"\\Device\\"ProviderName\r
-#define SDP_LINK_NAME L"\\DosDevices\\Global\\"ProviderName\r
-#define SDP_WIN32_NAME L"\\\\.\\"ProviderName\r
-\r
-// Define the IOCTL codes that will be used for sending the requests down\r
-\r
-#define IOCTL_WSP_SOCKET CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED ,FILE_ANY_ACCESS)\r
-#define IOCTL_WSP_CONNECT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED ,FILE_ANY_ACCESS)\r
-#define IOCTL_WSP_SEND CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED ,FILE_ANY_ACCESS)\r
-#define IOCTL_WSP_RECV CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED ,FILE_ANY_ACCESS)\r
-#define IOCTL_WSP_BIND CTL_CODE(FILE_DEVICE_UNKNOWN, 0x805, METHOD_BUFFERED ,FILE_ANY_ACCESS)\r
-#define IOCTL_WSP_LISTEN CTL_CODE(FILE_DEVICE_UNKNOWN, 0x806, METHOD_BUFFERED ,FILE_ANY_ACCESS)\r
-#define IOCTL_WSP_ACCEPT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x807, METHOD_BUFFERED ,FILE_ANY_ACCESS)\r
-#define IOCTL_WSP_GET_XXX_NAME CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED ,FILE_ANY_ACCESS)\r
-#define IOCTL_WSP_CLOSE_SOCKET CTL_CODE(FILE_DEVICE_UNKNOWN, 0x809, METHOD_BUFFERED ,FILE_ANY_ACCESS)\r
-#define IOCTL_WSP_USER_THREAD CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80A, METHOD_BUFFERED ,FILE_ANY_ACCESS)\r
-\r
-\r
-// Data structures that are used for connect\r
-struct WspSocketIn {\r
- ULONG dwFlags;\r
-};\r
-\r
-struct WspSocketOut {\r
- int Errno;\r
- VOID *pSocket;\r
-};\r
-\r
-const int MAC_ADDR_SIZE = 6;\r
-typedef char MAC_ADDR[MAC_ADDR_SIZE] ;\r
-\r
-struct WspConnectIn {\r
- VOID *pSocket;\r
- ULONG SrcIP;\r
- MAC_ADDR DestMac;\r
- ULONG DestIP;\r
- USHORT DestPort;\r
-};\r
-\r
-struct WspConnectOut {\r
- int Errno;\r
-};\r
-\r
-struct WspSendIn {\r
- VOID *pSocket;\r
- CHAR *pData;\r
- ULONG BufferSize;\r
- ULONG dwFlags;\r
-};\r
-\r
-struct WspSendOut {\r
- ULONG NumberOfBytesSent;\r
- int Errno;\r
-};\r
-\r
-struct WspRecvIn {\r
- VOID *pSocket;\r
- CHAR *pData;\r
- ULONG BufferSize;\r
- ULONG dwFlags;\r
-};\r
-\r
-struct WspRecvOut {\r
- ULONG NumberOfBytesRecieved;\r
- int Errno;\r
- ULONG dwFlags; \r
-};\r
-\r
-struct WspBindIn {\r
- VOID *pSocket; \r
- ULONG IP;\r
- USHORT Port;\r
-};\r
-\r
-struct WspBindOut {\r
- int Errno;\r
-};\r
-\r
-struct WspListenIn {\r
- VOID *pSocket; \r
- int backlog;\r
-};\r
-\r
-struct WspListenOut {\r
- int Errno;\r
-};\r
-\r
-struct WspAcceptIn {\r
- VOID *pSocket; \r
-};\r
-\r
-struct WspAcceptOut {\r
- int Errno;\r
- VOID *pAccaptedSocket;\r
- ULONG IP;\r
- USHORT Port; \r
-};\r
-\r
-struct WspGetSockXXIn {\r
- VOID *pSocket;\r
- bool LocaleAddress; // Tells if this is used as GetSockName or GetPeerName \r
-};\r
-\r
-struct WspGetSockXXOut {\r
- int Errno;\r
- ULONG IP;\r
- USHORT Port; \r
-};\r
-\r
-struct WspSocketCloseIn {\r
- VOID *pSocket; \r
-};\r
-\r
-struct WspSocketCloseOut {\r
- int Errno;\r
-};\r
-\r
-\r
-\r
-#endif //_SDP_SHARED_H\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-#ifndef _SDP_PRECOMP_\r
-#define _SDP_PRECOMP_\r
-extern "C" {\r
-#include <NTDDK.h>\r
-}\r
-\r
-// External classes declrations\r
-class SdpSocket;\r
-class SdpArp;\r
-\r
-#include "ib_al.h"\r
-#include "..\..\..\inc\iba\ib_at_ioctl.h"\r
-#include "sdpMsgs.h"\r
-#include "SdpGenUtils.h"\r
-#include "SdpTrace.h"\r
-#include "sdpLock.h"\r
-#include "RefCount.h"\r
-#include "SdpBufferPool.h"\r
-#include "SdpUserFile.h"\r
-#include "sdpdriver.h"\r
-#include "SdpShared.h"\r
-#include "SdpRecvPool.h"\r
-#include "SdpConnectionList.h"\r
-#include "SdpSocket.h"\r
-#include "SdpArp.h"\r
-\r
-\r
-#endif // _SDP_PRECOMP_\r
+++ /dev/null
-TARGETNAME=Sdp\r
-TARGETPATH=..\..\..\bin\kernel\obj$(BUILD_ALT_DIR)\r
-TARGETTYPE=DRIVER\r
-\r
-ENABLE_EVENT_TRACING=1\r
-\r
-SOURCES= Sdp.rc \\r
- SdpDriver.cpp \\r
- SdpUserFile.cpp \\r
- SdpGenUtils.cpp \\r
- SdpSocket.cpp \\r
- SdpArp.cpp \\r
- SdpBufferPool.cpp \\r
- SdpRecvPool.cpp \\r
- SdpConnectionList.cpp \\r
- SdpTrace.cpp \r
- \r
-\r
-INCLUDES=..\include;\\r
- ..\..\..\inc;\\r
- ..\..\..\inc\kernel;\\r
- ..\..\..\inc\iba\r
-\r
-C_DEFINES=$(C_DEFINES) -DNDIS_WDM=1 \\r
- -DDEPRECATE_DDK_FUNCTIONS \r
-\r
-TARGETLIBS= \\r
- $(TARGETPATH)\*\complib.lib \\r
- $(TARGETPATH)\*\ibal.lib \\r
-\r
-!if !defined(DDK_TARGET_OS) || "$(DDK_TARGET_OS)"=="Win2K"\r
-#\r
-# The driver is built in the Win2K build environment\r
-# - use the library version of safe strings \r
-#\r
-TARGETLIBS= $(TARGETLIBS) $(DDK_LIB_PATH)\ntstrsafe.lib\r
-!endif\r
-\r
-!IFDEF ENABLE_EVENT_TRACING\r
-\r
-C_DEFINES = $(C_DEFINES) -DEVENT_TRACING\r
-\r
-RUN_WPP= $(SOURCES) -km -dll -ext: .c .cpp .h .C .CPP .H\\r
- -preserveext:.cpp .h\\r
- -func:SDP_PRINT(LEVEL,FLAGS,MSG,...) \r
-!ENDIF\r
-\r
-MSC_WARNING_LEVEL= /W3\r
-\r
-PRECOMPILED_INCLUDE=Precompile.h\r
-PRECOMPILED_PCH=Precompile.pch\r
-PRECOMPILED_CXX=1\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-#include "precompile.h"\r
-\r
-#pragma warning(disable: 4244 ) \r
-\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "SdpArp.tmh"\r
-#endif\r
-\r
-\r
-\r
-NTSTATUS \r
-SdpArp::Init(PDRIVER_OBJECT DriverObject) \r
-{ \r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"Entering");\r
-\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- UNICODE_STRING DevName1;\r
- IO_STATUS_BLOCK ioStatus;\r
- m_DeviceObject = NULL;\r
-\r
- OBJECT_ATTRIBUTES objectAttributes;\r
-\r
- RtlInitUnicodeString( &DevName1, IBAT_DEV_NAME );\r
-\r
- InitializeObjectAttributes( &objectAttributes,\r
- &DevName1,\r
- OBJ_KERNEL_HANDLE,\r
- (HANDLE) NULL,\r
- (PSECURITY_DESCRIPTOR) NULL );\r
-\r
- // Try to open the IPOIB device object\r
- //\r
- // The reason for using ZwOpenFile instead of IoGetDeviceObjectPointer\r
- // is to keep the handle around because the NDISPROT makes an assumption\r
- // that there is no I/O requests between Cleanup and Close requests.\r
- //\r
- rc = ZwOpenFile( &m_FileHandle,\r
- STANDARD_RIGHTS_ALL,\r
- &objectAttributes,\r
- &ioStatus,\r
- 0,\r
- FILE_NON_DIRECTORY_FILE );\r
- if (!NT_SUCCESS( rc )) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_ARP,"ZwOpenFile failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
-\r
- //\r
- // obtain a pointer to the device object for the handle.\r
- //\r
- rc = ObReferenceObjectByHandle(m_FileHandle,\r
- THREAD_ALL_ACCESS,\r
- *IoFileObjectType,\r
- KernelMode,\r
- (PVOID *) &m_FileObject,\r
- NULL );\r
- if (!NT_SUCCESS( rc )) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_ARP,"ObReferenceObjectByHandle failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
-\r
- // This is what we are looking for\r
- m_DeviceObject = IoGetRelatedDeviceObject(m_FileObject);\r
-\r
-Cleanup:\r
- if (!NT_SUCCESS( rc )) {\r
- if (m_FileHandle) {\r
- ZwClose(m_FileHandle);\r
- m_FileHandle = NULL;\r
- }\r
- if (m_FileObject) {\r
- ObDereferenceObject(m_FileObject);\r
- m_FileObject = NULL;\r
- }\r
- } \r
- return rc;\r
-\r
-}\r
-\r
-VOID \r
-SdpArp::Shutdown()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = %p\n", this);\r
- if (m_FileHandle) {\r
- ZwClose(m_FileHandle);\r
- m_FileHandle = NULL;\r
- }\r
- if (m_FileObject) {\r
- ObDereferenceObject(m_FileObject);\r
- m_FileObject = NULL;\r
- }\r
- m_DeviceObject = NULL; // Not valid any more\r
-}\r
-\r
-\r
-NTSTATUS \r
-SdpArp::SourcePortGidFromIP(\r
- IN ULONG SourceAddr, \r
- OUT ib_net64_t *SrcPortGuid,\r
- OUT ib_net64_t *SrcCaGuid\r
- )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET, "IP = %d.%d.%d.%d\n", \r
- (SourceAddr & 0xff000000) >> 24,\r
- (SourceAddr & 0xff0000) >> 16,\r
- (SourceAddr & 0xff00) >> 8 , \r
- SourceAddr & 0xff);\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- KEVENT event;\r
- PIRP irp;\r
- IO_STATUS_BLOCK ioStatus;\r
- char temp [1000]; // BUGBUG: Handle the case of more IPs\r
- \r
- IOCTL_IBAT_PORTS_IN ipoib_ports_in;\r
- IOCTL_IBAT_PORTS_OUT *pipoib_ports_out;\r
- IBAT_PORT_RECORD *ports_records;\r
-\r
- ipoib_ports_in.Version = IBAT_IOCTL_VERSION;\r
-\r
- pipoib_ports_out = (IOCTL_IBAT_PORTS_OUT *)temp;\r
-\r
- ASSERT(m_DeviceObject != NULL);\r
-\r
- KeInitializeEvent(&event, NotificationEvent, FALSE);\r
- irp = IoBuildDeviceIoControlRequest(\r
- IOCTL_IBAT_PORTS ,\r
- m_DeviceObject,\r
- &ipoib_ports_in,\r
- sizeof ipoib_ports_in,\r
- pipoib_ports_out,\r
- sizeof temp,\r
- TRUE,\r
- &event,\r
- &ioStatus\r
- );\r
-\r
- if(NULL == irp) {\r
- rc = STATUS_INSUFFICIENT_RESOURCES;\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_ARP,"IoBuildDeviceIoControlRequest failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
-\r
- rc = IoCallDriver(m_DeviceObject, irp);\r
- if(STATUS_PENDING == rc) {\r
- KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);\r
- }\r
- else {\r
- ioStatus.Status = rc;\r
- }\r
-\r
- if(!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_ARP,"IoCallDriver failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
- if (pipoib_ports_out->Size > sizeof temp) {\r
- // The number of bytes that we have allocated wasn't enough\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_ARP,"pipoib_ports_out.Size = %d\n", pipoib_ports_out->Size );\r
- rc = STATUS_INSUFFICIENT_RESOURCES;\r
- goto Cleanup;\r
- // BUGBUG: We should try again, with a bigger buffer\r
- }\r
-\r
- rc = SourcePortGidFromPorts(SourceAddr, pipoib_ports_out, SrcPortGuid, SrcCaGuid);\r
- if(!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_ARP,"SourcePortGidFromPorts failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
-\r
-Cleanup:\r
- return rc;\r
-}\r
-\r
-NTSTATUS\r
-SdpArp::SourcePortGidFromPorts(\r
- IN ULONG SourceAddr, \r
- IN IOCTL_IBAT_PORTS_OUT *pPorts, \r
- OUT ib_net64_t *SrcPortGuid,\r
- OUT ib_net64_t *SrcCaGuid\r
- )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"Entered\n");\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- KEVENT event;\r
- PIRP irp;\r
- IO_STATUS_BLOCK ioStatus;\r
- \r
- int i = 0, j = 0;\r
-\r
- IOCTL_IBAT_IP_ADDRESSES_IN addresses_in;\r
- IOCTL_IBAT_IP_ADDRESSES_OUT *addresses_out;\r
- char temp[1000];\r
- addresses_out = (IOCTL_IBAT_IP_ADDRESSES_OUT *)temp;\r
-\r
- addresses_in.Version = IBAT_IOCTL_VERSION;\r
-\r
- for (i = 0 ; i < pPorts->NumPorts; i++) {\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET, "%d: ca guid = 0x%I64x port guid=0x%I64x\n",\r
- i, CL_NTOH64(pPorts->Ports[i].CaGuid), CL_NTOH64(pPorts->Ports[i].PortGuid));\r
-\r
- // Do a quary to find out if this is the correct port\r
- ASSERT(m_DeviceObject != NULL);\r
-\r
- addresses_in.PortGuid = pPorts->Ports[i].PortGuid;\r
-\r
- KeInitializeEvent(&event, NotificationEvent, FALSE);\r
- irp = IoBuildDeviceIoControlRequest(\r
- IOCTL_IBAT_IP_ADDRESSES ,\r
- m_DeviceObject,\r
- &addresses_in,\r
- sizeof addresses_in,\r
- addresses_out,\r
- sizeof temp,\r
- TRUE,\r
- &event,\r
- &ioStatus\r
- );\r
-\r
- if(NULL == irp) {\r
- rc = STATUS_INSUFFICIENT_RESOURCES;\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_ARP,"IoBuildDeviceIoControlRequest failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
-\r
- rc = IoCallDriver(m_DeviceObject, irp);\r
- if(STATUS_PENDING == rc) {\r
- KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);\r
- }\r
- else {\r
- ioStatus.Status = rc;\r
- }\r
-\r
- if(!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_ARP,"IoCallDriver failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
- if (addresses_out->Size > sizeof temp) {\r
- // The number of bytes that we have allocated wasn't enough\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_ARP,"addresses_out.Size = %d\n", addresses_out->Size );\r
- rc = STATUS_INSUFFICIENT_RESOURCES;\r
- goto Cleanup;\r
- // BUGBUG: We should try again, with a bigger buffer\r
- }\r
-\r
-\r
- // We now have the addreses, we can check if this is what we need\r
- for (j = 0 ; j < addresses_out->AddressCount; j++) {\r
- ULONG *pIp;\r
- ASSERT(addresses_out->Address[j].IpVersion == 4);\r
- pIp = (ULONG *) (&addresses_out->Address[j].Address[12]);\r
- if (*pIp == CL_NTOH32(SourceAddr)) {\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_ARP, \r
- "Found the IP: ca guid = 0x%I64x port guid=0x%I64x\n", \r
- CL_NTOH64(pPorts->Ports[i].CaGuid), CL_NTOH64(pPorts->Ports[i].PortGuid));\r
- ASSERT(rc == STATUS_SUCCESS);\r
- *SrcPortGuid = pPorts->Ports[i].PortGuid;\r
- *SrcCaGuid = pPorts->Ports[i].CaGuid;\r
- goto Cleanup;\r
- }\r
-\r
- }\r
-\r
- }\r
- // If we have reached here the data was not found\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_ARP, \r
- "HCA not found for ip=%d.%d.%d.%d\n", \r
- (SourceAddr & 0xff000000) >> 24,\r
- (SourceAddr & 0xff0000) >> 16,\r
- (SourceAddr & 0xff00) >> 8 , \r
- SourceAddr & 0xff\r
- );\r
- rc = STATUS_NOT_FOUND;\r
-\r
-Cleanup:\r
- return rc;\r
-\r
-}\r
-\r
-\r
-NTSTATUS \r
-SdpArp::DestPortGidFromMac(\r
- IN ib_net64_t SrcPortGuid,\r
- IN MAC_ADDR DestMac, \r
- OUT ib_gid_t *pDestPortGid)\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"MAC = ????\n");\r
- NTSTATUS rc = STATUS_SUCCESS;\r
-\r
- KEVENT event;\r
- PIRP irp;\r
- IO_STATUS_BLOCK ioStatus;\r
-\r
- IOCTL_IBAT_MAC_TO_GID_IN ipoib_mac2gid_in;\r
- IOCTL_IBAT_MAC_TO_GID_OUT ipoib_mac2gid_out;\r
-\r
- C_ASSERT(MAC_ADDR_SIZE == sizeof (ipoib_mac2gid_in.DestMac));\r
- ipoib_mac2gid_in.Version = IBAT_IOCTL_VERSION;\r
- ipoib_mac2gid_in.PortGuid = SrcPortGuid;\r
- memcpy(ipoib_mac2gid_in.DestMac, DestMac, MAC_ADDR_SIZE);\r
- \r
-\r
-\r
- ASSERT(m_DeviceObject != NULL);\r
-\r
- KeInitializeEvent(&event, NotificationEvent, FALSE);\r
- irp = IoBuildDeviceIoControlRequest(\r
- IOCTL_IBAT_MAC_TO_GID ,\r
- m_DeviceObject,\r
- &ipoib_mac2gid_in,\r
- sizeof ipoib_mac2gid_in,\r
- &ipoib_mac2gid_out,\r
- sizeof ipoib_mac2gid_out,\r
- TRUE,\r
- &event,\r
- &ioStatus\r
- );\r
-\r
- if(NULL == irp) {\r
- rc = STATUS_INSUFFICIENT_RESOURCES;\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_ARP,"IoBuildDeviceIoControlRequest failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
-\r
- rc = IoCallDriver(m_DeviceObject, irp);\r
- if(STATUS_PENDING == rc) {\r
- KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);\r
- }\r
- else {\r
- ioStatus.Status = rc;\r
- }\r
-\r
- if(!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_ARP,"IoCallDriver failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
-\r
- *pDestPortGid = ipoib_mac2gid_out.DestGid;\r
-Cleanup:\r
- return rc;\r
-}\r
-\r
-NTSTATUS\r
-SdpArp::QueryPathRecord(\r
- IN ib_net64_t SrcPortGuid,\r
- IN ib_gid_t DestPortGid,\r
- OUT ib_path_rec_t *path_rec )\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- ib_gid_pair_t user_query;\r
- struct query_pr_context query_context;\r
- ib_query_handle_t query_handle;\r
- ib_query_req_t query_req;\r
- ib_api_status_t ib_status;\r
-\r
- query_req.query_type = IB_QUERY_PATH_REC_BY_GIDS;\r
- query_req.p_query_input = &user_query;\r
- query_req.port_guid = SrcPortGuid;\r
- query_req.timeout_ms = 500;\r
- query_req.retry_cnt = 4;\r
- query_req.flags = IB_FLAGS_SYNC;\r
- query_req.query_context = &query_context;\r
- query_req.pfn_query_cb = SdpArp::query_pr_callback;\r
-\r
- ib_gid_set_default( &user_query.src_gid, SrcPortGuid );\r
- \r
- user_query.dest_gid = DestPortGid;\r
-\r
- query_context.path_rec = path_rec;\r
-\r
- SDP_PRINT( TRACE_LEVEL_INFORMATION, SDP_ARP, "Query for path from %I64x to %I64x\n",\r
- SrcPortGuid, DestPortGid.unicast.interface_id);\r
-\r
- ib_status = ib_query( g_pSdpDriver->m_al_handle, &query_req, &query_handle );\r
-\r
- if ( ib_status != IB_SUCCESS) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_ARP,"ib_query failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
-\r
- if( query_context.status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_ARP,"query_context.status failed ib_status = 0x%d\n", query_context.status );\r
- rc = IB2Status(query_context.status);\r
- goto Cleanup;\r
- }\r
-\r
-// BUGBUG: This code was in the orginanl function. We have to decide\r
-// if we want to keep it.\r
-#if 0\r
- if( (port->hca->dev_id == 0x5A44) &&\r
- (ib_path_rec_mtu( path_rec ) > IB_MTU_1024) )\r
- {\r
- /* Local endpoint is Tavor - cap MTU to 1K for extra bandwidth. */\r
- path_rec->mtu &= IB_PATH_REC_SELECTOR_MASK;\r
- path_rec->mtu |= IB_MTU_1024;\r
- }\r
-#endif\r
-\r
-Cleanup:\r
- return rc;\r
-}\r
-\r
-void AL_API\r
-SdpArp::query_pr_callback(\r
- IN ib_query_rec_t *p_query_rec)\r
-{\r
- query_pr_context * __ptr64 query_context =\r
- (query_pr_context * __ptr64)p_query_rec->query_context;\r
-\r
- \r
- ib_api_status_t status;\r
-\r
- SDP_PRINT( TRACE_LEVEL_INFORMATION, SDP_ARP,"query_pr_callback status is %d irql=%d\n", p_query_rec->status, KeGetCurrentIrql());\r
-\r
- query_context->status = p_query_rec->status;\r
-\r
- if( p_query_rec->status == IB_SUCCESS ){\r
- ib_path_rec_t *path_rec;\r
-\r
- path_rec = ib_get_query_path_rec(p_query_rec->p_result_mad, 0 );\r
-\r
- ASSERT( path_rec );\r
-\r
- /* Copy the path record */\r
- *query_context->path_rec = *path_rec;\r
- }\r
-\r
- if( p_query_rec->status == IB_SUCCESS || p_query_rec->status == IB_REMOTE_ERROR )\r
- {\r
- status = ib_put_mad( p_query_rec->p_result_mad );\r
-\r
- ASSERT(status == IB_SUCCESS);\r
- if( status != IB_SUCCESS )\r
- {\r
- SDP_PRINT( TRACE_LEVEL_ERROR, SDP_ARP,"ib_put_mad failed ");\r
- }\r
- } else {\r
- // When do we free this mad ???\r
- ASSERT(p_query_rec->p_result_mad == NULL);\r
- }\r
-\r
-}\r
-\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-class SdpArp {\r
- /* \r
- Look at the routing table of the machine and see which port\r
- to use for outbound traffic\r
- */\r
-\r
-public:\r
-\r
- SdpArp() {\r
- m_DeviceObject = NULL;\r
- m_FileObject = NULL;\r
- m_FileHandle = NULL;\r
- \r
- }\r
-\r
- struct query_pr_context\r
- {\r
- ib_api_status_t status;\r
- ib_path_rec_t *path_rec;\r
- };\r
-\r
- NTSTATUS Init(PDRIVER_OBJECT DriverObject);\r
-\r
- VOID Shutdown();\r
-\r
- NTSTATUS GetPort(\r
- IN ULONG SourceAddr, \r
- OUT USHORT *SrcPort\r
- )\r
- {\r
- // If the port is 0, choose your own free port.\r
- // If the port is not 0 check if this port is already in use\r
- *SrcPort = 5050; // BUGBUG: Complete this mechanism\r
- return STATUS_SUCCESS;\r
-\r
- }\r
-\r
- NTSTATUS SourcePortGidFromIP(\r
- IN ULONG SourceAddr, \r
- OUT ib_net64_t *SrcPortGuid,\r
- OUT ib_net64_t *SrcCaGuid\r
- );\r
- NTSTATUS DestPortGidFromMac(\r
- IN ib_net64_t SrcPortGuid,\r
- IN MAC_ADDR DestMac, \r
- OUT ib_gid_t *pDestPortGid);\r
-\r
-/* \r
-Synchronously query the SA for a GUID. (started from wsd - query_pr)\r
-*/\r
-/* \r
- * Get a path record from a GUID \r
- */\r
- \r
- NTSTATUS\r
- QueryPathRecord(\r
- IN ib_net64_t SrcPortGuid,\r
- IN ib_gid_t DestPortGid,\r
- OUT ib_path_rec_t *path_rec \r
- );\r
-\r
- static void AL_API\r
- query_pr_callback(\r
- IN ib_query_rec_t *p_query_rec);\r
-\r
- private :\r
- PDEVICE_OBJECT m_DeviceObject;\r
- PFILE_OBJECT m_FileObject;\r
- HANDLE m_FileHandle;\r
-\r
- \r
-\r
- NTSTATUS\r
- SourcePortGidFromPorts(\r
- IN ULONG SourceAddr, \r
- IN IOCTL_IBAT_PORTS_OUT *pPorts, \r
- OUT ib_net64_t *SrcPortGuid,\r
- OUT ib_net64_t *SrcCaGuid\r
- );\r
- \r
-\r
-};\r
-\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-\r
-#include "preCompile.h"\r
-\r
-#pragma warning(disable: 4244 ) \r
-\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "SdpBufferPool.tmh"\r
-#endif\r
-\r
-\r
-\r
-\r
-//static \r
-NTSTATUS \r
-BufferDescriptor::AllocateBuffer(BufferDescriptor ** ppBufferDescriptor, int BufferSize, int Tag)\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_BUFFER_POOL,"\n");\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- BufferDescriptor *pBufferDescriptor = NULL;\r
-\r
- // Allocate the buffer descriptor\r
- pBufferDescriptor = \r
- (BufferDescriptor *)\r
- ExAllocatePoolWithTag(\r
- NonPagedPool ,\r
- sizeof BufferDescriptor, \r
- Tag\r
- );\r
- \r
- if (pBufferDescriptor == NULL) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"ExAllocatePoolWithTag failed \n");\r
- rc = STATUS_NO_MEMORY;\r
- goto Cleanup;\r
- }\r
-\r
- // Allocate the buffer itself (from continious memory)\r
- PHYSICAL_ADDRESS mem;\r
- mem.HighPart = 0xffffffff;\r
- mem.LowPart = 0xffffffff; \r
- pBufferDescriptor->pBuffer = MmAllocateContiguousMemory(BufferSize, mem);\r
- \r
- if (pBufferDescriptor->pBuffer == NULL) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"ExAllocatePoolWithTag failed BufferSize = %d irql=%d\n",BufferSize, KeGetCurrentIrql());\r
- rc = STATUS_NO_MEMORY;\r
- goto Cleanup;\r
- }\r
-\r
- pBufferDescriptor->BufferSize = BufferSize;\r
- pBufferDescriptor->Reset();\r
-\r
-Cleanup:\r
- if (!NT_SUCCESS(rc)) {\r
- if (pBufferDescriptor != NULL) {\r
- if (pBufferDescriptor->pBuffer != NULL) {\r
- MmFreeContiguousMemory(pBufferDescriptor->pBuffer);\r
- }\r
- ExFreePoolWithTag(pBufferDescriptor, SEND_BUFFERS_ALLOCATION_TAG);\r
- pBufferDescriptor = NULL;\r
- } \r
- } \r
- *ppBufferDescriptor = pBufferDescriptor;\r
- return rc;\r
-\r
-}\r
-\r
-//static \r
-VOID \r
-BufferDescriptor::DeAllocateBuffer(BufferDescriptor *pBufferDescriptor, int Tag)\r
-{\r
- MmFreeContiguousMemory(pBufferDescriptor->pBuffer);\r
- ExFreePoolWithTag(pBufferDescriptor, Tag);\r
-\r
-}\r
-\r
-/*\r
- Currently the implmentation of shutdown should allow it to work, even without\r
- init being called\r
-*/\r
-BufferPool::BufferPool()\r
-{\r
- m_SendSeq = 0;\r
- m_AdvtSeq = 0;\r
- m_CurrentlySentBuffers = 0;\r
- m_CurrentlyAllocated = 0;\r
- m_PostCreditsWhenCan = false;\r
- m_CreditsCurrentlyPosted = false;\r
- m_CreditdBufferDescriptor = NULL;\r
- m_pSdpSocket = NULL;\r
-\r
-\r
- m_NumberOfBytesSent = 0;\r
- m_NumberOfBytesSentAndAcked = 0;\r
-\r
-}\r
-\r
-NTSTATUS \r
-BufferPool::Init(\r
- int MaxBuffers, \r
- int MaxConcurrentSends, \r
- int MaxMessageSize,\r
- ib_pd_handle_t pd,\r
- ib_qp_handle_t qp,\r
- net32_t lkey,\r
- SdpSocket *pSdpSocket\r
-\r
- )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_BUFFER_POOL,"this = 0x%p \n",this);\r
- m_MaxBuffers = MaxBuffers;\r
- m_MaxConcurrentSends = MaxConcurrentSends;\r
- m_MaxMessageSize = MaxMessageSize; \r
- ASSERT(pd != NULL);\r
- m_pd = pd;\r
- ASSERT(qp != NULL); \r
- m_qp = qp;\r
- ASSERT(lkey != NULL);\r
- m_lkey = lkey;\r
- m_pSdpSocket = pSdpSocket;\r
- m_CallBackPending = false;\r
-\r
- \r
-\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-/*\r
- This function is being called by a thread that wants to do a send in order\r
- to have a buffer that he can copy the data to.\r
- FirstBuffer tells if this is the first buffer that he wants.\r
- If it is true, this means that no other request will be handled before\r
- this client will indicate that he has finished queing his data.\r
- If an event is returned this means that the caller has to wait on the\r
- event before the request will be staisfied.\r
-\r
- This function is being called under a lock\r
-\r
-*/\r
-NTSTATUS \r
-BufferPool::GetBuffer(\r
- BufferDescriptor **ppBufferDescriptor\r
- )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_BUFFER_POOL, "this = 0x%p \n",this);\r
- AssertLocked();\r
-\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- *ppBufferDescriptor = NULL;\r
-\r
- if (m_FreePackets.Size() > 0) {\r
- LIST_ENTRY *item = m_FreePackets.RemoveHeadList();\r
- *ppBufferDescriptor = CONTAINING_RECORD(item, BufferDescriptor , BuffersList);\r
- goto Cleanup;\r
- } else if (m_CurrentlyAllocated < m_MaxBuffers) {\r
- // we need to alocate a new buffer\r
- rc = BufferDescriptor::AllocateBuffer(ppBufferDescriptor, m_MaxMessageSize, SEND_BUFFERS_ALLOCATION_TAG);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL, "AllocateBuffer failed rc = 0x%x\n", rc );\r
- ASSERT(*ppBufferDescriptor == NULL);\r
- goto Cleanup;\r
- }\r
- m_CurrentlyAllocated++;\r
- goto Cleanup;\r
- } \r
- // No buffers available, we return NULL\r
- ASSERT(*ppBufferDescriptor == NULL);\r
-\r
-Cleanup: \r
- return rc;\r
-}\r
-\r
-/* \r
-Send the buffers if possibale, if not possibale ,adds them to the\r
-queue\r
-*/\r
-\r
-NTSTATUS \r
-BufferPool::AddBufferToQueuedList(BufferDescriptor *pBufferDescriptor)\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_BUFFER_POOL, "this = 0x%p pBufferDescriptor = 0x%p\n",this,\r
- pBufferDescriptor);\r
- AssertLocked();\r
-\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- ASSERT(pBufferDescriptor->GetFlags() == 0 || \r
- pBufferDescriptor->GetFlags() == DISCONNECT_MESSAGE);\r
-\r
- // Assert that we are not sending an empty buffer\r
- if (pBufferDescriptor->DataSize == 0) {\r
- msg_hdr_bsdh *pHeader = (msg_hdr_bsdh *) pBufferDescriptor->pBuffer;\r
- ASSERT(pHeader->mid == SDP_MID_DISCONNECT );\r
- }\r
-\r
- m_QueuedPackets.InsertTailList(&pBufferDescriptor->BuffersList);\r
- rc = SendBuffersIfCan();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"SendBuffersIfCan failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- } \r
-\r
-Cleanup: \r
- return rc;\r
-\r
-}\r
-\r
-/*\r
- called when a send packet has finished.\r
-*/\r
-\r
-NTSTATUS \r
-BufferPool::ReturnBuffer(BufferDescriptor *pBufferDescriptor)\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_BUFFER_POOL,"this = 0x%p buffer=0x%p\n",this, pBufferDescriptor);\r
- AssertLocked();\r
- bool CreditUpdate = false;\r
- bool DissconnectMessage = false;\r
- NTSTATUS rc = STATUS_SUCCESS;\r
-\r
-#if DBG \r
- if (m_CurrentlySentBuffers == 1) {\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_PERFORMANCE, "Currently no packets are bing sent \n"); \r
- }\r
-#endif\r
- ASSERT( pBufferDescriptor->GetFlags() == CREDIT_UPDATE ||\r
- pBufferDescriptor->GetFlags() == DISCONNECT_MESSAGE ||\r
- pBufferDescriptor->GetFlags() == 0);\r
-\r
- CreditUpdate = (pBufferDescriptor->GetFlags() == CREDIT_UPDATE);\r
- DissconnectMessage = (pBufferDescriptor->GetFlags() == DISCONNECT_MESSAGE);\r
- if (CreditUpdate) {\r
- // This is a credit update packet, need to act accordingly\r
- ASSERT(m_CreditdBufferDescriptor == NULL);\r
- ASSERT(m_CreditsCurrentlyPosted == true);\r
- m_CreditdBufferDescriptor = pBufferDescriptor;\r
- m_CreditsCurrentlyPosted = false;\r
- \r
- if (m_PostCreditsWhenCan == true) {\r
- m_PostCreditsWhenCan = false;\r
- rc = PostCredits();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"PostCredits failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- } \r
- }\r
- } else {\r
- m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList);\r
- // We have to ask for another thread to do the job, as\r
- // we might be in a DPC context\r
-\r
- // Ask for a new callback only in the following conditions:\r
- // 1) There is no request on the way AND\r
- // 2) There is a buffer that can be used AND\r
- // 3) We have enough free space to complete a packet\r
- // 4) We have gone under some threshold\r
-// TODO: 4 above, didn't seem to have a real influance, so it is not in\r
-// the code now. It should be testsed in the future.\r
- if (!m_CallBackPending && (m_UserPackets.Size() > 0)) {\r
- // Now testing 3,4\r
-\r
- LIST_ENTRY *item = m_UserPackets.Head();\r
- IRP * pIrp = CONTAINING_RECORD(item, IRP ,Tail.Overlay.ListEntry);\r
- \r
- if ((RemainingToCopy(pIrp) < m_MaxMessageSize * m_FreePackets.Size())) {\r
- rc = m_pSdpSocket->RequestCallBack();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL, "PostCredits failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- } \r
- m_CallBackPending = true;\r
- }\r
- }\r
-\r
- if (DissconnectMessage) {\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_BUFFER_POOL,"We have recieved a DissconnectMessage complition\n" );\r
- m_pSdpSocket->DisconectSentEvent();\r
- }\r
- }\r
- /*\r
- We allow buffers to be sent here since it is possible that the\r
- socket is already closed, and the user thread is not present.\r
- */\r
- rc = SendBuffersIfCan();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL, "SendBuffersIfCan failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- } \r
- \r
- \r
-Cleanup:\r
- ASSERT(m_CurrentlySentBuffers != 0);\r
- m_CurrentlySentBuffers--;\r
- \r
-\r
- return rc;\r
-}\r
-\r
-NTSTATUS \r
-BufferPool::AddToUserBuffers(\r
- bool *pCopied, \r
- bool ForceCopy,\r
- char *pData, \r
- uint32_t BufferSize, \r
- uint32_t Coppied, \r
- IRP* pIrp\r
- )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_BUFFER_POOL, "this = 0x%p m_UserPackets.Size() = %d \n",this, m_UserPackets.Size());\r
- AssertLocked();\r
- NTSTATUS rc = STATUS_SUCCESS;\r
-\r
- if ((m_UserPackets.Size() == 0) && (ForceCopy == false) ){\r
- *pCopied = false;\r
- goto Cleanup;\r
- }\r
-\r
- // We have to queue this IRP (following logic from sample)\r
- ASSERT(pData != NULL);\r
- SetBufferSize(pIrp, BufferSize);\r
- SetUserBuffer(pIrp, pData);\r
- SetCoppied(pIrp,Coppied);\r
- SetSocket(pIrp,m_pSdpSocket);\r
-\r
-\r
- IoMarkIrpPending(pIrp);\r
- m_UserPackets.InsertTailList(&pIrp->Tail.Overlay.ListEntry);\r
- *pCopied = true;\r
- // We mark the IRP as pending\r
- pIrp->IoStatus.Status = STATUS_PENDING;\r
- rc = STATUS_PENDING;\r
-\r
-Cleanup:\r
-\r
- \r
-#if 0\r
-The above code should be activated if we want to allow returning offsetof\r
-the user mode thread as fast as possible.\r
- if (m_CallBackPending == false) {\r
- NTSTATUS rc1 = m_pSdpSocket->RequestCallBack();\r
- if (!NT_SUCCESS(rc1)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL, "RequestCallBack failed rc = 0x%x\n", rc );\r
- ASSERT(FALSE);\r
- } \r
- m_CallBackPending = true;\r
- }\r
-#endif\r
- \r
- ASSERT(rc == STATUS_PENDING || rc == STATUS_SUCCESS);\r
- return rc;\r
-}\r
-\r
-\r
-NTSTATUS \r
-BufferPool::UsersThreadCallBack()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_BUFFER_POOL, "this = 0x%p \n",this);\r
- AssertLocked();\r
- ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);\r
- IRP *pIrp = NULL;\r
- LIST_ENTRY *item;\r
- \r
- NTSTATUS rc = STATUS_SUCCESS, rc1;\r
- BufferDescriptor *pBufferDescriptor = NULL;\r
- ASSERT(m_CallBackPending == true);\r
- ASSERT(m_UserPackets.Size() > 0 );\r
-\r
- m_CallBackPending = false;\r
-\r
- while (m_UserPackets.Size() > 0) {\r
- rc = GetBuffer(&pBufferDescriptor);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "GetBuffer failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
-\r
- if (pBufferDescriptor == NULL) {\r
- // We don't have a new buffer any more, we just\r
- // wait for a new packet to be freed\r
- ASSERT(rc == STATUS_SUCCESS);\r
- goto Cleanup;\r
- }\r
-\r
- item = m_UserPackets.Head();\r
-\r
- pIrp = CONTAINING_RECORD(item, IRP ,Tail.Overlay.ListEntry);\r
-\r
- // copy the data from the user mode to the buffers \r
- ULONG CopySize = pBufferDescriptor->BufferSize - sizeof msg_hdr_bsdh;\r
- CopySize = min(CopySize, RemainingToCopy(pIrp));\r
- \r
- rc = pBufferDescriptor->WriteData((CHAR *)GetUserBuffer(pIrp) + GetCoppied(pIrp), CopySize);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "pBufferDescriptor->WriteData failed rc = 0x%x\n", rc );\r
- // free the buffer that you have\r
- rc1 = ReturnBuffer(pBufferDescriptor);\r
- ASSERT(NT_SUCCESS(rc1));\r
- goto Cleanup;\r
- }\r
- // Update the user buffer\r
- SetCoppied(pIrp, GetCoppied(pIrp) + CopySize);\r
- \r
- // send the data to the buffer\r
- pBufferDescriptor->SetMid(SDP_MID_DATA);\r
- rc = AddBufferToQueuedList(pBufferDescriptor);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "AddBufferToQueuedList failed rc = 0x%x\n", rc );\r
- // free the buffer that you have\r
- rc1 = ReturnBuffer(pBufferDescriptor);\r
- ASSERT(NT_SUCCESS(rc1));\r
- goto Cleanup;\r
- }\r
-\r
- if (RemainingToCopy(pIrp) == 0) {\r
- // We have finished with this users packet, we should\r
- // compleate the IRP\r
-\r
- WspSendOut *pWspSendOut = (WspSendOut *) pIrp->AssociatedIrp.SystemBuffer;\r
- m_UserPackets.RemoveHeadList();\r
-\r
- pIrp->IoStatus.Status = STATUS_SUCCESS;\r
- pIrp->IoStatus.Information = sizeof (WspSendOut);\r
- pWspSendOut->Errno = 0;\r
- pWspSendOut->NumberOfBytesSent = GetBufferSize(pIrp);\r
- IoCompleteRequest(pIrp, IO_NETWORK_INCREMENT);\r
-\r
- }\r
- }\r
-\r
-Cleanup:\r
-\r
- return rc;\r
-}\r
-\r
-\r
-/*\r
- This function goes over the list of packets that we can send, and sends\r
- them. It is called under the lock, and might be called also from a DPC\r
- context.\r
-\r
-*/\r
-NTSTATUS\r
-BufferPool::SendBuffersIfCan()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_BUFFER_POOL,"this = 0x%p \n",this);\r
- AssertLocked();\r
- NTSTATUS rc = STATUS_SUCCESS;\r
-\r
-// Check if such code should be here ???? what if we have packets ????\r
- if (m_PostCreditsWhenCan == true) {\r
- m_PostCreditsWhenCan = false;\r
- rc = PostCredits();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"PostCredits failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- } \r
- }\r
-\r
- while ((m_QueuedPackets.Size() > 0) && \r
- (m_CurrentlySentBuffers < m_MaxConcurrentSends) &&\r
- (m_rRecvBuf > 2)) {\r
- // we can now send the next buffer\r
- LIST_ENTRY *item = m_QueuedPackets.RemoveHeadList();\r
- BufferDescriptor *pBufferDescriptor = CONTAINING_RECORD(item, BufferDescriptor , BuffersList);\r
- rc = SendBuffer(pBufferDescriptor);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"SendBuffer failed rc = 0x%x\n", rc );\r
- m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList);\r
- goto Cleanup;\r
- } \r
- }\r
-\r
-Cleanup: \r
- return rc;\r
-\r
-}\r
-\r
-\r
-/* This function is called when the user mode has called close socket\r
- If a client is waiting on recieve we free him, he should get an\r
- error on his callback. *** The caller probably has a bug - as one\r
- can't race a closesocket ***\r
-*/ \r
-\r
-VOID \r
-BufferPool::CloseSocket()\r
-{\r
- LIST_ENTRY *item = NULL;\r
- IRP *pIrp = NULL;\r
-\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_BUFFER_POOL, "this = 0x%p \n",this);\r
- AssertLocked();\r
- // All IRP's that were not compleated, will be compleated as cancelled\r
- while (m_UserPackets.Size() > 0 ) {\r
- item = m_UserPackets.RemoveHeadList();\r
- pIrp = CONTAINING_RECORD(item, IRP ,Tail.Overlay.ListEntry);\r
- pIrp->IoStatus.Status = STATUS_CANCELLED;\r
- pIrp->IoStatus.Information = 0;\r
- IoCompleteRequest (pIrp, IO_NO_INCREMENT);\r
- }\r
-}\r
-\r
-\r
-\r
-/*\r
- This function is being called from under the lock and is the last one to be called.\r
- It frees all resources\r
-\r
-*/\r
-VOID \r
-BufferPool::ShutDown()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_BUFFER_POOL,"this = 0x%p \n",this);\r
-\r
- //AssertLocked();\r
- BufferDescriptor *pBufferDescriptor = NULL;\r
- LIST_ENTRY *item = NULL;\r
- IRP *pIrp = NULL;\r
-\r
- while (m_FreePackets.Size() > 0 ) {\r
- item = m_FreePackets.RemoveHeadList();\r
- pBufferDescriptor = CONTAINING_RECORD(item, BufferDescriptor , BuffersList);\r
- BufferDescriptor::DeAllocateBuffer(pBufferDescriptor, SEND_BUFFERS_ALLOCATION_TAG);\r
- }\r
-\r
- while (m_QueuedPackets.Size() > 0 ) {\r
- item = m_QueuedPackets.RemoveHeadList();\r
- pBufferDescriptor = CONTAINING_RECORD(item, BufferDescriptor , BuffersList);\r
- BufferDescriptor::DeAllocateBuffer(pBufferDescriptor, SEND_BUFFERS_ALLOCATION_TAG);\r
- }\r
-\r
- while (m_UserPackets.Size() > 0 ) {\r
- item = m_UserPackets.RemoveHeadList();\r
- pIrp = CONTAINING_RECORD(item, IRP ,Tail.Overlay.ListEntry);\r
- pIrp->IoStatus.Status = STATUS_CANCELLED;\r
- pIrp->IoStatus.Information = 0;\r
- IoCompleteRequest (pIrp, IO_NO_INCREMENT);\r
- }\r
-\r
- if(m_CreditdBufferDescriptor != NULL) {\r
- BufferDescriptor::DeAllocateBuffer(m_CreditdBufferDescriptor, SEND_BUFFERS_ALLOCATION_TAG);\r
- m_CreditdBufferDescriptor = NULL;\r
- }\r
-\r
-}\r
-\r
-NTSTATUS\r
-BufferPool::SendBuffer(BufferDescriptor *pBufferDescriptor)\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_BUFFER_POOL,"this = 0x%p \n",this);\r
- AssertLocked();\r
- NTSTATUS rc = STATUS_SUCCESS;\r
-\r
- msg_hdr_bsdh *pHeader = (msg_hdr_bsdh *) pBufferDescriptor->pBuffer;\r
-\r
- pHeader->recv_bufs = m_pSdpSocket->m_RecvBufferPool.GetCurrentlyPostedRecievedBuffers();\r
- pHeader->size = pBufferDescriptor->DataSize + sizeof msg_hdr_bsdh;\r
- pHeader->seq_num = GetAndIncreaseSendSeq();\r
- pHeader->seq_ack = m_pSdpSocket->m_RecvBufferPool.GetRecvSeq();\r
- m_AdvtSeq = pHeader->seq_ack;// Currently only for debug\r
- pHeader->flags = SDP_MSG_FLAG_NON_FLAG;\r
-\r
- /*\r
- * endian swap\r
- */\r
- sdp_msg_swap_bsdh(pHeader);\r
-\r
- ib_send_wr_t send_wr;\r
-\r
- send_wr.p_next = NULL;\r
- send_wr.wr_id = (uintn_t)pBufferDescriptor;\r
- send_wr.wr_type = WR_SEND;\r
- send_wr.send_opt = IB_SEND_OPT_SIGNALED;//socket_info->send_opt;\r
-\r
- pBufferDescriptor->ds_array.length = pBufferDescriptor->DataSize + sizeof msg_hdr_bsdh;\r
- pBufferDescriptor->ds_array.vaddr = MmGetPhysicalAddress( pBufferDescriptor->pBuffer ).QuadPart;\r
- pBufferDescriptor->ds_array.lkey = m_lkey;\r
-\r
- send_wr.num_ds = 1;\r
- send_wr.ds_array = &pBufferDescriptor->ds_array;\r
-\r
-\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_CREDITS, "Sending buffer pHeader->recv_bufs = %d pHeader->seq_ack = %d\n", CL_NTOH16(pHeader->recv_bufs),\r
- CL_NTOH32(pHeader->seq_ack));\r
-\r
- \r
- ib_api_status_t ib_status = ib_post_send(m_qp, &send_wr, NULL);\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"ib_post_send failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
- m_NumberOfBytesSent++;\r
- //????? Should we clear the post credits here ????????\r
- m_CurrentlySentBuffers ++;\r
- m_rRecvBuf--;\r
- m_pSdpSocket->m_RecvBufferPool.UpdateLocaleAdvertisedBuffers();\r
-\r
-Cleanup:\r
- return rc;\r
-}\r
-\r
-NTSTATUS \r
-BufferPool::PostCredits()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_BUFFER_POOL,"this = 0x%p \n",this);\r
- AssertLocked(); \r
- NTSTATUS rc = STATUS_SUCCESS;\r
-\r
- // TODO: If we currently have buffers with data that we should post, and we\r
- // have enough credits then we shouldn't do anything. data will be sent when\r
- // the time comes.\r
-\r
- if (m_CreditsCurrentlyPosted) {\r
- // We will have to send them once we can\r
- m_PostCreditsWhenCan = true;\r
- goto Cleanup;\r
- }\r
-\r
- if (m_pSdpSocket->GetState() != SS_CONNECTED) {\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_BUFFER_POOL, "this = 0x%p - Not sending credits,"\r
- " because state = %s \n",this, SdpSocket::SS2String(m_pSdpSocket->GetState() )); \r
- // We will have to send them once we can\r
- m_PostCreditsWhenCan = true;\r
- goto Cleanup;\r
- }\r
- \r
- // Post the credit\r
- if (m_CreditdBufferDescriptor == NULL) {\r
-\r
- rc = BufferDescriptor::AllocateBuffer(\r
- &m_CreditdBufferDescriptor, \r
- sizeof msg_hdr_bsdh,\r
- SEND_BUFFERS_ALLOCATION_TAG\r
- );\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"AllocateBuffer failed rc = 0x%x\n", rc );\r
- ASSERT(m_CreditdBufferDescriptor == NULL);\r
- goto Cleanup;\r
- }\r
- m_CreditdBufferDescriptor->SetFlags(CREDIT_UPDATE);\r
- }\r
- ASSERT(m_CreditdBufferDescriptor->GetFlags() == CREDIT_UPDATE);\r
-\r
- ASSERT(m_CreditdBufferDescriptor->DataSize == 0);\r
-\r
- m_CreditdBufferDescriptor->SetMid(SDP_MID_DATA);\r
- rc = SendBuffer(m_CreditdBufferDescriptor);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"SendBuffer failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
- \r
- m_CreditsCurrentlyPosted = true;\r
- m_CreditdBufferDescriptor = NULL;\r
- \r
-Cleanup:\r
- return rc;\r
-\r
-}\r
-\r
-NTSTATUS BufferPool::PostDisConn()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_BUFFER_POOL,"this = 0x%p \n",this);\r
- AssertLocked(); \r
- NTSTATUS rc = STATUS_SUCCESS;\r
- BufferDescriptor *pBufferDescriptor = NULL;\r
-\r
- rc = BufferDescriptor::AllocateBuffer(\r
- &pBufferDescriptor, \r
- sizeof msg_hdr_bsdh,\r
- SEND_BUFFERS_ALLOCATION_TAG\r
- );\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"AllocateBuffer failed rc = 0x%x\n", rc );\r
- ASSERT(m_CreditdBufferDescriptor == NULL);\r
- goto Cleanup;\r
- }\r
-\r
- pBufferDescriptor->SetFlags(DISCONNECT_MESSAGE);\r
-\r
- ASSERT(pBufferDescriptor->DataSize == 0);\r
-\r
- pBufferDescriptor->SetMid(SDP_MID_DISCONNECT);\r
- rc = AddBufferToQueuedList(pBufferDescriptor);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"AddBufferToQueuedList failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
- \r
-Cleanup:\r
- return rc;\r
-\r
-}\r
-\r
-\r
-VOID \r
-BufferPool::AssertLocked() {\r
-#if DBG\r
- if (m_pSdpSocket) {\r
- m_pSdpSocket->AssertLocked();\r
- }\r
-#endif\r
-}\r
-\r
-\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-#ifndef H_SDP_BUFFER_POOL_H\r
-#define H_SDP_BUFFER_POOL_H \r
-\r
-// This is simply a wrapper to the LIST_ENTRY class that allows \r
-// easier work with this list\r
-class LinkedList {\r
-\r
-public:\r
- LinkedList() {\r
- size = 0;\r
- InitializeListHead(&m_Data);\r
- }\r
-\r
- int Size() {return size;}\r
-\r
- LIST_ENTRY *RemoveHeadList() {\r
- LIST_ENTRY *pTemp;\r
- ASSERT(size > 0);\r
- ASSERT(!IsListEmpty(&m_Data));\r
- pTemp = ::RemoveHeadList(&m_Data);\r
- size--;\r
- return pTemp; \r
- }\r
- \r
- VOID InsertTailList (LIST_ENTRY *Item) {\r
- ::InsertTailList(&m_Data, Item);\r
- size++;\r
- }\r
-\r
- LIST_ENTRY *Head() {\r
- ASSERT(size > 0);\r
- ASSERT(!IsListEmpty(&m_Data));\r
- return m_Data.Flink;\r
-\r
- }\r
-\r
- VOID RemoveEntryList(LIST_ENTRY *Item) {\r
- ASSERT(size > 0);\r
- ASSERT(!IsListEmpty(&m_Data)); \r
-#if DBG\r
- // Verify that this item is indeed in the list\r
- LIST_ENTRY *current = m_Data.Flink;\r
- while (current != Item) {\r
- if (current == & m_Data) {\r
- ASSERT(FALSE);\r
- //SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"Object is not in the list\n");\r
- }\r
- current = current->Flink;\r
- }\r
- \r
-#endif\r
- ::RemoveEntryList(Item);\r
- size--;\r
- }\r
- \r
-private:\r
- int size;\r
- LIST_ENTRY m_Data;\r
-};\r
-\r
-\r
-// The defenition of the function that we use to report back errors\r
-typedef void (* SendErrorCB )(NTSTATUS Error, VOID *Context);\r
-\r
-// The flags that are being used to give more information about the BufferDescriptors\r
-const uint8_t CREDIT_UPDATE = 1;\r
-const uint8_t DISCONNECT_MESSAGE = 2;\r
-\r
-\r
-// Each buffer starts with msg_hdr_bsdh and is followed by the actual data\r
-class BufferDescriptor {\r
-public:\r
- // copies the data from the user to a buffer (to be used for send only)\r
- NTSTATUS WriteData(char *pData, uint32_t Size) {\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- ASSERT(Size <= BufferSize - sizeof msg_hdr_bsdh);\r
- char *pStart = (char *) pBuffer + sizeof msg_hdr_bsdh;\r
- rc = CopyFromUser(pStart, pData, Size);\r
- if (!NT_SUCCESS(rc)) {\r
- //SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"CopyFromUser failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- } \r
- DataSize = Size;\r
- Cleanup:\r
- return rc;\r
- }\r
-\r
- // copies data from the buffer to a user suplied buffer\r
- // to be used for recieve only\r
- NTSTATUS CopyToUser(char *pData, uint32_t Size) {\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- ASSERT(DataSize >= Size);\r
- char *pStart = (char *) pBuffer + DataStart;\r
- rc = ::CopyToUser(pData, pStart, Size);\r
- if (!NT_SUCCESS(rc)) {\r
- //SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"CopyToUser failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
- DataStart += Size;\r
- DataSize -= Size;\r
- Cleanup:\r
- return rc;\r
- }\r
- VOID Reset() {\r
- DataSize = 0;\r
- DataStart = 0;\r
- Flags = 0;\r
- }\r
-\r
- VOID SetFlags(uint8_t flags) { Flags = flags; }\r
- uint8_t GetFlags() { return Flags; }\r
-\r
- VOID SetMid(uint8_t Mid) {\r
- msg_hdr_bsdh *pHeader = (msg_hdr_bsdh *) pBuffer;\r
- pHeader->mid = Mid;\r
- }\r
-\r
- // Each buffer starts with bsdh_hdr structure\r
- VOID *pBuffer; // A pointer to the actual place that we put the data\r
- uint32_t BufferSize; // The total size of the buffer (size that we have allocated)\r
- uint32_t DataSize; // The size of the data\r
- uint32_t DataStart; // The place in which the data starts (used for recieve packets)\r
- LIST_ENTRY BuffersList; // The place to hold the list of the buffers\r
- uint8_t Flags; // A field that tells if there is anything special in this descriptor\r
-\r
- ib_local_ds_t ds_array; // Used for sending the buffer\r
-\r
- static NTSTATUS AllocateBuffer(BufferDescriptor ** ppBufferDescriptor, int BufferSize, int Tag);\r
-\r
- static VOID DeAllocateBuffer(BufferDescriptor *pBufferDescriptor, int Tag);\r
-\r
-\r
-};\r
-\r
-\r
-// We will define 4 pointers to store send data for the IRP:\r
-// This will have to change one day()\r
-// The users data\r
-\r
-inline VOID SetUserBuffer(IRP *pIrp, VOID * p) {\r
- pIrp->Tail.Overlay.DriverContext[0] = (VOID *)p;\r
-}\r
-inline VOID* GetUserBuffer(IRP *pIrp) {\r
- return (pIrp->Tail.Overlay.DriverContext[0]);\r
-}\r
-\r
-inline VOID SetBufferSize(IRP *pIrp, uint32_t i) {\r
- pIrp->Tail.Overlay.DriverContext[1] = (VOID *)(UINT_PTR)i;\r
-}\r
-inline uint32_t GetBufferSize(IRP *pIrp) {\r
- return (uint32_t)(UINT_PTR) (pIrp->Tail.Overlay.DriverContext[1]);\r
-}\r
-\r
-inline VOID SetCoppied(IRP *pIrp, uint32_t i) {\r
- pIrp->Tail.Overlay.DriverContext[2] = (VOID *)(UINT_PTR)i;\r
- ASSERT(i <= GetBufferSize(pIrp));\r
-}\r
-inline uint32_t GetCoppied(IRP *pIrp) {\r
- return (uint32_t)(UINT_PTR) (pIrp->Tail.Overlay.DriverContext[2]);\r
-}\r
-\r
-/* \r
- BUGBUG:\r
- As I intend to change this in any case, \r
- I will not use Referance count on the socket\r
- here.\r
-*/ // ???????????????????\r
-inline void SetSocket(IRP *pIrp, SdpSocket *pSdpSocket) {\r
- pIrp->Tail.Overlay.DriverContext[3] = pSdpSocket;\r
-}\r
-\r
-inline SdpSocket *GetSocket(IRP *pIrp) {\r
- return (SdpSocket *)pIrp->Tail.Overlay.DriverContext[3];\r
-}\r
-\r
-inline uint32_t RemainingToCopy(IRP *pIrp) {\r
- uint32_t Coppied = GetCoppied(pIrp);\r
- uint32_t BufferSize = GetBufferSize(pIrp);\r
- ASSERT(BufferSize >= Coppied);\r
- return BufferSize - Coppied;\r
-}\r
-\r
-class BufferPool {\r
-\r
-public:\r
-\r
- BufferPool();\r
-\r
- NTSTATUS Init(\r
- int MaxBuffers, \r
- int MaxConcurrentSends, \r
- int MaxMessageSize,\r
- ib_pd_handle_t pd,\r
- ib_qp_handle_t qp,\r
- net32_t lkey,\r
- SdpSocket *pSdpSocket\r
- );\r
-\r
- NTSTATUS GetBuffer(\r
- BufferDescriptor ** ppBufferDescriptor\r
- );\r
-\r
- NTSTATUS AddBufferToQueuedList(BufferDescriptor *pBufferDescriptor); \r
-\r
- NTSTATUS ReturnBuffer(BufferDescriptor *pBufferDescriptor);\r
-\r
- NTSTATUS AddToUserBuffers(bool *pCopied, bool ForceCopy,char *pData, uint32_t BufferSize, uint32_t Coppied, IRP* pIrp);\r
-\r
- VOID RemoveFromUserBuffers(PIRP pIrp) {\r
- m_UserPackets.RemoveEntryList(&pIrp->Tail.Overlay.ListEntry);\r
- }\r
-\r
- NTSTATUS UsersThreadCallBack();\r
-\r
- NTSTATUS SendBuffersIfCan();\r
-\r
- VOID CloseSocket();\r
-\r
- VOID ShutDown();\r
-\r
- uint32_t GetSendSeq() {return m_SendSeq;}\r
- uint32_t GetAndIncreaseSendSeq() {return ++m_SendSeq;}\r
- uint32_t GetAdvtSeq() {return m_AdvtSeq;}\r
-\r
- VOID SetRemoteRecvBuf (uint16_t rRecvBuf) {\r
- if (m_rRecvBuf == 2) {\r
- //SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_BUFFER_POOL,"m_rRecvBuf = %d, it is being set to %d seqnum = %d\n", m_rRecvBuf, rRecvBuf, m_SendSeq);\r
- }\r
- ASSERT(rRecvBuf < 1000);\r
- m_rRecvBuf = rRecvBuf;\r
- }\r
-\r
- NTSTATUS PostCredits();\r
-\r
- NTSTATUS PostDisConn();\r
- \r
-private:\r
-\r
- NTSTATUS SendBuffer(BufferDescriptor *pBufferDescriptor);\r
-\r
- // Global data about this connection\r
- uint32_t m_MaxBuffers; // The maximum number of buffers that we allow for this QP (to be allocated)\r
- uint32_t m_MaxConcurrentSends; // The total numbers of sends that are allowd for the QP\r
- uint32_t m_MaxMessageSize; // The maximum buffer size that we allow\r
-\r
- uint32_t m_CurrentlySentBuffers; // Number of buffers that we have sent, and didn't get an ack yet\r
- uint32_t m_CurrentlyAllocated; // The number of buffers that we have allocated\r
-\r
- LinkedList m_FreePackets; // This packets are free and might be used\r
- LinkedList m_QueuedPackets; // This packets were filled with data and should be sent\r
-\r
-\r
-//?????\r
- public:\r
- LinkedList m_UserPackets; // This is a list of user packets that we should send\r
-\r
- \r
-\r
-private: //????????? \r
-\r
- // IBAL constants from the main socket structure \r
- // TODO: Should they stay here and be used like this ?\r
- ib_pd_handle_t m_pd;\r
- ib_qp_handle_t m_qp;\r
- net32_t m_lkey;\r
-\r
- // A list of events that the users has to wait on. ???? currently only one\r
-\r
- uint32_t m_SendSeq; //sequence number of last message sent (send_seq in linux)\r
- uint32_t m_AdvtSeq; // sequence number of last message acknowledged (advt_seq in linux)\r
- uint16_t m_rRecvBuf; // number of recv buffers remote currently has (r_recv_bf in linux)\r
-\r
- SdpSocket *m_pSdpSocket;\r
-\r
- /*\r
- Following two flags are responsible for sending the credits to the \r
- remote side.\r
- Since we are not allowed to send more than one more credit at a time, \r
- we have to remember if a credit is being sent, and if one is, we have\r
- to delay the send of the next credit to the time that the previous \r
- credit was sent\r
- */\r
- bool m_PostCreditsWhenCan;\r
- bool m_CreditsCurrentlyPosted;\r
- BufferDescriptor *m_CreditdBufferDescriptor;\r
- bool m_CallBackPending; // Set to true if we have requesetd a callback from \r
- // the users thread\r
-\r
- // TODO: The two counters bellow are for debug only. move them to be\r
- // declared as such\r
-public: \r
- uint32_t m_NumberOfBytesSent;\r
- uint32_t m_NumberOfBytesSentAndAcked;\r
- \r
-\r
-VOID AssertLocked();\r
-\r
-};\r
-\r
-#endif // H_SDP_BUFFER_POOL_H\r
-\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-#include "Precompile.h"\r
-\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "SdpConnectionList.tmh"\r
-#endif\r
-\r
-\r
-VOID \r
-ConnectionList::Init(SdpSocket *pSdpSocket) \r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_CONNECTION_LIST,"this = 0x%p \n", this);\r
- m_pSdpSocket = pSdpSocket;\r
- m_ClientWaiting = false;\r
- KeInitializeEvent(&m_WaitForConnection, NotificationEvent , FALSE );\r
-}\r
-\r
-\r
-/* This function is called when the user mode has called close socket\r
- If a client is waiting on recieve we free him, he should get an\r
- error on his callback. *** The caller probably has a bug - as one\r
- can't race a closesocket ***\r
-*/ \r
-\r
-VOID \r
-ConnectionList::CloseSocket()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_BUFFER_POOL, "this = 0x%p m_WaitingClients = %s\n",this,\r
- m_ClientWaiting ? "true" : "false");\r
- AssertLocked();\r
-\r
- if (m_ClientWaiting) {\r
- KeSetEvent( &m_WaitForConnection, IO_NO_INCREMENT, FALSE );\r
- m_ClientWaiting = false;\r
- }\r
- // The next time our client will try to get data, he will get \r
- // the error \r
-}\r
-\r
-\r
-VOID ConnectionList::Shutdown() \r
-{\r
- //?????AssertLocked();\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_CONNECTION_LIST,"this = 0x%p \n", this);\r
- // Go over both lists, and shutdown all their objects\r
- LIST_ENTRY *item = NULL;\r
- SdpSocket *pSocket = NULL;\r
-\r
- while (m_ReplySentConnections.Size() > 0) {\r
- item = m_ReplySentConnections.RemoveHeadList();\r
- pSocket = CONTAINING_RECORD(item, SdpSocket , m_ListeningSocketList);\r
- pSocket->Shutdown();\r
- pSocket->Release();\r
- }\r
- ASSERT(m_ReplySentConnections.Size() == 0);\r
-\r
- while (m_ReadyConnections.Size() > 0) {\r
- item = m_ReadyConnections.RemoveHeadList();\r
- pSocket = CONTAINING_RECORD(item, SdpSocket , m_ListeningSocketList);\r
- pSocket->Shutdown();\r
- pSocket->Release();\r
- }\r
- ASSERT(m_ReadyConnections.Size() == 0);\r
- \r
-}\r
-\r
-bool \r
-ConnectionList::IsFull() \r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_CONNECTION_LIST,"this = 0x%p \n", this);\r
- AssertLocked();\r
- int CurrentConnections = \r
- m_ReplySentConnections.Size() + m_ReadyConnections.Size();\r
- return CurrentConnections >= m_BackLog;\r
-}\r
-\r
-NTSTATUS \r
-ConnectionList::AddConnectionToReplySent(SdpSocket *pNewSocket) \r
-{ \r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_CONNECTION_LIST,"this = 0x%p \n", this);\r
- AssertLocked();\r
- m_ReplySentConnections.InsertTailList(&pNewSocket->m_ListeningSocketList);\r
- pNewSocket->AddRef();\r
- return 0;\r
-}\r
-\r
-// Go over the list of connections and verify that such a connection\r
-// exists\r
-NTSTATUS \r
-ConnectionList::VerifyConnictionInReplySent(SdpSocket *pNewSocket) \r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_CONNECTION_LIST,"this = 0x%p \n", this);\r
- AssertLocked();\r
- SdpSocket *pSocket = NULL;\r
-#if DBG\r
- LIST_ENTRY *item = m_ReplySentConnections.Head();\r
- for (int i = 0 ; i < m_ReplySentConnections.Size(); i++) {\r
- pSocket = CONTAINING_RECORD(item, SdpSocket , m_ListeningSocketList);\r
- if (pSocket == pNewSocket) {\r
- // We have found what we were looking for\r
- return STATUS_SUCCESS;\r
- }\r
- item = item->Flink;\r
- }\r
- // Not found, return error\r
- ASSERT(FALSE);\r
- return STATUS_UNEXPECTED_IO_ERROR;\r
-#else\r
- return STATUS_SUCCESS;\r
- \r
-#endif // DBG\r
-\r
-}\r
-\r
-VOID \r
-ConnectionList::MoveConnectionFromReplyToReady(SdpSocket *pNewSocket) \r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_CONNECTION_LIST,"this = 0x%p \n", this);\r
- AssertLocked();\r
- pNewSocket->AssertLocked();\r
- // just take it out from one list and put it in the other\r
- // This must be done through the list, in order to make sure\r
- // that the list size is being kept correctly\r
- m_ReplySentConnections.RemoveEntryList(&pNewSocket->m_ListeningSocketList);\r
- m_ReadyConnections.InsertTailList(&pNewSocket->m_ListeningSocketList);\r
-}\r
-\r
-VOID \r
-ConnectionList::FreeWaitingIfCan() \r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_CONNECTION_LIST,"this = 0x%p \n", this);\r
- AssertLocked();\r
- if (m_ClientWaiting) {\r
- ASSERT(m_ReadyConnections.Size() > 0);\r
- KeSetEvent( &m_WaitForConnection, IO_NO_INCREMENT, FALSE );\r
- m_ClientWaiting = false;\r
- }\r
-}\r
-\r
-NTSTATUS \r
-ConnectionList::AcceptAReadyConnection(\r
- SdpSocket **ppNewSocket,\r
- KEVENT **ppEvent\r
- )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_CONNECTION_LIST,"this = 0x%p \n", this);\r
-\r
- ASSERT(*ppEvent == NULL);\r
- ASSERT(*ppNewSocket == NULL);\r
- LIST_ENTRY *item = NULL;\r
-\r
- if (m_ClientWaiting) {\r
- ASSERT(m_ClientWaiting == false);\r
- // This is very likely caused because of two threads that are calling\r
- // accept (not supported currently)\r
- //?????? print ?????\r
- return STATUS_UNEXPECTED_IO_ERROR;\r
- }\r
- if (m_ReadyConnections.Size() > 0) {\r
- // We have a connection to return\r
- // TODO: This connection might be in a bad state. What should we do\r
- item = m_ReadyConnections.RemoveHeadList();\r
- *ppNewSocket = CONTAINING_RECORD(item, SdpSocket , m_ListeningSocketList);\r
- // There is no change of the referance count, since we are taking \r
- // the socket from the list, but we are also giving it to someone else\r
- return STATUS_SUCCESS; \r
- }\r
-\r
- // We don't have a ready socket to return, the caller will have\r
- // to wait\r
- KeClearEvent(&m_WaitForConnection);\r
- m_ClientWaiting = true;\r
- *ppEvent = &m_WaitForConnection;\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-VOID \r
-ConnectionList::AssertLocked() {\r
-#if DBG\r
- m_pSdpSocket->AssertLocked();\r
-#endif\r
-}\r
-\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-#ifndef H_SDP_CONNECTION_LIST_H\r
-#define H_SDP_CONNECTION_LIST_H \r
-\r
-// All functions here (including shutdown, should be called with\r
-// the lock taken)\r
-\r
-class ConnectionList {\r
-\r
-public:\r
- VOID Init(SdpSocket *pSdpSocket);\r
-\r
- VOID CloseSocket();\r
-\r
- VOID Shutdown();\r
-\r
- bool IsFull();\r
- VOID SetBackLog(int BackLog) {\r
- m_BackLog = BackLog;\r
- };\r
- NTSTATUS AddConnectionToReplySent(SdpSocket *pNewSocket);\r
-\r
- // Go over the list of connections and verify that such a connection\r
- // exists\r
- NTSTATUS VerifyConnictionInReplySent(SdpSocket *pNewSocket);\r
- \r
- VOID MoveConnectionFromReplyToReady(SdpSocket *pNewSocket);\r
-\r
- VOID FreeWaitingIfCan();\r
-\r
- NTSTATUS AcceptAReadyConnection(\r
- SdpSocket **ppNewSocket,\r
- KEVENT **ppEvent\r
- );\r
-\r
-private:\r
-\r
- VOID AssertLocked();\r
-\r
- SdpSocket *m_pSdpSocket; // No refcount as we are part of this socket\r
-\r
- int m_BackLog;\r
- LinkedList m_ReplySentConnections;\r
- LinkedList m_ReadyConnections;\r
- KEVENT m_WaitForConnection;\r
- bool m_ClientWaiting;\r
-\r
-};\r
-#endif //H_SDP_CONNECTION_LIST_H\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-#include "Precompile.h"\r
-\r
-\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "SdpDriver.tmh"\r
-#endif\r
-\r
-\r
-\r
-SdpDriver *g_pSdpDriver = NULL;\r
-\r
-FAST_IO_DISPATCH FastIoDispatch =\r
-{\r
- FIELD_OFFSET(FAST_IO_DISPATCH, FastIoDeviceControl),\r
- NULL,\r
- NULL,\r
- NULL,\r
- NULL,\r
- NULL,\r
- NULL,\r
- NULL,\r
- NULL,\r
- NULL,\r
- SdpDriver::FastDispatch\r
-};\r
-\r
-\r
-VOID DriverUnload (\r
- IN PDRIVER_OBJECT pDriverObject \r
- ) \r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER,"called pDriverObject = 0x%p\n", pDriverObject );\r
- ib_api_status_t ib_status;\r
-\r
- g_pSdpDriver->Shutdown();\r
-\r
-\r
- ib_status = ib_close_al(g_pSdpDriver->m_al_handle);\r
- g_pSdpDriver->m_al_handle = NULL;\r
- ASSERT( ib_status == IB_SUCCESS);\r
-#if defined(EVENT_TRACING)\r
- WPP_CLEANUP(pDriverObject);\r
-#endif\r
- UNICODE_STRING LinkName;\r
-\r
- RtlInitUnicodeString( &LinkName, SDP_LINK_NAME );\r
- IoDeleteSymbolicLink(&LinkName);\r
-\r
- IoDeleteDevice( g_pSdpDriver->GetDeviceObject());\r
- g_pSdpDriver = NULL;\r
-}\r
-\r
-\r
-\r
-extern "C" NTSTATUS DriverEntry (\r
- IN PDRIVER_OBJECT pDriverObject,\r
- IN PUNICODE_STRING pRegistryPath )\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- ib_api_status_t ib_status;\r
- PDEVICE_OBJECT pDevObj;\r
- SdpDriver *pSdpDriver;\r
- bool DeviceCreated = false;\r
- bool LinkCreated = false;\r
- UNICODE_STRING DevName1, LinkName;\r
- int i;\r
-#if defined(EVENT_TRACING)\r
- WPP_INIT_TRACING(pDriverObject, pRegistryPath);\r
-#endif\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER,"called\n" );\r
-\r
- // fill the device functions\r
- pDriverObject->DriverUnload = DriverUnload;\r
- pDriverObject->FastIoDispatch = NULL;\r
- pDriverObject->DriverStartIo = NULL;\r
- for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {\r
- pDriverObject->MajorFunction[i] = SdpDriver::Dispatch;\r
- }\r
-\r
- // Create the device that will be used for comunication with the user mode\r
- // Now create the device\r
-\r
- RtlInitUnicodeString( &DevName1, SDP_DEVICE_NAME );\r
- RtlInitUnicodeString( &LinkName, SDP_LINK_NAME );\r
-\r
- \r
- // BUGBUG: Should we crearte a secure device object \r
- rc = IoCreateDevice( pDriverObject,\r
- sizeof(SdpDriver),\r
- &DevName1,\r
- FILE_DEVICE_UNKNOWN,\r
- 0, \r
- FALSE,\r
- &pDevObj );\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"IoCreateDevice failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
- DeviceCreated = true;\r
-\r
- pSdpDriver = new (pDevObj->DeviceExtension) SdpDriver;\r
- rc = pSdpDriver->Init(pDevObj, pDriverObject);\r
-\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"pSdpDriver->Init failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
-\r
-\r
- // Create a Win32-accessible device object\r
- rc = IoCreateSymbolicLink(\r
- &LinkName,\r
- &DevName1 \r
- );\r
-\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"IoCreateSymbolicLink failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
- LinkCreated = true;\r
-#pragma warning( push )\r
-#pragma warning(disable: 4244 ) \r
- ib_status = ib_open_al(&pSdpDriver->m_al_handle);\r
-#pragma warning( pop )\r
- if ( ib_status != IB_SUCCESS) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"ib_open_al failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
-\r
-Cleanup:\r
- if (!NT_SUCCESS(rc)) {\r
- if (LinkCreated) {\r
- IoDeleteSymbolicLink(&LinkName);\r
-\r
- }\r
- if ( DeviceCreated ) {\r
- IoDeleteDevice(pDevObj);\r
- }\r
- }\r
- g_pSdpDriver = pSdpDriver;\r
-\r
- return rc;\r
-\r
-}\r
-\r
-// TODO: Make sure that this function is used correctly, and that\r
-// parameters are being checked well.\r
-BOOLEAN SdpDriver::FastDispatch(\r
- PFILE_OBJECT pFileObject,\r
- BOOLEAN Wait,\r
- PVOID pInputBuffer,\r
- ULONG nInputBufferLength,\r
- PVOID pOutputBuffer,\r
- ULONG nOutputBufferLength,\r
- ULONG IoControlCode,\r
- PIO_STATUS_BLOCK IoStatus,\r
- PDEVICE_OBJECT pDeviceObject\r
- )\r
-{\r
- NTSTATUS rc;\r
- ULONG nSize = 0;\r
- ASSERT(FALSE); // Don't just use this function without modifications\r
-\r
- UNREFERENCED_PARAMETER(pDeviceObject);\r
-\r
- UNREFERENCED_PARAMETER(Wait);\r
-\r
- // IOCTLs are allowed only for user mode processes\r
- if (UserMode != ExGetPreviousMode()) {\r
- return (BOOLEAN)FALSE;\r
- }\r
-\r
- __try {\r
- if (pInputBuffer || nInputBufferLength) {\r
- ProbeForRead(pInputBuffer, nInputBufferLength, sizeof(UCHAR));\r
- }\r
- } __except(EXCEPTION_EXECUTE_HANDLER) { //??? what should I do\r
- ASSERT(FALSE);\r
- pInputBuffer = NULL;\r
- nInputBufferLength = 0;\r
- }\r
-\r
- __try {\r
- if (pOutputBuffer || nOutputBufferLength) {\r
- ProbeForWrite(pOutputBuffer, nOutputBufferLength, sizeof(UCHAR));\r
- }\r
- } __except(EXCEPTION_EXECUTE_HANDLER) {\r
- ASSERT(FALSE);\r
- pOutputBuffer = NULL;\r
- nOutputBufferLength = 0;\r
- }\r
-\r
- IO_STACK_LOCATION isl;\r
- isl.FileObject = pFileObject;\r
-\r
- // Dispatch the request\r
- rc = g_pSdpDriver->DispatchDeviceIoControl(\r
- NULL,\r
- NULL,\r
- &isl,\r
- pInputBuffer,\r
- nInputBufferLength,\r
- pOutputBuffer,\r
- nOutputBufferLength,\r
- IoControlCode,\r
- nSize\r
- );\r
-\r
- if (rc != STATUS_PENDING) {\r
- IoStatus->Information = nSize;\r
- IoStatus->Status = rc;\r
- }\r
-\r
- return ((rc == STATUS_PENDING) ? (BOOLEAN)FALSE : (BOOLEAN)TRUE);\r
-}\r
-\r
-\r
-\r
-NTSTATUS SdpDriver::Dispatch(\r
- IN PDEVICE_OBJECT pDeviceObject,\r
- IN PIRP pIrp\r
- )\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- PIO_STACK_LOCATION pIrpSp;\r
- pIrp->IoStatus.Status = STATUS_SUCCESS;\r
- pIrp->IoStatus.Information = 0;\r
- PVOID pInputBuffer = NULL;\r
- PVOID pOutputBuffer = NULL;\r
- ULONG OutputDataSize = 0;\r
- int Method;\r
- SdpUserFile *pSdpUserFile = NULL;\r
-\r
- pIrpSp = IoGetCurrentIrpStackLocation(pIrp);\r
-\r
- switch (pIrpSp->MajorFunction) {\r
-\r
- case IRP_MJ_CREATE: {\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER, "IRP_MJ_CREATE pIrpSp->FileObject = 0x%p\n", \r
- pIrpSp->FileObject );\r
- pSdpUserFile = new SdpUserFile;\r
- if (pSdpUserFile == NULL) {\r
- rc = STATUS_NO_MEMORY;\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"new SdpUserFile failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- } \r
- rc = pSdpUserFile->Init();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"pSdpUserFile->Init failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
- // Everything went well, and windows is still using this object.\r
- // As a result we want to make sure that this object will not be\r
- // freed\r
- pIrpSp->FileObject->FsContext = pSdpUserFile;\r
- pSdpUserFile = NULL;\r
- \r
-\r
- break;\r
- }\r
- case IRP_MJ_CLEANUP: {\r
- // All IRPs that were associated with this device should be cleaned\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER,"IRP_MJ_CLEANUP pIrpSp->FileObject = 0x%p\n", \r
- pIrpSp->FileObject );\r
- pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
- // The object is being shutdown, and it's cleaning should\r
- // be started\r
- pSdpUserFile->Shutdown();\r
- // The file object is still holding referance to the object,\r
- // so we set the pointer to NULL\r
- pSdpUserFile = NULL;\r
- \r
- break;\r
-\r
- }\r
-\r
- case IRP_MJ_CLOSE: { \r
- // Receipt of this request indicates that the last handle of the file object \r
- // that is associated with the target device object has been closed and \r
- //released. All outstanding I/O requests have been completed or canceled.\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER, "IRP_MJ_CLOSE pIrpSp->FileObject = 0x%p\n", \r
- pIrpSp->FileObject);\r
- pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
- // Nothing to do, the referance count will be removed once\r
- // we leave the function\r
- break;\r
- }\r
- case IRP_MJ_DEVICE_CONTROL: {\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_DRIVER,"IRP_MJ_DEVICE_CONTROL pIrpSp->FileObject = 0x%p\n", \r
- pIrpSp->FileObject);\r
-\r
- // IOCTLs are allowed only for user mode processes\r
- if (UserMode != pIrp->RequestorMode) {\r
- rc = STATUS_ACCESS_DENIED;\r
- break;\r
- }\r
-\r
- // Handle the mode of the request and get it's params\r
- Method = pIrpSp->Parameters.DeviceIoControl.IoControlCode & 0x3;\r
- switch (Method) {\r
- case METHOD_BUFFERED: {\r
- pInputBuffer = pOutputBuffer = \r
- pIrp->AssociatedIrp.SystemBuffer;\r
- break;\r
- }\r
-\r
- case METHOD_IN_DIRECT:\r
- case METHOD_OUT_DIRECT: {\r
- pInputBuffer = pIrp->AssociatedIrp.SystemBuffer;\r
- if (pIrp->MdlAddress && \r
- pIrpSp->Parameters.DeviceIoControl.OutputBufferLength) {\r
- if (NULL == (pOutputBuffer = \r
- MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, LowPagePriority))) {\r
- rc = STATUS_INSUFFICIENT_RESOURCES;\r
- goto Cleanup;\r
- }\r
- }\r
- break;\r
- }\r
-\r
- case METHOD_NEITHER: {\r
- pInputBuffer = \r
- pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer;\r
- pOutputBuffer = pIrp->UserBuffer;\r
- break;\r
- }\r
- }\r
-\r
- // If 'METHOD_NEITHER' probe the buffer\r
- if (METHOD_NEITHER == Method) {\r
-\r
- __try {\r
-\r
- if (pInputBuffer) {\r
- ProbeForRead(\r
- pInputBuffer, \r
- pIrpSp->Parameters.DeviceIoControl.InputBufferLength,\r
- sizeof(UCHAR)\r
- );\r
- }\r
- if (pOutputBuffer) {\r
- ProbeForWrite(\r
- pOutputBuffer,\r
- pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,\r
- sizeof(UCHAR)\r
- );\r
- }\r
-\r
- } __except(EXCEPTION_EXECUTE_HANDLER) {\r
- rc = STATUS_ACCESS_VIOLATION;\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"IRP_MJ_DEVICE_CONTROL Access "\r
- "violition when trying to read/write data\n");\r
- \r
- ASSERT(FALSE);\r
- goto Cleanup;\r
- }\r
- }\r
-\r
-\r
- // Handle the request itself\r
- rc = g_pSdpDriver->DispatchDeviceIoControl(\r
- pIrpSp->FileObject,\r
- pIrp,\r
- pIrpSp,\r
- pInputBuffer,\r
- pIrpSp->Parameters.DeviceIoControl.InputBufferLength,\r
- pOutputBuffer,\r
- pIrpSp->Parameters.DeviceIoControl.OutputBufferLength,\r
- pIrpSp->Parameters.DeviceIoControl.IoControlCode,\r
- OutputDataSize\r
- );\r
-\r
- break;\r
- \r
- } \r
- }\r
-\r
-Cleanup:\r
- if (rc != STATUS_PENDING) {\r
- pIrp->IoStatus.Status = rc;\r
- pIrp->IoStatus.Information = OutputDataSize;\r
- IoCompleteRequest(pIrp, IO_NO_INCREMENT);\r
- }\r
- if (pSdpUserFile) {\r
- pSdpUserFile->Release();\r
- }\r
- return rc;\r
-}\r
-\r
-// A macro to verify input/output params length\r
-#define VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, InStruct, OutStruct) \\r
-if ((InputBufferLength < sizeof (InStruct)) || \\r
- (OutputBufferLength < sizeof (OutStruct))) { \\r
- /*SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER, "DispatchDeviceIoControl bad buffer sizes\n" ); */ \\r
- ASSERT(FALSE); \\r
- rc = STATUS_ACCESS_VIOLATION; \\r
- goto Cleanup; \\r
-}\r
-\r
-NTSTATUS \r
-SdpDriver::Init(PDEVICE_OBJECT pDevObj, PDRIVER_OBJECT DriverObject) \r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- m_pDevObj = pDevObj;\r
- m_pSdpArp = new SdpArp;\r
- if (m_pSdpArp == NULL) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"new SdpArp failed \n"); \r
- rc = STATUS_NO_MEMORY;\r
- goto Cleanup;\r
- }\r
- rc = m_pSdpArp->Init(DriverObject);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"m_pSdpArp->Init failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
- \r
- ExInitializeFastMutex(&m_ThreadsMutex);\r
- \r
-Cleanup:\r
- if (!NT_SUCCESS(rc)) {\r
- if (m_pSdpArp) {\r
- m_pSdpArp->Shutdown();\r
- delete m_pSdpArp;\r
- }\r
- }\r
- return rc;\r
-}\r
-\r
-VOID \r
-SdpDriver::Shutdown()\r
-{\r
- m_pSdpArp->Shutdown();\r
- WaitForAllThreadsToDie();\r
-\r
-}\r
-\r
-NTSTATUS \r
-SdpDriver::DispatchDeviceIoControl(\r
- IN PFILE_OBJECT pDeviceObject,\r
- IN PIRP pIrp,\r
- IN PIO_STACK_LOCATION pIrpSp,\r
- IN PVOID pInputBuffer,\r
- IN ULONG InputBufferLength,\r
- IN PVOID pOutputBuffer,\r
- IN ULONG OutputBufferLength,\r
- IN ULONG IoControlCode,\r
- OUT ULONG &OutputDataSize\r
- )\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- SdpUserFile *pSdpUserFile = NULL;\r
- SdpSocket *pSdpSocket = NULL;\r
- SdpSocket *pAcceptedSdpSocket = NULL;\r
- \r
- switch (IoControlCode) {\r
- case IOCTL_WSP_SOCKET :\r
- {\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER,"IOCTL_WSP_SOCKET recieved\n" ); \r
- VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, WspSocketIn, WspSocketOut);\r
- OutputDataSize = sizeof (WspSocketOut);\r
-\r
- WspSocketIn wspSocketIn = *(WspSocketIn *) pInputBuffer;\r
- WspSocketOut *pWspSocketOut = (WspSocketOut *) pOutputBuffer;\r
- \r
- pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
- pSdpSocket = new SdpSocket;\r
- if (pSdpSocket == NULL) {\r
- rc = STATUS_NO_MEMORY;\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"new SdpSocket failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
- rc = pSdpSocket->Init(&wspSocketIn, pWspSocketOut, pSdpUserFile);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"pSdpSocket->Init failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
- rc = pSdpUserFile->AddSocket(pSdpSocket);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"pSdpUserFile->AddSocket failed rc = 0x%x\n", rc );\r
- pSdpSocket->Shutdown();\r
- goto Cleanup;\r
- } \r
- }\r
- break;\r
-\r
- case IOCTL_WSP_CONNECT :\r
- {\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER,"IOCTL_WSP_CONNECT recieved\n" ); \r
- VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, WspConnectIn, WspConnectOut);\r
- OutputDataSize = sizeof (WspConnectOut);\r
-\r
- // get the socket based on the users pointer\r
- WspConnectIn wspConnectIn = *(WspConnectIn *) pInputBuffer;\r
- WspConnectOut *pWspConnectOut = (WspConnectOut *) pOutputBuffer;\r
- pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
- pSdpSocket = pSdpUserFile->SocketByPointer(wspConnectIn.pSocket);\r
- if (pSdpSocket == NULL) {\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_DRIVER,"IOCTL_WSP_CONNECT socket %p not found\n",wspConnectIn.pSocket); \r
- // This is a well defined winsock error\r
- pWspConnectOut->Errno = WSAENOTSOCK;\r
- goto Cleanup;\r
- }\r
- rc = pSdpSocket->WSPConnect(&wspConnectIn, pWspConnectOut);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"pSdpSocket->WSPConnect failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
- }\r
- break;\r
-\r
- case IOCTL_WSP_SEND :\r
- {\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_DRIVER,"IOCTL_WSP_SEND recieved\n" ); \r
- VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, WspSendIn, WspSendOut);\r
- OutputDataSize = sizeof (WspSendOut);\r
-\r
- // get the socket based on the users pointer\r
- WspSendIn wspSendIn = *(WspSendIn *) pInputBuffer;\r
- WspSendOut *pWspSendOut = (WspSendOut *) pOutputBuffer;\r
- pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
- pSdpSocket = pSdpUserFile->SocketByPointer(wspSendIn.pSocket);\r
- if (pSdpSocket == NULL) {\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_DRIVER,"IOCTL_WSP_SEND socket %p not found\n",wspSendIn.pSocket); \r
- // This is a well defined winsock error\r
- pWspSendOut->Errno = WSAENOTSOCK;\r
- goto Cleanup;\r
- }\r
- rc = pSdpSocket->WSPSend(&wspSendIn, pWspSendOut, pIrp);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"pSdpSocket->WSPSend failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
- }\r
- break;\r
-\r
- case IOCTL_WSP_RECV :\r
- {\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_DRIVER,"IOCTL_WSP_RECV recieved\n" ); \r
- VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, WspRecvIn, WspRecvOut);\r
- OutputDataSize = sizeof (WspRecvOut);\r
-\r
- // get the socket based on the users pointer\r
- WspRecvIn wspRecvIn = *(WspRecvIn *) pInputBuffer;\r
- WspRecvOut *pWspRecvOut = (WspRecvOut *) pOutputBuffer;\r
- pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
- pSdpSocket = pSdpUserFile->SocketByPointer(wspRecvIn.pSocket);\r
- if (pSdpSocket == NULL) {\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_DRIVER,"IOCTL_WSP_RECV socket %p not found\n",wspRecvIn.pSocket); \r
- // This is a well defined winsock error\r
- pWspRecvOut->Errno = WSAENOTSOCK;\r
- goto Cleanup;\r
- }\r
- rc = pSdpSocket->WSPRecv(&wspRecvIn, pWspRecvOut);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"pSdpSocket->WSPRecv failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
- }\r
- break;\r
-\r
- case IOCTL_WSP_BIND:\r
- {\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER,"IOCTL_WSP_BIND recieved\n" ); \r
- VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, WspBindIn, WspBindOut);\r
- OutputDataSize = sizeof (WspBindOut);\r
-\r
- // get the socket based on the users pointer\r
- WspBindIn wspBindIn = *(WspBindIn *) pInputBuffer;\r
- WspBindOut *pWspBindOut = (WspBindOut *) pOutputBuffer;\r
- pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
- pSdpSocket = pSdpUserFile->SocketByPointer(wspBindIn.pSocket);\r
- if (pSdpSocket == NULL) {\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_DRIVER,"IOCTL_WSP_BIND socket %p not found\n", wspBindIn.pSocket); \r
- // This is a well defined winsock error\r
- pWspBindOut->Errno = WSAENOTSOCK;\r
- goto Cleanup;\r
- }\r
- rc = pSdpSocket->WSPBind(&wspBindIn, pWspBindOut);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"pSdpSocket->WSPBind failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
- }\r
- break;\r
-\r
- case IOCTL_WSP_LISTEN:\r
- {\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER,"IOCTL_WSP_LISTEN recieved\n" ); \r
- VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, WspListenIn, WspListenOut);\r
- OutputDataSize = sizeof (WspListenOut);\r
-\r
- // get the socket based on the users pointer\r
- WspListenIn wspListenIn = *(WspListenIn *) pInputBuffer;\r
- WspListenOut *pWspListenOut = (WspListenOut *) pOutputBuffer;\r
- pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
- pSdpSocket = pSdpUserFile->SocketByPointer(wspListenIn.pSocket);\r
- if (pSdpSocket == NULL) {\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_DRIVER,"IOCTL_WSP_LISTEN socket %p not found\n",wspListenIn.pSocket); \r
- // This is a well defined winsock error\r
- pWspListenOut->Errno = WSAENOTSOCK;\r
- goto Cleanup;\r
- }\r
- rc = pSdpSocket->WSPListen(&wspListenIn, pWspListenOut);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"pSdpSocket->WSPListen failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
- }\r
- break;\r
-\r
- case IOCTL_WSP_ACCEPT:\r
- {\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER,"IOCTL_WSP_ACCEPT recieved\n" ); \r
- VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, WspAcceptIn, WspAcceptOut);\r
- OutputDataSize = sizeof (WspAcceptOut);\r
-\r
- // get the socket based on the users pointer\r
- WspAcceptIn wspAcceptIn = *(WspAcceptIn *) pInputBuffer;\r
- WspAcceptOut *pWspAcceptOut = (WspAcceptOut *) pOutputBuffer;\r
- pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
- pSdpSocket = pSdpUserFile->SocketByPointer(wspAcceptIn.pSocket);\r
- if (pSdpSocket == NULL) {\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_DRIVER,"IOCTL_WSP_ACCEPT socket %p not found\n",wspAcceptIn.pSocket); \r
- // This is a well defined winsock error\r
- pWspAcceptOut->Errno = WSAENOTSOCK;\r
- goto Cleanup;\r
- }\r
- rc = pSdpSocket->WSPAccept(&wspAcceptIn, pWspAcceptOut);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"pSdpSocket->WSPAccept failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
- if (pWspAcceptOut->pAccaptedSocket != NULL) {\r
- pAcceptedSdpSocket = (SdpSocket *) pWspAcceptOut->pAccaptedSocket;\r
- rc = pSdpUserFile->AddSocket(pAcceptedSdpSocket);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"pSdpUserFile->AddSocket failed rc = 0x%x\n", rc );\r
- pAcceptedSdpSocket->Shutdown();\r
- goto Cleanup;\r
- } \r
- }\r
- }\r
- break;\r
-\r
- case IOCTL_WSP_GET_XXX_NAME:\r
- {\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER,"IOCTL_WSP_GET_XXX_NAME recieved\n" ); \r
- VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, WspGetSockXXIn, WspGetSockXXOut);\r
- OutputDataSize = sizeof (WspGetSockXXOut);\r
-\r
- // get the socket based on the users pointer\r
- WspGetSockXXIn wspGetSockXXin = *(WspGetSockXXIn *) pInputBuffer;\r
- WspGetSockXXOut *pWspGetSockXXOut = (WspGetSockXXOut *) pOutputBuffer;\r
- pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
- pSdpSocket = pSdpUserFile->SocketByPointer(wspGetSockXXin.pSocket);\r
- if (pSdpSocket == NULL) {\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_DRIVER,"IOCTL_WSP_GET_XXX_NAME socket %p not found\n", wspGetSockXXin.pSocket); \r
- // This is a well defined winsock error\r
- pWspGetSockXXOut->Errno = WSAENOTSOCK;\r
- goto Cleanup;\r
- }\r
- rc = pSdpSocket->WSPGetXXXName(&wspGetSockXXin, pWspGetSockXXOut);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"pSdpSocket->WSPGetXXXName failed rc = 0x%x\n", rc ); \r
- goto Cleanup;\r
- }\r
- }\r
- break;\r
- case IOCTL_WSP_CLOSE_SOCKET :\r
- {\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER,"IOCTL_WSP_CLOSE_SOCKET recieved\n" ); \r
- VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, WspSocketCloseIn, WspSocketCloseOut);\r
- OutputDataSize = sizeof (WspSocketCloseOut);\r
-\r
- // get the socket based on the users pointer\r
- WspSocketCloseIn wspSocketCloseIn = *(WspSocketCloseIn *) pInputBuffer;\r
- WspSocketCloseOut *pWspSocketCloseOut = (WspSocketCloseOut *) pOutputBuffer;\r
- pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
- pSdpSocket = pSdpUserFile->SocketByPointer(wspSocketCloseIn.pSocket);\r
- if (pSdpSocket == NULL) {\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_DRIVER,"IOCTL_WSP_CLOSE_SOCKET socket %p not found\n",wspSocketCloseIn.pSocket); \r
- // This is a well defined winsock error\r
- pWspSocketCloseOut->Errno = WSAENOTSOCK;\r
- goto Cleanup;\r
- }\r
- rc = pSdpSocket->WSPCloseSocket(&wspSocketCloseIn, pWspSocketCloseOut);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"pSdpSocket->WSPCloseSocket failed rc = 0x%x\n", rc ); \r
- goto Cleanup; \r
- }\r
- }\r
- break;\r
-\r
- case IOCTL_WSP_USER_THREAD :\r
- {\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_DRIVER, "IOCTL_WSP_USER_THREAD recieved\n" ); \r
- pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
-\r
- /* Ignore Error = */ pSdpUserFile->UsersThread();\r
- }\r
- break;\r
- \r
- default:\r
- // This is an unrecgnized IOCTL\r
- ASSERT(FALSE);\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_DRIVER,"unknow IOCTL code = 0x%x\n", IoControlCode );\r
- rc = STATUS_INVALID_PARAMETER;\r
- goto Cleanup;\r
-\r
- \r
- }\r
-Cleanup:\r
- if (pSdpSocket) {\r
- pSdpSocket->Release();\r
- }\r
- if (pAcceptedSdpSocket) {\r
- pAcceptedSdpSocket->Release();\r
- }\r
- \r
- return rc;\r
-}\r
-\r
-VOID \r
-SdpDriver::AddThread(ThreadHandle *pThreadHandle)\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER,"this = 0x%p\n", this );\r
- // Check if there is any next thread that can be removed from the queue\r
- LARGE_INTEGER WaitTime;\r
- WaitTime.QuadPart = 0; // Don't wait for them to die\r
-\r
- ExAcquireFastMutex(&m_ThreadsMutex);\r
-\r
- WaitForThreadsToDie(&WaitTime);\r
-\r
- // Add me to the list of threads that should be removed\r
- m_ShutDownThreads.InsertTailList(&pThreadHandle->m_List);\r
- ExReleaseFastMutex(&m_ThreadsMutex);\r
-\r
-}\r
-\r
-VOID \r
-SdpDriver::WaitForAllThreadsToDie()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER,"this = 0x%p\n", this );\r
-\r
- ExAcquireFastMutex(&m_ThreadsMutex);\r
- // Timeout of null will cause a wait forever\r
- WaitForThreadsToDie(NULL);\r
- ExReleaseFastMutex(&m_ThreadsMutex);\r
-}\r
-\r
-\r
-// This function has to be called with the mutex held\r
-VOID \r
-SdpDriver::WaitForThreadsToDie(LARGE_INTEGER *pWaitTime)\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER,"this = 0x%p\n", this );\r
- // Check if there is any next thread that can be removed from the queue\r
- NTSTATUS rc = STATUS_SUCCESS;\r
-\r
- LIST_ENTRY *pNextItem;\r
- ThreadHandle *pNextThreadHandle;\r
- while (m_ShutDownThreads.Size() > 0) {\r
- pNextItem = m_ShutDownThreads.Head();\r
- pNextThreadHandle = CONTAINING_RECORD(pNextItem, ThreadHandle, m_List);\r
-\r
- rc = MyKeWaitForSingleObject(\r
- pNextThreadHandle->ThreadObject, \r
- Executive,\r
- KernelMode,\r
- FALSE,\r
- pWaitTime\r
- );\r
- ASSERT((rc == STATUS_SUCCESS) ||\r
- (rc == STATUS_TIMEOUT));\r
-\r
- if (rc == STATUS_TIMEOUT) {\r
- // Nothing that we should do, the thread is not ready yet\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER,"this = 0x%p Former thread is not dead yet\n", this );\r
- break;\r
- }\r
- // SUCESS means that the thread is dead, we can remove it\r
- // from the list\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_DRIVER,"this = 0x%p Former thread is already dead\n", this );\r
-\r
- m_ShutDownThreads.RemoveHeadList();\r
- ObDereferenceObject(pNextThreadHandle->ThreadObject);\r
- delete pNextThreadHandle;\r
- \r
- // We now continue and try to remove the next object\r
-\r
- }\r
-\r
-}\r
-\r
-\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-#ifndef H_SDP_DRIVER_H\r
-#define H_SDP_DRIVER_H \r
-\r
-// This struct is being used to hold an object that we can wait on\r
-// for threads to die.\r
-\r
-struct ThreadHandle {\r
- // As this object has a simple life cycle I don't use refferance counting\r
- // for it. This might have to change.\r
- PVOID ThreadObject;\r
- LIST_ENTRY m_List;\r
-};\r
-\r
-\r
-class SdpDriver {\r
-public:\r
- SdpDriver() {\r
- m_al_handle = NULL;\r
- m_pDevObj = NULL;\r
- m_pSdpArp = NULL;\r
- }\r
- \r
- NTSTATUS Init(PDEVICE_OBJECT pDevObj, PDRIVER_OBJECT DriverObject);\r
-\r
- VOID Shutdown();\r
- \r
- PDEVICE_OBJECT GetDeviceObject() {\r
- return m_pDevObj;\r
- }\r
-\r
- static \r
- NTSTATUS Dispatch(\r
- IN PDEVICE_OBJECT pDeviceObject,\r
- IN PIRP pIrp\r
- );\r
-\r
- static \r
- BOOLEAN FastDispatch(\r
- PFILE_OBJECT pFileObject,\r
- BOOLEAN Wait,\r
- PVOID pInputBuffer,\r
- ULONG nInputBufferLength,\r
- PVOID pOutputBuffer,\r
- ULONG nOutputBufferLength,\r
- ULONG IoControlCode,\r
- PIO_STATUS_BLOCK IoStatus,\r
- PDEVICE_OBJECT pDeviceObject\r
- );\r
-\r
-\r
- NTSTATUS DispatchDeviceIoControl(\r
- IN PFILE_OBJECT pDeviceObject,\r
- IN PIRP pIrp,\r
- IN PIO_STACK_LOCATION pIrpSp,\r
- IN PVOID pInputBuffer,\r
- IN ULONG InputBufferLength,\r
- IN PVOID pOutputBuffer,\r
- IN ULONG OutputBufferLength,\r
- IN ULONG IoControlCode,\r
- OUT ULONG &OutputDataSize\r
- );\r
-\r
- // The following functions are being used so that the driver\r
- // will wait for all the created threads to end\r
- VOID AddThread(ThreadHandle *pThreadHandle);\r
-\r
- VOID WaitForAllThreadsToDie(); \r
-\r
-public:\r
- ib_al_handle_t m_al_handle ;\r
- SdpArp *m_pSdpArp;\r
-\r
-\r
-private:\r
-\r
- VOID WaitForThreadsToDie(LARGE_INTEGER *pWWaitTime);\r
-\r
-\r
- PDEVICE_OBJECT m_pDevObj;\r
-\r
- LinkedList m_ShutDownThreads;\r
-\r
- FAST_MUTEX m_ThreadsMutex;\r
- \r
-};\r
-\r
-extern SdpDriver *g_pSdpDriver;\r
-\r
-#endif //H_SDP_DRIVER_H\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-#include "Precompile.h"\r
-\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "SdpGenUtils.tmh"\r
-#endif\r
-\r
-//#define DONT_COPY_DATA\r
-\r
-USHORT ntohs(USHORT in)\r
-{\r
- return ((in & 0xff) << 8) | ((in & 0xff00) >> 8);\r
-}\r
-\r
-NTSTATUS IB2Status (ib_api_status_t ib_status)\r
-{\r
- if ( ib_status == IB_SUCCESS ) {\r
- return STATUS_SUCCESS;\r
- } if (( ib_status > IB_SUCCESS ) && (ib_status < IB_UNKNOWN_ERROR)) {\r
-//\r
-// Values are 32 bit values layed out as follows:\r
-//\r
-// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1\r
-// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0\r
-// +---+-+-+-----------------------+-------------------------------+\r
-// |Sev|C|R| Facility | Code |\r
-// +---+-+-+-----------------------+-------------------------------+\r
-\r
- return 0xcc000000 | ib_status; \r
- }\r
-\r
-\r
- // Keep translating as the error pops\r
- ASSERT(FALSE);\r
- return STATUS_UNEXPECTED_IO_ERROR;\r
-\r
-}\r
-\r
-// BUGBUG: Understand how to reomove the 20 from the code.\r
-// This function is a wrapper for the KeWaitForSingleObject that adds\r
-// assertsions to the valuas returned by it\r
-NTSTATUS \r
- MyKeWaitForSingleObject(\r
- IN PVOID Object,\r
- IN KWAIT_REASON WaitReason,\r
- IN KPROCESSOR_MODE WaitMode,\r
- IN BOOLEAN Alertable,\r
- IN PLARGE_INTEGER Timeout OPTIONAL\r
- )\r
-{\r
- NTSTATUS rc;\r
- for (int i=0; i < 20; i++) {\r
- rc = KeWaitForSingleObject(\r
- Object,\r
- WaitReason,\r
- WaitMode,\r
- Alertable,\r
- Timeout\r
- );\r
- if (!NT_SUCCESS(rc)) {\r
- ASSERT(FALSE);\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"KeWaitForSingleObject failed rc = 0x%x\n", rc );\r
- // No meter what we do the program can't continue, let's crush it\r
- int *i = NULL;\r
- *i = 5;\r
- }\r
- ASSERT((rc == STATUS_SUCCESS ) ||\r
- (rc == STATUS_ALERTED ) ||\r
- (rc == STATUS_USER_APC ) ||\r
- (rc == STATUS_TIMEOUT )); // This are simply all the return code from DDK\r
- \r
- ASSERT( (Timeout != NULL ) || rc != STATUS_TIMEOUT);\r
- if (rc != STATUS_USER_APC) {\r
- break;\r
- } else {\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET,"KeWaitForSingleObject was stoped because of STATUS_USER_APC\n" );\r
- }\r
- }\r
- if (i == 20) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"!!!! KeWaitForSingleObject was Exhausted STATUS_USER_APC\n" );\r
- // This is probably fine if we are runnign for a user thread\r
- ASSERT((WaitReason == UserRequest) && (WaitMode == UserMode));\r
- }\r
- return rc;\r
-}\r
-\r
-NTSTATUS\r
-CopyFromUser(\r
- IN void* const p_dest,\r
- IN const void* const p_src,\r
- IN const size_t count )\r
-{\r
- /*\r
- * The memory copy must be done within a try/except block as the\r
- * memory could be changing while the buffer is copied.\r
- */\r
- __try\r
- {\r
- ProbeForRead( (void*)p_src, count, 1 );\r
-#ifdef DONT_COPY_DATA \r
- if (count < 1000){\r
- RtlCopyMemory( p_dest, p_src, count );\r
- }\r
-#else\r
- RtlCopyMemory( p_dest, p_src, count );\r
-#endif\r
- return STATUS_SUCCESS;\r
- }\r
- __except(EXCEPTION_EXECUTE_HANDLER)\r
- {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"copying memory from user failed\n");\r
- ASSERT(FALSE); \r
- return STATUS_ACCESS_DENIED;\r
- }\r
-}\r
-\r
-NTSTATUS\r
-CopyToUser(\r
- IN void* const p_dest,\r
- IN const void* const p_src,\r
- IN const size_t count \r
- )\r
-{\r
- /*\r
- * The memory copy must be done within a try/except block as the\r
- * memory could be changing while the buffer is copied.\r
- */\r
- __try\r
- {\r
- ProbeForWrite( p_dest, count, 1 );\r
-#ifdef DONT_COPY_DATA \r
- if (count < 1000){\r
- RtlCopyMemory( p_dest, p_src, count );\r
- }\r
-#else\r
- RtlCopyMemory( p_dest, p_src, count );\r
-#endif\r
- return CL_SUCCESS;\r
- }\r
- __except(EXCEPTION_EXECUTE_HANDLER)\r
- {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"copying memory from user failed\n");\r
- ASSERT(FALSE); \r
- return STATUS_ACCESS_DENIED;\r
- }\r
-}\r
-\r
-VOID UpdateRc(NTSTATUS *rc, NTSTATUS rc1)\r
-{\r
- // We want to keep the first errro\r
- if (NT_SUCCESS(*rc)) {\r
- *rc = rc1;\r
- }\r
-}\r
-\r
-int abs(int i){\r
- if (i > 0) return i;\r
- return -i;\r
-}\r
-\r
-LARGE_INTEGER TimeFromLong(ULONG HandredNanos)\r
-{\r
- LARGE_INTEGER Timeout;\r
- Timeout.HighPart = 0xffffffff;\r
- Timeout.LowPart = 0xffffffff ^ HandredNanos;\r
- return Timeout;\r
-}\r
-\r
-NTSTATUS Sleep(ULONG HandredNanos)\r
-{\r
- KEVENT Event;\r
- NTSTATUS rc = STATUS_SUCCESS;\r
-\r
- KeInitializeEvent(&Event, NotificationEvent , FALSE );\r
-\r
- LARGE_INTEGER Timeout = TimeFromLong(HandredNanos);\r
-\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_BUFFER_POOL,"Before Sleep\n"); \r
- rc = MyKeWaitForSingleObject(\r
- &Event,\r
- UserRequest,\r
- UserMode,\r
- FALSE,\r
- &Timeout); \r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_BUFFER_POOL,"After Sleep rc = 0x%x\n", rc);\r
- return rc;\r
-\r
-}\r
-\r
-/* Convert an IBAL error to a Winsock error. */\r
-int IbalToWsaError(const ib_api_status_t ib_status )\r
-{\r
- switch( ib_status )\r
- {\r
- case IB_SUCCESS:\r
- return 0;\r
-\r
- case IB_INVALID_QP_HANDLE:\r
- return WSAENOTCONN;\r
-\r
- case IB_INVALID_PARAMETER:\r
- return WSAEINVAL;\r
-\r
- case IB_INSUFFICIENT_RESOURCES:\r
- return WSAENOBUFS;\r
-\r
- case IB_INVALID_WR_TYPE:\r
- return WSAEINVAL;\r
-\r
- case IB_INVALID_QP_STATE:\r
- return WSAENOTCONN;\r
-\r
- default:\r
- return WSAEINVAL;\r
- }\r
-}\r
-\r
-void* __cdecl operator new(size_t n ) throw() {\r
- return ExAllocatePoolWithTag(NonPagedPool , n, GLOBAL_ALLOCATION_TAG);\r
-}\r
-\r
-void __cdecl operator delete(void* p) {\r
- ExFreePoolWithTag(p, GLOBAL_ALLOCATION_TAG);\r
-}\r
-\r
-void* __cdecl operator new(size_t n, void *addr ) throw() {\r
- return addr;\r
-}\r
-\r
-\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-#ifndef _SDP_GEN_UTILS_H\r
-#define _SDP_GEN_UTILS_H\r
-\r
-\r
-\r
-#define GLOBAL_ALLOCATION_TAG ' pdS'\r
-#define SEND_BUFFERS_ALLOCATION_TAG 'SpdS'\r
-#define RECV_BUFFERS_ALLOCATION_TAG 'RpdS'\r
-\r
-\r
-class CSpinLockWrapper {\r
- KSPIN_LOCK &m_SpinLock;\r
- KIRQL m_OldIrql;\r
-\r
-public:\r
-\r
- CSpinLockWrapper (KSPIN_LOCK &SpinLock) : m_SpinLock(SpinLock){\r
- // Spinlock must already be initialized\r
-#if DBG\r
- m_OldIrql = 0xff;\r
-#endif\r
- }\r
- \r
- void Lock() {\r
- ASSERT(m_OldIrql == 0xff);\r
- KeAcquireSpinLock(&m_SpinLock, &m_OldIrql);\r
- }\r
-\r
- void Unlock() {\r
- ASSERT(m_OldIrql != 0xff);\r
- KeReleaseSpinLock(&m_SpinLock, m_OldIrql);\r
-#if DBG \r
- m_OldIrql = 0xff;\r
-#endif\r
- }\r
-\r
- ~CSpinLockWrapper() {\r
- ASSERT(m_OldIrql == 0xff);\r
- }\r
-\r
-};\r
-\r
-NTSTATUS IB2Status (ib_api_status_t ib_status); \r
-\r
-USHORT nthos(USHORT in);\r
-\r
-NTSTATUS \r
- MyKeWaitForSingleObject(\r
- IN PVOID Object,\r
- IN KWAIT_REASON WaitReason,\r
- IN KPROCESSOR_MODE WaitMode,\r
- IN BOOLEAN Alertable,\r
- IN PLARGE_INTEGER Timeout OPTIONAL\r
- );\r
-\r
-\r
-NTSTATUS\r
-CopyFromUser(\r
- IN void* const p_dest,\r
- IN const void* const p_src,\r
- IN const size_t count \r
- );\r
-\r
-NTSTATUS\r
-CopyToUser(\r
- IN void* const p_dest,\r
- IN const void* const p_src,\r
- IN const size_t count \r
- );\r
-\r
-VOID UpdateRc(NTSTATUS *rc, NTSTATUS rc1);\r
-\r
-int abs(int i);\r
-\r
-LARGE_INTEGER TimeFromLong(ULONG HandredNanos);\r
-\r
-NTSTATUS Sleep(ULONG HandredNanos);\r
-\r
-void* __cdecl operator new(size_t n, void *addr ) throw();\r
-\r
-/* Convert an IBAL error to a Winsock error. */\r
-int IbalToWsaError(const ib_api_status_t ib_status );\r
-\r
-#define INADDR_ANY (ULONG)0x00000000\r
-#define INADDR_LOOPBACK 0x7f000001\r
-\r
-// This error codes are taken from winsock2.h (the file can not)\r
-// be included from kernel mode\r
-\r
-/*\r
- * All Windows Sockets error constants are biased by WSABASEERR from\r
- * the "normal"\r
- */\r
-#define WSABASEERR 10000\r
-\r
-/*\r
- * Windows Sockets definitions of regular Microsoft C error constants\r
- */\r
-#define WSAEINTR (WSABASEERR+4)\r
-#define WSAEBADF (WSABASEERR+9)\r
-#define WSAEACCES (WSABASEERR+13)\r
-#define WSAEFAULT (WSABASEERR+14)\r
-#define WSAEINVAL (WSABASEERR+22)\r
-#define WSAEMFILE (WSABASEERR+24)\r
-\r
-/*\r
- * Windows Sockets definitions of regular Berkeley error constants\r
- */\r
-#define WSAEWOULDBLOCK (WSABASEERR+35)\r
-#define WSAEINPROGRESS (WSABASEERR+36)\r
-#define WSAEALREADY (WSABASEERR+37)\r
-#define WSAENOTSOCK (WSABASEERR+38)\r
-#define WSAEDESTADDRREQ (WSABASEERR+39)\r
-#define WSAEMSGSIZE (WSABASEERR+40)\r
-#define WSAEPROTOTYPE (WSABASEERR+41)\r
-#define WSAENOPROTOOPT (WSABASEERR+42)\r
-#define WSAEPROTONOSUPPORT (WSABASEERR+43)\r
-#define WSAESOCKTNOSUPPORT (WSABASEERR+44)\r
-#define WSAEOPNOTSUPP (WSABASEERR+45)\r
-#define WSAEPFNOSUPPORT (WSABASEERR+46)\r
-#define WSAEAFNOSUPPORT (WSABASEERR+47)\r
-#define WSAEADDRINUSE (WSABASEERR+48)\r
-#define WSAEADDRNOTAVAIL (WSABASEERR+49)\r
-#define WSAENETDOWN (WSABASEERR+50)\r
-#define WSAENETUNREACH (WSABASEERR+51)\r
-#define WSAENETRESET (WSABASEERR+52)\r
-#define WSAECONNABORTED (WSABASEERR+53)\r
-#define WSAECONNRESET (WSABASEERR+54)\r
-#define WSAENOBUFS (WSABASEERR+55)\r
-#define WSAEISCONN (WSABASEERR+56)\r
-#define WSAENOTCONN (WSABASEERR+57)\r
-#define WSAESHUTDOWN (WSABASEERR+58)\r
-#define WSAETOOMANYREFS (WSABASEERR+59)\r
-#define WSAETIMEDOUT (WSABASEERR+60)\r
-#define WSAECONNREFUSED (WSABASEERR+61)\r
-#define WSAELOOP (WSABASEERR+62)\r
-#define WSAENAMETOOLONG (WSABASEERR+63)\r
-#define WSAEHOSTDOWN (WSABASEERR+64)\r
-#define WSAEHOSTUNREACH (WSABASEERR+65)\r
-#define WSAENOTEMPTY (WSABASEERR+66)\r
-#define WSAEPROCLIM (WSABASEERR+67)\r
-#define WSAEUSERS (WSABASEERR+68)\r
-#define WSAEDQUOT (WSABASEERR+69)\r
-#define WSAESTALE (WSABASEERR+70)\r
-#define WSAEREMOTE (WSABASEERR+71)\r
-\r
-// Used for IRP cancell\r
-#define ERROR_OPERATION_ABORTED 995L\r
-#define WSA_OPERATION_ABORTED (ERROR_OPERATION_ABORTED)\r
-\r
-#endif // _SDP_GEN_UTILS_H\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-\r
-#ifndef _SDP_LOCK_H\r
-#define _SDP_LOCK_H\r
-\r
-/*\r
-The goal of this lock is to be a user mode lock that will allow us to synchronize\r
-both "user" operations at PASSIVE level as well as DPC's at DPC level.\r
-\r
-The main problem that we have is that we have many functions that we can only call at \r
-passive level, and therefore can not be called under a spinlock.\r
-\r
-We might, however, receive notifications at DPC level. Example of such are send and \r
-receive completions. As always, shutdown might appear at any time (at any level?).\r
-\r
-Bottom line of this is that the lock will be implemented as an event. DPC level \r
-callers that will call us will only mark our state as send/received/shutdown arrived.\r
-\r
-Once one tries to take/free the lock from passive level, he will have to handle this \r
-events first.\r
-\r
-Callers at DPC level, (send receive call backs) will only signal if the lock is taken\r
-or do the actual job if it is not taken.\r
-\r
-There will therefore be a spinlock that will protect the event. \r
-\r
-*/\r
-\r
-\r
-// Still Need to make sure that all errors are handled when they should ??????\r
-\r
-typedef NTSTATUS (* SendCBHandler )(SdpSocket *);\r
-typedef NTSTATUS (* RecvCBHandler )(SdpSocket *);\r
-typedef NTSTATUS (* CheckSocketStateFunction )(SdpSocket *);\r
-\r
-\r
-const int SEND_CB_CALLED = 0x00000001;\r
-const int RECV_CB_CALLED = 0x00000002;\r
-const int ERROR_SIGNALLED = 0x00000004;\r
-\r
-const int DPC_FLAGS = SEND_CB_CALLED | RECV_CB_CALLED;\r
-inline void ResetFlags(int &Flags)\r
-{\r
- Flags &= (!(SEND_CB_CALLED | RECV_CB_CALLED));\r
-}\r
-\r
-inline void ResetDpcFlags(int &Flags)\r
-{\r
- // Currently this function is just like the one above it. It will probably\r
- // change in the future\r
- Flags &= (!(DPC_FLAGS));\r
-}\r
-\r
-inline bool SomethingToHandle(int flags)\r
-{\r
- if (flags & SEND_CB_CALLED) return true;\r
- if (flags & RECV_CB_CALLED) return true;\r
-\r
- return false;\r
-}\r
-\r
-class SdpLock {\r
-public:\r
- SdpLock() {\r
- m_InUse = false;\r
- m_flags = 0;\r
- KeInitializeEvent(&m_Event, NotificationEvent , TRUE);\r
- KeInitializeSpinLock(&m_SpinLock);\r
- m_SendCBHandler = NULL;\r
- m_RecvCBHandler = NULL;\r
- m_NumberOfClientWaiting = 0;\r
- }\r
-\r
- VOID Init(\r
- SendCBHandler SendCB, \r
- RecvCBHandler RecvCB,\r
- CheckSocketStateFunction CheckSocketState,\r
- SdpSocket *pSdpSocket )\r
- {\r
- m_SendCBHandler = SendCB;\r
- m_CheckSocketState = CheckSocketState;\r
- m_RecvCBHandler = RecvCB;\r
- m_pSdpSocket = pSdpSocket;\r
- \r
- }\r
-\r
- /*\r
- Lock should handle recieve_cb/send_cb without user knowledge.\r
- for shutdown, it should return false and not continue\r
-\r
- return value of false means that the lock can not be taken (eitheir\r
- shutdown or STATUS_ALERTED, or some error has happend)\r
- */\r
- bool Lock(bool Force = false) {\r
- KIRQL OldIrql;\r
- int OldFlags = 0;\r
- NTSTATUS rc = STATUS_SUCCESS, rc1 = STATUS_SUCCESS;\r
- ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);\r
- bool Locked = false;\r
- bool WaitedOnLock = false;\r
- do {\r
- KeAcquireSpinLock(&m_SpinLock, &OldIrql);\r
-\r
- if (m_InUse) {\r
- // We have to release the spinlock and wait on the event\r
- if (WaitedOnLock == false) {\r
- m_NumberOfClientWaiting++;\r
- WaitedOnLock = true;\r
- }\r
- KeReleaseSpinLock(&m_SpinLock, OldIrql);\r
- rc = MyKeWaitForSingleObject(&m_Event, UserRequest, UserMode, false, NULL);\r
- if (( rc == STATUS_ALERTED ) ||( rc == STATUS_USER_APC )) {\r
- //SDP_PRINT(TRACE_LEVEL_WARNING, SDP_LOCK,"MyKeWaitForSingleObject was alerted = 0x%x\n", rc );\r
- rc = STATUS_UNEXPECTED_IO_ERROR;\r
- Locked = false;\r
- goto Cleanup;\r
- } \r
- continue;\r
- }\r
- m_InUse = true;\r
- KeClearEvent(&m_Event);\r
- OldFlags = m_flags;\r
- ResetFlags(m_flags);\r
- if (WaitedOnLock) {\r
- m_NumberOfClientWaiting--;\r
- }\r
- ASSERT(m_NumberOfClientWaiting >= 0); \r
- KeReleaseSpinLock(&m_SpinLock, OldIrql);\r
- rc = HandleFlags(OldFlags);\r
- if(!NT_SUCCESS(rc)) {\r
- //SDP_PRINT(SDP_ERR, SDP_LOCK, ("HandleFlags failed rc = 0x%x\n", rc ));\r
- }\r
- if ((Force == false) && \r
- (!NT_SUCCESS(rc) ||\r
- (m_flags & ERROR_SIGNALLED) ||\r
- (!NT_SUCCESS(rc1 = m_CheckSocketState(m_pSdpSocket)))\r
- )) {\r
- // We have to signal the error to the calling side\r
- if(!NT_SUCCESS(rc1)) {\r
- //SDP_PRINT(SDP_ERR, SDP_LOCK, ("m_CheckSocketState failed rc1 = 0x%x\n", rc1 ));\r
- }\r
- Locked = false;\r
- KeAcquireSpinLock(&m_SpinLock, &OldIrql);\r
- m_InUse = false;\r
- // Release whoever is waiting\r
- KeSetEvent(&m_Event, IO_NO_INCREMENT, FALSE);\r
- KeReleaseSpinLock(&m_SpinLock, OldIrql); \r
- goto Cleanup;\r
- }\r
- // Exit the loop\r
-\r
- Locked = true;\r
- goto Cleanup; \r
- } while (true);\r
- \r
-Cleanup:\r
- //SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_LOCK,"Lock is returing %s\n", Locked ? "true" : "false");\r
- return Locked;\r
- }\r
-\r
- // This is the first stage in moving the lock to return rc (and later void)\r
- NTSTATUS LockRc() {\r
- if (Lock()) return STATUS_SUCCESS;\r
- return STATUS_SHUTDOWN_IN_PROGRESS;\r
- }\r
-\r
- /*\r
- Frees the lock and handle any events that might happen there.\r
- Please note that the lock is freed no metter what the error code is.\r
- An error means that there was some error in the sockets.\r
- */\r
-\r
- //?????????? should this be ntstatus or bool ???????\r
- NTSTATUS Unlock()\r
- {\r
- KIRQL OldIrql;\r
- int OldFlags = 0;\r
- NTSTATUS rc = STATUS_SUCCESS;\r
-\r
- while (true) {\r
- ASSERT(m_InUse);\r
- ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);\r
- KeAcquireSpinLock(&m_SpinLock, &OldIrql);\r
- ASSERT(m_InUse); // Also with the lock taken\r
- OldFlags = m_flags;\r
- ResetFlags(m_flags);\r
- if (!SomethingToHandle(OldFlags)) {\r
- // We can safely quit the lock\r
- m_InUse = false;\r
- // Before we leave this function we check for errors / shutdown here\r
- if (m_flags & ERROR_SIGNALLED) {\r
- rc = STATUS_UNEXPECTED_IO_ERROR;\r
- } else {\r
- rc = m_CheckSocketState(m_pSdpSocket);\r
- }\r
- KeReleaseSpinLock(&m_SpinLock, OldIrql);\r
- break;\r
- }\r
- KeReleaseSpinLock(&m_SpinLock, OldIrql);\r
- ASSERT(SomethingToHandle(OldFlags));\r
- ASSERT(m_InUse);\r
- rc = HandleFlags(OldFlags); \r
- if (!NT_SUCCESS(rc)) {\r
- // We have to signal the error to the calling side\r
- //SDP_PRINT(TRACE_LEVEL_ERROR, SDP_LOCK,"HandleFlags failed rc = 0x%x\n", rc );\r
- ASSERT(m_flags & ERROR_SIGNALLED);\r
- }\r
- // At the time that we were handeling the flags, someone might have \r
- // signaled something, so we have to try again\r
- continue;\r
- }\r
- \r
- // Release whoever is waiting\r
- KeSetEvent(&m_Event, IO_NO_INCREMENT, FALSE);\r
-\r
- return rc;\r
- }\r
-/*\r
- This function is being called at DPC level. It has some message of a call back.\r
- to tell us. Once called, it will try to take the lock. If it succeeds, it will \r
- do the actual work, if not it will only signal. Once it returns the lock is freed \r
- again\r
-*/\r
-\r
- bool SignalCB(int flags)\r
- {\r
- KIRQL OldIrql;\r
- int OldFlags = 0;\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);\r
- KeAcquireSpinLock(&m_SpinLock, &OldIrql);\r
- if (m_InUse || (m_NumberOfClientWaiting > 0 ) ) {\r
- m_flags |= flags;\r
- KeReleaseSpinLock(&m_SpinLock, OldIrql);\r
- return false;\r
- }\r
- while (true) {\r
- m_InUse = true;\r
- // In this lock, we only handle DPC events\r
- OldFlags = (m_flags & DPC_FLAGS) | flags;\r
- flags = 0; // No need to handle the same event any more\r
- ResetDpcFlags(m_flags);\r
- KeClearEvent(&m_Event);\r
- KeReleaseSpinLock(&m_SpinLock, OldIrql);\r
- rc = HandleFlags(OldFlags); \r
- if (!NT_SUCCESS(rc)) {\r
- // We have to signal the error to the calling side\r
- //SDP_PRINT(TRACE_LEVEL_ERROR, SDP_LOCK,"HandleFlags failed rc = 0x%x\n", rc );\r
- ASSERT(m_flags & ERROR_SIGNALLED);\r
- }\r
- KeAcquireSpinLock(&m_SpinLock, &OldIrql);\r
- if ((m_flags & DPC_FLAGS) == 0) {\r
- // No flags to handle from the DPC layer\r
- break;\r
- }\r
- }\r
- \r
- // Release whoever is waiting\r
- m_InUse = false;\r
- KeSetEvent(&m_Event, IO_NO_INCREMENT, FALSE);\r
- KeReleaseSpinLock(&m_SpinLock, OldIrql);\r
-\r
- return true;\r
- }\r
-\r
- /*\r
- This function is responsible for handling the flags that we might get.\r
- Currently it can be called from passive or DPC level, and handle only "DPC" events\r
- */\r
- NTSTATUS HandleFlags(int flags) {\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- AssertLocked(); \r
- // Try to do this faster if nothing to do\r
- if (flags == 0) {\r
- return STATUS_SUCCESS;\r
- }\r
- if (flags & SEND_CB_CALLED) {\r
- // We need to handle the send CB\r
- rc = m_SendCBHandler(m_pSdpSocket);\r
- if (!NT_SUCCESS(rc)) {\r
- //SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"m_SendCBHandler failed rc = 0x%x\n", rc );\r
- m_flags |= ERROR_SIGNALLED;\r
- // We continue from here since, there might be other things to handle,\r
- // and this might be in a DPC context\r
- } \r
- }\r
- if (flags & RECV_CB_CALLED) {\r
- // We need to handle the send CB\r
- rc = m_RecvCBHandler(m_pSdpSocket);\r
- if (!NT_SUCCESS(rc)) {\r
- //SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"m_RecvCBHandler failed rc = 0x%x\n", rc );\r
- m_flags |= ERROR_SIGNALLED;\r
- // We continue from here since, there might be other things to handle,\r
- // and this might be in a DPC context\r
- } \r
- }\r
- return rc;\r
- }\r
-\r
- VOID SignalError(NTSTATUS rc) {\r
- m_flags |= ERROR_SIGNALLED;\r
- } \r
-\r
- VOID AssertLocked() {ASSERT(m_InUse);}\r
-\r
- KEVENT m_Event; // the event for passive level threads\r
- KSPIN_LOCK m_SpinLock; // The real guard of the lock\r
- SendCBHandler m_SendCBHandler;\r
- RecvCBHandler m_RecvCBHandler;\r
- CheckSocketStateFunction m_CheckSocketState;\r
-\r
-\r
- bool m_InUse; // Tells if this lock has any user\r
- int m_flags; // call backs that were recieved\r
- int m_NumberOfClientWaiting; // Number of clients that are waiting to be served\r
-\r
- SdpSocket *m_pSdpSocket;// The socket that this class depends on\r
-};\r
-\r
-#endif // _SDP_LOCK_H\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-/*\r
- This file holds the types that are used for SDP comunication\r
-\r
-*/\r
-\r
-#ifndef H_SDP_MSGS_H\r
-#define H_SDP_MSGS_H \r
-\r
-\r
-#pragma pack(push)\r
-#pragma pack(1)\r
-\r
-\r
-/*\r
- * Message Identifier Opcodes for BSDH\r
- */\r
-/* Name Value Extended Header Payload */\r
-#define SDP_MID_HELLO 0x00 /* msg_hdr_hh <none> */\r
-#define SDP_MID_HELLO_ACK 0x01 /* msg_hdr_hah <none> */\r
-#define SDP_MID_DISCONNECT 0x02 /* <none> <none> */\r
-#define SDP_MID_ABORT_CONN 0x03 /* <none> <none> */\r
-#define SDP_MID_SEND_SM 0x04 /* <none> <none> */\r
-#define SDP_MID_RDMA_WR_COMP 0x05 /* msg_hdr_rwch <none> */\r
-#define SDP_MID_RDMA_RD_COMP 0x06 /* msg_hdr_rrch <none> */\r
-#define SDP_MID_MODE_CHANGE 0x07 /* msg_hdr_mch <none> */\r
-#define SDP_MID_SRC_CANCEL 0x08 /* <none> <none> */\r
-#define SDP_MID_SNK_CANCEL 0x09 /* <none> <none> */\r
-#define SDP_MID_SNK_CANCEL_ACK 0x0A /* <none> <none> */\r
-#define SDP_MID_CH_RECV_BUF 0x0B /* msg_hdr_crbh <none> */\r
-#define SDP_MID_CH_RECV_BUF_ACK 0x0C /* msg_hdr_crbah <none> */\r
-#define SDP_MID_SUSPEND 0x0D /* msg_hdr_sch <none> */\r
-#define SDP_MID_SUSPEND_ACK 0x0E /* <none> <none> */\r
-#define SDP_MID_SNK_AVAIL 0xFD /* msg_hdr_snkah <optional> */\r
-#define SDP_MID_SRC_AVAIL 0xFE /* msg_hdr_srcah <optional> */\r
-#define SDP_MID_DATA 0xFF /* <none> <optional> */\r
-/*\r
- * shift number for BSDH Flags.\r
- */\r
-#define SDP_MSG_FLAG_NON_FLAG (0x0) /* no flag present */\r
-#define SDP_MSG_FLAG_OOB_PRES 0 /* out-of-band data present */\r
-#define SDP_MSG_FLAG_OOB_PEND 1 /* out-of-band data pending */\r
-#define SDP_MSG_FLAG_REQ_PIPE 2 /* request change to pipelined */\r
-/*\r
- * message type masks\r
- */\r
-#define SDP_MID_CTRL(mid) ((0xF0 & mid) ? 0 : 1)\r
-\r
-\r
-/*\r
- * Base Sockets Direct Header (header for all SDP messages)\r
- */\r
-struct msg_hdr_bsdh {\r
- uint8_t mid; /* message identifier opcode (SDP_MID_*) */\r
- uint8_t flags; /* flags as defined by SDP_MSG_FLAG_* */\r
- uint16_t recv_bufs; /* current number of posted private recv buffers */\r
- uint32_t size; /* length of msg, including header(s) and data */\r
- uint32_t seq_num; /* message sequence number */\r
- uint32_t seq_ack; /* last received message sequence number */\r
-};// __attribute__ ((packed)); /* struct msg_hdr_bsdh */\r
-\r
-/*\r
- * Hello Header constants (two 8-bit constants, no conversion needed)\r
- */\r
-#ifdef _SDP_MS_APRIL_ERROR_COMPAT\r
-this bug was probably solved \r
-#define SDP_MSG_IPVER 0x04 /* (1: ipversion), (0: reserved) */\r
-#else\r
-#define SDP_MSG_IPVER 0x40 /* (1: ipversion), (0: reserved) */\r
-#endif\r
-#define SDP_MSG_VERSION 0x11 /* (1: major ), (0: minor ) */\r
-\r
-\r
-/*\r
- * Hello Header (BSDH + HH are contained in private data of the CM REQ MAD\r
- */\r
-struct msg_hdr_hh {\r
- uint8_t version; /* 0-3: minor version (current spec; 0x1)\r
- 4-7: major version (current spec; 0x1) */\r
- uint8_t ip_ver; /* 0-3: reserved\r
- 4-7: ip version (0x4 = ipv4, 0x6 = ipv6) */\r
- uint8_t rsvd_1; /* reserved */\r
- uint8_t max_adv; /* max outstanding Zcopy advertisments (>0) */\r
- uint32_t r_rcv_size; /* requested size of each remote recv buffer */\r
- uint32_t l_rcv_size; /* initial size of each local receive buffer */\r
- uint16_t port; /* local port */\r
- uint16_t rsvd_2; /* reserved */\r
-\r
- union { /* source IP address. */\r
- struct {\r
- uint32_t addr3; /* ipv6 96-127 */\r
- uint32_t addr2; /* ipv6 64-95 */\r
- uint32_t addr1; /* ipv6 32-63 */\r
- uint32_t addr0; /* ipv6 0-31 */\r
- } ipv6; /* 128bit IPv6 address */\r
- struct {\r
- uint32_t none2; /* unused 96-127 */\r
- uint32_t none1; /* unused 64-95 */\r
- uint32_t none0; /* unused 32-63 */\r
- uint32_t addr; /* ipv4 0-31 */\r
- } ipv4; /* 32bit IPv4 address */\r
- } src;\r
-\r
- union { /* destination IP address. */\r
- struct {\r
- uint32_t addr3; /* ipv6 96-127 */\r
- uint32_t addr2; /* ipv6 64-95 */\r
- uint32_t addr1; /* ipv6 32-63 */\r
- uint32_t addr0; /* ipv6 0-31 */\r
- } ipv6; /* 128bit IPv6 address */\r
- struct {\r
- uint32_t none2; /* unused 96-127 */\r
- uint32_t none1; /* unused 64-95 */\r
- uint32_t none0; /* unused 32-63 */\r
- uint32_t addr; /* ipv4 0-31 */\r
- } ipv4; /* 32bit IPv4 address */\r
- } dst;\r
-\r
- uint8_t rsvd_3[28]; /* reserved for future use, and zero'd */\r
-}; //__attribute__ ((packed)); /* struct msg_hdr_hh */\r
-\r
-struct msg_hdr_hah {\r
- uint8_t version; /* 0-3: minor version (current spec; 0x1)\r
- 4-7: major version (current spec; 0x1) */\r
- uint16_t rsvd_1; /* reserved */\r
- uint8_t max_adv; /* max outstanding Zcopy advertisments (>0) */\r
- uint32_t l_rcv_size; /* initial size of each local receive buffer */\r
-#if 0 /* There is a bug in the 1.1 spec. REP message grew by 8 bytes. */\r
- __u8 rsvd_2[180]; /* reserved for future use, and zero'd (big) */\r
-#else\r
- uint8_t rsvd_2[172]; /* reserved for future use, and zero'd (big) */\r
-#endif\r
-}; //__attribute__ ((packed)); /* struct msg_hdr_hah */\r
-\r
-struct sdp_msg_hello {\r
- struct msg_hdr_bsdh bsdh; /* base sockets direct header */\r
- struct msg_hdr_hh hh; /* hello message header */\r
-} ;//__attribute__ ((packed)); /* struct sdp_msg_hello */\r
-\r
-struct sdp_msg_hello_ack {\r
- struct msg_hdr_bsdh bsdh; /* base sockets direct header */\r
- struct msg_hdr_hah hah; /* hello ack message header */\r
-};// __attribute__ ((packed)); /* struct sdp_msg_hello_ack */\r
-\r
-static inline void sdp_msg_swap_bsdh(struct msg_hdr_bsdh *header)\r
-{\r
- header->recv_bufs = CL_NTOH16(header->recv_bufs);\r
- header->size = CL_NTOH32(header->size);\r
- header->seq_num = CL_NTOH32(header->seq_num);\r
- header->seq_ack = CL_NTOH32(header->seq_ack);\r
-}\r
-\r
-static inline void sdp_msg_swap_hh(struct msg_hdr_hh *header)\r
-{\r
- header->r_rcv_size = CL_NTOH32(header->r_rcv_size);\r
- header->l_rcv_size = CL_NTOH32(header->l_rcv_size);\r
- header->port = CL_NTOH16(header->port);\r
- header->src.ipv6.addr0 = CL_NTOH32(header->src.ipv6.addr0);\r
- header->src.ipv6.addr1 = CL_NTOH32(header->src.ipv6.addr1);\r
- header->src.ipv6.addr2 = CL_NTOH32(header->src.ipv6.addr2);\r
- header->src.ipv6.addr3 = CL_NTOH32(header->src.ipv6.addr3);\r
- header->dst.ipv6.addr0 = CL_NTOH32(header->dst.ipv6.addr0);\r
- header->dst.ipv6.addr1 = CL_NTOH32(header->dst.ipv6.addr1);\r
- header->dst.ipv6.addr2 = CL_NTOH32(header->dst.ipv6.addr2);\r
- header->dst.ipv6.addr3 = CL_NTOH32(header->dst.ipv6.addr3);\r
-}\r
-\r
-/*\r
- * sdp_msg_swap_hah - SDP header endian byte swapping\r
- */\r
-static inline void sdp_msg_swap_hah(struct msg_hdr_hah *header)\r
-{\r
- header->l_rcv_size = CL_NTOH32(header->l_rcv_size);\r
-}\r
-\r
-#define BASE_LISTEN_ID (CL_CONST64(0x0000000000010000))\r
-\r
-static inline ib_net64_t\r
-get_service_id_for_port(\r
- ib_net16_t ip_port)\r
-{\r
- return CL_NTOH64( BASE_LISTEN_ID | ip_port );\r
-}\r
-\r
-\r
-// CM timeouts - Used for creating the sockets\r
-#define CM_MIN_LOCAL_TIMEOUT (18)\r
-#define CM_LOCAL_TIMEOUT (1)\r
-#define CM_MIN_REMOTE_TIMEOUT (18)\r
-#define CM_REMOTE_TIMEOUT (2)\r
-#define CM_RETRIES 4\r
-\r
-\r
-#pragma pack(pop)\r
-\r
-#endif H_SDP_MSGS_H\r
-\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-#include "preCompile.h"\r
-\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "SdpRecvPool.tmh"\r
-#endif\r
-\r
-\r
-\r
-RecvPool::RecvPool()\r
-{\r
- m_RecvSeq = 0;\r
- m_ClientBeingServed = false;\r
- m_CurrentlyPostedRecievedBuffers = 0;\r
- m_CurrentlyAllocated = 0;\r
- m_ClientWaiting = false;\r
- m_DisConnRecieved = false;\r
- m_LocaleAdvertisedBuffers = 0;\r
- m_pSdpSocket = NULL;\r
- m_NumberOfBuffersRecievedWithError = 0;\r
- m_NumberOfBuffersRecievedSuccessfully = 0;\r
-}\r
-\r
-NTSTATUS \r
-RecvPool::Init(\r
- int MaxBuffers, \r
- int MaxConcurrentRecieves, \r
- int MaxMessageSize,\r
- ib_pd_handle_t pd,\r
- ib_qp_handle_t qp,\r
- net32_t lkey,\r
- SdpSocket *pSdpSocket\r
- )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_BUFFER_POOL,"this = 0x%p \n", m_pSdpSocket);\r
- m_MaxBuffers = MaxBuffers;\r
- m_MaxConcurrentRecieves = MaxConcurrentRecieves;\r
- m_MaxMessageSize = MaxMessageSize; \r
- KeInitializeEvent(&m_WaitingClients, NotificationEvent, FALSE);\r
- ASSERT(pd != NULL);\r
- m_pd = pd;\r
- ASSERT(qp != NULL); \r
- m_qp = qp;\r
- ASSERT(lkey != NULL);\r
- m_lkey = lkey;\r
- m_pSdpSocket = pSdpSocket;\r
-\r
- // Allocate all the buffers as continues memory (better be done\r
- // at passive level)\r
- BufferDescriptor *pBufferDescriptor = NULL;\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- \r
- for (int i=0;i < MAX_RECV_PACKETS; i++) {\r
- rc = BufferDescriptor::AllocateBuffer(&pBufferDescriptor, m_MaxMessageSize, RECV_BUFFERS_ALLOCATION_TAG);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"BufferDescriptor::AllocateBuffer failed rc=0x%x \n", rc);\r
- goto Cleanup;\r
- }\r
-\r
- m_CurrentlyAllocated++;\r
- \r
- pBufferDescriptor->Reset();\r
- m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList);\r
- }\r
-Cleanup:\r
- if (!NT_SUCCESS(rc)) {\r
- LIST_ENTRY *item = NULL;\r
- while (m_FreePackets.Size() > 0 ) {\r
- item = m_FreePackets.RemoveHeadList();\r
- pBufferDescriptor = CONTAINING_RECORD(item, BufferDescriptor , BuffersList);\r
- BufferDescriptor::DeAllocateBuffer(pBufferDescriptor, RECV_BUFFERS_ALLOCATION_TAG);\r
- }\r
-\r
- }\r
- \r
- return rc;\r
-}\r
-\r
-/*\r
- A buffer was compleated and is being added to the queued list\r
-*/\r
-\r
-NTSTATUS\r
-RecvPool::RecievedBuffer(BufferDescriptor *pBufferDescriptor, bool error)\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_BUFFER_POOL, "this = 0x%p pBufferDescriptor = 0x%p sucess = %s\n"\r
- ,m_pSdpSocket, pBufferDescriptor, error ? "false" : "true");\r
- AssertLocked();\r
- NTSTATUS rc = STATUS_SUCCESS;\r
-\r
- m_CurrentlyPostedRecievedBuffers--;\r
- ASSERT(m_CurrentlyPostedRecievedBuffers >= 0);\r
-\r
- if (error) {\r
- // Not much that we can do in this case (only return the packet)\r
- m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList);\r
- m_NumberOfBuffersRecievedWithError++;\r
- goto Cleanup;\r
- }\r
- ASSERT(m_NumberOfBuffersRecievedWithError == 0);\r
- m_NumberOfBuffersRecievedSuccessfully++;\r
- \r
- // We have recieved a "RAW" buffer, we have to make sure that the buffer\r
- // descriptor is OK.\r
- msg_hdr_bsdh *pHeader = (msg_hdr_bsdh *)pBufferDescriptor->pBuffer;\r
-\r
- ASSERT(pBufferDescriptor->DataStart == 0);\r
- pBufferDescriptor->DataStart = sizeof (msg_hdr_bsdh);\r
- pBufferDescriptor->DataSize = pHeader->size - sizeof msg_hdr_bsdh;\r
-\r
- m_RecvSeq = pHeader->seq_num;\r
-\r
- // Start processing the different messages:\r
- // No metter what the message type is, we can update our credits\r
-\r
- uint16_t rRecvBuf = \r
- pHeader->recv_bufs - \r
- abs (\r
- (int)m_pSdpSocket->m_SendBufferPool.GetSendSeq()- \r
- (int)pHeader->seq_ack);\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_CREDITS,"SetRemoteRecvBuf rRecvBuf = %d, pHeader->recv_bufs = %d, SendSeq = %d , pHeader->seq_ack = %d\n",\r
- rRecvBuf,\r
- pHeader->recv_bufs,\r
- (int)m_pSdpSocket->m_SendBufferPool.GetSendSeq(),\r
- (int)pHeader->seq_ack);\r
- m_pSdpSocket->m_SendBufferPool.SetRemoteRecvBuf(rRecvBuf);\r
-\r
- // m_DisConnRecieved is the last "real" message that should be recieved\r
- // we might still get credits update\r
- ASSERT(m_DisConnRecieved == false ||\r
- (pHeader->mid == SDP_MID_DATA && pHeader->size == sizeof msg_hdr_bsdh)); // BUGBUG: do a real check here\r
-\r
- // ???? Handle more state changes here ????\r
- if (pHeader->mid != SDP_MID_DATA) {\r
- if (pHeader->mid == SDP_MID_DISCONNECT) {\r
- m_DisConnRecieved = true;\r
- if (m_ClientWaiting) {\r
- KeSetEvent( &m_WaitingClients, IO_NO_INCREMENT, FALSE );\r
- m_ClientWaiting = false;\r
- } \r
- }\r
- // This is a message without data, we currently ignore it\r
- m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList);\r
- } else {\r
-\r
- if(pHeader->size > sizeof msg_hdr_bsdh) {\r
- m_FullPackets.InsertTailList(&pBufferDescriptor->BuffersList);\r
- ASSERT(m_FullPackets.Size() <= m_MaxBuffers);\r
-\r
- // we need to notify the client that is waiting\r
- if (m_ClientWaiting) {\r
- KeSetEvent( &m_WaitingClients, IO_NO_INCREMENT, FALSE );\r
- m_ClientWaiting = false;\r
- }\r
- } else {\r
- // This is an empty buffer\r
- ASSERT(pHeader->size == sizeof msg_hdr_bsdh);\r
- m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList);\r
- }\r
- } \r
-\r
- // Check if we have to send more credits to the remote side\r
- ASSERT(m_LocaleAdvertisedBuffers > 0);\r
- m_LocaleAdvertisedBuffers--;\r
-\r
- ASSERT(m_CurrentlyPostedRecievedBuffers >= m_LocaleAdvertisedBuffers);\r
- if (m_CurrentlyPostedRecievedBuffers - m_LocaleAdvertisedBuffers > \r
- SDP_RECV_CREDIT_UPDATE) {\r
- rc = m_pSdpSocket->m_SendBufferPool.PostCredits();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"m_SendBufferPool.PostCredits failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- } \r
- }\r
-\r
- // Wake up the clients of the send (new credits were added)\r
- rc = m_pSdpSocket->m_SendBufferPool.SendBuffersIfCan();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"SendBuffersIfCan failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- } \r
- // We might be able to post a new recieve buffer now\r
- ASSERT(m_CurrentlyPostedRecievedBuffers < m_MaxConcurrentRecieves);\r
- rc = ReceiveIfCan();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"RecieveIfCan failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
-Cleanup:\r
- return rc;\r
-\r
-}\r
-\r
-/*\r
- This function is being called by a thread that wants to do a recieve in order\r
- to have a buffer with the data, that he can copy.\r
- FirstBuffer tells if this is the first buffer that he wants.\r
- If it is true, this means that no other request will be handled before\r
- this client will indicate that he has finished recieving his data.\r
- If an event is returned this means that the caller has to wait on the\r
- event before the request will be staisfied.\r
-\r
- pData is the place that the data should be copied to. CopySize is the number of\r
- requested bytes, while Copied is the number actually copied.\r
-\r
- This function is being called under the lock\r
-*/\r
-NTSTATUS \r
-RecvPool::GetData(\r
- char *pData,\r
- uint32_t CopySize,\r
- uint32_t *Copied,\r
- KEVENT **ppEvent,\r
- bool FirstBuffer,\r
- bool *pNoMoreData\r
- )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_BUFFER_POOL, "this = 0x%p FirstBuffer = %s\n", m_pSdpSocket,\r
- FirstBuffer ? "TRUE" : "FALSE");\r
- AssertLocked();\r
- bool BufferFreed = false;\r
- *Copied = 0;\r
- *pNoMoreData = false;\r
- BufferDescriptor *pBufferDescriptor = NULL;\r
- uint32_t OldDataSize = 0;\r
-\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- ASSERT(*ppEvent == NULL);\r
-\r
- if (m_ClientBeingServed == true && (FirstBuffer != false)) {\r
- // The request can not be staisfied right now. We need to hold it\r
- // until our request is being freed\r
- // BUGBUG: iMPLMENT: create event and put it in the queue.\r
- // This might only happen when there are two threads calling us\r
- ASSERT(FALSE);\r
- return STATUS_UNEXPECTED_IO_ERROR;\r
- }\r
-\r
- if (FirstBuffer == true) {\r
- m_ClientBeingServed = true; \r
- }\r
-\r
- // Can we supply data to the user right now ?\r
- while (*Copied < CopySize) {\r
- if (m_FullPackets.Size()) {\r
- // We have a buffer, we can use it to copy data to the user\r
- LIST_ENTRY *item = m_FullPackets.Head();\r
- pBufferDescriptor = CONTAINING_RECORD(item, BufferDescriptor , BuffersList);\r
- OldDataSize = pBufferDescriptor->DataSize;\r
- if (OldDataSize > CopySize - *Copied) {\r
- // we can only copy part of the buffer\r
- ASSERT(CopySize > *Copied);\r
- rc = pBufferDescriptor->CopyToUser(pData + *Copied, CopySize - *Copied);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"pBufferDescriptor->CopyToUser failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
- *Copied += CopySize - *Copied;\r
-\r
- } else {\r
- // We copy the entire buffer and remove it\r
- rc = pBufferDescriptor->CopyToUser(pData + *Copied, OldDataSize);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"pBufferDescriptor->CopyToUser failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
- *Copied += OldDataSize;\r
- m_FullPackets.RemoveHeadList();\r
- m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList);\r
- BufferFreed = true;\r
- }\r
-\r
- } else {\r
- *pNoMoreData = true;\r
- // If data was already supplied, then we shouldn't wait any more\r
- if ((*Copied > 0) || \r
- (FirstBuffer == false) ||\r
- m_DisConnRecieved) {\r
- ASSERT(*ppEvent == NULL);\r
- break;\r
- }\r
- // No buffers available, we have to wait\r
- ASSERT(m_ClientWaiting == false);\r
- KeClearEvent(&m_WaitingClients);\r
- m_ClientWaiting = true;\r
- *ppEvent = &m_WaitingClients;\r
- break;\r
- }\r
- }\r
-\r
- // As data was copyed, it is possibale that we will be able to post more receives\r
- if (BufferFreed) {\r
- ReceiveIfCan();\r
- }\r
-\r
-Cleanup: \r
- return rc;\r
-}\r
-\r
-VOID \r
-RecvPool::AllowOthersToGet()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_BUFFER_POOL,"this = 0x%p \n", m_pSdpSocket);\r
- ASSERT(m_ClientBeingServed == true);\r
- m_ClientBeingServed = false;\r
-\r
- // BUGBUG: this means that we should free the next waiter (Once we support more\r
- // than one thread).\r
-}\r
-\r
-NTSTATUS \r
-RecvPool::ReceiveIfCan()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_BUFFER_POOL, "this = 0x%p m_CurrentlyPostedRecievedBuffers = %d m_LocaleAdvertisedBuffers = %d\n",\r
- m_pSdpSocket, m_CurrentlyPostedRecievedBuffers, m_LocaleAdvertisedBuffers);\r
- AssertLocked();\r
- BufferDescriptor *pBufferDescriptor = NULL;\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- uint16_t StartLocaleAdvertisedBuffers = m_LocaleAdvertisedBuffers;\r
-\r
- while (m_CurrentlyPostedRecievedBuffers < m_MaxConcurrentRecieves) {\r
- // do we have a free packet ?\r
- if (m_FreePackets.Size() > 0) {\r
- // we can take a packet from the list\r
- LIST_ENTRY *item = m_FreePackets.RemoveHeadList();\r
- pBufferDescriptor = CONTAINING_RECORD(item, BufferDescriptor , BuffersList); \r
- } else if (m_CurrentlyAllocated < m_MaxBuffers) {\r
- // We can allocate more buffers\r
- rc = BufferDescriptor::AllocateBuffer(&pBufferDescriptor, m_MaxMessageSize, RECV_BUFFERS_ALLOCATION_TAG);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"AllocateBuffer failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
- m_CurrentlyAllocated++;\r
- } else {\r
- // Couldn't get any more free packets.\r
- break;\r
- }\r
- pBufferDescriptor->Reset();\r
-\r
- // we can now post the buffer for recieve\r
- rc = PostReceiveBuffer(pBufferDescriptor);\r
- if (!NT_SUCCESS(rc)) {\r
- m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList);\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"PostReceiveBuffer failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- } \r
- }\r
- if (StartLocaleAdvertisedBuffers <= 2) {\r
- // In this case we have (probably) posted some buffers. We have to notify the\r
- // other side that he has more credits\r
- rc = m_pSdpSocket->m_SendBufferPool.PostCredits();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"m_SendBufferPool.PostCredits failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- } \r
- }\r
-\r
-Cleanup:\r
- return rc;\r
-}\r
-\r
-/*\r
- Currently the implmentation of shutdown should allow it to work, even without\r
- init being called\r
-*/\r
-\r
-VOID \r
-RecvPool::ShutDown()\r
-{\r
- // Lock is not taken here, but we should be gurantied that no\r
- // one can be racing us in here\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_BUFFER_POOL,"this = 0x%p \n", m_pSdpSocket);\r
- BufferDescriptor *pBufferDescriptor = NULL;\r
- LIST_ENTRY *item = NULL;\r
-\r
- while (m_FreePackets.Size() > 0 ) {\r
- item = m_FreePackets.RemoveHeadList();\r
- pBufferDescriptor = CONTAINING_RECORD(item, BufferDescriptor , BuffersList);\r
- BufferDescriptor::DeAllocateBuffer(pBufferDescriptor, RECV_BUFFERS_ALLOCATION_TAG);\r
- }\r
-\r
- while (m_FullPackets.Size() > 0 ) {\r
- item = m_FullPackets.RemoveHeadList();\r
- pBufferDescriptor = CONTAINING_RECORD(item, BufferDescriptor , BuffersList);\r
- BufferDescriptor::DeAllocateBuffer(pBufferDescriptor, RECV_BUFFERS_ALLOCATION_TAG);\r
- }\r
-}\r
-\r
-/* This function is called when the user mode has called close socket\r
- If a client is waiting on recieve we free him, he should get an\r
- error on his callback. *** The caller probably has a bug - as one\r
- can't race a closesocket ***\r
-*/ \r
-\r
-VOID \r
-RecvPool::CloseSocket()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_BUFFER_POOL, "this = 0x%p m_WaitingClients = %s waiting buffer = %d\n",\r
- this,\r
- m_ClientWaiting ? "true" : "false",\r
- m_FullPackets.Size()\r
- );\r
- AssertLocked();\r
-\r
- if (m_ClientWaiting) {\r
- KeSetEvent( &m_WaitingClients, IO_NO_INCREMENT, FALSE );\r
- m_ClientWaiting = false;\r
- }\r
- // The next time our client will try to get data, he will get \r
- // the error \r
-}\r
-\r
-NTSTATUS \r
-RecvPool::PostReceiveBuffer(BufferDescriptor *pBufferDescriptor)\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_BUFFER_POOL,"this = 0x%p \n", m_pSdpSocket);\r
- AssertLocked();\r
- NTSTATUS rc = STATUS_SUCCESS;\r
-\r
- ib_recv_wr_t recv_wr;\r
- recv_wr.p_next = NULL;\r
- recv_wr.wr_id = (uintn_t)pBufferDescriptor;\r
- recv_wr.num_ds = 1;\r
- recv_wr.ds_array = &pBufferDescriptor->ds_array;\r
- \r
- pBufferDescriptor->ds_array.length = pBufferDescriptor->BufferSize;\r
- pBufferDescriptor->ds_array.vaddr = MmGetPhysicalAddress( pBufferDescriptor->pBuffer ).QuadPart;\r
- pBufferDescriptor->ds_array.lkey = m_lkey;\r
- \r
- ib_api_status_t ib_status = ib_post_recv(m_qp, &recv_wr, NULL);\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_BUFFER_POOL,"ib_post_recv failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
- m_CurrentlyPostedRecievedBuffers++;\r
-\r
-Cleanup:\r
- return rc;\r
-\r
-}\r
-\r
-VOID \r
-RecvPool::AssertLocked()\r
-{\r
-#if DBG\r
- if (m_pSdpSocket) {\r
- m_pSdpSocket->AssertLocked();\r
- }\r
-#endif\r
-}\r
-\r
-\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-#ifndef H_SDP_RECV_POOL_H\r
-#define H_SDP_RECV_POOL_H \r
-\r
-class RecvPool {\r
-\r
-public:\r
-\r
- RecvPool();\r
-\r
- NTSTATUS Init(\r
- int MaxBuffers, \r
- int MaxConcurrentRecives, \r
- int MaxMessageSize,\r
- ib_pd_handle_t pd,\r
- ib_qp_handle_t qp,\r
- net32_t lkey,\r
- SdpSocket *pSdpSocket\r
- );\r
-\r
- NTSTATUS GetData(\r
- char *pData,\r
- uint32_t CopySize,\r
- uint32_t *Copied,\r
- KEVENT **ppEvent,\r
- bool FirstBuffer,\r
- bool *pNoMoreData\r
- );\r
-\r
- VOID AllowOthersToGet(); \r
-\r
- NTSTATUS RecievedBuffer(BufferDescriptor *pBufferDescriptor, bool error);\r
-\r
- NTSTATUS ReceiveIfCan();\r
-\r
- uint32_t GetRecvSeq() { return m_RecvSeq;}\r
-\r
- VOID CloseSocket();\r
-\r
- VOID ShutDown();\r
-\r
- uint16_t GetCurrentlyPostedRecievedBuffers() {\r
- return m_CurrentlyPostedRecievedBuffers;\r
- }\r
-\r
- void SetLocaleAdvertisedBuffers(uint16_t LocaleAdvertisedBuffers) {\r
- m_LocaleAdvertisedBuffers = LocaleAdvertisedBuffers;\r
- }\r
-\r
- void UpdateLocaleAdvertisedBuffers() {\r
- m_LocaleAdvertisedBuffers = m_CurrentlyPostedRecievedBuffers;\r
- }\r
-private:\r
-\r
- NTSTATUS PostReceiveBuffer(BufferDescriptor *pBufferDescriptor);\r
-\r
- // Global data about this connection\r
- int m_MaxBuffers; // The maximum number of buffers that we allow for this QP (to be allocated)\r
- int m_MaxConcurrentRecieves; // The total numbers of recvs that are allowd for the QP\r
- int m_MaxMessageSize; // The maximum buffer size that we allow for recieving\r
-\r
- uint16_t m_CurrentlyPostedRecievedBuffers; // Number of buffers that we have posted for recieve and didn't get an answer yet\r
- uint16_t m_LocaleAdvertisedBuffers; // Number of buffers that we have advertised to the remote side (l_advt_bf in linux)\r
- \r
- int m_CurrentlyAllocated; // The number of buffers that we have already allocated\r
-\r
- bool m_ClientBeingServed; // true if we have already started giving buffers to a client\r
-\r
- LinkedList m_FreePackets; // This packets are free and might be used for recieving\r
- LinkedList m_FullPackets; // This packets were filled with data and can be used by the user\r
- \r
-\r
- // TODO: A queue of events for threads that are waiting for buffers.\r
-\r
- // IBAL constants from the main socket structure \r
- // TODO: Should they stay here and be used like this ?\r
- ib_pd_handle_t m_pd;\r
- ib_qp_handle_t m_qp;\r
- net32_t m_lkey;\r
-\r
- // A list of events that the users has to wait on. ???? currently only one\r
- KEVENT m_WaitingClients; // switch to a linked list\r
- bool m_ClientWaiting;\r
-\r
- uint32_t m_RecvSeq; // sequence number of last message received (recv_seq)\r
-\r
- SdpSocket *m_pSdpSocket;\r
-\r
- // This signals that the remote side will not be sending any data any more\r
- bool m_DisConnRecieved;\r
-\r
- // TODO: The two counters bellow are for debug only. move them to be\r
- // declared as such\r
- public:\r
- uint32_t m_NumberOfBuffersRecievedWithError;\r
- uint32_t m_NumberOfBuffersRecievedSuccessfully;\r
- \r
-\r
- VOID AssertLocked();\r
-\r
-};\r
-\r
-#endif // H_SDP_RECV_POOL_H\r
-\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies LTD. All rights reserved.\r
- *\r
- * This software is available to you under the OpenIB.org BSD license\r
- * below:\r
- *\r
- * Redistribution and use in source and binary forms, with or\r
- * without modification, are permitted provided that the following\r
- * conditions are met:\r
- *\r
- * - Redistributions of source code must retain the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer.\r
- *\r
- * - Redistributions in binary form must reproduce the above\r
- * copyright notice, this list of conditions and the following\r
- * disclaimer in the documentation and/or other materials\r
- * provided with the distribution.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
- * SOFTWARE.\r
- *\r
- */\r
-\r
-// Author: Tzachi Dar\r
-\r
-#include "Precompile.h"\r
-\r
-#pragma warning(disable: 4244 ) \r
-\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "SdpSocket.tmh"\r
-#endif\r
-\r
-\r
-NTSTATUS sdp_cm_hello_ack_check(struct sdp_msg_hello_ack *hello_ack);\r
-NTSTATUS sdp_cm_hello_check(struct sdp_msg_hello *msg_hello);\r
-static NTSTATUS __send_cb2(SdpSocket * pSdpSocket);\r
-static NTSTATUS __recv_cb2(SdpSocket * pSdpSocket);\r
-static NTSTATUS __accept_requests(SdpSocket * pSdpSocket);\r
-\r
-static void AL_API\r
-cm_rej_callback(IN ib_cm_rej_rec_t *p_cm_rej_rec )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"dispatch level = %d\n", KeGetCurrentIrql());\r
- // BUGBUG: This should be used to return error to the connecting side\r
-}\r
-\r
-static void AL_API\r
-cm_rep_callback(\r
- IN ib_cm_rep_rec_t *p_cm_rep_rec )\r
-{\r
- SdpSocket *pSocket = (SdpSocket *) p_cm_rep_rec->qp_context;\r
- pSocket->CmRepCallback(p_cm_rep_rec);\r
-}\r
-\r
-static void AL_API\r
-cm_mra_callback(\r
- IN ib_cm_mra_rec_t *p_cm_mra_rec )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"cm_mra_callback called");\r
- ASSERT(FALSE);\r
-}\r
-\r
-/*\r
- * A user-specified callback that is invoked after receiving a load\r
- * alternate path response message.\r
- */\r
-static void AL_API\r
-cm_apr_callback(\r
- IN ib_cm_apr_rec_t *p_cm_apr_rec )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"cm_apr_callback called");\r
- ASSERT(FALSE);\r
-}\r
-\r
-static void AL_API\r
-cm_dreq_callback(IN ib_cm_dreq_rec_t *p_cm_dreq_rec )\r
-{\r
- SdpSocket *pSocket = (SdpSocket *) p_cm_dreq_rec->qp_context;\r
- pSocket->CmDreqCallback(p_cm_dreq_rec);\r
-}\r
-\r
-static void AL_API\r
-cm_lap_callback(\r
- IN ib_cm_lap_rec_t *p_cm_lap_rec )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"dispatch level = %d\n", KeGetCurrentIrql());\r
- ASSERT(FALSE);\r
-}\r
-\r
-void \r
-cm_rtu_callback(\r
- IN ib_cm_rtu_rec_t *p_cm_rtu_rec )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"dispatch level = %d\n", KeGetCurrentIrql());\r
- // Note - Referance count is not increased here since this is a call\r
- // back, and we are gurantied that shuting down ibal will only end\r
- // after all callbacks are finished.\r
- SdpSocket *pSocket = (SdpSocket *) p_cm_rtu_rec->qp_context;\r
- SdpSocket *pListeningSocket = pSocket->m_pListeningSocket;\r
- pListeningSocket->CmRtuCallback(p_cm_rtu_rec);\r
- \r
-}\r
-/*\r
- * A user-specified callback that is invoked after an error has occurred on\r
- * a listen request.\r
- */\r
-static void AL_API\r
-listen_err_callback(\r
- IN ib_listen_err_rec_t *p_listen_err_rec )\r
-{\r
- /* TODO ??????????????*/\r
- UNUSED_PARAM( p_listen_err_rec );\r
- ASSERT( 0 );\r
-}\r
-\r
-void CloseSocketThread(void *pContext)\r
-{\r
- SdpSocket *pSocket = (SdpSocket *) pContext;\r
- pSocket->CloseSocketThread();\r
- \r
-}\r
-static void AL_API\r
-cm_req_callback(\r
- IN ib_cm_req_rec_t *p_cm_req_rec )\r
-{\r
- // Pass the request to the approperiate socket\r
- SdpSocket *pSocket = (SdpSocket *) p_cm_req_rec->context;\r
- pSocket->CmReqCallback(p_cm_req_rec);\r
-}\r
-\r
-SdpSocket::SdpSocket()\r
-{\r
- m_CreationFlags = 0;\r
- m_SrcPort = 0;\r
- m_SrcIp = 0;\r
- m_DstPort = 0;\r
- m_DstIp = 0;\r
- \r
- m_SrcPortGuid = 0;\r
- m_SrcCaGuid = 0;\r
- m_ListenHandle = NULL;\r
-\r
- mh_Ca = NULL;\r
- m_pd = NULL;\r
- m_rcq = NULL;\r
- m_scq = NULL;\r
- m_qp = NULL;\r
- m_mr = NULL;\r
-\r
- m_state = SS_IDLE;\r
- m_pListeningSocket = NULL;\r
-\r
- m_CloseSocketCalled = false;\r
- m_ShutdownCalled = false;\r
- m_DisconnectConnectionRecieved = false;\r
- m_pSdpUserFile = NULL;\r
- InitializeListHead(&m_CallBackRequestList);\r
- \r
-}\r
-\r
-VOID SdpSocket::AssertLocked()\r
-{\r
-#if DBG\r
- m_Lock.AssertLocked();\r
-#endif\r
-}\r
-\r
-NTSTATUS SdpSocket::Init(\r
- WspSocketIn *pSocketInParam, \r
- WspSocketOut *pSocketOutParam,\r
- SdpUserFile *pSdpUserFile)\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = 0x%p\n", this);\r
-\r
- m_CreationFlags = pSocketInParam->dwFlags;\r
-\r
- m_Lock.Init(__send_cb2, __recv_cb2, __accept_requests ,this);\r
- pSocketOutParam->Errno = 0;// No error\r
- pSocketOutParam->pSocket = this; // give the user a handle to the socket\r
- KeInitializeEvent(&m_ShutdownCompleteEvent, NotificationEvent , FALSE );\r
- KeInitializeEvent(&m_DisconectSentEvent, NotificationEvent , FALSE );\r
-\r
- m_ConnectionList.Init(this);\r
-\r
- // We now allocate the needed structure for the close socket, so that \r
- // we won't be in trouble after the thread was created\r
- m_pCloseSocketThread = new ThreadHandle;\r
- if (m_pCloseSocketThread == NULL) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Failed to allocate new SocketThread this = 0x%p \n",this);\r
- rc = STATUS_NO_MEMORY;\r
- goto Cleanup;\r
- }\r
-\r
- m_pSdpUserFile = pSdpUserFile;\r
- m_pSdpUserFile->AddRef();\r
- \r
- \r
-Cleanup:\r
- return rc;\r
-}\r
-\r
-\r
-NTSTATUS SdpSocket::AcceptRequests() \r
-{\r
- // Check if our state allows us to handle send/recv/accept ...\r
- if (m_ShutdownCalled) return STATUS_SHUTDOWN_IN_PROGRESS;\r
- if (m_CloseSocketCalled) return STATUS_HANDLES_CLOSED; // Not the exact code\r
- // But it seems relatively closest\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-NTSTATUS SdpSocket::WSPSend(\r
- WspSendIn *pWspSendIn,\r
- WspSendOut *pWspSendOut,\r
- IRP *pIrp\r
- )\r
-{ \r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_SOCKET,"this = 0x%p size = %d \n",this, pWspSendIn->BufferSize);\r
-\r
- NTSTATUS rc = STATUS_SUCCESS; \r
- BufferDescriptor * pBufferDescriptor = NULL;\r
- bool First = true;\r
- ULONG Coppied = 0;\r
- PRKEVENT pBuffersEvent = NULL;\r
- bool BufferCopied;\r
- NTSTATUS rc1;\r
-\r
- // For zero bytes send we currently don't do anything and return with status \r
- // success\r
- if (pWspSendIn->BufferSize == 0) {\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET,"this = 0x%p - zero size send \n",this);\r
- goto Cleanup;\r
- }\r
-\r
- if (!m_Lock.Lock()) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "Failed to lock this = 0x%p \n",this);\r
- rc = STATUS_SHUTDOWN_IN_PROGRESS;\r
- goto Cleanup;\r
- }\r
-\r
- if ((m_state != SS_CONNECTED)) {\r
- // We can not send now.\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET,"Can't send now, m_state = %s\n",\r
- SS2String(m_state));\r
- rc = STATUS_SHUTDOWN_IN_PROGRESS;\r
- pWspSendOut->Errno = WSAENOTCONN;\r
- \r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- goto Cleanup;\r
- }\r
-\r
- // Check if there is already data in the queue, if yes we just \r
- // increase the queue and leave.\r
-\r
- ASSERT(!m_CloseSocketCalled);\r
- rc = m_SendBufferPool.AddToUserBuffers(&BufferCopied, false , pWspSendIn->pData, pWspSendIn->BufferSize,Coppied, pIrp);\r
- ASSERT(rc == STATUS_PENDING || rc == STATUS_SUCCESS);\r
- if (rc == STATUS_PENDING) {\r
- ASSERT(BufferCopied);\r
- // TODO: We already took the lock, and we are in the right context,\r
- // We should probably do some work there\r
- // Data was already copied to the buffer we are done.\r
- rc = m_Lock.Unlock();\r
- if (!NT_SUCCESS(rc)) {\r
- // No need to complete the IRP, as it will be be deleted\r
- // when all other IRPs will be\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "m_Lock.Unlock() failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
- // This IRP will be pending (make sure to change this after the unlock)\r
- rc = STATUS_PENDING;\r
-\r
- goto Cleanup;\r
- } \r
-\r
- ASSERT(rc == STATUS_SUCCESS);\r
- ASSERT(BufferCopied == false);\r
- // We now try to copy the data to the internal buffers\r
-\r
- while (Coppied < pWspSendIn->BufferSize) {\r
-\r
- rc = m_SendBufferPool.GetBuffer(&pBufferDescriptor);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_SendBufferPool.GetBuffer failed rc = 0x%x\n", rc );\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- goto Cleanup;\r
- }\r
-\r
- if (pBufferDescriptor == NULL) {\r
- // We don't have a new buffer any more, we store the remaining\r
- // buffer and quit\r
- rc = m_SendBufferPool.AddToUserBuffers(\r
- &BufferCopied, \r
- true , \r
- pWspSendIn->pData, \r
- pWspSendIn->BufferSize,\r
- Coppied,\r
- pIrp);\r
- ASSERT(rc == STATUS_PENDING);\r
- ASSERT(BufferCopied == true);\r
-\r
- rc = m_Lock.Unlock();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Unlock()");\r
- // No need to complete the IRP, as it will be be deleted\r
- // when all other IRPs will be\r
- goto Cleanup;\r
- }\r
- rc = STATUS_PENDING;// This IRP will be pending (make sure to change this after the unlock)\r
- goto Cleanup;\r
- }\r
- // copy the data from the user mode to the buffers \r
- ULONG CopySize = pBufferDescriptor->BufferSize - sizeof msg_hdr_bsdh;\r
- CopySize = min(CopySize, pWspSendIn->BufferSize - Coppied);\r
- \r
- rc = pBufferDescriptor->WriteData(pWspSendIn->pData + Coppied, CopySize);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"pBufferDescriptor->WriteData failed rc = 0x%x\n", rc );\r
- // free the buffer that you have\r
- rc1 = m_SendBufferPool.ReturnBuffer(pBufferDescriptor);\r
- ASSERT(NT_SUCCESS(rc1));\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass \r
- goto Cleanup;\r
- }\r
- Coppied += CopySize;\r
- \r
- // send the data to the buffer\r
- pBufferDescriptor->SetMid(SDP_MID_DATA);\r
- rc = m_SendBufferPool.AddBufferToQueuedList(pBufferDescriptor);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_SendBufferPool.AddBufferToQueuedList failed rc = 0x%x\n", rc );\r
- // free the buffer that you have\r
- rc1 = m_SendBufferPool.ReturnBuffer(pBufferDescriptor);\r
- ASSERT(NT_SUCCESS(rc1));\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass \r
- goto Cleanup;\r
- }\r
- }\r
- \r
- rc = m_Lock.Unlock();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Unlock()");\r
- goto Cleanup;\r
- }\r
-\r
-Cleanup:\r
- if (NT_SUCCESS(rc) ) {\r
- ASSERT((rc == STATUS_SUCCESS) || (rc == STATUS_PENDING));\r
- if (rc != STATUS_PENDING) {\r
- pWspSendOut->Errno = 0;\r
- ASSERT(pWspSendIn->BufferSize == Coppied);\r
- pWspSendOut->NumberOfBytesSent = Coppied;\r
- }\r
- } else {\r
- // Make sure that we have the error setted\r
- Shutdown();\r
- ASSERT(pWspSendOut->Errno != 0); // BUGBUG: Need to make sure that this\r
- if(pWspSendOut->Errno == 0) {\r
- // Some default value\r
- pWspSendOut->Errno = WSAENOBUFS;\r
- }\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET, "this = 0x%p rc = 0x%x\n",this, rc);\r
- // is indeed the case.\r
- }\r
- return rc;\r
-}\r
-\r
-NTSTATUS \r
-SdpSocket::WSPRecv(\r
- WspRecvIn *pWspRecvIn,\r
- WspRecvOut *pWspRecvOut\r
- )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_SOCKET,"this = 0x%p BufferSize = %d\n",this, pWspRecvIn->BufferSize);\r
-\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- bool First = true;\r
- uint32_t Coppied = 0, ThisCopy = 0;\r
- bool Locked = false;\r
- PRKEVENT pBuffersEvent = NULL;\r
- bool NoMoreData;\r
-\r
- if (pWspRecvIn->BufferSize == 0) {\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET,"this = 0x%p - zero size recv \n",this);\r
- goto Cleanup;\r
- }\r
-\r
- while (Coppied < pWspRecvIn->BufferSize) {\r
- if ((Locked == false) && !m_Lock.Lock()) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Failed to lock this = 0x%p \n",this);\r
- rc = STATUS_SHUTDOWN_IN_PROGRESS;\r
- goto Cleanup;\r
- }\r
- Locked = true;\r
- ASSERT(pBuffersEvent == NULL);\r
-\r
- if ((m_state != SS_CONNECTED && m_state!= SS_CONNECTED_DREP_SENT ) ) {\r
- // We can not recv now.\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET, "Can't recv now, m_state = %s this = %p\n",\r
- SS2String(m_state), this);\r
- rc = STATUS_SHUTDOWN_IN_PROGRESS;\r
- pWspRecvOut->Errno = WSAENOTCONN;\r
- \r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- Locked = false;\r
- goto Cleanup;\r
- }\r
-\r
- rc = m_RecvBufferPool.GetData(\r
- pWspRecvIn->pData + Coppied, \r
- pWspRecvIn->BufferSize - Coppied, \r
- &ThisCopy, \r
- &pBuffersEvent, \r
- First,\r
- &NoMoreData\r
- );\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_RecvBufferPool.GetData failed rc = 0x%x\n", rc );\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- Locked = false;\r
- goto Cleanup;\r
- }\r
- Coppied += ThisCopy;\r
-\r
- if (NoMoreData && pBuffersEvent == NULL) {\r
- // this means that there is nothing to copy, and we should return\r
- ASSERT(pBuffersEvent == NULL);\r
- break;\r
- }\r
- \r
- First = false;\r
- \r
- if (pBuffersEvent != NULL) {\r
- // We are told to wait on this event\r
- ASSERT(Coppied < pWspRecvIn->BufferSize);\r
- rc = m_Lock.Unlock();\r
- Locked = false;\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Unlock()");\r
- goto Cleanup;\r
- }\r
-\r
- rc = MyKeWaitForSingleObject(\r
- pBuffersEvent,\r
- UserRequest,\r
- UserMode,\r
- FALSE,\r
- NULL\r
- );\r
- pBuffersEvent = NULL;\r
- if (( rc == STATUS_ALERTED ) ||( rc == STATUS_USER_APC )) {\r
- // BUGBUG: Think what to do here, we should be able to stop the\r
- // connect, and quit (probably shutdown should be enough)\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET,"MyKeWaitForSingleObject was alerted rc = 0x%x\n", rc );\r
- rc = STATUS_UNEXPECTED_IO_ERROR;\r
- //pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
- Shutdown();\r
- goto Cleanup;\r
- }\r
- // try getting the buffer again\r
- continue;\r
- }\r
- } \r
- ASSERT(Locked == true);\r
- rc = m_Lock.Unlock();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Unlock()");\r
- goto Cleanup;\r
- }\r
-\r
- // This should happen only for good path anyway \r
- m_RecvBufferPool.AllowOthersToGet(); \r
-Cleanup:\r
- if (NT_SUCCESS(rc) ) {\r
- pWspRecvOut->Errno = 0;\r
- ASSERT(pWspRecvIn->BufferSize >= Coppied);\r
- pWspRecvOut->NumberOfBytesRecieved = Coppied;\r
- } else {\r
- // Make sure that we have the error setted\r
- ASSERT(pWspRecvOut->Errno != 0); // BUGBUG: Need to make sure that this\r
- pWspRecvOut->NumberOfBytesRecieved = 0;\r
- // is indeed the case.\r
- }\r
- // Currently in any case, the flags are not being used:\r
- pWspRecvOut->dwFlags = 0;\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_SOCKET,"this = 0x%p returning %d bytes \n",this, pWspRecvOut->NumberOfBytesRecieved);\r
- return rc;\r
-\r
-}\r
-\r
-NTSTATUS SdpSocket::WSPConnect(\r
- WspConnectIn *pWspConnectIn,\r
- WspConnectOut *pWspConnectOut\r
- )\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- ib_api_status_t ib_status;\r
- ib_gid_t DestPortGid;\r
- \r
- ib_path_rec_t path_rec;\r
- ULONG SrcIp = 0;\r
- \r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET, "this = 0x%p remote addresses ip=%d.%d.%d.%d:%d\n",\r
- this,\r
- (pWspConnectIn->DestIP & 0XFF000000) >> 24,\r
- (pWspConnectIn->DestIP & 0XFF0000) >> 16,\r
- (pWspConnectIn->DestIP & 0XFF00) >> 8,\r
- (pWspConnectIn->DestIP & 0XFF),\r
- pWspConnectIn->DestPort\r
- );\r
-\r
- if((pWspConnectIn->DestIP == 0) || \r
- (pWspConnectIn->DestPort == 0) ||\r
- (pWspConnectIn->SrcIP == 0)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Invalid Addresses");\r
- pWspConnectOut->Errno = WSAEADDRNOTAVAIL;\r
- goto Cleanup;\r
- }\r
-\r
- // check socket state\r
- m_Lock.Lock();//??? retval\r
- if ((m_state != SS_IDLE)) {\r
- // We can not connect in this state \r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET, "Can't send now, m_state = %s\n",\r
- SS2String(m_state));\r
- rc = STATUS_SHUTDOWN_IN_PROGRESS;\r
- pWspConnectOut->Errno = WSAENOTCONN;\r
-\r
- m_Lock.Unlock(); //?????retval\r
- goto Cleanup;\r
- \r
- }\r
-\r
- //\r
- // Arp: this means that based on the ARP protocol we should convert the \r
- // IP address into gid.\r
- //\r
- if (m_SrcIp == 0) {\r
- // No explicit bind was done, we use the default addresses\r
- m_SrcIp = pWspConnectIn->SrcIP;\r
- }\r
- if (m_SrcIp == INADDR_LOOPBACK) {\r
- // This is the loopback case, we use the dest IP in order to\r
- // get the port\r
- SrcIp = pWspConnectIn->DestIP;\r
- } else {\r
- SrcIp = m_SrcIp;\r
- }\r
-\r
- // Now that we know the source IP we can decide about the src port\r
- if (m_SrcPort == 0) {\r
- rc = g_pSdpDriver->m_pSdpArp->GetPort(m_SrcIp, &m_SrcPort);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_pSdpArp->GetPort failed rc = 0x%x\n", rc );\r
- pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- goto Cleanup;\r
- } \r
- } else {\r
- // We need to connect to the global table of ports\r
-\r
- }\r
- \r
- rc = g_pSdpDriver->m_pSdpArp->SourcePortGidFromIP(SrcIp, &m_SrcPortGuid, &m_SrcCaGuid);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_pSdpArp->SourcePortGidFromIP failed rc = 0x%x\n", rc );\r
- pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- goto Cleanup;\r
- } \r
-\r
- rc = g_pSdpDriver->m_pSdpArp->DestPortGidFromMac(m_SrcPortGuid, pWspConnectIn->DestMac, &DestPortGid);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_pSdpArp->DestPortGidFromIP failed rc = 0x%x\n", rc );\r
- pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- goto Cleanup;\r
- } \r
-\r
- //\r
- // Next step is convert the gid to a path record\r
- //\r
-\r
- // Since this is a function that might wait we do it without the lock\r
- m_state = SS_CONNECTING_QPR_SENT;\r
- m_Lock.Unlock(); //?????\r
-\r
- rc = g_pSdpDriver->m_pSdpArp->QueryPathRecord( m_SrcPortGuid, DestPortGid, &path_rec );\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_pSdpArp->QueryPathRecord failed rc = 0x%x\n", rc );\r
- pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
- goto Cleanup;\r
- }\r
-\r
-\r
- // Verify that we are in the correct state (just looking - without the lock)\r
- if (m_state != SS_CONNECTING_QPR_SENT) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"wrong state after QueryPathRecord\n" );\r
- pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
- goto Cleanup;\r
- }\r
-\r
- rc = CreateQp();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"CreateQp failed rc = 0x%x\n", rc );\r
- pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
- goto Cleanup;\r
- } \r
-\r
- // We need to prepare the hello mesage for the CM\r
- sdp_msg_hello hello_msg;\r
- CreateHelloHeader(&hello_msg, pWspConnectIn->DestIP);\r
- // We can now update the number of buffers that we have\r
- m_RecvBufferPool.SetLocaleAdvertisedBuffers(CL_NTOH16(hello_msg.bsdh.recv_bufs));\r
-\r
- // Create the CM request\r
- ib_cm_req_t cm_req;\r
- CreateCmRequest(&cm_req, &hello_msg, &path_rec, pWspConnectIn->DestPort);\r
-\r
- // Create the event to wait on to the connection request to end:\r
- KeInitializeEvent(&m_ConnectCmCompleteEvent, NotificationEvent , FALSE );\r
-\r
- m_state = SS_CONNECTING_REQ_SENT;\r
- \r
- ib_status = ib_cm_req( &cm_req );\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_cm_req failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
- goto Cleanup;\r
- }\r
-\r
- rc = MyKeWaitForSingleObject(\r
- &m_ConnectCmCompleteEvent,\r
- UserRequest,\r
- UserMode,\r
- FALSE,\r
- NULL);\r
-\r
- if (( rc == STATUS_ALERTED ) ||( rc == STATUS_USER_APC )) {\r
- // BUGBUG: Think what to do here, we should be able to stop the\r
- // connect, and quit (probably shutdown should be enough)\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET,"MyKeWaitForSingleObject was alerted rc = 0x%x\n", rc );\r
- rc = STATUS_UNEXPECTED_IO_ERROR;\r
- pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
- Shutdown();\r
- goto Cleanup;\r
- }\r
-\r
- //\r
- // We have recieved the REP, we send the RTU code\r
- // \r
- \r
- m_state = SS_CONNECTING_REQ_SENT;\r
-\r
- rc = CmSendRTU();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"CmSendRTU failed rc = 0x%x\n", rc );\r
- pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
- goto Cleanup;\r
- } \r
-\r
- // we should now complete the request\r
- m_Lock.Lock(); //????? retval\r
- if (m_state == SS_CONNECTED) {\r
- pWspConnectOut->Errno = 0;\r
- ASSERT(rc == STATUS_SUCCESS);\r
- m_Lock.Unlock(); //????? retval\r
- goto Cleanup;\r
- } else {\r
- // There probably was some error or some kind of shutdown, we \r
- // need to return an error.\r
- rc = STATUS_UNEXPECTED_IO_ERROR;\r
- pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- goto Cleanup;\r
- }\r
-\r
-Cleanup:\r
- // Make sure that success/failure is marked in both places\r
- ASSERT(((pWspConnectOut->Errno == 0) && (NT_SUCCESS(rc))) |\r
- ((pWspConnectOut->Errno != 0) && (!NT_SUCCESS(rc))));\r
-\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"connect is returning %s this = 0x%p\n",\r
- NT_SUCCESS(rc) ? "SUCCESS" : "FAILURE", this); \r
- return rc;\r
-\r
-}\r
-\r
-NTSTATUS \r
-SdpSocket::WSPBind(\r
- WspBindIn *pWspBindIn,\r
- WspBindOut *pWspBindOut\r
- )\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
-\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET, "this = 0x%p bind address ip=%d.%d.%d.%d:%d\n",\r
- this,\r
- (pWspBindIn->IP & 0XFF000000) >> 24,\r
- (pWspBindIn->IP & 0XFF0000) >> 16,\r
- (pWspBindIn->IP & 0XFF00) >> 8,\r
- (pWspBindIn->IP & 0XFF),\r
- pWspBindIn->Port\r
- );\r
-\r
- if (!m_Lock.Lock()) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Failed to lock this = 0x%p \n",this);\r
- rc = STATUS_SHUTDOWN_IN_PROGRESS;\r
- goto Cleanup;\r
- }\r
-\r
- /* Verify the state of the socket */\r
- if( m_state != SS_IDLE) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "socket is in invalid state %s this = 0x%p \n",\r
- SS2String(m_state),this );\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- rc = STATUS_INVALID_DEVICE_STATE;\r
- pWspBindOut->Errno = WSAEINVAL;\r
- goto Cleanup;\r
- }\r
-\r
- \r
- /* Check if the ip address is assigned to one of our IBoIB HCA. */\r
- if( pWspBindIn->IP != INADDR_ANY )\r
- {\r
- ASSERT(m_SrcCaGuid == NULL);\r
- rc = g_pSdpDriver->m_pSdpArp->SourcePortGidFromIP(pWspBindIn->IP, &m_SrcPortGuid, &m_SrcCaGuid);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_pSdpArp->SourcePortGidFromIP failed rc = 0x%x\n", rc );\r
- pWspBindOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- goto Cleanup;\r
- } \r
- }\r
- else\r
- {\r
- m_SrcPortGuid = 0;\r
- }\r
-\r
- if( pWspBindIn->IP != INADDR_ANY ) {\r
- /* Time to allocate our IB QP */\r
- rc = CreateQp();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"CreateQp failed rc = 0x%x\n", rc );\r
- pWspBindOut->Errno = WSAENOBUFS;\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- goto Cleanup;\r
- } \r
- }\r
-\r
- // If the src port is 0, we need to allocate a port for the caller.\r
- if (pWspBindIn->Port == 0) {\r
- m_SrcPort = 0;\r
- rc = g_pSdpDriver->m_pSdpArp->GetPort(pWspBindIn->IP, &m_SrcPort);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_pSdpArp->GetPort failed rc = 0x%x\n", rc );\r
- pWspBindOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- goto Cleanup;\r
- } \r
- } else {\r
- // We have to allocate the needed port in the table???????\r
-\r
- }\r
-\r
- // Everything went OK\r
- m_SrcPort = pWspBindIn->Port;\r
- m_SrcIp = pWspBindIn->IP;\r
-\r
- m_state = SS_BOUND;\r
- rc = m_Lock.Unlock();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Unlock()");\r
- goto Cleanup;\r
- }\r
-\r
-Cleanup: \r
- if (NT_SUCCESS(rc) ) {\r
- pWspBindOut->Errno = 0;\r
- } else {\r
- // Make sure that we have the error setted\r
- ASSERT(pWspBindOut->Errno != 0); // BUGBUG: Need to make sure that this\r
- // is indeed the case.\r
- //??????????? Make sure that we clean this function on exit\r
- }\r
- return rc;\r
-\r
-}\r
-\r
-NTSTATUS SdpSocket::WSPListen(\r
- WspListenIn *pWspListenIn,\r
- WspListenOut *pWspListenOut\r
- )\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- ib_cm_listen_t param;\r
- ib_api_status_t ib_status;\r
-\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = 0x%p \n",this);\r
- if (!m_Lock.Lock()) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Failed to lock this = 0x%p \n",this);\r
- rc = STATUS_SHUTDOWN_IN_PROGRESS;\r
- goto Cleanup;\r
- }\r
-\r
- /* Verify the state of the socket */\r
- if( m_state != SS_BOUND) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "socket is in invalid state %s this = 0x%p \n",\r
- SS2String(m_state),this);\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- rc = STATUS_INVALID_DEVICE_STATE;\r
- pWspListenOut->Errno = WSAEINVAL;\r
- goto Cleanup;\r
- }\r
-\r
- m_ConnectionList.SetBackLog(pWspListenIn->backlog);\r
-\r
- // Create the CM request\r
- memset( ¶m, 0, sizeof(param) );\r
-\r
- ASSERT(m_SrcPort != 0);\r
- param.svc_id = get_service_id_for_port( m_SrcPort);\r
- if( m_SrcPortGuid )\r
- {\r
- /* The socket is bound to an IP address */\r
- param.ca_guid = m_SrcCaGuid;\r
- param.port_guid = m_SrcPortGuid;\r
- }\r
- else\r
- {\r
- /* The socket is bound to INADDR_ANY */\r
- param.ca_guid = IB_ALL_CAS;\r
- param.port_guid = IB_ALL_PORTS;\r
- }\r
-\r
- param.lid = IB_ALL_LIDS;\r
-\r
- /* Currently no compare function ?????\r
- param.p_compare_buffer = (uint8_t *) & socket_info->info.listen.listen_req_param;\r
- param.compare_length = sizeof(struct listen_req_param);\r
- param.compare_offset = offsetof(struct cm_req_params, listen_req_param);\r
- */ \r
-\r
- param.pfn_cm_req_cb = cm_req_callback;\r
-\r
- param.qp_type = IB_QPT_RELIABLE_CONN;\r
-\r
- ASSERT(m_ListenHandle == NULL);\r
-\r
- ib_status = ib_cm_listen(\r
- g_pSdpDriver->m_al_handle , \r
- ¶m, \r
- listen_err_callback, \r
- this,\r
- &m_ListenHandle \r
- );\r
-\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_cm_listen failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- pWspListenOut->Errno = IbalToWsaError( ib_status );\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- goto Cleanup;\r
- }\r
- \r
- // SUCCESS - change the state \r
- m_state = SS_LISTENING;\r
- rc = m_Lock.Unlock();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Unlock()");\r
- goto Cleanup;\r
- }\r
-\r
-Cleanup: \r
- if (NT_SUCCESS(rc) ) {\r
- pWspListenOut->Errno = 0;\r
- } else {\r
- // Make sure that we have the error setted\r
- ASSERT(pWspListenOut->Errno != 0); // BUGBUG: Need to make sure that this\r
- // is indeed the case.\r
- }\r
- return rc;\r
-}\r
-\r
-NTSTATUS \r
-SdpSocket::WSPAccept(\r
- WspAcceptIn *pWspAcceptIn,\r
- WspAcceptOut *pWspAcceptOut\r
- )\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- bool Locked = false;\r
- SdpSocket *pNewSocket = NULL;\r
- PRKEVENT pAcceptEvent = NULL;\r
-\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = 0x%p \n",this);\r
-\r
- while (true) {\r
- if ((Locked == false) && !m_Lock.Lock()) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Failed to lock this = 0x%p \n",this);\r
- rc = STATUS_SHUTDOWN_IN_PROGRESS;\r
- goto Cleanup;\r
- }\r
- Locked = true;\r
- ASSERT(pNewSocket == NULL);\r
-\r
- /* Verify the state of the socket */\r
- if( m_state != SS_LISTENING) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"socket is in invalid state %s this = 0x%p \n",\r
- SS2String(m_state),this);\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- Locked = false;\r
- rc = STATUS_INVALID_DEVICE_STATE;\r
- pWspAcceptOut->Errno = WSAEINVAL;\r
- goto Cleanup;\r
- }\r
-\r
- rc = m_ConnectionList.AcceptAReadyConnection(&pNewSocket, &pAcceptEvent);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_ConnectionList.AcceptAReadyConnection failed rc = 0x%x\n", rc );\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- Locked = false;\r
- goto Cleanup;\r
- }\r
-\r
- if (pNewSocket != NULL) {\r
- ASSERT(pAcceptEvent == NULL);\r
- break;\r
- }\r
-\r
- ASSERT(pAcceptEvent != NULL);\r
- \r
- // We are told to wait on this event\r
- rc = m_Lock.Unlock();\r
- Locked = false;\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Unlock()");\r
- goto Cleanup;\r
- }\r
-\r
- rc = MyKeWaitForSingleObject(\r
- pAcceptEvent,\r
- UserRequest,\r
- UserMode,\r
- FALSE,\r
- NULL\r
- ); \r
- pAcceptEvent = NULL;\r
- if (( rc == STATUS_ALERTED ) ||( rc == STATUS_USER_APC )) {\r
- // BUGBUG: Think what to do here, we should be able to stop the\r
- // connect, and quit (probably shutdown should be enough)\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET,"MyKeWaitForSingleObject was alerted = 0x%x\n", rc );\r
- rc = STATUS_UNEXPECTED_IO_ERROR;\r
- //pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
- Shutdown();\r
- goto Cleanup;\r
- }\r
- // try getting the socket again\r
- } \r
-\r
- // I want to copy this data before releasing the lock\r
- ULONG IP = pNewSocket->m_DstIp;\r
- USHORT Port = pNewSocket->m_DstPort; \r
- \r
- ASSERT(Locked == true);\r
- rc = m_Lock.Unlock();\r
- Locked = false;\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Unlock()");\r
- goto Cleanup;\r
- }\r
- \r
-Cleanup: \r
- ASSERT(Locked == false);\r
- if (NT_SUCCESS(rc) ) {\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = 0x%p returning socket 0x%p \n",this, pNewSocket);\r
- pWspAcceptOut->pAccaptedSocket = pNewSocket;\r
- pWspAcceptOut->IP = IP;\r
- pWspAcceptOut->Port = Port;\r
- pWspAcceptOut->Errno = 0;\r
- // We need to "register" this socket in the global list\r
- \r
- } else {\r
- // Make sure that we have the error setted\r
- ASSERT(pWspAcceptOut->Errno != 0); // BUGBUG: Need to make sure that this\r
- ASSERT(pNewSocket == NULL);\r
- pWspAcceptOut->pAccaptedSocket = NULL;\r
- // is indeed the case.\r
- }\r
- // referance on pNewSocket is not currently released, since we are\r
- // returning them to the next level\r
- return rc;\r
-}\r
-\r
-NTSTATUS \r
-SdpSocket::WSPGetXXXName(\r
- WspGetSockXXIn *pWspGetSockXXIn,\r
- WspGetSockXXOut *pWspGetSockXXOut\r
- )\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- ib_api_status_t ib_status;\r
-\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = 0x%p \n",this);\r
- rc = m_Lock.LockRc();\r
- if (!NT_SUCCESS(rc)) { \r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Failed to lock this = 0x%p \n",this);\r
- pWspGetSockXXOut->Errno = WSAENETDOWN;\r
- goto Cleanup;\r
- }\r
- pWspGetSockXXOut->Errno = 0;\r
- if(pWspGetSockXXIn->LocaleAddress) {\r
- // This is the WSPGetSockName\r
- pWspGetSockXXOut->IP = m_SrcIp;\r
- pWspGetSockXXOut->Port = m_SrcPort; \r
- } else {\r
- // This is the WSPGetPeerName\r
- pWspGetSockXXOut->IP = m_DstIp;\r
- pWspGetSockXXOut->Port = m_DstPort; \r
- }\r
- rc = m_Lock.Unlock();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Unlock()");\r
- pWspGetSockXXOut->Errno = WSAENETDOWN; \r
- goto Cleanup;\r
- }\r
- \r
-Cleanup: \r
- if (NT_SUCCESS(rc) ) {\r
- pWspGetSockXXOut->Errno = 0;\r
- } else {\r
- // Make sure that we have the error setted\r
- ASSERT(pWspGetSockXXOut->Errno != 0);\r
- // is indeed the case.\r
- }\r
- return rc;\r
-\r
-\r
-}\r
-\r
-\r
-\r
-/*\r
- CloseSocket is probably one of the most complicated winsock APIs.\r
- Our current implmentation will be the default implmentation always. \r
- This means that the call is always non-blocking, and it is always gracefully.\r
- As a result, the remote side should return 0 on it's last read, and we should\r
- send a DisConn mesage.\r
-\r
- Well, gracefull or not, the other side is not gourantied to call recieve and \r
- we can't wait for ever. As a result a timer will be created and after 40 \r
- seconds, we close abortively.\r
-\r
- If a different thread is waiting on some event (read, send or accept), we will\r
- stop the blocking operation, and complete that wait with error.\r
-\r
- A special case to handle, is a socket that was created and after a while \r
- closed. In this case, there is nothing really to do, and we will use the \r
- same thread to close the socket.\r
-\r
- In the case of an error, an abortive close will be done (using the CM).\r
-\r
- There will be the following flag, telling the state of the socket.\r
-\r
- 1) CloseSocket called.\r
-\r
- So basicly, on close, we will do the following:\r
- 1) Stop all blocking operations (send, recieve, accept). (ofcourse, new ones\r
- are not allowed anymore)\r
- 2) Create the DisConn packet and send it. (if needed)\r
- 3) Start the timer, and wait for all the sends to end.\r
- 4) When ever a send is complited, we will check if this a shutdown in progress\r
- and we can close the socket.\r
-\r
- The "real" work of closing the socket will be done by the Shutdown function,\r
- that will be called either by the CloseSocket when the logic is finished.\r
-\r
-*/\r
-\r
-NTSTATUS \r
-SdpSocket::WSPCloseSocket(\r
- WspSocketCloseIn *pWspSocketCloseIn,\r
- WspSocketCloseOut *pWspSocketCloseOut\r
- )\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = 0x%p state = %s \n",this, SS2String(m_state));\r
- OBJECT_ATTRIBUTES attr;\r
- HANDLE ThreadHandle;\r
-\r
- if (!m_Lock.Lock()) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Failed to lock this = 0x%p \n",this);\r
- rc = STATUS_SHUTDOWN_IN_PROGRESS;\r
- goto Cleanup;\r
- }\r
-\r
- /* Verify the state of the socket */\r
- if(m_state == SS_IDLE) {\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"socket is in idle state this = 0x%p \n",\r
- this);\r
- m_Lock.Unlock(); // Error ignored as this is already a Shutdown pass\r
- Shutdown();\r
- pWspSocketCloseOut->Errno = 0;\r
- goto Cleanup;\r
- }\r
-\r
- // This will force that no more calls will be allowed\r
- ASSERT(m_CloseSocketCalled == FALSE); // If this is not the case \r
- // We shouldn't be able to take the lock\r
- m_CloseSocketCalled = true;\r
-\r
- // notify to all "subclients" to free all waiting clients\r
- // and also return cancell on all IRPs\r
- m_RecvBufferPool.CloseSocket();\r
- m_SendBufferPool.CloseSocket();\r
- m_ConnectionList.CloseSocket();\r
-\r
- if (m_state == SS_CONNECTED) {\r
- // Need to send the DisConn message to the remote side and wait\r
- rc = m_SendBufferPool.PostDisConn();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_SendBufferPool.PostDisConn failed rc = 0x%x\n", rc );\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- goto Cleanup;\r
- }\r
- } else {\r
- // Already set the event, so that the created thread won't have to wait\r
- // for anything\r
- KeSetEvent( &m_DisconectSentEvent, IO_NO_INCREMENT, FALSE );\r
- }\r
- \r
- // We will now create a thread that will be resposible for the\r
- // destruction of this socket\r
- AddRef();\r
-\r
- /* Create a new thread, storing both the handle and thread id. */\r
- InitializeObjectAttributes( &attr, NULL, OBJ_KERNEL_HANDLE, NULL, NULL );\r
- \r
- rc = PsCreateSystemThread(\r
- &ThreadHandle, \r
- THREAD_ALL_ACCESS,\r
- &attr,\r
- NULL,\r
- NULL,\r
- ::CloseSocketThread,\r
- this\r
- );\r
-\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"PsCreateSystemThread failed rc = 0x%x\n", rc );\r
- m_Lock.Unlock(); // Error ignored as this is already an error pass\r
- // The thread wasn't created so we should remove the refferance\r
- Release(); \r
- goto Cleanup;\r
- }\r
-\r
- ASSERT(m_pCloseSocketThread != NULL);\r
- // Convert the thread into a handle\r
- rc = ObReferenceObjectByHandle(\r
- ThreadHandle,\r
- THREAD_ALL_ACCESS,\r
- NULL,\r
- KernelMode,\r
- &m_pCloseSocketThread->ThreadObject,\r
- NULL\r
- );\r
- ASSERT(rc == STATUS_SUCCESS); // According to MSDN, must succeed if I set the params\r
- \r
- rc = ZwClose(ThreadHandle);\r
- ASSERT(NT_SUCCESS(rc)); // Should always succeed\r
-\r
- g_pSdpDriver->AddThread(m_pCloseSocketThread);\r
- m_pCloseSocketThread = NULL; // Will be delated when the callback thread is deleted\r
-\r
- rc = m_Lock.Unlock();\r
- if (rc == STATUS_HANDLES_CLOSED) {\r
- // shutdown in progress is fine since we have started the shutdown ...\r
- rc = STATUS_SUCCESS;\r
- }\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Unlock()");\r
- goto Cleanup;\r
- }\r
- \r
-Cleanup: \r
- if (NT_SUCCESS(rc) ) {\r
- pWspSocketCloseOut->Errno = 0;\r
- } else {\r
- // Make sure that we have the error setted\r
- ASSERT(pWspSocketCloseOut->Errno != 0); // BUGBUG: Need to make sure that this\r
- // is indeed the case. (also check if error was already signaled)\r
- // In the current model, we call shutdown in any case (to kill the socket)\r
- Shutdown(); \r
- }\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET, "this = 0x%p returning Errno = %d\n", \r
- this , pWspSocketCloseOut->Errno);\r
-\r
-\r
- return rc;\r
-}\r
-\r
-/*\r
- This function is supposed to wait for the send to compleate\r
- and then to kill the socket.\r
-\r
-*/ \r
-\r
-\r
-VOID SdpSocket::DisconectSentEvent()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET, "this = 0x%p\n",this);\r
- KeSetEvent( &m_DisconectSentEvent, IO_NO_INCREMENT, FALSE );\r
-}\r
-\r
-/*\r
- This is the "CloseSocket" thread call back.\r
- This thread waits WAIT_TO_SOCKET_SHUTDOWN seconds for tht send to complete \r
- and then it kills the socket abortively.\r
-*/ \r
-VOID SdpSocket::CloseSocketThread()\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = 0x%p\n",this);\r
-\r
- // wait for the last thread to end.\r
- LARGE_INTEGER WaitTime;\r
- \r
- WaitTime = TimeFromLong(WAIT_TO_SOCKET_SHUTDOWN * 10 * 1000000);\r
- rc = MyKeWaitForSingleObject(\r
- &m_DisconectSentEvent,\r
- Executive,\r
- KernelMode,\r
- FALSE,\r
- &WaitTime\r
- );\r
-\r
- if (rc == STATUS_TIMEOUT) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Wait failed with time out\n");\r
- }\r
-\r
- ASSERT(NT_SUCCESS(rc));\r
- ASSERT(rc == STATUS_SUCCESS || rc == STATUS_TIMEOUT);// || rc == STATUS_USER_APC); //???????? what to do \r
- \r
- Shutdown();\r
-\r
- // Everything done - the threads releases the last referance\r
- // and kills itself\r
- Release();\r
- PsTerminateSystemThread(STATUS_SUCCESS);\r
-\r
- // Do I get here ?\r
- ASSERT(FALSE);\r
- \r
-}\r
-\r
-NTSTATUS SdpSocket::CmSendRTU()\r
-{\r
- // This is only valid in connect.\r
- // We might also be in shutdown, but nothing else currently\r
- \r
- ib_api_status_t ib_status;\r
- NTSTATUS rc = STATUS_SUCCESS;\r
-\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = 0x%p \n", this);\r
-\r
- if (m_state != SS_CONNECTING_REQ_SENT) {\r
- // There was some error, we can release the waiting thread.\r
- // The error will be handled there\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET,"this = 0x%p invalid state %s\n", this, SS2String(m_state));\r
- rc = STATUS_UNEXPECTED_IO_ERROR;\r
- goto Cleanup;\r
- } \r
- \r
- /*\r
- * check Hello Header Ack, to determine if we want\r
- * the connection.\r
- */\r
-\r
- rc = sdp_cm_hello_ack_check(&m_hello_ack);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"sdp_cm_hello_ack_check failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
-\r
- int MaxMessageSize = min(m_hello_ack.hah.l_rcv_size, MAX_SEND_BUFFER_SIZE);\r
-\r
- rc = m_SendBufferPool.Init(MAX_SEND_PACKETS, SDP_QP_ATTRIB_SQ_DEPTH, MaxMessageSize, m_pd, m_qp, m_lkey, this);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_SendBufferPool.Init failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
-\r
- rc = m_RecvBufferPool.Init(MAX_RECV_PACKETS, QP_ATTRIB_RQ_DEPTH, MaxMessageSize, m_pd, m_qp, m_lkey, this);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_RecvBufferPool.Init failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
- m_SendBufferPool.SetRemoteRecvBuf(m_hello_ack.bsdh.recv_bufs);\r
-\r
-#if 0\r
- /*\r
- * read remote information\r
- */\r
- conn->send_size = hello_ack->hah.l_rcv_size;\r
- conn->r_max_adv = hello_ack->hah.max_adv;\r
- conn->r_recv_bf = hello_ack->bsdh.recv_bufs;\r
- conn->recv_seq = hello_ack->bsdh.seq_num;\r
- conn->advt_seq = hello_ack->bsdh.seq_num;\r
-\r
- conn->d_qpn = event->param.rep_rcvd.remote_qpn;\r
- /*\r
- * The maximum amount of data that can be sent to the remote\r
- * peer is the smaller of the local and remote buffer sizes, \r
- * minus the size of the message header.\r
- */\r
- conn->send_size = min((u16)sdp_buff_pool_buff_size(),\r
- (u16)conn->send_size) - SDP_MSG_HDR_SIZE;\r
-\r
-#endif\r
-\r
- ib_cm_rtu_t cm_rtu;\r
-\r
- memset( &cm_rtu, 0, sizeof(cm_rtu) );\r
-\r
- cm_rtu.access_ctrl = IB_AC_RDMA_READ | IB_AC_RDMA_WRITE | IB_AC_LOCAL_WRITE;\r
-\r
-#if 0 // Do we want to keep it\r
- // Bug in TAVOR\r
- cm_rtu.sq_depth = QP_ATTRIB_SQ_DEPTH;\r
- cm_rtu.rq_depth = QP_ATTRIB_RQ_DEPTH;\r
-#endif\r
-\r
- cm_rtu.pfn_cm_apr_cb = cm_apr_callback;\r
- cm_rtu.pfn_cm_dreq_cb = cm_dreq_callback;\r
-\r
- ib_status = ib_cm_rtu( m_cm_handle_t, &cm_rtu );\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_cm_rtu failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
- // We are now connected\r
- // How should this be locked ??\r
- m_state = SS_CONNECTED;\r
-\r
- // we now arm the CQs\r
- ib_status = ib_rearm_cq(m_rcq, FALSE);\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_rearm_cq failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
-\r
- ib_status = ib_rearm_cq(m_scq, FALSE);\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_rearm_cq failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
-\r
- // We now start the recieve processing\r
-\r
- rc = m_Lock.LockRc();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Lock failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
- \r
- rc = m_RecvBufferPool.ReceiveIfCan(); //??? error\r
- m_Lock.Unlock(); // error ????\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_RecvBufferPool.ReceiveIfCan failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
-\r
-Cleanup: \r
- return rc;\r
-}\r
-\r
-\r
-VOID SdpSocket::CmRepCallback(IN ib_cm_rep_rec_t *p_cm_rep_rec)\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = 0x%p\n", this);\r
- ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);\r
-\r
- if (m_state != SS_CONNECTING_REQ_SENT) {\r
- // This is not the state that we waited for, not much that we can\r
- // do. (This might happen in shutdown)\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Not the expacted state %s\n", SS2String(m_state));\r
- ASSERT(FALSE);\r
- return;\r
- }\r
-\r
- // We need to store the params and signal the event\r
- sdp_msg_hello_ack *hello_ack = (sdp_msg_hello_ack *)p_cm_rep_rec->p_rep_pdata;\r
- m_hello_ack = *hello_ack;\r
- m_cm_handle_t = p_cm_rep_rec->h_cm_rep;\r
-\r
- KeSetEvent(&m_ConnectCmCompleteEvent, IO_NO_INCREMENT, FALSE);\r
-}\r
-\r
-VOID \r
-SdpSocket::CmReqCallback(IN ib_cm_req_rec_t *p_cm_req_rec)\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = 0x%p\n", this);\r
-\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);\r
- net64_t SrcCaGuid;\r
- ib_net64_t SrcPortGuid;\r
- ib_api_status_t ib_status;\r
- SdpSocket *pNewSocket = NULL;\r
-\r
- sdp_msg_hello *msg_hello = (sdp_msg_hello *)p_cm_req_rec->p_req_pdata;\r
-\r
- rc = sdp_cm_hello_check(msg_hello);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"sdp_cm_hello_ack_check failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
-\r
- // Take the lock and verify the state\r
- rc = m_Lock.LockRc();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Lock failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
-\r
- if (m_state != SS_LISTENING) {\r
- // This is not the state that we waited for, we drop the request\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Not the expacted state %s\n", SS2String(m_state));\r
- ASSERT(FALSE);\r
- goto ErrorLocked;\r
- }\r
-\r
- // Check that we haven't passed the backlog for this connection\r
- if (m_ConnectionList.IsFull()) {\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET,"Dropping the connection, because of a backlog that is too small\n");\r
- goto ErrorLocked; \r
- }\r
-\r
- // Create a new socket for this request\r
- pNewSocket = new SdpSocket;\r
- if (pNewSocket == NULL) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"new pNewSocket failed\n"); \r
- goto ErrorLocked;\r
- }\r
-\r
- // Code here is a little dirty to allow us to use the existing infrastructure\r
- WspSocketIn SocketInParam;\r
- WspSocketOut SocketOutParam;\r
- SocketInParam.dwFlags = 0; \r
- rc = pNewSocket->Init(&SocketInParam, &SocketOutParam, m_pSdpUserFile);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"pNewSocket.Init()");\r
- goto ErrorLocked;\r
- }\r
- ASSERT(SocketOutParam.Errno == 0);\r
- ASSERT(SocketOutParam.pSocket == pNewSocket);\r
-\r
- // Connect the new socket to it's creator\r
- ASSERT(pNewSocket->m_pListeningSocket == NULL);\r
- pNewSocket->m_pListeningSocket = this;\r
- pNewSocket->m_pListeningSocket->AddRef(); \r
-\r
- /*\r
- * save hello parameters.\r
- */\r
- pNewSocket->m_state = SS_REQ_RECV; //?????? do we really need this state?????\r
-\r
- pNewSocket->m_SrcIp = msg_hello->hh.dst.ipv4.addr;\r
- ASSERT(m_SrcPort != 0);\r
- pNewSocket->m_SrcPort = m_SrcPort;\r
- pNewSocket->m_DstIp = msg_hello->hh.src.ipv4.addr;\r
- pNewSocket->m_DstPort = msg_hello->hh.port;\r
-\r
- // Initiate parameters based on what we recieve from the remote side\r
-// pNewSocket->send_size = msg_hello->hh.l_rcv_size; ??? MAX_Message_size when calling init on the buffers ???\r
-//??? pNewSocket->r_max_adv = msg_hello->hh.max_adv; ???????????\r
-//???? pNewSocket->r_recv_bf = msg_hello->bsdh.recv_bufs; <= m_pSdpSocket->m_SendBufferPool.SetRemoteRecvBuf(rRecvBuf);\r
-//??? pNewSocket->recv_seq = msg_hello->bsdh.seq_num;\r
-//??? pNewSocket->advt_seq = msg_hello->bsdh.seq_num;\r
-\r
- /*\r
- * The maximum amount of data that can be sent to the remote\r
- * peer is the smaller of the local and remote buffer sizes,\r
- * minus the size of the message header.\r
- */\r
-// conn->send_size = min((u16)sdp_buff_pool_buff_size(),\r
-// (u16)conn->send_size) - SDP_MSG_HDR_SIZE; ??????????\r
-\r
- // We will now allocate our QP.\r
-\r
- rc = g_pSdpDriver->m_pSdpArp->SourcePortGidFromIP(pNewSocket->m_SrcIp, &SrcPortGuid, &SrcCaGuid);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_pSdpArp->SourcePortGidFromIP failed rc = 0x%x\n", rc );\r
- goto ErrorLocked;\r
- } \r
-\r
- if (pNewSocket->m_SrcCaGuid == 0) {\r
- pNewSocket->m_SrcCaGuid = SrcCaGuid;\r
- } else {\r
- ASSERT(pNewSocket->m_SrcCaGuid == CL_NTOH64(p_cm_req_rec->primary_path.sgid.unicast.interface_id));\r
- }\r
- \r
- // MAke sure that the port that was recieved muches the one that we\r
- // get based on the source IP.\r
- if (SrcPortGuid != p_cm_req_rec->primary_path.sgid.unicast.interface_id) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Recieved guid is not what we have expected\n" ); \r
- ASSERT(0);\r
- goto ErrorLocked;\r
- }\r
-\r
- rc = pNewSocket->CreateQp();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"pNewSocket.CreateQp()");\r
- goto ErrorLocked;\r
- }\r
-\r
- // We will now call init on the sender and the reciever\r
- int MaxMessageSize = min(msg_hello->hh.l_rcv_size, MAX_SEND_BUFFER_SIZE);\r
-\r
- rc = pNewSocket->m_SendBufferPool.Init(MAX_SEND_PACKETS, SDP_QP_ATTRIB_SQ_DEPTH, MaxMessageSize, pNewSocket->m_pd, pNewSocket->m_qp, pNewSocket->m_lkey, pNewSocket);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_SendBufferPool.Init failed rc = 0x%x\n", rc );\r
- goto ErrorLocked;\r
- }\r
-\r
- rc = pNewSocket->m_RecvBufferPool.Init(MAX_RECV_PACKETS, QP_ATTRIB_RQ_DEPTH, MaxMessageSize, pNewSocket->m_pd, pNewSocket->m_qp, pNewSocket->m_lkey, pNewSocket);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_RecvBufferPool.Init failed rc = 0x%x\n", rc );\r
- goto ErrorLocked;\r
- }\r
- pNewSocket->m_SendBufferPool.SetRemoteRecvBuf(msg_hello->bsdh.recv_bufs);\r
-\r
- // It won't be used, but I want to make sure that there won't be\r
- // problems later\r
- pNewSocket->m_ConnectionList.Init(pNewSocket);\r
-\r
-#if 0 // ???????????????????????\r
- /*\r
- * Save connect request info for QP modify in cm_accept().\r
- */\r
- conn->d_lid = event->param.req_rcvd.primary_path->dlid;\r
- conn->s_lid = event->param.req_rcvd.primary_path->slid;\r
- conn->d_qpn = event->param.req_rcvd.remote_qpn;\r
-\r
- conn->path_mtu = event->param.req_rcvd.primary_path->mtu;\r
- /*\r
- * inherit listener properties\r
- */\r
- sdp_cm_listen_inherit(listen_conn, conn);\r
- /*\r
- * initiate a CM response message.\r
- */\r
-#endif \r
-\r
- //\r
- // Send the ib_cm_rep message to the remote side\r
- //\r
- ib_cm_rep_t cm_rep;\r
-\r
- memset( &cm_rep, 0, sizeof(cm_rep) );\r
-\r
- cm_rep.qp_type = IB_QPT_RELIABLE_CONN;\r
- cm_rep.h_qp = pNewSocket->m_qp;\r
-// TODO: Add more cababilities once we start using RDMA\r
-// cm_rep.access_ctrl = IB_AC_RDMA_READ | IB_AC_RDMA_WRITE | IB_AC_LOCAL_WRITE;\r
- cm_rep.access_ctrl = IB_AC_LOCAL_WRITE;\r
-#if 0\r
- // Bug in TAVOR\r
- cm_rep.sq_depth = QP_ATTRIB_SQ_DEPTH;\r
- cm_rep.rq_depth = QP_ATTRIB_RQ_DEPTH;\r
-#endif\r
- // We need to prepare the hello mesage for the CM\r
- sdp_msg_hello_ack hello_ack_msg;\r
- CreateHelloAckHeader(&hello_ack_msg);\r
-\r
- pNewSocket->m_RecvBufferPool.SetLocaleAdvertisedBuffers(CL_NTOH16(hello_ack_msg.bsdh.recv_bufs));\r
-\r
- cm_rep.p_rep_pdata = (uint8_t *) &hello_ack_msg;\r
- cm_rep.rep_length = sizeof(hello_ack_msg);\r
-\r
- cm_rep.init_depth = QP_ATTRIB_INITIATOR_DEPTH;\r
- cm_rep.target_ack_delay = 10;\r
- cm_rep.failover_accepted = IB_FAILOVER_ACCEPT_UNSUPPORTED;\r
- cm_rep.flow_ctrl = p_cm_req_rec->flow_ctrl;\r
- cm_rep.rnr_nak_timeout = QP_ATTRIB_RNR_NAK_TIMEOUT;\r
- cm_rep.rnr_retry_cnt = p_cm_req_rec->rnr_retry_cnt;\r
- cm_rep.pfn_cm_mra_cb = cm_mra_callback;\r
- cm_rep.pfn_cm_rej_cb = cm_rej_callback;\r
- cm_rep.pfn_cm_rtu_cb = cm_rtu_callback;\r
- cm_rep.pfn_cm_lap_cb = cm_lap_callback;\r
- cm_rep.pfn_cm_dreq_cb = cm_dreq_callback;\r
-\r
- ib_status = ib_cm_rep( p_cm_req_rec->h_cm_req, &cm_rep );\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_cm_rep failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto ErrorLocked;\r
- }\r
-\r
- // Add this socket to the list of sockets ?????? should this also be done on errors ????\r
- rc = m_ConnectionList.AddConnectionToReplySent(pNewSocket);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"pNewSocket.Init()");\r
- goto ErrorLocked;\r
- }\r
-\r
- rc = pNewSocket->m_Lock.LockRc();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"pNewSocket.Init()");\r
- goto ErrorLocked;\r
- } \r
-\r
- rc = pNewSocket->m_RecvBufferPool.ReceiveIfCan();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"pNewSocket.Init()");\r
- pNewSocket->m_Lock.Unlock(); // Error is ignored, since this is already an error path\r
- goto ErrorLocked;\r
- }\r
-\r
- // we now arm the CQs (after that a call back might happen)\r
- ib_status = ib_rearm_cq(pNewSocket->m_rcq, FALSE);\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_rearm_cq failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- pNewSocket->m_Lock.Unlock(); // Error is ignored, since this is already an error path\r
- goto ErrorLocked;\r
- }\r
-\r
- ib_status = ib_rearm_cq(pNewSocket->m_scq, FALSE);\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_rearm_cq failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto ErrorLocked;\r
- }\r
- \r
- // Sucess - we can now release the lock and update our state\r
- pNewSocket->m_state = SS_REP_SENT;\r
-\r
- rc = pNewSocket->m_Lock.Unlock(); // ???????? Error is ignored, since this is already an error path\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"pNewSocket->m_Lock.Unlock()");\r
- // BUGBUG: who is responsibale for the cleanup ???????\r
- goto ErrorLocked;\r
- } \r
- \r
- rc = m_Lock.Unlock();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Unlock()");\r
- // BUGBUG: who is responsibale for the cleanup ???????\r
- } \r
-\r
-Cleanup:\r
- if (!NT_SUCCESS(rc)) {\r
- // BUGBUG: We need to send a rej here\r
- }\r
- if (pNewSocket != NULL) {\r
- pNewSocket->Release();\r
- } \r
- return;\r
-\r
-ErrorLocked:\r
- // Previous rc doesn't mater as this function is void\r
- rc = m_Lock.Unlock();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Unlock()");\r
- // BUGBUG: who is responsibale for the cleanup ???????\r
- }\r
- goto Cleanup; \r
-\r
-}\r
-\r
-VOID \r
-SdpSocket::CmRtuCallback(IN ib_cm_rtu_rec_t *p_cm_rtu_rec)\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);\r
-\r
- SdpSocket *pSocket = (SdpSocket *) p_cm_rtu_rec->qp_context;\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = 0x%p pSocket = 0x%p\n", this, pSocket);\r
-\r
- // In order to make our model more consistent we increase the refcount here.\r
- // (This is not a must since this is a callback and we are gurantied that the last\r
- // callback won't happen untill we free IBAL)\r
- pSocket->AddRef();\r
-\r
-\r
- // Take the lock and verify the state\r
- rc = m_Lock.LockRc();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Lock failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
-\r
- if (m_state != SS_LISTENING) {\r
- // This is not the state that we waited for, we drop the request\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Not the expacted state %s\n", SS2String(m_state));\r
- ASSERT(FALSE); // Can this happen on shutdown ?\r
- goto ErrorLocked;\r
- }\r
- \r
- // First step is to verify that we have the new socket\r
- rc = m_ConnectionList.VerifyConnictionInReplySent(pSocket);\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_ConnectionList.GetConnection failed (got a call back on a not existing connection)");\r
- ASSERT(FALSE);\r
- goto ErrorLocked;\r
- }\r
-\r
- // Next step is to move the new socket to the SS_CONNECTED state\r
- rc = pSocket->m_Lock.LockRc();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Lock failed rc = 0x%x\n", rc );\r
- goto ErrorLocked;\r
- }\r
- if (pSocket->m_state != SS_REP_SENT) {\r
- ASSERT(pSocket->m_state == SS_REP_SENT);\r
- // This is not the expected state (probably shutdown).\r
- // we should signal an error also on the one that is waiting\r
- pSocket->m_Lock.Unlock(); // Error is ignored since this is already\r
- // an error path\r
- pSocket->Shutdown(); \r
- rc = STATUS_UNEXPECTED_IO_ERROR;\r
- goto ErrorLocked;\r
- }\r
-\r
- pSocket->m_state = SS_CONNECTED;\r
-\r
- m_ConnectionList.MoveConnectionFromReplyToReady(pSocket);\r
- rc = pSocket->m_Lock.Unlock();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"pSocket->m_Lock.Lock failed rc = 0x%x\n", rc );\r
- goto ErrorLocked;\r
- }\r
-\r
- // if needed we will free the one that is waiting\r
- m_ConnectionList.FreeWaitingIfCan();\r
- rc = m_Lock.Unlock();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Lock failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
- \r
-Cleanup:\r
-\r
- if (pSocket != NULL) {\r
- pSocket->Release();\r
- }\r
- \r
- // Who should take care of the errors that were found here (if found)????????\r
- return;\r
-\r
-ErrorLocked:\r
- // Previous rc doesn't mater as this function is void\r
- rc = m_Lock.Unlock();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Unlock()");\r
- // BUGBUG: who is responsibale for the cleanup ???????\r
- }\r
- goto Cleanup; \r
-\r
-}\r
-\r
-VOID \r
-SdpSocket::CmDreqCallback(IN ib_cm_dreq_rec_t *p_cm_dreq_rec)\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = 0x%p, dispatch level = %d\n", this, KeGetCurrentIrql());\r
- ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- ib_cm_drep_t cm_drep;\r
- ib_api_status_t ib_status;\r
- bool Locked;\r
-\r
-\r
- // Take the lock and verify the state\r
- rc = m_Lock.LockRc();\r
- // BUGBUG: It seems that even when the lock fails we should send\r
- // drep\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Lock failed rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
-\r
- if (m_state != SS_CONNECTED) {\r
- // This is not the state that we waited for, we drop the request\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Not the expacted state %s\n", SS2String(m_state));\r
- ASSERT(FALSE); // Can this happen on shutdown ?\r
- goto ErrorLocked;\r
- }\r
-\r
- // We should send a DREP now\r
- memset( &cm_drep, 0, sizeof(cm_drep) );\r
-\r
- ib_status = ib_cm_drep( p_cm_dreq_rec->h_cm_dreq, &cm_drep );\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_cm_drep failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto ErrorLocked;\r
- }\r
-\r
- // last step is to change our state (this will affect close socket for example)\r
- m_state = SS_CONNECTED_DREP_SENT;\r
-\r
- // We should close the connection know ??????????/\r
-\r
- rc = m_Lock.Unlock();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Unlock()");\r
- // BUGBUG: who is responsibale for the cleanup ???????\r
- } \r
-\r
- //??????? abortive close the connection \r
-\r
-Cleanup:\r
-\r
- // Who should take care of the errors that were found here (if found)????????\r
- return;\r
-\r
-ErrorLocked:\r
- // Previous rc doesn't mater as this function is void\r
- rc = m_Lock.Unlock();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_Lock.Unlock()");\r
- // BUGBUG: who is responsibale for the cleanup ???????\r
- }\r
- goto Cleanup; \r
-\r
-}\r
-\r
-\r
-VOID\r
-SdpSocket::__recv_cb1(\r
- IN const ib_cq_handle_t h_cq,\r
- IN void *cq_context )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_SOCKET,"__recv_cb1\n");\r
-\r
- SdpSocket *pSocket = (SdpSocket *) cq_context;\r
- pSocket->m_Lock.SignalCB(RECV_CB_CALLED);\r
-}\r
-\r
-NTSTATUS\r
-SdpSocket::recv_cb()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_SOCKET,"this = 0x%p \n", this);\r
- NTSTATUS rc = STATUS_SUCCESS, rc1 = STATUS_SUCCESS; \r
- ib_api_status_t ib_status;\r
- ib_wc_t *p_free, *p_wc1;\r
- uint32_t pkt_cnt, recv_cnt = 0;\r
- size_t i;\r
- BufferDescriptor *pBufferDescriptor = NULL;\r
-\r
- for( i = 0; i < QP_ATTRIB_RQ_DEPTH; i++ )\r
- m_RecvComplitionWC[i].p_next = &m_RecvComplitionWC[i + 1];\r
- m_RecvComplitionWC[QP_ATTRIB_RQ_DEPTH - 1].p_next = NULL;\r
-\r
- do\r
- {\r
- /* If we get here, then the list of WCs is intact. */\r
- p_free = m_RecvComplitionWC;\r
-\r
- ib_status = ib_poll_cq( m_rcq, &p_free, &p_wc1 );\r
- if( (ib_status != IB_SUCCESS) && (ib_status != IB_NOT_FOUND) ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_poll_cq failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
- if (ib_status == IB_NOT_FOUND) {\r
- // Nothing to do in this case\r
- ASSERT(NT_SUCCESS(rc));\r
- goto Cleanup;\r
- }\r
- \r
- ASSERT (ib_status == IB_SUCCESS);\r
- ib_wc_t *p_wc;\r
- for( p_wc = p_wc1; p_wc; p_wc = p_wc->p_next ) {\r
- ASSERT( p_wc->status == IB_WCS_SUCCESS || p_wc->status == IB_WCS_WR_FLUSHED_ERR); // BUGBUG: Can there be other errors here ???\r
- if (p_wc->status == IB_WCS_WR_FLUSHED_ERR) {\r
- // We have an error, but we still need to return the packet to the caller\r
- pBufferDescriptor = (BufferDescriptor *)p_wc->wr_id;\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_SOCKET,"p_wc->status == IB_WCS_WR_FLUSHED_ERR \n" );\r
- // we can not handle it, but we can and should return it to the pool of recieved buffers\r
- rc1 = m_RecvBufferPool.RecievedBuffer(pBufferDescriptor, true);\r
- ASSERT(rc1 == STATUS_SUCCESS); // return with error can not fail\r
- UpdateRc(&rc, rc1);\r
- continue;\r
- }\r
- if (p_wc->status == IB_WCS_SUCCESS) {\r
- int len = p_wc->length;\r
- pBufferDescriptor = (BufferDescriptor *)p_wc->wr_id;\r
- ASSERT(len >= sizeof msg_hdr_bsdh);\r
- if (len < sizeof msg_hdr_bsdh) {\r
- // This is a message that is not big enough\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Recieved a message with a buffer that is too short len = %d\n", len );\r
- // we can not handle it, but we can and should return it to the pool of recieved buffers\r
- rc1 = m_RecvBufferPool.RecievedBuffer(pBufferDescriptor, true);\r
- ASSERT(rc1 == STATUS_SUCCESS); // return with error can not fail\r
- UpdateRc(&rc, rc1);\r
- continue;\r
- }\r
- \r
- msg_hdr_bsdh *pHeader = (msg_hdr_bsdh *)pBufferDescriptor->pBuffer;\r
- sdp_msg_swap_bsdh(pHeader);\r
- ASSERT(pHeader->size >= 0x10);\r
- if (len != pHeader->size) {\r
- // This is a message that is not formated well\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Recieved a message with a len != pHeader->size = %d : %d\n", len , pHeader->size );\r
- // we can not handle it, but we can and should return it to the pool of recieved buffers\r
- rc1 = m_RecvBufferPool.RecievedBuffer(pBufferDescriptor, true);\r
- ASSERT(rc1 == STATUS_SUCCESS); // return with error can not fail\r
- UpdateRc(&rc, rc1);\r
- continue;\r
- }\r
- // BUGBUG: currently we only handle this messages, we should handle\r
- // them better ???????????\r
- ASSERT(pHeader->mid == 0xff || \r
- pHeader->mid == 2 ||\r
- pHeader->mid == 7);\r
-\r
- rc1 = m_RecvBufferPool.RecievedBuffer(pBufferDescriptor, false);\r
- if (!NT_SUCCESS(rc1)) {\r
- // We have an error, but we should continue, or we will have a leak\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"m_RecvBufferPool.RecievedBuffer failed rc = 0x%x\n", rc1 );\r
- UpdateRc(&rc, rc1);\r
- continue;\r
- }\r
- }\r
- }\r
-\r
- } while( !p_free );\r
-\r
- // Rearm after filtering \r
-Cleanup:\r
- if (NT_SUCCESS(rc)) { \r
- ib_status = ib_rearm_cq(m_rcq, FALSE );\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_rearm_cq failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- // get out of this function\r
- }\r
- }\r
-\r
- return rc;\r
-\r
-}\r
-\r
-\r
-// TODO: Clear the callback functions mess\r
-void\r
-SdpSocket::__send_cb1(\r
- IN const ib_cq_handle_t h_cq,\r
- IN void *cq_context )\r
-{\r
- SdpSocket *pSocket = (SdpSocket *) cq_context;\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_SOCKET,"called this = 0x%p\n", pSocket ); \r
- pSocket->m_Lock.SignalCB(SEND_CB_CALLED);\r
-}\r
-\r
-\r
-// This function is here so it's addresses can be taken\r
-static NTSTATUS __send_cb2(SdpSocket * pSdpSocket)\r
-{\r
- return pSdpSocket->send_cb();\r
-}\r
-\r
-// This function is here so it's addresses can be taken\r
-static NTSTATUS __recv_cb2(SdpSocket * pSdpSocket)\r
-{\r
- return pSdpSocket->recv_cb();\r
-}\r
-\r
-static NTSTATUS __accept_requests(SdpSocket * pSdpSocket)\r
-{\r
- return pSdpSocket->AcceptRequests();\r
-}\r
-\r
-NTSTATUS SdpSocket::send_cb()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_SOCKET,"called this =0x%p\n", this);\r
- NTSTATUS rc = STATUS_SUCCESS, rc1 = STATUS_SUCCESS, rc2 = STATUS_SUCCESS;\r
- AssertLocked();\r
- ib_api_status_t ib_status;\r
- ib_wc_t *p_wc, *p_free;\r
- size_t i;\r
- BufferDescriptor *pBufferDescriptor = NULL;\r
-\r
- for( i = 0; i < SDP_QP_ATTRIB_SQ_DEPTH; i++ ) {\r
- m_SendComplitionWC[i].p_next = &m_SendComplitionWC[i + 1];\r
- }\r
- m_SendComplitionWC[SDP_QP_ATTRIB_SQ_DEPTH - 1].p_next = NULL;\r
-\r
- do \r
- {\r
- p_free = m_SendComplitionWC;\r
- ib_status = ib_poll_cq( m_scq, &p_free, &p_wc );\r
- ASSERT( ib_status == IB_SUCCESS || ib_status == IB_NOT_FOUND);\r
- if (ib_status == IB_NOT_FOUND) {\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET,"ib_poll_cq returned IB_NOT_FOUND, this =0x%p\n", this);\r
- break;\r
- }\r
- if (ib_status != IB_SUCCESS) { \r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_poll_cq failed ib_status=%d, this =0x%p\n", ib_status,this);\r
- ASSERT(ib_status == IB_INVALID_CQ_HANDLE || ib_status == IB_NOT_FOUND);\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
-\r
- while( p_wc )\r
- {\r
- ASSERT( p_wc->wc_type == IB_WC_SEND );\r
- pBufferDescriptor = (BufferDescriptor*)(uintn_t)p_wc->wr_id;\r
- m_SendBufferPool.m_NumberOfBytesSentAndAcked++;\r
-\r
- rc2 = m_SendBufferPool.ReturnBuffer(pBufferDescriptor);\r
- UpdateRc(&rc1, rc2); // We remember the error here and continue to avoid leaks\r
- switch( p_wc->status )\r
- {\r
- case IB_WCS_SUCCESS:\r
- // Nothing to do here\r
- break;\r
-\r
- case IB_WCS_WR_FLUSHED_ERR:\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "Flushed send completion. this =0x%p\n", this);\r
- // Intentainly fall down\r
- default:\r
- SDP_PRINT( TRACE_LEVEL_ERROR, SDP_SOCKET, "Send failed with %s\n",\r
- ib_get_wc_status_str( p_wc->status ));\r
- m_Lock.SignalError(IB2Status(ib_status));\r
- }\r
-\r
- p_wc = p_wc->p_next;\r
- }\r
- /* If we didn't use up every WC, break out. */\r
- } while( !p_free );\r
- if (!NT_SUCCESS(rc1)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "Error was detected on ReturnBuffer rc1 = 0x%x\n", rc1 );\r
- ASSERT(NT_SUCCESS(rc));\r
- rc = rc1;\r
- goto Cleanup;\r
- }\r
-\r
- /* Rearm the CQ. */\r
- ib_status = ib_rearm_cq(m_scq, FALSE );\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "ib_rearm_cq failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
-\r
- /* Resume any sends awaiting resources. */\r
- rc = m_SendBufferPool.SendBuffersIfCan();\r
- if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "m_SendBufferPool.Init SendBuffersIfCan rc = 0x%x\n", rc );\r
- goto Cleanup;\r
- }\r
-\r
-Cleanup:\r
- return rc;\r
-\r
-}\r
-\r
-\r
-// BUGBUG: This code is based on __cq_event, find out what it realy does\r
-static void\r
-__cq_event1(\r
- IN ib_async_event_rec_t *p_event_rec )\r
-{\r
- ASSERT(FALSE);\r
- UNUSED_PARAM( p_event_rec );\r
- ASSERT( p_event_rec->context );\r
- /* Place holder for proper error handler. */\r
- ASSERT( p_event_rec->code == IB_AE_UNKNOWN );\r
-}\r
-\r
-\r
-// Based on __qp_event - do we need it?\r
-static void\r
-__qp_event1(\r
- IN ib_async_event_rec_t *p_event_rec )\r
-{\r
- UNUSED_PARAM( p_event_rec );\r
- ASSERT( p_event_rec->context );\r
- /* Place holder for proper error handler. */\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"Async QP event: %d\n", p_event_rec->code);\r
- ASSERT( p_event_rec->code == IB_AE_UNKNOWN );\r
-}\r
-\r
-\r
-// This currently works only for the connect\r
-NTSTATUS SdpSocket::CreateQp()\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- ib_cq_create_t cq_create;\r
- ib_qp_create_t qp_create;\r
- ib_api_status_t ib_status;\r
- ib_phys_create_t phys_create;\r
- ib_phys_range_t phys_range;\r
- uint64_t vaddr;\r
- net32_t rkey;\r
-\r
-\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = 0x%p\n", this);\r
- ASSERT(m_SrcCaGuid != 0);\r
- /* Open the CA. */\r
- ib_status = ib_open_ca(\r
- g_pSdpDriver->m_al_handle, \r
- m_SrcCaGuid,\r
- NULL, \r
- this, \r
- &mh_Ca \r
- );\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_open_ca failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
-\r
- /* Allocate the PD. */\r
- ib_status = ib_alloc_pd(\r
- mh_Ca, \r
- IB_PDT_NORMAL, \r
- this, \r
- &m_pd \r
- );\r
- \r
- if( ib_status != IB_SUCCESS )\r
- {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_alloc_pd failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
-\r
- /* Allocate receive CQ. */\r
- cq_create.size = QP_ATTRIB_RQ_DEPTH;\r
- cq_create.pfn_comp_cb = __recv_cb1;\r
- cq_create.h_wait_obj = NULL;\r
-\r
- ib_status = ib_create_cq(\r
- mh_Ca, \r
- &cq_create, \r
- this,\r
- __cq_event1, \r
- &m_rcq \r
- );\r
-\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_create_cq failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
-\r
- /* Allocate send CQ. */\r
- cq_create.size = SDP_QP_ATTRIB_SQ_DEPTH;\r
- cq_create.pfn_comp_cb = SdpSocket::__send_cb1;\r
-\r
- ib_status = ib_create_cq(\r
- mh_Ca, \r
- &cq_create, \r
- this,\r
- __cq_event1, \r
- &m_scq \r
- );\r
-\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_create_cq failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
-\r
- /* Allocate the QP. */\r
- cl_memclr( &qp_create, sizeof(qp_create) );\r
- qp_create.qp_type = IB_QPT_RELIABLE_CONN;\r
- qp_create.rq_depth = QP_ATTRIB_RQ_DEPTH;\r
- qp_create.rq_sge = QP_ATTRIB_RQ_SGE; /* To support buffers spanning pages. */\r
- qp_create.h_rq_cq = m_rcq;\r
- qp_create.sq_depth = SDP_QP_ATTRIB_SQ_DEPTH;\r
- //TODO: Figure out the right number of SGE entries for sends.\r
- qp_create.sq_sge = QP_ATTRIB_SQ_SGE;\r
- qp_create.h_sq_cq = m_scq;\r
- qp_create.sq_signaled = TRUE;\r
- ib_status = ib_create_qp( m_pd, &qp_create, this, __qp_event1, &m_qp );\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_create_qp failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
-#if DBG\r
- /* Query the QP so we can get our QPN. */\r
- ib_qp_attr_t qp_attr;\r
- ib_status = ib_query_qp(\r
- m_qp, &qp_attr );\r
- if( ib_status != IB_SUCCESS )\r
- {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_query_qp failed ib_status = 0x%d\n", ib_status );\r
- // ignore the error, this is only needed for debug\r
- }\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"QP number is %x\n", CL_NTOH32(qp_attr.num));\r
-#endif \r
-\r
- const net64_t MEM_REG_SIZE = 0xFFFFFFFFFFFFFFFF;\r
- /* Register all of physical memory */\r
- phys_create.length = MEM_REG_SIZE;\r
- phys_create.num_ranges = 1;\r
- phys_create.range_array = &phys_range;\r
- phys_create.buf_offset = 0;\r
- phys_create.hca_page_size = PAGE_SIZE;\r
- phys_create.access_ctrl = IB_AC_LOCAL_WRITE;\r
- phys_range.base_addr = 0;\r
- phys_range.size = MEM_REG_SIZE;\r
- vaddr = 0;\r
- ib_status = ib_reg_phys(\r
- m_pd, \r
- &phys_create, \r
- &vaddr,\r
- &m_lkey,\r
- &rkey, \r
- &m_mr );\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_reg_phys failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- goto Cleanup;\r
- }\r
- \r
-Cleanup:\r
- // In the case of failure the mess will be cleaned on\r
- // shutdown \r
- // TODO: Need to make a beter cleanup here\r
- return rc;\r
-\r
-}\r
-\r
-VOID SdpSocket::CreateHelloHeader(\r
- sdp_msg_hello *hello_msg, \r
- ULONG DestIp\r
- \r
- )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = 0x%p\n", this);\r
- ASSERT(DestIp != 0);\r
- ASSERT(m_SrcPort != 0);\r
- ASSERT(m_SrcIp != 0);\r
-\r
- memset(hello_msg, 0, sizeof(struct sdp_msg_hello));\r
- hello_msg->bsdh.recv_bufs = QP_ATTRIB_RQ_DEPTH; //????conn->l_advt_bf;\r
- hello_msg->bsdh.flags = SDP_MSG_FLAG_NON_FLAG;\r
- hello_msg->bsdh.mid = SDP_MID_HELLO;\r
- hello_msg->bsdh.size = sizeof(struct sdp_msg_hello);\r
- hello_msg->bsdh.seq_num = m_SendBufferPool.GetAndIncreaseSendSeq();//conn->send_seq; ???\r
- hello_msg->bsdh.seq_ack = m_RecvBufferPool.GetRecvSeq();//conn->advt_seq; ???\r
-\r
- hello_msg->hh.max_adv = QP_ATTRIB_RQ_DEPTH;// ??? conn->l_max_adv;\r
- hello_msg->hh.ip_ver = SDP_MSG_IPVER;\r
- hello_msg->hh.version = SDP_MSG_VERSION;\r
- hello_msg->hh.r_rcv_size = MAX_RECV_BUFFER_SIZE;//???conn->recv_size;\r
- hello_msg->hh.l_rcv_size = MAX_RECV_BUFFER_SIZE;//???conn->recv_size;\r
- hello_msg->hh.port = m_SrcPort;\r
- hello_msg->hh.src.ipv4.addr = m_SrcIp;\r
- hello_msg->hh.dst.ipv4.addr = DestIp;\r
-\r
- /*\r
- * endian swap\r
- */\r
- sdp_msg_swap_bsdh(&hello_msg->bsdh);\r
- sdp_msg_swap_hh(&hello_msg->hh);\r
-\r
-}\r
-\r
-VOID SdpSocket::CreateHelloAckHeader(\r
- sdp_msg_hello_ack* hello_ack_msg\r
- )\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"called this = 0x%p\n", this);\r
-\r
- memset(hello_ack_msg, 0, sizeof(struct sdp_msg_hello_ack));\r
- hello_ack_msg->bsdh.recv_bufs = QP_ATTRIB_RQ_DEPTH; //????conn->l_advt_bf;\r
- hello_ack_msg->bsdh.flags = SDP_MSG_FLAG_NON_FLAG;\r
- hello_ack_msg->bsdh.mid = SDP_MID_HELLO_ACK;\r
- hello_ack_msg->bsdh.size = sizeof(struct sdp_msg_hello_ack);\r
- hello_ack_msg->bsdh.seq_num = m_SendBufferPool.GetAndIncreaseSendSeq();//conn->send_seq; ???\r
- hello_ack_msg->bsdh.seq_ack = m_RecvBufferPool.GetRecvSeq();//conn->advt_seq; ???\r
-\r
- hello_ack_msg->hah.max_adv = QP_ATTRIB_RQ_DEPTH;// ??? conn->l_max_adv;\r
- hello_ack_msg->hah.version = SDP_MSG_VERSION;\r
- hello_ack_msg->hah.l_rcv_size = MAX_RECV_BUFFER_SIZE;//???conn->recv_size;\r
-\r
- /*\r
- * endian swap\r
- */\r
- sdp_msg_swap_bsdh(&hello_ack_msg->bsdh);\r
- sdp_msg_swap_hah(&hello_ack_msg->hah);\r
-\r
-\r
-}\r
-\r
-\r
-VOID SdpSocket::CreateCmRequest(\r
- ib_cm_req_t *cm_req,\r
- sdp_msg_hello *hello_msg,\r
- ib_path_rec_t *path_rec,\r
- USHORT DestPort\r
- )\r
-{\r
-\r
- memset( cm_req, 0, sizeof(ib_cm_req_t) );\r
- cm_req->qp_type = IB_QPT_RELIABLE_CONN;\r
- cm_req->h_qp = m_qp;\r
- cm_req->p_primary_path = path_rec;\r
- cm_req->p_alt_path = NULL;\r
- cm_req->svc_id = get_service_id_for_port(DestPort );\r
- cm_req->p_req_pdata = (uint8_t *) hello_msg;\r
- cm_req->req_length = sizeof(sdp_msg_hello);\r
-\r
- // Caution: From here we live the linux code, as it was in: gen2 - sdp_cm_path_complete\r
- cm_req->max_cm_retries = CM_RETRIES;\r
- cm_req->resp_res = 4;//???????? what are this??? QP_ATTRIB_RESPONDER_RESOURCES;\r
- cm_req->init_depth = 4;//?????QP_ATTRIB_INITIATOR_DEPTH;\r
-\r
- cm_req->remote_resp_timeout =\r
- ib_path_rec_pkt_life( path_rec ) + CM_REMOTE_TIMEOUT;\r
- if( cm_req->remote_resp_timeout > 0x1F )\r
- cm_req->remote_resp_timeout = 0x1F;\r
- else if( cm_req->remote_resp_timeout < CM_MIN_REMOTE_TIMEOUT )\r
- cm_req->remote_resp_timeout = CM_MIN_REMOTE_TIMEOUT;\r
-\r
- cm_req->flow_ctrl = TRUE; /* HCAs must support end-to-end flow control. */\r
-\r
- cm_req->local_resp_timeout =\r
- ib_path_rec_pkt_life( path_rec ) + CM_LOCAL_TIMEOUT;\r
- if( cm_req->local_resp_timeout > 0x1F )\r
- cm_req->local_resp_timeout = 0x1F;\r
- else if( cm_req->local_resp_timeout < CM_MIN_LOCAL_TIMEOUT )\r
- cm_req->local_resp_timeout = CM_MIN_LOCAL_TIMEOUT;\r
-\r
- cm_req->rnr_nak_timeout = 6;//???QP_ATTRIB_RNR_NAK_TIMEOUT;\r
- cm_req->rnr_retry_cnt = 6;//????QP_ATTRIB_RNR_RETRY;\r
- cm_req->retry_cnt = 6;//????QP_ATTRIB_RETRY_COUNT;\r
-\r
- cm_req->pfn_cm_req_cb = NULL;\r
- cm_req->pfn_cm_mra_cb = cm_mra_callback;\r
- cm_req->pfn_cm_rej_cb = cm_rej_callback;\r
- cm_req->pfn_cm_rep_cb = cm_rep_callback;\r
-}\r
-\r
-\r
-VOID SdpSocket::UsersThreadCallBack(bool Send)\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
-\r
- if (!m_Lock.Lock()) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "Failed to lock this = 0x%p \n",this);\r
- // Error is ignored, as it is a callback path, socket is already at an error state\r
- goto Cleanup;\r
- }\r
- if (Send) {\r
- InitializeListHead(&m_CallBackRequestList);\r
- rc = m_SendBufferPool.UsersThreadCallBack();\r
- if (!NT_SUCCESS(rc)) { \r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "m_SendBufferPool.UsersThreadCallBack failed this = 0x%p, rc = 0x%x \n",\r
- this, rc);\r
- m_Lock.Unlock(); // Error is ignored, as this is already an error path\r
- Shutdown();\r
- goto Cleanup;\r
- }\r
- \r
- }\r
-\r
- rc = m_Lock.Unlock(); // Error is ignored, as it is a callback path \r
- if (!NT_SUCCESS(rc)) { \r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "m_Lock.Unlock failed this = 0x%p, rc = 0x%x \n",\r
- this, rc);\r
- Shutdown();\r
- goto Cleanup;\r
- }\r
-\r
-Cleanup:\r
- return;\r
-}\r
-\r
-// static\r
-VOID SdpSocket::ShutdownCB(VOID* pContext)\r
-{\r
- SdpSocket *pSocket = (SdpSocket *) pContext;\r
- KeSetEvent(&pSocket->m_ShutdownCompleteEvent, IO_NO_INCREMENT, FALSE);;\r
-\r
-}\r
-\r
-// This is just a wrapper for some operations that have to be done for the code bellow\r
-// It will probably be converted to a macro\r
-VOID WaitForShutdownEvent(KEVENT *ShutdownCompleteEvent)\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
-\r
- LARGE_INTEGER WaitTime;\r
- // Why are we waiting with timeout? obviously we should wait forever\r
- // and if this is the case, there is a bug *SOMEWHERE ELSE*\r
- // Still I wait WAIT_TO_SOCKET_SHUTDOWN seconds and believe that the user \r
- // will like me more If I do quit and let the application close\r
- \r
- WaitTime = TimeFromLong(WAIT_TO_SOCKET_SHUTDOWN * 10 * 1000000);\r
-\r
- rc = MyKeWaitForSingleObject(\r
- ShutdownCompleteEvent,\r
- Executive,\r
- KernelMode,\r
- FALSE,\r
- &WaitTime\r
- );\r
-\r
- if (rc == STATUS_TIMEOUT) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"Wait failed with time out\n");\r
- ASSERT(FALSE);\r
- }\r
-\r
- ASSERT(NT_SUCCESS(rc));\r
- ASSERT(rc == STATUS_SUCCESS || rc == STATUS_TIMEOUT);// || rc == STATUS_USER_APC); //???????? what to do \r
- //???????? the wait fails\r
- KeClearEvent(ShutdownCompleteEvent);\r
-}\r
-\r
-/* \r
- This function is called when the usercallback thread has detected\r
- that the user thread is dead, or when we have a IRP_MJ_CLEANUP.\r
- In this case, if CloseSocket was called, we don't do anything\r
- (since there is alreadya thread that is garantied to close it) and on \r
- all other cases, we close it abortively.\r
-*/\r
-\r
-VOID SdpSocket::DyingProcessDetected()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET, "called this = 0x%p\n", this);\r
- m_Lock.Lock(true); //????? verify must succeed\r
- if (m_CloseSocketCalled) {\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET, "this = 0x%p m_CloseSocketCalled, letting it finish his job\n", this);\r
- m_Lock.Unlock(); // Error is ignored since this is already\r
- // shutdown call\r
- return;\r
- }\r
- m_Lock.Unlock(); // Error is ignored since this is already\r
- // shutdown call\r
- Shutdown();\r
-}\r
-\r
-VOID SdpSocket::Shutdown()\r
-{\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET, "called this = 0x%p\n", this);\r
- \r
- NTSTATUS rc = STATUS_SUCCESS;\r
- ib_api_status_t ib_status;\r
- ib_qp_mod_t qp_mod;\r
-\r
- if (m_ShutdownCalled) {\r
- // Since this variable is always changing from false to true\r
- // we can check it without the lock. Since there is no memory\r
- // barier, this test is not true for multiple enviorments, but it\r
- // still makes the shutodwn reentrent\r
- return;\r
- }\r
- // now take the lock and test again\r
-\r
- m_Lock.Lock(true); //????? verify must succeed\r
- if (m_ShutdownCalled) {\r
- // Already handled\r
- m_Lock.Unlock(); // Error is ignored since this is already\r
- // shutdown call\r
- return;\r
- }\r
- m_ShutdownCalled = true;\r
- m_Lock.Unlock(); \r
-\r
- //\r
- // Here we start a list of operations that once comlpeated,\r
- // should force that no complition exists anymore\r
- // Although we are not holding the lock, they will not be able to\r
- // lock it. This means that they will try to take it and fail\r
- \r
- if (m_ListenHandle != NULL) {\r
- ib_status = ib_cm_cancel( m_ListenHandle, ShutdownCB );\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_cm_cancel failed ib_status = 0x%d\n", ib_status );\r
- rc = IB2Status(ib_status);\r
- } else {\r
- WaitForShutdownEvent(&m_ShutdownCompleteEvent);\r
- m_ListenHandle = NULL;\r
- }\r
- }\r
-\r
- m_ConnectionList.Shutdown();\r
-\r
- \r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"111111%p\n", this);\r
-\r
- if (m_qp != NULL) {\r
-\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"222222%p\n", this);\r
-\r
- cl_memclr( &qp_mod, sizeof(ib_qp_mod_t) );\r
- qp_mod.req_state = IB_QPS_ERROR;\r
- ib_status = ib_modify_qp( m_qp, &qp_mod );\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_modify_qp failed ib_status = 0x%d\n", ib_status );\r
- ASSERT(FALSE);\r
- // We are probably going to leak, but we have to continue\r
- }\r
- \r
- ib_status = ib_destroy_qp(m_qp, ShutdownCB);\r
- //m_qp = NULL;\r
- if(ib_status == IB_SUCCESS) {\r
- WaitForShutdownEvent(&m_ShutdownCompleteEvent);\r
- } else {\r
- ASSERT(ib_status == IB_SUCCESS);\r
- // If this is not the case, then we could have probably being\r
- // closing a different socket, which is very bad.\r
- // To give things a chance to work without shutdown, I'll continue\r
- }\r
- }\r
-\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"333333%p\n", this);\r
- \r
- if (m_scq != NULL) {\r
- ib_status = ib_destroy_cq(m_scq, ShutdownCB);\r
- //???ASSERT(ib_status == IB_SUCCESS);\r
- if(ib_status == IB_SUCCESS) {\r
- WaitForShutdownEvent(&m_ShutdownCompleteEvent);\r
- }\r
- //?????m_scq = NULL;\r
- }\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"444444%p\n", this); \r
-\r
- if (m_rcq != NULL) {\r
- ib_status = ib_destroy_cq(m_rcq, ShutdownCB); \r
- //???ASSERT(ib_status == IB_SUCCESS);\r
- if(ib_status == IB_SUCCESS) {\r
- WaitForShutdownEvent(&m_ShutdownCompleteEvent);\r
- }\r
- //??????m_rcq = NULL;\r
-\r
- }\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"555555%p\n", this); \r
- if (m_pd != NULL) {\r
- ib_status = ib_dealloc_pd(m_pd, ShutdownCB); \r
- //???ASSERT(ib_status == IB_SUCCESS);\r
- if(ib_status == IB_SUCCESS) { \r
- WaitForShutdownEvent(&m_ShutdownCompleteEvent);\r
- }\r
- //?????m_pd = NULL;\r
- \r
- }\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"666666%p\n", this); \r
-\r