[ofw] [Patch 58/62] Reference implementation of NDv2

Fab Tillier ftillier at microsoft.com
Wed Feb 20 21:11:38 PST 2013


IBAT: Add support for cancelling path queries

Signed-off-by: Fab Tillier <ftillier at microsoft.com>

diff -dwup3 -X excl.txt -I ^ \*$ -I ^ \* \$ -r \dev\openib\Mellanox\11011\core\ibat\kernel\ibat.cpp .\core\ibat\kernel\ibat.cpp
--- \dev\openib\Mellanox\11011\core\ibat\kernel\ibat.cpp	Thu Sep 20 17:51:00 2012
+++ .\core\ibat\kernel\ibat.cpp	Tue Oct 02 12:24:12 2012
@@ -702,50 +702,70 @@ IbatpResolveRemoteAddressUnsafe(
     KeWaitForSingleObject( &g_ibatResolveMutex, UserRequest, KernelMode, FALSE, NULL );
 #endif
     status = GetIpNetEntry2( &row );
-    if( NT_SUCCESS( status ) && row.State < NlnsReachable )
+    //
+    // If the neighbor does not exist (including local address), we will
+    // get STATUS_NOT_FOUND.  Treat that as NlnsUnreachable.
+    //
+    if( status == STATUS_NOT_FOUND )
     {
-        status = ResolveIpNetEntry2( &row, pLocalAddress );
+        row.State = NlnsUnreachable;
+    }
+    else if( !NT_SUCCESS(status) )
+    {
+        goto Unlock;
     }
-#if OSVER(NTDDI_VERSION) <= OSVER(NTDDI_WIN7)
-    KeReleaseMutex( &g_ibatResolveMutex, FALSE );
-#endif
 
+    switch( row.State )
+    {
+    case NlnsUnreachable:
+        //
+        // ResolveIpNetEntry2 will not fill the row if resolution is incomplete,
+        // so we need to query the row to get the current state.
+        //
+        status = ResolveIpNetEntry2( &row, pLocalAddress );
+        if( status == STATUS_BAD_NETWORK_NAME )
+        {
+            status = GetIpNetEntry2( &row );
+            if( status == STATUS_NOT_FOUND )
+            {
+                status = STATUS_BAD_NETWORK_NAME;
+            }
+        }
     if( !NT_SUCCESS( status ) )
     {
-        return status;
+            break;
     }
-
-    if( row.State < NlnsReachable || row.PhysicalAddressLength > sizeof(*pMac) )
+        if( row.State == NlnsUnreachable )
     {
-        return STATUS_NETWORK_UNREACHABLE;
+            status = STATUS_BAD_NETWORK_NAME;
+            break;
     }
-
+        if( row.State > NlnsIncomplete )
+        {
     //
-    // The common case is that the physical address is an Ethernet MAC, and 6 bytes.
-    // We use the MAC for looking up a route in an AVL tree, and treat it as a
-    // 64-bit integer.  Clear the the entire 64-bit MAC variable and then copy the
-    // physical address to set only the valid bytes.
+            // Entry might be old, but it was valid before - run with it.
     //
-    *pMac = 0;
-    RtlCopyMemory( pMac, row.PhysicalAddress, row.PhysicalAddressLength );
-
-    return STATUS_SUCCESS;
+            break;
 }
+        __fallthrough;
 
+    case NlnsIncomplete:
+        status = STATUS_IO_TIMEOUT;
+        break;
 
-static
-NTSTATUS
-IbatpResolveLoopbackAddressUnsafe(
-    __in UINT64                 luid,
-    __out UINT64*               pMac
-    )
-{
-    MIB_IF_ROW2 row;
-    NTSTATUS status;
-
-    NT_ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
-
-    row.InterfaceIndex      = 0;
-    row.InterfaceLuid.Value = luid;
+    case NlnsProbe:
+    case NlnsDelay:
+    case NlnsStale:
+    case NlnsReachable:
+    case NlnsPermanent:
+        status = STATUS_SUCCESS;
+        break;
+    }
 
-    status = GetIfEntry2(&row);
+Unlock:
+#if OSVER(NTDDI_VERSION) <= OSVER(NTDDI_WIN7)
+    KeReleaseMutex( &g_ibatResolveMutex, FALSE );
+#endif
     if( !NT_SUCCESS(status) )
     {
         return status;
@@ -756,7 +773,7 @@ IbatpResolveLoopbackAddressUnsafe(
 
     if( row.PhysicalAddressLength > sizeof(*pMac) )
     {
-        return STATUS_NOT_FOUND;
+        return STATUS_NETWORK_UNREACHABLE;
     }
 
     //
@@ -767,6 +784,7 @@ IbatpResolveLoopbackAddressUnsafe(
     //
     *pMac = 0;
     RtlCopyMemory( pMac, row.PhysicalAddress, row.PhysicalAddressLength );
+
     return STATUS_SUCCESS;
 }
 
@@ -792,19 +810,6 @@ IbatpResolvePhysicalAddressUnsafe(
     }
 
     status = IbatpResolveRemoteAddressUnsafe( luid, pLocalAddress, pRemoteAddress, pMac );
-
-    if( (status == STATUS_NOT_FOUND) )
-    {
-        if( (IbatUtil::IsEqual(*pLocalAddress, *pRemoteAddress) == true) )
-        {
-            status = IbatpResolveLoopbackAddressUnsafe( luid, pMac );
-        }
-        else
-        {
-            status = STATUS_BAD_NETWORK_NAME;
-        }
-    }
-
     return status;
 }
 
@@ -956,6 +961,115 @@ IbatQueryPathByPhysicalAddress(
 
 
 EXTERN_C
+NTSTATUS
+IbatQueryPath(
+    __in IBAT_ROUTING_CONTEXT routingContext,
+    __in UINT64 destMac,
+    __in FN_IBAT_QUERY_PATH_CALLBACK* completionCallback,
+    __in VOID* completionContext,
+    __out ib_path_rec_t* pPath
+    )
+{
+    return routingContext->Resolve(
+        destMac,
+        completionCallback,
+        completionContext,
+        pPath
+        );
+}
+
+
+EXTERN_C
+NTSTATUS
+IbatCancelQuery(
+    __in IBAT_ROUTING_CONTEXT routingContext,
+    __in UINT64 destMac,
+    __in FN_IBAT_QUERY_PATH_CALLBACK* completionCallback,
+    __in VOID* completionContext
+    )
+{
+    return routingContext->CancelResolve(
+        destMac,
+        completionCallback,
+        completionContext
+        );
+}
+
+
+EXTERN_C
+NTSTATUS
+IbatCancelQueryByIpAddress(
+    __in const SOCKADDR_INET* pLocalAddress,
+    __in const SOCKADDR_INET* pRemoteAddress,
+    __in FN_IBAT_QUERY_PATH_CALLBACK* completionCallback,
+    __in VOID* completionContext
+    )
+{
+    NTSTATUS status;
+    ULONG iReg;
+    ULONG64 mac;
+
+    NT_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
+
+    KeEnterCriticalRegion();
+    ExAcquireResourceSharedLite( &g_ibatLock, TRUE );
+
+    status = IbatpResolvePhysicalAddressUnsafe(
+                                pLocalAddress,
+                                pRemoteAddress,
+                                &iReg,
+                                &mac
+                                );
+
+    if( NT_SUCCESS( status ) )
+    {
+        status = g_ibatPorts[iReg].pRouter->CancelResolve(
+            mac,
+            completionCallback,
+            completionContext
+            );
+    }
+
+    ExReleaseResourceLite( &g_ibatLock );
+    KeLeaveCriticalRegion();
+    return status;
+}
+
+
+EXTERN_C
+NTSTATUS
+IbatCancelQueryByPhysicalAddress(
+    __in UINT64 srcMac,
+    __in UINT64 destMac,
+    __in FN_IBAT_QUERY_PATH_CALLBACK* completionCallback,
+    __in VOID* completionContext
+    )
+{
+    NTSTATUS status;
+    ULONG iReg;
+
+    NT_ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );
+
+    KeEnterCriticalRegion();
+    ExAcquireResourceSharedLite( &g_ibatLock, TRUE );
+
+    status = IbatpPortToIndexUnsafe( srcMac, &iReg );
+    if( NT_SUCCESS( status ) )
+    {
+        status = g_ibatPorts[iReg].pRouter->CancelResolve(
+            destMac,
+            completionCallback,
+            completionContext
+            );
+    }
+
+    ExReleaseResourceLite( &g_ibatLock );
+    KeLeaveCriticalRegion();
+    return status;
+}
+
+
+EXTERN_C
 void
 IbatGetInterface(
     __out IBAT_IFC* pIbatIfc
@@ -966,10 +1080,14 @@ IbatGetInterface(
     pIbatIfc->UpdateRegistration =          IbatUpdateRegistration;
     pIbatIfc->UpdateRoute =                 IbatUpdateRoute;
     pIbatIfc->ClearAllRoutes =              IbatClearAllRoutes;
+    pIbatIfc->QueryPath =                   IbatQueryPath;
+    pIbatIfc->CancelQuery =                 IbatCancelQuery;
     pIbatIfc->GetIpList =                   IbatGetIpList;
     pIbatIfc->IpToPort =                    IbatIpToPort;
     pIbatIfc->QueryPathByIpAddress =        IbatQueryPathByIpAddress;
+    pIbatIfc->CancelQueryByIpAddress =      IbatCancelQueryByIpAddress;
     pIbatIfc->QueryPathByPhysicalAddress =  IbatQueryPathByPhysicalAddress;
+    pIbatIfc->CancelQueryByPhysicalAddress = IbatCancelQueryByPhysicalAddress;
     pIbatIfc->ResolvePhysicalAddress =      IbatResolvePhysicalAddress;
     pIbatIfc->MacToPort =                   IbatMacToPort;
 }
diff -dwup3 -X excl.txt -I ^ \*$ -I ^ \* \$ -r \dev\openib\Mellanox\11011\core\ibat\kernel\route.cpp .\core\ibat\kernel\route.cpp
--- \dev\openib\Mellanox\11011\core\ibat\kernel\route.cpp	Thu Sep 20 17:51:00 2012
+++ .\core\ibat\kernel\route.cpp	Thu Oct 04 16:24:57 2012
@@ -33,7 +33,19 @@
 #include "route.h"
 
 
-#define IBAT_PATH_QUERY_TIMEOUT 500
+//
+// Negative timeout does recursive doubling.
+//
+// Retry intervals total 10 seconds, and are as follow:
+//  250 ms
+//  500 ms
+//  1000 ms
+//  2000 ms
+//  3125 ms
+//  3125 ms
+//
+#define IBAT_PATH_QUERY_TIMEOUT (ULONG)-(3125L << 16 | 250L)
+#define IBAT_PATH_QUERY_RETRIES 5
 
 
 //
@@ -212,7 +224,7 @@ IbatRoute::QueryPathUnsafe()
     query.port_guid = m_srcGid.unicast.interface_id;
 
     query.timeout_ms = IBAT_PATH_QUERY_TIMEOUT;
-    query.retry_cnt = 0;
+    query.retry_cnt = IBAT_PATH_QUERY_RETRIES;
     query.flags = 0;
 
     query.query_context = this;
@@ -303,4 +315,39 @@ IbatRoute::Resolve(
     {
         QueryPathCompletion( status, NULL );
     }
+}
+
+
+NTSTATUS
+IbatRoute::CancelResolve(
+    __in FN_IBAT_QUERY_PATH_CALLBACK* completionCallback,
+    __in VOID* completionContext
+    )
+{
+    KLOCK_QUEUE_HANDLE hLock;
+    IBAT_ROUTE_REQUEST* pRequest;
+    IBAT_ROUTE_REQUEST** link;
+    NTSTATUS status = STATUS_NOT_FOUND;
+
+    KeAcquireInStackQueuedSpinLock( &m_requestLock, &hLock );
+
+    link = &m_requestList;
+    for( pRequest = *link; pRequest != NULL; pRequest = *link )
+    {
+        if( pRequest->callback == completionCallback &&
+            pRequest->completionContext == completionContext )
+        {
+            *link = pRequest->pNext;
+
+            ExFreePoolWithTag( pRequest, IBAT_POOL_TAG );
+            status = STATUS_SUCCESS;
+        }
+        else
+        {
+            link = &pRequest->pNext;
+        }
+    }
+
+    KeReleaseInStackQueuedSpinLock( &hLock );
+    return status;
 }
diff -dwup3 -X excl.txt -I ^ \*$ -I ^ \* \$ -r \dev\openib\Mellanox\11011\core\ibat\kernel\route.h .\core\ibat\kernel\route.h
--- \dev\openib\Mellanox\11011\core\ibat\kernel\route.h	Thu Sep 20 17:51:00 2012
+++ .\core\ibat\kernel\route.h	Tue Oct 02 11:51:45 2012
@@ -81,6 +81,11 @@ public:
         __in_opt IBAT_ROUTE_REQUEST* pRequestList
         );
 
+    NTSTATUS CancelResolve(
+        __in FN_IBAT_QUERY_PATH_CALLBACK* completionCallback,
+        __in VOID* completionContext
+        );
+
 private:
     static VOID AL_API PathQueryCallback( __in ib_query_rec_t* pQueryResult );
     VOID
diff -dwup3 -X excl.txt -I ^ \*$ -I ^ \* \$ -r \dev\openib\Mellanox\11011\core\ibat\kernel\router.cpp .\core\ibat\kernel\router.cpp
--- \dev\openib\Mellanox\11011\core\ibat\kernel\router.cpp	Thu Sep 20 17:51:00 2012
+++ .\core\ibat\kernel\router.cpp	Thu Oct 04 16:25:50 2012
@@ -301,3 +301,36 @@ IbatRouter::Resolve(
     KeReleaseInStackQueuedSpinLock( &hdl );
     return status;
 }
+
+
+NTSTATUS
+IbatRouter::CancelResolve(
+    __in UINT64 destMac,
+    __in FN_IBAT_QUERY_PATH_CALLBACK* completionCallback,
+    __in VOID* completionContext
+    )
+{
+    if( m_isRoCE == TRUE )
+    {
+        return STATUS_NOT_FOUND;
+    }
+
+    NTSTATUS status = STATUS_NOT_FOUND;
+    KLOCK_QUEUE_HANDLE hdl;
+
+    KeAcquireInStackQueuedSpinLock( &m_lock, &hdl );
+    IBAT_ROUTE_ENTRY* pEntry = static_cast<IBAT_ROUTE_ENTRY*>(
+        RtlLookupElementGenericTableAvl( &m_table, &destMac )
+        );
+
+    if( pEntry != NULL )
+    {
+        status = pEntry->pRoute->CancelResolve(
+            completionCallback,
+            completionContext
+            );
+    }
+
+    KeReleaseInStackQueuedSpinLock( &hdl );
+    return status;
+}
diff -dwup3 -X excl.txt -I ^ \*$ -I ^ \* \$ -r \dev\openib\Mellanox\11011\core\ibat\kernel\router.h .\core\ibat\kernel\router.h
--- \dev\openib\Mellanox\11011\core\ibat\kernel\router.h	Thu Sep 20 17:51:00 2012
+++ .\core\ibat\kernel\router.h	Tue Oct 02 11:51:46 2012
@@ -73,4 +73,10 @@ public:
         __in VOID* completionContext,
         __out ib_path_rec_t* pPath
         );
+
+    NTSTATUS CancelResolve(
+        __in UINT64 destMac,
+        __in FN_IBAT_QUERY_PATH_CALLBACK* completionCallback,
+        __in VOID* completionContext
+        );
 };
diff -dwup3 -X excl.txt -I ^ \*$ -I ^ \* \$ -r \dev\openib\Mellanox\11011\inc\kernel\iba\ibat.h .\inc\kernel\iba\ibat.h
--- \dev\openib\Mellanox\11011\inc\kernel\iba\ibat.h	Thu Sep 20 17:51:06 2012
+++ .\inc\kernel\iba\ibat.h	Tue Oct 02 14:10:32 2012
@@ -102,6 +102,46 @@ FN_IBAT_CLEAR_ALL_ROUTES(
     );
 FN_IBAT_CLEAR_ALL_ROUTES IbatClearAllRoutes;
 
+//
+// Callback for path queries.
+//
+typedef
+__drv_maxFunctionIRQL(DISPATCH_LEVEL)
+VOID
+FN_IBAT_QUERY_PATH_CALLBACK(
+    __in VOID* completionContext,
+    __in NTSTATUS status,
+    __in ib_path_rec_t* const pPath
+    );
+
+//
+// Queries the path record for the supplied route.
+//
+typedef
+__drv_maxFunctionIRQL(DISPATCH_LEVEL)
+NTSTATUS
+FN_IBAT_QUERY_PATH(
+    __in IBAT_ROUTING_CONTEXT routingContext,
+    __in UINT64 destMac,
+    __in FN_IBAT_QUERY_PATH_CALLBACK* completionCallback,
+    __in VOID* completionContext,
+    __out ib_path_rec_t* pPath
+    );
+FN_IBAT_QUERY_PATH IbatQueryPath;
+
+//
+// Cancel an outstanding query.
+//
+typedef
+__drv_maxFunctionIRQL(DISPATCH_LEVEL)
+NTSTATUS
+FN_IBAT_CANCEL_QUERY(
+    __in IBAT_ROUTING_CONTEXT routingContext,
+    __in UINT64 destMac,
+    __in FN_IBAT_QUERY_PATH_CALLBACK* completionCallback,
+    __in VOID* completionContext
+    );
+FN_IBAT_CANCEL_QUERY IbatCancelQuery;
 
 //
 // Initializes global structures - called by whoever provides IBAT support.
@@ -183,30 +223,32 @@ FN_IBAT_MAC_TO_PORT IbatMacToPort;
 // the completion callback and the path out parameter is not used.
 //
 typedef
-__drv_maxFunctionIRQL(DISPATCH_LEVEL)
-VOID
-FN_IBAT_QUERY_PATH_CALLBACK(
+__drv_maxFunctionIRQL(PASSIVE_LEVEL)
+NTSTATUS
+FN_IBAT_QUERY_PATH_BY_IP_ADDRESS(
+    __in const SOCKADDR_INET* pLocalAddress,
+    __in const SOCKADDR_INET* pRemoteAddress,
+    __in FN_IBAT_QUERY_PATH_CALLBACK* completionCallback,
     __in VOID* completionContext,
-    __in NTSTATUS status,
-    __in ib_path_rec_t* const pPath
+    __out ib_path_rec_t* pPath
     );
+FN_IBAT_QUERY_PATH_BY_IP_ADDRESS IbatQueryPathByIpAddress;
 
 
 typedef
-__drv_maxFunctionIRQL(APC_LEVEL)
+__drv_maxFunctionIRQL(PASSIVE_LEVEL)
 NTSTATUS
-FN_IBAT_QUERY_PATH_BY_IP_ADDRESS(
+FN_IBAT_CANCEL_QUERY_BY_IP_ADDRESS(
     __in const SOCKADDR_INET* pLocalAddress,
     __in const SOCKADDR_INET* pRemoteAddress,
     __in FN_IBAT_QUERY_PATH_CALLBACK* completionCallback,
-    __in VOID* completionContext,
-    __out ib_path_rec_t* pPath
+    __in VOID* completionContext
     );
-FN_IBAT_QUERY_PATH_BY_IP_ADDRESS IbatQueryPathByIpAddress;
+FN_IBAT_CANCEL_QUERY_BY_IP_ADDRESS IbatCancelQueryByIpAddress;
 
 
 typedef
-__drv_maxFunctionIRQL(APC_LEVEL)
+__drv_maxFunctionIRQL(PASSIVE_LEVEL)
 NTSTATUS
 FN_IBAT_QUERY_PATH_BY_PHYSICAL_ADDRESS(
     __in UINT64 srcMac,
@@ -219,7 +261,19 @@ FN_IBAT_QUERY_PATH_BY_PHYSICAL_ADDRESS I
 
 
 typedef
-__drv_maxFunctionIRQL(APC_LEVEL)
+__drv_maxFunctionIRQL(PASSIVE_LEVEL)
+NTSTATUS
+FN_IBAT_CANCEL_QUERY_BY_PHYSICAL_ADDRESS(
+    __in UINT64 srcMac,
+    __in UINT64 destMac,
+    __in FN_IBAT_QUERY_PATH_CALLBACK* completionCallback,
+    __in VOID* completionContext
+    );
+FN_IBAT_CANCEL_QUERY_BY_PHYSICAL_ADDRESS IbatCancelQueryByPhysicalAddress;
+
+
+typedef
+__drv_maxFunctionIRQL(PASSIVE_LEVEL)
 NTSTATUS
 FN_IBAT_RESOLVE_PHYSICAL_ADDRESS(
     __in const SOCKADDR_INET*   pLocalAddress,
@@ -228,6 +282,7 @@ FN_IBAT_RESOLVE_PHYSICAL_ADDRESS(
     __out UINT64*               pDestMac
     );
 FN_IBAT_RESOLVE_PHYSICAL_ADDRESS IbatResolvePhysicalAddress;
+
 
 #ifdef __cplusplus
 } //extern "C" {
diff -dwup3 -X excl.txt -I ^ \*$ -I ^ \* \$ -r \dev\openib\Mellanox\11011\inc\kernel\iba\ibat_ifc.h .\inc\kernel\iba\ibat_ifc.h
--- \dev\openib\Mellanox\11011\inc\kernel\iba\ibat_ifc.h	Thu Sep 20 17:51:06 2012
+++ .\inc\kernel\iba\ibat_ifc.h	Tue Oct 02 12:25:04 2012
@@ -33,7 +33,7 @@
 
 #include <iba\ibat.h>
 
-#define IBAT_INTERFACE_VERSION		(3)
+#define IBAT_INTERFACE_VERSION		(4)
 
 
 /* Interface definitions */
@@ -47,10 +47,14 @@ typedef struct _IBAT_IFC
     FN_IBAT_UPDATE_REGISTRATION*            UpdateRegistration;
     FN_IBAT_UPDATE_ROUTE*                   UpdateRoute;
     FN_IBAT_CLEAR_ALL_ROUTES*               ClearAllRoutes;
+    FN_IBAT_QUERY_PATH*                     QueryPath;
+    FN_IBAT_CANCEL_QUERY*                   CancelQuery;
     FN_IBAT_GET_IP_LIST*                    GetIpList;
     FN_IBAT_IP_TO_PORT*                     IpToPort;
     FN_IBAT_QUERY_PATH_BY_IP_ADDRESS*       QueryPathByIpAddress;
+    FN_IBAT_CANCEL_QUERY_BY_IP_ADDRESS*     CancelQueryByIpAddress;
     FN_IBAT_QUERY_PATH_BY_PHYSICAL_ADDRESS* QueryPathByPhysicalAddress;
+    FN_IBAT_CANCEL_QUERY_BY_PHYSICAL_ADDRESS* CancelQueryByPhysicalAddress;
     FN_IBAT_RESOLVE_PHYSICAL_ADDRESS*       ResolvePhysicalAddress;
     FN_IBAT_MAC_TO_PORT*                    MacToPort;

-------------- next part --------------
A non-text attachment was scrubbed...
Name: ndv2.58.patch
Type: application/octet-stream
Size: 17325 bytes
Desc: ndv2.58.patch
URL: <http://lists.openfabrics.org/pipermail/ofw/attachments/20130221/abe50b39/attachment.obj>


More information about the ofw mailing list