#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
+\r
\r
\r
// Data structures that are used for connect\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
\r
#endif //_SDP_SHARED_H\r
#include "SdpShared.h"\r
#include "SdpUserFile.h"\r
#include "SdpBufferPool.h"\r
+#include "SdpRecvPool.h"\r
#include "SdpSocket.h"\r
#include "SdpArp.h"\r
\r
SdpSocket.cpp \\r
SdpArp.cpp \\r
SdpBufferPool.cpp \\r
+ SdpRecvPool.cpp \\r
SdpTrace.cpp\r
\r
INCLUDES=..\include;\\r
!endif\r
\r
MSC_WARNING_LEVEL= /W3\r
+\r
+PRECOMPILED_INCLUDE=Precompile.h\r
+PRECOMPILED_PCH=Precompile.pch\r
+PRECOMPILED_CXX=1\r
#include "preCompile.h"\r
\r
\r
+//static \r
+NTSTATUS \r
+BufferDescriptor::AllocateBuffer(BufferDescriptor ** ppBufferDescriptor, int BufferSize, int Tag)\r
+{\r
+ SDP_PRINT(SDP_TRACE, 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
+ if (pBufferDescriptor == NULL) {\r
+ SDP_PRINT(SDP_ERR, SDP_BUFFER_POOL, ("ExAllocatePoolWithTag failed \n"));\r
+ rc = STATUS_NO_MEMORY;\r
+ goto Cleanup;\r
+ }\r
+\r
+ // Allocate the buffer itself\r
+ pBufferDescriptor->pBuffer = \r
+ ExAllocatePoolWithTag(\r
+ NonPagedPool ,\r
+ BufferSize, \r
+ Tag\r
+ );\r
+\r
+ if (pBufferDescriptor->pBuffer == NULL) {\r
+ SDP_PRINT(SDP_ERR, SDP_BUFFER_POOL, ("ExAllocatePoolWithTag failed \n"));\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
+ ExFreePoolWithTag(pBufferDescriptor->pBuffer, SEND_BUFFERS_ALLOCATION_TAG);\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
+ ExFreePoolWithTag(pBufferDescriptor->pBuffer, Tag);\r
+ ExFreePoolWithTag(pBufferDescriptor, Tag);\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_ClientBeingServed = false;\r
+ m_CurrentlySentBuffers = 0;\r
+ m_CurrentlyAllocated = 0;\r
+ m_ClientWaiting = false;\r
+}\r
+\r
NTSTATUS \r
BufferPool::Init(\r
int MaxBuffers, \r
m_MaxBuffers = MaxBuffers;\r
m_MaxConcurrentSends = MaxConcurrentSends;\r
m_MaxMessageSize = MaxMessageSize; \r
- m_ClientBeingServed = false;\r
- m_CurrentlySentBuffers = 0;\r
- m_CurrentlyAllocated = 0;\r
- m_ClientWaiting = false;\r
KeInitializeEvent(&m_WaitingClients, NotificationEvent, FALSE);\r
ASSERT(pd != NULL);\r
m_pd = pd;\r
m_qp = qp;\r
ASSERT(lkey != NULL);\r
m_lkey = lkey;\r
-#if DBG \r
m_pSdpSocket = pSdpSocket;\r
-#endif\r
-\r
-\r
return STATUS_SUCCESS;\r
}\r
\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
goto Cleanup;\r
} else if (m_CurrentlyAllocated < m_MaxBuffers) {\r
// we need to alocate a new buffer\r
- rc = AllocateBuffer(ppBufferDescriptor);\r
+ rc = BufferDescriptor::AllocateBuffer(ppBufferDescriptor, m_MaxMessageSize, SEND_BUFFERS_ALLOCATION_TAG);\r
if (!NT_SUCCESS(rc)) {\r
SDP_PRINT(SDP_ERR, 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
} \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
(m_QueuedPackets.Size() == 0 )){\r
// we can send right away (no need to wait for anything)\r
rc = SendBuffer(pBufferDescriptor);\r
+ if (!NT_SUCCESS(rc)) {\r
+ SDP_PRINT(SDP_ERR, SDP_BUFFER_POOL, ("SendBuffer failed rc = 0x%x\n", rc ));\r
+ m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList);\r
+ goto Cleanup;\r
+ } \r
+ // We have finished our job\r
goto Cleanup;\r
} else {\r
// we put the buffer in the queued list\r
// than one thread).\r
}\r
\r
-\r
+/*\r
+ called when a send packet has finished.\r
+*/\r
VOID \r
BufferPool::ReturnBuffer(BufferDescriptor *pBufferDescriptor)\r
{\r
rc = SendBuffer(pBufferDescriptor);\r
if (!NT_SUCCESS(rc)) {\r
SDP_PRINT(SDP_ERR, SDP_BUFFER_POOL, ("SendBuffer failed rc = 0x%x\n", rc ));\r
+ m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList);\r
goto Cleanup;\r
} \r
}\r
while (m_FreePackets.Size() > 0 ) {\r
item = m_FreePackets.RemoveHeadList();\r
pBufferDescriptor = CONTAINING_RECORD(item, BufferDescriptor , BuffersList);\r
- DeAllocateBuffer(pBufferDescriptor);\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
- DeAllocateBuffer(pBufferDescriptor);\r
- }\r
-\r
-}\r
-\r
-NTSTATUS \r
-BufferPool::AllocateBuffer(BufferDescriptor ** ppBufferDescriptor)\r
-{\r
- SDP_PRINT(SDP_TRACE, SDP_BUFFER_POOL, ("this = 0x%p \n",this));\r
- AssertLocked();\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
- SEND_BUFFERS_ALLOCATION_TAG\r
- );\r
- if (pBufferDescriptor == NULL) {\r
- SDP_PRINT(SDP_ERR, SDP_BUFFER_POOL, ("ExAllocatePoolWithTag failed \n"));\r
- rc = STATUS_NO_MEMORY;\r
- goto Cleanup;\r
- }\r
-\r
- // Allocate the buffer itself\r
- pBufferDescriptor->pBuffer = \r
- ExAllocatePoolWithTag(\r
- NonPagedPool ,\r
- m_MaxMessageSize, \r
- SEND_BUFFERS_ALLOCATION_TAG\r
- );\r
-\r
- if (pBufferDescriptor->pBuffer == NULL) {\r
- SDP_PRINT(SDP_ERR, SDP_BUFFER_POOL, ("ExAllocatePoolWithTag failed \n"));\r
- rc = STATUS_NO_MEMORY;\r
- goto Cleanup;\r
+ BufferDescriptor::DeAllocateBuffer(pBufferDescriptor, SEND_BUFFERS_ALLOCATION_TAG);\r
}\r
\r
- pBufferDescriptor->BufferSize = m_MaxMessageSize;\r
- pBufferDescriptor->DataSize = 0;\r
- pBufferDescriptor->mr_handle = NULL;\r
-\r
-\r
-Cleanup:\r
- if (NT_SUCCESS(rc)) {\r
- m_CurrentlyAllocated++;\r
- } else {\r
- if (pBufferDescriptor != NULL) {\r
- if (pBufferDescriptor->pBuffer != NULL) {\r
- ExFreePoolWithTag(pBufferDescriptor->pBuffer, SEND_BUFFERS_ALLOCATION_TAG);\r
- }\r
- ExFreePoolWithTag(pBufferDescriptor, SEND_BUFFERS_ALLOCATION_TAG);\r
- pBufferDescriptor = NULL;\r
- } \r
- } \r
- *ppBufferDescriptor = pBufferDescriptor;\r
- return rc;\r
-}\r
-\r
-VOID \r
-BufferPool::DeAllocateBuffer(BufferDescriptor *pBufferDescriptor)\r
-{\r
- ExFreePoolWithTag(pBufferDescriptor->pBuffer, SEND_BUFFERS_ALLOCATION_TAG);\r
- ExFreePoolWithTag(pBufferDescriptor, SEND_BUFFERS_ALLOCATION_TAG);\r
}\r
\r
NTSTATUS\r
\r
msg_hdr_bsdh *pHeader = (msg_hdr_bsdh *) pBufferDescriptor->pBuffer;\r
\r
- pHeader->recv_bufs = QP_ATTRIB_RQ_DEPTH; //?????recv_bufs = conn->l_advt_bf;\r
+ pHeader->recv_bufs = m_pSdpSocket->m_RecvBufferPool.GetCurrentlyPostedRecievedBuffers(); //?????recv_bufs = conn->l_advt_bf;\r
pHeader->size = pBufferDescriptor->DataSize + sizeof msg_hdr_bsdh;\r
- pHeader->seq_num = 1;//?????++conn->send_seq;\r
- pHeader->seq_ack = 0;//????conn->advt_seq;\r
+ pHeader->seq_num = GetSendSeq();\r
+ pHeader->seq_ack = m_pSdpSocket->m_RecvBufferPool.GetRecvSeq();//????conn->advt_seq;\r
+ m_AdvtSeq = pHeader->seq_ack;// Currently only for debug\r
pHeader->mid = SDP_MID_DATA;\r
pHeader->flags = SDP_MSG_FLAG_NON_FLAG;\r
/*\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
+\r
private:\r
int size;\r
LIST_ENTRY m_Data;\r
// Each buffer starts with msg_hdr_bsdh and is followed by the actual data\r
class BufferDescriptor {\r
public:\r
- NTSTATUS WriteData(char *pData, uint32_t size) {\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
+ ASSERT(Size <= BufferSize - sizeof msg_hdr_bsdh);\r
char *pStart = (char *) pBuffer + sizeof msg_hdr_bsdh;\r
- rc = CopyFromUser(pStart, pData, size);\r
+ rc = CopyFromUser(pStart, pData, Size);\r
if (!NT_SUCCESS(rc)) {\r
SDP_PRINT(SDP_ERR, SDP_BUFFER_POOL, ("CopyFromUser failed rc = 0x%x\n", rc ));\r
goto Cleanup;\r
} \r
- DataSize = size;\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(SDP_ERR, 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
+ }\r
\r
// Each buffer starts with bsdh_hdr structure\r
VOID *pBuffer; // A pointer to the actual place that we put the data\r
- int BufferSize; // The total size of the buffer\r
- int DataSize; // The size of the data that we have allocated\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
- ib_mr_handle_t mr_handle; // A handle to the registared memory,\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
class BufferPool {\r
\r
public:\r
\r
+ BufferPool();\r
+\r
NTSTATUS Init(\r
int MaxBuffers, \r
int MaxConcurrentSends, \r
NTSTATUS SendBuffersIfCan();\r
\r
VOID ShutDown();\r
- \r
-private:\r
\r
- NTSTATUS AllocateBuffer(BufferDescriptor ** ppBufferDescriptor);\r
+ uint32_t GetSendSeq() {return m_SendSeq++;}\r
+ uint32_t GetAdvtSeq() {return m_AdvtSeq;}\r
\r
- VOID DeAllocateBuffer(BufferDescriptor *pBufferDescriptor);\r
+ \r
+ \r
+private:\r
\r
NTSTATUS SendBuffer(BufferDescriptor *pBufferDescriptor);\r
\r
// Global data about this connection\r
- int m_MaxBuffers; // The maximum number of buffers that we allow for this QP\r
+ int m_MaxBuffers; // The maximum number of buffers that we allow for this QP (to be allocated)\r
int m_MaxConcurrentSends; // The total numbers of sends that are allowd for the QP\r
- int m_MaxMessageSize; // The maximum buffer size that we allw\r
+ int m_MaxMessageSize; // The maximum buffer size that we allow\r
\r
int m_CurrentlySentBuffers; // Number of buffers that we have sent, and didn't get an ack yet\r
int m_CurrentlyAllocated; // The number of buffers that we have allocated\r
KEVENT m_WaitingClients; // switch to a linked list\r
bool m_ClientWaiting;\r
\r
-#if DBG\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
+\r
SdpSocket *m_pSdpSocket;\r
-#endif //DBG\r
\r
VOID AssertLocked();\r
\r
IN PDRIVER_OBJECT pDriverObject \r
) \r
{\r
- SDP_PRINT(SDP_TRACE, SDP_DRIVER, ("DriverUnload called pDriverObject = 0x%x\n", pDriverObject ));\r
+ SDP_PRINT(SDP_TRACE, SDP_DRIVER, ("called pDriverObject = 0x%x\n", pDriverObject ));\r
ib_api_status_t ib_status;\r
\r
\r
UNICODE_STRING DevName, LinkName;\r
int i;\r
\r
- SDP_PRINT(SDP_TRACE, SDP_DRIVER, ("DriverEntry called\n" ));\r
+ SDP_PRINT(SDP_TRACE, SDP_DRIVER, ("called\n" ));\r
\r
// fill the device functions\r
pDriverObject->DriverUnload = DriverUnload;\r
NTSTATUS rc = STATUS_SUCCESS;\r
SdpUserFile *pSdpUserFile = NULL;\r
SdpSocket *pSdpSocket = NULL;\r
-\r
- WspConnectIn *pWspConnectIn = NULL;\r
- WspConnectOut *pWspConnectOut = NULL;\r
\r
switch (IoControlCode) {\r
case IOCTL_WSP_SOCKET :\r
- SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("DispatchDeviceIoControl IOCTL_WSP_SOCKET recieved\n" )); \r
+ {\r
+ SDP_PRINT(SDP_DEBUG, 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
SDP_PRINT(SDP_ERR, SDP_DRIVER, ("new SdpSocket failed rc = 0x%x\n", rc )); \r
goto Cleanup;\r
}\r
- rc = pSdpSocket->Init((WspSocketIn *)pInputBuffer, (WspSocketOut *)pOutputBuffer);\r
+ rc = pSdpSocket->Init(&wspSocketIn, pWspSocketOut);\r
if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpSocket->Init failed rc = 0x%x\n", rc )); \r
+ SDP_PRINT(SDP_ERR, 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(SDP_ERR, SDP_DRIVER, ("pSdpUserFile->AddSocket failed rc = 0x%x\n", rc )); \r
+ SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpUserFile->AddSocket failed rc = 0x%x\n", rc ));\r
+ pSdpSocket->Shutdown();\r
goto Cleanup;\r
- }\r
- OutputDataSize = sizeof (WspSocketOut);\r
-\r
+ } \r
+ }\r
break;\r
\r
case IOCTL_WSP_CONNECT :\r
- SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("DispatchDeviceIoControl IOCTL_WSP_CONNECT recieved\n" )); \r
+ {\r
+ SDP_PRINT(SDP_DEBUG, 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
- pWspConnectIn = (WspConnectIn *) pInputBuffer;\r
- pWspConnectOut = (WspConnectOut *) pOutputBuffer;\r
+ WspConnectIn wspConnectIn = *(WspConnectIn *) pInputBuffer;\r
+ WspConnectOut *pWspConnectOut = (WspConnectOut *) pOutputBuffer;\r
pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
- pSdpSocket = pSdpUserFile->SocketByPointer(pWspConnectIn->pSocket);\r
+ pSdpSocket = pSdpUserFile->SocketByPointer(wspConnectIn.pSocket);\r
if (pSdpSocket == NULL) {\r
- SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("DispatchDeviceIoControl IOCTL_WSP_CONNECT socket %x not found\n",pWspConnectIn->pSocket)); \r
+ SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("IOCTL_WSP_CONNECT socket %x 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(pWspConnectIn, pWspConnectOut);\r
+ rc = pSdpSocket->WSPConnect(&wspConnectIn, pWspConnectOut);\r
if (!NT_SUCCESS(rc)) {\r
SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpSocket->WSPConnect failed rc = 0x%x\n", rc )); \r
goto Cleanup;\r
}\r
+ }\r
break;\r
\r
case IOCTL_WSP_SEND :\r
OutputDataSize = sizeof (WspSendOut);\r
\r
// get the socket based on the users pointer\r
- WspSendIn *pWspSendIn = (WspSendIn *) pInputBuffer;\r
+ WspSendIn wspSendIn = *(WspSendIn *) pInputBuffer;\r
WspSendOut *pWspSendOut = (WspSendOut *) pOutputBuffer;\r
pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext;\r
- pSdpSocket = pSdpUserFile->SocketByPointer(pWspSendIn->pSocket);\r
+ pSdpSocket = pSdpUserFile->SocketByPointer(wspSendIn.pSocket);\r
if (pSdpSocket == NULL) {\r
- SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("IOCTL_WSP_SEND socket %x not found\n",pWspConnectIn->pSocket)); \r
+ SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("IOCTL_WSP_SEND socket %x not found\n",wspSendIn.pSocket)); \r
// This is a well defined winsock error\r
- pWspConnectOut->Errno = WSAENOTSOCK;\r
+ pWspSendOut->Errno = WSAENOTSOCK;\r
goto Cleanup;\r
}\r
- rc = pSdpSocket->WSPSend(pWspSendIn, pWspSendOut);\r
+ rc = pSdpSocket->WSPSend(&wspSendIn, pWspSendOut);\r
if (!NT_SUCCESS(rc)) {\r
SDP_PRINT(SDP_ERR, 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(SDP_DEBUG, 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(SDP_DEBUG, SDP_DRIVER, ("IOCTL_WSP_RECV socket %x 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(SDP_ERR, SDP_DRIVER, ("pSdpSocket->WSPRecv failed rc = 0x%x\n", rc )); \r
+ goto Cleanup;\r
+ }\r
+ }\r
+ break;\r
+\r
\r
\r
default:\r
// This is an unrecgnized IOCTL\r
ASSERT(FALSE);\r
- SDP_PRINT(SDP_ERR, SDP_DRIVER, ("DispatchDeviceIoControl unknow IOCTL code = 0x%x\n", IoControlCode ));\r
+ SDP_PRINT(SDP_ERR, SDP_DRIVER, ("unknow IOCTL code = 0x%x\n", IoControlCode ));\r
rc = STATUS_INVALID_PARAMETER;\r
goto Cleanup;\r
\r
\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
IN PLARGE_INTEGER Timeout OPTIONAL\r
)\r
{\r
- NTSTATUS rc = KeWaitForSingleObject(\r
- Object,\r
- WaitReason,\r
- WaitMode,\r
- Alertable,\r
- Timeout\r
- );\r
- if (!NT_SUCCESS(rc)) {\r
- ASSERT(FALSE);\r
- SDP_PRINT(SDP_ERR, 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
+ 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(SDP_ERR, 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(SDP_WARN, SDP_SOCKET, ("KeWaitForSingleObject was stoped because of STATUS_USER_APC\n" ));\r
+ }\r
+ }\r
+ if (i == 20) {\r
+ SDP_PRINT(SDP_ERR, SDP_SOCKET, ("!!!! KeWaitForSingleObject was Exhausted STATUS_USER_APC\n" ));\r
+\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
return rc;\r
}\r
\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
+ RtlCopyMemory( p_dest, p_src, count );\r
+ return CL_SUCCESS;\r
+ }\r
+ __except(EXCEPTION_EXECUTE_HANDLER)\r
+ {\r
+ SDP_PRINT(SDP_ERR, 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
void* __cdecl operator new(size_t n ) throw() {\r
return ExAllocatePoolWithTag(NonPagedPool , n, GLOBAL_ALLOCATION_TAG);\r
\r
USHORT nthos(USHORT in);\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
NTSTATUS \r
MyKeWaitForSingleObject(\r
IN PVOID Object,\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
+\r
// This error codes are taken from winsock2.h (the file can not)\r
// be included from user mode\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
+\r
\r
const int SEND_CB_CALLED = 0x00000001;\r
const int RECV_CB_CALLED = 0x00000002;\r
const int SHUTDOWN_HANDELED = 0x00000008;\r
const int ERROR_SIGNALLED = 0x00000010;\r
\r
-const int DPC_FLAGS = SEND_CB_CALLED | SEND_CB_CALLED;\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
KeInitializeEvent(&m_Event, NotificationEvent , TRUE);\r
KeInitializeSpinLock(&m_SpinLock);\r
m_SendCBHandler = NULL;\r
- m_ClientWaiting = false;\r
+ m_RecvCBHandler = NULL;\r
+ m_NumberOfClientWaiting = 0;\r
}\r
\r
- VOID Init(SendCBHandler SendCB, SdpSocket *pSdpSocket)\r
+ VOID Init(SendCBHandler SendCB, RecvCBHandler RecvCB, SdpSocket *pSdpSocket)\r
{\r
m_SendCBHandler = SendCB;\r
m_pSdpSocket = pSdpSocket;\r
+ m_RecvCBHandler = RecvCB;\r
}\r
\r
/*\r
\r
if (m_InUse) {\r
// We have to release the spinlock and wait on the event\r
- m_ClientWaiting = true;\r
+ m_NumberOfClientWaiting++;\r
KeReleaseSpinLock(&m_SpinLock, OldIrql);\r
rc = MyKeWaitForSingleObject(&m_Event, UserRequest, UserMode, false, NULL);\r
if (( rc == STATUS_ALERTED ) ||( rc == STATUS_USER_APC )) {\r
KeClearEvent(&m_Event);\r
OldFlags = m_flags;\r
ResetFlags(m_flags);\r
- m_ClientWaiting = false;\r
+ m_NumberOfClientWaiting--;\r
KeReleaseSpinLock(&m_SpinLock, OldIrql);\r
rc = HandleFlags(OldFlags);\r
if (!NT_SUCCESS(rc)) {\r
if (!SomethingToHandle(OldFlags)) {\r
// We can safely quit the lock\r
m_InUse = false;\r
+ KeReleaseSpinLock(&m_SpinLock, OldIrql);\r
+ break;\r
}\r
KeReleaseSpinLock(&m_SpinLock, OldIrql);\r
- if (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(SDP_ERR, 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
+ 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(SDP_ERR, SDP_LOCK, ("HandleFlags failed rc = 0x%x\n", rc ));\r
+ ASSERT(m_flags & ERROR_SIGNALLED);\r
}\r
- break;\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
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
NTSTATUS rc = STATUS_SUCCESS;\r
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);\r
KeAcquireSpinLock(&m_SpinLock, &OldIrql);\r
- if (m_InUse || m_ClientWaiting ) {\r
+ if (m_InUse || (m_NumberOfClientWaiting > 0 ) ) {\r
m_flags |= flags;\r
KeReleaseSpinLock(&m_SpinLock, OldIrql);\r
return false;\r
}\r
- m_InUse = true;\r
- // In this lock, we only handle DPC events\r
- OldFlags = (m_flags & DPC_FLAGS) | flags;\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(SDP_ERR, SDP_LOCK, ("HandleFlags failed rc = 0x%x\n", rc ));\r
- ASSERT(m_flags & ERROR_SIGNALLED);\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(SDP_ERR, SDP_LOCK, ("HandleFlags failed rc = 0x%x\n", rc ));\r
+ ASSERT(m_flags & ERROR_SIGNALLED);\r
+ }\r
+ KeAcquireSpinLock(&m_SpinLock, &OldIrql);\r
+ int xxx = m_flags;\r
+ if ((m_flags & DPC_FLAGS) == 0) {\r
+ // No flags to handle from the DPC layer\r
+ ASSERT(m_flags == 0);\r
+ break;\r
+ }\r
}\r
- KeAcquireSpinLock(&m_SpinLock, &OldIrql);\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
// We need to handle the send CB\r
rc = m_SendCBHandler(m_pSdpSocket);\r
if (!NT_SUCCESS(rc)) {\r
- SDP_PRINT(SDP_ERR, SDP_BUFFER_POOL, ("SendBuffer failed rc = 0x%x\n", rc ));\r
+ SDP_PRINT(SDP_ERR, 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(SDP_ERR, 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
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
\r
\r
bool m_InUse; // Tells if this lock has any user\r
int m_flags; // call backs that were recieved\r
- bool m_ClientWaiting; // True if there is a client waiting to be served\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
--- /dev/null
+/* Copyright mellanox */\r
+#pragma warning(disable: 4244 ) \r
+\r
+#include "preCompile.h"\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
+}\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(SDP_TRACE, SDP_BUFFER_POOL, ("this = 0x%p \n",this));\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
+#if DBG \r
+ m_pSdpSocket = pSdpSocket;\r
+#endif\r
+ return STATUS_SUCCESS;\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(SDP_TRACE, SDP_BUFFER_POOL, ("this = 0x%p pBufferDescriptor = 0x%x error = %s\n"\r
+ ,this, pBufferDescriptor, error ? "true" : "false"));\r
+ AssertLocked();\r
+ NTSTATUS rc = STATUS_SUCCESS;\r
+ if (error) {\r
+ // Not much that we can do in this case (only return the packet)\r
+ m_FreePackets.InsertTailList(&pBufferDescriptor->BuffersList);\r
+ goto Cleanup;\r
+ }\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
+ 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
+ // ???? Handle state changes here ????\r
+\r
+ //???? we will also have to wake up the clients of the send ???????\r
+\r
+\r
+ m_CurrentlyPostedRecievedBuffers--;\r
+ ASSERT(m_CurrentlyPostedRecievedBuffers >= 0);\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(SDP_ERR, SDP_BUFFER_POOL, ("RecieveIfCan failed rc = 0x%x\n", rc ));\r
+ goto Cleanup;\r
+ } \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
+ )\r
+{\r
+ SDP_PRINT(SDP_TRACE, SDP_BUFFER_POOL, ("this = 0x%p FirstBuffer = %s\n",this,\r
+ FirstBuffer ? "TRUE" : "FALSE"));\r
+ AssertLocked();\r
+ bool BufferFreed = false;\r
+ *Copied = 0;\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 userd 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(SDP_ERR, 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(SDP_ERR, 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
+ // 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(SDP_TRACE, SDP_BUFFER_POOL, ("this = 0x%p \n",this));\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(SDP_TRACE, SDP_BUFFER_POOL, ("this = 0x%p \n",this));\r
+ AssertLocked();\r
+ BufferDescriptor *pBufferDescriptor = NULL;\r
+ NTSTATUS rc = STATUS_SUCCESS;\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, SEND_BUFFERS_ALLOCATION_TAG);\r
+ if (!NT_SUCCESS(rc)) {\r
+ SDP_PRINT(SDP_ERR, 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(SDP_ERR, SDP_BUFFER_POOL, ("PostReceiveBuffer 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
+ SDP_PRINT(SDP_TRACE, SDP_BUFFER_POOL, ("this = 0x%p \n",this));\r
+ //???? AssertLocked();\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, SEND_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, SEND_BUFFERS_ALLOCATION_TAG);\r
+ }\r
+}\r
+\r
+NTSTATUS \r
+RecvPool::PostReceiveBuffer(BufferDescriptor *pBufferDescriptor)\r
+{\r
+ SDP_PRINT(SDP_TRACE, SDP_BUFFER_POOL, ("this = 0x%p \n",this));\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(SDP_ERR, 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
+ m_pSdpSocket->AssertLocked();\r
+#endif\r
+}\r
+\r
+\r
--- /dev/null
+/* Copyright mellanox */\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
+ );\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 ShutDown();\r
+\r
+ uint16_t GetCurrentlyPostedRecievedBuffers(){return 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 sends 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
+ 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
+\r
+#if DBG\r
+ SdpSocket *m_pSdpSocket;\r
+#endif //DBG\r
+\r
+VOID AssertLocked();\r
+\r
+};\r
+\r
+#endif // H_SDP_RECV_POOL_H\r
+\r
\r
NTSTATUS sdp_cm_hello_ack_check(struct sdp_msg_hello_ack *hello_ack);\r
static NTSTATUS __send_cb2(SdpSocket * pSdpSocket);\r
+static NTSTATUS __recv_cb2(SdpSocket * pSdpSocket);\r
\r
static void AL_API\r
cm_rej_callback(IN ib_cm_rej_rec_t *p_cm_rej_rec )\r
WspSocketOut *pSocketOutParam)\r
{\r
NTSTATUS rc = STATUS_SUCCESS;\r
- SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("SdpSocket::Init this = 0x%p\n", this));\r
+ SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%p\n", this));\r
\r
m_CreationFlags = pSocketInParam->dwFlags;\r
\r
- m_Lock.Init(__send_cb2, this);\r
+ m_Lock.Init(__send_cb2, __recv_cb2, 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
return rc;\r
}\r
\r
-# if 0\r
-struct sdpc_buff {\r
-// struct sdpc_buff *next;\r
-// struct sdpc_buff *prev;\r
-// u32 type; /* element type. (for generic queue) */\r
-// struct sdpc_buff_q *pool; /* pool currently holding this buffer. */\r
-// int (*release)(struct sdpc_buff *buff); /* release the object */\r
- /*\r
- * primary generic data pointers\r
- */\r
- void *head; /* first byte of data buffer */\r
- void *data; /* first byte of valid data in buffer */\r
- void *tail; /* last byte of valid data in buffer */\r
- void *end; /* last byte of data buffer */\r
- /*\r
- * Experimental\r
- */\r
- uint32_t flags; /* Buffer flags */\r
- /*\r
- * Protocol specific data\r
- */\r
- struct msg_hdr_bsdh *bsdh_hdr; /* SDP header (BSDH) */\r
- uint32_t data_size; /* size of just data in the buffer */\r
- uint64_t wrid; /* IB work request ID */\r
- /*\r
- * IB specific data (The main buffer pool sets the lkey when \r
- * it is created)\r
- */\r
- uint64_t real; /* component of scather/gather list (address) */\r
- uint32_t size; /* component of scather/gather list (lenght) */\r
- uint32_t lkey; /* component of scather/gather list (key) */\r
-};\r
-\r
-const int BUFFER_SIZE = 4000 + 16;//65536;\r
-\r
-#define SDP_BUFF_F_UNSIG 0x0001 /* unsignalled buffer */\r
-\r
-#define SDP_BUFF_F_GET_UNSIG(buff) ((buff)->flags & SDP_BUFF_F_UNSIG)\r
-#define SDP_BUFF_F_SET_UNSIG(buff) ((buff)->flags |= SDP_BUFF_F_UNSIG)\r
-#define SDP_BUFF_F_CLR_UNSIG(buff) ((buff)->flags &= (~SDP_BUFF_F_UNSIG))\r
-\r
-#endif \r
-\r
NTSTATUS SdpSocket::WSPSend(\r
WspSendIn *pWspSendIn,\r
WspSendOut *pWspSendOut\r
)\r
{ \r
SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%p \n",this));\r
- char temp[4000];\r
- memcpy(temp,"abcd",5);\r
\r
NTSTATUS rc = STATUS_SUCCESS;\r
BufferDescriptor * pBufferDescriptor = NULL;\r
bool Locked = false;\r
PRKEVENT pBuffersEvent = NULL;\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(SDP_WARN, SDP_SOCKET, ("this = 0x%p - zero size send \n",this));\r
+ goto Cleanup;\r
+ }\r
+\r
while (Coppied < pWspSendIn->BufferSize) {\r
if ((Locked == false) && !m_Lock.Lock()) {\r
SDP_PRINT(SDP_ERR, SDP_SOCKET, ("Failed to lock this = 0x%p \n",this));\r
Cleanup:\r
if (NT_SUCCESS(rc) ) {\r
pWspSendOut->Errno = 0;\r
- pWspSendOut->NumberOfBytesSent = pWspSendIn->BufferSize;\r
+ ASSERT(pWspSendIn->BufferSize == Coppied);\r
+ pWspSendOut->NumberOfBytesSent = Coppied;\r
} else {\r
// Make sure that we have the error setted\r
ASSERT(pWspSendOut->Errno != 0); // BUGBUG: Need to make sure that this\r
return rc;\r
}\r
\r
-\r
-#if 0\r
-//Naive send implmentation.\r
-NTSTATUS SdpSocket::WSPSend(\r
- WspSendIn *pWspSendIn,\r
- WspSendOut *pWspSendOut\r
+NTSTATUS \r
+SdpSocket::WSPRecv(\r
+ WspRecvIn *pWspRecvIn,\r
+ WspRecvOut *pWspRecvOut\r
)\r
{\r
- NTSTATUS rc = STATUS_SUCCESS;\r
SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%p \n",this));\r
\r
- ib_mr_create_t mr_create;\r
-\r
- /* Memory registration parameters, returned by ib_reg_mem. */\r
- char *BufferStart = NULL;\r
- uint32_t lkey;\r
- uint32_t rkey;\r
- ib_mr_handle_t mr_handle = NULL;\r
-\r
- \r
-\r
- // First allocate a buffer and a buffer descriptor\r
- sdpc_buff *buff = new sdpc_buff;\r
- ASSERT(buff != NULL);\r
- BufferStart = new CHAR [BUFFER_SIZE]; \r
- ASSERT(BufferStart != NULL);\r
- buff->head = BufferStart;\r
-\r
- // we leave enough space for holding the header of the request\r
- buff->end = (CHAR *)(buff->head) + BUFFER_SIZE;\r
- buff->head = (char *)(buff->head) + 0x10;\r
- \r
- buff->data = buff->head;\r
- buff->tail = buff->head;\r
- buff->lkey = 0;\r
- buff->real = 0;\r
- buff->size = 0;\r
-\r
- // Copy the data to the buffer\r
- memcpy(buff->data, "5678",5);\r
- buff->tail = (char *)(buff->tail) + 5;\r
- \r
-\r
- // Register the buffer\r
- mr_create.vaddr = BufferStart;\r
- mr_create.length = BUFFER_SIZE;\r
- mr_create.access_ctrl = IB_AC_LOCAL_WRITE;\r
-\r
- ib_api_status_t ib_status = ib_reg_mem( m_pd, &mr_create, &lkey, &rkey, &mr_handle );\r
- ASSERT(ib_status == IB_SUCCESS);\r
- \r
-\r
-\r
- \r
-\r
- // Send the buffer.\r
- buff->data = (char *)(buff->head) - sizeof(struct msg_hdr_bsdh);\r
- buff->bsdh_hdr = (struct msg_hdr_bsdh *) buff->data;\r
- buff->bsdh_hdr->mid = SDP_MID_DATA;\r
- buff->bsdh_hdr->flags = SDP_MSG_FLAG_NON_FLAG;\r
- buff->bsdh_hdr->size = BUFFER_SIZE;\r
-\r
-\r
- /*\r
- * signalled? With no delay turned off, data transmission may be\r
- * waiting for a send completion.\r
- */\r
- SDP_BUFF_F_SET_UNSIG(buff);\r
-\r
- buff->wrid = 0;//conn->send_wrid++;\r
-\r
- buff->lkey = lkey;\r
- buff->bsdh_hdr->recv_bufs = QP_ATTRIB_RQ_DEPTH; //?????recv_bufs = conn->l_advt_bf;\r
-//?????? put this in buff->bsdh_hdr->size = (char *)buff->tail - (char *)buff->data;\r
- buff->bsdh_hdr->seq_num = 1;//?????++conn->send_seq;\r
- buff->bsdh_hdr->seq_ack = 0;//????conn->advt_seq;\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
\r
- /*\r
- * endian swap\r
- */\r
- sdp_msg_swap_bsdh(buff->bsdh_hdr);\r
- buff->real = (uint64_t)(void* __ptr64)BufferStart;\r
- buff->size = BUFFER_SIZE;\r
- \r
- /*\r
- * save the buffer for the event handler.\r
- */\r
-#if 0\r
- result = sdp_buff_q_put_tail(&conn->send_post, buff);\r
- if (result < 0) {\r
- sdp_dbg_warn(conn, "Error <%d> queueing send buffer", result);\r
- goto done;\r
+ if (pWspRecvIn->BufferSize == 0) {\r
+ SDP_PRINT(SDP_WARN, SDP_SOCKET, ("this = 0x%p - zero size recv \n",this));\r
+ goto Cleanup;\r
}\r
-#endif \r
- /*\r
- * post send\r
- */\r
-/* \r
- buff->size = buff->tail - buff->data;\r
- buff->real = dma_map_single(conn->ca->dma_device,\r
- buff->data,\r
- buff->size,\r
- PCI_DMA_TODEVICE);\r
- send_param.next = NULL;\r
- send_param.wr_id = buff->wrid;\r
- send_param.sg_list = (struct ib_sge *)&buff->real;\r
- send_param.num_sge = 1;\r
- send_param.opcode = IB_WR_SEND;\r
-*/\r
- ib_send_wr_t send_wr;\r
\r
- send_wr.p_next = NULL;\r
- send_wr.wr_id = buff->wrid;//?????(uint64_t) (uintptr_t) wr;\r
- send_wr.wr_type = WR_SEND;\r
- send_wr.send_opt = IB_SEND_OPT_SIGNALED;//IB_SEND_OPT_INLINE;//socket_info->send_opt;\r
-\r
-\r
- ib_local_ds_t ds_array;\r
- ds_array.length = buff->size;\r
- ds_array.lkey = buff->lkey;\r
- ds_array.vaddr = buff->real;\r
-\r
- send_wr.num_ds = 1;\r
- send_wr.ds_array = &ds_array;\r
- \r
- ib_status = ib_post_send(m_qp, &send_wr, NULL);\r
- ASSERT(ib_status == IB_SUCCESS);\r
+ while (Coppied < pWspRecvIn->BufferSize) {\r
+ if ((Locked == false) && !m_Lock.Lock()) {\r
+ SDP_PRINT(SDP_ERR, 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
- \r
+ rc = m_RecvBufferPool.GetData(\r
+ pWspRecvIn->pData + Coppied, \r
+ pWspRecvIn->BufferSize - Coppied, \r
+ &ThisCopy, \r
+ &pBuffersEvent, \r
+ First\r
+ );\r
+ if (!NT_SUCCESS(rc)) {\r
+ SDP_PRINT(SDP_ERR, 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
+ First = false;\r
+ Coppied += ThisCopy;\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(SDP_ERR, SDP_SOCKET, ("m_Lock.Unlock() failed rc = 0x%x\n", rc ));\r
+ goto Cleanup;\r
+ }\r
\r
- // Wait for the notification of send compleated ?????\r
- rc = MyKeWaitForSingleObject(\r
- &m_SendCompleteEvent,\r
+ rc = MyKeWaitForSingleObject(\r
+ pBuffersEvent,\r
UserRequest,\r
UserMode,\r
FALSE,\r
- NULL); \r
- KeResetEvent(&m_SendCompleteEvent);\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(SDP_WARN, 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 buffer again\r
+ continue;\r
+ }\r
+ } \r
+ ASSERT(Locked == true);\r
+ rc = m_Lock.Unlock();\r
+ if (!NT_SUCCESS(rc)) {\r
+ SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_Lock.Unlock() failed rc = 0x%x\n", rc ));\r
+ goto Cleanup;\r
+ }\r
\r
-//Cleanup:\r
- if (mr_handle != NULL) {\r
- ib_dereg_mr(mr_handle);\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
+ // is indeed the case.\r
}\r
- delete [] BufferStart;\r
- delete buff; \r
- pWspSendOut->Errno = 0;\r
- pWspSendOut->NumberOfBytesSent = pWspSendIn->BufferSize;\r
+ // Currently in any case, the flags are not being used:\r
+ pWspRecvOut->dwFlags = 0; \r
+ return rc;\r
\r
- return rc; \r
}\r
\r
-#endif\r
-\r
-\r
NTSTATUS SdpSocket::WSPConnect(\r
WspConnectIn *pWspConnectIn,\r
WspConnectOut *pWspConnectOut\r
ib_api_status_t ib_status;\r
NTSTATUS rc = STATUS_SUCCESS;\r
\r
- SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("SdpSocket::CmSendRTU this = 0x%p \n", this));\r
+ SDP_PRINT(SDP_TRACE, 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(SDP_WARN, SDP_SOCKET, ("SdpSocket::CmSendRTU this = 0x%p invalid state %s\n", this, SS2String(m_state)));\r
+ SDP_PRINT(SDP_WARN, SDP_SOCKET, ("this = 0x%p invalid state %s\n", this, SS2String(m_state)));\r
rc = STATUS_UNEXPECTED_IO_ERROR;\r
goto Cleanup;\r
} \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(SDP_ERR, SDP_SOCKET, ("m_RecvBufferPool.Init failed rc = 0x%x\n", rc ));\r
+ goto Cleanup;\r
+ }\r
+\r
#if 0\r
/*\r
* read remote information\r
}\r
\r
// We now start the recieve processing\r
- RecieveOnce();\r
+\r
+ rc = m_Lock.Lock();\r
+ if (!NT_SUCCESS(rc)) {\r
+ SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_RecvBufferPool.Init 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(SDP_ERR, SDP_SOCKET, ("m_RecvBufferPool.Init failed rc = 0x%x\n", rc ));\r
+ goto Cleanup;\r
+ }\r
\r
Cleanup: \r
return rc;\r
}\r
\r
\r
-//????????? Let's implmeant a naive read\r
-// BUGBUG: based on __recv_cb - need to implment\r
-static void\r
-__recv_cb1(\r
+VOID\r
+SdpSocket::__recv_cb1(\r
IN const ib_cq_handle_t h_cq,\r
IN void *cq_context )\r
{\r
SdpSocket *pSocket = (SdpSocket *) cq_context;\r
- //pSocket->m_Lock.SignalCB(RECV_CB_CALLED);\r
-\r
- pSocket->__recv_cb2();\r
- \r
+ pSocket->m_Lock.SignalCB(RECV_CB_CALLED);\r
}\r
-char g_Recieve[6000];\r
\r
-VOID \r
-SdpSocket::__recv_cb2()\r
+NTSTATUS\r
+SdpSocket::recv_cb()\r
{\r
+ SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("this = 0x%p \n", this));\r
+ NTSTATUS rc = STATUS_SUCCESS, rc1 = STATUS_SUCCESS; \r
if (m_Lock.IsShutdownSignaled()) {\r
- return;\r
+ return 0; //?????????????????? this will cause a leak ??????\r
}\r
\r
- ib_api_status_t status;\r
+ ib_api_status_t ib_status;\r
ib_wc_t wc[QP_ATTRIB_RQ_DEPTH], *p_free, *p_wc1;\r
uint32_t pkt_cnt, recv_cnt = 0;\r
size_t i;\r
-\r
+ BufferDescriptor *pBufferDescriptor = NULL;\r
\r
for( i = 0; i < QP_ATTRIB_RQ_DEPTH; i++ )\r
wc[i].p_next = &wc[i + 1];\r
/* If we get here, then the list of WCs is intact. */\r
p_free = wc;\r
\r
- status = ib_poll_cq( m_rcq, &p_free, &p_wc1 );\r
- CL_ASSERT( status == IB_SUCCESS || status == IB_NOT_FOUND );\r
-\r
- /* Look at the payload now and filter ARP and DHCP packets. */\r
- //recv_cnt += __recv_mgr_filter( p_port, p_wc, &done_list, &bad_list );\r
- if (status == IB_SUCCESS)\r
- {\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 );\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(SDP_ERR, 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);\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(SDP_ERR, 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
- msg_hdr_bsdh *pHeader = (msg_hdr_bsdh *)g_Recieve;\r
+ if (len < sizeof msg_hdr_bsdh) {\r
+ // This is a message that is not big enough\r
+ SDP_PRINT(SDP_ERR, 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->mid == 0xff && pHeader->size == 0x10);\r
+ ASSERT(pHeader->size >= 0x10);\r
+ if (len != pHeader->size) {\r
+ // This is a message that is not formated well\r
+ SDP_PRINT(SDP_ERR, 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(SDP_ERR, 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
-\r
- /* Update our posted depth. */\r
-\r
- /* Notify NDIS of any and all possible receive buffers. */\r
-\r
- /* Only indicate receives if we actually had any. */\r
-// if( pkt_cnt )\r
- {\r
-// NdisMIndicateReceivePacket( p_port->p_adapter->h_adapter,\r
-// p_port->recv_mgr.recv_pkt_array, pkt_cnt );\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(SDP_ERR, 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 any discarded receives to the pool */\r
-\r
- /* Repost receives. */\r
-\r
- RecieveOnce();\r
-\r
-\r
- /*\r
- * Rearm after filtering to prevent contention on the enpoint maps\r
- * and eliminate the possibility of having a call to\r
- * __endpt_mgr_insert find a duplicate.\r
- */\r
- status = ib_rearm_cq(m_rcq, FALSE );\r
- CL_ASSERT( status == IB_SUCCESS );\r
-\r
-\r
-\r
-}\r
-\r
-\r
-\r
-VOID \r
-SdpSocket::RecieveOnce()\r
-{\r
- ib_local_ds_t l_ds;\r
-\r
- ib_recv_wr_t recv_wr;\r
- recv_wr.p_next = NULL;\r
- recv_wr.num_ds = 1;\r
- recv_wr.wr_id = 123;\r
- recv_wr.ds_array = & l_ds;\r
+ return rc;\r
\r
- l_ds.length = sizeof(g_Recieve);\r
- l_ds.lkey = m_lkey;\r
- l_ds.vaddr = MmGetPhysicalAddress( g_Recieve ).QuadPart;\r
- \r
- ib_api_status_t ib_status = ib_post_recv(m_qp, &recv_wr, NULL);\r
- ASSERT(ib_status == IB_SUCCESS);\r
- \r
}\r
\r
\r
-\r
// TODO: Clear the callback functions mess\r
void\r
SdpSocket::__send_cb1(\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
+\r
NTSTATUS SdpSocket::send_cb()\r
{\r
SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("called this =0x%x\n", this));\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 = 0;//conn->send_seq; ???\r
- hello_msg->bsdh.seq_ack = 0;//conn->advt_seq; ???\r
+ hello_msg->bsdh.seq_num = m_SendBufferPool.GetSendSeq();//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
);\r
\r
ASSERT(NT_SUCCESS(rc));\r
- ASSERT(rc == STATUS_SUCCESS);\r
+ ASSERT(rc == STATUS_SUCCESS || rc == STATUS_USER_APC); //???????? what to do \r
+ //???????? the wait fails\r
KeClearEvent(ShutdownCompleteEvent);\r
}\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
\r
/*\r
#define _SDP_SOCKET_H\r
\r
const int MAX_SEND_BUFFER_SIZE = 32768; // This is the maximum send packet size\r
-const int MAX_SEND_PACKETS = 800; // This is the maximum number of packets allocated per send\r
-\r
- \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
#define QP_ATTRIB_SQ_DEPTH 32\r
#define QP_ATTRIB_SQ_SGE 1 /* Set based on inline data requirements */\r
\r
net32_t m_lkey;\r
\r
- BufferPool m_SendBufferPool;\r
\r
KEVENT m_ConnectCmCompleteEvent;\r
KEVENT m_ShutdownCompleteEvent;\r
VOID SignalShutdown();\r
\r
static VOID __send_cb1(\r
- IN const ib_cq_handle_t h_cq,\r
- IN void *cq_context );\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
+\r
+ \r
SdpSocket();\r
\r
NTSTATUS Init(\r
WspSendOut *pWspSendOut\r
); \r
\r
+ NTSTATUS WSPRecv(\r
+ WspRecvIn *pWspRecvIn,\r
+ WspRecvOut *pWspRecvOut\r
+ ); \r
+\r
VOID Shutdown();\r
\r
static VOID ShutdownCB(VOID* pContext);\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
#endif\r
\r
- VOID AssertLocked();\r
-\r
- VOID RecieveOnce(); //???????? remove me\r
- VOID __recv_cb2();\r
- \r
+ VOID AssertLocked(); \r
};\r
\r
#endif // _SDP_SOCKET_H\r
BOOLEAN CheckCondition(int sev, int top, char *file, int line, char * func)\r
{\r
if (sev < SDP_WARN) return FALSE;\r
+ if (top == SDP_PERFORMANCE) return FALSE;\r
+ \r
DbgPrint ("%s: ", func);\r
if (sev == SDP_ERR) DbgPrint ("ERROR - ");\r
return TRUE;\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) On send: implmeant some kind of a negal algorithm.\r
2) On send: 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.\r
- 4) \r
+ 4) Consider copying big packets from the DPC handler, instead of using the users thread\r
+ for the copy\r
\r
+ recv:\r
+ 1) What to do when I don\92t have all the buffer to return?\r
\r
+general:\r
+ \r
\r
USER MODE:\r
\r
\r
* Check the lifetime of the SdpSocket (when is it deleted and so)??\r
\r
-* make sure that the asserts are implmented in debug\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
\r
-* make sure that the SDP socket is deleted at least in the main path
\ No newline at end of file