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.

828 lines
17 KiB

  1. /*++
  2. Copyright (c) 1995-1998 Microsoft Corporation
  3. Module Name:
  4. lkuptst.c
  5. Abstract:
  6. Contains routines for testing an implementation
  7. for the generalized best matching prefix lookup
  8. interface.
  9. Author:
  10. Chaitanya Kodeboyina (chaitk) 30-Jun-1998
  11. Revision History:
  12. --*/
  13. #include "lkuptst.h"
  14. //
  15. // Main
  16. //
  17. #if LOOKUP_TESTING
  18. __cdecl
  19. main (
  20. IN UINT argc,
  21. IN CHAR *argv[]
  22. )
  23. {
  24. CHAR RouteDatabase[MAX_FNAME_LEN];
  25. FILE *FilePtr;
  26. UINT NumRoutes;
  27. Route InputRoutes[MAXROUTES];
  28. UINT i;
  29. DWORD Status;
  30. // Initialize input arguments
  31. RouteDatabase[0] = '\0';
  32. for ( i = 1; i < argc - 1; i++ )
  33. {
  34. if ( ( argv[i][0] == '-' ) || ( argv[i][0] == '/' ) )
  35. {
  36. if (argv[i][2])
  37. {
  38. Usage();
  39. }
  40. switch (toupper(argv[i][1]))
  41. {
  42. case 'D':
  43. strcpy(RouteDatabase, argv[++i]);
  44. continue;
  45. default:
  46. Usage();
  47. }
  48. }
  49. else
  50. {
  51. Usage();
  52. }
  53. }
  54. if (RouteDatabase[0] == '\0')
  55. {
  56. Usage();
  57. }
  58. if ((FilePtr = fopen(RouteDatabase, "r")) == NULL)
  59. {
  60. Fatal("Failed open route database with status = %08x\n",
  61. ERROR_OPENING_DATABASE);
  62. }
  63. // Print("InputRoutes = %p\n", InputRoutes);
  64. NumRoutes = ReadRoutesFromFile(FilePtr, MAXROUTES, InputRoutes);
  65. // Print("InputRoutes = %p\n", InputRoutes);
  66. fclose(FilePtr);
  67. Status = WorkOnLookup(InputRoutes,
  68. NumRoutes);
  69. return 0;
  70. }
  71. #endif
  72. DWORD
  73. WorkOnLookup (
  74. IN Route *InputRoutes,
  75. IN UINT NumRoutes
  76. )
  77. {
  78. Route *OutputRoute;
  79. HANDLE Table;
  80. UINT Status;
  81. UINT i, j;
  82. PLOOKUP_LINKAGE linkage;
  83. #if PROF
  84. HANDLE Thread;
  85. UINT Priority;
  86. PROFVARS;
  87. Thread = GetCurrentThread();
  88. Priority = GetThreadPriority(Thread);
  89. SetThreadPriority(Thread, THREAD_PRIORITY_TIME_CRITICAL);
  90. #endif
  91. // Create and Initialize a new lookup table
  92. #if PROF
  93. INITPROF;
  94. STARTPROF;
  95. #endif
  96. Status = CreateTable(NUMBYTES, &Table);
  97. #if PROF
  98. STOPPROF;
  99. ADDPROF;
  100. PRINTPROF;
  101. Print("Time for an Initialize Table : %.3f ns\n\n", duration);
  102. #endif
  103. if (!SUCCESS(Status))
  104. {
  105. Fatal("Initialize Failed With Status: %08x\n", Status);
  106. }
  107. CheckTable(Table);
  108. // Compute the total time for inserting all routes
  109. #if PROF
  110. INITPROF;
  111. STARTPROF;
  112. #endif
  113. // Add each route one by one to the table
  114. for (i = 0; i < NumRoutes ; i++)
  115. {
  116. // Print("Inserting Route %6d\n", i + 1);
  117. Status = InsertIntoTable(Table,
  118. LEN(&InputRoutes[i]),
  119. (PUCHAR) &DEST(&InputRoutes[i]),
  120. NULL,
  121. &InputRoutes[i].backptr);
  122. // CheckTable(Table);
  123. if (!SUCCESS(Status))
  124. {
  125. Print("Inserting item %08x/%08x, but got an error",
  126. DEST(&InputRoutes[i]),
  127. MASK(&InputRoutes[i]));
  128. Fatal("Insert Failed With Status: %08x\n", Status);
  129. }
  130. }
  131. #if PROF
  132. STOPPROF;
  133. ADDPROF;
  134. #endif
  135. // Subtract from above the for - loop overhead
  136. #if PROF
  137. STARTPROF;
  138. #endif
  139. for (i = 0; i < NumRoutes ; i++) { ; }
  140. #if PROF
  141. STOPPROF;
  142. SUBPROF;
  143. Print("Avg Time for an Insert Table : %.3f ns for %d routes\n\n",
  144. duration/i, i);
  145. #endif
  146. CheckTable(Table);
  147. #ifdef _DBG_
  148. DumpTable(Table, VERBOSE);
  149. #endif
  150. #ifdef _DBG_
  151. EnumerateAllRoutes(Table);
  152. #endif
  153. #ifdef _DBG_
  154. ReadAddrAndGetRoute(Table);
  155. #endif
  156. // Compute the total time for searching all routes
  157. #if PROF
  158. INITPROF;
  159. STARTPROF;
  160. #endif
  161. for (i = 0; i < NumRoutes ; i++)
  162. {
  163. Status = SearchInTable(Table,
  164. LEN(&InputRoutes[i]),
  165. (PUCHAR) &DEST(&InputRoutes[i]),
  166. NULL,
  167. &linkage);
  168. if (!SUCCESS(Status))
  169. {
  170. Print("Searching for %08x/%08x, but got an error\n",
  171. DEST(&InputRoutes[i]),
  172. MASK(&InputRoutes[i]));
  173. Fatal("Search Failed With Status: %08x\n", Status);
  174. }
  175. OutputRoute = CONTAINING_RECORD(linkage, Route, backptr);
  176. if (OutputRoute != &InputRoutes[i])
  177. {
  178. if ((DEST(OutputRoute) != DEST(&InputRoutes[i])) ||
  179. (MASK(OutputRoute) != MASK(&InputRoutes[i])))
  180. {
  181. Print("Searching for %08x/%08x, but got %08x/%08x\n",
  182. DEST(&InputRoutes[i]),
  183. MASK(&InputRoutes[i]),
  184. DEST(OutputRoute),
  185. MASK(OutputRoute));
  186. }
  187. else
  188. {
  189. // Print("Possible Duplicate Insertion @S\n");
  190. }
  191. }
  192. }
  193. #if PROF
  194. STOPPROF;
  195. ADDPROF;
  196. #endif
  197. // Subtract from above the for - loop overhead
  198. #if PROF
  199. STARTPROF;
  200. #endif
  201. for (i = 0; i < NumRoutes ; i++) { ; }
  202. #if PROF
  203. STOPPROF;
  204. SUBPROF;
  205. Print("Avg Time for a Search Table : %.3f ns for %d routes\n\n",
  206. duration/i, i);
  207. #endif
  208. // Compute the total time for searching all prefixes
  209. #if PROF
  210. INITPROF;
  211. STARTPROF;
  212. #endif
  213. for (i = 0; i < NumRoutes ; i++)
  214. {
  215. Status = BestMatchInTable(Table,
  216. (PUCHAR) &DEST(&InputRoutes[i]),
  217. &linkage);
  218. OutputRoute = CONTAINING_RECORD(linkage, Route, backptr);
  219. if (!SUCCESS(Status))
  220. {
  221. Print("Searching for %08x, but got an error\n",
  222. DEST(&InputRoutes[i]));
  223. Fatal("Search Failed With Status: %08x\n", Status);
  224. }
  225. if (OutputRoute != &InputRoutes[i])
  226. {
  227. if (DEST(OutputRoute) != DEST(&InputRoutes[i]))
  228. {
  229. Print("Searching for %08x, but got %08x/%08x\n",
  230. DEST(&InputRoutes[i]),
  231. DEST(OutputRoute),
  232. MASK(OutputRoute));
  233. }
  234. else
  235. {
  236. // Print("Possible Duplicate Insertion @S\n");
  237. }
  238. }
  239. }
  240. #if PROF
  241. STOPPROF;
  242. ADDPROF;
  243. #endif
  244. // Subtract from above the for - loop overhead
  245. #if PROF
  246. STARTPROF;
  247. #endif
  248. for (i = 0; i < NumRoutes ; i++) { ; }
  249. #if PROF
  250. STOPPROF;
  251. SUBPROF;
  252. Print("Avg Time for Prefix in Table : %.3f ns for %d routes\n\n",
  253. duration/i, i);
  254. #endif
  255. // Compute the total time for deleting all routes
  256. #if PROF
  257. INITPROF;
  258. STARTPROF;
  259. #endif
  260. // Del each route one by one to the table
  261. for (i = 0; i < NumRoutes ; i++)
  262. {
  263. // Print("Deleting Route %6d\n", i + 1);
  264. j = NumRoutes - 1 - i;
  265. Status = DeleteFromTable(Table,
  266. LEN(&InputRoutes[j]),
  267. (PUCHAR) &DEST(&InputRoutes[j]),
  268. NULL,
  269. &linkage);
  270. OutputRoute = CONTAINING_RECORD(linkage, Route, backptr);
  271. // CheckTable(Table);
  272. if (!SUCCESS(Status))
  273. {
  274. /*
  275. Print("Deleting route %08x/%08x, but got an error\n",
  276. DEST(&InputRoutes[j]),
  277. MASK(&InputRoutes[j]));
  278. Error("Delete Failed With Status: %08x\n", Status);
  279. */
  280. }
  281. else
  282. if (OutputRoute != &InputRoutes[j])
  283. {
  284. if ((DEST(OutputRoute) != DEST(&InputRoutes[j])) ||
  285. (MASK(OutputRoute) != MASK(&InputRoutes[j])))
  286. {
  287. Print("Deleting route %08x/%08x, but got %08x/%08x\n",
  288. DEST(&InputRoutes[j]),
  289. MASK(&InputRoutes[j]),
  290. DEST(OutputRoute),
  291. MASK(OutputRoute));
  292. }
  293. else
  294. {
  295. // Print("Possible Duplicate Insertion @D\n");
  296. }
  297. }
  298. }
  299. #if PROF
  300. STOPPROF;
  301. ADDPROF;
  302. #endif
  303. // Subtract from above the for - loop overhead
  304. #if PROF
  305. STARTPROF;
  306. #endif
  307. for (i = 0; i < NumRoutes ; i++) { j = NumRoutes - 1 - i; }
  308. #if PROF
  309. STOPPROF;
  310. SUBPROF;
  311. Print("Avg Time for a Delete Table : %.3f ns for %d routes\n\n",
  312. duration/i, i);
  313. #endif
  314. CheckTable(Table);
  315. #ifdef _DBG_
  316. DumpTable(Table, VERBOSE);
  317. #endif
  318. #ifdef _DBG_
  319. EnumerateAllRoutes(Table);
  320. #endif
  321. #ifdef _DBG_
  322. ReadAddrAndGetRoute(Table);
  323. #endif
  324. // Destory the lookup table
  325. #if PROF
  326. INITPROF;
  327. STARTPROF;
  328. #endif
  329. Status = DestroyTable(Table);
  330. #if PROF
  331. STOPPROF;
  332. ADDPROF;
  333. PRINTPROF;
  334. Print("Time for a Destroy Table : %.3f ns\n\n", duration);
  335. #endif
  336. if (!SUCCESS(Status))
  337. {
  338. Fatal("Destroy Failed With Status: %08x\n", Status);
  339. }
  340. #if PROF
  341. SetThreadPriority(Thread, Priority);
  342. #endif
  343. return 0;
  344. }
  345. // Search Testing
  346. VOID
  347. ReadAddrAndGetRoute (
  348. IN PVOID Table
  349. )
  350. {
  351. LOOKUP_CONTEXT Context;
  352. FILE *FilePtr;
  353. Route *BestRoute;
  354. UINT Status;
  355. ULONG Addr;
  356. PLOOKUP_LINKAGE linkage;
  357. FilePtr = fopen("con", "r");
  358. do
  359. {
  360. Print("Enter the IP Addr to search for: ");
  361. ReadIPAddr(FilePtr, &Addr);
  362. Print("Searching route table for Addr = ");
  363. PrintIPAddr(&Addr);
  364. Print("\n");
  365. Status = SearchInTable(Table,
  366. ADDRSIZE,
  367. (PUCHAR) &Addr,
  368. &Context,
  369. &linkage);
  370. BestRoute = CONTAINING_RECORD(linkage, Route, backptr);
  371. if (!SUCCESS(Status))
  372. {
  373. Fatal("Search Failed With Status: %08x\n", Status);
  374. }
  375. Print("The BMP for this addr: \n");
  376. PrintRoute(BestRoute);
  377. }
  378. while (Addr != 0);
  379. fclose(FilePtr);
  380. }
  381. // Enumerate Testing
  382. VOID
  383. EnumerateAllRoutes (
  384. IN PVOID Table
  385. )
  386. {
  387. LOOKUP_CONTEXT Context;
  388. USHORT NumBits;
  389. UCHAR KeyBits[NUMBYTES];
  390. UINT Status;
  391. PLOOKUP_LINKAGE Linkage;
  392. UINT NumDests = 1;
  393. PVOID DestItems[1];
  394. Print("\n---------------- ENUMERATION BEGIN ---------------------\n");
  395. ZeroMemory(&Context, sizeof(LOOKUP_CONTEXT));
  396. ZeroMemory(&KeyBits, NUMBYTES);
  397. NumBits = 0;
  398. do
  399. {
  400. Status = EnumOverTable(Table,
  401. &NumBits,
  402. KeyBits,
  403. &Context,
  404. 0,
  405. NULL,
  406. &NumDests,
  407. &Linkage);
  408. DestItems[0] = CONTAINING_RECORD(Linkage, Route, backptr);
  409. if (SUCCESS(Status))
  410. {
  411. PrintRoute((Route *)DestItems[0]);
  412. }
  413. }
  414. while (SUCCESS(Status));
  415. // If it is just an EOF, print last route
  416. if (Status == ERROR_NO_MORE_ITEMS)
  417. {
  418. PrintRoute((Route *)DestItems[0]);
  419. }
  420. Print("---------------- ENUMERATION END ---------------------\n\n");
  421. }
  422. UINT ReadRoutesFromFile(
  423. IN FILE *FilePtr,
  424. IN UINT NumRoutes,
  425. OUT Route *RouteTable
  426. )
  427. {
  428. UINT i;
  429. for (i = 0; (!feof(FilePtr)) && (i < NumRoutes) ; )
  430. {
  431. // Print("RouteTable = %p\n", RouteTable);
  432. if (ReadRoute(FilePtr, &RouteTable[i]) != EOF)
  433. {
  434. if (RouteTable[i].len)
  435. {
  436. ;
  437. }
  438. else
  439. {
  440. ;
  441. }
  442. i++;
  443. }
  444. // Print("RouteTable = %p\n", RouteTable);
  445. }
  446. if (i >= NumRoutes)
  447. {
  448. Error("Number of routes in file exceeds the limit\n",
  449. ERROR_MAX_NUM_ROUTES);
  450. }
  451. Print("Total number of routes = %lu\n\n", i);
  452. return i;
  453. }
  454. INT
  455. ReadRoute (
  456. IN FILE *FilePtr,
  457. OUT Route *route
  458. )
  459. {
  460. UCHAR currLine[MAX_LINE_LEN];
  461. UCHAR *addrBytes;
  462. UCHAR *maskBytes;
  463. UINT byteRead;
  464. UINT byteTemp;
  465. INT numConv;
  466. UINT i;
  467. // Zero the input addr, mask, and len
  468. ClearMemory(route, sizeof(Route));
  469. // Input format: A1.A2..An/M1.M2..Mn!
  470. // Read destination IP address
  471. addrBytes = (UCHAR *) &DEST(route);
  472. // Read the address A1.A2..An
  473. for (i = 0; i < NUMBYTES; i++)
  474. {
  475. numConv = fscanf(FilePtr, "%d.", &byteRead);
  476. // Last Line in file
  477. if (numConv == EOF)
  478. {
  479. return EOF;
  480. }
  481. // End of Address
  482. if (numConv == 0)
  483. {
  484. break;
  485. }
  486. addrBytes[i] = (UCHAR) byteRead;
  487. }
  488. // Read the '/' seperator
  489. fscanf(FilePtr, "%c", &byteRead);
  490. // Read destination IP mask
  491. maskBytes = (UCHAR *) &MASK(route);
  492. // Read the mask M1.M2..Mn
  493. for (i = 0; i < NUMBYTES; i++)
  494. {
  495. numConv = fscanf(FilePtr, "%d.", &byteRead);
  496. // Incomplete line
  497. if (numConv == EOF)
  498. {
  499. return EOF;
  500. }
  501. // End of Mask
  502. if (numConv == 0)
  503. {
  504. break;
  505. }
  506. maskBytes[i] = (UCHAR) byteRead;
  507. // Assume route mask is contiguous
  508. byteTemp = byteRead;
  509. while (byteTemp)
  510. {
  511. byteTemp &= byteTemp - 1;
  512. LEN(route)++;
  513. }
  514. }
  515. // Read the ',' seperator
  516. fscanf(FilePtr, "%c", &byteRead);
  517. // Read next hop information
  518. addrBytes = (UCHAR *) &NHOP(route);
  519. // Read the next hop N1.N2..Nn
  520. for (i = 0; i < NUMBYTES; i++)
  521. {
  522. numConv = fscanf(FilePtr, "%d.", &byteRead);
  523. // Incomplete line
  524. if (numConv == EOF)
  525. {
  526. return EOF;
  527. }
  528. // End of Address
  529. if (numConv == 0)
  530. {
  531. break;
  532. }
  533. addrBytes[i] = (UCHAR) byteRead;
  534. }
  535. // Read the ',' seperator
  536. fscanf(FilePtr, "%c", &byteRead);
  537. // Read interface addr/index
  538. addrBytes = (UCHAR *) &IF(route);
  539. // Read the interface I1.I2..In
  540. for (i = 0; i < NUMBYTES; i++)
  541. {
  542. numConv = fscanf(FilePtr, "%d.", &byteRead);
  543. // Incomplete line
  544. if (numConv == EOF)
  545. {
  546. return EOF;
  547. }
  548. // End of Address
  549. if (numConv == 0)
  550. {
  551. break;
  552. }
  553. addrBytes[i] = (UCHAR) byteRead;
  554. }
  555. // Read the ',' seperator
  556. fscanf(FilePtr, "%c", &byteRead);
  557. // Read the route's metric
  558. fscanf(FilePtr, "%lu", &METRIC(route));
  559. // Read the rest of the line
  560. fscanf(FilePtr, "%s\n", currLine);
  561. #ifdef _DBG_
  562. PrintRoute(route);
  563. #endif
  564. return TRUE;
  565. }
  566. VOID
  567. PrintRoute (
  568. IN Route *route
  569. )
  570. {
  571. if (NULL_ROUTE(route))
  572. {
  573. Print("NULL route\n");
  574. }
  575. else
  576. {
  577. Print("Route: Len = %2d", LEN(route));
  578. Print(", Addr = ");
  579. PrintIPAddr(&DEST(route));
  580. Print(", NHop = ");
  581. PrintIPAddr(&NHOP(route));
  582. Print(", IF = %08x", PtrToInt(IF(route)));
  583. Print(", Metric = %3lu\n", METRIC(route));
  584. }
  585. }
  586. INT
  587. ReadIPAddr (
  588. IN FILE *FilePtr,
  589. OUT ULONG *addr
  590. )
  591. {
  592. UCHAR *addrBytes;
  593. UINT byteRead;
  594. INT numConv;
  595. UINT i;
  596. // Initialize the addr variable to 0
  597. *addr = 0;
  598. // Cast it for easy byte access
  599. addrBytes = (UCHAR *)addr;
  600. // Read the address A1.A2..An
  601. for (i = 0; i < NUMBYTES; i++)
  602. {
  603. numConv = fscanf(FilePtr, "%d.", &byteRead);
  604. // Last Line in file
  605. if (numConv == EOF)
  606. {
  607. return EOF;
  608. }
  609. // End of Address
  610. if (numConv == 0)
  611. {
  612. break;
  613. }
  614. addrBytes[i] = (UCHAR) byteRead;
  615. }
  616. return 0;
  617. }
  618. VOID
  619. PrintIPAddr (
  620. IN ULONG *addr
  621. )
  622. {
  623. UCHAR *addrBytes = (UCHAR *) addr;
  624. UINT i;
  625. if (addrBytes)
  626. {
  627. for (i = 0; i < NUMBYTES; i++)
  628. {
  629. Print("%3d.", addrBytes[i]);
  630. }
  631. Print(" ");
  632. }
  633. else
  634. {
  635. Print("NULL Addr ");
  636. }
  637. }
  638. VOID
  639. Usage (
  640. VOID
  641. )
  642. {
  643. Fatal("Failed Operation with status = %08x"
  644. "\n"
  645. "Tests and measures the IP route lookup mechanism \n"
  646. "\n"
  647. "Usage: \n"
  648. "\t lkuptst \t [ -d routing_database ] \n"
  649. "\n"
  650. "Options:\n"
  651. " -d routing_database \t Name of the route database\n"
  652. "\n",
  653. ERROR_WRONG_CMDUSAGE);
  654. }