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.

869 lines
23 KiB

  1. /*++
  2. Copyright (c) 1997-2000 Microsoft Corporation
  3. Module Name:
  4. ftrie.c
  5. Abstract:
  6. This module contains routines that manipulate
  7. an F-trie data stucture, that forms the fast
  8. path in a fast IP route lookup implementation.
  9. Author:
  10. Chaitanya Kodeboyina (chaitk) 26-Nov-1997
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #include "ftrie.h"
  15. UINT
  16. CALLCONV
  17. InitFTrie(IN FTrie * pFTrie,
  18. IN ULONG levels,
  19. IN ULONG maxMemory)
  20. /*++
  21. Routine Description:
  22. Initialises an F-trie. This should be done prior to
  23. any other trie operations.
  24. Arguments:
  25. pFTrie - Pointer to the trie to be initialized
  26. levels - Bitmap [ 32 bits ] of expanded levels
  27. maxMemory - Limit on memory taken by the F-Trie
  28. For example, levels = 0xF0F0F0F0 [8,16,24,32 bits]
  29. means -> all prefixes are expanded to these levels
  30. and only these trie levels have any dests at all
  31. Num of Levels + 2 memory accesses are needed in the
  32. worst case to get to the dest corresponding to a
  33. prefix - Num of Levels + 1 accesses including the
  34. zero level access, and 1 access to read the dest.
  35. Return Value:
  36. TRIE_SUCCESS or ERROR_TRIE_*
  37. --*/
  38. {
  39. UINT prevLevel;
  40. UINT currLevel;
  41. UINT nBytes, i;
  42. TRY_BLOCK
  43. {
  44. if (levels == 0) {
  45. Error("NewFTrie: No levels specified", ERROR_TRIE_BAD_PARAM);
  46. }
  47. // Zero all the memory for the trie header
  48. RtlZeroMemory(pFTrie, sizeof(FTrie));
  49. // Set a limit on the memory for trie/nodes
  50. pFTrie->availMemory = maxMemory;
  51. // Initialize list of trienodes allocated
  52. InitializeListHead(&pFTrie->listofNodes);
  53. // Initialize root node with a NULL dest
  54. pFTrie->trieRoot = StoreDestPtr(NULL);
  55. // Initialize the number of bits in each level
  56. nBytes = (MAXLEVEL + 1) * sizeof(UINT);
  57. AllocMemory2(pFTrie->bitsInLevel,
  58. nBytes,
  59. pFTrie->availMemory);
  60. RtlZeroMemory(pFTrie->bitsInLevel, nBytes);
  61. // Get the number of index bits at each level
  62. prevLevel = 0;
  63. i = 0;
  64. for (currLevel = 1; currLevel <= MAXLEVEL; currLevel++) {
  65. if (levels & 1) {
  66. pFTrie->bitsInLevel[i++] = currLevel - prevLevel;
  67. prevLevel = currLevel;
  68. }
  69. levels >>= 1;
  70. }
  71. pFTrie->numLevels = i;
  72. // Make sure that the last level is MAXLEVEL
  73. if (pFTrie->bitsInLevel[i] = MAXLEVEL - prevLevel) {
  74. pFTrie->numLevels++;
  75. }
  76. #if DBG
  77. Print("Num of levels: %d\n", pFTrie->numLevels);
  78. Print("Bits In Level:\n");
  79. for (i = 0; i < pFTrie->numLevels; i++) {
  80. Print("\t%d", pFTrie->bitsInLevel[i]);
  81. if (i % 8 == 7)
  82. Print("\n");
  83. }
  84. Print("\n\n");
  85. #endif
  86. // Allocate and Zero all the statistics variables
  87. nBytes = (MAXLEVEL + 1) * sizeof(UINT);
  88. AllocMemory2(pFTrie->numDestsInOrigLevel,
  89. nBytes,
  90. pFTrie->availMemory);
  91. RtlZeroMemory(pFTrie->numDestsInOrigLevel, nBytes);
  92. nBytes = pFTrie->numLevels * sizeof(UINT);
  93. AllocMemory2(pFTrie->numNodesInExpnLevel,
  94. nBytes,
  95. pFTrie->availMemory);
  96. RtlZeroMemory(pFTrie->numNodesInExpnLevel, nBytes);
  97. nBytes = pFTrie->numLevels * sizeof(UINT);
  98. AllocMemory2(pFTrie->numDestsInExpnLevel,
  99. nBytes,
  100. pFTrie->availMemory);
  101. RtlZeroMemory(pFTrie->numDestsInExpnLevel, nBytes);
  102. return TRIE_SUCCESS;
  103. }
  104. ERR_BLOCK
  105. {
  106. // Not enough resources to create an FTrie
  107. CleanupFTrie(pFTrie);
  108. }
  109. END_BLOCK
  110. }
  111. UINT
  112. CALLCONV
  113. InsertIntoFTrie(IN FTrie * pFTrie,
  114. IN Route * pInsRoute,
  115. IN Dest * pInsDest,
  116. IN Dest * pOldDest)
  117. /*++
  118. Routine Description:
  119. Inserts a dest corresponding to an address
  120. prefix into a F-trie. It actually replaces
  121. all pointers to OldDest by that of InsDest.
  122. Arguments:
  123. pFTrie - Pointer to the F-Trie to insert into
  124. pInsRoute - Pointer to best route on new dest
  125. pInsDest - Pointer to the dest being inserted
  126. pOldDest - Pointer to the dest being replaced
  127. Return Value:
  128. TRIE_SUCCESS or ERROR_TRIE_*
  129. --*/
  130. {
  131. FTrieNode **ppCurrNode;
  132. FTrieNode *pCurrNode;
  133. Dest *pBestDest;
  134. Dest *pComDest;
  135. UINT startIndex;
  136. UINT stopIndex;
  137. UINT nextIndex;
  138. UINT shiftIndex;
  139. UINT addrBits;
  140. UINT numBits;
  141. UINT bitsLeft;
  142. UINT i, j;
  143. #if DBG
  144. // Make sure the trie is initialized
  145. if (!pFTrie || !pFTrie->trieRoot) {
  146. Fatal("Insert Dest: FTrie not initialized",
  147. ERROR_TRIE_NOT_INITED);
  148. }
  149. // Make sure input dest is valid
  150. if (NULL_DEST(pInsDest)) {
  151. Fatal("Insert Dest: NULL or invalid dest",
  152. ERROR_TRIE_BAD_PARAM);
  153. }
  154. // Make sure input route is valid
  155. if (NULL_ROUTE(pInsRoute)) {
  156. Fatal("Insert Dest: NULL or invalid route",
  157. ERROR_TRIE_BAD_PARAM);
  158. }
  159. if (LEN(pInsRoute) > ADDRSIZE) {
  160. Fatal("Insert Dest: Invalid mask length",
  161. ERROR_TRIE_BAD_PARAM);
  162. }
  163. #endif
  164. Assert(pInsDest != pOldDest);
  165. // Use addr bits to index the trie
  166. addrBits = RtlConvertEndianLong(DEST(pInsRoute));
  167. bitsLeft = LEN(pInsRoute);
  168. #if DBG
  169. // Make sure addr and mask agree
  170. if (ShowMostSigNBits(addrBits, bitsLeft) != addrBits) {
  171. Fatal("Insert Dest: Addr & mask don't agree",
  172. ERROR_TRIE_BAD_PARAM);
  173. }
  174. #endif
  175. TRY_BLOCK
  176. {
  177. // Special case: Default Prefix
  178. if (LEN(pInsRoute) == 0) {
  179. // Do we have a subtree in the trie's root node ?
  180. if (IsPtrADestPtr(pFTrie->trieRoot)) {
  181. // Make sure you are replacing right dest
  182. Assert(pFTrie->trieRoot == StoreDestPtr(pOldDest));
  183. // Make the root to point to the new default
  184. pFTrie->trieRoot = StoreDestPtr(pInsDest);
  185. } else {
  186. // Make sure you are replacing right dest
  187. Assert(pFTrie->trieRoot->comDest == pOldDest);
  188. // Make new dest the common subtrie dest
  189. pFTrie->trieRoot->comDest = pInsDest;
  190. }
  191. return TRIE_SUCCESS;
  192. }
  193. // Start going down the trie using addr bits
  194. pBestDest = NULL;
  195. ppCurrNode = &pFTrie->trieRoot;
  196. for (i = 0; /* NOTHING */ ; i++) {
  197. pCurrNode = *ppCurrNode;
  198. if (IsPtrADestPtr(pCurrNode)) {
  199. // Creating a new subtree for the current level
  200. // This pointer actually points to a dest node
  201. pComDest = RestoreDestPtr(pCurrNode);
  202. // Create, initialize a new FTrie node (grow it)
  203. NewFTrieNode(pFTrie,
  204. pCurrNode,
  205. pFTrie->bitsInLevel[i],
  206. pComDest);
  207. // Attach it to the FTrie
  208. *ppCurrNode = pCurrNode;
  209. // Update FTrie Statistics
  210. pFTrie->numNodesInExpnLevel[i]++;
  211. }
  212. // Update the best dest seen so far - used later
  213. pComDest = pCurrNode->comDest;
  214. if (pComDest) {
  215. pBestDest = pComDest;
  216. }
  217. // Increment the number of dests in this subtrie
  218. pCurrNode->numDests++;
  219. // Can I pass this level with remaining bits ?
  220. if (bitsLeft <= pFTrie->bitsInLevel[i]) {
  221. break;
  222. }
  223. // Get the next index from the IP addr
  224. numBits = pCurrNode->numBits;
  225. nextIndex = PickMostSigNBits(addrBits, numBits);
  226. ppCurrNode = &pCurrNode->child[nextIndex];
  227. // Throw away the used bits
  228. addrBits <<= numBits;
  229. bitsLeft -= numBits;
  230. }
  231. // Update FTrie stats before expanding
  232. // Update if this isn't a dest change
  233. pFTrie->numDestsInExpnLevel[i]++;
  234. pFTrie->numDestsInOrigLevel[LEN(pInsRoute)]++;
  235. // At this level, expand and add the dest
  236. nextIndex = PickMostSigNBits(addrBits, bitsLeft);
  237. shiftIndex = pFTrie->bitsInLevel[i] - bitsLeft;
  238. startIndex = nextIndex << shiftIndex;
  239. stopIndex = (nextIndex + 1) << shiftIndex;
  240. // Have you seen the old dest already ?
  241. if (pBestDest == pOldDest) {
  242. pOldDest = NULL;
  243. }
  244. // These dests cannot be the same here
  245. Assert(pInsDest != pOldDest);
  246. // Fill the expanded range with the dest
  247. for (i = startIndex; i < stopIndex; i++) {
  248. if (IsPtrADestPtr(pCurrNode->child[i])) {
  249. // A dest pointer - replace with new one
  250. ReplaceDestPtr(StoreDestPtr(pInsDest),
  251. StoreDestPtr(pOldDest),
  252. &pCurrNode->child[i]);
  253. } else {
  254. // Node pointer - update subtree's dest
  255. ReplaceDestPtr(pInsDest,
  256. pOldDest,
  257. &pCurrNode->child[i]->comDest);
  258. }
  259. }
  260. return TRIE_SUCCESS;
  261. }
  262. ERR_BLOCK
  263. {
  264. // Not enough resources - rollback to original state
  265. DeleteFromFTrie(pFTrie, pInsRoute, pInsDest, pOldDest, PARTIAL);
  266. }
  267. END_BLOCK
  268. }
  269. UINT
  270. CALLCONV
  271. DeleteFromFTrie(IN FTrie * pFTrie,
  272. IN Route * pDelRoute,
  273. IN Dest * pDelDest,
  274. IN Dest * pNewDest,
  275. IN BOOLEAN trieState)
  276. /*++
  277. Routine Description:
  278. Deletes a dest corresponding to an address
  279. prefix from a F-trie. It actually replaces
  280. all pointers to DelDest by that of NewDest.
  281. Arguments:
  282. pFTrie - Pointer to the F-Trie to delete from
  283. pDelRoute - Pointer to last route on old dest
  284. pDelDest - Pointer to the dest being deleted
  285. pNewDest - Pointer to the dest replacing above
  286. trieState - NORMAL - deleting from a consistent FTrie
  287. PARTIAL - cleaning up an incomplete insert
  288. Return Value:
  289. TRIE_SUCCESS or ERROR_TRIE_*
  290. --*/
  291. {
  292. FTrieNode **ppCurrNode;
  293. FTrieNode *pCurrNode;
  294. FTrieNode *pPrevNode;
  295. FTrieNode *pNextNode;
  296. Dest *pBestDest;
  297. Dest *pComDest;
  298. UINT startIndex;
  299. UINT stopIndex;
  300. UINT nextIndex;
  301. UINT shiftIndex;
  302. UINT addrBits;
  303. UINT numBits;
  304. UINT bitsLeft;
  305. UINT i, j;
  306. #if DBG
  307. // Make sure the trie is initialized
  308. if (!pFTrie || !pFTrie->trieRoot) {
  309. Fatal("Delete Dest: FTrie not initialized",
  310. ERROR_TRIE_NOT_INITED);
  311. }
  312. // Make sure input dest is valid
  313. if (NULL_DEST(pDelDest)) {
  314. Fatal("Delete Dest: NULL or invalid dest",
  315. ERROR_TRIE_BAD_PARAM);
  316. }
  317. // Make sure input route is valid
  318. if (NULL_ROUTE(pDelRoute)) {
  319. Fatal("Delete Dest: NULL or invalid route",
  320. ERROR_TRIE_BAD_PARAM);
  321. }
  322. if (LEN(pDelRoute) > ADDRSIZE) {
  323. Fatal("Delete Dest: Invalid mask length",
  324. ERROR_TRIE_BAD_PARAM);
  325. }
  326. #endif
  327. // Use addr bits to index the trie
  328. addrBits = RtlConvertEndianLong(DEST(pDelRoute));
  329. bitsLeft = LEN(pDelRoute);
  330. #if DBG
  331. // Make sure addr and mask agree
  332. if (ShowMostSigNBits(addrBits, bitsLeft) != addrBits) {
  333. Fatal("Delete Dest: Addr & mask don't agree",
  334. ERROR_TRIE_BAD_PARAM);
  335. }
  336. #endif
  337. Assert(pDelDest != pNewDest);
  338. // Special case: Default Prefix
  339. if (LEN(pDelRoute) == 0) {
  340. // Do we have a subtree in the trie's root node ?
  341. if (IsPtrADestPtr(pFTrie->trieRoot)) {
  342. // Make sure you are replacing right dest
  343. Assert(pFTrie->trieRoot == StoreDestPtr(pDelDest));
  344. // Make the root to point to the new default
  345. pFTrie->trieRoot = StoreDestPtr(pNewDest);
  346. } else {
  347. // Make sure you are replacing right dest
  348. Assert(pFTrie->trieRoot->comDest == pDelDest);
  349. // Make new dest the common subtrie dest
  350. pFTrie->trieRoot->comDest = pNewDest;
  351. }
  352. return TRIE_SUCCESS;
  353. }
  354. // Start going down the trie using addr bits
  355. pBestDest = NULL;
  356. ppCurrNode = &pFTrie->trieRoot;
  357. pPrevNode = pCurrNode = *ppCurrNode;
  358. for (i = 0; /* NOTHING */ ; i++) {
  359. // We still have bits left, so we go down the trie
  360. // Do we have a valid subtree at the current node
  361. if (IsPtrADestPtr(pCurrNode)) {
  362. // We are cleaning a partial (failed) insert
  363. Assert(trieState == PARTIAL);
  364. // We have cleaned up the trie - return now
  365. return TRIE_SUCCESS;
  366. }
  367. // We have a valid subtree, so we go down the trie
  368. // Update the best dest seen so far - used later
  369. pComDest = pCurrNode->comDest;
  370. if (pComDest) {
  371. pBestDest = pComDest;
  372. }
  373. // Decrement the number of dests in this subtrie
  374. pCurrNode->numDests--;
  375. // Is the number of dests in curr subtree zero ?
  376. if (pCurrNode->numDests == 0) {
  377. #if DBG
  378. int k = 0;
  379. // Just make sure that only one dest exists
  380. for (j = 1; j < (UINT) 1 << pCurrNode->numBits; j++) {
  381. if (pCurrNode->child[j - 1] != pCurrNode->child[j]) {
  382. Assert((pCurrNode->child[j] == StoreDestPtr(NULL)) ||
  383. (pCurrNode->child[j - 1] == StoreDestPtr(NULL)));
  384. k++;
  385. }
  386. }
  387. if (trieState == NORMAL) {
  388. if ((k != 1) && (k != 2)) {
  389. Print("k = %d\n", k);
  390. Assert(FALSE);
  391. }
  392. } else {
  393. if ((k != 0) && (k != 1) && (k != 2)) {
  394. Print("k = %d\n", k);
  395. Assert(FALSE);
  396. }
  397. }
  398. #endif
  399. // Remove link from its parent (if it exists)
  400. if (pPrevNode) {
  401. *ppCurrNode = StoreDestPtr(pCurrNode->comDest);
  402. }
  403. }
  404. // Can I pass this level with remaining bits ?
  405. if (bitsLeft <= pFTrie->bitsInLevel[i]) {
  406. break;
  407. }
  408. // Get the next index from the IP addr
  409. numBits = pCurrNode->numBits;
  410. nextIndex = PickMostSigNBits(addrBits, numBits);
  411. ppCurrNode = &pCurrNode->child[nextIndex];
  412. pNextNode = *ppCurrNode;
  413. // Throw away the used bits
  414. addrBits <<= numBits;
  415. bitsLeft -= numBits;
  416. // Is the number of dests in subtree zero ?
  417. if (pCurrNode->numDests == 0) {
  418. // Deallocate it (shrink FTrie)
  419. FreeFTrieNode(pFTrie, pCurrNode);
  420. // Update FTrie Statistics
  421. pFTrie->numNodesInExpnLevel[i]--;
  422. }
  423. pPrevNode = pCurrNode;
  424. pCurrNode = pNextNode;
  425. }
  426. // Update F-Trie stats before deleting
  427. pFTrie->numDestsInExpnLevel[i]--;
  428. pFTrie->numDestsInOrigLevel[LEN(pDelRoute)]--;
  429. // Is the number of dests in curr subtree zero ?
  430. if (pCurrNode->numDests == 0) {
  431. // Deallocate it (shrink FTrie)
  432. FreeFTrieNode(pFTrie, pCurrNode);
  433. // Update FTrie Statistics
  434. pFTrie->numNodesInExpnLevel[i]--;
  435. } else {
  436. // At this level, expand and add the dest
  437. nextIndex = PickMostSigNBits(addrBits, bitsLeft);
  438. shiftIndex = pFTrie->bitsInLevel[i] - bitsLeft;
  439. startIndex = nextIndex << shiftIndex;
  440. stopIndex = (nextIndex + 1) << shiftIndex;
  441. // Have you seen the new dest already ?
  442. if (pBestDest == pNewDest) {
  443. pNewDest = NULL;
  444. }
  445. // These dests cannot be the same here
  446. Assert(pDelDest != pNewDest);
  447. // Fill the expanded range with the dest
  448. for (i = startIndex; i < stopIndex; i++) {
  449. if (IsPtrADestPtr(pCurrNode->child[i])) {
  450. // A dest pointer - replace with new one
  451. ReplaceDestPtr(StoreDestPtr(pNewDest),
  452. StoreDestPtr(pDelDest),
  453. &pCurrNode->child[i]);
  454. } else {
  455. // Node pointer - update subtree's dest
  456. ReplaceDestPtr(pNewDest,
  457. pDelDest,
  458. &pCurrNode->child[i]->comDest);
  459. }
  460. }
  461. }
  462. return TRIE_SUCCESS;
  463. }
  464. UINT
  465. CALLCONV
  466. SearchDestInFTrie(IN FTrie * pFTrie,
  467. IN Dest * pSerDest,
  468. OUT UINT * pNumPtrs,
  469. OUT Dest ** pStartPtr)
  470. /*++
  471. Routine Description:
  472. Search for a specific dest in an F-trie,
  473. returns the expanded range for the dest
  474. Arguments:
  475. pFTrie - Pointer to the F-trie to search
  476. pSerDest - Pointer to dest being searched
  477. pStartPtr - Start of dest's expanded range
  478. pNumPtrs - Number of pointers in the range
  479. Return Value:
  480. TRIE_SUCCESS or ERROR_TRIE_*
  481. --*/
  482. {
  483. return ERROR_TRIE_BAD_PARAM;
  484. }
  485. Dest *
  486. CALLCONV
  487. SearchAddrInFTrie(IN FTrie * pFTrie,
  488. IN ULONG Addr)
  489. /*++
  490. Routine Description:
  491. Search for an address in an F-trie
  492. Arguments:
  493. pFTrie - Pointer to the trie to search
  494. Addr - Pointer to addr being queried
  495. Return Value:
  496. Return best dest match for this address
  497. --*/
  498. {
  499. FTrieNode *pCurrNode;
  500. Dest *pBestDest;
  501. Dest *pDest;
  502. ULONG addrBits;
  503. UINT numBits;
  504. UINT nextIndex;
  505. #if DBG
  506. if (!pFTrie || !pFTrie->trieRoot) {
  507. Fatal("Searching into an uninitialized FTrie",
  508. ERROR_TRIE_NOT_INITED);
  509. }
  510. #endif
  511. addrBits = RtlConvertEndianLong(Addr);
  512. pBestDest = NULL;
  513. pCurrNode = pFTrie->trieRoot;
  514. do {
  515. // Have we reached the end of this search ?
  516. if (IsPtrADestPtr(pCurrNode)) {
  517. // Get the best matching dest until now
  518. pDest = RestoreDestPtr(pCurrNode);
  519. if (!NULL_DEST(pDest)) {
  520. pBestDest = pDest;
  521. }
  522. return pBestDest;
  523. } else {
  524. // Get the best matching dest until now
  525. pDest = pCurrNode->comDest;
  526. if (!NULL_DEST(pDest)) {
  527. pBestDest = pDest;
  528. }
  529. }
  530. // Number of bits to use in this FTrie level
  531. numBits = pCurrNode->numBits;
  532. // Get the next index from IP address bits
  533. nextIndex = PickMostSigNBits(addrBits, numBits);
  534. // And go down the tree with the new index
  535. pCurrNode = pCurrNode->child[nextIndex];
  536. // Throw away the used bits for this iteration
  537. addrBits <<= numBits;
  538. }
  539. while (TRUE);
  540. }
  541. UINT
  542. CALLCONV
  543. CleanupFTrie(IN FTrie * pFTrie)
  544. /*++
  545. Routine Description:
  546. Deletes an F-trie if it is empty
  547. Arguments:
  548. ppFTrie - Ptr to the F-trie
  549. Return Value:
  550. TRIE_SUCCESS or ERROR_TRIE_*
  551. --*/
  552. {
  553. FTrieNode *pCurrNode;
  554. LIST_ENTRY *p;
  555. // Free all trie nodes and corresponding memory
  556. while (!IsListEmpty(&pFTrie->listofNodes)) {
  557. p = RemoveHeadList(&pFTrie->listofNodes);
  558. pCurrNode = CONTAINING_RECORD(p, FTrieNode, linkage);
  559. FreeFTrieNode(pFTrie, pCurrNode);
  560. }
  561. // Free the memory for the arr of levels
  562. if (pFTrie->bitsInLevel) {
  563. FreeMemory1(pFTrie->bitsInLevel,
  564. (MAXLEVEL + 1) * sizeof(UINT),
  565. pFTrie->availMemory);
  566. }
  567. // Free memory allocated for statistics
  568. if (pFTrie->numDestsInOrigLevel) {
  569. FreeMemory1(pFTrie->numDestsInOrigLevel,
  570. (MAXLEVEL + 1) * sizeof(UINT),
  571. pFTrie->availMemory);
  572. }
  573. if (pFTrie->numNodesInExpnLevel) {
  574. FreeMemory1(pFTrie->numNodesInExpnLevel,
  575. pFTrie->numLevels * sizeof(UINT),
  576. pFTrie->availMemory);
  577. }
  578. if (pFTrie->numDestsInExpnLevel) {
  579. FreeMemory1(pFTrie->numDestsInExpnLevel,
  580. pFTrie->numLevels * sizeof(UINT),
  581. pFTrie->availMemory);
  582. }
  583. // Reset other fields in trie structure
  584. pFTrie->trieRoot = NULL;
  585. pFTrie->numLevels = 0;
  586. return TRIE_SUCCESS;
  587. }
  588. #if DBG
  589. VOID
  590. CALLCONV
  591. PrintFTrie(IN FTrie * pFTrie,
  592. IN UINT printFlags)
  593. /*++
  594. Routine Description:
  595. Print an F-Trie
  596. Arguments:
  597. pFTrie - Pointer to the F-Trie
  598. printFlags - Information to print
  599. Return Value:
  600. None
  601. --*/
  602. {
  603. FTrieNode *pCurrNode;
  604. UINT i;
  605. if (pFTrie == NULL) {
  606. Print("%s", "Uninitialized FTrie\n\n");
  607. return;
  608. }
  609. if ((printFlags & SUMM) == SUMM) {
  610. Print("\n\n/***Fast-Trie------------------------------------------------");
  611. Print("\n/***---------------------------------------------------------\n");
  612. }
  613. if (printFlags & POOL) {
  614. Print("Available Memory: %10lu\n\n", pFTrie->availMemory);
  615. }
  616. if (printFlags & STAT) {
  617. Print("Statistics:\n\n");
  618. Print("Num of levels: %d\n", pFTrie->numLevels);
  619. Print("Bits In Level:\n");
  620. for (i = 0; i < pFTrie->numLevels; i++) {
  621. Print("\t%d", pFTrie->bitsInLevel[i]);
  622. if (i % 8 == 7)
  623. Print("\n");
  624. }
  625. Print("\n\n");
  626. Print("Num of Nodes in Expanded Levels:\n");
  627. for (i = 0; i < pFTrie->numLevels; i++) {
  628. Print("\t%d", pFTrie->numNodesInExpnLevel[i]);
  629. if (i % 8 == 7)
  630. Print("\n");
  631. }
  632. Print("\n\n");
  633. Print("Num of Dests in Original Levels:\n");
  634. for (i = 0; i < MAXLEVEL + 1; i++) {
  635. Print("\t%d", pFTrie->numDestsInOrigLevel[i]);
  636. if (i % 8 == 0)
  637. Print("\n");
  638. }
  639. Print("\n\n");
  640. Print("Num of Dests in Expanded Levels:\n");
  641. for (i = 0; i < pFTrie->numLevels; i++) {
  642. Print("\t%d", pFTrie->numDestsInExpnLevel[i]);
  643. if (i % 8 == 7)
  644. Print("\n");
  645. }
  646. Print("\n\n");
  647. }
  648. if (printFlags & TRIE) {
  649. if (!IsPtrADestPtr(pFTrie->trieRoot)) {
  650. PrintFTrieNode(pFTrie->trieRoot, 0);
  651. } else {
  652. PrintDest(RestoreDestPtr(pFTrie->trieRoot));
  653. }
  654. }
  655. if ((printFlags & SUMM) == SUMM) {
  656. Print("\n---------------------------------------------------------***/\n");
  657. Print("---------------------------------------------------------***/\n\n");
  658. }
  659. }
  660. VOID
  661. CALLCONV
  662. PrintFTrieNode(IN FTrieNode * pFTrieNode,
  663. IN UINT levelNumber)
  664. /*++
  665. Routine Description:
  666. Print an F-Trie node
  667. Arguments:
  668. pFTrieNode - Pointer to the FTrie node
  669. Return Value:
  670. None
  671. --*/
  672. {
  673. FTrieNode *pCurrNode;
  674. UINT numElmts;
  675. UINT i, j;
  676. Print("\n/*-----------------------------------------------------------\n");
  677. Print("Num of bits at level %3d : %d\n", levelNumber, pFTrieNode->numBits);
  678. Print("Number of Subtrie Dests : %d\n", pFTrieNode->numDests);
  679. Print("Common SubTree Dest : ");
  680. PrintDest(pFTrieNode->comDest);
  681. Print("\n");
  682. numElmts = 1 << pFTrieNode->numBits;
  683. pCurrNode = StoreDestPtr(NULL);
  684. Print("Child Ptrs:\n\n");
  685. for (i = 0; i < numElmts; i++) {
  686. if (pFTrieNode->child[i] != pCurrNode) {
  687. pCurrNode = pFTrieNode->child[i];
  688. Print("Child Index: %8lu ", i);
  689. if (IsPtrADestPtr(pCurrNode)) {
  690. PrintDest(RestoreDestPtr(pCurrNode));
  691. } else {
  692. PrintFTrieNode(pCurrNode, levelNumber + 1);
  693. }
  694. }
  695. }
  696. Print("-----------------------------------------------------------*/\n\n");
  697. }
  698. #endif // DBG
  699.