[CORE, TESTS] This patch adds a library and test utility that performs IP to IB addre...
authorleonidk <leonidk@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Thu, 3 Jul 2008 08:22:07 +0000 (08:22 +0000)
committerleonidk <leonidk@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Thu, 3 Jul 2008 08:22:07 +0000 (08:22 +0000)
It's a sequence of operations between the IP helper library and IPoIB.

1. Get the local IPoIB port's IB address information (GID).
2. Lookup the destination MAC address via the IP Helper functions, send ARP if needed 3. Ask IPoIB for the destination IB address information given the destination Ethernet MAC.

As input, the IBAT library takes two IP addresses (v4 or v6).  As output, it returns two GIDs (as IN6_ADDRs), as well as the pkey.

There's a test program, wherebu, that will exercise the IBAT library.

Note that there is special code for Windows Vista/Server 2008 to take advantage of newer functionality in the IP Helper library.  Without this lookups get quite slow as you increase the number of nodes.  On our 256 node cluster the Windows Server 2008 code path performed an order of magnitude better than the Windows Server 2003 code path.

There will be a follow up patch that moves WSD over to using this library.

Signed-off-by: Fab Tillier <ftillier@microsoft.com>
git-svn-id: svn://openib.tc.cornell.edu/gen1/trunk@1331 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

13 files changed:
core/dirs
core/ibat/dirs [new file with mode: 0644]
core/ibat/user/SOURCES [new file with mode: 0644]
core/ibat/user/ibat.cpp [new file with mode: 0644]
core/ibat/user/makefile [new file with mode: 0644]
inc/iba/ib_at_ioctl.h
inc/user/iba/ibat.h [new file with mode: 0644]
tests/dirs
tests/wherebu/dirs [new file with mode: 0644]
tests/wherebu/user/SOURCES [new file with mode: 0644]
tests/wherebu/user/makefile [new file with mode: 0644]
tests/wherebu/user/wherebu.cpp [new file with mode: 0644]
ulp/ipoib/kernel/ipoib_ibat.c

index ec1177b..2dc3235 100644 (file)
--- a/core/dirs
+++ b/core/dirs
@@ -2,4 +2,5 @@ DIRS=\
        complib \\r
        al              \\r
        bus             \\r
-       iou\r
+       iou             \\r
+       ibat\r
diff --git a/core/ibat/dirs b/core/ibat/dirs
new file mode 100644 (file)
index 0000000..389156f
--- /dev/null
@@ -0,0 +1,2 @@
+DIRS=\\r
+       user\r
diff --git a/core/ibat/user/SOURCES b/core/ibat/user/SOURCES
new file mode 100644 (file)
index 0000000..a29928f
--- /dev/null
@@ -0,0 +1,14 @@
+TARGETNAME=ibat\r
+\r
+TARGETPATH=..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE=LIBRARY\r
+\r
+SOURCES=\\r
+       ibat.cpp\r
+\r
+\r
+INCLUDES=$(SDK_INC_PATH);..;..\..\..\inc;..\..\..\inc\user;$(PLATFORM_SDK_PATH)\Include\r
+\r
+USER_C_FLAGS=$(USER_C_FLAGS)\r
+\r
+MSC_WARNING_LEVEL= /W4\r
diff --git a/core/ibat/user/ibat.cpp b/core/ibat/user/ibat.cpp
new file mode 100644 (file)
index 0000000..f6b2408
--- /dev/null
@@ -0,0 +1,400 @@
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+//\r
+// IBAT: InfiniBand Address Translation\r
+//\r
+// Description:\r
+//  Maps remote IP addresses (IPv4 and IPv6) to the remote GID.\r
+//\r
+//  The mapping requires two steps:\r
+//      1. Mapping the remote IP address to the remote Ethernet MAC address\r
+//      2. Retrieve the remote GID given the remote Ethernet MAC address\r
+//      from IPoIB\r
+//\r
+//  The first step is accomplished as follows on Windows Server 2008:\r
+//      1. Lookup the desired MAC from the OS using GetIpNetEntry2\r
+//      2. If the remote IP isn't found, resolve the remote IP address\r
+//      using ResolveIpNetEntry2\r
+//\r
+//  The first step is accomplished as follows on Windows Server 2003:\r
+//      1. Retrieve the whole IP->MAC mapping table from the OS using\r
+//      GetIpNetTable.\r
+//      2. Walk the returned table looking for the destination IP to\r
+//      find the destination Ethernet MAC address.\r
+//      3. If the remote IP isn't found, resolve the remote IP address using\r
+//      SendARP.\r
+//\r
+//  The second step is accomplished by asking IPoIB for the remote GID\r
+//  given the remote MAC.\r
+\r
+#pragma warning( push, 3 )\r
+#include <windows.h>\r
+#include <stdlib.h>\r
+#include <winioctl.h>\r
+#pragma warning( pop )\r
+#include "iba/ibat.h"\r
+#include <iphlpapi.h>\r
+#include "iba/ib_at_ioctl.h"\r
+\r
+\r
+namespace IBAT\r
+{\r
+\r
+    const IN6_ADDR x_DefaultGid = {0xFE,0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0};\r
+\r
+class H\r
+{\r
+public:\r
+    H( HANDLE h = INVALID_HANDLE_VALUE ) : m_h( h ) {};\r
+    ~H(){ if( m_h != INVALID_HANDLE_VALUE ) CloseHandle( m_h ); }\r
+\r
+    H& operator =(HANDLE h){ CloseHandle( m_h ); m_h = h; }\r
+    operator HANDLE() const { return m_h; }\r
+\r
+private:\r
+    HANDLE m_h;\r
+};\r
+\r
+#if WINVER >= 0x600\r
+HRESULT\r
+Resolve(\r
+    __in const struct sockaddr* pSrcAddr,\r
+    __in const struct sockaddr* pDestAddr,\r
+    __out IN6_ADDR* pSrcGid,\r
+    __out IN6_ADDR* pDestGid,\r
+    __out USHORT* pPkey\r
+    )\r
+{\r
+    if( pSrcAddr->sa_family != pDestAddr->sa_family )\r
+        return E_INVALIDARG;\r
+\r
+    H hIbatDev = CreateFileW( IBAT_WIN32_NAME,\r
+        MAXIMUM_ALLOWED, 0, NULL,\r
+        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
+    if( hIbatDev == INVALID_HANDLE_VALUE )\r
+        return HRESULT_FROM_WIN32( GetLastError() );\r
+\r
+    bool fLoopback;\r
+    IOCTL_IBAT_IP_TO_PORT_IN port_in;\r
+    port_in.Version = IBAT_IOCTL_VERSION;\r
+    if( pSrcAddr->sa_family == AF_INET )\r
+    {\r
+        port_in.Address.IpVersion = 4;\r
+        RtlCopyMemory(\r
+            &port_in.Address.Address[12],\r
+            &((struct sockaddr_in*)pSrcAddr)->sin_addr,\r
+            sizeof( ((struct sockaddr_in*)pSrcAddr)->sin_addr ) );\r
+\r
+        fLoopback = ((struct sockaddr_in*)pDestAddr)->sin_addr.s_addr ==\r
+            ((struct sockaddr_in*)pSrcAddr)->sin_addr.s_addr;\r
+    }\r
+    else\r
+    {\r
+        port_in.Address.IpVersion = 6;\r
+        RtlCopyMemory(\r
+            port_in.Address.Address,\r
+            &((struct sockaddr_in6*)pSrcAddr)->sin6_addr,\r
+            sizeof(port_in.Address.Address) );\r
+        fLoopback = IN6_ADDR_EQUAL(\r
+            &((struct sockaddr_in6*)pDestAddr)->sin6_addr,\r
+            &((struct sockaddr_in6*)pSrcAddr)->sin6_addr\r
+            ) == TRUE;\r
+    }\r
+\r
+    IBAT_PORT_RECORD port_out;\r
+    DWORD size;\r
+    BOOL fSuccess = DeviceIoControl( hIbatDev, IOCTL_IBAT_IP_TO_PORT,\r
+        &port_in, sizeof(port_in), &port_out, sizeof(port_out), &size, NULL );\r
+\r
+    if( !fSuccess )\r
+        return HRESULT_FROM_WIN32( GetLastError() );\r
+\r
+    // Check for loopback.\r
+    if( fLoopback )\r
+    {\r
+        *pSrcGid = x_DefaultGid;\r
+        RtlCopyMemory(\r
+            &pSrcGid->u.Byte[8],\r
+            &port_out.PortGuid,\r
+            sizeof(port_out.PortGuid) );\r
+        *pDestGid = *pSrcGid;\r
+        *pPkey = port_out.PKey;\r
+        return S_OK;\r
+    }\r
+\r
+    NET_LUID luid;\r
+    DWORD ret;\r
+    do\r
+    {\r
+        DWORD iIf;\r
+        ret = GetBestInterfaceEx( (struct sockaddr*)pSrcAddr, &iIf );\r
+        if( ret != NO_ERROR )\r
+            return HRESULT_FROM_WIN32( ret );\r
+\r
+        // Interface indexes are not constant, so get the LUID mapping for the\r
+        // returned interface for use in the rest of the function.\r
+        ret = ConvertInterfaceIndexToLuid( iIf, &luid );\r
+\r
+    } while( ret != NO_ERROR );\r
+\r
+    SOCKADDR_INET src;\r
+    MIB_IPNET_ROW2 net = {0};\r
+    net.InterfaceLuid = luid;\r
+    switch( pDestAddr->sa_family )\r
+    {\r
+    case AF_INET:\r
+        net.Address.si_family = src.si_family = AF_INET;\r
+        net.Address.Ipv4 = *(struct sockaddr_in*)pDestAddr;\r
+        src.Ipv4 = *(struct sockaddr_in*)pSrcAddr;\r
+        break;\r
+\r
+    case AF_INET6:\r
+        net.Address.si_family = src.si_family = AF_INET6;\r
+        net.Address.Ipv6 = *(struct sockaddr_in6*)pDestAddr;\r
+        src.Ipv6 = *(struct sockaddr_in6*)pSrcAddr;\r
+        break;\r
+\r
+    default:\r
+        return E_INVALIDARG;\r
+    }\r
+\r
+    bool fRetry = true;\r
+retry:\r
+    ret = GetIpNetEntry2( &net );\r
+    if( ret != NO_ERROR )\r
+        return HRESULT_FROM_WIN32( ret );\r
+\r
+    switch( net.State )\r
+    {\r
+    default:\r
+    case NlnsUnreachable:\r
+        ret = ResolveIpNetEntry2( &net, &src );\r
+        if( ret == ERROR_BAD_NET_NAME && fRetry )\r
+        {\r
+            fRetry = false;\r
+            goto retry;\r
+        }\r
+        else if( ret != NO_ERROR )\r
+        {\r
+            return HRESULT_FROM_WIN32( ret );\r
+        }\r
+        break;\r
+\r
+    case NlnsReachable:\r
+    case NlnsPermanent:\r
+        break;\r
+\r
+    case NlnsIncomplete:\r
+        return E_PENDING;\r
+    }\r
+\r
+    if( net.PhysicalAddressLength > 6 )\r
+        return E_UNEXPECTED;\r
+\r
+    IOCTL_IBAT_MAC_TO_GID_IN mac_in;\r
+    mac_in.Version = IBAT_IOCTL_VERSION;\r
+    mac_in.PortGuid = port_out.PortGuid;\r
+    RtlCopyMemory( mac_in.DestMac, net.PhysicalAddress, IBAT_MAC_LEN );\r
+\r
+    fSuccess = DeviceIoControl( hIbatDev, IOCTL_IBAT_MAC_TO_GID,\r
+        &mac_in, sizeof(mac_in), pDestGid, sizeof(*pDestGid), &size, NULL );\r
+    if( !fSuccess )\r
+        return HRESULT_FROM_WIN32( GetLastError() );\r
+\r
+    // Use the same subnet prefix as the destination.\r
+    *pSrcGid = *pDestGid;\r
+    RtlCopyMemory( &pSrcGid->u.Byte[8], &port_out.PortGuid, sizeof(port_out.PortGuid) );\r
+    *pPkey = port_out.PKey;\r
+    return S_OK;\r
+}\r
+#else   // Back compatibility with Windows Server 2003\r
+\r
+\r
+static HRESULT\r
+GetDestMac(\r
+    __in struct sockaddr_in* pDestAddr,\r
+    __out BYTE* pDestMac\r
+    )\r
+{\r
+    DWORD ret;\r
+\r
+    MIB_IPNETTABLE* pTable = NULL;\r
+    ULONG len = 0;\r
+    do\r
+    {\r
+        ret = GetIpNetTable( pTable, &len, FALSE );\r
+        if( ret != ERROR_INSUFFICIENT_BUFFER )\r
+            break;\r
+\r
+        if( pTable != NULL )\r
+        {\r
+            HeapFree( GetProcessHeap(), 0, pTable );\r
+        }\r
+\r
+        pTable = (MIB_IPNETTABLE*)HeapAlloc( GetProcessHeap(), 0, len );\r
+    } while( ret == ERROR_INSUFFICIENT_BUFFER );\r
+\r
+    if( ret != NO_ERROR )\r
+    {\r
+        if( pTable != NULL )\r
+        {\r
+            HeapFree( GetProcessHeap(), 0, pTable );\r
+        }\r
+        return HRESULT_FROM_WIN32( ret );\r
+    }\r
+\r
+    ret = ERROR_NOT_SUPPORTED;\r
+    DWORD i;\r
+    for( i = 0; i < pTable->dwNumEntries; i++ )\r
+    {\r
+        if( pTable->table[i].dwType == MIB_IPNET_TYPE_OTHER ||\r
+            pTable->table[i].dwType == MIB_IPNET_TYPE_INVALID )\r
+        {\r
+            continue;\r
+        }\r
+\r
+        if( pTable->table[i].dwAddr !=\r
+            ((struct sockaddr_in*)pDestAddr)->sin_addr.s_addr )\r
+        {\r
+            continue;\r
+        }\r
+\r
+        if( pTable->table[i].dwPhysAddrLen != IBAT_MAC_LEN )\r
+        {\r
+            continue;\r
+        }\r
+\r
+        RtlCopyMemory( pDestMac, pTable->table[i].bPhysAddr, IBAT_MAC_LEN );\r
+        ret = S_OK;\r
+        break;\r
+    }\r
+    HeapFree( GetProcessHeap(), 0, pTable );\r
+\r
+    return HRESULT_FROM_WIN32( ret );\r
+}\r
+\r
+HRESULT\r
+Resolve(\r
+    __in const struct sockaddr* pSrcAddr,\r
+    __in const struct sockaddr* pDestAddr,\r
+    __out IN6_ADDR* pSrcGid,\r
+    __out IN6_ADDR* pDestGid,\r
+    __out USHORT* pPkey\r
+    )\r
+{\r
+    if( pDestAddr->sa_family != AF_INET )\r
+        return E_NOTIMPL;\r
+\r
+    H hIbatDev = CreateFileW( IBAT_WIN32_NAME,\r
+        MAXIMUM_ALLOWED, 0, NULL,\r
+        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
+    if( hIbatDev == INVALID_HANDLE_VALUE )\r
+        return HRESULT_FROM_WIN32( GetLastError() );\r
+\r
+    IOCTL_IBAT_IP_TO_PORT_IN port_in;\r
+    port_in.Version = IBAT_IOCTL_VERSION;\r
+    port_in.Address.IpVersion = 4;\r
+    RtlCopyMemory(\r
+        &port_in.Address.Address[12],\r
+        &((struct sockaddr_in*)pSrcAddr)->sin_addr,\r
+        sizeof( ((struct sockaddr_in*)pSrcAddr)->sin_addr ) );\r
+\r
+    IBAT_PORT_RECORD port_out;\r
+    DWORD size;\r
+    BOOL fSuccess = DeviceIoControl( hIbatDev, IOCTL_IBAT_IP_TO_PORT,\r
+        &port_in, sizeof(port_in), &port_out, sizeof(port_out), &size, NULL );\r
+\r
+    if( !fSuccess )\r
+        return HRESULT_FROM_WIN32( GetLastError() );\r
+\r
+    // Check for loopback.\r
+    if( ((struct sockaddr_in*)pDestAddr)->sin_addr.s_addr ==\r
+        ((struct sockaddr_in*)pSrcAddr)->sin_addr.s_addr )\r
+    {\r
+        *pSrcGid = x_DefaultGid;\r
+        RtlCopyMemory(\r
+            &pSrcGid->u.Byte[8],\r
+            &port_out.PortGuid,\r
+            sizeof(port_out.PortGuid) );\r
+        *pDestGid = *pSrcGid;\r
+        *pPkey = port_out.PKey;\r
+        return S_OK;\r
+    }\r
+\r
+    IOCTL_IBAT_MAC_TO_GID_IN mac_in;\r
+    mac_in.Version = IBAT_IOCTL_VERSION;\r
+    mac_in.PortGuid = port_out.PortGuid;\r
+    HRESULT hr = GetDestMac( (struct sockaddr_in*)pDestAddr, mac_in.DestMac );\r
+    if( FAILED( hr ) )\r
+    {\r
+        ULONG len = sizeof(mac_in.DestMac);\r
+        DWORD ret = SendARP(\r
+            ((struct sockaddr_in*)pDestAddr)->sin_addr.s_addr,\r
+            ((struct sockaddr_in*)pSrcAddr)->sin_addr.s_addr,\r
+            (ULONG*)mac_in.DestMac,\r
+            &len\r
+            );\r
+        if( ret != NO_ERROR )\r
+            return HRESULT_FROM_WIN32( ret );\r
+    }\r
+\r
+    fSuccess = DeviceIoControl( hIbatDev, IOCTL_IBAT_MAC_TO_GID,\r
+        &mac_in, sizeof(mac_in), pDestGid, sizeof(*pDestGid), &size, NULL );\r
+    if( !fSuccess )\r
+        return HRESULT_FROM_WIN32( GetLastError() );\r
+\r
+    // Use the same subnet prefix as the destination.\r
+    *pSrcGid = *pDestGid;\r
+    RtlCopyMemory( &pSrcGid->u.Byte[8], &port_out.PortGuid, sizeof(port_out.PortGuid) );\r
+    *pPkey = port_out.PKey;\r
+    return S_OK;\r
+}\r
+\r
+#endif\r
+}\r
+\r
+extern "C"\r
+{\r
+\r
+HRESULT\r
+IbatResolve(\r
+    __in const struct sockaddr* pSrcAddr,\r
+    __in const struct sockaddr* pDestAddr,\r
+    __out IN6_ADDR* pSrcGid,\r
+    __out IN6_ADDR* pDestGid,\r
+    __out USHORT* pPkey\r
+    )\r
+{\r
+    return IBAT::Resolve( pSrcAddr, pDestAddr, pSrcGid, pDestGid, pPkey );\r
+}\r
+\r
+} /* extern "C" */\r
diff --git a/core/ibat/user/makefile b/core/ibat/user/makefile
new file mode 100644 (file)
index 0000000..bffacaa
--- /dev/null
@@ -0,0 +1,7 @@
+#\r
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source\r
+# file to this component.  This file merely indirects to the real make file\r
+# that is shared by all the driver components of the OpenIB Windows project.\r
+#\r
+\r
+!INCLUDE ..\..\..\inc\openib.def\r
index 6fc9b55..fd12699 100644 (file)
@@ -1,6 +1,7 @@
 /*\r
  * Copyright (c) 2005 Mellanox Technologies.  All rights reserved.\r
  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.\r
+ * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
  *\r
  * This software is available to you under the OpenIB.org BSD license\r
  * below:\r
@@ -39,7 +40,7 @@
 #define        _IB_AT_IOCTL_H_\r
 \r
 \r
-#define        IBAT_IOCTL_VERSION              4\r
+#define        IBAT_IOCTL_VERSION              5\r
 \r
 #define        IBAT_MAC_LEN                    6\r
 \r
@@ -56,6 +57,7 @@ typedef struct _IBAT_PORT_RECORD
 {\r
        UINT64                          CaGuid;\r
        UINT64                          PortGuid;\r
+       UINT16                          PKey;\r
        UINT8                           PortNum;\r
 \r
 } IBAT_PORT_RECORD;\r
diff --git a/inc/user/iba/ibat.h b/inc/user/iba/ibat.h
new file mode 100644 (file)
index 0000000..9d4bda9
--- /dev/null
@@ -0,0 +1,60 @@
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+#include <winsock2.h>\r
+#include <ws2tcpip.h>\r
+\r
+#ifdef __cplusplus\r
+namespace IBAT\r
+{\r
+\r
+HRESULT\r
+Resolve(\r
+    __in const struct sockaddr* pSrcAddr,\r
+    __in const struct sockaddr* pDestAddr,\r
+    __out IN6_ADDR* pSrcGid,\r
+    __out IN6_ADDR* pDestGid,\r
+    __out USHORT* pPkey\r
+    );\r
+\r
+}\r
+#else /* __cplusplus */\r
+\r
+HRESULT\r
+IbatResolve(\r
+    __in const struct sockaddr* pSrcAddr,\r
+    __in const struct sockaddr* pDestAddr,\r
+    __out IN6_ADDR* pSrcGid,\r
+    __out IN6_ADDR* pDestGid,\r
+    __out USHORT* pPkey\r
+    );\r
+\r
+#endif /* __cplusplus */\r
index fc792b6..cc9e1a7 100644 (file)
@@ -3,4 +3,5 @@ DIRS=\
        cmtest  \\r
        wsd             \\r
        ibat    \\r
-       limits\r
+       limits  \\r
+       wherebu\r
diff --git a/tests/wherebu/dirs b/tests/wherebu/dirs
new file mode 100644 (file)
index 0000000..389156f
--- /dev/null
@@ -0,0 +1,2 @@
+DIRS=\\r
+       user\r
diff --git a/tests/wherebu/user/SOURCES b/tests/wherebu/user/SOURCES
new file mode 100644 (file)
index 0000000..f2f1804
--- /dev/null
@@ -0,0 +1,20 @@
+TARGETNAME=wherebu\r
+TARGETPATH=..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE=PROGRAM\r
+UMTYPE=console\r
+USE_MSVCRT=1\r
+\r
+SOURCES=\\r
+       wherebu.cpp\r
+\r
+TARGETLIBS=\\r
+       $(TARGETPATH)\*\ibat.lib \\r
+       $(SDK_LIB_PATH)\ws2_32.lib \\r
+       $(SDK_LIB_PATH)\Iphlpapi.lib\r
+\r
+MSC_WARNING_LEVEL= /W4\r
+\r
+INCLUDES=$(SDK_INC_PATH);\\r
+       ..\..\..\inc;\\r
+       ..\..\..\inc\user;\\r
+       $(PLATFORM_SDK_PATH)\include;\r
diff --git a/tests/wherebu/user/makefile b/tests/wherebu/user/makefile
new file mode 100644 (file)
index 0000000..128ed37
--- /dev/null
@@ -0,0 +1,7 @@
+#\r
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source\r
+# file to this component.  This file merely indirects to the real make file\r
+# that is shared by all the driver components of the Windows NT DDK\r
+#\r
+\r
+!INCLUDE ..\..\..\inc\openib.def\r
diff --git a/tests/wherebu/user/wherebu.cpp b/tests/wherebu/user/wherebu.cpp
new file mode 100644 (file)
index 0000000..e23721f
--- /dev/null
@@ -0,0 +1,123 @@
+/*\r
+ * Copyright (c) 2008 Microsoft Corporation.  All rights reserved.\r
+ *\r
+ * This software is available to you under the OpenIB.org BSD license\r
+ * below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ * $Id:$\r
+ */\r
+\r
+\r
+#include "iba/ibat.h"\r
+#include "stdlib.h"\r
+#include "stdio.h"\r
+\r
+\r
+inline LONGLONG GetElapsedTime()\r
+{\r
+    LARGE_INTEGER elapsed;\r
+    QueryPerformanceCounter(&elapsed);\r
+    return elapsed.QuadPart;\r
+}\r
+\r
+inline LONGLONG GetFrequency()\r
+{\r
+    LARGE_INTEGER Frequency;\r
+    QueryPerformanceFrequency(&Frequency);\r
+    return Frequency.QuadPart;\r
+}\r
+\r
+int PrintUsage( int argc, char *argv[] )\r
+{\r
+    UNREFERENCED_PARAMETER( argc );\r
+    printf( "%s <source IP> <destination IP>\n", argv[0] );\r
+\r
+    return __LINE__;\r
+}\r
+\r
+int __cdecl main(int argc, char *argv[])\r
+{\r
+    if( argc < 3 )\r
+        return PrintUsage( argc, argv );\r
+\r
+    struct sockaddr_in srcAddr = {0};\r
+    srcAddr.sin_family = AF_INET;\r
+    srcAddr.sin_addr.s_addr = inet_addr( argv[1] );\r
+\r
+    struct sockaddr_in destAddr = {0};\r
+    destAddr.sin_family = AF_INET;\r
+    destAddr.sin_addr.s_addr = inet_addr( argv[2] );\r
+\r
+    IN6_ADDR srcGid;\r
+    IN6_ADDR destGid;\r
+    USHORT pkey;\r
+\r
+    HRESULT hr = IBAT::Resolve(\r
+        (struct sockaddr*)&srcAddr,\r
+        (struct sockaddr*)&destAddr,\r
+        &srcGid,\r
+        &destGid,\r
+        &pkey\r
+        );\r
+    if( FAILED( hr ) )\r
+    {\r
+        printf( "Resolve returned %08x.\n", hr );\r
+        return hr;\r
+    }\r
+\r
+    printf(\r
+        "I B at:\n"\r
+        "partition %x\n"\r
+        "source GID %x:%x:%x:%x:%x:%x:%x:%x\n"\r
+        "destination GID %x:%x:%x:%x:%x:%x:%x:%x\n",\r
+        pkey,\r
+        srcGid.u.Word[0], srcGid.u.Word[1], srcGid.u.Word[2], srcGid.u.Word[3],\r
+        srcGid.u.Word[4], srcGid.u.Word[5], srcGid.u.Word[6], srcGid.u.Word[7],\r
+        destGid.u.Word[0], destGid.u.Word[1], destGid.u.Word[2], destGid.u.Word[3],\r
+        destGid.u.Word[4], destGid.u.Word[5], destGid.u.Word[6], destGid.u.Word[7]\r
+    );\r
+\r
+    LONGLONG StartTime = GetElapsedTime();\r
+    for( int i = 0; i < 2000; i++ )\r
+    {\r
+        HRESULT hr = IBAT::Resolve(\r
+            (struct sockaddr*)&srcAddr,\r
+            (struct sockaddr*)&destAddr,\r
+            &srcGid,\r
+            &destGid,\r
+            &pkey\r
+            );\r
+        if( FAILED( hr ) )\r
+        {\r
+            printf( "Resolve returned %08x.\n", hr );\r
+            return hr;\r
+        }\r
+    }\r
+    LONGLONG RunTime = GetElapsedTime() - StartTime;\r
+    double Rate = 2000.0 / ((double)RunTime / (double)GetFrequency());\r
+    printf( "%7.2f lookups per second\n", Rate );\r
+\r
+    return 0;\r
+}\r
index e162765..55ef84c 100644 (file)
@@ -142,6 +142,7 @@ __ibat_get_ports(
                pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );\r
                pOut->Ports[pOut->NumPorts].CaGuid = pAdapter->guids.ca_guid;\r
                pOut->Ports[pOut->NumPorts].PortGuid = pAdapter->guids.port_guid.guid;\r
+               pOut->Ports[pOut->NumPorts].PKey = IB_DEFAULT_PKEY;\r
                pOut->Ports[pOut->NumPorts].PortNum = pAdapter->guids.port_num;\r
                pOut->NumPorts++;\r
 \r
@@ -396,6 +397,7 @@ __ibat_ip_to_port(
                        {\r
                                pOut->Port.CaGuid = pAdapter->guids.ca_guid;\r
                                pOut->Port.PortGuid = pAdapter->guids.port_guid.guid;\r
+                               pOut->Port.PKey = IB_DEFAULT_PKEY;\r
                                pOut->Port.PortNum = pAdapter->guids.port_num;\r
                                pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_TO_PORT_OUT);\r
                                status = STATUS_SUCCESS;\r