[ofw] ***SPAM*** [PATCH] Add smarter IB address translation

Fab Tillier ftillier at windows.microsoft.com
Wed Jul 2 11:37:12 PDT 2008


This patch adds a library and test utility that performs IP to IB address translation without going to the SA for DAPL ATS service records.  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 at microsoft.com>

diff -up -N -r -X trunk\docs\dontdiff.txt -I \$Id: old\core\dirs trunk\core\dirs
--- old\core\dirs       Thu Jun 26 20:35:13 2008
+++ trunk\core\dirs     Sat Jun 14 00:13:25 2008
@@ -2,4 +2,5 @@ DIRS=\
        complib \
        al              \
        bus             \
-       iou
+       iou             \
+       ibat
diff -up -N -r -X trunk\docs\dontdiff.txt -I \$Id: old\core\ibat\dirs trunk\core\ibat\dirs
--- old\core\ibat\dirs  Wed Dec 31 16:00:00 1969
+++ trunk\core\ibat\dirs        Wed Jul 02 11:00:10 2008
@@ -0,0 +1,2 @@
+DIRS=\
+       user
diff -up -N -r -X trunk\docs\dontdiff.txt -I \$Id: old\core\ibat\user\ibat.cpp trunk\core\ibat\user\ibat.cpp
--- old\core\ibat\user\ibat.cpp Wed Dec 31 16:00:00 1969
+++ trunk\core\ibat\user\ibat.cpp       Wed Jul 02 11:00:10 2008
@@ -0,0 +1,400 @@
+/*
+ * Copyright (c) 2008 Microsoft Corporation.  All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id:$
+ */
+
+//
+// IBAT: InfiniBand Address Translation
+//
+// Description:
+//  Maps remote IP addresses (IPv4 and IPv6) to the remote GID.
+//
+//  The mapping requires two steps:
+//      1. Mapping the remote IP address to the remote Ethernet MAC address
+//      2. Retrieve the remote GID given the remote Ethernet MAC address
+//      from IPoIB
+//
+//  The first step is accomplished as follows on Windows Server 2008:
+//      1. Lookup the desired MAC from the OS using GetIpNetEntry2
+//      2. If the remote IP isn't found, resolve the remote IP address
+//      using ResolveIpNetEntry2
+//
+//  The first step is accomplished as follows on Windows Server 2003:
+//      1. Retrieve the whole IP->MAC mapping table from the OS using
+//      GetIpNetTable.
+//      2. Walk the returned table looking for the destination IP to
+//      find the destination Ethernet MAC address.
+//      3. If the remote IP isn't found, resolve the remote IP address using
+//      SendARP.
+//
+//  The second step is accomplished by asking IPoIB for the remote GID
+//  given the remote MAC.
+
+#pragma warning( push, 3 )
+#include <windows.h>
+#include <stdlib.h>
+#include <winioctl.h>
+#pragma warning( pop )
+#include "iba/ibat.h"
+#include <iphlpapi.h>
+#include "iba/ib_at_ioctl.h"
+
+
+namespace IBAT
+{
+
+    const IN6_ADDR x_DefaultGid = {0xFE,0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+class H
+{
+public:
+    H( HANDLE h = INVALID_HANDLE_VALUE ) : m_h( h ) {};
+    ~H(){ if( m_h != INVALID_HANDLE_VALUE ) CloseHandle( m_h ); }
+
+    H& operator =(HANDLE h){ CloseHandle( m_h ); m_h = h; }
+    operator HANDLE() const { return m_h; }
+
+private:
+    HANDLE m_h;
+};
+
+#if WINVER >= 0x600
+HRESULT
+Resolve(
+    __in const struct sockaddr* pSrcAddr,
+    __in const struct sockaddr* pDestAddr,
+    __out IN6_ADDR* pSrcGid,
+    __out IN6_ADDR* pDestGid,
+    __out USHORT* pPkey
+    )
+{
+    if( pSrcAddr->sa_family != pDestAddr->sa_family )
+        return E_INVALIDARG;
+
+    H hIbatDev = CreateFileW( IBAT_WIN32_NAME,
+        MAXIMUM_ALLOWED, 0, NULL,
+        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+    if( hIbatDev == INVALID_HANDLE_VALUE )
+        return HRESULT_FROM_WIN32( GetLastError() );
+
+    bool fLoopback;
+    IOCTL_IBAT_IP_TO_PORT_IN port_in;
+    port_in.Version = IBAT_IOCTL_VERSION;
+    if( pSrcAddr->sa_family == AF_INET )
+    {
+        port_in.Address.IpVersion = 4;
+        RtlCopyMemory(
+            &port_in.Address.Address[12],
+            &((struct sockaddr_in*)pSrcAddr)->sin_addr,
+            sizeof( ((struct sockaddr_in*)pSrcAddr)->sin_addr ) );
+
+        fLoopback = ((struct sockaddr_in*)pDestAddr)->sin_addr.s_addr ==
+            ((struct sockaddr_in*)pSrcAddr)->sin_addr.s_addr;
+    }
+    else
+    {
+        port_in.Address.IpVersion = 6;
+        RtlCopyMemory(
+            port_in.Address.Address,
+            &((struct sockaddr_in6*)pSrcAddr)->sin6_addr,
+            sizeof(port_in.Address.Address) );
+        fLoopback = IN6_ADDR_EQUAL(
+            &((struct sockaddr_in6*)pDestAddr)->sin6_addr,
+            &((struct sockaddr_in6*)pSrcAddr)->sin6_addr
+            ) == TRUE;
+    }
+
+    IBAT_PORT_RECORD port_out;
+    DWORD size;
+    BOOL fSuccess = DeviceIoControl( hIbatDev, IOCTL_IBAT_IP_TO_PORT,
+        &port_in, sizeof(port_in), &port_out, sizeof(port_out), &size, NULL );
+
+    if( !fSuccess )
+        return HRESULT_FROM_WIN32( GetLastError() );
+
+    // Check for loopback.
+    if( fLoopback )
+    {
+        *pSrcGid = x_DefaultGid;
+        RtlCopyMemory(
+            &pSrcGid->u.Byte[8],
+            &port_out.PortGuid,
+            sizeof(port_out.PortGuid) );
+        *pDestGid = *pSrcGid;
+        *pPkey = port_out.PKey;
+        return S_OK;
+    }
+
+    NET_LUID luid;
+    DWORD ret;
+    do
+    {
+        DWORD iIf;
+        ret = GetBestInterfaceEx( (struct sockaddr*)pSrcAddr, &iIf );
+        if( ret != NO_ERROR )
+            return HRESULT_FROM_WIN32( ret );
+
+        // Interface indexes are not constant, so get the LUID mapping for the
+        // returned interface for use in the rest of the function.
+        ret = ConvertInterfaceIndexToLuid( iIf, &luid );
+
+    } while( ret != NO_ERROR );
+
+    SOCKADDR_INET src;
+    MIB_IPNET_ROW2 net = {0};
+    net.InterfaceLuid = luid;
+    switch( pDestAddr->sa_family )
+    {
+    case AF_INET:
+        net.Address.si_family = src.si_family = AF_INET;
+        net.Address.Ipv4 = *(struct sockaddr_in*)pDestAddr;
+        src.Ipv4 = *(struct sockaddr_in*)pSrcAddr;
+        break;
+
+    case AF_INET6:
+        net.Address.si_family = src.si_family = AF_INET6;
+        net.Address.Ipv6 = *(struct sockaddr_in6*)pDestAddr;
+        src.Ipv6 = *(struct sockaddr_in6*)pSrcAddr;
+        break;
+
+    default:
+        return E_INVALIDARG;
+    }
+
+    bool fRetry = true;
+retry:
+    ret = GetIpNetEntry2( &net );
+    if( ret != NO_ERROR )
+        return HRESULT_FROM_WIN32( ret );
+
+    switch( net.State )
+    {
+    default:
+    case NlnsUnreachable:
+        ret = ResolveIpNetEntry2( &net, &src );
+        if( ret == ERROR_BAD_NET_NAME && fRetry )
+        {
+            fRetry = false;
+            goto retry;
+        }
+        else if( ret != NO_ERROR )
+        {
+            return HRESULT_FROM_WIN32( ret );
+        }
+        break;
+
+    case NlnsReachable:
+    case NlnsPermanent:
+        break;
+
+    case NlnsIncomplete:
+        return E_PENDING;
+    }
+
+    if( net.PhysicalAddressLength > 6 )
+        return E_UNEXPECTED;
+
+    IOCTL_IBAT_MAC_TO_GID_IN mac_in;
+    mac_in.Version = IBAT_IOCTL_VERSION;
+    mac_in.PortGuid = port_out.PortGuid;
+    RtlCopyMemory( mac_in.DestMac, net.PhysicalAddress, IBAT_MAC_LEN );
+
+    fSuccess = DeviceIoControl( hIbatDev, IOCTL_IBAT_MAC_TO_GID,
+        &mac_in, sizeof(mac_in), pDestGid, sizeof(*pDestGid), &size, NULL );
+    if( !fSuccess )
+        return HRESULT_FROM_WIN32( GetLastError() );
+
+    // Use the same subnet prefix as the destination.
+    *pSrcGid = *pDestGid;
+    RtlCopyMemory( &pSrcGid->u.Byte[8], &port_out.PortGuid, sizeof(port_out.PortGuid) );
+    *pPkey = port_out.PKey;
+    return S_OK;
+}
+#else   // Back compatibility with Windows Server 2003
+
+
+static HRESULT
+GetDestMac(
+    __in struct sockaddr_in* pDestAddr,
+    __out BYTE* pDestMac
+    )
+{
+    DWORD ret;
+
+    MIB_IPNETTABLE* pTable = NULL;
+    ULONG len = 0;
+    do
+    {
+        ret = GetIpNetTable( pTable, &len, FALSE );
+        if( ret != ERROR_INSUFFICIENT_BUFFER )
+            break;
+
+        if( pTable != NULL )
+        {
+            HeapFree( GetProcessHeap(), 0, pTable );
+        }
+
+        pTable = (MIB_IPNETTABLE*)HeapAlloc( GetProcessHeap(), 0, len );
+    } while( ret == ERROR_INSUFFICIENT_BUFFER );
+
+    if( ret != NO_ERROR )
+    {
+        if( pTable != NULL )
+        {
+            HeapFree( GetProcessHeap(), 0, pTable );
+        }
+        return HRESULT_FROM_WIN32( ret );
+    }
+
+    ret = ERROR_NOT_SUPPORTED;
+    DWORD i;
+    for( i = 0; i < pTable->dwNumEntries; i++ )
+    {
+        if( pTable->table[i].dwType == MIB_IPNET_TYPE_OTHER ||
+            pTable->table[i].dwType == MIB_IPNET_TYPE_INVALID )
+        {
+            continue;
+        }
+
+        if( pTable->table[i].dwAddr !=
+            ((struct sockaddr_in*)pDestAddr)->sin_addr.s_addr )
+        {
+            continue;
+        }
+
+        if( pTable->table[i].dwPhysAddrLen != IBAT_MAC_LEN )
+        {
+            continue;
+        }
+
+        RtlCopyMemory( pDestMac, pTable->table[i].bPhysAddr, IBAT_MAC_LEN );
+        ret = S_OK;
+        break;
+    }
+    HeapFree( GetProcessHeap(), 0, pTable );
+
+    return HRESULT_FROM_WIN32( ret );
+}
+
+HRESULT
+Resolve(
+    __in const struct sockaddr* pSrcAddr,
+    __in const struct sockaddr* pDestAddr,
+    __out IN6_ADDR* pSrcGid,
+    __out IN6_ADDR* pDestGid,
+    __out USHORT* pPkey
+    )
+{
+    if( pDestAddr->sa_family != AF_INET )
+        return E_NOTIMPL;
+
+    H hIbatDev = CreateFileW( IBAT_WIN32_NAME,
+        MAXIMUM_ALLOWED, 0, NULL,
+        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+    if( hIbatDev == INVALID_HANDLE_VALUE )
+        return HRESULT_FROM_WIN32( GetLastError() );
+
+    IOCTL_IBAT_IP_TO_PORT_IN port_in;
+    port_in.Version = IBAT_IOCTL_VERSION;
+    port_in.Address.IpVersion = 4;
+    RtlCopyMemory(
+        &port_in.Address.Address[12],
+        &((struct sockaddr_in*)pSrcAddr)->sin_addr,
+        sizeof( ((struct sockaddr_in*)pSrcAddr)->sin_addr ) );
+
+    IBAT_PORT_RECORD port_out;
+    DWORD size;
+    BOOL fSuccess = DeviceIoControl( hIbatDev, IOCTL_IBAT_IP_TO_PORT,
+        &port_in, sizeof(port_in), &port_out, sizeof(port_out), &size, NULL );
+
+    if( !fSuccess )
+        return HRESULT_FROM_WIN32( GetLastError() );
+
+    // Check for loopback.
+    if( ((struct sockaddr_in*)pDestAddr)->sin_addr.s_addr ==
+        ((struct sockaddr_in*)pSrcAddr)->sin_addr.s_addr )
+    {
+        *pSrcGid = x_DefaultGid;
+        RtlCopyMemory(
+            &pSrcGid->u.Byte[8],
+            &port_out.PortGuid,
+            sizeof(port_out.PortGuid) );
+        *pDestGid = *pSrcGid;
+        *pPkey = port_out.PKey;
+        return S_OK;
+    }
+
+    IOCTL_IBAT_MAC_TO_GID_IN mac_in;
+    mac_in.Version = IBAT_IOCTL_VERSION;
+    mac_in.PortGuid = port_out.PortGuid;
+    HRESULT hr = GetDestMac( (struct sockaddr_in*)pDestAddr, mac_in.DestMac );
+    if( FAILED( hr ) )
+    {
+        ULONG len = sizeof(mac_in.DestMac);
+        DWORD ret = SendARP(
+            ((struct sockaddr_in*)pDestAddr)->sin_addr.s_addr,
+            ((struct sockaddr_in*)pSrcAddr)->sin_addr.s_addr,
+            (ULONG*)mac_in.DestMac,
+            &len
+            );
+        if( ret != NO_ERROR )
+            return HRESULT_FROM_WIN32( ret );
+    }
+
+    fSuccess = DeviceIoControl( hIbatDev, IOCTL_IBAT_MAC_TO_GID,
+        &mac_in, sizeof(mac_in), pDestGid, sizeof(*pDestGid), &size, NULL );
+    if( !fSuccess )
+        return HRESULT_FROM_WIN32( GetLastError() );
+
+    // Use the same subnet prefix as the destination.
+    *pSrcGid = *pDestGid;
+    RtlCopyMemory( &pSrcGid->u.Byte[8], &port_out.PortGuid, sizeof(port_out.PortGuid) );
+    *pPkey = port_out.PKey;
+    return S_OK;
+}
+
+#endif
+}
+
+extern "C"
+{
+
+HRESULT
+IbatResolve(
+    __in const struct sockaddr* pSrcAddr,
+    __in const struct sockaddr* pDestAddr,
+    __out IN6_ADDR* pSrcGid,
+    __out IN6_ADDR* pDestGid,
+    __out USHORT* pPkey
+    )
+{
+    return IBAT::Resolve( pSrcAddr, pDestAddr, pSrcGid, pDestGid, pPkey );
+}
+
+} /* extern "C" */
diff -up -N -r -X trunk\docs\dontdiff.txt -I \$Id: old\core\ibat\user\makefile trunk\core\ibat\user\makefile
--- old\core\ibat\user\makefile Wed Dec 31 16:00:00 1969
+++ trunk\core\ibat\user\makefile       Wed Jul 02 11:00:10 2008
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
+# file to this component.  This file merely indirects to the real make file
+# that is shared by all the driver components of the OpenIB Windows project.
+#
+
+!INCLUDE ..\..\..\inc\openib.def
diff -up -N -r -X trunk\docs\dontdiff.txt -I \$Id: old\core\ibat\user\SOURCES trunk\core\ibat\user\SOURCES
--- old\core\ibat\user\SOURCES  Wed Dec 31 16:00:00 1969
+++ trunk\core\ibat\user\SOURCES        Wed Jul 02 11:00:10 2008
@@ -0,0 +1,14 @@
+TARGETNAME=ibat
+
+TARGETPATH=..\..\..\bin\user\obj$(BUILD_ALT_DIR)
+TARGETTYPE=LIBRARY
+
+SOURCES=\
+       ibat.cpp
+
+
+INCLUDES=$(SDK_INC_PATH);..;..\..\..\inc;..\..\..\inc\user;$(PLATFORM_SDK_PATH)\Include
+
+USER_C_FLAGS=$(USER_C_FLAGS)
+
+MSC_WARNING_LEVEL= /W4
diff -up -N -r -X trunk\docs\dontdiff.txt -I \$Id: old\hw\mthca\kernel\mthca_log.rc trunk\hw\mthca\kernel\mthca_log.rc
--- old\hw\mthca\kernel\mthca_log.rc    Mon Jun 30 11:07:40 2008
+++ trunk\hw\mthca\kernel\mthca_log.rc  Wed Dec 31 16:00:00 1969
@@ -1,2 +0,0 @@
-LANGUAGE 0x9,0x1
-1 11 MSG00001.bin
diff -up -N -r -X trunk\docs\dontdiff.txt -I \$Id: old\inc\iba\ib_at_ioctl.h trunk\inc\iba\ib_at_ioctl.h
--- old\inc\iba\ib_at_ioctl.h   Thu Jun 26 20:35:14 2008
+++ trunk\inc\iba\ib_at_ioctl.h Wed Jul 02 11:33:43 2008
@@ -1,6 +1,7 @@
 /*
  * Copyright (c) 2005 Mellanox Technologies.  All rights reserved.
  * Copyright (c) 2005 SilverStorm Technologies.  All rights reserved.
+ * Portions Copyright (c) 2008 Microsoft Corporation.  All rights reserved.
  *
  * This software is available to you under the OpenIB.org BSD license
  * below:
@@ -39,7 +40,7 @@
 #define        _IB_AT_IOCTL_H_


-#define        IBAT_IOCTL_VERSION              4
+#define        IBAT_IOCTL_VERSION              5

 #define        IBAT_MAC_LEN                    6

@@ -56,6 +57,7 @@ typedef struct _IBAT_PORT_RECORD
 {
        UINT64                          CaGuid;
        UINT64                          PortGuid;
+       UINT16                          PKey;
        UINT8                           PortNum;

 } IBAT_PORT_RECORD;
diff -up -N -r -X trunk\docs\dontdiff.txt -I \$Id: old\tests\dirs trunk\tests\dirs
--- old\tests\dirs      Thu Apr 24 11:29:39 2008
+++ trunk\tests\dirs    Wed Jul 02 10:55:48 2008
@@ -3,4 +3,5 @@ DIRS=\
        cmtest  \
        wsd             \
        ibat    \
-       limits
+       limits  \
+       wherebu
diff -up -N -r -X trunk\docs\dontdiff.txt -I \$Id: old\tests\wherebu\dirs trunk\tests\wherebu\dirs
--- old\tests\wherebu\dirs      Wed Dec 31 16:00:00 1969
+++ trunk\tests\wherebu\dirs    Thu May 08 09:38:22 2008
@@ -0,0 +1,2 @@
+DIRS=\
+       user
diff -up -N -r -X trunk\docs\dontdiff.txt -I \$Id: old\tests\wherebu\user\makefile trunk\tests\wherebu\user\makefile
--- old\tests\wherebu\user\makefile     Wed Dec 31 16:00:00 1969
+++ trunk\tests\wherebu\user\makefile   Thu May 08 09:38:22 2008
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
+# file to this component.  This file merely indirects to the real make file
+# that is shared by all the driver components of the Windows NT DDK
+#
+
+!INCLUDE ..\..\..\inc\openib.def
diff -up -N -r -X trunk\docs\dontdiff.txt -I \$Id: old\tests\wherebu\user\SOURCES trunk\tests\wherebu\user\SOURCES
--- old\tests\wherebu\user\SOURCES      Wed Dec 31 16:00:00 1969
+++ trunk\tests\wherebu\user\SOURCES    Thu May 08 09:38:22 2008
@@ -0,0 +1,20 @@
+TARGETNAME=wherebu
+TARGETPATH=..\..\..\bin\user\obj$(BUILD_ALT_DIR)
+TARGETTYPE=PROGRAM
+UMTYPE=console
+USE_MSVCRT=1
+
+SOURCES=\
+       wherebu.cpp
+
+TARGETLIBS=\
+       $(TARGETPATH)\*\ibat.lib \
+       $(SDK_LIB_PATH)\ws2_32.lib \
+       $(SDK_LIB_PATH)\Iphlpapi.lib
+
+MSC_WARNING_LEVEL= /W4
+
+INCLUDES=$(SDK_INC_PATH);\
+       ..\..\..\inc;\
+       ..\..\..\inc\user;\
+       $(PLATFORM_SDK_PATH)\include;
diff -up -N -r -X trunk\docs\dontdiff.txt -I \$Id: old\tests\wherebu\user\wherebu.cpp trunk\tests\wherebu\user\wherebu.cpp
--- old\tests\wherebu\user\wherebu.cpp  Wed Dec 31 16:00:00 1969
+++ trunk\tests\wherebu\user\wherebu.cpp        Wed Jul 02 11:36:08 2008
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2008 Microsoft Corporation.  All rights reserved.
+ *
+ * This software is available to you under the OpenIB.org BSD license
+ * below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id:$
+ */
+
+
+#include "iba/ibat.h"
+#include "stdlib.h"
+#include "stdio.h"
+
+
+inline LONGLONG GetElapsedTime()
+{
+    LARGE_INTEGER elapsed;
+    QueryPerformanceCounter(&elapsed);
+    return elapsed.QuadPart;
+}
+
+inline LONGLONG GetFrequency()
+{
+    LARGE_INTEGER Frequency;
+    QueryPerformanceFrequency(&Frequency);
+    return Frequency.QuadPart;
+}
+
+int PrintUsage( int argc, char *argv[] )
+{
+    UNREFERENCED_PARAMETER( argc );
+    printf( "%s <source IP> <destination IP>\n", argv[0] );
+
+    return __LINE__;
+}
+
+int __cdecl main(int argc, char *argv[])
+{
+    if( argc < 3 )
+        return PrintUsage( argc, argv );
+
+    struct sockaddr_in srcAddr = {0};
+    srcAddr.sin_family = AF_INET;
+    srcAddr.sin_addr.s_addr = inet_addr( argv[1] );
+
+    struct sockaddr_in destAddr = {0};
+    destAddr.sin_family = AF_INET;
+    destAddr.sin_addr.s_addr = inet_addr( argv[2] );
+
+    IN6_ADDR srcGid;
+    IN6_ADDR destGid;
+    USHORT pkey;
+
+    HRESULT hr = IBAT::Resolve(
+        (struct sockaddr*)&srcAddr,
+        (struct sockaddr*)&destAddr,
+        &srcGid,
+        &destGid,
+        &pkey
+        );
+    if( FAILED( hr ) )
+    {
+        printf( "Resolve returned %08x.\n", hr );
+        return hr;
+    }
+
+    printf(
+        "I B at:\n"
+        "partition %x\n"
+        "source GID %x:%x:%x:%x:%x:%x:%x:%x\n"
+        "destination GID %x:%x:%x:%x:%x:%x:%x:%x\n",
+        pkey,
+        srcGid.u.Word[0], srcGid.u.Word[1], srcGid.u.Word[2], srcGid.u.Word[3],
+        srcGid.u.Word[4], srcGid.u.Word[5], srcGid.u.Word[6], srcGid.u.Word[7],
+        destGid.u.Word[0], destGid.u.Word[1], destGid.u.Word[2], destGid.u.Word[3],
+        destGid.u.Word[4], destGid.u.Word[5], destGid.u.Word[6], destGid.u.Word[7]
+    );
+
+    LONGLONG StartTime = GetElapsedTime();
+    for( int i = 0; i < 2000; i++ )
+    {
+        HRESULT hr = IBAT::Resolve(
+            (struct sockaddr*)&srcAddr,
+            (struct sockaddr*)&destAddr,
+            &srcGid,
+            &destGid,
+            &pkey
+            );
+        if( FAILED( hr ) )
+        {
+            printf( "Resolve returned %08x.\n", hr );
+            return hr;
+        }
+    }
+    LONGLONG RunTime = GetElapsedTime() - StartTime;
+    double Rate = 2000.0 / ((double)RunTime / (double)GetFrequency());
+    printf( "%7.2f lookups per second\n", Rate );
+
+    return 0;
+}
diff -up -N -r -X trunk\docs\dontdiff.txt -I \$Id: old\ulp\ipoib\kernel\ipoib_ibat.c trunk\ulp\ipoib\kernel\ipoib_ibat.c
--- old\ulp\ipoib\kernel\ipoib_ibat.c   Mon Jun 30 11:09:26 2008
+++ trunk\ulp\ipoib\kernel\ipoib_ibat.c Wed Jul 02 11:17:43 2008
@@ -142,6 +142,7 @@ __ibat_get_ports(
                pAdapter = CONTAINING_RECORD( pItem, ipoib_adapter_t, entry );
                pOut->Ports[pOut->NumPorts].CaGuid = pAdapter->guids.ca_guid;
                pOut->Ports[pOut->NumPorts].PortGuid = pAdapter->guids.port_guid.guid;
+               pOut->Ports[pOut->NumPorts].PKey = IB_DEFAULT_PKEY;
                pOut->Ports[pOut->NumPorts].PortNum = pAdapter->guids.port_num;
                pOut->NumPorts++;

@@ -396,6 +397,7 @@ __ibat_ip_to_port(
                        {
                                pOut->Port.CaGuid = pAdapter->guids.ca_guid;
                                pOut->Port.PortGuid = pAdapter->guids.port_guid.guid;
+                               pOut->Port.PKey = IB_DEFAULT_PKEY;
                                pOut->Port.PortNum = pAdapter->guids.port_num;
                                pIrp->IoStatus.Information = sizeof(IOCTL_IBAT_IP_TO_PORT_OUT);
                                status = STATUS_SUCCESS;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: ibat.patch
Type: application/octet-stream
Size: 21961 bytes
Desc: ibat.patch
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20080702/5e995655/attachment.obj>


More information about the ofw mailing list