1933 lines
53 KiB
C
1933 lines
53 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1990 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
kdcn.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Clustner Xport KD extension - based on Vert's skeleton
|
||
|
|
||
|
Author:
|
||
|
|
||
|
John Vert (jvert) 6-Aug-1992
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
//
|
||
|
// globals
|
||
|
//
|
||
|
|
||
|
EXT_API_VERSION ApiVersion = { 5, 0, EXT_API_VERSION_NUMBER, 0 };
|
||
|
WINDBG_EXTENSION_APIS ExtensionApis;
|
||
|
USHORT SavedMajorVersion;
|
||
|
USHORT SavedMinorVersion;
|
||
|
|
||
|
CHAR igrepLastPattern[256];
|
||
|
DWORD igrepSearchStartAddress;
|
||
|
DWORD igrepLastPc;
|
||
|
|
||
|
PCHAR EventTypes[] = {
|
||
|
"", // used if the number is out of range
|
||
|
"Node Up",
|
||
|
"Node Down",
|
||
|
"Poison Packet Received",
|
||
|
"Halt",
|
||
|
"Net IF Up",
|
||
|
"Net IF Unreachable",
|
||
|
"Net IF Failed",
|
||
|
"(not used)",
|
||
|
"Add Address",
|
||
|
"Delete Address"
|
||
|
};
|
||
|
|
||
|
PCHAR NetObjState[] = {
|
||
|
"Offline",
|
||
|
"OfflinePending",
|
||
|
"Partitioned",
|
||
|
"OnlinePending",
|
||
|
"Online"
|
||
|
};
|
||
|
|
||
|
PCHAR NodeObjCommState[] = {
|
||
|
"Offline",
|
||
|
"OfflinePending",
|
||
|
"Unreachable",
|
||
|
"OnlinePending",
|
||
|
"Online"
|
||
|
};
|
||
|
|
||
|
PCHAR NodeObjMemberState[] = {
|
||
|
"Alive",
|
||
|
"Joining",
|
||
|
"Dead",
|
||
|
"Not Configured"
|
||
|
};
|
||
|
|
||
|
PCHAR InterfaceState[] = {
|
||
|
"Offline",
|
||
|
"OfflinePending",
|
||
|
"Unreachable",
|
||
|
"OnlinePending",
|
||
|
"Online"
|
||
|
};
|
||
|
|
||
|
PCHAR CcmpMessageTypes[] = {
|
||
|
"Invalid",
|
||
|
"Heartbeat",
|
||
|
"Poison",
|
||
|
"Membership"
|
||
|
};
|
||
|
|
||
|
#define TrueOrFalse( _x ) ( _x ? "True" : "False" )
|
||
|
|
||
|
/* forwards */
|
||
|
|
||
|
VOID
|
||
|
DumpEventData(
|
||
|
PCLUSNET_EVENT_ENTRY EventAddress,
|
||
|
PCLUSNET_EVENT_ENTRY EventEntry
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
DumpInterfaceObj(
|
||
|
PCNP_INTERFACE TargetIfObj,
|
||
|
PCNP_INTERFACE LocalIfObj
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
ReadNodeTable(
|
||
|
PCNP_NODE **LocalNodeTable,
|
||
|
CL_NODE_ID *MaxNodeId,
|
||
|
CL_NODE_ID *MinNodeId
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
DumpNodeObjFlags(
|
||
|
ULONG Flags
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
DumpNetObjFlags(
|
||
|
ULONG Flag
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
ReadTargetMemory(
|
||
|
PVOID TargetAddress,
|
||
|
PVOID LocalBuffer,
|
||
|
ULONG BytesToRead
|
||
|
);
|
||
|
|
||
|
__inline PCHAR
|
||
|
ListInUse(
|
||
|
PLIST_ENTRY ListHead,
|
||
|
PLIST_ENTRY ListToCheck
|
||
|
);
|
||
|
|
||
|
__inline PCHAR
|
||
|
TrueFalse(
|
||
|
BOOLEAN Value
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
DprintUnicodeString(
|
||
|
PUNICODE_STRING String,
|
||
|
DWORD_PTR AddrString,
|
||
|
PCHAR Symbol OPTIONAL,
|
||
|
DWORD_PTR Displacement OPTIONAL
|
||
|
);
|
||
|
|
||
|
#if 0
|
||
|
VOID
|
||
|
DumpRGPCounters(
|
||
|
rgp_counter_t *counters
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
DumpClusterMask(
|
||
|
PCHAR Title,
|
||
|
cluster_t *
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
DumpRGPOSSpecific(
|
||
|
OS_specific_rgp_control_t *Target_rgpos,
|
||
|
OS_specific_rgp_control_t *Local_rgpos
|
||
|
);
|
||
|
#endif
|
||
|
|
||
|
/* end forwards */
|
||
|
|
||
|
DllInit(
|
||
|
HANDLE hModule,
|
||
|
DWORD dwReason,
|
||
|
DWORD dwReserved
|
||
|
)
|
||
|
{
|
||
|
switch (dwReason) {
|
||
|
case DLL_THREAD_ATTACH:
|
||
|
break;
|
||
|
|
||
|
case DLL_THREAD_DETACH:
|
||
|
break;
|
||
|
|
||
|
case DLL_PROCESS_DETACH:
|
||
|
break;
|
||
|
|
||
|
case DLL_PROCESS_ATTACH:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID
|
||
|
WinDbgExtensionDllInit(
|
||
|
PWINDBG_EXTENSION_APIS lpExtensionApis,
|
||
|
USHORT MajorVersion,
|
||
|
USHORT MinorVersion
|
||
|
)
|
||
|
{
|
||
|
ExtensionApis = *lpExtensionApis;
|
||
|
|
||
|
SavedMajorVersion = MajorVersion;
|
||
|
SavedMinorVersion = MinorVersion;
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
DECLARE_API( version )
|
||
|
{
|
||
|
#if DBG
|
||
|
PCHAR DebuggerType = "Checked";
|
||
|
#else
|
||
|
PCHAR DebuggerType = "Free";
|
||
|
#endif
|
||
|
|
||
|
dprintf("%s Extension dll for Build %d debugging %s clusnet for Build %d\n",
|
||
|
DebuggerType,
|
||
|
VER_PRODUCTBUILD,
|
||
|
SavedMajorVersion == 0x0c ? "Checked" : "Free",
|
||
|
SavedMinorVersion
|
||
|
);
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
CheckVersion(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
PVOID cnDebugAddr;
|
||
|
|
||
|
cnDebugAddr = (PVOID)GetExpression( "clusnet!cndebug" );
|
||
|
|
||
|
#if DBG
|
||
|
if ( cnDebugAddr == NULL ) {
|
||
|
dprintf("\r\nYou MUST use the checked built KDCN with the checked built driver!!!\n\n");
|
||
|
}
|
||
|
|
||
|
if ((SavedMajorVersion != 0x0c) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
|
||
|
dprintf("\r\n*** Extension DLL(%d Checked) does not match target system(%d %s)\r\n\r\n",
|
||
|
VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
|
||
|
}
|
||
|
#else
|
||
|
if ( cnDebugAddr != NULL ) {
|
||
|
dprintf("\r\nYou MUST use the free built KDCN with the free built driver!!!\n\n");
|
||
|
}
|
||
|
if ((SavedMajorVersion != 0x0f) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
|
||
|
dprintf("\r\n*** Extension DLL(%d Free) does not match target system(%d %s)\r\n\r\n",
|
||
|
VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
LPEXT_API_VERSION
|
||
|
ExtensionApiVersion(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
return &ApiVersion;
|
||
|
}
|
||
|
|
||
|
DECLARE_API( ustr )
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This function is called as a KD extension to format and dump
|
||
|
counted unicode string.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
see wdbgexts.h
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
UNICODE_STRING UnicodeString;
|
||
|
DWORD_PTR dwAddrString;
|
||
|
CHAR Symbol[64];
|
||
|
DWORD_PTR Displacement;
|
||
|
BOOL b;
|
||
|
|
||
|
//
|
||
|
// Evaluate the argument string to get the address of
|
||
|
// the string to dump.
|
||
|
//
|
||
|
|
||
|
dwAddrString = GetExpression(args);
|
||
|
if ( !dwAddrString ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the symbolic name of the string
|
||
|
//
|
||
|
|
||
|
GetSymbol((LPVOID)dwAddrString,Symbol,&Displacement);
|
||
|
|
||
|
//
|
||
|
// Read the string from the debuggees address space into our
|
||
|
// own.
|
||
|
|
||
|
b = ReadMemory(dwAddrString, &UnicodeString, sizeof(UnicodeString), NULL);
|
||
|
|
||
|
if ( !b ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
DprintUnicodeString(&UnicodeString, dwAddrString, Symbol, Displacement);
|
||
|
|
||
|
} // ustr
|
||
|
|
||
|
DECLARE_API( netobj )
|
||
|
/*
|
||
|
* dump the specified clusnet network object structure or all if no
|
||
|
* arg is specified
|
||
|
*/
|
||
|
{
|
||
|
PCNP_NETWORK TargetNetObj;
|
||
|
CNP_NETWORK LocalNetObj;
|
||
|
PCNP_NETWORK LastNetObj;
|
||
|
LIST_ENTRY LocalListHead;
|
||
|
PLIST_ENTRY TargetListHead;
|
||
|
BOOLEAN DumpAllNetObjs = FALSE;
|
||
|
|
||
|
if ( *args == '\0' ) {
|
||
|
|
||
|
//
|
||
|
// run down the network object list, dumping the contents of each one
|
||
|
//
|
||
|
TargetListHead = (PLIST_ENTRY)GetExpression( "clusnet!cnpnetworklist" );
|
||
|
if ( !TargetListHead ) {
|
||
|
dprintf("Can't convert clusnet!cnpnetworklist symbol\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read network object listhead out of target's memory
|
||
|
//
|
||
|
if ( !ReadTargetMemory( TargetListHead, &LocalListHead, sizeof(LIST_ENTRY))) {
|
||
|
|
||
|
dprintf("Can't get CnpNetworkList data\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
TargetNetObj = (PCNP_NETWORK)LocalListHead.Flink;
|
||
|
LastNetObj = (PCNP_NETWORK)TargetListHead;
|
||
|
DumpAllNetObjs = TRUE;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
TargetNetObj = (PCNP_NETWORK)GetExpression( args );
|
||
|
if ( !TargetNetObj ) {
|
||
|
dprintf("bad string conversion (%s) \n", args );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
LastNetObj = 0;
|
||
|
}
|
||
|
|
||
|
while ( TargetNetObj != LastNetObj ) {
|
||
|
|
||
|
if (CheckControlC()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read network object struct out of target's memory
|
||
|
//
|
||
|
TargetNetObj = CONTAINING_RECORD( TargetNetObj, CNP_NETWORK, Linkage );
|
||
|
if ( !ReadTargetMemory( TargetNetObj, &LocalNetObj, sizeof( CNP_NETWORK ))) {
|
||
|
dprintf("Problem reading net obj at %p\n", TargetNetObj );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#if DBG
|
||
|
if ( LocalNetObj.Signature != CNP_NETWORK_SIG ) {
|
||
|
dprintf( "CNP_NETWORK @ %p has the wrong signature\n", TargetNetObj );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
dprintf( "\nNetObj @ %p\n\n", TargetNetObj );
|
||
|
dprintf( " Next NetObj @ %p\n", LocalNetObj.Linkage.Flink );
|
||
|
|
||
|
dprintf( " ID = %d\n", LocalNetObj.Id );
|
||
|
dprintf( " Lock @ %p\n", &TargetNetObj->Lock );
|
||
|
dprintf( " Irql = %d\n", LocalNetObj.Irql );
|
||
|
dprintf( " RefCount = %d\n", LocalNetObj.RefCount );
|
||
|
dprintf( " Active RefCount = %d\n", LocalNetObj.ActiveRefCount );
|
||
|
dprintf( " State = %s\n", NetObjState [ LocalNetObj.State ]);
|
||
|
DumpNetObjFlags( LocalNetObj.Flags );
|
||
|
dprintf( " Priority = %d\n", LocalNetObj.Priority );
|
||
|
dprintf( " DatagramHandle @ %p\n", LocalNetObj.DatagramHandle );
|
||
|
dprintf( " Datagram File Obj @ %p\n", LocalNetObj.DatagramFileObject );
|
||
|
dprintf( " Datagram Device Obj @ %p\n", LocalNetObj.DatagramDeviceObject );
|
||
|
dprintf( " TDI provider info @ %p\n", &TargetNetObj->ProviderInfo );
|
||
|
dprintf( " Current mcast group @ %p\n", LocalNetObj.CurrentMcastGroup );
|
||
|
dprintf( " Previous mcast group @ %p\n", LocalNetObj.PreviousMcastGroup );
|
||
|
dprintf( " Multicast reachable node set = %lx\n", LocalNetObj.McastReachableNodes);
|
||
|
dprintf( " Multicast reachable node count = %d\n", LocalNetObj.McastReachableCount);
|
||
|
dprintf( " Pending Delete IRP @ %p\n", LocalNetObj.PendingDeleteIrp );
|
||
|
dprintf( " Pending Offline IRP @ %p\n", LocalNetObj.PendingOfflineIrp );
|
||
|
dprintf( " Work Q Item @ %p\n", &TargetNetObj->ExWorkItem );
|
||
|
|
||
|
if ( !DumpAllNetObjs ) {
|
||
|
break;
|
||
|
} else {
|
||
|
TargetNetObj = (PCNP_NETWORK)LocalNetObj.Linkage.Flink;
|
||
|
}
|
||
|
}
|
||
|
} // netobj
|
||
|
|
||
|
VOID
|
||
|
DumpNetObjFlags(
|
||
|
ULONG Flags
|
||
|
)
|
||
|
{
|
||
|
dprintf(" Flags = %08X (", Flags );
|
||
|
if ( Flags & CNP_NET_FLAG_DELETING )
|
||
|
dprintf(" Deleting" );
|
||
|
if ( Flags & CNP_NET_FLAG_PARTITIONED )
|
||
|
dprintf(" Partitioned" );
|
||
|
if ( Flags & CNP_NET_FLAG_RESTRICTED )
|
||
|
dprintf(" Restricted" );
|
||
|
if ( Flags & CNP_NET_FLAG_LOCALDISCONN ) {
|
||
|
dprintf(" Local-Disconnect" );
|
||
|
}
|
||
|
if ( Flags & CNP_NET_FLAG_MULTICAST ) {
|
||
|
dprintf(" Multicast-Enabled" );
|
||
|
}
|
||
|
dprintf(")\n");
|
||
|
}
|
||
|
|
||
|
DECLARE_API( nodeobj )
|
||
|
/*
|
||
|
* if no arg, run down the node table, dumping each clusnet node object
|
||
|
* structure. otherwise, dump the indicated node obj
|
||
|
*/
|
||
|
{
|
||
|
PCNP_NODE TargetNodeObj;
|
||
|
CNP_NODE LocalNodeObj;
|
||
|
PCNP_NODE *LocalNodeTable = NULL;
|
||
|
CL_NODE_ID MaxNodeId, MinNodeId;
|
||
|
ULONG StartNode, EndNode, Node;
|
||
|
|
||
|
//
|
||
|
// read in the node table
|
||
|
//
|
||
|
if ( !ReadNodeTable( &LocalNodeTable, &MaxNodeId, &MinNodeId )) {
|
||
|
if ( LocalNodeTable )
|
||
|
free( LocalNodeTable );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( *args == '\0' ) {
|
||
|
|
||
|
StartNode = MinNodeId;
|
||
|
EndNode = MaxNodeId;
|
||
|
} else {
|
||
|
|
||
|
StartNode = EndNode = (ULONG)GetExpression( args );
|
||
|
|
||
|
if ( StartNode > MaxNodeId ) {
|
||
|
dprintf("Node ID out of Range: 0 to %d\n", MaxNodeId );
|
||
|
|
||
|
if ( LocalNodeTable )
|
||
|
free( LocalNodeTable );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dprintf("Min, Max Node ID = ( %u, %d )\n", MinNodeId, MaxNodeId );
|
||
|
|
||
|
for ( Node = StartNode; Node <= EndNode; ++Node ) {
|
||
|
|
||
|
if (CheckControlC()) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read node object struct out of target's memory
|
||
|
//
|
||
|
TargetNodeObj = *(LocalNodeTable + Node);
|
||
|
if ( TargetNodeObj == NULL ) {
|
||
|
|
||
|
continue;
|
||
|
} else if ( !ReadTargetMemory( TargetNodeObj, &LocalNodeObj, sizeof( CNP_NODE ))) {
|
||
|
|
||
|
dprintf("Problem reading node obj at %p (Node %d)\n", TargetNodeObj, Node );
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
#if DBG
|
||
|
if ( LocalNodeObj.Signature != CNP_NODE_SIG ) {
|
||
|
dprintf( "CNP_NODE @ %p has the wrong signature\n", TargetNodeObj );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
dprintf( "\nNodeObj @ %p\n\n", TargetNodeObj );
|
||
|
dprintf( " Linkage.Flink @ %p\n", LocalNodeObj.Linkage.Flink );
|
||
|
|
||
|
dprintf( " ID = %d\n", LocalNodeObj.Id );
|
||
|
dprintf( " Lock @ %p\n", &TargetNodeObj->Lock );
|
||
|
dprintf( " Irql = %d\n", LocalNodeObj.Irql );
|
||
|
dprintf( " RefCount = %d\n", LocalNodeObj.RefCount );
|
||
|
dprintf( " Comm State = %s\n", NodeObjCommState [ LocalNodeObj.CommState ]);
|
||
|
dprintf( " MMState = %s\n", NodeObjMemberState [ LocalNodeObj.MMState ]);
|
||
|
DumpNodeObjFlags( LocalNodeObj.Flags );
|
||
|
dprintf( " Interface List @ %p", &TargetNodeObj->InterfaceList );
|
||
|
if ( &TargetNodeObj->InterfaceList == LocalNodeObj.InterfaceList.Flink ) {
|
||
|
dprintf( " (empty)" );
|
||
|
}
|
||
|
dprintf( "\n" );
|
||
|
|
||
|
dprintf( " Current Interface @ %p\n", LocalNodeObj.CurrentInterface );
|
||
|
dprintf( " Pending Delete IRP @ %p\n", LocalNodeObj.PendingDeleteIrp );
|
||
|
|
||
|
dprintf( " HBWasMissed = %s\n", TrueOrFalse( LocalNodeObj.HBWasMissed ));
|
||
|
dprintf( " Node Down Issued = %s\n", TrueOrFalse( LocalNodeObj.NodeDownIssued ));
|
||
|
dprintf( " MissedHBs = %u\n", LocalNodeObj.MissedHBs );
|
||
|
}
|
||
|
|
||
|
if ( LocalNodeTable ) {
|
||
|
free( LocalNodeTable );
|
||
|
}
|
||
|
} // nodeobj
|
||
|
|
||
|
VOID
|
||
|
DumpNodeObjFlags(
|
||
|
ULONG Flags
|
||
|
)
|
||
|
{
|
||
|
dprintf(" Flags = %08X (", Flags );
|
||
|
if ( Flags & CNP_NODE_FLAG_DELETING )
|
||
|
dprintf(" Deleting" );
|
||
|
if ( Flags & CNP_NODE_FLAG_UNREACHABLE )
|
||
|
dprintf(" Unreachable" );
|
||
|
if ( Flags & CNP_NODE_FLAG_LOCAL )
|
||
|
dprintf(" Local" );
|
||
|
dprintf(")\n");
|
||
|
}
|
||
|
|
||
|
DECLARE_API( nodeifs )
|
||
|
/*
|
||
|
* dump the interface list for the indicated node obj
|
||
|
*/
|
||
|
{
|
||
|
PCNP_NODE TargetNodeObj;
|
||
|
CNP_NODE LocalNodeObj;
|
||
|
PCNP_NODE *LocalNodeTable = NULL;
|
||
|
PCNP_INTERFACE NextTargetIfObj;
|
||
|
CNP_INTERFACE LocalIfObj;
|
||
|
CL_NODE_ID MaxNodeId, MinNodeId;
|
||
|
ULONG Node;
|
||
|
|
||
|
if ( *args == '\0' ) {
|
||
|
dprintf("Node ID must be specified\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !ReadNodeTable( &LocalNodeTable, &MaxNodeId, &MinNodeId )) {
|
||
|
|
||
|
if ( LocalNodeTable )
|
||
|
free( LocalNodeTable );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Node = (ULONG)GetExpression( args );
|
||
|
|
||
|
if ( Node > MaxNodeId || Node < MinNodeId ) {
|
||
|
dprintf("Node ID is out of range: %u to %u\n", MinNodeId, MaxNodeId );
|
||
|
|
||
|
if ( LocalNodeTable )
|
||
|
free( LocalNodeTable );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read node object struct out of target's memory
|
||
|
//
|
||
|
|
||
|
TargetNodeObj = *(LocalNodeTable + Node);
|
||
|
if ( !ReadTargetMemory( TargetNodeObj, &LocalNodeObj, sizeof( CNP_NODE ))) {
|
||
|
dprintf("Problem reading node obj at %p (Node %d)\n", TargetNodeObj, Node );
|
||
|
|
||
|
if ( LocalNodeTable )
|
||
|
free( LocalNodeTable );
|
||
|
return;
|
||
|
|
||
|
}
|
||
|
|
||
|
#if DBG
|
||
|
if ( LocalNodeObj.Signature != CNP_NODE_SIG ) {
|
||
|
dprintf( "CNP_NODE @ %p has the wrong signature\n", TargetNodeObj );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
dprintf( "\nNodeObj @ %p Interface List @ %p", TargetNodeObj, &TargetNodeObj->InterfaceList );
|
||
|
if ( &TargetNodeObj->InterfaceList == LocalNodeObj.InterfaceList.Flink ) {
|
||
|
dprintf( " (empty)" );
|
||
|
}
|
||
|
dprintf( "\n\n" );
|
||
|
|
||
|
NextTargetIfObj = (PCNP_INTERFACE)LocalNodeObj.InterfaceList.Flink;
|
||
|
|
||
|
while ( &TargetNodeObj->InterfaceList != (PLIST_ENTRY)NextTargetIfObj ) {
|
||
|
|
||
|
if (CheckControlC()) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
NextTargetIfObj = CONTAINING_RECORD( NextTargetIfObj, CNP_INTERFACE, NodeLinkage );
|
||
|
if ( !ReadTargetMemory(
|
||
|
NextTargetIfObj,
|
||
|
&LocalIfObj,
|
||
|
FIELD_OFFSET( CNP_INTERFACE, TdiAddress ) + sizeof(TA_IP_ADDRESS)
|
||
|
)
|
||
|
) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
DumpInterfaceObj( NextTargetIfObj, &LocalIfObj );
|
||
|
|
||
|
NextTargetIfObj = (PCNP_INTERFACE)LocalIfObj.NodeLinkage.Flink;
|
||
|
}
|
||
|
|
||
|
if ( LocalNodeTable ) {
|
||
|
free( LocalNodeTable );
|
||
|
}
|
||
|
} // nodeifs
|
||
|
|
||
|
DECLARE_API( currif )
|
||
|
/*
|
||
|
* for the specified node, dump the current interface obj
|
||
|
*/
|
||
|
{
|
||
|
PCNP_NODE TargetNodeObj;
|
||
|
CNP_NODE LocalNodeObj;
|
||
|
PCNP_NODE *LocalNodeTable = NULL;
|
||
|
CL_NODE_ID MaxNodeId, MinNodeId;
|
||
|
CNP_INTERFACE LocalIfObj;
|
||
|
ULONG Node;
|
||
|
|
||
|
if ( *args == '\0' ) {
|
||
|
dprintf("Node ID must be specified\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read in the node table
|
||
|
//
|
||
|
if ( !ReadNodeTable( &LocalNodeTable, &MaxNodeId, &MinNodeId )) {
|
||
|
|
||
|
if ( LocalNodeTable )
|
||
|
free( LocalNodeTable );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Node = (ULONG)GetExpression( args );
|
||
|
|
||
|
if ( Node > MaxNodeId || Node < MinNodeId ) {
|
||
|
dprintf("Node ID is out of range: %u to %u\n", MinNodeId, MaxNodeId );
|
||
|
|
||
|
if ( LocalNodeTable )
|
||
|
free( LocalNodeTable );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read node object struct out of target's memory
|
||
|
//
|
||
|
TargetNodeObj = *(LocalNodeTable + Node);
|
||
|
|
||
|
if ( !ReadTargetMemory( TargetNodeObj, &LocalNodeObj, sizeof( CNP_NODE ))) {
|
||
|
|
||
|
dprintf("Problem reading node obj at %p (Node %d)\n", TargetNodeObj, Node );
|
||
|
if ( LocalNodeTable )
|
||
|
free( LocalNodeTable );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#if DBG
|
||
|
if ( LocalNodeObj.Signature != CNP_NODE_SIG ) {
|
||
|
dprintf( "CNP_NODE @ %p has the wrong signature\n", TargetNodeObj );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
dprintf( "\nNodeObj @ %p Current Interface @ %p\n\n", TargetNodeObj, LocalNodeObj.CurrentInterface );
|
||
|
|
||
|
if ( LocalNodeObj.CurrentInterface ) {
|
||
|
|
||
|
if ( ReadTargetMemory( LocalNodeObj.CurrentInterface, &LocalIfObj, sizeof( CNP_INTERFACE ))) {
|
||
|
DumpInterfaceObj( LocalNodeObj.CurrentInterface, &LocalIfObj );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( LocalNodeTable ) {
|
||
|
free( LocalNodeTable );
|
||
|
}
|
||
|
} // currif
|
||
|
|
||
|
VOID
|
||
|
DumpInterfaceObj(
|
||
|
PCNP_INTERFACE TargetIfObj,
|
||
|
PCNP_INTERFACE IfObj
|
||
|
)
|
||
|
{
|
||
|
LONG i, j;
|
||
|
TA_ADDRESS *TA;
|
||
|
TDI_ADDRESS_IP UNALIGNED *TAIp;
|
||
|
|
||
|
#if DBG
|
||
|
if ( IfObj->Signature != CNP_INTERFACE_SIG ) {
|
||
|
dprintf( "CNP_INTERFACE @ %p has the wrong signature\n", TargetIfObj );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
dprintf("Interface Obj @ %p\n", TargetIfObj );
|
||
|
dprintf(" Node Obj @ %p\n", IfObj->Node );
|
||
|
dprintf(" Net Obj @ %p\n", IfObj->Network );
|
||
|
dprintf(" State = %s\n", InterfaceState[ IfObj->State ]);
|
||
|
dprintf(" Priority = %d\n", IfObj->Priority );
|
||
|
dprintf(" Flags = %08X\n", IfObj->Flags );
|
||
|
dprintf(" MissedHBs = %u\n", IfObj->MissedHBs );
|
||
|
dprintf(" Seq to send = %u\n", IfObj->SequenceToSend );
|
||
|
dprintf(" Last Seq Recv'd = %u\n", IfObj->LastSequenceReceived );
|
||
|
dprintf(" Multicast discovery count = %u\n", IfObj->McastDiscoverCount );
|
||
|
dprintf(" AdapterWMIProviderId = %08X\n", IfObj->AdapterWMIProviderId );
|
||
|
|
||
|
dprintf(" TDI Addr Len = %d\n", IfObj->TdiAddressLength );
|
||
|
dprintf(" TDI Addr Count = %d\n", IfObj->TdiAddress.TAAddressCount );
|
||
|
|
||
|
TA = IfObj->TdiAddress.Address;
|
||
|
for (i=0; i < IfObj->TdiAddress.TAAddressCount; ++i ) {
|
||
|
dprintf(" [%d] Addr Length = %d\n", i, TA->AddressLength );
|
||
|
dprintf(" [%d] Addr Type = %d", i, TA->AddressType );
|
||
|
|
||
|
switch ( TA->AddressType ) {
|
||
|
case TDI_ADDRESS_TYPE_IP:
|
||
|
TAIp = (TDI_ADDRESS_IP UNALIGNED *)TA->Address;
|
||
|
// dprintf("%08X %08X\n", TAIp->in_addr,ntohl(TAIp->in_addr));
|
||
|
dprintf(" (IP)\n [%d] Port: %d Addr: %d.%d.%d.%d\n",
|
||
|
i, ntohs(TAIp->sin_port), (ntohl(TAIp->in_addr) >> 24 ) & 0xFF,
|
||
|
(ntohl(TAIp->in_addr) >> 16 ) & 0xFF,
|
||
|
(ntohl(TAIp->in_addr) >> 8 ) & 0xFF,
|
||
|
ntohl(TAIp->in_addr) & 0xFF);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
dprintf("\n [%d] Addr:", i );
|
||
|
for( j = 0; j < TA->AddressLength; ++j )
|
||
|
dprintf(" %02X", TA->Address[j]);
|
||
|
dprintf("\n");
|
||
|
}
|
||
|
TA = (TA_ADDRESS *)((CHAR UNALIGNED *)TA + TA->AddressLength);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DECLARE_API( memlog )
|
||
|
/*
|
||
|
* dump the heart beat log. can optionally specify starting entry number
|
||
|
*/
|
||
|
{
|
||
|
PMEMLOG_ENTRY TargetMemLog;
|
||
|
PMEMLOG_ENTRY TargetLogEntry;
|
||
|
MEMLOG_ENTRY LogEntry;
|
||
|
PULONG TargetLogEntries;
|
||
|
ULONG LogEntries;
|
||
|
PULONG TargetNextLogEntry;
|
||
|
ULONG NextLogEntry;
|
||
|
LONG NumEntries;
|
||
|
ULONG Pass;
|
||
|
ULONG LineCount = 0;
|
||
|
ULONG StartingEntry;
|
||
|
LARGE_INTEGER LastSysTime;
|
||
|
DOUBLE LastTimeDelta;
|
||
|
DOUBLE FirstTimeDelta;
|
||
|
BOOLEAN PrintTime = TRUE;
|
||
|
LARGE_INTEGER FirstEntryTime;
|
||
|
|
||
|
//
|
||
|
// get address of MemLog and read its contents to get the real start
|
||
|
// of the log
|
||
|
//
|
||
|
|
||
|
TargetMemLog = (PMEMLOG_ENTRY)GetExpression( "clusnet!memlog" );
|
||
|
if ( !TargetMemLog ) {
|
||
|
|
||
|
dprintf( "Can't find symbol clusnet!memlog\n" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !ReadTargetMemory( TargetMemLog, &TargetMemLog, sizeof( PMEMLOG_ENTRY ))) {
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// repeat this process, getting the size of the log and the next entry index
|
||
|
//
|
||
|
|
||
|
TargetLogEntries = (PULONG)GetExpression( "clusnet!memlogentries" );
|
||
|
if ( !TargetLogEntries ) {
|
||
|
|
||
|
dprintf( "Can't find symbol clusnet!memlogentries\n" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !ReadTargetMemory( TargetLogEntries, &LogEntries, sizeof( ULONG ))) {
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
TargetNextLogEntry = (PULONG)GetExpression( "clusnet!memlognextlogentry" );
|
||
|
if ( !TargetNextLogEntry ) {
|
||
|
|
||
|
dprintf( "Can't find symbol clusnet!memlognextlogentry\n" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !ReadTargetMemory( TargetNextLogEntry, &NextLogEntry, sizeof( ULONG ))) {
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// get optional starting entry number
|
||
|
//
|
||
|
|
||
|
if ( *args != '\0' ) {
|
||
|
|
||
|
StartingEntry = (ULONG)GetExpression( args );
|
||
|
if ( StartingEntry >= LogEntries ) {
|
||
|
|
||
|
dprintf("Starting entry out of range (0 to %d)\n", LogEntries - 1);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( StartingEntry <= NextLogEntry ) {
|
||
|
|
||
|
//
|
||
|
// adjust starting number if on significant boundry
|
||
|
//
|
||
|
|
||
|
if ( StartingEntry == NextLogEntry ) {
|
||
|
if ( NextLogEntry == 0 )
|
||
|
StartingEntry = LogEntries - 1;
|
||
|
else
|
||
|
StartingEntry = NextLogEntry - 1;
|
||
|
}
|
||
|
|
||
|
Pass = 0;
|
||
|
NumEntries = StartingEntry + 1;
|
||
|
} else {
|
||
|
|
||
|
Pass = 1;
|
||
|
NumEntries = StartingEntry - NextLogEntry;
|
||
|
}
|
||
|
|
||
|
TargetLogEntry = TargetMemLog + StartingEntry;
|
||
|
} else {
|
||
|
|
||
|
Pass = 0;
|
||
|
|
||
|
if ( NextLogEntry == 0 )
|
||
|
NumEntries = LogEntries - 1;
|
||
|
else
|
||
|
NumEntries = NextLogEntry - 1;
|
||
|
|
||
|
TargetLogEntry = TargetMemLog + NumEntries;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read in the most current entry to get its time. We calc the first time
|
||
|
// delta from this value
|
||
|
//
|
||
|
|
||
|
if ( !ReadTargetMemory(TargetMemLog + NextLogEntry - 1, &LogEntry, sizeof( MEMLOG_ENTRY ))) {
|
||
|
|
||
|
dprintf("can't read current log entry (%p) from memory\n\n", TargetLogEntry);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
LastSysTime.QuadPart = LogEntry.SysTime.QuadPart;
|
||
|
FirstEntryTime.QuadPart = LogEntry.SysTime.QuadPart;
|
||
|
|
||
|
dprintf("MemLog @ %p, Log Entries = %d, Next Entry = %d (%p)\n\n",
|
||
|
TargetMemLog, LogEntries, NextLogEntry, TargetMemLog + NextLogEntry);
|
||
|
|
||
|
//
|
||
|
// depending on our starting entry, look through the log twice.
|
||
|
// next entry might have wrapped so first time we
|
||
|
// dump all the entries down to the base. Next time we start at the end and
|
||
|
// dump out the remaining entries
|
||
|
|
||
|
dprintf("First Last\n");
|
||
|
dprintf("Entry Entry Line Log\n");
|
||
|
dprintf("Delta Delta No Type Desc\n");
|
||
|
|
||
|
while ( Pass < 2 ) {
|
||
|
|
||
|
while ( NumEntries-- ) {
|
||
|
|
||
|
if (CheckControlC()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !ReadTargetMemory(TargetLogEntry, &LogEntry, sizeof( MEMLOG_ENTRY ))) {
|
||
|
|
||
|
dprintf("can't read log entry (%p) from memory\n\n", TargetLogEntry);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( LogEntry.Type == 0 )
|
||
|
break;
|
||
|
|
||
|
LastTimeDelta = ( LastSysTime.QuadPart - LogEntry.SysTime.QuadPart ) / 10000000.0;
|
||
|
FirstTimeDelta = ( FirstEntryTime.QuadPart - LogEntry.SysTime.QuadPart ) / 10000000.0;
|
||
|
|
||
|
if ( PrintTime ) {
|
||
|
dprintf("%8.3f %6.3f: (%4hu, 0x%02X) ", FirstTimeDelta, LastTimeDelta,
|
||
|
LogEntry.LineNo, LogEntry.Type );
|
||
|
}
|
||
|
|
||
|
PrintTime = TRUE;
|
||
|
|
||
|
switch ( LogEntry.Type ) {
|
||
|
case MemLogInitLog:
|
||
|
dprintf("Memory Log Init'ed\n");
|
||
|
break;
|
||
|
|
||
|
case MemLogInitHB:
|
||
|
dprintf("Heartbeats Init'ed\n");
|
||
|
break;
|
||
|
|
||
|
case MemLogHBStarted:
|
||
|
dprintf("START: Period = %u ms\n", LogEntry.Arg1);
|
||
|
break;
|
||
|
|
||
|
case MemLogHBStopped:
|
||
|
dprintf("STOPPED\n");
|
||
|
break;
|
||
|
|
||
|
case MemLogHBDpcRunning:
|
||
|
dprintf("DPC not removed. HeartBeatDpcRunning = %s\n",
|
||
|
TrueOrFalse( LogEntry.Arg1 ));
|
||
|
break;
|
||
|
|
||
|
case MemLogWaitForDpcFinish:
|
||
|
dprintf("DPC: Waiting to finish running\n");
|
||
|
break;
|
||
|
|
||
|
case MemLogMissedIfHB:
|
||
|
dprintf("HB MISSED on interface. Node = %u net = %u",
|
||
|
LogEntry.Arg1, LogEntry.Arg2);
|
||
|
PrintTime = FALSE;
|
||
|
break;
|
||
|
|
||
|
case MemLogMissedIfHB1:
|
||
|
dprintf(" (IF @ %p) MissedHBCount = %d\n", LogEntry.Arg1, LogEntry.Arg2);
|
||
|
break;
|
||
|
|
||
|
case MemLogFailingIf:
|
||
|
dprintf("IF FAILED. Node = %d, net = %d",
|
||
|
LogEntry.Arg1, LogEntry.Arg2);
|
||
|
PrintTime = FALSE;
|
||
|
break;
|
||
|
|
||
|
case MemLogFailingIf1:
|
||
|
dprintf(" (IF @ %p) IF State = %s\n", LogEntry.Arg1, InterfaceState[LogEntry.Arg2]);
|
||
|
break;
|
||
|
|
||
|
case MemLogSendHBWalkNode:
|
||
|
dprintf("Walking node %d to send HB. MMState = %s\n",
|
||
|
LogEntry.Arg1, NodeObjMemberState[LogEntry.Arg2]);
|
||
|
break;
|
||
|
|
||
|
case MemLogCheckHBWalkNode:
|
||
|
dprintf("Walking node %d to check for HB. MMState = %s.\n",
|
||
|
LogEntry.Arg1, NodeObjMemberState[LogEntry.Arg2]);
|
||
|
break;
|
||
|
|
||
|
case MemLogCheckHBNodeReachable:
|
||
|
dprintf("Node %d is currently %sreachable\n", LogEntry.Arg1,
|
||
|
(LogEntry.Arg2 ? "" : "NOT "));
|
||
|
break;
|
||
|
|
||
|
case MemLogCheckHBMissedHB:
|
||
|
dprintf("NODE MISSED HB on all IFs. MissedHBCount = %u MMState = %s\n",
|
||
|
LogEntry.Arg1, NodeObjMemberState[LogEntry.Arg2]);
|
||
|
break;
|
||
|
|
||
|
case MemLogSendingHB:
|
||
|
dprintf("Sending HB to Node %d on net %d\n", LogEntry.Arg1, LogEntry.Arg2);
|
||
|
break;
|
||
|
|
||
|
case MemLogNodeDown:
|
||
|
dprintf("NODE DOWN EVENT for node %d\n", LogEntry.Arg1);
|
||
|
break;
|
||
|
|
||
|
case MemLogSetDpcEvent:
|
||
|
dprintf("DPC: setting finished event\n");
|
||
|
break;
|
||
|
|
||
|
case MemLogNoNetID:
|
||
|
dprintf("BAD NET POINTER: Recv'd packet from node %d (%p)\n",
|
||
|
LogEntry.Arg1, LogEntry.Arg2);
|
||
|
break;
|
||
|
|
||
|
case MemLogOnlineIf:
|
||
|
dprintf("NODE %d ONLINE. IF State = %s\n", LogEntry.Arg1,
|
||
|
InterfaceState[LogEntry.Arg2]);
|
||
|
break;
|
||
|
|
||
|
case MemLogSeqAckMismatch:
|
||
|
dprintf("Recv'ed ack off with seq on IF %p. IF State = %s\n",
|
||
|
LogEntry.Arg1, InterfaceState[LogEntry.Arg2]);
|
||
|
break;
|
||
|
|
||
|
case MemLogNodeUp:
|
||
|
dprintf("NODE UP EVENT for node %d\n", LogEntry.Arg1);
|
||
|
break;
|
||
|
|
||
|
case MemLogReceivedPacket:
|
||
|
dprintf("Recv'ed HB from Node %d, net %d", LogEntry.Arg1, LogEntry.Arg2);
|
||
|
PrintTime = FALSE;
|
||
|
break;
|
||
|
|
||
|
case MemLogReceivedPacket1:
|
||
|
dprintf(" (S: %u A: %u)\n", LogEntry.Arg1, LogEntry.Arg2);
|
||
|
break;
|
||
|
|
||
|
case MemLogDpcTimeSkew:
|
||
|
dprintf("HB DPC fired %8.3f ms late\n", (double)(LogEntry.Arg1/10000.0));
|
||
|
break;
|
||
|
|
||
|
case MemLogHBPacketSend:
|
||
|
dprintf("%s Packet handed to CNP", CcmpMessageTypes[ LogEntry.Arg1 ]);
|
||
|
if ( LogEntry.Arg1 == CcmpHeartbeatMsgType )
|
||
|
dprintf(" (S:%u)", LogEntry.Arg2);
|
||
|
else if ( LogEntry.Arg1 == CcmpPoisonMsgType )
|
||
|
dprintf(" by %s", LogEntry.Arg2 == 1 ? "Heartbeat DPC" : "clussvc" );
|
||
|
dprintf("\n");
|
||
|
break;
|
||
|
|
||
|
case MemLogHBPacketSendComplete:
|
||
|
dprintf("%s Packet Send completed", CcmpMessageTypes[ LogEntry.Arg1 ]);
|
||
|
if ( LogEntry.Arg1 == CcmpHeartbeatMsgType )
|
||
|
dprintf(" (S:%u)", LogEntry.Arg2);
|
||
|
else if ( LogEntry.Arg1 == CcmpPoisonMsgType )
|
||
|
dprintf(" by %s", LogEntry.Arg2 == 1 ? "Heartbeat DPC" : "clussvc" );
|
||
|
dprintf("\n");
|
||
|
break;
|
||
|
|
||
|
case MemLogPoisonPktReceived:
|
||
|
dprintf("Poison Packet received from node %u\n", LogEntry.Arg1);
|
||
|
break;
|
||
|
|
||
|
case MemLogOuterscreen:
|
||
|
dprintf("Outerscreen changed to %04X\n",
|
||
|
((LogEntry.Arg1 & 0xFF ) << 8) | ((LogEntry.Arg1 >> 8 ) & 0xFF ));
|
||
|
break;
|
||
|
|
||
|
case MemLogNodeDownIssued:
|
||
|
dprintf("Node %u NodeDownIssued set to %s\n",
|
||
|
LogEntry.Arg1, TrueOrFalse( LogEntry.Arg2 ));
|
||
|
break;
|
||
|
|
||
|
case MemLogRegroupFinished:
|
||
|
dprintf("REGROUP FINISHED. New Epoch = %u\n", LogEntry.Arg1 );
|
||
|
break;
|
||
|
|
||
|
case MemLogInconsistentStates:
|
||
|
dprintf("INCONSISTENT STATES. STARTING NEW REGROUP. Node = %u, MMState = %s\n",
|
||
|
LogEntry.Arg1, NodeObjMemberState[ LogEntry.Arg2 ]);
|
||
|
break;
|
||
|
|
||
|
case MemLogOutOfSequence:
|
||
|
dprintf("Out Of Sequence Packet from Node = %u, SeqNo = %u\n",
|
||
|
LogEntry.Arg1, LogEntry.Arg2 );
|
||
|
break;
|
||
|
|
||
|
case MemLogInvalidSignature:
|
||
|
dprintf("Packet with bad Signature from Node = %u, type = %s\n",
|
||
|
LogEntry.Arg1, CcmpMessageTypes[ LogEntry.Arg2 ]);
|
||
|
break;
|
||
|
|
||
|
case MemLogSignatureSize:
|
||
|
dprintf("Invalid Signature buffer size from Node = %u, size = %u\n",
|
||
|
LogEntry.Arg1, LogEntry.Arg2 );
|
||
|
break;
|
||
|
|
||
|
case MemLogNoSecurityContext:
|
||
|
dprintf("No context to verify signature for Node = %u\n",
|
||
|
LogEntry.Arg1 );
|
||
|
break;
|
||
|
|
||
|
case MemLogPacketSendFailed:
|
||
|
dprintf("Packet not sent to Node %d, status = %08X\n",
|
||
|
LogEntry.Arg1, LogEntry.Arg2 );
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
dprintf(" unknown event, Arg1 = %p Arg2 = %p\n",
|
||
|
LogEntry.Arg1, LogEntry.Arg2);
|
||
|
}
|
||
|
|
||
|
LastSysTime.QuadPart = LogEntry.SysTime.QuadPart;
|
||
|
|
||
|
--TargetLogEntry;
|
||
|
}
|
||
|
|
||
|
if ( ++Pass < 2 ) {
|
||
|
|
||
|
NumEntries = LogEntries - NextLogEntry - 1;
|
||
|
TargetLogEntry = TargetMemLog + LogEntries - 1;
|
||
|
}
|
||
|
}
|
||
|
} // memlog
|
||
|
|
||
|
DECLARE_API( mlfind )
|
||
|
/*
|
||
|
* list the entry nums of the specified events in the memory log
|
||
|
*/
|
||
|
{
|
||
|
PMEMLOG_ENTRY TargetMemLog;
|
||
|
PMEMLOG_ENTRY TargetLogEntry;
|
||
|
MEMLOG_ENTRY LogEntry;
|
||
|
PULONG TargetLogEntries;
|
||
|
ULONG LogEntries;
|
||
|
PULONG TargetNextLogEntry;
|
||
|
ULONG NextLogEntry;
|
||
|
LONG NumEntries;
|
||
|
ULONG i;
|
||
|
DOUBLE FirstTimeDelta;
|
||
|
LARGE_INTEGER FirstEntryTime;
|
||
|
MEMLOG_TYPES LogType;
|
||
|
ULONG EntryDelta;
|
||
|
|
||
|
if ( *args == '\0' ) {
|
||
|
|
||
|
dprintf("Event type must be specified\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
LogType = (MEMLOG_TYPES)GetExpression( args );
|
||
|
|
||
|
//
|
||
|
// get address of MemLog and read its contents to get the real start
|
||
|
// of the log
|
||
|
//
|
||
|
|
||
|
TargetMemLog = (PMEMLOG_ENTRY)GetExpression( "clusnet!memlog" );
|
||
|
if ( !TargetMemLog ) {
|
||
|
|
||
|
dprintf( "Can't find symbol clusnet!memlog\n" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !ReadTargetMemory( TargetMemLog, &TargetMemLog, sizeof( PMEMLOG_ENTRY ))) {
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// repeat this process, getting the size of the log and the next entry index
|
||
|
//
|
||
|
|
||
|
TargetLogEntries = (PULONG)GetExpression( "clusnet!memlogentries" );
|
||
|
if ( !TargetLogEntries ) {
|
||
|
|
||
|
dprintf( "Can't find symbol clusnet!memlogentries\n" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !ReadTargetMemory( TargetLogEntries, &LogEntries, sizeof( ULONG ))) {
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
TargetNextLogEntry = (PULONG)GetExpression( "clusnet!memlognextlogentry" );
|
||
|
if ( !TargetNextLogEntry ) {
|
||
|
|
||
|
dprintf( "Can't find symbol clusnet!memlognextlogentry\n" );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !ReadTargetMemory( TargetNextLogEntry, &NextLogEntry, sizeof( ULONG ))) {
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
dprintf("MemLog @ %p, Log Entries = %d, Next Entry = %d (%p)\n",
|
||
|
TargetMemLog, LogEntries, NextLogEntry, TargetMemLog + NextLogEntry);
|
||
|
|
||
|
FirstEntryTime.QuadPart = 0;
|
||
|
|
||
|
//
|
||
|
// look through the log twice. next entry might have wrapped so first time we
|
||
|
// dump all the entries down to the base. Next time we start at the end and
|
||
|
// dump out the remaining entries
|
||
|
|
||
|
for ( i = 0; i < 2; ++i ) {
|
||
|
|
||
|
if ( i == 0 ) {
|
||
|
|
||
|
NumEntries = NextLogEntry;
|
||
|
TargetLogEntry = TargetMemLog + NumEntries;
|
||
|
} else {
|
||
|
|
||
|
NumEntries = LogEntries - NextLogEntry - 1;
|
||
|
TargetLogEntry = TargetMemLog + LogEntries;
|
||
|
}
|
||
|
|
||
|
while ( --TargetLogEntry, NumEntries-- ) {
|
||
|
|
||
|
if (CheckControlC()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( !ReadTargetMemory(TargetLogEntry, &LogEntry, sizeof( MEMLOG_ENTRY ))) {
|
||
|
|
||
|
dprintf("can't read log entry (%p) from memory\n\n", TargetLogEntry);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ( LogEntry.Type == 0 )
|
||
|
break;
|
||
|
|
||
|
if ( FirstEntryTime.QuadPart == 0 ) {
|
||
|
FirstEntryTime.QuadPart = LogEntry.SysTime.QuadPart;
|
||
|
}
|
||
|
|
||
|
if ( LogEntry.Type != LogType )
|
||
|
continue;
|
||
|
|
||
|
FirstTimeDelta = ( FirstEntryTime.QuadPart - LogEntry.SysTime.QuadPart ) / 10000000.0;
|
||
|
|
||
|
EntryDelta = (DWORD)(TargetLogEntry - TargetMemLog);
|
||
|
dprintf("%8.3f: (%5hu) Entry at %d (0x%X)\n", FirstTimeDelta, LogEntry.LineNo,
|
||
|
EntryDelta, EntryDelta);
|
||
|
}
|
||
|
}
|
||
|
} // mlfind
|
||
|
|
||
|
DECLARE_API( events )
|
||
|
|
||
|
//
|
||
|
// run down the event file handle list, dumping interesting info for each one
|
||
|
//
|
||
|
|
||
|
{
|
||
|
PCN_FSCONTEXT targetFSContext;
|
||
|
PCN_FSCONTEXT lastFSContext;
|
||
|
CN_FSCONTEXT localFSContext;
|
||
|
LIST_ENTRY localListHead;
|
||
|
PLIST_ENTRY targetListHead;
|
||
|
PCLUSNET_EVENT_ENTRY nextEvent;
|
||
|
CLUSNET_EVENT_ENTRY localEvent;
|
||
|
|
||
|
//
|
||
|
// get the event file handle list head
|
||
|
//
|
||
|
targetListHead = (PLIST_ENTRY)GetExpression( "clusnet!eventfilehandles" );
|
||
|
if ( !targetListHead ) {
|
||
|
|
||
|
dprintf("Can't convert clusnet!eventfilehandles symbol\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read CN FS context object listhead out of target's memory
|
||
|
//
|
||
|
if ( !ReadTargetMemory( targetListHead, &localListHead, sizeof(LIST_ENTRY))) {
|
||
|
dprintf("Can't get EventFileHandles data\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
targetFSContext = (PCN_FSCONTEXT)localListHead.Flink;
|
||
|
lastFSContext = (PCN_FSCONTEXT)targetListHead;
|
||
|
|
||
|
if ( targetFSContext == lastFSContext ) {
|
||
|
dprintf("No file objects in EventFileHandles\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
while ( targetFSContext != lastFSContext ) {
|
||
|
|
||
|
if (CheckControlC()) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read FS context struct out of target's memory
|
||
|
//
|
||
|
targetFSContext = CONTAINING_RECORD( targetFSContext, CN_FSCONTEXT, Linkage );
|
||
|
if ( !ReadTargetMemory( targetFSContext, &localFSContext, sizeof( CN_FSCONTEXT ))) {
|
||
|
dprintf("Problem reading FS context at %p\n", targetFSContext );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#if DBG
|
||
|
if ( localFSContext.Signature != CN_CONTROL_CHANNEL_SIG ) {
|
||
|
dprintf( "CN_FSCONTEXT @ %p has the wrong signature\n", targetFSContext );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
dprintf( "\nFSContext @ %p\n\n", targetFSContext );
|
||
|
dprintf( " Next FSContext @ %p\n", localFSContext.Linkage.Flink );
|
||
|
|
||
|
dprintf( " Event Mask %08X\n", localFSContext.EventMask );
|
||
|
dprintf( " Event IRP @ %p\n", localFSContext.EventIrp );
|
||
|
dprintf( " Event list @ %p %s\n", &targetFSContext->EventList,
|
||
|
ListInUse( &targetFSContext->EventList, &localFSContext.EventList ));
|
||
|
|
||
|
nextEvent = (PCLUSNET_EVENT_ENTRY)localFSContext.EventList.Flink;
|
||
|
while ( &targetFSContext->EventList != (PLIST_ENTRY)nextEvent ) {
|
||
|
|
||
|
if (CheckControlC()) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
nextEvent = CONTAINING_RECORD( nextEvent, CLUSNET_EVENT_ENTRY, Linkage );
|
||
|
if ( !ReadTargetMemory( nextEvent, &localEvent, sizeof( CLUSNET_EVENT_ENTRY ))) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
DumpEventData( nextEvent, &localEvent );
|
||
|
|
||
|
nextEvent = (PCLUSNET_EVENT_ENTRY)localEvent.Linkage.Flink;
|
||
|
}
|
||
|
|
||
|
targetFSContext = (PCN_FSCONTEXT)localFSContext.Linkage.Flink;
|
||
|
}
|
||
|
} // events
|
||
|
|
||
|
DWORD
|
||
|
GetEventTypeIndex(
|
||
|
CLUSNET_EVENT_TYPE EventType
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Description
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
DWORD index;
|
||
|
|
||
|
for ( index = 0; index < 10; ++index ) {
|
||
|
if ( ( 1 << index ) & EventType ) {
|
||
|
return index + 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
DumpEventData(
|
||
|
PCLUSNET_EVENT_ENTRY EventAddress,
|
||
|
PCLUSNET_EVENT_ENTRY EventEntry
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Description
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
dprintf(" Event @ %p\n", EventAddress );
|
||
|
dprintf(" Epoch %u\n", EventEntry->EventData.Epoch );
|
||
|
dprintf(" Type 0x%03X (%s)\n",
|
||
|
EventEntry->EventData.EventType,
|
||
|
EventTypes[ GetEventTypeIndex( EventEntry->EventData.EventType )]);
|
||
|
dprintf(" NodeId %u\n", EventEntry->EventData.NodeId );
|
||
|
dprintf(" NetId %u (%08X)\n", EventEntry->EventData.NetworkId,
|
||
|
EventEntry->EventData.NetworkId);
|
||
|
}
|
||
|
|
||
|
DECLARE_API( fsctxt )
|
||
|
/*
|
||
|
* dump the specified clusnet file object context struct
|
||
|
*/
|
||
|
{
|
||
|
PCN_FSCONTEXT targetFSContext;
|
||
|
CN_FSCONTEXT localFSContext;
|
||
|
|
||
|
if ( *args == '\0' ) {
|
||
|
dprintf("Address must be specified\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
targetFSContext = (PCN_FSCONTEXT)GetExpression( args );
|
||
|
if ( !targetFSContext ) {
|
||
|
dprintf("bad string conversion (%s) \n", args );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read network object struct out of target's memory
|
||
|
//
|
||
|
if ( !ReadTargetMemory( targetFSContext, &localFSContext, sizeof( CN_FSCONTEXT ))) {
|
||
|
dprintf("Problem reading FS Context obj at %p\n", targetFSContext );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
#if DBG
|
||
|
if ( localFSContext.Signature != CN_CONTROL_CHANNEL_SIG ) {
|
||
|
dprintf( "CN_FSCONTEXT @ %p has the wrong signature\n", targetFSContext );
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
dprintf( "\nFS Context @ %p\n\n", targetFSContext );
|
||
|
dprintf( " Next FS Ctxt on EventFileHandles @ %p\n", localFSContext.Linkage.Flink );
|
||
|
|
||
|
dprintf( " File Obj @ %p\n", localFSContext.FileObject );
|
||
|
dprintf( " RefCount = %d\n", localFSContext.ReferenceCount );
|
||
|
dprintf( " CancelIrps = %s\n", TrueOrFalse( localFSContext.CancelIrps ));
|
||
|
dprintf( " ShutdownOnClose = %s\n", TrueOrFalse( localFSContext.ShutdownOnClose ));
|
||
|
dprintf( " CleanupEvent @ %p\n", &targetFSContext->CleanupEvent );
|
||
|
dprintf( " Event List @ %p %s\n",
|
||
|
&targetFSContext->EventList,
|
||
|
ListInUse( &targetFSContext->EventList, &localFSContext.EventList ));
|
||
|
dprintf( " EventIrp @ %p\n", localFSContext.EventIrp );
|
||
|
dprintf( " EventMask = %08X\n", localFSContext.EventMask );
|
||
|
dprintf( " Krn Event Callback @ %p\n", localFSContext.KmodeEventCallback );
|
||
|
} // fsctxt
|
||
|
|
||
|
DECLARE_API( sendreq )
|
||
|
/*
|
||
|
* dump the specified CNP send request struct
|
||
|
*/
|
||
|
{
|
||
|
PCNP_SEND_REQUEST targetCnpSendReq;
|
||
|
CNP_SEND_REQUEST localCnpSendReq;
|
||
|
|
||
|
if ( *args == '\0' ) {
|
||
|
dprintf("Address must be specified\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
targetCnpSendReq = (PCNP_SEND_REQUEST)GetExpression( args );
|
||
|
if ( !targetCnpSendReq ) {
|
||
|
dprintf("bad string conversion (%s) \n", args );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read send request struct out of target's memory
|
||
|
//
|
||
|
if ( !ReadTargetMemory( targetCnpSendReq, &localCnpSendReq, sizeof( CNP_SEND_REQUEST ))) {
|
||
|
dprintf("Problem reading CNP send request at %p\n", targetCnpSendReq );
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
dprintf( "\nCNP Send Request @ %p\n\n", targetCnpSendReq );
|
||
|
dprintf( " CnResource @ %p\n", &targetCnpSendReq->CnResource );
|
||
|
dprintf( " HeaderMdl @ %p\n", localCnpSendReq.HeaderMdl );
|
||
|
dprintf( " CnpHeader @ %p\n", localCnpSendReq.CnpHeader );
|
||
|
dprintf( " UpperProtocolIrp @ %p\n", localCnpSendReq.UpperProtocolIrp );
|
||
|
dprintf( " UpperProtocolHeader @ %p\n", localCnpSendReq.UpperProtocolHeader );
|
||
|
dprintf( " UpperProtocolHeaderLength %d\n", localCnpSendReq.UpperProtocolHeaderLength );
|
||
|
dprintf( " UpperProtocolIrpMode %d\n", localCnpSendReq.UpperProtocolIrpMode );
|
||
|
dprintf( " UpperProtocolMdl @ %p\n", localCnpSendReq.UpperProtocolMdl );
|
||
|
dprintf( " UpperProtocolContext @ %p\n", localCnpSendReq.UpperProtocolContext );
|
||
|
dprintf( " CompletionRoutine @ %p\n", localCnpSendReq.CompletionRoutine );
|
||
|
dprintf( " Network @ %p\n", localCnpSendReq.Network );
|
||
|
dprintf( " DestAddress @ %p\n", localCnpSendReq.TdiSendDatagramInfo.RemoteAddress );
|
||
|
dprintf( " Multicast Group @ %p\n", localCnpSendReq.McastGroup );
|
||
|
|
||
|
} // fsctxt
|
||
|
|
||
|
#if 0
|
||
|
// from when regroup was in the kernel
|
||
|
DECLARE_API( rgpdump )
|
||
|
/*
|
||
|
* dump the regroup struct
|
||
|
*/
|
||
|
{
|
||
|
rgp_control_t **TargetRGPAddress;
|
||
|
rgp_control_t *TargetRGP;
|
||
|
rgp_control_t LocalRGP;
|
||
|
OS_specific_rgp_control_t *Local_rgpos; // points to local memory
|
||
|
OS_specific_rgp_control_t *Target_rgpos; // points to target memory
|
||
|
BOOL success;
|
||
|
LONG BytesRead;
|
||
|
|
||
|
//
|
||
|
// get address of RGP symbol
|
||
|
//
|
||
|
|
||
|
TargetRGPAddress = (rgp_control_t **)GetExpression( "Clusnet!rgp" );
|
||
|
|
||
|
if ( !TargetRGPAddress ) {
|
||
|
|
||
|
dprintf("Can't convert Clusnet!rgp symbol\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read address of RGP block
|
||
|
//
|
||
|
|
||
|
if ( !ReadTargetMemory((PVOID)TargetRGPAddress,
|
||
|
(PVOID)&TargetRGP,
|
||
|
sizeof(rgp_control_t *))) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read actual RGP block into our local buffer
|
||
|
//
|
||
|
|
||
|
if ( !ReadTargetMemory((PVOID)TargetRGP,
|
||
|
(PVOID)&LocalRGP,
|
||
|
sizeof( rgp_control_t ))) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Target_rgpos = &TargetRGP->OS_specific_control;
|
||
|
Local_rgpos = &LocalRGP.OS_specific_control;
|
||
|
|
||
|
dprintf( "RGP @ %p\n\n", TargetRGP );
|
||
|
|
||
|
dprintf( "info:\n" );
|
||
|
dprintf( " Version = %u\n", LocalRGP.rgpinfo.version );
|
||
|
dprintf( " Seq number = %u\n", LocalRGP.rgpinfo.seqnum );
|
||
|
dprintf( " Clock Period = %hu ms\n", LocalRGP.rgpinfo.a_tick );
|
||
|
dprintf( " I Am Alive ticks = %hu\n", LocalRGP.rgpinfo.iamalive_ticks );
|
||
|
dprintf( " Check ticks = %hu\n", LocalRGP.rgpinfo.check_ticks );
|
||
|
dprintf( " Min stage1 ticks = %hu\n", LocalRGP.rgpinfo.Min_Stage1_ticks );
|
||
|
DumpClusterMask( " Cluster mask = ", &LocalRGP.rgpinfo.cluster );
|
||
|
|
||
|
dprintf( " My node = %hu\n", LocalRGP.mynode );
|
||
|
dprintf( " Tiebreaker node = %hu\n", LocalRGP.tiebreaker );
|
||
|
dprintf( " Number of nodes in cluster = %u\n", LocalRGP.num_nodes );
|
||
|
dprintf( " Clock tick counter = %hu\n", LocalRGP.clock_ticks );
|
||
|
dprintf( " RGP counter = %hu\n", LocalRGP.rgpcounter );
|
||
|
dprintf( " Restart counter = %hu\n", LocalRGP.restartcount );
|
||
|
dprintf( " Pruning ticks = %hu\n", LocalRGP.pruning_ticks );
|
||
|
dprintf( " PFail State = %hu\n", LocalRGP.pfail_state );
|
||
|
|
||
|
dprintf( " Cautious Mode = %u\n", LocalRGP.cautiousmode );
|
||
|
dprintf( " Send Stage = %u\n", LocalRGP.sendstage );
|
||
|
dprintf( " Tie Breaker Selected = %u\n", LocalRGP.tiebreaker_selected );
|
||
|
dprintf( " Has Unreachable Nodes = %u\n", LocalRGP.has_unreachable_nodes );
|
||
|
|
||
|
DumpClusterMask( " Outer Screen = ", &LocalRGP.outerscreen );
|
||
|
DumpClusterMask( " Inner Screen = ", &LocalRGP.innerscreen );
|
||
|
DumpClusterMask( " Status Targets = ", &LocalRGP.status_targets );
|
||
|
DumpClusterMask( " Poison Targets = ", &LocalRGP.poison_targets );
|
||
|
DumpClusterMask( " Init Nodes = ", &LocalRGP.initnodes );
|
||
|
DumpClusterMask( " End Nodes = ", &LocalRGP.endnodes );
|
||
|
DumpClusterMask( " Unreachable Nodes = ", &LocalRGP.unreachable_nodes );
|
||
|
|
||
|
DumpRGPOSSpecific( &TargetRGP->OS_specific_control, &LocalRGP.OS_specific_control );
|
||
|
}
|
||
|
|
||
|
DECLARE_API( rgposdump )
|
||
|
/*
|
||
|
* dump just the OS specific portion of the regroup struct
|
||
|
*/
|
||
|
{
|
||
|
rgp_control_t **TargetRGPAddress;
|
||
|
rgp_control_t *TargetRGP;
|
||
|
rgp_control_t LocalRGP;
|
||
|
OS_specific_rgp_control_t *Local_rgpos; // points to local memory
|
||
|
OS_specific_rgp_control_t *Target_rgpos; // points to target memory
|
||
|
BOOL success;
|
||
|
LONG BytesRead;
|
||
|
|
||
|
//
|
||
|
// get address of RGP symbol
|
||
|
//
|
||
|
|
||
|
TargetRGPAddress = (rgp_control_t **)GetExpression( "Clusnet!rgp" );
|
||
|
|
||
|
if ( !TargetRGPAddress ) {
|
||
|
|
||
|
dprintf("Can't convert Clusnet!rgp symbol\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read address of RGP block
|
||
|
//
|
||
|
|
||
|
if ( !ReadTargetMemory((PVOID)TargetRGPAddress,
|
||
|
(PVOID)&TargetRGP,
|
||
|
sizeof(rgp_control_t *))) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read actual RGP block into our local buffer
|
||
|
//
|
||
|
|
||
|
if ( !ReadTargetMemory((PVOID)TargetRGP,
|
||
|
(PVOID)&LocalRGP,
|
||
|
sizeof( rgp_control_t ))) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Target_rgpos = &TargetRGP->OS_specific_control;
|
||
|
Local_rgpos = &LocalRGP.OS_specific_control;
|
||
|
|
||
|
dprintf( "RGP @ %p\n\n", TargetRGP );
|
||
|
|
||
|
DumpRGPOSSpecific( &TargetRGP->OS_specific_control, &LocalRGP.OS_specific_control );
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
DumpRGPOSSpecific(
|
||
|
OS_specific_rgp_control_t *Target_rgpos,
|
||
|
OS_specific_rgp_control_t *Local_rgpos
|
||
|
)
|
||
|
{
|
||
|
dprintf( "OS specific\n" );
|
||
|
|
||
|
dprintf( "RGP Counters:\n" );
|
||
|
DumpRGPCounters( &Local_rgpos->counter );
|
||
|
|
||
|
DumpClusterMask( " CPUUPMASK = ", &Local_rgpos->CPUUPMASK );
|
||
|
|
||
|
dprintf( " RgpLock @ %p\n", &Target_rgpos->RgpLock );
|
||
|
dprintf( " RGPTimer @ %p\n", &Target_rgpos->RGPTimer );
|
||
|
dprintf( " PeriodicCheckDPC @ %p\n", &Target_rgpos->PeriodicCheckDPC );
|
||
|
dprintf( " TimerDPCFinished @ %p\n", &Target_rgpos->TimerDPCFinished );
|
||
|
dprintf( " CallbackLock @ %p\n", &Target_rgpos->CallbackLock );
|
||
|
dprintf( " CallbackIRP @ %p\n", &Target_rgpos->CallbackIrp );
|
||
|
|
||
|
dprintf( " CallbackEvents @ %p %s\n", &Target_rgpos->CallbackEvents,
|
||
|
ListInUse( &Local_rgpos->CallbackEvents ));
|
||
|
|
||
|
dprintf( " SendMsgQLock @ %p\n", &Target_rgpos->SendMsgQLock );
|
||
|
dprintf( " SendMsgQDPC @ %p\n", &Target_rgpos->SendMsgQDPC );
|
||
|
dprintf( " SendMsgQ @ %p %s\n", &Target_rgpos->SendMsgQ,
|
||
|
ListInUse( &Local_rgpos->SendMsgQ ));
|
||
|
dprintf( " MsgShutdown: %s\n", TrueFalse( Local_rgpos->MsgShutdown ));
|
||
|
dprintf( " MsgDPCQueued: %s\n", TrueFalse( Local_rgpos->MsgDPCQueued ));
|
||
|
dprintf( " MsgDPCFinished @ %p\n", &Target_rgpos->MsgDPCFinished );
|
||
|
|
||
|
DumpClusterMask( " NeedsNodeDownCallback = ", &Local_rgpos->NeedsNodeDownCallback );
|
||
|
|
||
|
} // rgpdump
|
||
|
|
||
|
VOID
|
||
|
DumpRGPCounters(
|
||
|
rgp_counter_t *counters
|
||
|
)
|
||
|
{
|
||
|
dprintf( " QueuedIAmAlive = %u\n", counters->QueuedIAmAlive );
|
||
|
dprintf( " RcvdLocalIAmAlive = %u\n", counters->RcvdLocalIAmAlive );
|
||
|
dprintf( " RcvdRemoteIAmAlive = %u\n", counters->RcvdRemoteIAmAlive );
|
||
|
dprintf( " RcvdRegroup = %u\n", counters->RcvdRegroup );
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
DumpClusterMask(
|
||
|
PCHAR Title,
|
||
|
cluster_t *nodemask
|
||
|
)
|
||
|
{
|
||
|
UINT i;
|
||
|
|
||
|
dprintf( Title );
|
||
|
|
||
|
for ( i = 0; i < BYTES_IN_CLUSTER; ++i ) {
|
||
|
|
||
|
dprintf("%02X", (ULONG)(*nodemask[i]) );
|
||
|
}
|
||
|
dprintf("\n");
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
BOOL
|
||
|
ReadNodeTable(
|
||
|
PCNP_NODE **LocalNodeTable,
|
||
|
CL_NODE_ID *MaxNodeId,
|
||
|
CL_NODE_ID *MinNodeId
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Description
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PCNP_NODE TargetNodeTable;
|
||
|
CL_NODE_ID *TargetMaxNodeId;
|
||
|
CL_NODE_ID *TargetMinNodeId;
|
||
|
ULONG NumberOfValidNodes;
|
||
|
|
||
|
//
|
||
|
// get the address of the node table symbol on the target machine
|
||
|
//
|
||
|
|
||
|
TargetNodeTable = (PCNP_NODE)GetExpression( "clusnet!cnpnodetable" );
|
||
|
|
||
|
if ( !TargetNodeTable ) {
|
||
|
|
||
|
dprintf("Can't convert clusnet!cnpnnodetable symbol\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ( !ReadTargetMemory( TargetNodeTable, &TargetNodeTable, sizeof(PCNP_NODE))) {
|
||
|
|
||
|
dprintf("Can't get pointer to target node table\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ( TargetNodeTable == NULL ) {
|
||
|
|
||
|
dprintf("Node Table hasn't been allocated.\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// get lowest and highest valid node in the cluster
|
||
|
//
|
||
|
|
||
|
TargetMaxNodeId = (CL_NODE_ID *)GetExpression( "clusnet!cnmaxvalidnodeid" );
|
||
|
|
||
|
if ( !TargetMaxNodeId ) {
|
||
|
|
||
|
dprintf("Can't convert clusnet!cnmaxvalidnodeid symbol\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ( !ReadTargetMemory( TargetMaxNodeId, MaxNodeId, sizeof(CL_NODE_ID))) {
|
||
|
|
||
|
dprintf("Can't get Max Node ID data\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
TargetMinNodeId = (CL_NODE_ID *)GetExpression( "clusnet!cnminvalidnodeid" );
|
||
|
|
||
|
if ( !TargetMinNodeId ) {
|
||
|
|
||
|
dprintf("Can't convert clusnet!cnMinvalidnodeid symbol\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ( !ReadTargetMemory( TargetMinNodeId, MinNodeId, sizeof(CL_NODE_ID))) {
|
||
|
|
||
|
dprintf("Can't get Min Node ID data\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// allocate space for local copy of node table. The max and min are added
|
||
|
// together since Node Ids may not be zero based while the node table is
|
||
|
// zero based.
|
||
|
//
|
||
|
|
||
|
NumberOfValidNodes = *MaxNodeId + *MinNodeId;
|
||
|
*LocalNodeTable = malloc( NumberOfValidNodes * sizeof( PCNP_NODE ));
|
||
|
|
||
|
if ( !*LocalNodeTable ) {
|
||
|
|
||
|
dprintf("Can't get local mem for node table\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// read node table from target memory
|
||
|
//
|
||
|
|
||
|
if ( !ReadTargetMemory(TargetNodeTable,
|
||
|
*LocalNodeTable,
|
||
|
ClusterDefaultMaxNodes * sizeof(PCNP_NODE))) {
|
||
|
|
||
|
dprintf("Can't get local copy of node table data\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
ReadTargetMemory(
|
||
|
PVOID TargetAddress,
|
||
|
PVOID LocalBuffer,
|
||
|
ULONG BytesToRead
|
||
|
)
|
||
|
{
|
||
|
BOOL success;
|
||
|
ULONG BytesRead;
|
||
|
|
||
|
success = ReadMemory((ULONG_PTR)TargetAddress, LocalBuffer, BytesToRead, &BytesRead);
|
||
|
|
||
|
if (success) {
|
||
|
|
||
|
if (BytesRead != BytesToRead) {
|
||
|
|
||
|
dprintf("wrong byte count. expected=%d, read =%d\n", BytesToRead, BytesRead);
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
dprintf("Problem reading memory at %p for %u bytes\n",
|
||
|
TargetAddress, BytesToRead);
|
||
|
|
||
|
success = FALSE;
|
||
|
}
|
||
|
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
__inline PCHAR
|
||
|
ListInUse(
|
||
|
PLIST_ENTRY ListHead,
|
||
|
PLIST_ENTRY ListToCheck
|
||
|
)
|
||
|
{
|
||
|
return ListToCheck->Flink == ListHead ? "(empty)" : "";
|
||
|
}
|
||
|
|
||
|
__inline PCHAR
|
||
|
TrueFalse(
|
||
|
BOOLEAN Value
|
||
|
)
|
||
|
{
|
||
|
return Value ? "TRUE" : "FALSE";
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
DprintUnicodeString(
|
||
|
PUNICODE_STRING UnicodeString,
|
||
|
DWORD_PTR AddrString,
|
||
|
PCHAR Symbol OPTIONAL,
|
||
|
DWORD_PTR Displacement OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
ANSI_STRING AnsiString;
|
||
|
LPSTR StringData;
|
||
|
BOOL b;
|
||
|
|
||
|
StringData = malloc(UnicodeString->Length+sizeof(UNICODE_NULL));
|
||
|
if ( StringData == NULL ) {
|
||
|
dprintf("Unable to allocate memory for string buffer\n");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
b = ReadMemory((ULONG_PTR)UnicodeString->Buffer,
|
||
|
StringData,
|
||
|
UnicodeString->Length,
|
||
|
NULL);
|
||
|
if ( !b ) {
|
||
|
free(StringData);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
UnicodeString->Buffer = (PWSTR)StringData;
|
||
|
UnicodeString->MaximumLength = UnicodeString->Length+(USHORT)sizeof(UNICODE_NULL);
|
||
|
|
||
|
RtlUnicodeStringToAnsiString(&AnsiString,UnicodeString,TRUE);
|
||
|
free(StringData);
|
||
|
|
||
|
if (Symbol == NULL || Displacement == (DWORD_PTR) NULL) {
|
||
|
dprintf("String(%d,%d) at %p: %s\n",
|
||
|
UnicodeString->Length,
|
||
|
UnicodeString->MaximumLength,
|
||
|
AddrString,
|
||
|
AnsiString.Buffer
|
||
|
);
|
||
|
}
|
||
|
else {
|
||
|
dprintf("String(%d,%d) %s+%p at %p: %s\n",
|
||
|
UnicodeString->Length,
|
||
|
UnicodeString->MaximumLength,
|
||
|
Symbol,
|
||
|
Displacement,
|
||
|
AddrString,
|
||
|
AnsiString.Buffer
|
||
|
);
|
||
|
}
|
||
|
|
||
|
RtlFreeAnsiString(&AnsiString);
|
||
|
|
||
|
} // DprintUnicodeString
|
||
|
|
||
|
DECLARE_API( help )
|
||
|
{
|
||
|
dprintf("Clusnet kd extensions\n\n");
|
||
|
dprintf("netobj [address] - dump a network object\n");
|
||
|
dprintf("nodeobj [node ID] - dump a node object\n");
|
||
|
dprintf("nodeifs <node ID> - dump the interface objects of a node object\n");
|
||
|
dprintf("currif <node ID> - dump the current interface object of a node object\n");
|
||
|
dprintf("memlog [starting entry number] - dump the in-memory log\n");
|
||
|
dprintf("mlfind <entry type> - find all specified entry types in the memory log\n");
|
||
|
dprintf("events - dump the FS context structs on the EventFileHandles list\n");
|
||
|
dprintf("fsctxt <address> - dump a CN_FSCONTEXT struct\n");
|
||
|
dprintf("sendreq <address> - dump a CNP send request struct\n");
|
||
|
}
|