Leaked source code of windows server 2003
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.

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