|
|
/*++
Copyright (c) 1998-1999 Microsoft Corporation
Module Name:
main.cpp
Abstract:
User space log viewer
Author:
Rajesh Sundaram (1st Aug, 1998)
Revision History:
--*/
#define UNICODE
#define INITGUID
#include "precomp.h"
void ClNotifyHandler( HANDLE ClRegCtx, HANDLE ClIfcCtx, ULONG Event, HANDLE SubCode, ULONG BufSize, PVOID Buffer ) { }
static PCHAR SendRecvActions[] = { "", "ENTER", "NO_RESOURCES", "LOW_RESOURCES", "INDICATING", "RETURNED", "NOT_OURS", "OURS", "RETURNING", "TRANSFERRING", "NOT READY"};
#define FILE 1
#define CONFIG 2
#define LEVEL 4
#define MASK 8
VOID ParseOidRecord( CHAR * DataStart, ULONG *Size ) { static PCHAR OIDActions[] = { "", "MpSetInformation", "MpQueryInformation", "SetRequestComplete", "QueryRequestComplete" }; TRACE_RECORD_OID *record = (TRACE_RECORD_OID *)DataStart;
*Size = sizeof(TRACE_RECORD_OID);
if(record->Now.QuadPart){
printf("[%I64u]: OID: %5s:%9s:(%d:%d):%p:%08X:%08X\n", record->Now.QuadPart, OIDActions[record->Action], record->Local == TRUE?"Local":"Non Local", record->PTState, record->MPState, record->Adapter, record->Oid, record->Status); } else { printf("OID: %5s:%9s:(%d:%d):%p:%08X:%08X\n", OIDActions[record->Action], record->Local == TRUE?"Local":"Non Local", record->PTState, record->MPState, record->Adapter, record->Oid, record->Status); } }
VOID ParseStringRecord( CHAR * DataStart, ULONG *Size ) { TRACE_RECORD_STRING *record = (TRACE_RECORD_STRING *) DataStart;
*Size = sizeof(TRACE_RECORD_STRING);
if(record->Now.QuadPart){ printf("%I64u:%s", record->Now.QuadPart, record->StringStart); } else{ printf("%s", record->StringStart); }
}
VOID ParseSchedRecord( CHAR * DataStart, ULONG *Size ) { TRACE_RECORD_SCHED * record = (TRACE_RECORD_SCHED *)DataStart; static PCHAR SchedModules[] = { "NOP", "TB CONFORMER", "SHAPER", "DRR SEQ", "CBQ"};
static PCHAR SchedActions[] = { "NOP", "ENQUEUE", "DEQUEUE", "CONFORMANCE", "DISCARD"};
LARGE_INTEGER ArrivalTime, ConformanceTime;
ConformanceTime.QuadPart = record->ConformanceTime; ArrivalTime.QuadPart = record->ArrivalTime;
printf("SCHED:%s:VC %p:%p:%u:%s:%d:%I64u:[%u,%u]:%I64u:[%u,%u]:%u\n", SchedModules[record->SchedulerComponent], record->VC, record->Packet, record->PacketLength, SchedActions[record->Action], record->Priority, ArrivalTime.QuadPart, ArrivalTime.HighPart, ArrivalTime.LowPart, ConformanceTime.QuadPart, ConformanceTime.HighPart, ConformanceTime.LowPart, record->PacketsInComponent);
*Size = sizeof(TRACE_RECORD_SCHED); }
VOID ParseRecvRecord( CHAR * DataStart, PULONG size ) {
static PCHAR RecvEvents[] = { "", "CL_RECV_PACKET", "MP_RETURN_PACKET", "CL_RECV_INDICATION", "CL_RECV_COMPLETE", "MP_TRANSFER_DATA", "CL_TRANSFER_COMPLETE"};
TRACE_RECORD_RECV *record = (TRACE_RECORD_RECV*)DataStart;
*size = sizeof(TRACE_RECORD_RECV);
printf("%I64u:Adapter %p:%s:%s:%p:%p \n", record->Now.QuadPart, record->Adapter, RecvEvents[record->Event], SendRecvActions[record->Action], record->Packet1, record->Packet2); }
VOID ParseSendRecord( CHAR * DataStart, PULONG Size ) { TRACE_RECORD_SEND* record = (TRACE_RECORD_SEND *)DataStart; static PCHAR SendEvents[] = { "", "MP_SEND", "MP_CO_SEND", "DUP_PACKET", "DROP_PACKET", "CL_SEND_COMPLETE" };
*Size = sizeof(TRACE_RECORD_SEND);
printf("%I64u:Adapter %p:%s:%s:%p:%p:%p\n", record->Now.QuadPart, record->Adapter, SendEvents[record->Event], SendRecvActions[record->Action], record->Vc, record->Packet1, record->Packet2);
}
VOID ParseBuffer( CHAR * DataStart, ULONG Size ) { CHAR * recordEnd; LONG records; BOOLEAN success; CHAR hold; ULONG bytesread; ULONG TotalValidBytesRead = 0;
records = 0;
while(TRUE) { hold = *(DataStart+4);
switch(hold) {
case RECORD_TSTRING:
ParseStringRecord(DataStart, &bytesread); break;
case RECORD_OID: ParseOidRecord(DataStart, &bytesread); break;
case RECORD_SCHED:
ParseSchedRecord(DataStart, &bytesread); break;
case RECORD_RECV: ParseRecvRecord(DataStart, &bytesread); break;
case RECORD_SEND: ParseSendRecord(DataStart, &bytesread); break; default:
printf("Unrecognized record type!\n");
//
// we cannot proceed - we don't know how much to advance it by.
//
return; }
records++;
TotalValidBytesRead += bytesread;
if(TotalValidBytesRead >= Size){ printf("\nDONE:Completed parsing trace buffer. %d records found.\n", records); break; }
DataStart += bytesread; } }
BOOLEAN TcDone( HANDLE ClientHandle, HANDLE InterfaceHandle )
{ ULONG Status;
Status = TcCloseInterface(InterfaceHandle);
if(!NT_SUCCESS(Status)) { printf("TcCloseInterface failed : Status = %d \n", Status); }
Status = TcDeregisterClient(ClientHandle);
if(!NT_SUCCESS(Status)) { printf("TcDeregisterClient failed : Status = %d \n", Status); }
return TRUE;
}
BOOLEAN TcInit( PHANDLE ClientHandle, PHANDLE InterfaceHandle ) { TCI_CLIENT_FUNC_LIST ClientHandlerList; ULONG Size = 100 * sizeof(TC_IFC_DESCRIPTOR); PTC_IFC_DESCRIPTOR InterfaceBuffer; ULONG x, Status;
memset( &ClientHandlerList, 0, sizeof(ClientHandlerList) ); ClientHandlerList.ClNotifyHandler = ClNotifyHandler;
InterfaceBuffer = (PTC_IFC_DESCRIPTOR) malloc(Size); if(!InterfaceBuffer) return FALSE;
//
// Register the TC client.
//
Status = TcRegisterClient(CURRENT_TCI_VERSION, NULL, &ClientHandlerList, ClientHandle);
if(!NT_SUCCESS(Status)) { printf("Cannot register as TC client \n"); free(InterfaceBuffer); return FALSE; }
//
// Enumerate interfaces.
//
Status = TcEnumerateInterfaces( *ClientHandle, &Size, InterfaceBuffer);
if(ERROR_INSUFFICIENT_BUFFER == Status) { free(InterfaceBuffer);
InterfaceBuffer = (PTC_IFC_DESCRIPTOR) malloc(Size);
if ( !InterfaceBuffer ) { TcDeregisterClient(*ClientHandle);
printf("Unable to allocate memory to call TcEnumerateInterfaces\n");
return FALSE; } Status = TcEnumerateInterfaces( *ClientHandle, &Size, InterfaceBuffer);
if(!NT_SUCCESS(Status)) { TcDeregisterClient(*ClientHandle);
free(InterfaceBuffer);
printf("TcEnumerateInterfaces failed with error %d \n", Status);
return FALSE; } } else { if(!NT_SUCCESS(Status)) { TcDeregisterClient(*ClientHandle);
free(InterfaceBuffer);
printf("TcEnumerateInterfaces failed with error %d \n", Status);
return FALSE; } }
if(Size) { Status = TcOpenInterface( InterfaceBuffer->pInterfaceName, *ClientHandle, NULL, InterfaceHandle);
if(!NT_SUCCESS(Status)) { //
printf("TcOpenInterface failed for interface %ws with Status %d \n", InterfaceBuffer->pInterfaceName, Status);
TcDeregisterClient(*ClientHandle);
free(InterfaceBuffer);
return FALSE; }
} else { printf("No Traffic Interfaces \n"); return FALSE; }
return TRUE; }
int __cdecl main(int argc, char **argv) {
HANDLE ClientHandle, InterfaceHandle; BOOLEAN flags = 0; ULONG mask, level; ULONG DataSize; CHAR *Buffer;
if (argc < 2) goto usage;
argv++; argc--;
while( argc>0 && argv[0][0] == '-' ) {
switch (argv[0][1]) {
case 'F': case 'f': flags |= FILE; break;
case 'c': case 'C': flags |= CONFIG; break;
case 'l': case 'L': if(sscanf(&argv[0][2], "%d", &level) == 1) { if((ULONG)level > 10) { goto usage; } flags |= LEVEL; } else { goto usage; } break;
case 'm': case 'M': if(argv[0][2]!='0' && argv[0][3]!='x') { goto usage; }
if(sscanf(&argv[0][2], "%x", &mask) == 1) { flags |= MASK; } else goto usage;
break;
default: goto usage; } argv++; argc--; }
if((flags & CONFIG) && (flags & (FILE|LEVEL|MASK))) { goto usage; }
if(TcInit(&ClientHandle, &InterfaceHandle)) { ULONG size = sizeof(ULONG); ULONG chk; if(TcQueryInterface(InterfaceHandle, (LPGUID)&GUID_QOS_LOG_MASK, FALSE, &size, &chk) != STATUS_SUCCESS) { printf("Does not work on free bits \n"); }
if(flags & LEVEL) {
TcSetInterface(InterfaceHandle, (LPGUID)&GUID_QOS_LOG_LEVEL, sizeof(level), &level); }
if(flags & MASK) { printf("Setting Mask to 0x%x \n", mask); TcSetInterface(InterfaceHandle, (LPGUID)&GUID_QOS_LOG_MASK, sizeof(mask), &mask); }
if(flags & CONFIG) { TcQueryInterface(InterfaceHandle, (LPGUID)&GUID_QOS_LOG_MASK, FALSE, &size, &mask);
TcQueryInterface(InterfaceHandle, (LPGUID)&GUID_QOS_LOG_LEVEL, FALSE, &size, &level);
printf("Masks supported\n"); printf(" DBG_INIT 0x00000001 \n"); printf(" DBG_MINIPORT 0x00000002 \n"); printf(" DBG_PROTOCOL 0x00000004 \n"); printf(" DBG_SEND 0x00000008 \n"); printf(" DBG_RECEIVE 0x00000010 \n"); printf(" DBG_IO 0x00000020 \n"); printf(" DBG_MEMORY 0x00000040 \n"); printf(" DBG_CM 0x00000080 \n"); printf(" DBG_REFCNTS 0x00000100 \n"); printf(" DBG_VC 0x00000200 \n"); printf(" DBG_GPC_QOS 0x00000400 \n"); printf(" DBG_WAN 0x00000800 \n"); printf(" DBG_STATE 0x00001000 \n"); printf(" DBG_ROUTINEOIDS 0x00002000 \n"); printf(" DBG_SCHED_TBC 0x00004000 \n"); printf(" DBG_SCHED_SHAPER 0x00008000 \n"); printf(" DBG_SCHED_DRR 0x00010000 \n"); printf(" DBG_WMI 0x00020000 \n");
printf("\nLevels supported\n"); printf(" DBG_DEATH 1\n"); printf(" DBG_CRITICAL_ERROR 2\n"); printf(" DBG_FAILURE 4\n"); printf(" DBG_INFO 6\n"); printf(" DBG_TRACE 8\n"); printf(" DBG_VERBOSE 10\n"); printf("\n Current Level is %d, Current Mask is 0x%x \n", level, mask); }
if(flags & FILE) { ULONG Status;
Status = TcQueryInterface(InterfaceHandle, (LPGUID)&GUID_QOS_LOG_THRESHOLD, FALSE, &size, &DataSize);
DataSize *= 2;
if(NT_SUCCESS(Status)) { if(DataSize != 0) { Buffer = (PCHAR) malloc(DataSize);
Status = TcQueryInterface(InterfaceHandle, (LPGUID)&GUID_QOS_LOG_DATA, FALSE, &DataSize, Buffer); if(NT_SUCCESS(Status)) { ParseBuffer(Buffer, DataSize); } else { printf("Query for the data buffer failed with status %d \n", Status); }
free(Buffer); } else { printf("No Data in buffer. \n"); } } else { printf("Failed to read the sched bytes unread \n"); } }
TcDone(InterfaceHandle, ClientHandle); }
return 0;
usage: printf("Usage %s [-f | -c | -m<0xmask> | -l<level> ] \n", argv[0]); printf(" -f : dump the tt log on screen. \n"); printf(" -c : Print the current value of the mask and level \n"); printf(" -m<0xvalue> : Set the mask to this value \n"); printf(" -l<value> : Set the level to this value (0-10) \n");
return 1;
}
|