Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

629 lines
15 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. main.cpp
  5. Abstract:
  6. User space log viewer
  7. Author:
  8. Rajesh Sundaram (1st Aug, 1998)
  9. Revision History:
  10. --*/
  11. #define UNICODE
  12. #define INITGUID
  13. #include "precomp.h"
  14. void ClNotifyHandler( HANDLE ClRegCtx, HANDLE ClIfcCtx, ULONG Event, HANDLE SubCode, ULONG BufSize, PVOID Buffer )
  15. {
  16. }
  17. static PCHAR SendRecvActions[] = {
  18. "",
  19. "ENTER",
  20. "NO_RESOURCES",
  21. "LOW_RESOURCES",
  22. "INDICATING",
  23. "RETURNED",
  24. "NOT_OURS",
  25. "OURS",
  26. "RETURNING",
  27. "TRANSFERRING",
  28. "NOT READY"};
  29. #define FILE 1
  30. #define CONFIG 2
  31. #define LEVEL 4
  32. #define MASK 8
  33. VOID
  34. ParseOidRecord(
  35. CHAR * DataStart,
  36. ULONG *Size
  37. )
  38. {
  39. static PCHAR OIDActions[] =
  40. {
  41. "",
  42. "MpSetInformation",
  43. "MpQueryInformation",
  44. "SetRequestComplete",
  45. "QueryRequestComplete"
  46. };
  47. TRACE_RECORD_OID *record = (TRACE_RECORD_OID *)DataStart;
  48. *Size = sizeof(TRACE_RECORD_OID);
  49. if(record->Now.QuadPart){
  50. printf("[%I64u]: OID: %5s:%9s:(%d:%d):%p:%08X:%08X\n",
  51. record->Now.QuadPart,
  52. OIDActions[record->Action],
  53. record->Local == TRUE?"Local":"Non Local",
  54. record->PTState,
  55. record->MPState,
  56. record->Adapter,
  57. record->Oid,
  58. record->Status);
  59. }
  60. else {
  61. printf("OID: %5s:%9s:(%d:%d):%p:%08X:%08X\n",
  62. OIDActions[record->Action],
  63. record->Local == TRUE?"Local":"Non Local",
  64. record->PTState,
  65. record->MPState,
  66. record->Adapter,
  67. record->Oid,
  68. record->Status);
  69. }
  70. }
  71. VOID
  72. ParseStringRecord(
  73. CHAR * DataStart,
  74. ULONG *Size
  75. )
  76. {
  77. TRACE_RECORD_STRING *record = (TRACE_RECORD_STRING *) DataStart;
  78. *Size = sizeof(TRACE_RECORD_STRING);
  79. if(record->Now.QuadPart){
  80. printf("%I64u:%s",
  81. record->Now.QuadPart,
  82. record->StringStart);
  83. }
  84. else{
  85. printf("%s",
  86. record->StringStart);
  87. }
  88. }
  89. VOID
  90. ParseSchedRecord(
  91. CHAR * DataStart,
  92. ULONG *Size
  93. )
  94. {
  95. TRACE_RECORD_SCHED * record = (TRACE_RECORD_SCHED *)DataStart;
  96. static PCHAR SchedModules[] = {
  97. "NOP",
  98. "TB CONFORMER",
  99. "SHAPER",
  100. "DRR SEQ",
  101. "CBQ"};
  102. static PCHAR SchedActions[] = {
  103. "NOP",
  104. "ENQUEUE",
  105. "DEQUEUE",
  106. "CONFORMANCE",
  107. "DISCARD"};
  108. LARGE_INTEGER ArrivalTime, ConformanceTime;
  109. ConformanceTime.QuadPart = record->ConformanceTime;
  110. ArrivalTime.QuadPart = record->ArrivalTime;
  111. printf("SCHED:%s:VC %p:%p:%u:%s:%d:%I64u:[%u,%u]:%I64u:[%u,%u]:%u\n",
  112. SchedModules[record->SchedulerComponent],
  113. record->VC,
  114. record->Packet,
  115. record->PacketLength,
  116. SchedActions[record->Action],
  117. record->Priority,
  118. ArrivalTime.QuadPart,
  119. ArrivalTime.HighPart,
  120. ArrivalTime.LowPart,
  121. ConformanceTime.QuadPart,
  122. ConformanceTime.HighPart,
  123. ConformanceTime.LowPart,
  124. record->PacketsInComponent);
  125. *Size = sizeof(TRACE_RECORD_SCHED);
  126. }
  127. VOID
  128. ParseRecvRecord(
  129. CHAR * DataStart,
  130. PULONG size
  131. )
  132. {
  133. static PCHAR RecvEvents[] = {
  134. "",
  135. "CL_RECV_PACKET",
  136. "MP_RETURN_PACKET",
  137. "CL_RECV_INDICATION",
  138. "CL_RECV_COMPLETE",
  139. "MP_TRANSFER_DATA",
  140. "CL_TRANSFER_COMPLETE"};
  141. TRACE_RECORD_RECV *record = (TRACE_RECORD_RECV*)DataStart;
  142. *size = sizeof(TRACE_RECORD_RECV);
  143. printf("%I64u:Adapter %p:%s:%s:%p:%p \n",
  144. record->Now.QuadPart,
  145. record->Adapter,
  146. RecvEvents[record->Event],
  147. SendRecvActions[record->Action],
  148. record->Packet1,
  149. record->Packet2);
  150. }
  151. VOID
  152. ParseSendRecord(
  153. CHAR * DataStart,
  154. PULONG Size
  155. )
  156. {
  157. TRACE_RECORD_SEND* record = (TRACE_RECORD_SEND *)DataStart;
  158. static PCHAR SendEvents[] = {
  159. "",
  160. "MP_SEND",
  161. "MP_CO_SEND",
  162. "DUP_PACKET",
  163. "DROP_PACKET",
  164. "CL_SEND_COMPLETE" };
  165. *Size = sizeof(TRACE_RECORD_SEND);
  166. printf("%I64u:Adapter %p:%s:%s:%p:%p:%p\n",
  167. record->Now.QuadPart,
  168. record->Adapter,
  169. SendEvents[record->Event],
  170. SendRecvActions[record->Action],
  171. record->Vc,
  172. record->Packet1,
  173. record->Packet2);
  174. }
  175. VOID
  176. ParseBuffer(
  177. CHAR * DataStart,
  178. ULONG Size
  179. )
  180. {
  181. CHAR * recordEnd;
  182. LONG records;
  183. BOOLEAN success;
  184. CHAR hold;
  185. ULONG bytesread;
  186. ULONG TotalValidBytesRead = 0;
  187. records = 0;
  188. while(TRUE)
  189. {
  190. hold = *(DataStart+4);
  191. switch(hold)
  192. {
  193. case RECORD_TSTRING:
  194. ParseStringRecord(DataStart, &bytesread);
  195. break;
  196. case RECORD_OID:
  197. ParseOidRecord(DataStart, &bytesread);
  198. break;
  199. case RECORD_SCHED:
  200. ParseSchedRecord(DataStart, &bytesread);
  201. break;
  202. case RECORD_RECV:
  203. ParseRecvRecord(DataStart, &bytesread);
  204. break;
  205. case RECORD_SEND:
  206. ParseSendRecord(DataStart, &bytesread);
  207. break;
  208. default:
  209. printf("Unrecognized record type!\n");
  210. //
  211. // we cannot proceed - we don't know how much to advance it by.
  212. //
  213. return;
  214. }
  215. records++;
  216. TotalValidBytesRead += bytesread;
  217. if(TotalValidBytesRead >= Size){
  218. printf("\nDONE:Completed parsing trace buffer. %d records found.\n", records);
  219. break;
  220. }
  221. DataStart += bytesread;
  222. }
  223. }
  224. BOOLEAN TcDone(
  225. HANDLE ClientHandle,
  226. HANDLE InterfaceHandle
  227. )
  228. {
  229. ULONG Status;
  230. Status = TcCloseInterface(InterfaceHandle);
  231. if(!NT_SUCCESS(Status))
  232. {
  233. printf("TcCloseInterface failed : Status = %d \n", Status);
  234. }
  235. Status = TcDeregisterClient(ClientHandle);
  236. if(!NT_SUCCESS(Status))
  237. {
  238. printf("TcDeregisterClient failed : Status = %d \n", Status);
  239. }
  240. return TRUE;
  241. }
  242. BOOLEAN TcInit(
  243. PHANDLE ClientHandle,
  244. PHANDLE InterfaceHandle
  245. )
  246. {
  247. TCI_CLIENT_FUNC_LIST ClientHandlerList;
  248. ULONG Size = 100 * sizeof(TC_IFC_DESCRIPTOR);
  249. PTC_IFC_DESCRIPTOR InterfaceBuffer;
  250. ULONG x, Status;
  251. memset( &ClientHandlerList, 0, sizeof(ClientHandlerList) );
  252. ClientHandlerList.ClNotifyHandler = ClNotifyHandler;
  253. InterfaceBuffer = (PTC_IFC_DESCRIPTOR) malloc(Size);
  254. if(!InterfaceBuffer)
  255. return FALSE;
  256. //
  257. // Register the TC client.
  258. //
  259. Status = TcRegisterClient(CURRENT_TCI_VERSION,
  260. NULL,
  261. &ClientHandlerList,
  262. ClientHandle);
  263. if(!NT_SUCCESS(Status))
  264. {
  265. printf("Cannot register as TC client \n");
  266. free(InterfaceBuffer);
  267. return FALSE;
  268. }
  269. //
  270. // Enumerate interfaces.
  271. //
  272. Status = TcEnumerateInterfaces(
  273. *ClientHandle,
  274. &Size,
  275. InterfaceBuffer);
  276. if(ERROR_INSUFFICIENT_BUFFER == Status)
  277. {
  278. free(InterfaceBuffer);
  279. InterfaceBuffer = (PTC_IFC_DESCRIPTOR) malloc(Size);
  280. if ( !InterfaceBuffer )
  281. {
  282. TcDeregisterClient(*ClientHandle);
  283. printf("Unable to allocate memory to call TcEnumerateInterfaces\n");
  284. return FALSE;
  285. }
  286. Status = TcEnumerateInterfaces(
  287. *ClientHandle,
  288. &Size,
  289. InterfaceBuffer);
  290. if(!NT_SUCCESS(Status))
  291. {
  292. TcDeregisterClient(*ClientHandle);
  293. free(InterfaceBuffer);
  294. printf("TcEnumerateInterfaces failed with error %d \n", Status);
  295. return FALSE;
  296. }
  297. }
  298. else
  299. {
  300. if(!NT_SUCCESS(Status))
  301. {
  302. TcDeregisterClient(*ClientHandle);
  303. free(InterfaceBuffer);
  304. printf("TcEnumerateInterfaces failed with error %d \n", Status);
  305. return FALSE;
  306. }
  307. }
  308. if(Size)
  309. {
  310. Status = TcOpenInterface(
  311. InterfaceBuffer->pInterfaceName,
  312. *ClientHandle,
  313. NULL,
  314. InterfaceHandle);
  315. if(!NT_SUCCESS(Status))
  316. {
  317. //
  318. printf("TcOpenInterface failed for interface %ws with Status %d \n",
  319. InterfaceBuffer->pInterfaceName, Status);
  320. TcDeregisterClient(*ClientHandle);
  321. free(InterfaceBuffer);
  322. return FALSE;
  323. }
  324. }
  325. else
  326. {
  327. printf("No Traffic Interfaces \n");
  328. return FALSE;
  329. }
  330. return TRUE;
  331. }
  332. int __cdecl main(int argc, char **argv)
  333. {
  334. HANDLE ClientHandle, InterfaceHandle;
  335. BOOLEAN flags = 0;
  336. ULONG mask, level;
  337. ULONG DataSize;
  338. CHAR *Buffer;
  339. if (argc < 2) goto usage;
  340. argv++; argc--;
  341. while( argc>0 && argv[0][0] == '-' ) {
  342. switch (argv[0][1])
  343. {
  344. case 'F':
  345. case 'f':
  346. flags |= FILE;
  347. break;
  348. case 'c':
  349. case 'C':
  350. flags |= CONFIG;
  351. break;
  352. case 'l':
  353. case 'L':
  354. if(sscanf(&argv[0][2], "%d", &level) == 1)
  355. {
  356. if((ULONG)level > 10)
  357. {
  358. goto usage;
  359. }
  360. flags |= LEVEL;
  361. }
  362. else
  363. {
  364. goto usage;
  365. }
  366. break;
  367. case 'm':
  368. case 'M':
  369. if(argv[0][2]!='0' && argv[0][3]!='x')
  370. {
  371. goto usage;
  372. }
  373. if(sscanf(&argv[0][2], "%x", &mask) == 1)
  374. {
  375. flags |= MASK;
  376. }
  377. else goto usage;
  378. break;
  379. default:
  380. goto usage;
  381. }
  382. argv++; argc--;
  383. }
  384. if((flags & CONFIG) && (flags & (FILE|LEVEL|MASK)))
  385. {
  386. goto usage;
  387. }
  388. if(TcInit(&ClientHandle, &InterfaceHandle))
  389. {
  390. ULONG size = sizeof(ULONG);
  391. ULONG chk;
  392. if(TcQueryInterface(InterfaceHandle,
  393. (LPGUID)&GUID_QOS_LOG_MASK,
  394. FALSE,
  395. &size,
  396. &chk) != STATUS_SUCCESS)
  397. {
  398. printf("Does not work on free bits \n");
  399. }
  400. if(flags & LEVEL)
  401. {
  402. TcSetInterface(InterfaceHandle,
  403. (LPGUID)&GUID_QOS_LOG_LEVEL,
  404. sizeof(level),
  405. &level);
  406. }
  407. if(flags & MASK)
  408. {
  409. printf("Setting Mask to 0x%x \n", mask);
  410. TcSetInterface(InterfaceHandle,
  411. (LPGUID)&GUID_QOS_LOG_MASK,
  412. sizeof(mask),
  413. &mask);
  414. }
  415. if(flags & CONFIG)
  416. {
  417. TcQueryInterface(InterfaceHandle,
  418. (LPGUID)&GUID_QOS_LOG_MASK,
  419. FALSE,
  420. &size,
  421. &mask);
  422. TcQueryInterface(InterfaceHandle,
  423. (LPGUID)&GUID_QOS_LOG_LEVEL,
  424. FALSE,
  425. &size,
  426. &level);
  427. printf("Masks supported\n");
  428. printf(" DBG_INIT 0x00000001 \n");
  429. printf(" DBG_MINIPORT 0x00000002 \n");
  430. printf(" DBG_PROTOCOL 0x00000004 \n");
  431. printf(" DBG_SEND 0x00000008 \n");
  432. printf(" DBG_RECEIVE 0x00000010 \n");
  433. printf(" DBG_IO 0x00000020 \n");
  434. printf(" DBG_MEMORY 0x00000040 \n");
  435. printf(" DBG_CM 0x00000080 \n");
  436. printf(" DBG_REFCNTS 0x00000100 \n");
  437. printf(" DBG_VC 0x00000200 \n");
  438. printf(" DBG_GPC_QOS 0x00000400 \n");
  439. printf(" DBG_WAN 0x00000800 \n");
  440. printf(" DBG_STATE 0x00001000 \n");
  441. printf(" DBG_ROUTINEOIDS 0x00002000 \n");
  442. printf(" DBG_SCHED_TBC 0x00004000 \n");
  443. printf(" DBG_SCHED_SHAPER 0x00008000 \n");
  444. printf(" DBG_SCHED_DRR 0x00010000 \n");
  445. printf(" DBG_WMI 0x00020000 \n");
  446. printf("\nLevels supported\n");
  447. printf(" DBG_DEATH 1\n");
  448. printf(" DBG_CRITICAL_ERROR 2\n");
  449. printf(" DBG_FAILURE 4\n");
  450. printf(" DBG_INFO 6\n");
  451. printf(" DBG_TRACE 8\n");
  452. printf(" DBG_VERBOSE 10\n");
  453. printf("\n Current Level is %d, Current Mask is 0x%x \n", level, mask);
  454. }
  455. if(flags & FILE)
  456. {
  457. ULONG Status;
  458. Status = TcQueryInterface(InterfaceHandle,
  459. (LPGUID)&GUID_QOS_LOG_THRESHOLD,
  460. FALSE,
  461. &size,
  462. &DataSize);
  463. DataSize *= 2;
  464. if(NT_SUCCESS(Status))
  465. {
  466. if(DataSize != 0)
  467. {
  468. Buffer = (PCHAR) malloc(DataSize);
  469. Status = TcQueryInterface(InterfaceHandle,
  470. (LPGUID)&GUID_QOS_LOG_DATA,
  471. FALSE,
  472. &DataSize,
  473. Buffer);
  474. if(NT_SUCCESS(Status))
  475. {
  476. ParseBuffer(Buffer, DataSize);
  477. }
  478. else
  479. {
  480. printf("Query for the data buffer failed with status %d \n", Status);
  481. }
  482. free(Buffer);
  483. }
  484. else
  485. {
  486. printf("No Data in buffer. \n");
  487. }
  488. }
  489. else
  490. {
  491. printf("Failed to read the sched bytes unread \n");
  492. }
  493. }
  494. TcDone(InterfaceHandle, ClientHandle);
  495. }
  496. return 0;
  497. usage:
  498. printf("Usage %s [-f | -c | -m<0xmask> | -l<level> ] \n", argv[0]);
  499. printf(" -f : dump the tt log on screen. \n");
  500. printf(" -c : Print the current value of the mask and level \n");
  501. printf(" -m<0xvalue> : Set the mask to this value \n");
  502. printf(" -l<value> : Set the level to this value (0-10) \n");
  503. return 1;
  504. }