sdp dll connects to a Linux machine from kernel mode. (Locking mechanism still has...
authortzachid <tzachid@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 21 Nov 2005 12:03:31 +0000 (12:03 +0000)
committertzachid <tzachid@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Mon, 21 Nov 2005 12:03:31 +0000 (12:03 +0000)
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@161 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

12 files changed:
ulp/sdp/kernel/Precompile.h
ulp/sdp/kernel/SOURCES
ulp/sdp/kernel/SdpArp.cpp [new file with mode: 0644]
ulp/sdp/kernel/SdpArp.h [new file with mode: 0644]
ulp/sdp/kernel/SdpDriver.cpp
ulp/sdp/kernel/SdpDriver.h
ulp/sdp/kernel/SdpGenUtils.cpp
ulp/sdp/kernel/SdpGenUtils.h
ulp/sdp/kernel/SdpMsgs.h [new file with mode: 0644]
ulp/sdp/kernel/SdpSocket.cpp
ulp/sdp/kernel/SdpSocket.h
ulp/sdp/kernel/SdpTrace.h

index e936c55..ca6a3bc 100644 (file)
@@ -11,8 +11,11 @@ extern "C" {
 \r
 // External classes declrations\r
 class SdpSocket;\r
+class SdpArp;\r
 \r
+#include "ib_al.h"\r
 \r
+#include "sdpMsgs.h"\r
 #include "SdpTrace.h"\r
 #include "RefCount.h"\r
 #include "sdpdriver.h"\r
@@ -20,6 +23,7 @@ class SdpSocket;
 #include "SdpUserFile.h"\r
 #include "SdpGenUtils.h"\r
 #include "SdpSocket.h"\r
+#include "SdpArp.h"\r
 \r
 \r
 #endif  // _SDP_PRECOMP_\r
index 667b1fb..2767487 100644 (file)
@@ -5,15 +5,20 @@ TARGETTYPE=DRIVER
 SOURCES= SdpDriver.cpp         \\r
         SdpUserFile.cpp        \\r
         SdpGenUtils.cpp        \\r
-        SdpSocket.cpp\r
+        SdpSocket.cpp          \\r
+        SdpArp.cpp\r
 \r
-INCLUDES=..\include;..\..\..\inc;..\..\..\inc\kernel;\r
+INCLUDES=..\include;\\r
+         ..\..\..\inc;\\r
+         ..\..\..\inc\kernel;\\r
+         ..\..\..\inc\iba\r
 \r
 C_DEFINES=$(C_DEFINES) -DNDIS_WDM=1  \\r
        -DDEPRECATE_DDK_FUNCTIONS \r
 \r
 TARGETLIBS= \\r
        $(TARGETPATH)\*\complib.lib \\r
+        $(TARGETPATH)\*\ibal.lib \\r
 \r
 !if !defined(DDK_TARGET_OS) || "$(DDK_TARGET_OS)"=="Win2K"\r
 #\r
diff --git a/ulp/sdp/kernel/SdpArp.cpp b/ulp/sdp/kernel/SdpArp.cpp
new file mode 100644 (file)
index 0000000..62b985d
--- /dev/null
@@ -0,0 +1,109 @@
+/* Copyright mellanox */\r
+\r
+#include "precompile.h"\r
+\r
+#pragma warning(disable: 4244 ) \r
+\r
+\r
+NTSTATUS\r
+SdpArp::QueryPathRecord(\r
+    IN  ib_net64_t      SrcPortGuid,\r
+    IN  ib_net64_t      DestPortGuid,\r
+    OUT ib_path_rec_t   *path_rec )\r
+{\r
+    NTSTATUS rc = STATUS_SUCCESS;\r
+    ib_gid_pair_t user_query;\r
+    struct query_pr_context query_context;\r
+    ib_query_handle_t query_handle;\r
+    ib_query_req_t query_req;\r
+    ib_api_status_t ib_status;\r
+\r
+    query_req.query_type = IB_QUERY_PATH_REC_BY_GIDS;\r
+    query_req.p_query_input = &user_query;\r
+    query_req.port_guid = SrcPortGuid;\r
+    query_req.timeout_ms = 500;\r
+    query_req.retry_cnt = 4;\r
+    query_req.flags = IB_FLAGS_SYNC;\r
+    query_req.query_context = &query_context;\r
+    query_req.pfn_query_cb = SdpArp::query_pr_callback;\r
+\r
+    ib_gid_set_default( &user_query.src_gid, SrcPortGuid );\r
+    ib_gid_set_default( &user_query.dest_gid, DestPortGuid );\r
+\r
+    query_context.path_rec = path_rec;\r
+\r
+    SDP_PRINT( SDP_TRACE, SDP_ARP,\r
+    ("Query for path from %I64x to %I64x\n",\r
+    SrcPortGuid, DestPortGuid) );\r
+\r
+    ib_status = ib_query( g_pSdpDriver->m_al_handle, &query_req, &query_handle );\r
+\r
+    if ( ib_status != IB_SUCCESS) {\r
+        SDP_PRINT(SDP_ERR, SDP_ARP, ("ib_query failed ib_status = 0x%d\n", ib_status ));\r
+        rc = IB2Status(ib_status);\r
+        goto Cleanup;\r
+    }\r
+\r
+    if( query_context.status != IB_SUCCESS ) {\r
+        SDP_PRINT(SDP_ERR, SDP_ARP, ("ib_query failed ib_status = 0x%d\n", query_context.status ));\r
+        rc = IB2Status(query_context.status);\r
+        goto Cleanup;\r
+    }\r
+\r
+// BUGBUG: This code was in the orginanl function. We have to decide\r
+// if we want to keep it.\r
+#if 0\r
+    if( (port->hca->dev_id == 0x5A44) &&\r
+        (ib_path_rec_mtu( path_rec ) > IB_MTU_1024) )\r
+    {\r
+        /* Local endpoint is Tavor - cap MTU to 1K for extra bandwidth. */\r
+        path_rec->mtu &= IB_PATH_REC_SELECTOR_MASK;\r
+        path_rec->mtu |= IB_MTU_1024;\r
+    }\r
+#endif\r
+\r
+Cleanup:\r
+    return rc;\r
+}\r
+\r
+void AL_API\r
+SdpArp::query_pr_callback(\r
+    IN              ib_query_rec_t              *p_query_rec)\r
+{\r
+     query_pr_context * __ptr64 query_context  =\r
+        (query_pr_context * __ptr64)p_query_rec->query_context;\r
+\r
+    \r
+    ib_api_status_t status;\r
+\r
+    SDP_PRINT( SDP_TRACE, SDP_ARP,("query_pr_callback status is %d irql=%d\n", p_query_rec->status, KeGetCurrentIrql()) );\r
+\r
+    query_context->status = p_query_rec->status;\r
+\r
+    if( p_query_rec->status == IB_SUCCESS ){\r
+        ib_path_rec_t *path_rec;\r
+\r
+        path_rec = ib_get_query_path_rec(p_query_rec->p_result_mad, 0 );\r
+\r
+        ASSERT( path_rec );\r
+\r
+        /* Copy the path record */\r
+        *query_context->path_rec = *path_rec;\r
+    }\r
+\r
+    if( p_query_rec->status == IB_SUCCESS || p_query_rec->status == IB_REMOTE_ERROR )\r
+    {\r
+        status = ib_put_mad( p_query_rec->p_result_mad );\r
+\r
+        ASSERT(status == IB_SUCCESS);\r
+        if( status != IB_SUCCESS )\r
+        {\r
+            SDP_PRINT( SDP_ERR, SDP_ARP, ("ib_put_mad failed (%d)\n", status) );\r
+        }\r
+    } else {\r
+        // When do we free this mad ???\r
+        ASSERT(p_query_rec->p_result_mad == NULL);\r
+    }\r
+\r
+}\r
+\r
diff --git a/ulp/sdp/kernel/SdpArp.h b/ulp/sdp/kernel/SdpArp.h
new file mode 100644 (file)
index 0000000..ada6432
--- /dev/null
@@ -0,0 +1,114 @@
+/* Copyright mellanox */\r
+\r
+// BUGBUG: complete this mechanisms\r
+\r
+\r
+class SdpArp {\r
+    /* \r
+        Look at the routing table of the machine and see which port\r
+        to use for outbound traffic\r
+    */\r
+\r
+public:\r
+\r
+  struct query_pr_context\r
+    {\r
+           ib_api_status_t status;\r
+           ib_path_rec_t *path_rec;\r
+    };\r
+\r
+    NTSTATUS Init() { return STATUS_SUCCESS;}\r
+\r
+    NTSTATUS SourceAddrFromDestAddr(\r
+        IN  ULONG  DestIp, \r
+        OUT ULONG  *SrcIp\r
+        )\r
+    {\r
+        NTSTATUS rc = STATUS_SUCCESS;\r
+        if (DestIp == 11 * 256*256*256 + \r
+                      4 * 256*256 +\r
+                      8 * 256 +\r
+                      + 124) {\r
+            *SrcIp = 11 * 256*256*256 + \r
+                      4 * 256*256 +\r
+                      8 * 256 +\r
+                      + 120;\r
+            return STATUS_SUCCESS;\r
+        }\r
+        ASSERT(FALSE);\r
+        *SrcIp = 0;\r
+        return STATUS_UNEXPECTED_IO_ERROR;\r
+\r
+    }\r
+\r
+    NTSTATUS GetPort(\r
+        IN  ULONG  SourceAddr, \r
+        OUT USHORT *SrcPort\r
+        )\r
+    {\r
+        ASSERT(SourceAddr != 0);\r
+        // If the port is 0, choose your own free port.\r
+        // If the port is not 0 check if this port is already in use\r
+        *SrcPort = 5050;\r
+        return STATUS_SUCCESS;\r
+\r
+    }\r
+\r
+\r
+    NTSTATUS SourcePortGidFromIP(\r
+        IN  ULONG  SourceAddr, \r
+        OUT ib_net64_t *SrcPortGuid,\r
+        OUT ib_net64_t *SrcCaGuid\r
+        )\r
+    {\r
+        if (SourceAddr == 11 * 256*256*256 + \r
+                      4 * 256*256 +\r
+                      8 * 256 +\r
+                      + 120) {\r
+            *SrcPortGuid = CL_NTOH64(0x2c90200002002);//????? swlab120\r
+            *SrcCaGuid = CL_NTOH64(0x2c90200002000);\r
+            return STATUS_SUCCESS;\r
+        }\r
+        ASSERT(FALSE);\r
+        *SrcPortGuid = 0;\r
+        *SrcCaGuid = 0;\r
+        return STATUS_UNEXPECTED_IO_ERROR;\r
+\r
+    }\r
+\r
+\r
+    NTSTATUS DestPortGidFromIP(\r
+        IN  ULONG  DestAddr, \r
+        OUT ib_net64_t *DestPortGuid)\r
+    {\r
+        if (DestAddr == 11 * 256*256*256 + \r
+                      4 * 256*256 +\r
+                      8 * 256 +\r
+                      + 124) {\r
+            *DestPortGuid = CL_NTOH64(0x0000c900012a3a41);//????? swlab124\r
+            return STATUS_SUCCESS;\r
+        }\r
+        ASSERT(FALSE);\r
+        *DestPortGuid = 0;\r
+        return STATUS_UNEXPECTED_IO_ERROR;\r
+\r
+    }\r
+/* \r
+Synchronously query the SA for a GUID. (started from wsd - query_pr)\r
+*/\r
+/* \r
+ * Get a path record from a GUID \r
+ */\r
+  \r
+    NTSTATUS\r
+    QueryPathRecord(\r
+       IN                              ib_net64_t                              SrcPortGuid,\r
+       IN                              ib_net64_t                                      DestPortGuid,\r
+       OUT                         ib_path_rec_t                               *path_rec \r
+       );\r
+\r
+    static void AL_API\r
+        query_pr_callback(\r
+        IN                             ib_query_rec_t                          *p_query_rec);\r
+};\r
+\r
index 3af15f2..7166fe3 100644 (file)
@@ -10,17 +10,20 @@ VOID DriverUnload (
         ) \r
 {\r
     SDP_PRINT(SDP_TRACE, SDP_DRIVER, ("DriverUnload called pDriverObject = 0x%x\n", pDriverObject ));\r
+    ib_api_status_t ib_status;\r
 \r
-    SdpDriver *pSdpDriver;\r
-    UNICODE_STRING LinkName;\r
 \r
-    pSdpDriver = (SdpDriver *) pDriverObject->DeviceObject->DeviceExtension;\r
+    ib_status = ib_close_al(g_pSdpDriver->m_al_handle);\r
+    g_pSdpDriver->m_al_handle = NULL;\r
+    ASSERT( ib_status == IB_SUCCESS);\r
 \r
+    UNICODE_STRING LinkName;\r
 \r
     RtlInitUnicodeString( &LinkName, SDP_LINK_NAME );\r
     IoDeleteSymbolicLink(&LinkName);\r
 \r
-    IoDeleteDevice( pSdpDriver->GetDeviceObject());\r
+    IoDeleteDevice( g_pSdpDriver->GetDeviceObject());\r
+    g_pSdpDriver = NULL;\r
 }\r
 \r
 \r
@@ -30,9 +33,11 @@ extern "C" NTSTATUS DriverEntry (
     IN PUNICODE_STRING pRegistryPath   )\r
 {\r
     NTSTATUS rc;\r
+    ib_api_status_t ib_status;\r
     PDEVICE_OBJECT pDevObj;\r
     SdpDriver *pSdpDriver;\r
     bool DeviceCreated = false;\r
+    bool LinkCreated = false;\r
     UNICODE_STRING  DevName, LinkName;\r
     int i;\r
 \r
@@ -88,9 +93,23 @@ extern "C" NTSTATUS DriverEntry (
         SDP_PRINT(SDP_ERR, SDP_DRIVER, ("IoCreateSymbolicLink failed rc = 0x%x\n", rc ));\r
         goto Cleanup;\r
     }\r
+    LinkCreated = true;\r
+#pragma warning( push )\r
+#pragma warning(disable: 4244 ) \r
+    ib_status = ib_open_al(&pSdpDriver->m_al_handle);\r
+#pragma warning( pop )\r
+    if ( ib_status != IB_SUCCESS) {\r
+        SDP_PRINT(SDP_ERR, SDP_DRIVER, ("ib_open_al failed ib_status = 0x%d\n", ib_status ));\r
+        rc = IB2Status(ib_status);\r
+        goto Cleanup;\r
+    }\r
 \r
 Cleanup:\r
     if (!NT_SUCCESS(rc)) {\r
+        if (LinkCreated) {\r
+            IoDeleteSymbolicLink(&LinkName);\r
+\r
+        }\r
         if ( DeviceCreated ) {\r
             IoDeleteDevice(pDevObj);\r
         }\r
@@ -285,6 +304,24 @@ if ((InputBufferLength < sizeof (InStruct)) ||
         goto Cleanup;                                                               \\r
 }\r
 \r
+NTSTATUS SdpDriver::Init(PDEVICE_OBJECT pDevObj) \r
+{\r
+    NTSTATUS rc = STATUS_SUCCESS;\r
+    m_pDevObj = pDevObj;\r
+    m_pSdpArp = new SdpArp;\r
+    if (m_pSdpArp == NULL) {\r
+        SDP_PRINT(SDP_ERR, SDP_DRIVER, ("new SdpArp failed \n"));        \r
+        rc = STATUS_NO_MEMORY;\r
+        goto Cleanup;\r
+    }\r
+    rc = m_pSdpArp->Init();\r
+    if (!NT_SUCCESS(rc)) {\r
+        SDP_PRINT(SDP_ERR, SDP_DRIVER, ("m_pSdpArp->Init failed rc = 0x%x\n", rc ));        \r
+        goto Cleanup;\r
+    }\r
+Cleanup:        \r
+    return rc;\r
+}\r
 \r
 \r
 NTSTATUS SdpDriver::DispatchDeviceIoControl(\r
index d820c7c..f509fab 100644 (file)
@@ -6,10 +6,14 @@
 \r
 class SdpDriver {\r
 public:\r
-       NTSTATUS Init(PDEVICE_OBJECT pDevObj) {\r
-               m_pDevObj = pDevObj;\r
-               return STATUS_SUCCESS;\r
-       }\r
+    SdpDriver() {\r
+        m_al_handle = NULL;\r
+        m_pDevObj = NULL;\r
+        m_pSdpArp = NULL;\r
+    }\r
+    \r
+       NTSTATUS Init(PDEVICE_OBJECT pDevObj);\r
+    \r
        PDEVICE_OBJECT GetDeviceObject() {\r
                return m_pDevObj;\r
        }\r
@@ -34,11 +38,15 @@ public:
         \r
         \r
 \r
-\r
+public:\r
+    ib_al_handle_t m_al_handle ;\r
+    SdpArp *m_pSdpArp;\r
 \r
 private:\r
 \r
        PDEVICE_OBJECT m_pDevObj;\r
+\r
+    \r
 };\r
 \r
 extern SdpDriver *g_pSdpDriver;\r
index 67cc886..b99b18b 100644 (file)
@@ -3,11 +3,70 @@
 #include "Precompile.h"\r
 \r
 \r
-USHORT nthos(USHORT in)\r
+USHORT ntohs(USHORT in)\r
 {\r
     return ((in & 0xff) << 8) | ((in & 0xff00) >> 8);\r
 }\r
 \r
+NTSTATUS IB2Status (ib_api_status_t ib_status)\r
+{\r
+    if ( ib_status == IB_SUCCESS ) {\r
+        return STATUS_SUCCESS;\r
+    } if (( ib_status > IB_SUCCESS ) && (ib_status < IB_UNKNOWN_ERROR)) {\r
+//\r
+//  Values are 32 bit values layed out as follows:\r
+//\r
+//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1\r
+//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0\r
+//  +---+-+-+-----------------------+-------------------------------+\r
+//  |Sev|C|R|     Facility          |               Code            |\r
+//  +---+-+-+-----------------------+-------------------------------+\r
+\r
+        return 0xcc000000 |  ib_status;     \r
+    }\r
+\r
+\r
+    // Keep translating as the error pops\r
+    ASSERT(FALSE);\r
+    return STATUS_UNEXPECTED_IO_ERROR;\r
+\r
+}\r
+\r
+\r
+// This function is a wrapper for the KeWaitForSingleObject that adds\r
+// assertsions to the valuas returned by it\r
+NTSTATUS \r
+  MyKeWaitForSingleObject(\r
+    IN PVOID  Object,\r
+    IN KWAIT_REASON  WaitReason,\r
+    IN KPROCESSOR_MODE  WaitMode,\r
+    IN BOOLEAN  Alertable,\r
+    IN PLARGE_INTEGER  Timeout  OPTIONAL\r
+    )\r
+{\r
+    NTSTATUS rc = 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
+    return rc;\r
+}\r
+\r
 \r
 \r
 void* __cdecl operator new(size_t n ) throw() {\r
index 8e9bd9e..30deb83 100644 (file)
@@ -39,10 +39,20 @@ public:
 \r
 };\r
 \r
+NTSTATUS IB2Status (ib_api_status_t ib_status); \r
 \r
 USHORT nthos(USHORT in);\r
 \r
 \r
+NTSTATUS \r
+  MyKeWaitForSingleObject(\r
+    IN PVOID  Object,\r
+    IN KWAIT_REASON  WaitReason,\r
+    IN KPROCESSOR_MODE  WaitMode,\r
+    IN BOOLEAN  Alertable,\r
+    IN PLARGE_INTEGER  Timeout  OPTIONAL\r
+    );\r
+\r
 // This error codes are taken from winsock2.h (the file can not)\r
 // be included from user mode\r
 \r
diff --git a/ulp/sdp/kernel/SdpMsgs.h b/ulp/sdp/kernel/SdpMsgs.h
new file mode 100644 (file)
index 0000000..1895d67
--- /dev/null
@@ -0,0 +1,198 @@
+/* Copyright mellanox */\r
+\r
+/*\r
+    This file holds the types that are used for SDP comunication\r
+\r
+*/\r
+\r
+#ifndef H_SDP_MSGS_H\r
+#define H_SDP_MSGS_H \r
+\r
+\r
+#pragma pack(push)\r
+#pragma pack(1)\r
+\r
+\r
+/*\r
+ * Message Identifier Opcodes for BSDH\r
+ */\r
+/*        Name                        Value    Extended Header   Payload   */\r
+#define SDP_MID_HELLO           0x00 /* msg_hdr_hh      <none>   */\r
+#define SDP_MID_HELLO_ACK       0x01 /* msg_hdr_hah     <none>   */\r
+#define SDP_MID_DISCONNECT      0x02 /* <none>          <none>   */\r
+#define SDP_MID_ABORT_CONN      0x03 /* <none>          <none>   */\r
+#define SDP_MID_SEND_SM         0x04 /* <none>          <none>   */\r
+#define SDP_MID_RDMA_WR_COMP    0x05 /* msg_hdr_rwch    <none>   */\r
+#define SDP_MID_RDMA_RD_COMP    0x06 /* msg_hdr_rrch    <none>   */\r
+#define SDP_MID_MODE_CHANGE     0x07 /* msg_hdr_mch     <none>   */\r
+#define SDP_MID_SRC_CANCEL      0x08 /* <none>          <none>   */\r
+#define SDP_MID_SNK_CANCEL      0x09 /* <none>          <none>   */\r
+#define SDP_MID_SNK_CANCEL_ACK  0x0A /* <none>          <none>   */\r
+#define SDP_MID_CH_RECV_BUF     0x0B /* msg_hdr_crbh    <none>   */\r
+#define SDP_MID_CH_RECV_BUF_ACK 0x0C /* msg_hdr_crbah   <none>   */\r
+#define SDP_MID_SUSPEND         0x0D /* msg_hdr_sch     <none>   */\r
+#define SDP_MID_SUSPEND_ACK     0x0E /* <none>          <none>   */\r
+#define SDP_MID_SNK_AVAIL       0xFD /* msg_hdr_snkah   <optional> */\r
+#define SDP_MID_SRC_AVAIL       0xFE /* msg_hdr_srcah   <optional> */\r
+#define SDP_MID_DATA            0xFF /* <none>          <optional> */\r
+/*\r
+ * shift number for BSDH Flags.\r
+ */\r
+#define SDP_MSG_FLAG_NON_FLAG (0x0)    /* no flag present */\r
+#define SDP_MSG_FLAG_OOB_PRES  0       /* out-of-band data present */\r
+#define SDP_MSG_FLAG_OOB_PEND  1       /* out-of-band data pending */\r
+#define SDP_MSG_FLAG_REQ_PIPE  2       /* request change to pipelined  */\r
+/*\r
+ * message type masks\r
+ */\r
+#define SDP_MID_CTRL(mid) ((0xF0 & mid) ? 0 : 1)\r
+\r
+\r
+/*\r
+ * Base Sockets Direct Header (header for all SDP messages)\r
+ */\r
+struct msg_hdr_bsdh {\r
+    uint8_t  mid;       /* message identifier opcode (SDP_MID_*) */\r
+    uint8_t  flags;     /* flags as defined by SDP_MSG_FLAG_* */\r
+    uint16_t recv_bufs; /* current number of posted private recv buffers */\r
+    uint32_t size;      /* length of msg, including header(s) and data */\r
+    uint32_t seq_num;   /* message sequence number */\r
+    uint32_t seq_ack;   /* last received message sequence number */\r
+};// __attribute__ ((packed)); /* struct msg_hdr_bsdh */\r
+\r
+/*\r
+ * Hello Header constants (two 8-bit constants, no conversion needed)\r
+ */\r
+#ifdef _SDP_MS_APRIL_ERROR_COMPAT\r
+this bug was probably solved \r
+#define SDP_MSG_IPVER   0x04   /* (1: ipversion), (0: reserved) */\r
+#else\r
+#define SDP_MSG_IPVER   0x40   /* (1: ipversion), (0: reserved) */\r
+#endif\r
+#define SDP_MSG_VERSION 0x11   /* (1: major ), (0: minor ) */\r
+\r
+\r
+/*\r
+ * Hello Header (BSDH + HH are contained in private data of the CM REQ MAD\r
+ */\r
+struct msg_hdr_hh {\r
+    uint8_t  version;     /* 0-3: minor version (current spec; 0x1)\r
+                     4-7: major version (current spec; 0x1) */\r
+    uint8_t  ip_ver;      /* 0-3: reserved\r
+                     4-7: ip version (0x4 = ipv4, 0x6 = ipv6) */\r
+    uint8_t  rsvd_1;      /* reserved */\r
+    uint8_t  max_adv;     /* max outstanding Zcopy advertisments (>0) */\r
+    uint32_t r_rcv_size;  /* requested size of each remote recv buffer */\r
+    uint32_t l_rcv_size;  /* initial size of each local receive buffer */\r
+    uint16_t port;        /* local port */\r
+    uint16_t rsvd_2;      /* reserved */\r
+\r
+    union {               /* source IP address. */\r
+        struct {\r
+            uint32_t addr3;    /* ipv6 96-127 */\r
+            uint32_t addr2;    /* ipv6 64-95  */\r
+            uint32_t addr1;    /* ipv6 32-63  */\r
+            uint32_t addr0;    /* ipv6  0-31  */\r
+        } ipv6;           /* 128bit IPv6 address */\r
+        struct {\r
+            uint32_t none2;    /* unused 96-127 */\r
+            uint32_t none1;    /* unused 64-95  */\r
+            uint32_t none0;    /* unused 32-63  */\r
+            uint32_t addr;     /* ipv4    0-31  */\r
+        } ipv4;           /* 32bit IPv4 address */\r
+       } src;\r
+\r
+    union {               /* destination IP address. */\r
+        struct {\r
+            uint32_t addr3;    /* ipv6 96-127 */\r
+            uint32_t addr2;    /* ipv6 64-95  */\r
+            uint32_t addr1;    /* ipv6 32-63  */\r
+            uint32_t addr0;    /* ipv6  0-31  */\r
+        } ipv6;           /* 128bit IPv6 address */\r
+        struct {\r
+            uint32_t none2;    /* unused 96-127 */\r
+            uint32_t none1;    /* unused 64-95  */\r
+            uint32_t none0;    /* unused 32-63  */\r
+            uint32_t addr;     /* ipv4    0-31  */\r
+        } ipv4;           /* 32bit IPv4 address */\r
+    } dst;\r
+\r
+    uint8_t rsvd_3[28];   /* reserved for future use, and zero'd */\r
+}; //__attribute__ ((packed)); /* struct msg_hdr_hh */\r
+\r
+struct msg_hdr_hah {\r
+       uint8_t  version;     /* 0-3: minor version (current spec; 0x1)\r
+                             4-7: major version (current spec; 0x1) */\r
+       uint16_t rsvd_1;      /* reserved */\r
+       uint8_t  max_adv;     /* max outstanding Zcopy advertisments (>0) */\r
+       uint32_t l_rcv_size;  /* initial size of each local receive buffer */\r
+#if 0 /* There is a bug in the 1.1 spec. REP message grew by 8 bytes. */\r
+       __u8  rsvd_2[180]; /* reserved for future use, and zero'd (big) */\r
+#else\r
+       uint8_t  rsvd_2[172]; /* reserved for future use, and zero'd (big) */\r
+#endif\r
+}; //__attribute__ ((packed)); /* struct msg_hdr_hah */\r
+\r
+struct sdp_msg_hello {\r
+    struct msg_hdr_bsdh bsdh;  /* base sockets direct header */\r
+    struct msg_hdr_hh   hh;    /* hello message header */\r
+} ;//__attribute__ ((packed)); /* struct sdp_msg_hello */\r
+\r
+struct sdp_msg_hello_ack {\r
+       struct msg_hdr_bsdh bsdh;  /* base sockets direct header */\r
+       struct msg_hdr_hah  hah;   /* hello ack message header */\r
+};// __attribute__ ((packed)); /* struct sdp_msg_hello_ack */\r
+\r
+static inline void sdp_msg_swap_bsdh(struct msg_hdr_bsdh *header)\r
+{\r
+    header->recv_bufs = CL_NTOH16(header->recv_bufs);\r
+    header->size = CL_NTOH32(header->size);\r
+    header->seq_num = CL_NTOH32(header->seq_num);\r
+    header->seq_ack = CL_NTOH32(header->seq_ack);\r
+}\r
+\r
+static inline void sdp_msg_swap_hh(struct msg_hdr_hh *header)\r
+{\r
+    header->r_rcv_size = CL_NTOH32(header->r_rcv_size);\r
+    header->l_rcv_size = CL_NTOH32(header->l_rcv_size);\r
+    header->port = CL_NTOH16(header->port);\r
+    header->src.ipv6.addr0 = CL_NTOH32(header->src.ipv6.addr0);\r
+    header->src.ipv6.addr1 = CL_NTOH32(header->src.ipv6.addr1);\r
+    header->src.ipv6.addr2 = CL_NTOH32(header->src.ipv6.addr2);\r
+    header->src.ipv6.addr3 = CL_NTOH32(header->src.ipv6.addr3);\r
+    header->dst.ipv6.addr0 = CL_NTOH32(header->dst.ipv6.addr0);\r
+    header->dst.ipv6.addr1 = CL_NTOH32(header->dst.ipv6.addr1);\r
+    header->dst.ipv6.addr2 = CL_NTOH32(header->dst.ipv6.addr2);\r
+    header->dst.ipv6.addr3 = CL_NTOH32(header->dst.ipv6.addr3);\r
+}\r
+\r
+/*\r
+ * sdp_msg_swap_hah - SDP header endian byte swapping\r
+ */\r
+static inline void sdp_msg_net_to_cpu_hah(struct msg_hdr_hah *header)\r
+{\r
+       header->l_rcv_size = CL_NTOH32(header->l_rcv_size);\r
+}\r
+\r
+#define BASE_LISTEN_ID (CL_CONST64(0x0000000000010000))\r
+\r
+static inline ib_net64_t\r
+get_service_id_for_port(\r
+                                       ib_net16_t                                      ip_port)\r
+{\r
+       return CL_NTOH64( BASE_LISTEN_ID | ip_port );\r
+}\r
+\r
+\r
+// CM timeouts - Used for creating the sockets\r
+#define CM_MIN_LOCAL_TIMEOUT   (18)\r
+#define CM_LOCAL_TIMEOUT               (1)\r
+#define CM_MIN_REMOTE_TIMEOUT  (18)\r
+#define CM_REMOTE_TIMEOUT              (2)\r
+#define CM_RETRIES 4\r
+\r
+\r
+#pragma pack(pop)\r
+\r
+#endif H_SDP_MSGS_H\r
+\r
index ca54437..dc74a7b 100644 (file)
@@ -2,18 +2,91 @@
 \r
 \r
 #include "Precompile.h"\r
+#pragma warning(disable: 4244 ) \r
+\r
+NTSTATUS sdp_cm_hello_ack_check(struct sdp_msg_hello_ack *hello_ack);\r
+\r
+static void AL_API\r
+cm_rej_callback(IN ib_cm_rej_rec_t *p_cm_rej_rec )\r
+{\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("cm_rej_callback called"));\r
+}\r
+\r
+static void AL_API\r
+cm_rep_callback(\r
+    IN          ib_cm_rep_rec_t         *p_cm_rep_rec )\r
+{\r
+    \r
+\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("cm_rep_callback called\n"));\r
+    SdpSocket *pSocket = (SdpSocket *) p_cm_rep_rec->qp_context;\r
+    pSocket->CmRepCallback(p_cm_rep_rec);\r
+}\r
+\r
+static void AL_API\r
+cm_req_callback(\r
+    IN  ib_cm_req_rec_t *p_cm_req_rec )\r
+{\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("cm_req_callback called"));\r
+    ASSERT(FALSE);\r
+}\r
+\r
+static void AL_API\r
+cm_mra_callback(\r
+    IN  ib_cm_mra_rec_t                                *p_cm_mra_rec )\r
+{\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("cm_mra_callback called"));\r
+    ASSERT(FALSE);\r
+}\r
+\r
+/*\r
+ * A user-specified callback that is invoked after receiving a load\r
+ * alternate path response message.\r
+ */\r
+static void AL_API\r
+cm_apr_callback(\r
+    IN  ib_cm_apr_rec_t     *p_cm_apr_rec )\r
+{\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("cm_apr_callback called"));\r
+    ASSERT(FALSE);\r
+}\r
+\r
+static void AL_API\r
+cm_dreq_callback(IN ib_cm_dreq_rec_t    *p_cm_dreq_rec )\r
+{\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("cm_dreq_callback called"));\r
+    ASSERT(FALSE);\r
+}\r
+SdpSocket::SdpSocket()\r
+{\r
+    m_CreationFlags = 0;\r
+    m_SrcPort = 0;\r
+    m_SrcIp = 0;\r
+\r
+    mh_Ca = NULL;\r
+    m_pd = NULL;\r
+    m_rcq = NULL;\r
+    m_scq = NULL;\r
+    m_qp = NULL;\r
+\r
+    m_shutdown = false;\r
+\r
+    m_state = SS_IDLE;\r
+}\r
 \r
 NTSTATUS SdpSocket::Init(\r
     WspSocketIn *pSocketInParam, \r
     WspSocketOut *pSocketOutParam)\r
 {\r
-    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("SdpSocket::Init this = 0x%x\n", this));\r
+    NTSTATUS rc = STATUS_SUCCESS;\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("SdpSocket::Init this = 0x%p\n", this));\r
 \r
     m_CreationFlags = pSocketInParam->dwFlags;\r
     pSocketOutParam->Errno = 0;// No error\r
     pSocketOutParam->pSocket = this; // give the user a handle to the socket\r
-                                     \r
-    return STATUS_SUCCESS;\r
+    KeInitializeSpinLock(&m_Lock);\r
+\r
+    return rc;\r
 }\r
 \r
 NTSTATUS SdpSocket::WSPConnect(\r
@@ -22,13 +95,19 @@ NTSTATUS SdpSocket::WSPConnect(
     )\r
 {\r
     NTSTATUS rc = STATUS_SUCCESS;\r
-    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("SdpSocket::WSPConnect this = 0x%x remote addresses ip=%d.%d.%d.%d:%d",\r
+    ib_api_status_t ib_status;\r
+    ib_net64_t SrcPortGuid;\r
+    ib_net64_t DestPortGuid;\r
+    ib_path_rec_t path_rec;\r
+    CSpinLockWrapper Lock(m_Lock);\r
+        \r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("SdpSocket::WSPConnect this = 0x%p remote addresses ip=%d.%d.%d.%d:%d\n",\r
         this,\r
-        (pWspConnectIn->IP & 0XFF),\r
-        (pWspConnectIn->IP & 0XFF00) >> 8,\r
-        (pWspConnectIn->IP & 0XFF0000) >> 16,\r
         (pWspConnectIn->IP & 0XFF000000) >> 24,\r
-        nthos(pWspConnectIn->Port)\r
+        (pWspConnectIn->IP & 0XFF0000) >> 16,\r
+        (pWspConnectIn->IP & 0XFF00) >> 8,\r
+        (pWspConnectIn->IP & 0XFF),\r
+        pWspConnectIn->Port\r
         ));\r
 \r
     if((pWspConnectIn->IP == 0) || (pWspConnectIn->Port == 0)) {\r
@@ -37,17 +116,594 @@ NTSTATUS SdpSocket::WSPConnect(
         goto Cleanup;\r
     }\r
 \r
+    // check socket state\r
+    // BUGBUG: Do a better work here\r
+    Lock.Lock();\r
+    if (m_state != SS_IDLE) {\r
+        // We can not connect in this state \r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("Invalid Socket state %s\n", SS2String(m_state)));\r
+        pWspConnectOut->Errno = WSAEINVAL;\r
+        goto Cleanup;\r
+        Lock.Unlock();\r
+    }\r
+\r
+    //\r
+    // Arp: this means that based on the ARP protocol we should convert the \r
+    // IP address into gid.\r
+    //\r
+    if (m_SrcIp == 0) {\r
+        // This means that we need to do an implicit bind to get the source\r
+        // address\r
+        rc = g_pSdpDriver->m_pSdpArp->SourceAddrFromDestAddr(pWspConnectIn->IP , &m_SrcIp);\r
+        if (!NT_SUCCESS(rc)) {\r
+            SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_pSdpArp->SourceAddrFromDestAddr failed rc = 0x%x\n", rc ));\r
+            pWspConnectOut->Errno = WSAENETUNREACH;\r
+            Lock.Unlock();\r
+            goto Cleanup;\r
+        }        \r
+    }\r
+\r
+    // Now that we know the source IP we can decide about the src port\r
+    if (m_SrcPort == 0) {\r
+       rc = g_pSdpDriver->m_pSdpArp->GetPort(m_SrcIp, &m_SrcPort);\r
+       if (!NT_SUCCESS(rc)) {\r
+            SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_pSdpArp->SourcePortGidFromIP failed rc = 0x%x\n", rc ));\r
+            pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
+            Lock.Unlock();\r
+            goto Cleanup;\r
+        }    \r
+    }\r
+    rc = g_pSdpDriver->m_pSdpArp->SourcePortGidFromIP(m_SrcIp, &SrcPortGuid, &m_CaGuid);\r
+    if (!NT_SUCCESS(rc)) {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_pSdpArp->SourcePortGidFromIP failed rc = 0x%x\n", rc ));\r
+        pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
+        Lock.Unlock();\r
+        goto Cleanup;\r
+    }        \r
+\r
+    rc = g_pSdpDriver->m_pSdpArp->DestPortGidFromIP(pWspConnectIn->IP, &DestPortGuid);\r
+    if (!NT_SUCCESS(rc)) {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_pSdpArp->DestPortGidFromIP failed rc = 0x%x\n", rc ));\r
+        pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
+        Lock.Unlock();\r
+        goto Cleanup;\r
+    }        \r
+\r
+    //\r
+    // Next step is convert the gid to a path record\r
+    //\r
+\r
+    // Since this is a function that might wait we do it without the lock\r
+    m_state = SS_CONNECTING_QPR_SENT;\r
+    Lock.Unlock();\r
+\r
+    rc = g_pSdpDriver->m_pSdpArp->QueryPathRecord( SrcPortGuid, DestPortGuid, &path_rec );\r
+    if (!NT_SUCCESS(rc)) {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("m_pSdpArp->QueryPathRecord failed rc = 0x%x\n", rc ));\r
+        pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
+        goto Cleanup;\r
+    }\r
+\r
+\r
+    // Verify that we are in the correct state (just looking - without the lock)\r
+    if (m_state != SS_CONNECTING_QPR_SENT) {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("wrong state after QueryPathRecord\n" ));\r
+        pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
+        goto Cleanup;\r
+    }\r
+\r
+    rc = CreateQp();\r
+    if (!NT_SUCCESS(rc)) {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("CreateQp failed rc = 0x%x\n", rc ));\r
+        pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
+        goto Cleanup;\r
+    }    \r
+\r
+//    Lock.Lock(); // Do we really need the lock ?\r
+\r
+\r
+\r
+    // We need to prepare the hello mesage for the CM\r
+    sdp_msg_hello hello_msg;\r
+    CreateHelloHeader(&hello_msg, pWspConnectIn->IP);\r
+\r
+    // Create the CM request\r
+    ib_cm_req_t cm_req;\r
+    CreateCmRequest(&cm_req, &hello_msg, &path_rec, pWspConnectIn->Port);\r
+\r
+    // Create the event to wait on to the connection request to end:\r
+    KeInitializeEvent(&m_ConnectCmCompleteEvent, NotificationEvent, FALSE );   \r
+\r
+    m_state = SS_CONNECTING_REQ_SENT;\r
+    \r
+    ib_status = ib_cm_req( &cm_req );\r
+    if( ib_status != IB_SUCCESS ) {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("ib_open_ca failed ib_status = 0x%d\n", ib_status ));\r
+        rc = IB2Status(ib_status);\r
+        pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
+        goto Cleanup;\r
+    }\r
+\r
+    rc = MyKeWaitForSingleObject(\r
+                &m_ConnectCmCompleteEvent,\r
+                UserRequest,\r
+                UserMode,\r
+                FALSE,\r
+                NULL);\r
+\r
+    if (( rc == STATUS_ALERTED ) ||( rc == STATUS_USER_APC )) {\r
+        // BUGBUG: Think what to do here, we should be able to stop the\r
+        // connect, and quit (probably shutdown should be enough)\r
+        SDP_PRINT(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
+\r
+    //\r
+    // We have recieved the REP, we send the RTU code\r
+    //  \r
+    \r
+    m_state = SS_CONNECTING_REQ_SENT;\r
+\r
+    rc = CmSendRTU();\r
+    if (!NT_SUCCESS(rc)) {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("CmSendRTU failed rc = 0x%x\n", rc ));\r
+        pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
+        goto Cleanup;\r
+    }    \r
+\r
+    // we should now complete the request\r
+    Lock.Lock();    \r
+    if (m_state == SS_CONNECTED) {\r
+        pWspConnectOut->Errno = 0;\r
+        ASSERT(rc == STATUS_SUCCESS);\r
+        Lock.Unlock();\r
+        goto Cleanup;\r
+    } else {\r
+        // There probably was some error or some kind of shutdown, we \r
+        // need to return an error.\r
+        rc = STATUS_UNEXPECTED_IO_ERROR;\r
+        pWspConnectOut->Errno = WSAENETUNREACH; // BUGBUG: verify this error\r
+        Lock.Unlock();\r
+        goto Cleanup;\r
+    }\r
+\r
+Cleanup:\r
+    // Make sure that success/failure is marked in both places\r
+    ASSERT(((pWspConnectOut->Errno == 0) && (NT_SUCCESS(rc))) |\r
+           ((pWspConnectOut->Errno != 0) && (!NT_SUCCESS(rc))));\r
+\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("connect is returning %s this = 0x%p\n",\r
+        NT_SUCCESS(rc) ? "SUCCESS" : "FAILURE", this ));    \r
+    return rc;\r
+\r
+}\r
+\r
+\r
+NTSTATUS SdpSocket::CmSendRTU()\r
+{\r
+    // This is only valid in connect.\r
+    // We might also be in shutdown, but nothing else currently\r
+    \r
+    ib_api_status_t ib_status;\r
+    NTSTATUS rc = STATUS_SUCCESS;\r
+\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("SdpSocket::CmSendRTU 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
+        rc = STATUS_UNEXPECTED_IO_ERROR;\r
+        goto Cleanup;\r
+    } \r
+    \r
+    /*\r
+     * check Hello Header Ack, to determine if we want\r
+     * the connection.\r
+     */\r
+\r
+    rc = sdp_cm_hello_ack_check(&m_hello_ack);\r
+    if (!NT_SUCCESS(rc)) {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("sdp_cm_hello_ack_check failed rc = 0x%x\n", rc ));\r
+        goto Cleanup;\r
+    }         \r
+\r
+#if 0\r
+    /*\r
+     * read remote information\r
+     */\r
+    conn->send_size = hello_ack->hah.l_rcv_size;\r
+    conn->r_max_adv = hello_ack->hah.max_adv;\r
+    conn->r_recv_bf = hello_ack->bsdh.recv_bufs;\r
+    conn->recv_seq  = hello_ack->bsdh.seq_num;\r
+    conn->advt_seq  = hello_ack->bsdh.seq_num;\r
+\r
+    conn->d_qpn  = event->param.rep_rcvd.remote_qpn;\r
+    /*\r
+     * The maximum amount of data that can be sent to the remote\r
+     * peer is the smaller of the local and remote buffer sizes, \r
+     * minus the size of the message header.\r
+     */\r
+    conn->send_size = min((u16)sdp_buff_pool_buff_size(),\r
+            (u16)conn->send_size) - SDP_MSG_HDR_SIZE;\r
+\r
+#endif\r
+    /*\r
+     * Pop the hello message that was sent ????? I don't think that we need this\r
+     */\r
+\r
+    ib_cm_rtu_t cm_rtu;\r
+\r
+    memset( &cm_rtu, 0, sizeof(cm_rtu) );\r
+\r
+    cm_rtu.access_ctrl = IB_AC_RDMA_READ | IB_AC_RDMA_WRITE | IB_AC_LOCAL_WRITE;\r
+\r
+#if 0 // Do we want to keep it\r
+    // Bug in TAVOR\r
+    cm_rtu.sq_depth = QP_ATTRIB_SQ_DEPTH;\r
+    cm_rtu.rq_depth = QP_ATTRIB_RQ_DEPTH;\r
+#endif\r
+\r
+    cm_rtu.pfn_cm_apr_cb = cm_apr_callback;\r
+    cm_rtu.pfn_cm_dreq_cb = cm_dreq_callback;\r
+    \r
+    ib_status = ib_cm_rtu( m_cm_handle_t, &cm_rtu );\r
+    if( ib_status != IB_SUCCESS ) {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("ib_cm_rtu failed ib_status = 0x%d\n", ib_status ));\r
+        rc = IB2Status(ib_status);\r
+        goto Cleanup;\r
+    }\r
+    // We are now connected\r
+    // How should this be locked ??\r
+    m_state = SS_CONNECTED;\r
+\r
 Cleanup:    \r
     return rc;\r
+}\r
+\r
+\r
+VOID SdpSocket::CmRepCallback(IN   ib_cm_rep_rec_t *p_cm_rep_rec)\r
+{\r
+    if (m_state != SS_CONNECTING_REQ_SENT) {\r
+        // This is not the state that we waited for, not much that we can\r
+        // do. (This might happen in shutdown)\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("SdpSocket::CmRepCallback Not the expacted state %s\n", SS2String(m_state)));\r
+        ASSERT(FALSE);\r
+        return;\r
+    }\r
+\r
+    // We need to store the params and signal the event\r
+    sdp_msg_hello_ack *hello_ack = (sdp_msg_hello_ack *)p_cm_rep_rec->p_rep_pdata;\r
+    m_hello_ack = *hello_ack;\r
+    m_cm_handle_t = p_cm_rep_rec->h_cm_rep;\r
 \r
+    KeSetEvent(&m_ConnectCmCompleteEvent, IO_NO_INCREMENT, FALSE);\r
 }\r
 \r
 \r
+// BUGBUG: based on __recv_cb - need to implment\r
+static void\r
+__recv_cb1(\r
+    IN  const  ib_cq_handle_t                          h_cq,\r
+    IN                         void                                            *cq_context )\r
+{\r
+//    status = ib_rearm_cq(\r
+//        p_port->ib_mgr.h_recv_cq, FALSE );\r
+//    ASSERT(exp)( status == IB_SUCCESS );\r
+    ASSERT(FALSE);\r
+}\r
+\r
+\r
+\r
+// BUGBUG: This code is based on __cq_event, find out what it realy does\r
+static void\r
+__cq_event1(\r
+    IN  ib_async_event_rec_t           *p_event_rec )\r
+{\r
+    ASSERT(FALSE);\r
+    UNUSED_PARAM( p_event_rec );\r
+    ASSERT( p_event_rec->context );\r
+    /* Place holder for proper error handler. */\r
+    ASSERT( p_event_rec->code == IB_AE_UNKNOWN );\r
+}\r
+\r
+\r
+// Based on __qp_event - do we need it?\r
+static void\r
+__qp_event1(\r
+    IN          ib_async_event_rec_t        *p_event_rec )\r
+{\r
+    UNUSED_PARAM( p_event_rec );\r
+    ASSERT( p_event_rec->context );\r
+    /* Place holder for proper error handler. */\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("Async QP event: %d\n", p_event_rec->code));\r
+    ASSERT( p_event_rec->code == IB_AE_UNKNOWN );\r
+}\r
+\r
+\r
+// This currently works only for the connect\r
+NTSTATUS SdpSocket::CreateQp()\r
+{\r
+    NTSTATUS rc = STATUS_SUCCESS;\r
+    ib_cq_create_t  cq_create;\r
+    ib_qp_create_t    qp_create;\r
+    ib_api_status_t ib_status;\r
+\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("CreateQp called this = 0x%p\n", this));\r
+    /* Open the CA. */\r
+    ib_status = ib_open_ca(\r
+        g_pSdpDriver->m_al_handle, \r
+        m_CaGuid,\r
+        NULL, \r
+        this, \r
+        &mh_Ca \r
+        );\r
+    if( ib_status != IB_SUCCESS ) {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("ib_open_ca failed ib_status = 0x%d\n", ib_status ));\r
+        rc = IB2Status(ib_status);\r
+        goto Cleanup;\r
+    }\r
+\r
+    /* Allocate the PD. */\r
+    ib_status = ib_alloc_pd(\r
+        mh_Ca, \r
+        IB_PDT_NORMAL, \r
+        this, \r
+        &m_pd \r
+    );\r
+    \r
+    if( ib_status != IB_SUCCESS )\r
+    {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("ib_alloc_pd failed ib_status = 0x%d\n", ib_status ));\r
+        rc = IB2Status(ib_status);\r
+        goto Cleanup;\r
+    }\r
+\r
+    /* Allocate receive CQ. */\r
+    cq_create.size = QP_ATTRIB_RQ_DEPTH;\r
+    cq_create.pfn_comp_cb = __recv_cb1;\r
+    cq_create.h_wait_obj = NULL;\r
+\r
+    ib_status = ib_create_cq(\r
+                    mh_Ca, \r
+                    &cq_create, \r
+                    this,\r
+                    __cq_event1,  \r
+                    &m_rcq \r
+                    );\r
+\r
+    if( ib_status != IB_SUCCESS ) {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("ib_create_cq failed ib_status = 0x%d\n", ib_status ));\r
+        rc = IB2Status(ib_status);\r
+        goto Cleanup;\r
+    }\r
+\r
+    /* Allocate send CQ. */\r
+    cq_create.size = QP_ATTRIB_SQ_DEPTH;\r
+    cq_create.pfn_comp_cb = __recv_cb1; // ???? We are not doing anything there ??? why bother\r
+\r
+    ib_status = ib_create_cq(\r
+                    mh_Ca, \r
+                    &cq_create, \r
+                    this,\r
+                    __cq_event1,  \r
+                    &m_scq \r
+                    );\r
+\r
+    if( ib_status != IB_SUCCESS ) {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("ib_create_cq failed ib_status = 0x%d\n", ib_status ));\r
+        rc = IB2Status(ib_status);\r
+        goto Cleanup;\r
+    }\r
+\r
+    /* Allocate the QP. */\r
+    cl_memclr( &qp_create, sizeof(qp_create) );\r
+    qp_create.qp_type = IB_QPT_RELIABLE_CONN;\r
+    qp_create.rq_depth = QP_ATTRIB_RQ_DEPTH;\r
+    qp_create.rq_sge = QP_ATTRIB_RQ_SGE;       /* To support buffers spanning pages. */\r
+    qp_create.h_rq_cq = m_rcq;\r
+    qp_create.sq_depth = QP_ATTRIB_SQ_DEPTH;\r
+    //TODO: Figure out the right number of SGE entries for sends.\r
+    qp_create.sq_sge = QP_ATTRIB_SQ_SGE;\r
+    qp_create.h_sq_cq = m_scq;\r
+    qp_create.sq_signaled = TRUE;\r
+    ib_status = ib_create_qp( m_pd, &qp_create, this, __qp_event1, &m_qp );\r
+    if( ib_status != IB_SUCCESS ) {\r
+        SDP_PRINT(SDP_ERR, SDP_SOCKET, ("ib_create_qp failed ib_status = 0x%d\n", ib_status ));\r
+        rc = IB2Status(ib_status);\r
+        goto Cleanup;\r
+    }\r
+#if 0    \r
+    /* Query the QP so we can get our QPN. */\r
+    status = p_port->p_adapter->p_ifc->query_qp(\r
+       p_port->ib_mgr.h_qp, &qp_attr );\r
+    if( status != IB_SUCCESS )\r
+    {\r
+       IPOIB_TRACE_EXIT( IPOIB_DBG_ERROR,\r
+               ("ib_query_qp returned %s\n", \r
+               p_port->p_adapter->p_ifc->get_err_str( status )) );\r
+       return status;\r
+    }\r
+    p_port->ib_mgr.qpn = qp_attr.num;\r
+#endif    \r
+           \r
+Cleanup:\r
+    return rc;\r
+\r
+}\r
+\r
+VOID SdpSocket::CreateHelloHeader(\r
+                        sdp_msg_hello *hello_msg, \r
+                        ULONG DestIp\r
+                         \r
+                        )\r
+{\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("SdpSocket::CreateHelloHeader called this = 0x%p\n", this));\r
+    ASSERT(DestIp != 0);\r
+    ASSERT(m_SrcPort != 0);\r
+    ASSERT(m_SrcIp != 0);\r
+\r
+    memset(hello_msg, 0, sizeof(struct sdp_msg_hello));\r
+    hello_msg->bsdh.recv_bufs = QP_ATTRIB_RQ_DEPTH; //????conn->l_advt_bf;\r
+    hello_msg->bsdh.flags     = SDP_MSG_FLAG_NON_FLAG;\r
+    hello_msg->bsdh.mid       = SDP_MID_HELLO;\r
+    hello_msg->bsdh.size      = sizeof(struct sdp_msg_hello);\r
+    hello_msg->bsdh.seq_num   = 0;//conn->send_seq; ???\r
+    hello_msg->bsdh.seq_ack   = 0;//conn->advt_seq; ???\r
+\r
+    hello_msg->hh.max_adv       = QP_ATTRIB_RQ_DEPTH;// ??? conn->l_max_adv;\r
+    hello_msg->hh.ip_ver        = SDP_MSG_IPVER;\r
+    hello_msg->hh.version       = SDP_MSG_VERSION;\r
+    hello_msg->hh.r_rcv_size    = 4096;//???conn->recv_size;\r
+    hello_msg->hh.l_rcv_size    = 4096;//???conn->recv_size;\r
+    hello_msg->hh.port          = m_SrcPort;\r
+    hello_msg->hh.src.ipv4.addr = m_SrcIp;\r
+    hello_msg->hh.dst.ipv4.addr = DestIp;\r
+\r
+    /*\r
+     * endian swap\r
+     */\r
+    sdp_msg_swap_bsdh(&hello_msg->bsdh);\r
+    sdp_msg_swap_hh(&hello_msg->hh);\r
+\r
+\r
+}\r
+\r
+VOID SdpSocket::CreateCmRequest(\r
+        ib_cm_req_t *cm_req,\r
+        sdp_msg_hello *hello_msg,\r
+        ib_path_rec_t *path_rec,\r
+        USHORT DestPort\r
+    )\r
+{\r
+\r
+    memset( cm_req, 0, sizeof(ib_cm_req_t) );\r
+    cm_req->qp_type = IB_QPT_RELIABLE_CONN;\r
+    cm_req->h_qp = m_qp;\r
+    cm_req->p_primary_path = path_rec;\r
+    cm_req->p_alt_path = NULL;\r
+    cm_req->svc_id = get_service_id_for_port(DestPort );\r
+    cm_req->p_req_pdata = (uint8_t *) hello_msg;\r
+    cm_req->req_length = sizeof(sdp_msg_hello);\r
+\r
+    // Caution: From here we live the linux code, as it was in: gen2 - sdp_cm_path_complete\r
+    cm_req->max_cm_retries = CM_RETRIES;\r
+    cm_req->resp_res = 4;//???????? what are this??? QP_ATTRIB_RESPONDER_RESOURCES;\r
+    cm_req->init_depth = 4;//?????QP_ATTRIB_INITIATOR_DEPTH;\r
+\r
+    cm_req->remote_resp_timeout =\r
+         ib_path_rec_pkt_life( path_rec ) + CM_REMOTE_TIMEOUT;\r
+       if( cm_req->remote_resp_timeout > 0x1F )\r
+       cm_req->remote_resp_timeout = 0x1F;\r
+        else if( cm_req->remote_resp_timeout < CM_MIN_REMOTE_TIMEOUT )\r
+        cm_req->remote_resp_timeout = CM_MIN_REMOTE_TIMEOUT;\r
+\r
+    cm_req->flow_ctrl = TRUE;  /* HCAs must support end-to-end flow control. */\r
+\r
+    cm_req->local_resp_timeout =\r
+       ib_path_rec_pkt_life( path_rec ) + CM_LOCAL_TIMEOUT;\r
+        if( cm_req->local_resp_timeout > 0x1F )\r
+       cm_req->local_resp_timeout = 0x1F;\r
+        else if( cm_req->local_resp_timeout < CM_MIN_LOCAL_TIMEOUT )\r
+        cm_req->local_resp_timeout = CM_MIN_LOCAL_TIMEOUT;\r
+\r
+    cm_req->rnr_nak_timeout = 6;//???QP_ATTRIB_RNR_NAK_TIMEOUT;\r
+    cm_req->rnr_retry_cnt = 6;//????QP_ATTRIB_RNR_RETRY;\r
+    cm_req->retry_cnt = 6;//????QP_ATTRIB_RETRY_COUNT;\r
+\r
+    cm_req->pfn_cm_req_cb = cm_req_callback;\r
+    cm_req->pfn_cm_mra_cb = cm_mra_callback;\r
+    cm_req->pfn_cm_rej_cb = cm_rej_callback;\r
+    cm_req->pfn_cm_rep_cb = cm_rep_callback;\r
+}\r
 \r
 VOID SdpSocket::Shutdown()\r
 {\r
-    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("SdpSocket::Shutdown called this = 0x%x\n", this));\r
+    //???? locking\r
+    // if(m_shutdown) ???\r
+    m_shutdown = true;\r
+\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("SdpSocket::Shutdown called this = 0x%p\n", this));\r
+\r
+    if (m_qp != NULL) {\r
+        ib_destroy_qp(m_qp, NULL); //?????? CALL BACK ??? IMPLMENT\r
+    }\r
+\r
+    if (m_scq != NULL) {\r
+        ib_destroy_cq(m_scq, NULL); //?????? CALL BACK ??? IMPLMENT\r
+    }\r
+\r
+    if (m_rcq != NULL) {\r
+        ib_destroy_cq(m_rcq, NULL); //?????? CALL BACK ??? IMPLMENT\r
+    }\r
+\r
+    if (m_pd != NULL) {\r
+        ib_dealloc_pd(m_pd, NULL); //?????? CALL BACK ??? IMPLMENT\r
+    }\r
+\r
+    if (mh_Ca != NULL) {\r
+        ib_close_ca(mh_Ca, NULL); //?????? CALL BACK ??? IMPLMENT\r
+    }\r
+}\r
+\r
+/*\r
+ * sdp_cm_hello_ack_check - validate the hello ack header\r
+ */\r
+NTSTATUS sdp_cm_hello_ack_check(struct sdp_msg_hello_ack *hello_ack)\r
+{\r
+    /*\r
+     * endian swap\r
+     */\r
+    sdp_msg_swap_bsdh(&hello_ack->bsdh);\r
+    sdp_msg_net_to_cpu_hah(&hello_ack->hah);\r
+    /*\r
+     * validation and consistency checks\r
+     */\r
+    if (hello_ack->bsdh.size != sizeof(struct sdp_msg_hello_ack)) {\r
+        SDP_PRINT(SDP_WARN, SDP_SOCKET, ("hello ack, size mismatch. (2) <%d:%d>",\r
+                hello_ack->bsdh.size,\r
+                sizeof(struct sdp_msg_hello_ack)));\r
+        return STATUS_UNEXPECTED_IO_ERROR;\r
+    }\r
+\r
+    if (SDP_MID_HELLO_ACK != hello_ack->bsdh.mid) {\r
+        SDP_PRINT(SDP_WARN, SDP_SOCKET, ("hello ack, unexpected message. <%d>",\r
+                hello_ack->bsdh.mid\r
+                ));\r
+        return STATUS_UNEXPECTED_IO_ERROR;        \r
+    }\r
 \r
+    if (hello_ack->hah.max_adv <= 0) {\r
+        SDP_PRINT(SDP_WARN, SDP_SOCKET, ("hello ack, bad zcopy advertisment. <%d>",\r
+                hello_ack->hah.max_adv\r
+                ));\r
+        return STATUS_UNEXPECTED_IO_ERROR;                \r
+    }\r
 \r
+    if ((0xF0 & hello_ack->hah.version) != (0xF0 & SDP_MSG_VERSION)) {\r
+        SDP_PRINT(SDP_WARN, SDP_SOCKET, ("hello ack, version mismatch. <%d:%d>",\r
+                ((0xF0 & hello_ack->hah.version) >> 4),\r
+                ((0xF0 & SDP_MSG_VERSION) >> 4)));\r
+        return STATUS_UNEXPECTED_IO_ERROR;                        \r
+    }\r
+\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("Hello Ack BSDH <%04x:%02x:%02x:%08x:%08x:%08x>",\r
+            hello_ack->bsdh.recv_bufs,\r
+            hello_ack->bsdh.flags,\r
+            hello_ack->bsdh.mid,\r
+            hello_ack->bsdh.size,\r
+            hello_ack->bsdh.seq_num,\r
+            hello_ack->bsdh.seq_ack));\r
+    SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("Hello Ack HAH <%02x:%02x:%08x",\r
+            hello_ack->hah.max_adv,\r
+            hello_ack->hah.version, \r
+            hello_ack->hah.l_rcv_size));\r
+\r
+    return STATUS_SUCCESS;\r
 }\r
 \r
+\r
+\r
index 9dc1479..24e402e 100644 (file)
@@ -12,14 +12,60 @@ It keeps a list of all the objects so we know when to remove them.
 #define _SDP_SOCKET_H\r
 \r
 \r
+#define QP_ATTRIB_SQ_DEPTH                             16\r
+#define QP_ATTRIB_SQ_SGE                               1       /* Set based on inline data requirements */\r
+\r
+/* \r
+ * TODO: During testing, the switch has been observed to post\r
+ * 12 receive buffers.  It would be nice to know what the max is.\r
+ */\r
+#define QP_ATTRIB_RQ_DEPTH                             16\r
+#define QP_ATTRIB_RQ_SGE                               1\r
+\r
+/* Number of entries in a CQ */\r
+#define IB_CQ_SIZE (QP_ATTRIB_SQ_DEPTH + QP_ATTRIB_RQ_DEPTH + 1)\r
+\r
+enum SocketStates {\r
+    SS_IDLE,\r
+    SS_CONNECTING_QPR_SENT, // QPR = Query path record\r
+    SS_CONNECTING_REQ_SENT,\r
+    SS_CONNECTING_RTU_SENT,\r
+    SS_CONNECTED,\r
+    SS_INSHUTDOWN\r
+};\r
+\r
+\r
 class SdpSocket : public RefCountImpl {\r
 private: \r
+   \r
+    SocketStates m_state;\r
+    \r
     // This flags are being Initiated when the socket is being\r
     // created\r
     ULONG m_CreationFlags;\r
 \r
-    \r
+    USHORT m_SrcPort;\r
+    ULONG  m_SrcIp;\r
+\r
+\r
+    KSPIN_LOCK  m_Lock;\r
+    bool        m_shutdown;\r
+\r
+\r
+    // A handle to the ca that is being used (in connect) and its guid\r
+    ib_ca_handle_t          mh_Ca;\r
+    net64_t                 m_CaGuid;\r
+\r
+    ib_pd_handle_t          m_pd;\r
+    ib_cq_handle_t          m_rcq;\r
+    ib_cq_handle_t          m_scq;\r
+    ib_qp_handle_t          m_qp;\r
+\r
+    KEVENT                  m_ConnectCmCompleteEvent;\r
+\r
 public:\r
+    SdpSocket();\r
+\r
     NTSTATUS Init(\r
         WspSocketIn     *pSocketInParam, \r
         WspSocketOut    *pSocketOutParam\r
@@ -33,7 +79,48 @@ public:
     VOID Shutdown();\r
 \r
 \r
+    NTSTATUS CreateQp();\r
+\r
+    NTSTATUS CmSendRTU();\r
+    \r
+    VOID CreateHelloHeader(\r
+        sdp_msg_hello *hello_msg, \r
+        ULONG DestIp\r
+        );\r
+\r
+    VOID CreateCmRequest(\r
+        ib_cm_req_t *cm_req,\r
+        sdp_msg_hello *hello_msg,\r
+        ib_path_rec_t *path_rec,\r
+        USHORT DestPort\r
+    );\r
+\r
+    VOID CmRepCallback(IN   ib_cm_rep_rec_t *p_cm_rep_rec);\r
+    // Two varibales that are needed for passing REP data\r
+    struct sdp_msg_hello_ack m_hello_ack;\r
+    ib_cm_handle_t m_cm_handle_t; // BUGBUG: Check how this is used / locked\r
+\r
+    \r
+\r
+    // Used to allow the user file to remember us\r
     LIST_ENTRY m_UserFileList;\r
+\r
+#ifdef DBG\r
+    char * SS2String(SocketStates state) {\r
+        switch (state) {\r
+            case SS_IDLE                    : return "SS_IDLE";\r
+            case SS_CONNECTING_REQ_SENT     : return "SS_CONNECTING_REQ_SENT";\r
+            case SS_CONNECTING_RTU_SENT     : return "SS_CONNECTING_RTU_SENT";\r
+            case SS_CONNECTED               : return "SS_CONNECTED";\r
+            case SS_INSHUTDOWN              : return "SS_INSHUTDOWN";\r
+            default : \r
+                ASSERT(FALSE);\r
+\r
+        }\r
+        return "Unknown state";\r
+    }\r
+#endif\r
+    \r
 };\r
 \r
 #endif // _SDP_SOCKET_H\r
index 556be79..fe7b48a 100644 (file)
@@ -14,6 +14,7 @@
 #define SDP_CONNECT        0x000002\r
 #define SDP_DRIVER             0x000004\r
 #define SDP_SOCKET             0x000008\r
+#define SDP_ARP                0x000010\r
 \r
 // BUGBUG: CONVERT TO A FUNCTION\r
 \r