[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