+++ /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
- if (mh_Ca != NULL) {\r
- ib_status = ib_close_ca(mh_Ca, ShutdownCB); \r
- //ASSERT(ib_status == IB_SUCCESS);\r
- if(ib_status == IB_SUCCESS) {\r
- WaitForShutdownEvent(&m_ShutdownCompleteEvent);\r
- }\r
- //?????mh_Ca = NULL;\r
-\r
- }\r
-\r
- // No compleations should exist any more\r
-\r
- if (m_pListeningSocket != NULL) {\r
- m_pListeningSocket->Release();\r
- m_pListeningSocket = NULL;\r
- }\r
-\r
- if (m_pCloseSocketThread != NULL) {\r
- delete m_pCloseSocketThread;\r
- m_pCloseSocketThread = NULL;\r
- }\r
-\r
- // Now that all ibal operations have finished we can free the memory\r
- m_SendBufferPool.ShutDown();\r
- m_RecvBufferPool.ShutDown();\r
-\r
- if (m_pSdpUserFile != NULL) {\r
- m_pSdpUserFile->RemoveSocket(this);\r
- m_pSdpUserFile->Release();\r
- m_pSdpUserFile = NULL;\r
- }\r
-\r
-/*\r
- Memory reagion probably cleans when the other handles are closed\r
- if (m_mr != NULL) {\r
- ib_status = ib_dereg_mr(m_mr);\r
- if( ib_status != IB_SUCCESS ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET,"ib_dereg_mr failed ib_status = 0x%d\n", ib_status );\r
- ASSERT( ib_status == IB_SUCCESS );\r
- }\r
- m_mr = NULL;\r
- }\r
-*/\r
- \r
-}\r
-\r
-/*\r
- * sdp_cm_hello_ack_check - validate the hello ack header\r
- */\r
-NTSTATUS sdp_cm_hello_ack_check(struct sdp_msg_hello_ack *hello_ack)\r
-{\r
- /*\r
- * endian swap\r
- */\r
- sdp_msg_swap_bsdh(&hello_ack->bsdh);\r
- sdp_msg_swap_hah(&hello_ack->hah);\r
- /*\r
- * validation and consistency checks\r
- */\r
- if (hello_ack->bsdh.size != sizeof(struct sdp_msg_hello_ack)) {\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET, "hello ack, size mismatch. (2) <%d:%d>",\r
- hello_ack->bsdh.size,\r
- sizeof(struct sdp_msg_hello_ack));\r
- return STATUS_UNEXPECTED_IO_ERROR;\r
- }\r
-\r
- if (SDP_MID_HELLO_ACK != hello_ack->bsdh.mid) {\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET, "hello ack, unexpected message. <%d>",\r
- hello_ack->bsdh.mid);\r
- return STATUS_UNEXPECTED_IO_ERROR; \r
- }\r
-\r
- if (hello_ack->hah.max_adv <= 0) {\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET, "hello ack, bad zcopy advertisment. <%d>",\r
- hello_ack->hah.max_adv);\r
- return STATUS_UNEXPECTED_IO_ERROR; \r
- }\r
-\r
- if ((0xF0 & hello_ack->hah.version) != (0xF0 & SDP_MSG_VERSION)) {\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET, "hello ack, version mismatch. <%d:%d>",\r
- ((0xF0 & hello_ack->hah.version) >> 4),\r
- ((0xF0 & SDP_MSG_VERSION) >> 4));\r
- return STATUS_UNEXPECTED_IO_ERROR; \r
- }\r
-\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET, "Hello Ack BSDH <%04x:%02x:%02x:%08x:%08x:%08x>",\r
- hello_ack->bsdh.recv_bufs,\r
- hello_ack->bsdh.flags,\r
- hello_ack->bsdh.mid,\r
- hello_ack->bsdh.size,\r
- hello_ack->bsdh.seq_num,\r
- hello_ack->bsdh.seq_ack);\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET, "Hello Ack HAH <%02x:%02x:%08x",\r
- hello_ack->hah.max_adv,\r
- hello_ack->hah.version, \r
- hello_ack->hah.l_rcv_size);\r
-\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-NTSTATUS sdp_cm_hello_check(struct sdp_msg_hello *msg_hello)\r
-{\r
- /*\r
- * endian swap\r
- */\r
- sdp_msg_swap_bsdh(&msg_hello->bsdh);\r
- sdp_msg_swap_hh(&msg_hello->hh);\r
- /*\r
- * validation and consistency checks\r
- */\r
- \r
- if (msg_hello->bsdh.size != sizeof(struct sdp_msg_hello)) {\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET, "hello msg size mismatch. (2) <%d:%d>",\r
- msg_hello->bsdh.size,\r
- sizeof(struct sdp_msg_hello));\r
- return STATUS_UNEXPECTED_IO_ERROR;\r
- }\r
-\r
- if (SDP_MID_HELLO != msg_hello->bsdh.mid) {\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET, "hello msg unexpected ID. <%d>",\r
- msg_hello->bsdh.mid);\r
- return STATUS_UNEXPECTED_IO_ERROR;\r
- }\r
-\r
- if (msg_hello->hh.max_adv <= 0) {\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET, "hello msg, bad zcopy count <%d>",\r
- msg_hello->hh.max_adv);\r
- return STATUS_UNEXPECTED_IO_ERROR;\r
- }\r
-\r
- if ((0xF0 & msg_hello->hh.version) != (0xF0 & SDP_MSG_VERSION)) {\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET, "hello msg, version mismatch. <%d:%d>",\r
- ((0xF0 & msg_hello->hh.version) >> 4),\r
- ((0xF0 & SDP_MSG_VERSION) >> 4));\r
- return STATUS_UNEXPECTED_IO_ERROR;\r
- }\r
-#ifdef _SDP_MS_APRIL_ERROR_COMPAT\r
- if ((SDP_MSG_IPVER & 0x0F) != (msg_hello->hh.ip_ver & 0x0F)) \r
-#else\r
- if ((SDP_MSG_IPVER & 0xF0) != (msg_hello->hh.ip_ver & 0xF0)) {\r
-#endif\r
- SDP_PRINT(TRACE_LEVEL_WARNING, SDP_SOCKET, "hello msg, ip version mismatch. <%d:%d>",\r
- msg_hello->hh.ip_ver, SDP_MSG_IPVER);\r
- return STATUS_UNEXPECTED_IO_ERROR;\r
- }\r
-\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET, "Hello BSDH <%04x:%02x:%02x:%08x:%08x:%08x>",\r
- msg_hello->bsdh.recv_bufs,\r
- msg_hello->bsdh.flags,\r
- msg_hello->bsdh.mid,\r
- msg_hello->bsdh.size,\r
- msg_hello->bsdh.seq_num,\r
- msg_hello->bsdh.seq_ack);\r
- SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET, "Hello HH <%02x:%02x:%02x:%08x:%08x:%04x:%08x:%08x>",\r
- msg_hello->hh.max_adv,\r
- msg_hello->hh.ip_ver,\r
- msg_hello->hh.version,\r
- msg_hello->hh.r_rcv_size,\r
- msg_hello->hh.l_rcv_size,\r
- msg_hello->hh.port,\r
- msg_hello->hh.src.ipv4.addr,\r
- msg_hello->hh.dst.ipv4.addr);\r
-\r
- return STATUS_SUCCESS;\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
-This class is being used to truck all the user objects that are being\r
-created per user mode dll (each dll opens a handle to the driver once)\r
-\r
-It keeps a list of all the objects so we know when to remove them.\r
-\r
-*/\r
-\r
-#ifndef _SDP_SOCKET_H\r
-#define _SDP_SOCKET_H\r
-\r
-\r
-const int MAX_SEND_BUFFER_SIZE = 1*4096; // This is the maximum send packet size\r
-\r
-const int MAX_RECV_BUFFER_SIZE = 1*4096; // This is the maximum send packet size\r
-const int MAX_SEND_PACKETS = 200; // This is the maximum number of packets allocated per send\r
-const int MAX_RECV_PACKETS = 200; // This is the maximum number of packets allocated per send\r
- \r
-\r
-const short SDP_QP_ATTRIB_SQ_DEPTH = 64;\r
-const short QP_ATTRIB_SQ_SGE = 1; /* Set based on inline data requirements */\r
-//#define QP_ATTRIB_RESPONDER_RESOURCES 4\r
-const short QP_ATTRIB_INITIATOR_DEPTH = 4;\r
-//#define QP_ATTRIB_RETRY_COUNT 6\r
-//#define QP_ATTRIB_RNR_RETRY 6\r
-const short QP_ATTRIB_RNR_NAK_TIMEOUT = 6;\r
-\r
-const short WAIT_TO_SOCKET_SHUTDOWN = 40; // The time to wait for a socket to complete\r
- // it's shutdown before we become brutal\r
-/* \r
- * TODO: During testing, the switch has been observed to post\r
- * 12 receive buffers. It would be nice to know what the max is.\r
- */\r
-const short QP_ATTRIB_RQ_DEPTH = 64;//64\r
-#define QP_ATTRIB_RQ_SGE 1\r
-const int SDP_RECV_CREDIT_UPDATE = 20; // send credit update to the remote \r
- // side.\r
-\r
-/* Number of entries in a CQ */\r
-#define IB_CQ_SIZE (QP_ATTRIB_SQ_DEPTH + QP_ATTRIB_RQ_DEPTH + 1)\r
-\r
-enum SocketStates {\r
- SS_IDLE,\r
- SS_CONNECTING_QPR_SENT, // QPR = Query path record\r
- SS_CONNECTING_REQ_SENT,\r
- SS_CONNECTING_RTU_SENT,\r
- SS_CONNECTED,\r
- SS_BOUND,\r
- SS_LISTENING,\r
- SS_REQ_RECV, //???? not really used ????\r
- SS_REP_SENT,\r
- SS_CONNECTED_DREP_SENT //??? not really used \r
-};\r
- // Plesae note that shutdwon and close socket is being done \r
- // through flags\r
-\r
-void cm_rtu_callback(IN ib_cm_rtu_rec_t *p_cm_rtu_rec );\r
-\r
-\r
-class SdpSocket : public RefCountImpl {\r
-\r
- friend void cm_rtu_callback(IN ib_cm_rtu_rec_t *p_cm_rtu_rec );\r
- friend class ConnectionList;\r
-\r
-private: \r
- \r
- SocketStates m_state;\r
- \r
- // This flags are being Initiated when the socket is being\r
- // created\r
- ULONG m_CreationFlags;\r
-\r
- USHORT m_SrcPort;\r
- ULONG m_SrcIp;\r
-\r
- USHORT m_DstPort;\r
- ULONG m_DstIp;\r
-\r
- SdpLock m_Lock;\r
-\r
-\r
- // A handle to the ca that is being used (in connect) and its guid\r
- ib_ca_handle_t mh_Ca;\r
- net64_t m_SrcCaGuid; // The guid of the CA that is used\r
- ib_net64_t m_SrcPortGuid; // The guid of the port that is used\r
- ib_pd_handle_t m_pd;\r
- ib_cq_handle_t m_rcq;\r
-\r
- ib_cq_handle_t m_scq;\r
- \r
- ib_qp_handle_t m_qp;\r
-\r
- ib_mr_handle_t m_mr;\r
-\r
- net32_t m_lkey;\r
-\r
- // This handle is used if this is a socket that is listening for new connections\r
- ib_listen_handle_t m_ListenHandle;\r
-\r
- // If this socket was created fron a listening socket, this is a\r
- // pointer to the "mother socket"\r
- SdpSocket* m_pListeningSocket;\r
-\r
- // If this socket is in a listners list of socket, this is the place that is\r
- // used for puting it in the list\r
- LIST_ENTRY m_ListeningSocketList;\r
-\r
-\r
- KEVENT m_ConnectCmCompleteEvent;\r
- KEVENT m_ShutdownCompleteEvent;\r
- KEVENT m_DisconectSentEvent;\r
-\r
- ib_wc_t m_SendComplitionWC[SDP_QP_ATTRIB_SQ_DEPTH];\r
- ib_wc_t m_RecvComplitionWC[QP_ATTRIB_RQ_DEPTH];\r
-\r
- // The following three falgs are used to shutdown a socket\r
- bool m_CloseSocketCalled;\r
- bool m_ShutdownCalled;\r
- bool m_DisconnectConnectionRecieved;\r
-\r
- ThreadHandle* m_pCloseSocketThread;\r
-\r
- SdpUserFile *m_pSdpUserFile;\r
-\r
- static VOID __send_cb1(\r
- IN const ib_cq_handle_t h_cq,\r
- IN void *cq_context );\r
-\r
- static VOID __recv_cb1(\r
- IN const ib_cq_handle_t h_cq,\r
- IN void *cq_context );\r
-\r
-public:\r
-\r
- BufferPool m_SendBufferPool;\r
- RecvPool m_RecvBufferPool;\r
- ConnectionList m_ConnectionList;\r
-\r
- LIST_ENTRY m_CallBackRequestList;// Used by the call back request thread to hold the request\r
-\r
- \r
- SdpSocket();\r
-\r
- ~SdpSocket() {\r
- //SDP_PRINT(TRACE_LEVEL_INFORMATION, SDP_SOCKET,"this = 0x%p\n", this);\r
- }\r
-\r
- NTSTATUS Init(\r
- WspSocketIn *pSocketInParam, \r
- WspSocketOut *pSocketOutParam,\r
- SdpUserFile *pSdpUserFile\r
- );\r
-\r
- NTSTATUS WSPConnect(\r
- WspConnectIn *pWspConnectIn,\r
- WspConnectOut *pWspConnectOut\r
- );\r
-\r
- NTSTATUS WSPSend(\r
- WspSendIn *pWspSendIn,\r
- WspSendOut *pWspSendOut,\r
- IRP *pIrp \r
- ); \r
-\r
- NTSTATUS WSPRecv(\r
- WspRecvIn *pWspRecvIn,\r
- WspRecvOut *pWspRecvOut\r
- ); \r
-\r
- NTSTATUS WSPBind(\r
- WspBindIn *pWspBindIn,\r
- WspBindOut *pWspBindOut\r
- ); \r
-\r
- NTSTATUS WSPListen(\r
- WspListenIn *pWspListenIn,\r
- WspListenOut *pWspListenOut\r
- );\r
-\r
- NTSTATUS WSPAccept(\r
- WspAcceptIn *pWspAcceptIn,\r
- WspAcceptOut *pWspAcceptOut\r
- );\r
-\r
- NTSTATUS WSPGetXXXName(\r
- WspGetSockXXIn *pWspGetSockXXIn,\r
- WspGetSockXXOut *pWspGetSockXXOut\r
- );\r
- \r
- NTSTATUS WSPCloseSocket(\r
- WspSocketCloseIn *pWspSocketCloseIn,\r
- WspSocketCloseOut *pWspSocketCloseOut\r
- ); \r
-\r
- VOID DyingProcessDetected();\r
-\r
- VOID Shutdown();\r
-\r
- static VOID ShutdownCB(VOID* pContext);\r
-\r
- NTSTATUS AcceptRequests();\r
-\r
- NTSTATUS CreateQp();\r
-\r
- NTSTATUS CmSendRTU();\r
- \r
- VOID CreateHelloHeader(\r
- sdp_msg_hello *hello_msg, \r
- ULONG DestIp\r
- );\r
-\r
- VOID CreateHelloAckHeader(\r
- sdp_msg_hello_ack* hello_ack_msg\r
- );\r
-\r
- VOID 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
- NTSTATUS RequestCallBack() {\r
- AssertLocked();\r
- ASSERT(IsListEmpty(&m_CallBackRequestList));\r
- return m_pSdpUserFile->RequestCallBack(&m_CallBackRequestList);\r
- }\r
-\r
- VOID UsersThreadCallBack(bool Send);\r
-\r
- VOID CmRepCallback(IN ib_cm_rep_rec_t *p_cm_rep_rec);\r
- VOID CmReqCallback(IN ib_cm_req_rec_t *p_cm_req_rec);\r
- VOID CmRtuCallback(IN ib_cm_rtu_rec_t *p_cm_rtu_rec);\r
- VOID CmDreqCallback(IN ib_cm_dreq_rec_t *p_cm_dreq_rec);\r
-\r
- VOID CloseSocketThread();\r
-\r
- VOID DisconectSentEvent();\r
-\r
- SocketStates GetState() {return m_state;};\r
-\r
- // Two varibales that are needed for passing REP data\r
- struct sdp_msg_hello_ack m_hello_ack;\r
- ib_cm_handle_t m_cm_handle_t; // BUGBUG: Check how this is used / locked\r
-\r
- NTSTATUS send_cb();\r
- NTSTATUS recv_cb();\r
-\r
- // Used to allow the user file to remember us\r
- LIST_ENTRY m_UserFileList;\r
-\r
-\r
-\r
- static char * SS2String(SocketStates state) {\r
- switch (state) {\r
- case SS_IDLE : return "SS_IDLE";\r
- case SS_CONNECTING_QPR_SENT : return "SS_CONNECTING_QPR_SENT"; \r
- case SS_CONNECTING_REQ_SENT : return "SS_CONNECTING_REQ_SENT";\r
- case SS_CONNECTING_RTU_SENT : return "SS_CONNECTING_RTU_SENT";\r
- case SS_CONNECTED : return "SS_CONNECTED";\r
- case SS_BOUND : return "SS_BOUND";\r
- case SS_LISTENING : return "SS_LISTENING";\r
- case SS_REQ_RECV : return "SS_REQ_RECV";\r
- case SS_REP_SENT : return "SS_REP_SENT";\r
- case SS_CONNECTED_DREP_SENT : return "SS_CONNECTED_DREP_SENT";\r
- default : \r
- ASSERT(FALSE);\r
-\r
- }\r
- return "Unknown state";\r
- }\r
-\r
-\r
-\r
- VOID AssertLocked(); \r
-};\r
-\r
-#endif // _SDP_SOCKET_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
-#include <stdio.h> \r
-#include <stdarg.h>\r
-#include <ntstrsafe.h>\r
-\r
-#if !defined(EVENT_TRACING)\r
-\r
-const int g_SdpDbgLevel = SDP_WARN;\r
-//const int g_SdpDbgLevel = SDP_TRACE;\r
-//const int g_SdpDbgLevel = SDP_DEBUG;\r
-\r
-\r
-#if DBG \r
-//int g_SdpDbgLevel = TRACE_LEVEL_WARNING;\r
-uint32_t g_SdpDbgLevel = TRACE_LEVEL_INFORMATION;\r
-//int g_SdpDbgLevel = TRACE_LEVEL_VERBOSE;\r
-uint32_t g_SdpDbgFlags= SDP_API;\r
-#endif\r
-\r
-VOID\r
-SDP_PRINT (\r
- IN ULONG lvl,\r
- IN ULONG flags,\r
- IN PCCHAR msg,\r
- ...\r
- )\r
-\r
-/*++\r
-\r
-Routine Description:\r
-\r
- Debug print for the sample driver.\r
-\r
-Arguments:\r
-\r
- DebugPrintLevel - print level between 0 and 3, with 3 the most verbose\r
-\r
-Return Value:\r
-\r
- None.\r
-\r
- --*/\r
- {\r
-#if DBG\r
-#define TEMP_BUFFER_SIZE 1024\r
- va_list list;\r
- UCHAR debugMessageBuffer[TEMP_BUFFER_SIZE];\r
- NTSTATUS status;\r
- \r
- va_start(list, msg);\r
- \r
- if (msg) {\r
-\r
- //\r
- // Using new safe string functions instead of _vsnprintf. This function takes\r
- // care of NULL terminating if the message is longer than the buffer.\r
- //\r
- status = RtlStringCbVPrintfA(msg, sizeof(msg), \r
- msg, list);\r
- if(!NT_SUCCESS(status)) {\r
- \r
- KdPrint ((": RtlStringCbVPrintfA failed %x\n", status));\r
- return;\r
- }\r
- if ((lvl <= g_SdpDbgLevel && \r
- ((flags & g_SdpDbgFlags) == flags))) {\r
- KdPrint(("%s:",__FUNCTION__));\r
- if(lvl == TRACE_LEVEL_ERROR) KdPrint (("ERROR - "));\r
- KdPrint ((":%s", msg));\r
- } \r
- }\r
- va_end(list);\r
-\r
- return;\r
-#endif\r
-}\r
-\r
-#endif \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_TRACE_H\r
-#define H_SDP_TRACE_H \r
-extern "C" {\r
-#include <ntddk.h>\r
-#include <evntrace.h>\r
-}\r
-#if defined(EVENT_TRACING)\r
-\r
-//\r
-// Software Tracing Definitions \r
-//\r
-#define WPP_CONTROL_GUIDS \\r
- WPP_DEFINE_CONTROL_GUID(SdpCtlGuid,(2D4C03CC, E071, 48e2, BDBD, 526A0D69D6C9), \\r
- WPP_DEFINE_BIT( SDP_API) \\r
- WPP_DEFINE_BIT( SDP_CONNECT) \\r
- WPP_DEFINE_BIT( SDP_DRIVER) \\r
- WPP_DEFINE_BIT( SDP_SOCKET) \\r
- WPP_DEFINE_BIT( SDP_ARP) \\r
- WPP_DEFINE_BIT( SDP_BUFFER_POOL) \\r
- WPP_DEFINE_BIT( SDP_LOCK) \\r
- WPP_DEFINE_BIT( SDP_PERFORMANCE) \\r
- WPP_DEFINE_BIT( SDP_CONNECTION_LIST) \\r
- WPP_DEFINE_BIT( SDP_CREDITS))\r
-\r
-#define WPP_LEVEL_FLAGS_ENABLED(lvl, flags) (WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= lvl)\r
-#define WPP_LEVEL_FLAGS_LOGGER(lvl,flags) WPP_LEVEL_LOGGER(flags)\r
-#define WPP_FLAG_ENABLED(flags)(WPP_LEVEL_ENABLED(flags) && WPP_CONTROL(WPP_BIT_ ## flags).Level >= TRACE_LEVEL_VERBOSE)\r
-#define WPP_FLAG_LOGGER(flags) WPP_LEVEL_LOGGER(flags)\r
-\r
-// begin_wpp config\r
-// SDP_ENTER(FLAG);\r
-// SDP_EXIT(FLAG);\r
-// USESUFFIX(SDP_ENTER, "%!FUNC![");\r
-// USESUFFIX(SDP_ENTER, "%!FUNC!]");\r
-// end_wpp\r
-\r
-#else\r
-\r
-// Debug toppics\r
-#define SDP_API 0x000001\r
-#define SDP_CONNECT 0x000002\r
-#define SDP_DRIVER 0x000004\r
-#define SDP_SOCKET 0x000008\r
-#define SDP_ARP 0x000010\r
-#define SDP_BUFFER_POOL 0x000020\r
-#define SDP_LOCK 0x000040\r
-#define SDP_PERFORMANCE 0x000080\r
-#define SDP_CONNECTION_LIST 0x000100\r
-#define SDP_CREDITS 0x000200\r
-\r
-\r
-\r
-VOID\r
- SDP_PRINT(\r
- IN ULONG lvl, \r
- IN ULONG flags, \r
- IN PCCHAR msg,\r
- ...);\r
-\r
-#endif\r
-\r
-\r
-#endif //H_SDP_TRACE_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
-\r
-#if defined(EVENT_TRACING)\r
-#ifdef offsetof\r
-#undef offsetof\r
-#endif\r
-#include "SdpUserFile.tmh"\r
-#endif\r
-\r
-SdpUserFile::SdpUserFile()\r
-{\r
- InitializeListHead(&m_SocketsList);\r
- m_shutdown = false;\r
- m_NumberOfUserThreads = 0;\r
-}\r
-\r
-NTSTATUS SdpUserFile::Init()\r
-{\r
- InitializeListHead(&m_SocketsList);\r
- KeInitializeEvent(&m_UsersCallEvent, SynchronizationEvent , FALSE );\r
- m_shutdown = false;\r
- KeInitializeSpinLock(&m_Lock);\r
- return STATUS_SUCCESS;\r
-}\r
-\r
-void SdpUserFile::Shutdown()\r
-{ \r
- SDP_PRINT(TRACE_LEVEL_VERBOSE, SDP_SOCKET, "Called this = 0x%p \n",this);\r
- // go over the entire list, and release it's objects\r
- CSpinLockWrapper Lock(m_Lock);\r
- Lock.Lock();\r
- if (m_shutdown) {\r
- // Nothing to do\r
- Lock.Unlock();\r
- return;\r
- }\r
- m_shutdown = true;\r
-\r
- // Go over the list of callbacks that you have to make and remove \r
- // them.\r
- while (m_UsersCallList.Size() > 0) {\r
- PLIST_ENTRY pTemp = m_UsersCallList.RemoveHeadList();\r
- SdpSocket * pSdpSocket = CONTAINING_RECORD(pTemp, SdpSocket , m_CallBackRequestList);\r
-\r
- // Don't call release with the lock being hold\r
- Lock.Unlock();\r
- pSdpSocket->Release();\r
- // It seems that we shoule be protected by the m_shutdown\r
- // flag, but will take the lock just in case\r
- Lock.Lock();\r
- }\r
- \r
- while (!IsListEmpty(&m_SocketsList)) {\r
- PLIST_ENTRY pTemp = RemoveHeadList(&m_SocketsList);\r
- SdpSocket *pSdpSocket = CONTAINING_RECORD(pTemp, SdpSocket, m_UserFileList );\r
-\r
- // Don't call release with the lock being hold\r
- Lock.Unlock();\r
- // We currently call this both when the process is dead as well as \r
- // when the device is closed\r
- pSdpSocket->DyingProcessDetected();\r
- pSdpSocket->Release();\r
- // It seems that we shoule be protected by the m_shutdown\r
- // flag, but will take the lock just in case\r
- Lock.Lock();\r
- }\r
- \r
- Lock.Unlock();\r
- // Free the users thread\r
- KePulseEvent(&m_UsersCallEvent,IO_NO_INCREMENT ,FALSE); \r
-}\r
-\r
-NTSTATUS SdpUserFile::AddSocket(SdpSocket *pSdpSocket)\r
-{\r
- CSpinLockWrapper Lock(m_Lock);\r
- Lock.Lock();\r
- if (m_shutdown) {\r
- Lock.Unlock();\r
- return STATUS_FILE_CLOSED;\r
- }\r
- InsertHeadList(&m_SocketsList, &pSdpSocket->m_UserFileList);\r
- pSdpSocket->AddRef();\r
- \r
- Lock.Unlock();\r
- return STATUS_SUCCESS;\r
-\r
-}\r
-\r
-VOID SdpUserFile::RemoveSocket(SdpSocket *pSdpSocket)\r
-{\r
- CSpinLockWrapper Lock(m_Lock);\r
- Lock.Lock();\r
-\r
- // If shutodown is running, we don't do anything, weather this\r
- // socket is out of the list already, or that it will soon be \r
- // out\r
- if (m_shutdown) {\r
- Lock.Unlock();\r
- return ;\r
- }\r
-\r
- RemoveEntryList(&pSdpSocket->m_UserFileList);\r
- pSdpSocket->Release();\r
- \r
- Lock.Unlock();\r
-}\r
-\r
-\r
-SdpSocket *SdpUserFile::SocketByPointer(VOID *Socket)\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- SdpSocket *pSdpSocket = NULL;\r
- PLIST_ENTRY pNext;\r
- CSpinLockWrapper Lock(m_Lock);\r
- Lock.Lock();\r
- if (m_shutdown) {\r
- Lock.Unlock();\r
- return NULL;\r
- }\r
-\r
- pNext = m_SocketsList.Flink;\r
- while (pNext != &m_SocketsList) {\r
- pSdpSocket = CONTAINING_RECORD(pNext, SdpSocket, m_UserFileList );\r
- if (pSdpSocket == Socket) {\r
- // We have found the socket that we are looking for\r
- break;\r
- }\r
- pNext = pNext->Flink;\r
- }\r
- if (pSdpSocket != Socket) {\r
- // We have found something, but this is not the correct object\r
- pSdpSocket = NULL;\r
- }\r
- if (pSdpSocket) { \r
- pSdpSocket->AddRef();\r
- }\r
- \r
- Lock.Unlock();\r
-\r
- return pSdpSocket;\r
-}\r
-\r
-NTSTATUS \r
-SdpUserFile::RequestCallBack(LIST_ENTRY *pList)\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- CSpinLockWrapper Lock(m_Lock);\r
- SdpSocket *pSdpSocket = NULL;\r
- \r
- pSdpSocket = CONTAINING_RECORD(pList, SdpSocket , m_CallBackRequestList);\r
- // Take the lock and add the wanted event\r
- Lock.Lock();\r
- if (m_shutdown) {\r
- Lock.Unlock();\r
- return STATUS_SHUTDOWN_IN_PROGRESS;\r
- }\r
- pSdpSocket->AddRef();\r
-\r
- ASSERT(IsListEmpty(pList));\r
- m_UsersCallList.InsertTailList(pList);\r
-\r
- Lock.Unlock();\r
- // Make sure someone tries to read our objects\r
- KeSetEvent(&m_UsersCallEvent,IO_NETWORK_INCREMENT ,FALSE);\r
- return rc;\r
-\r
-}\r
-\r
-/*\r
- This function is being called by a thread that reaches us from \r
- the user, and is responisble for copying data from user buffers\r
- to kernel memory.\r
-\r
- Only in the case of shutdown, the thread will exit.\r
- Since we only do the cleanup of the SdpUserFile on IRP_MJ_CLOSE\r
- there is no feer of working on a removed object.\r
-*/\r
-\r
-NTSTATUS \r
-SdpUserFile::UsersThread()\r
-{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
- CSpinLockWrapper Lock(m_Lock);\r
- LIST_ENTRY *item = NULL;\r
- SdpSocket *pSdpSocket = NULL;\r
- bool ShutdownCalled = false; // This will only change from false\r
- // to true\r
- long NumberOfThreads = InterlockedIncrement(&m_NumberOfUserThreads);\r
- if(NumberOfThreads != 1) {\r
- // It seems that more than one uesr is here, don't let him\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "More than one user thread !!! \n");\r
- ASSERT(FALSE);\r
- return STATUS_ACCESS_DENIED;\r
- }\r
- \r
- int count = 0; \r
- while (true) {\r
- // Take the lock, and see the state:\r
- Lock.Lock();\r
- ShutdownCalled = m_shutdown;\r
- // Process all data that exists\r
- if(m_UsersCallList.Size() > 0) {\r
- item = m_UsersCallList.RemoveHeadList();\r
- pSdpSocket = CONTAINING_RECORD(item, SdpSocket , m_CallBackRequestList);\r
-\r
- Lock.Unlock();\r
- // Do the call back \r
- if (!ShutdownCalled) {\r
- pSdpSocket->UsersThreadCallBack(true);\r
- } else {\r
- //Currently, we don't call on shutdown.\r
- }\r
-\r
- // Release everything\r
- pSdpSocket->Release();\r
- continue;\r
- }\r
- if (ShutdownCalled) {\r
- // Is there some other thread that is hidding ? Shouldn't happen\r
- // but we can't trust the user\r
- KePulseEvent(&m_UsersCallEvent,IO_NO_INCREMENT ,FALSE);\r
- Lock.Unlock();\r
- return STATUS_SUCCESS;\r
- }\r
- // Wait for a new event to arrive\r
- Lock.Unlock();\r
- rc = MyKeWaitForSingleObject(&m_UsersCallEvent, UserRequest, UserMode, TRUE, NULL);\r
- \r
- if (rc == STATUS_USER_APC ) {\r
- SDP_PRINT(TRACE_LEVEL_ERROR, SDP_SOCKET, "Worker thread has recieved a user APC, shuting down the process \n");\r
- Shutdown();\r
- return STATUS_SUCCESS;\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
-This class is being used to truck all the user objects that are being\r
-created per user mode dll (each dll opens a handle to the driver once)\r
-\r
-It keeps a list of all the objects so we know when to remove them.\r
-\r
-*/\r
-\r
-#ifndef _SDP_USER_FILE_H\r
-#define _SDP_USER_FILE_H\r
-\r
-class SdpUserFile : public RefCountImpl {\r
-private: \r
- KSPIN_LOCK m_Lock;\r
- bool m_shutdown;\r
-\r
-// BUGBUG: Use something more effiecent for this storage\r
- LIST_ENTRY m_SocketsList; \r
-\r
- LinkedList m_UsersCallList; // This list holds all the requests of users for callback\r
- KEVENT m_UsersCallEvent; // The users thread waits on this event\r
-\r
- volatile long m_NumberOfUserThreads;// Make sure that there is only one user thread\r
-\r
-public:\r
-\r
- SdpUserFile();\r
-\r
- NTSTATUS Init();\r
- VOID Shutdown();\r
-\r
- SdpSocket *SocketByPointer(VOID *Socket);\r
- \r
- NTSTATUS AddSocket(SdpSocket *pSdpSocket);\r
-\r
- VOID RemoveSocket(SdpSocket *pSdpSocket);\r
-\r
-// VOID MoveSocketT(SdpSocket *pSdpSocket);\r
-\r
- NTSTATUS RequestCallBack(LIST_ENTRY *pList);\r
-\r
- NTSTATUS UsersThread();\r
-\r
-};\r
-\r
-#endif //_SDP_USER_FILE_H\r
-\r
+++ /dev/null
-#\r
-# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source\r
-# file to this component. This file merely indirects to the real make file\r
-# that is shared by all the driver components of the Windows NT DDK\r
-#\r
-\r
-!INCLUDE ..\..\..\inc\openib.def\r
+++ /dev/null
-/*\r
- * Copyright (c) 2005 Mellanox Technologies. 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
- * $Id$\r
- */\r
-\r
-\r
-#include <oib_ver.h>\r
-\r
-#define VER_FILETYPE VFT_DRV\r
-#define VER_FILESUBTYPE VFT2_UNKNOWN\r
-\r
-#if DBG\r
-#define VER_FILEDESCRIPTION_STR "SDP over InfiniBand Driver (Debug)"\r
-#else\r
-#define VER_FILEDESCRIPTION_STR "SDP over InfiniBand Driver"\r
-#endif\r
-\r
-#define VER_INTERNALNAME_STR "sdp.sys"\r
-#define VER_ORIGINALFILENAME_STR "sdp.sys"\r
-\r
-#include <common.ver>\r
+++ /dev/null
-#include <winsock2.h>\r
-#include <windows.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <Setupapi.h>\r
-#include <tchar.h>\r
-#include <strsafe.h>\r
-#include <assert.h>\r
-#include <strsafe.h>\r
-\r
-\r
-static int result = 0;\r
-\r
-\r
-// Notes:\r
-//\r
-// -- Maximum message size calculation:\r
-// The maximum lenght of an IP message is 64K-1 (the length field in the IP header is 16 bits wide).\r
-// The IP length field includes the IP header.\r
-// Therefore, the maximum length of a UDP message payload is:\r
-// 64K-1-20(IP header)-8(UDP header) = 65507 bytes\r
-\r
-\r
-void printUsage(char *exeName){\r
- printf("usage of program is:\n");\r
- printf("%s <\"client\"> <destinationIP> <destinationPort> <numberOfMessages> <constSize>\nif contSize==0, then client will send numberOfMessages messages of 1,2,3,...numberOfMessages bytes\nif contSize!=0 then client will send numberOfMessages messages of contSize bytes\n",exeName);\r
- printf("\n or\n\n");\r
- printf("%s <server> <localPort>\n\t", exeName);\r
-}\r
-\r
-WSABUF* allocateBuffer(int len){\r
- WSABUF* buffer = new WSABUF[1];\r
- if (buffer == NULL) {\r
- printf("Error in allocating memory for buffer\n");\r
- return NULL;\r
- }else{\r
- buffer[0].len = len;\r
- buffer[0].buf = new char [len];\r
- if (buffer[0].buf == NULL) {\r
- printf("Error in allocating memory for buffer[0].buf\n");\r
- delete [] buffer;\r
- return NULL;\r
- }else{\r
- buffer[0].buf[0] = 0;\r
- return buffer;\r
- }\r
- }\r
-}\r
-\r
-void freeBuffer(WSABUF* buffer){\r
- delete [] buffer[0].buf; \r
- delete [] buffer;\r
-}\r
-\r
-SOCKET createSocket(){\r
- WSADATA wsaData;\r
- int error = WSAStartup( MAKEWORD( 2, 2 ), &wsaData);\r
- if (error) {\r
- printf("Error in WSAStartup: winsock error=%d\n", WSAGetLastError());\r
- return INVALID_SOCKET;\r
- }\r
- SOCKET socket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);\r
- if (socket == INVALID_SOCKET) {\r
- printf("Error in WSASocket: winsock error=%d\n", WSAGetLastError());\r
- }\r
- return socket; \r
-}\r
-\r
-bool increaseSendBuffSize(SOCKET socket, int requestedBufferSize){\r
- int realSendBufferSize;\r
- int error = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char*)&requestedBufferSize, sizeof (int));\r
- if (error) {\r
- printf("Error in setsockopt: winsock error=%d\n", WSAGetLastError());\r
- return FALSE;\r
- }\r
- int size = sizeof (int);\r
- error = getsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char*)&realSendBufferSize, &size);\r
- if (error) {\r
- printf("Error in getsockopt: winsock error=%d\n", WSAGetLastError());\r
- return FALSE;\r
- }\r
- if (realSendBufferSize != requestedBufferSize) {\r
- printf("Error: realSendBufferSize!=requestedBufferSize:\n \\r
- , realSendBufferSize = %d, requestedBufferSize=%d", \r
- realSendBufferSize, requestedBufferSize);\r
- return FALSE;\r
- }\r
- return TRUE;\r
-}\r
-\r
-sockaddr addressFromString(char *address, USHORT port)\r
-\r
-{\r
- SOCKADDR_IN socket_address;\r
- sockaddr *socket_address_ptr = (sockaddr*)&socket_address;\r
- memset(&socket_address, 0, sizeof(socket_address));\r
- socket_address.sin_family = AF_INET;\r
- socket_address.sin_port = htons(port);\r
- int b1,b2,b3,b4;\r
- sscanf(address, "%d.%d.%d.%d",&b1, &b2, &b3, &b4);\r
- socket_address.sin_addr.S_un.S_un_b.s_b1 = (BYTE)b1;\r
- socket_address.sin_addr.S_un.S_un_b.s_b2 = (BYTE)b2;\r
- socket_address.sin_addr.S_un.S_un_b.s_b3 = (BYTE)b3;\r
- socket_address.sin_addr.S_un.S_un_b.s_b4 = (BYTE)b4;\r
- return *socket_address_ptr;\r
-}\r
-\r
-void performancePrint(double size, DWORD startTime){\r
- DWORD mseconds = GetTickCount()-startTime;\r
- if(mseconds!=0){\r
- printf("sent and received %f bytes/%d mseconds => %f MBPS\n", \r
- size, mseconds, (size/mseconds)/1000.0); \r
- }else{\r
- printf("sent and received %f bytes, in 0 mseconds\n", size);\r
- }\r
-}\r
-\r
-void clientDebugMessage(bool printEnable, int debugMessageNumber, double size, DWORD time){\r
- if(!printEnable){\r
- return;\r
- }\r
- switch(debugMessageNumber){\r
- case 1:\r
- printf("sending %f bytes at time %d msec\n", size, time);\r
- break;\r
- case 2:\r
- performancePrint(size, time);\r
- break;\r
- case 3:\r
- printf("\n\n\nPerformance summary:\n");\r
- performancePrint(size, time);\r
- break;\r
- default:\r
- break;\r
- }\r
-}\r
-\r
-// 0: normanl good receive\r
-// 2: error\r
-int myReceive(\r
- SOCKET socket, \r
- WSABUF* receiveBufferArray, \r
- WSAOVERLAPPED* wsaoverlappedPtr,\r
- DWORD* numOfRecvBytesPtr, \r
- DWORD* flagsPtr,\r
- int timeoutTime\r
- ){\r
-\r
- int recvStat = WSARecv(\r
- socket, \r
- receiveBufferArray, \r
- 1, \r
- numOfRecvBytesPtr, \r
- flagsPtr, \r
- NULL, \r
- NULL\r
- );\r
- if( (recvStat!= 0) ){ \r
- printf("erroro\n");\r
- DWORD dwgle = WSAGetLastError();\r
- if (dwgle != WSA_IO_PENDING ) {\r
- printf("Error in WSARecv: winsock error=%d\n", WSAGetLastError());\r
- return 2;\r
- }\r
- } \r
- return 0; \r
-}\r
-\r
-\r
-#define SEND\r
-\r
-void client(char *IP, int Port, int numberOfMessages, int constSize)\r
-{\r
- bool debug = FALSE;\r
- SOCKET socket = INVALID_SOCKET;\r
- sockaddr localSockAddr;\r
- sockaddr destSockAddr;\r
- WSABUF* sendBufferArray = NULL;\r
- WSABUF* receiveBufferArray = NULL;\r
- DWORD firstSendStartTime;\r
- DWORD startTime;\r
- DWORD flags = 0;\r
- DWORD numOfSentBytes;\r
- DWORD numOfRecvBytes;\r
- double totalSentBytes = 0;\r
- DWORD timeoutTime = 3000; //represents mseconds\r
- DWORD totalWaitTime = 0;\r
- int ret;\r
-\r
-\r
- printf("client starting: ip=%s, port=%d, numberOfMessages=%d\n", IP, Port, numberOfMessages );\r
-\r
- // open and connect the socket:\r
- socket = createSocket();\r
- if(socket==INVALID_SOCKET) {\r
- result = 1;\r
- goto cleanup;\r
- }\r
-\r
- destSockAddr = addressFromString (IP, (USHORT)Port);\r
- if(WSAConnect(socket, &destSockAddr, sizeof(destSockAddr), NULL, NULL, NULL, NULL)!=0){\r
- printf("Error in WSAConnect: winsock error=%d\n", WSAGetLastError());\r
- result = 1;\r
- goto cleanup;\r
- }\r
-\r
-\r
-#ifndef SEND\r
- // Send the buffer sizes\r
- char message[40];\r
- StringCbPrintf(message, sizeof message, "%d,%d,", constSize,numberOfMessages);\r
- ret = send(socket, message, strlen (message), 0);\r
- if (ret != strlen (message)) {\r
- printf("Error in send winsock error=%d\n", WSAGetLastError());\r
- result = 1;\r
- goto cleanup;\r
- }\r
-#endif \r
-\r
- // allocate send & receive buffers:\r
- sendBufferArray = allocateBuffer(constSize);\r
- if(sendBufferArray==NULL){ \r
- result = 1;\r
- goto cleanup;\r
- }\r
- receiveBufferArray = allocateBuffer(constSize);\r
- if(receiveBufferArray==NULL){\r
- result = 1;\r
- goto cleanup;\r
- }\r
-\r
- firstSendStartTime = GetTickCount();\r
- // main client loop:\r
- for(int i = 0; i < numberOfMessages; i++) {\r
- int messageSize = constSize==0 ? i : constSize;\r
- startTime = GetTickCount();\r
- clientDebugMessage(debug, 1, (double)messageSize, startTime);\r
- sendBufferArray[0].len = messageSize;\r
- if(i==numberOfMessages){\r
- sendBufferArray[0].buf[0] = 1;\r
- }\r
-\r
- if (messageSize > 10 ) {\r
- // Just put some data in here\r
- int q;\r
- for (q= 0; q< 8; q++ ) {\r
- sendBufferArray[0].buf[q] = (char)q + 'A';\r
- }\r
- }\r
-#ifdef SEND\r
- if(WSASend(socket, sendBufferArray, 1, &numOfSentBytes, 0, NULL, NULL) != 0) {\r
- printf("Error in WSASend in messageSize=%d: winsock error=%d\n", messageSize, WSAGetLastError());\r
- result = 1;\r
- goto cleanup;\r
- }\r
- if(numOfSentBytes!=messageSize) {\r
- printf("numOfSentBytes!=messageSize\n");\r
- result = 1;\r
- goto cleanup;\r
- }\r
-#else\r
- DWORD Flags = 0;\r
- if(WSARecv(socket, sendBufferArray, 1, &numOfSentBytes, &Flags, NULL, NULL) != 0) {\r
- printf("Error in WSARecv in messageSize=%d: winsock error=%d\n", messageSize, WSAGetLastError());\r
- result = 1;\r
- goto cleanup;\r
- }\r
- assert(numOfSentBytes == messageSize); // Make sure we have a complete buffer\r
- if (numOfSentBytes > 4) {\r
- //printf("Recieved %c%c%c%c\n", sendBufferArray->buf[0], sendBufferArray->buf[1], sendBufferArray->buf[2], sendBufferArray->buf[3] );\r
- }\r
- //printf("i = %d Recieved %d bytes\n",i, numOfSentBytes); \r
-\r
-#endif\r
-/*\r
- int recvStatus = myReceive(\r
- socket, \r
- receiveBufferArray, \r
- NULL, \r
- &numOfRecvBytes, \r
- &flags, \r
- timeoutTime\r
- );\r
- switch(recvStatus){\r
- case 0:\r
- totalSentBytes+=messageSize;\r
- if(numOfRecvBytes!=messageSize){\r
- printf("numOfRecvBytes(%d) != messageSize(%d)\n", numOfRecvBytes, messageSize);\r
- result = 1;\r
- goto cleanup;\r
- }\r
- clientDebugMessage(debug, 2, messageSize, startTime);\r
- break;\r
- case 2:\r
- result = 1;\r
- goto cleanup;\r
- default:\r
- printf("reached default in switch statement\n");\r
- result = 1;\r
- goto cleanup;\r
- }\r
-*/\r
- }\r
- \r
- if(totalSentBytes!=0){\r
- clientDebugMessage(TRUE, 3, totalSentBytes, firstSendStartTime+totalWaitTime);\r
- }else{\r
- printf("no bytes transferred\n");\r
- }\r
- \r
- cleanup:\r
- if(socket!=INVALID_SOCKET){\r
- if(closesocket(socket)!=0){\r
- printf("closesocket error: error = %d\n", WSAGetLastError());\r
- }\r
- }\r
- WSACleanup();\r
- if(sendBufferArray!=NULL){\r
- freeBuffer(sendBufferArray);\r
- }\r
- if(receiveBufferArray!=NULL){\r
- freeBuffer(receiveBufferArray);\r
- }\r
-// printf("sleeping ...\n");\r
-// Sleep(1000);\r
-}\r
-\r
-void serverDebugMessage(bool printEnable, int messageNumber, double size){\r
- if(!printEnable){\r
- return;\r
- }\r
- switch(messageNumber){\r
- case 1:\r
- printf("-----------------------------------------------------------\n");\r
- printf(" received %f bytes at time %d\n", size, GetTickCount());\r
- break;\r
- case 2:\r
- printf("sent back %f bytes at time %d\n", size, GetTickCount());\r
- printf("-----------------------------------------------------------\n\n");\r
- break;\r
- default:\r
- break;\r
- }\r
-}\r
-\r
-void Server(int Port)\r
-{\r
- SOCKET s;\r
- WSADATA wsaData;\r
- sockaddr saLocal, saFrom;\r
- int i;\r
- DWORD start, end, Flags = 0;\r
- int NumberOfMessages = 1;\r
- int MessageSize = 70000;\r
- WSABUF wsb;\r
- \r
-\r
- printf("Starting as Server port=%d, \n", Port );\r
-\r
- int err = WSAStartup( MAKEWORD( 2, 2 ), &wsaData);\r
- if ( err != 0 ) {\r
- printf("Error opening winsock err=%d", WSAGetLastError());\r
- goto cleanup;\r
- }\r
-\r
- s = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0 );\r
- if (s == INVALID_SOCKET) {\r
- printf("Error creating socket winsock err=%d", WSAGetLastError());\r
- goto cleanup;\r
- }\r
-\r
- int RecvBufferSize = 0* 1024, RealRecvBufferSize;\r
- err = setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&RecvBufferSize, sizeof (int));\r
- if ( err != 0 ) {\r
- printf("Error setsockopt failed err=%d", WSAGetLastError());\r
- goto cleanup;\r
- }\r
- int Size = sizeof (int);\r
- err = getsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&RealRecvBufferSize, &Size);\r
- if ( err != 0 ) {\r
- printf("Error setsockopt failed err=%d", WSAGetLastError());\r
- goto cleanup;\r
- }\r
- if (RealRecvBufferSize != RecvBufferSize) {\r
- printf("Error: RealSendBufferSize = %d", RealRecvBufferSize);\r
- goto cleanup;\r
- }\r
-\r
-\r
- DWORD dwBytesRecieved;\r
-\r
- // Bind the socket first\r
-\r
- SOCKADDR_IN *psa = (SOCKADDR_IN*)&saLocal;\r
- memset(&saLocal, 0, sizeof(saLocal));\r
- psa->sin_family = AF_INET;\r
- psa->sin_port = htons((USHORT)Port);\r
- \r
- err = bind(s, &saLocal, sizeof(saLocal));\r
- if ( err != 0 ) {\r
- printf("Error bind winsock err=%d", WSAGetLastError());\r
- goto cleanup;\r
- }\r
-\r
- err = listen(s, 10);\r
- if ( err != 0 ) {\r
- printf("Error on listen winsock err=%d", WSAGetLastError());\r
- goto cleanup;\r
- }\r
-\r
- while (1) {\r
- int addrLen = sizeof (saFrom);\r
- SOCKET s1 = accept(s, &saFrom, &addrLen);\r
- if (s1 == INVALID_SOCKET) {\r
- printf("Error accept failed err=%d", WSAGetLastError());\r
- goto cleanup;\r
- }\r
-\r
- \r
- for (i =0; i < 1; i++) {\r
- // Recieve the data\r
- printf ("Calling recieve\n");\r
- \r
- wsb.len = MessageSize;\r
- wsb.buf = new char [MessageSize];\r
- if (wsb.buf == NULL ) {\r
- printf("Error Allocating memory\n");\r
- goto cleanup;\r
- } \r
- \r
- err = WSARecv(\r
- s1,\r
- &wsb,\r
- 1,\r
- &dwBytesRecieved,\r
- &Flags,\r
- NULL,\r
- NULL\r
- );\r
- if (err == SOCKET_ERROR) {\r
- DWORD gle = WSAGetLastError();\r
- if (gle != WSA_IO_PENDING) {\r
- \r
- printf("Error WSARecv winsock err=%d", gle);\r
- goto cleanup;\r
- }\r
- }\r
-\r
- // send a reply packet\r
- \r
- StringCbCopy(wsb.buf, wsb.len, "I'm a demo server");\\r
- wsb.len = strlen(wsb.buf);\r
- err = WSASend(\r
- s1,\r
- &wsb,\r
- 1,\r
- &dwBytesRecieved,\r
- Flags,\r
- NULL,\r
- NULL\r
- );\r
- if (err == SOCKET_ERROR) {\r
- DWORD gle = WSAGetLastError();\r
- if (gle != WSA_IO_PENDING) {\r
- \r
- printf("Error WSASend winsock err=%d", gle);\r
- goto cleanup;\r
- }\r
- } \r
- }\r
- } \r
- cleanup:\r
- WSACleanup(); \r
-\r
-}\r
-\r
-__cdecl main (int argc, char *argv[]){\r
- if ((argc == 6) && !_stricmp(argv[1],"client") ) {\r
- int port = atoi(argv[3]);\r
- int numberOfMessages = atoi(argv[4]);\r
- int constSize = atoi(argv[5]);\r
- client(argv[2], port, numberOfMessages, constSize);\r
- return result;\r
- }else if((argc==3 ) && !_stricmp(argv[1],"server") ){\r
- int port = atoi(argv[2]);\r
- Server(port);\r
- return result;\r
- }else{\r
- printUsage(argv[0]);\r
- return 1; \r
- }\r
-}\r
+++ /dev/null
-\r
-#ifdef _WIN32\r
-#include <Winsock2.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <assert.h>\r
-\r
-#define AF_INET_FAMILY PF_INET\r
-\r
-#define sleep(x) Sleep(1000 * (x));\r
-#define CloseSocket closesocket\r
-\r
-#define GetTimeMs() GetTickCount()\r
-#else\r
-\r
-#define AF_INET_FAMILY 27\r
-\r
-#include <sys/types.h>\r
-#include <netinet/in.h>\r
-#include <sys/socket.h>\r
-#include <stdio.h>\r
-#include <errno.h>\r
-\r
-#define _stricmp strcasecmp\r
-#define WSAGetLastError() errno\r
-#define CloseSocket close\r
-\r
-\r
-#endif\r
-// Windows linux \r
-\r
-const int NumberOfThreads = 2;\r
-\r
-HANDLE g_ComplitionPort;\r
-HANDLE g_pThreads[NumberOfThreads];\r
-\r
-#define ASSERT assert\r
-\r
-struct sockaddr addressFromString(char *address, int port)\r
-{\r
- unsigned int b1,b2,b3,b4;\r
-\r
- struct sockaddr_in socket_address;\r
- struct sockaddr *socket_address_ptr = (struct sockaddr*)&socket_address;\r
- \r
- memset(&socket_address, 0, sizeof(socket_address));\r
- socket_address.sin_family = AF_INET;\r
- socket_address.sin_port = htons((u_short)port);\r
-\r
-\r
- sscanf(address, "%d.%d.%d.%d",&b1, &b2, &b3, &b4);\r
- socket_address.sin_addr.s_addr = b4 * 256 * 256 *256 +\r
- b3 * 256 * 256 + \r
- b2 * 256 +\r
- b1;\r
- \r
- return *socket_address_ptr;\r
-}\r
-\r
-\r
-struct OverlappedSend {\r
- OVERLAPPED Overlapped;\r
- SOCKET Socket;\r
- void *Buffer; // The data to send\r
- int DataSize;\r
- DWORD NumberOfBytesSent;\r
- static int s_RemainingSends;\r
- static int s_SendsInAir; // Curently sent data (debug only)\r
- static CRITICAL_SECTION s_Lock;\r
- static HANDLE s_SendDoneEvent;\r
-\r
-};\r
-\r
-int OverlappedSend::s_RemainingSends;\r
-int OverlappedSend::s_SendsInAir; // Curently sent data (debug only)\r
-CRITICAL_SECTION OverlappedSend::s_Lock;\r
-HANDLE OverlappedSend::s_SendDoneEvent;\r
-\r
-\r
-DWORD WINAPI WorkerThreadFunc( LPVOID lpParam )\r
-{\r
- BOOL ret;\r
- DWORD NumberOfBytes;\r
- ULONG_PTR CompletionKey;\r
- OVERLAPPED* lpOverlapped;\r
- OverlappedSend *pOverLappedSend;\r
- BOOL ContinueLoop = true;\r
- int iRet;\r
- \r
- while (TRUE) {\r
- ret = GetQueuedCompletionStatus(\r
- g_ComplitionPort,\r
- &NumberOfBytes,\r
- &CompletionKey,\r
- &lpOverlapped,\r
- INFINITE);\r
- ASSERT(ret != 0);\r
- pOverLappedSend = CONTAINING_RECORD(lpOverlapped, OverlappedSend, Overlapped);\r
- // Work on the object itself:\r
- EnterCriticalSection(&pOverLappedSend->s_Lock);\r
- pOverLappedSend->s_SendsInAir--;\r
- if (pOverLappedSend->s_RemainingSends > 0) {\r
- // do the next send\r
- WSABUF Buffers;\r
- Buffers.len = pOverLappedSend->DataSize;\r
- Buffers.buf = (char *) pOverLappedSend->Buffer;\r
- pOverLappedSend->s_SendsInAir++;\r
- pOverLappedSend->s_RemainingSends--;\r
- \r
- iRet = WSASend(\r
- pOverLappedSend->Socket,\r
- &Buffers,\r
- 1,\r
- &pOverLappedSend->NumberOfBytesSent,\r
- 0,\r
- &pOverLappedSend->Overlapped,\r
- NULL\r
- );\r
- ASSERT((iRet ==0) || (iRet == SOCKET_ERROR && WSAGetLastError() == WSA_IO_PENDING ));\r
-\r
- } else {\r
- // Nothing more to send - signal compleation and exit\r
- SetEvent(pOverLappedSend->s_SendDoneEvent);\r
- ContinueLoop = false;\r
- }\r
- LeaveCriticalSection(&pOverLappedSend->s_Lock);\r
- if (!ContinueLoop) {\r
- break;\r
- }\r
-\r
- }\r
- return 0;\r
-}\r
-\r
-void CreateComplitionPort(SOCKET newfd)\r
-{\r
-\r
- g_ComplitionPort = CreateIoCompletionPort((HANDLE)newfd, NULL, NULL, 2);\r
- if(g_ComplitionPort == NULL) {\r
- printf("Create complition port failed err=%d", GetLastError());\r
- exit(1);\r
- }\r
-\r
-\r
- for (int i=0; i <NumberOfThreads;i++ ) {\r
- // Create the threads that will work on the complitions\r
- g_pThreads[i] = CreateThread(NULL, 0 ,WorkerThreadFunc ,NULL, 0,NULL ); \r
- }\r
-\r
-\r
-\r
-\r
-\r
-}\r
-\r
-void CloseComplitionPort()\r
-{\r
-\r
- // Post a complition thread end message\r
- for (int i=0; i <NumberOfThreads - 1;i++ ) {\r
- // Sending an overlapped of NULL works, since the\r
- // reciever tests first for end of test\r
- BOOL ret = PostQueuedCompletionStatus(\r
- g_ComplitionPort,\r
- 0,\r
- NULL,\r
- NULL\r
- );\r
- ASSERT(ret != 0);\r
- }\r
- WaitForMultipleObjects(NumberOfThreads,g_pThreads, TRUE, INFINITE);\r
- CloseHandle(g_ComplitionPort);\r
-\r
-}\r
-\r
-void SendDataOverlapped(SOCKET newfd, int NumberOfOverlappedSend, double NumberOfBuffers, double BufferSize, BOOL SendPacketNumber)\r
-{\r
- int i ;\r
- VOID *buffer = NULL;\r
- double elapsed, acc = 0;\r
- OverlappedSend *pOverLappedSend = NULL;\r
- BOOL ret;\r
-\r
- printf("Starting to send asyncroniously (%d overlapped) %lf messages of size %lf\n", NumberOfOverlappedSend, NumberOfBuffers, BufferSize );\r
-\r
-\r
- CreateComplitionPort(newfd);\r
- pOverLappedSend->s_RemainingSends = (size_t)NumberOfBuffers;\r
- pOverLappedSend->s_SendsInAir = 1; // To force a simulate of the compleation\r
- InitializeCriticalSection(&pOverLappedSend->s_Lock);\r
- pOverLappedSend->s_SendDoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL);\r
- \r
- double Start = GetTimeMs();\r
-\r
- for(i = 0; i < NumberOfOverlappedSend; i++) {\r
-\r
- buffer = new char [(size_t)BufferSize];\r
- if (buffer == NULL) {\r
- printf("Error allocating buffer\n");\r
- exit(1);\r
- }\r
-\r
- pOverLappedSend = new OverlappedSend;\r
-\r
- // Set it's fields\r
- memset(&pOverLappedSend->Overlapped, 0, sizeof (pOverLappedSend->Overlapped));\r
- pOverLappedSend->Socket = newfd;\r
- pOverLappedSend->Buffer = buffer;\r
- pOverLappedSend->DataSize = (size_t)BufferSize;\r
-\r
- // Post the message that will do the first send\r
- ret = PostQueuedCompletionStatus(\r
- g_ComplitionPort,\r
- (DWORD)BufferSize,\r
- NULL,\r
- &pOverLappedSend->Overlapped\r
- );\r
- ASSERT(ret != 0);\r
-\r
- }\r
-\r
- // wait for the send \r
- WaitForSingleObject(pOverLappedSend->s_SendDoneEvent, INFINITE);\r
- elapsed = (GetTimeMs() - Start) / 1000;\r
- printf("Finishd sending correctly %f mbytes/sec\n", NumberOfBuffers * BufferSize /elapsed/1024/1024 );\r
- CloseComplitionPort();\r
-//Cleanup:\r
- for(i = 0; i < NumberOfOverlappedSend; i++) {\r
- delete []pOverLappedSend->Buffer;\r
- delete pOverLappedSend;\r
- }\r
-}\r
-\r
-\r
-\r
-void SendData(SOCKET newfd, double NumberOfBuffers, double BufferSize, BOOL SendPacketNumber)\r
-{\r
- int i ;\r
- double d;\r
- CHAR *buffer = NULL;\r
- double elapsed, acc = 0;\r
-\r
- buffer = new char [(size_t)BufferSize];\r
- if (buffer == NULL) {\r
- printf("Error allocating buffer\n");\r
- exit(1);\r
- }\r
-\r
- printf("Starting to send syncroniously %lf messages of size %lf\n", NumberOfBuffers, BufferSize );\r
-\r
- i = 0;\r
-\r
- for (i = 0; i < 10; i++) {\r
- buffer[i] = 'a' + i;\r
- }\r
- double Start = GetTimeMs();\r
-\r
- for (d=0; d < NumberOfBuffers; d++) {\r
- int j;\r
- if (SendPacketNumber) {\r
- memset(buffer, (char) d, (size_t)BufferSize);\r
- }\r
- \r
- j = send(newfd, buffer, (size_t)BufferSize, 0 );\r
- acc += j;\r
- if (j!=BufferSize) {\r
- printf("Error send not compleated sent %lf\n", acc);\r
- goto Cleanup;\r
- }\r
- }\r
- elapsed = (GetTimeMs() - Start) / 1000;\r
- printf("Finishd sending correctly %f mbytes/sec (%f seconfs)\n", acc/elapsed/1024/1024, elapsed );\r
-Cleanup:\r
- free(buffer);\r
-}\r
-\r
-\r
-void RecvData(SOCKET newfd, double NumberOfBuffers, double BufferSize )\r
-{\r
- const int ReadSize = 400000;\r
- int read1 = 1;\r
- unsigned char *p;\r
- double elapsed, acc = 0;\r
- int i;\r
- double Start = GetTimeMs();\r
- char *buffer = new char [ReadSize];\r
- if (buffer == NULL) {\r
- printf("Error allocating memory");\r
- exit(4);\r
- }\r
-\r
- while ((read1 != -1) /*&& (acc < (double)BufferSize * NumberOfBuffers)*/) {\r
- read1 = recv(newfd, buffer, ReadSize, 0);\r
- if (read1 == -1 || read1 == 0) {\r
- printf("Finsihed reading, total read %lf bytes last read =%d\n", acc, read1 );\r
- if (acc != BufferSize * NumberOfBuffers) {\r
- printf("Error, expected to read %lf but read %lf\n",\r
- (BufferSize * NumberOfBuffers), acc);\r
- }\r
- break;\r
- }\r
- else {\r
- acc += read1;\r
-\r
-// printf("read returned %d \"%c%c%c%c\"\n",read1,\r
-// buffer[0],buffer[1], buffer[2], buffer[3]);\r
- }\r
- }\r
-\r
- if (acc != ((double)BufferSize * NumberOfBuffers)) {\r
- printf("Error, expected to read %lf but read %lf",\r
- ((double)BufferSize * NumberOfBuffers), acc);\r
- } else {\r
- elapsed = (GetTimeMs() - Start) / 1000;\r
- printf("Finishd reading correctly %lf mbytes/sec (time = %lf)\n", acc / elapsed/1024/1024, elapsed);\r
- }\r
- delete []buffer;\r
-}\r
-\r
-void PrintUsage(char *name)\r
-{\r
- printf("The program might be used in client or server mode\n");\r
- printf("usage is %s <server> <port number>\n", name);\r
- printf("usage is %s <client> <ip> <port number> <option number> <WritePacketNumber> <UseOverlappedSend> <Number of packets> <PacketSize>\n", name);\r
- printf("The option will be sent to the remote side\n");\r
- printf("Available options are:\n");\r
- printf(" 1 - just recieve packets forever (the other side will send xxx bytes yyy times)\n");\r
- printf(" 2 - send xxx bytes yyy times (based on input from network)\n");\r
- printf(" WritePacketNumber can be 0 (no) or 1 (yes)\n");\r
- printf(" UseOverlappedSend can be 0 (no) or > 0 (number of operations to use)\n");\r
-\r
-}\r
-\r
-int Connect(int argc, char *argv[])\r
-{\r
- struct sockaddr server_addr;\r
- int port = atoi(argv[3]);\r
- int ret;\r
- SOCKET s;\r
- int Send = 0;\r
- int BufferSize, NumberOfBuffers;\r
- int result = 0;\r
- bool SendPacketNumber;\r
- int NumberOfOverlappedSend = 0;\r
-\r
- if (argv[4][0] == '1') {\r
- Send = 1;\r
- }else if (argv[4][0] == '2') {\r
- Send = 0;\r
- } else {\r
- printf("Error - don't know if to send or recieve\n");\r
- exit(1);\r
- }\r
-\r
- if (argv[5][0] == '0') {\r
- SendPacketNumber = false;\r
- }else if (argv[5][0] == '1') {\r
- SendPacketNumber = true;\r
- } else {\r
- printf("Error - don't know if to send the packet number\n");\r
- exit(1);\r
- }\r
-\r
- NumberOfOverlappedSend = atoi(argv[6]);\r
-\r
- if ((NumberOfOverlappedSend > 0 ) && (SendPacketNumber == true)) {\r
- printf("Warning, Sending packet number is not supported yet in overlapped send\n");\r
- exit(1);\r
- }\r
- \r
- NumberOfBuffers = atoi(argv[7]);\r
- BufferSize = atoi(argv[8]);\r
- \r
- printf("Using port %d %s %s %s NumberOfBuffers = %d , BufferSize = %d \n", \r
- port, \r
- Send == 1 ? "sending" : "recieving", \r
- SendPacketNumber ? "Packets Are filed with data" : "Packets are not filled with data",\r
- NumberOfOverlappedSend > 0 ? "Using overlapped send" : "not using overlapped send", \r
- NumberOfBuffers,\r
- BufferSize\r
- );\r
-\r
- server_addr = addressFromString(argv[2], port);\r
-\r
- s = socket (AF_INET_FAMILY, SOCK_STREAM, 0);\r
- if (s == -1) {\r
- printf("Error creating socket\n");\r
- }\r
-\r
- ret = connect(s, &server_addr, sizeof(server_addr));\r
- if (ret ==0) {\r
- printf("connect succeeded\n");\r
- } else {\r
- printf("connect failed\n");\r
- result = 1;\r
- goto cleanup;\r
- }\r
-\r
- // Send the other side the correct information: \r
- // send(=1), UseOverlapped ,NumberOfBuffers, BufferSize,\r
- // or recieve(=0),UseOverlapped ,NumberOfBuffers, BufferSize,\r
- if (Send) {\r
- char message[60];\r
- sprintf(message, "1,%d,%d,%d,0,", NumberOfOverlappedSend ,NumberOfBuffers, BufferSize);\r
- ret = send(s, message, strlen (message), 0);\r
- if (ret != strlen (message)) {\r
- printf("Error in send winsock error=%d\n", WSAGetLastError());\r
- result = 1;\r
- goto cleanup;\r
- } \r
- } else {\r
- char message[60];\r
- sprintf(message, "2,%d,%d,%d,%d,",NumberOfOverlappedSend, NumberOfBuffers, BufferSize, SendPacketNumber ? 1 : 0);\r
- ret = send(s, message, strlen (message), 0);\r
- if (ret != strlen (message)) {\r
- printf("Error in send winsock error=%d\n", WSAGetLastError());\r
- result = 1;\r
- goto cleanup;\r
- }\r
- }\r
- if (Send) {\r
- if (NumberOfOverlappedSend > 0 ) {\r
- SendDataOverlapped(s, NumberOfOverlappedSend, NumberOfBuffers, BufferSize, SendPacketNumber);\r
- } else {\r
- SendData(s, NumberOfBuffers, BufferSize, SendPacketNumber);\r
- }\r
- } else {\r
- RecvData(s, NumberOfBuffers, BufferSize);\r
- }\r
-cleanup:\r
- ret = CloseSocket(s);\r
- if (ret == 0) {\r
- printf("CloseSocket succeeded\n");\r
- } else {\r
- printf("CloseSocket failed\n");\r
- }\r
- \r
- \r
-\r
- return result;\r
-\r
-\r
-\r
-}\r
-int ReadNumber(SOCKET fd)\r
-{\r
- //???\r
- char Data[20]; // Don't care about buffer overflows :-)\r
- int i = 0, ret;\r
-// printf("ReadNumber called\n");\r
-\r
- while (1) {\r
- ret = recv(fd,&Data[i],1,0);\r
- if (ret != 1) {\r
- printf("Error reading data 1\n");\r
- exit(1);\r
- }\r
-// printf("%c",Data[i]);\r
- if (Data[i] == ',') break;\r
- i++;\r
- if (i == 20) {\r
- printf("Error reading data 2\n");\r
- exit(1);\r
- } \r
- }\r
- return atoi(Data);\r
-}\r
-\r
-int Server(int argc, char *argv[])\r
-{\r
-\r
- u_short port = (u_short)atoi(argv[2]);\r
- int option;\r
- SOCKET s, newfd;\r
- int ret;\r
- struct sockaddr_in my_addr, client_addr;\r
- int addr_len = sizeof(client_addr);\r
- int BufferSize, NumberOfBuffers;\r
- BOOL SendPacketNumber;\r
- int UseOverlappedSend;\r
-\r
- printf("Using port %d\n", port);\r
- \r
- memset(&my_addr, 0, sizeof(my_addr));\r
- my_addr.sin_family = AF_INET;\r
- my_addr.sin_port = htons(port);\r
- s = socket (AF_INET_FAMILY , SOCK_STREAM, IPPROTO_TCP);\r
- if (s == -1) {\r
- printf("Error creating socket\n");\r
- return 1;\r
- }\r
-\r
- ret = bind(s, (struct sockaddr*)&my_addr, sizeof(my_addr));\r
- if (ret < 0) {\r
- printf("Error in bind\n" );\r
- return 2;\r
- }\r
-\r
- ret = listen(s, 5);\r
- for(;;) {\r
- struct sockaddr name;\r
- int namelen;\r
- unsigned char *p;\r
- \r
- newfd = accept(s, (struct sockaddr *)&client_addr, &addr_len);\r
- namelen = sizeof(name);\r
- getpeername(newfd, &name, &namelen);\r
- p = (unsigned char *) &client_addr;\r
- printf("recieved a client %d from %d.%d.%d.%d:%d\n", newfd, \r
- p[4], p[5],p[6], p[7], p[2] *256 + p[3] ) ;\r
-\r
-\r
- option = ReadNumber(newfd);\r
- UseOverlappedSend = ReadNumber(newfd);\r
- NumberOfBuffers = ReadNumber(newfd);\r
- BufferSize = ReadNumber(newfd);\r
- SendPacketNumber = ReadNumber(newfd);\r
-\r
- printf("%s ,%d overlapped Send,NumberOfBuffers = %d , BufferSize =%d PacketsFilled=%s \n", \r
- option == 2 ? "sending" : "recieving",\r
- UseOverlappedSend,\r
- NumberOfBuffers,\r
- BufferSize,\r
- SendPacketNumber ? "true" : "false"\r
- );\r
- \r
- if (option == 1) RecvData(newfd, NumberOfBuffers, BufferSize);\r
- if (option == 2) {\r
- if (UseOverlappedSend > 0) {\r
- SendDataOverlapped(newfd, UseOverlappedSend, NumberOfBuffers, BufferSize, SendPacketNumber);\r
- } else {\r
- SendData(newfd, NumberOfBuffers, BufferSize, SendPacketNumber);\r
- }\r
- }\r
- \r
- ret = CloseSocket(newfd);\r
- if (ret == 0) {\r
- printf("CloseSocket succeeded\n");\r
- } else {\r
- printf("CloseSocket failed\n");\r
- }\r
- //break; \r
- }\r
- return 0;\r
-}\r
-\r
-int __cdecl main(int argc, char *argv[])\r
-{\r
- int error; \r
-\r
- if (argc < 3) {\r
- PrintUsage(argv[0]);\r
- return 1;\r
- }\r
-\r
-#ifdef _WIN32\r
- {\r
- WSADATA wsaData;\r
-\r
- error = WSAStartup( MAKEWORD( 2, 2 ), &wsaData);\r
- if (error) {\r
- printf("Error in WSAStartup: winsock error=%d\n", WSAGetLastError());\r
- return 1;\r
- }\r
- }\r
-#endif \r
- if (!_stricmp(argv[1],"client")) {\r
- Connect(argc, argv);\r
- //sleep(2);\r
- } else if (!_stricmp(argv[1],"server")) {\r
- Server(argc, argv);\r
- } else {\r
- printf("Unknowion option %s", argv[1]);\r
- PrintUsage(argv[0]);\r
- \r
- }\r
- SOCKET s;\r
- s = socket (AF_INET_FAMILY, SOCK_STREAM, 0);\r
-CloseSocket(s); \r
- //printf("calling WSACleanup\n ");\r
- int ret = WSACleanup ();\r
- //printf("ret = %d", ret);\r
- return 0;\r
-}\r
-\r
+++ /dev/null
-#\r
-# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source\r
-# file to this component. This file merely indirects to the real make file\r
-# that is shared by all the driver components of the Windows NT DDK\r
-#\r
-\r
-!INCLUDE $(NTMAKEENV)\makefile.def\r
+++ /dev/null
-########################################################################\r
-#\r
-# Copyright(c) Infinicon Systems All rights reserved.\r
-#\r
-########################################################################\r
-\r
-########################################################################\r
-# The first section is nothing but manditory items.\r
-########################################################################\r
-\r
-########################################################################\r
-# The TARGETNAME. This is name of the item being built (without the\r
-# extension.\r
-TARGETNAME=SdpConnect\r
-\r
-########################################################################\r
-# The path where all binaries are built. \r
-#\r
-TARGETPATH=..\..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
-\r
-########################################################################\r
-# The type of item that is being built. This is manditory.\r
-# Value Meaning\r
-# DYNLINK - A DLL.\r
-# DRIVER - A kernel device driver.\r
-# EXPORT_DRIVER - A kernel device driver with exports.\r
-# PROGRAM - A windows executable.\r
-# PROGLIB - A windows library.\r
-# MINPORT - A miniport driver.\r
-# GDI_DRIVER - A video driver.\r
-# LIBRARY - A library \r
-TARGETTYPE=PROGRAM\r
-UMTYPE=console\r
-USE_CRTDLL=1\r
-\r
-#\r
-########################################################################\r
-# All the source files in this project. \r
-#\r
-SOURCES=\\r
- SdpConnect.cpp\r
-\r
-#\r
-########################################################################\r
-# The items below this line are not manditory, but they are certainly\r
-# helpful!\r
-########################################################################\r
-\r
-########################################################################\r
-# The include directories for project.\r
-INCLUDES=..\sdpdll; f:\Progra~1\Micros~1.net\vc7\PlatformSDK\Include\r
-#RCOPTIONS=/I..\..\win\include\r
-#\r
-\r
-########################################################################\r
-# Set defines particular to the driver. A good Idea to build listings\r
-#USER_C_FLAGS=$(USER_C_FLAGS) -DEXPORT_CL_SYMBOLS\r
-\r
-############################################\r
-# Libraries that I want the driver to link with.\r
-TARGETLIBS=\\r
- $(SDK_LIB_PATH)\ws2_32.lib \\r
- $(SDK_LIB_PATH)\Rpcrt4.lib\r
-#\r
-########################################################################\r
-\r
-\r
-########################################################################\r
-# Set the warning levels to maximum.\r
-MSC_WARNING_LEVEL= /W3\r
-#\r
-\r
-########################################################################\r
-# Set the linker to produce a map file. A must have in emergency\r
-# situations.\r
-LINKER_FLAGS=$(LINKER_FLAGS)\r
-#\r
-\r
-########################################################################\r
-#BROWSER_INFO=1\r
-#BROWSERFILE=$(TARGETPATH)\*\$(TARGETNAME).bsc -n\r
-#\r
-\r
-########################################################################\r
-# Things to be built before compile, before link, after build\r
-#NTTARGETFILE0=\r
-#NTTARGETFILE1=\r
-#NTTARGETFILES \r
-########################################################################\r
-\r
-\r
+++ /dev/null
-dirs = \\r
-basic \\r
-\r
+++ /dev/null
-This file includes things that should be impreoved in the sdp implmentation\r
-=============================================================================\r
-\r
-KERNEL MODE:\r
- 1) What to do with zero size send (currently I send nothing) and recieve.\r
- 2) How to handle shutdown? the waits fail with user Apc.\r
-\r
- connect:\r
- 1) Clean error path.\r
-\r
- send:\r
- 1) implmeant some kind of a negal algorithm.\r
- 2) Create some kind of mechanism that will allow to recieve complitions on more than\r
- one send.\r
- 3) If possibale, post more than one send, at a time\r
- 4) [Critical] Use refferance count when queing the socket in an IRP structure.\r
-\r
- recv:\r
- 1) Find and fix the race when the socket is being initialized\r
- 2) When posting the credits, consider not sending the credits if there are packets pending and \r
- and we have credits.\r
-\r
-general:\r
-\r
- Close the IPOIB device: Probably based on the example from src\general\toaster\toastmon\toastmon.c\r
- proabably (EventCategoryDeviceInterfaceChange)\r
- \r
- Find a better solution for threading and remove the current solution.\r
- Fix the race of sdp user file\r
-\r
- Fix the lock implmentation to have also a void implmentation as well as an RC implmentation.\r
-\r
- Check the ArpCache problems (on a native windows machine) and decide what to do.\r
- \r
-\r
-Overlapped IO:\r
-1) Split to two types of overlapped operations\r
-2) Use referance counting on our type? If not, make sure that the life time of objects is well.\r
-3) Replace InterlockedIncrement with _InterlockedIncrement\r
-4) Make sure that in UserFile module, operations can start only when there is a user mode thread\r
- that is already waiting.\r
-\r
-\r
-USER MODE:\r
-\r
-* Check the lifetime of the SdpSocket (when is it deleted and so)??\r
-\r
-* check with intel that we can remove their lisence from the files.\r
-\r
-* check the way that errors are reported to the user mode. It seems that returning an error\r
-in rc means that the output buffer won't pass out.\r
-\r
-* Check why sometimes the QP and so are not valid when you come to kill them\r