Basic implementation of receive. (Rev 100)
authortzachid <tzachid@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 21 Nov 2005 12:15:25 +0000 (12:15 +0000)
committertzachid <tzachid@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 21 Nov 2005 12:15:25 +0000 (12:15 +0000)
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@168 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

15 files changed:
ulp/sdp/include/SdpShared.h
ulp/sdp/kernel/Precompile.h
ulp/sdp/kernel/SOURCES
ulp/sdp/kernel/SdpBufferPool.cpp
ulp/sdp/kernel/SdpBufferPool.h
ulp/sdp/kernel/SdpDriver.cpp
ulp/sdp/kernel/SdpGenUtils.cpp
ulp/sdp/kernel/SdpGenUtils.h
ulp/sdp/kernel/SdpLock.h
ulp/sdp/kernel/SdpRecvPool.cpp [new file with mode: 0644]
ulp/sdp/kernel/SdpRecvPool.h [new file with mode: 0644]
ulp/sdp/kernel/SdpSocket.cpp
ulp/sdp/kernel/SdpSocket.h
ulp/sdp/kernel/SdpTrace.cpp
ulp/sdp/todo

index a6e6532..2c4a8d5 100644 (file)
@@ -14,6 +14,8 @@
 #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
@@ -48,5 +50,18 @@ struct WspSendOut {
     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
index d2079c2..3f31442 100644 (file)
@@ -24,6 +24,7 @@ class SdpArp;
 #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
index 79448a6..a675f0a 100644 (file)
@@ -8,6 +8,7 @@ SOURCES= SdpDriver.cpp          \
         SdpSocket.cpp          \\r
         SdpArp.cpp             \\r
         SdpBufferPool.cpp      \\r
+        SdpRecvPool.cpp        \\r
         SdpTrace.cpp\r
 \r
 INCLUDES=..\include;\\r
@@ -31,3 +32,7 @@ TARGETLIBS= $(TARGETLIBS) $(DDK_LIB_PATH)\ntstrsafe.lib
 !endif\r
 \r
 MSC_WARNING_LEVEL= /W3\r
+\r
+PRECOMPILED_INCLUDE=Precompile.h\r
+PRECOMPILED_PCH=Precompile.pch\r
+PRECOMPILED_CXX=1\r
index 80cda01..5524e4d 100644 (file)
@@ -4,6 +4,82 @@
 #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
@@ -20,10 +96,6 @@ BufferPool::Init(
     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
@@ -31,11 +103,7 @@ BufferPool::Init(
     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
@@ -69,7 +137,9 @@ BufferPool::GetBuffer(
         // 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
@@ -85,12 +155,13 @@ BufferPool::GetBuffer(
             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
@@ -104,6 +175,11 @@ Cleanup:
     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
@@ -117,6 +193,12 @@ BufferPool::AddBufferToQueuedList(BufferDescriptor *pBufferDescriptor)
         (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
@@ -142,7 +224,9 @@ BufferPool::AllowOthersToGet()
     // 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
@@ -187,6 +271,7 @@ BufferPool::SendBuffersIfCan()
         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
@@ -212,79 +297,15 @@ BufferPool::ShutDown()
     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
@@ -296,10 +317,11 @@ BufferPool::SendBuffer(BufferDescriptor *pBufferDescriptor)
 \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
index 8ad0da5..28ed8db 100644 (file)
@@ -31,6 +31,14 @@ public:
         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
@@ -44,35 +52,64 @@ typedef void (* SendErrorCB )(NTSTATUS Error, VOID *Context);
 // 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
@@ -98,19 +135,20 @@ public:
     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
@@ -133,9 +171,10 @@ private:
     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
index 556328a..e262f0d 100644 (file)
@@ -9,7 +9,7 @@ VOID DriverUnload (
         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
@@ -41,7 +41,7 @@ extern "C" NTSTATUS DriverEntry (
     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
@@ -339,14 +339,17 @@ NTSTATUS SdpDriver::DispatchDeviceIoControl(
     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
@@ -354,41 +357,43 @@ NTSTATUS SdpDriver::DispatchDeviceIoControl(
                 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
@@ -398,29 +403,55 @@ NTSTATUS SdpDriver::DispatchDeviceIoControl(
             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
index bfccea6..db4eb65 100644 (file)
@@ -32,7 +32,7 @@ NTSTATUS IB2Status (ib_api_status_t ib_status)
 \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
@@ -44,26 +44,38 @@ NTSTATUS
     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
@@ -91,6 +103,38 @@ CopyFromUser(
     }\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
index 622eae0..e810afd 100644 (file)
@@ -44,12 +44,6 @@ NTSTATUS IB2Status (ib_api_status_t ib_status);
 \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
@@ -59,6 +53,24 @@ NTSTATUS
     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
index c920d69..56b1625 100644 (file)
@@ -29,6 +29,8 @@ There will therefore be a spinlock that will protect the event.
 // 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
@@ -36,7 +38,7 @@ const int SHUTDOWN_SIGNALLED    = 0x00000004;
 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
@@ -66,13 +68,15 @@ public:
         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
@@ -93,7 +97,7 @@ public:
 \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
@@ -109,7 +113,7 @@ public:
             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
@@ -154,25 +158,26 @@ Cleanup:
             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
@@ -181,6 +186,7 @@ Cleanup:
     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
@@ -188,28 +194,39 @@ Cleanup:
         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
@@ -224,7 +241,17 @@ Cleanup:
             // 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
@@ -250,11 +277,12 @@ Cleanup:
     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
diff --git a/ulp/sdp/kernel/SdpRecvPool.cpp b/ulp/sdp/kernel/SdpRecvPool.cpp
new file mode 100644 (file)
index 0000000..2cdf2e8
--- /dev/null
@@ -0,0 +1,310 @@
+/* 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
diff --git a/ulp/sdp/kernel/SdpRecvPool.h b/ulp/sdp/kernel/SdpRecvPool.h
new file mode 100644 (file)
index 0000000..68ac183
--- /dev/null
@@ -0,0 +1,84 @@
+/* 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
index 614292b..af8adbb 100644 (file)
@@ -6,6 +6,7 @@
 \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
@@ -87,11 +88,11 @@ NTSTATUS SdpSocket::Init(
     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
@@ -99,57 +100,12 @@ NTSTATUS SdpSocket::Init(
     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
@@ -158,6 +114,13 @@ NTSTATUS SdpSocket::WSPSend(
     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
@@ -242,7 +205,8 @@ NTSTATUS SdpSocket::WSPSend(
 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
@@ -251,160 +215,106 @@ Cleanup:
     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
@@ -602,12 +512,12 @@ NTSTATUS SdpSocket::CmSendRTU()
     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
@@ -631,6 +541,12 @@ NTSTATUS SdpSocket::CmSendRTU()
         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
@@ -696,7 +612,19 @@ NTSTATUS SdpSocket::CmSendRTU()
     }\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
@@ -722,33 +650,29 @@ VOID SdpSocket::CmRepCallback(IN   ib_cm_rep_rec_t *p_cm_rep_rec)
 }\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
@@ -759,81 +683,92 @@ SdpSocket::__recv_cb2()
         /* 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
@@ -844,12 +779,20 @@ SdpSocket::__send_cb1(
     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
@@ -1122,8 +1065,8 @@ VOID SdpSocket::CreateHelloHeader(
     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
@@ -1213,7 +1156,8 @@ VOID WaitForShutdownEvent(KEVENT *ShutdownCompleteEvent)
         );\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
@@ -1262,6 +1206,7 @@ VOID SdpSocket::Shutdown()
 \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
index 466c65f..b31ce87 100644 (file)
@@ -12,9 +12,9 @@ It keeps a list of all the objects so we know when to remove them.
 #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
@@ -70,7 +70,6 @@ private:
 \r
     net32_t                            m_lkey;\r
 \r
-    BufferPool              m_SendBufferPool;\r
 \r
     KEVENT                  m_ConnectCmCompleteEvent;\r
     KEVENT                  m_ShutdownCompleteEvent;\r
@@ -78,10 +77,19 @@ private:
     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
@@ -99,6 +107,11 @@ public:
         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
@@ -126,6 +139,7 @@ public:
     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
@@ -147,11 +161,7 @@ public:
 \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
index 564a6ed..cba394c 100644 (file)
@@ -6,6 +6,8 @@
 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
index 42b8391..37a4ff5 100644 (file)
@@ -2,22 +2,34 @@ This file includes things that should be impreoved in the sdp implmentation
 =============================================================================\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