4 * @brief Memory handling routines for the MAC address database
7 * IXP400 SW Release version 2.0
9 * -- Copyright Notice --
12 * Copyright 2001-2005, Intel Corporation.
13 * All rights reserved.
16 * SPDX-License-Identifier: BSD-3-Clause
18 * -- End of Copyright Notice --
22 #include "IxEthDB_p.h"
24 IX_ETH_DB_PRIVATE HashNode *nodePool = NULL;
25 IX_ETH_DB_PRIVATE MacDescriptor *macPool = NULL;
26 IX_ETH_DB_PRIVATE MacTreeNode *treePool = NULL;
28 IX_ETH_DB_PRIVATE HashNode nodePoolArea[NODE_POOL_SIZE];
29 IX_ETH_DB_PRIVATE MacDescriptor macPoolArea[MAC_POOL_SIZE];
30 IX_ETH_DB_PRIVATE MacTreeNode treePoolArea[TREE_POOL_SIZE];
32 IX_ETH_DB_PRIVATE IxOsalMutex nodePoolLock;
33 IX_ETH_DB_PRIVATE IxOsalMutex macPoolLock;
34 IX_ETH_DB_PRIVATE IxOsalMutex treePoolLock;
36 #define LOCK_NODE_POOL { ixOsalMutexLock(&nodePoolLock, IX_OSAL_WAIT_FOREVER); }
37 #define UNLOCK_NODE_POOL { ixOsalMutexUnlock(&nodePoolLock); }
39 #define LOCK_MAC_POOL { ixOsalMutexLock(&macPoolLock, IX_OSAL_WAIT_FOREVER); }
40 #define UNLOCK_MAC_POOL { ixOsalMutexUnlock(&macPoolLock); }
42 #define LOCK_TREE_POOL { ixOsalMutexLock(&treePoolLock, IX_OSAL_WAIT_FOREVER); }
43 #define UNLOCK_TREE_POOL { ixOsalMutexUnlock(&treePoolLock); }
45 /* private function prototypes */
46 IX_ETH_DB_PRIVATE MacDescriptor* ixEthDBPoolAllocMacDescriptor(void);
47 IX_ETH_DB_PRIVATE void ixEthDBPoolFreeMacDescriptor(MacDescriptor *macDescriptor);
50 * @addtogroup EthMemoryManagement
56 * @brief initializes the memory pools used by the ethernet database component
58 * Initializes the hash table node, mac descriptor and mac tree node pools.
59 * Called at initialization time by @ref ixEthDBInit().
64 void ixEthDBInitMemoryPools(void)
69 ixOsalMutexInit(&nodePoolLock);
71 for (local_index = 0 ; local_index < NODE_POOL_SIZE ; local_index++)
73 HashNode *freeNode = &nodePoolArea[local_index];
75 freeNode->nextFree = nodePool;
79 /* MacDescriptor pool */
80 ixOsalMutexInit(&macPoolLock);
82 for (local_index = 0 ; local_index < MAC_POOL_SIZE ; local_index++)
84 MacDescriptor *freeDescriptor = &macPoolArea[local_index];
86 freeDescriptor->nextFree = macPool;
87 macPool = freeDescriptor;
90 /* MacTreeNode pool */
91 ixOsalMutexInit(&treePoolLock);
93 for (local_index = 0 ; local_index < TREE_POOL_SIZE ; local_index++)
95 MacTreeNode *freeNode = &treePoolArea[local_index];
97 freeNode->nextFree = treePool;
103 * @brief allocates a hash node from the pool
105 * Allocates a hash node and resets its value.
107 * @return the allocated hash node or NULL if the pool is empty
112 HashNode* ixEthDBAllocHashNode(void)
114 HashNode *allocatedNode = NULL;
116 if (nodePool != NULL)
120 allocatedNode = nodePool;
121 nodePool = nodePool->nextFree;
125 memset(allocatedNode, 0, sizeof(HashNode));
128 return allocatedNode;
132 * @brief frees a hash node into the pool
134 * @param hashNode node to be freed
139 void ixEthDBFreeHashNode(HashNode *hashNode)
141 if (hashNode != NULL)
145 hashNode->nextFree = nodePool;
153 * @brief allocates a mac descriptor from the pool
155 * Allocates a mac descriptor and resets its value.
156 * This function is not used directly, instead @ref ixEthDBAllocMacDescriptor()
157 * is used, which keeps track of the pointer reference count.
159 * @see ixEthDBAllocMacDescriptor()
161 * @warning this function is not used directly by any other function
162 * apart from ixEthDBAllocMacDescriptor()
164 * @return the allocated mac descriptor or NULL if the pool is empty
169 MacDescriptor* ixEthDBPoolAllocMacDescriptor(void)
171 MacDescriptor *allocatedDescriptor = NULL;
177 allocatedDescriptor = macPool;
178 macPool = macPool->nextFree;
182 memset(allocatedDescriptor, 0, sizeof(MacDescriptor));
185 return allocatedDescriptor;
189 * @brief allocates and initializes a mac descriptor smart pointer
191 * Uses @ref ixEthDBPoolAllocMacDescriptor() to allocate a mac descriptor
192 * from the pool and initializes its reference count.
194 * @see ixEthDBPoolAllocMacDescriptor()
196 * @return the allocated mac descriptor or NULL if the pool is empty
201 MacDescriptor* ixEthDBAllocMacDescriptor(void)
203 MacDescriptor *allocatedDescriptor = ixEthDBPoolAllocMacDescriptor();
205 if (allocatedDescriptor != NULL)
209 allocatedDescriptor->refCount++;
214 return allocatedDescriptor;
218 * @brief frees a mac descriptor back into the pool
220 * @param macDescriptor mac descriptor to be freed
222 * @warning this function is not to be called by anyone but
223 * ixEthDBFreeMacDescriptor()
225 * @see ixEthDBFreeMacDescriptor()
230 void ixEthDBPoolFreeMacDescriptor(MacDescriptor *macDescriptor)
234 macDescriptor->nextFree = macPool;
235 macPool = macDescriptor;
241 * @brief frees or reduces the usage count of a mac descriptor smart pointer
243 * If the reference count reaches 0 (structure is no longer used anywhere)
244 * then the descriptor is freed back into the pool using ixEthDBPoolFreeMacDescriptor().
246 * @see ixEthDBPoolFreeMacDescriptor()
251 void ixEthDBFreeMacDescriptor(MacDescriptor *macDescriptor)
253 if (macDescriptor != NULL)
257 if (macDescriptor->refCount > 0)
259 macDescriptor->refCount--;
261 if (macDescriptor->refCount == 0)
265 ixEthDBPoolFreeMacDescriptor(macDescriptor);
280 * @brief clones a mac descriptor smart pointer
282 * @param macDescriptor mac descriptor to clone
284 * Increments the usage count of the smart pointer
286 * @returns the cloned smart pointer
291 MacDescriptor* ixEthDBCloneMacDescriptor(MacDescriptor *macDescriptor)
295 if (macDescriptor->refCount == 0)
302 macDescriptor->refCount++;
306 return macDescriptor;
310 * @brief allocates a mac tree node from the pool
312 * Allocates and initializes a mac tree node from the pool.
314 * @return the allocated mac tree node or NULL if the pool is empty
319 MacTreeNode* ixEthDBAllocMacTreeNode(void)
321 MacTreeNode *allocatedNode = NULL;
323 if (treePool != NULL)
327 allocatedNode = treePool;
328 treePool = treePool->nextFree;
332 memset(allocatedNode, 0, sizeof(MacTreeNode));
335 return allocatedNode;
339 * @brief frees a mac tree node back into the pool
341 * @param macNode mac tree node to be freed
343 * @warning not to be used except from ixEthDBFreeMacTreeNode().
345 * @see ixEthDBFreeMacTreeNode()
349 void ixEthDBPoolFreeMacTreeNode(MacTreeNode *macNode)
355 macNode->nextFree = treePool;
363 * @brief frees or reduces the usage count of a mac tree node smart pointer
365 * @param macNode mac tree node to free
367 * Reduces the usage count of the given mac node. If the usage count
368 * reaches 0 the node is freed back into the pool using ixEthDBPoolFreeMacTreeNode()
373 void ixEthDBFreeMacTreeNode(MacTreeNode *macNode)
375 if (macNode->descriptor != NULL)
377 ixEthDBFreeMacDescriptor(macNode->descriptor);
380 if (macNode->left != NULL)
382 ixEthDBFreeMacTreeNode(macNode->left);
385 if (macNode->right != NULL)
387 ixEthDBFreeMacTreeNode(macNode->right);
390 ixEthDBPoolFreeMacTreeNode(macNode);
394 * @brief clones a mac tree node
396 * @param macNode mac tree node to be cloned
398 * Increments the usage count of the node, <i>its associated descriptor
399 * and <b>recursively</b> of all its child nodes</i>.
401 * @warning this function is recursive and clones whole trees/subtrees, use only for
407 MacTreeNode* ixEthDBCloneMacTreeNode(MacTreeNode *macNode)
411 MacTreeNode *clonedMacNode = ixEthDBAllocMacTreeNode();
413 if (clonedMacNode != NULL)
415 if (macNode->right != NULL)
417 clonedMacNode->right = ixEthDBCloneMacTreeNode(macNode->right);
420 if (macNode->left != NULL)
422 clonedMacNode->left = ixEthDBCloneMacTreeNode(macNode->left);
425 if (macNode->descriptor != NULL)
427 clonedMacNode->descriptor = ixEthDBCloneMacDescriptor(macNode->descriptor);
431 return clonedMacNode;
440 /* Debug statistical functions for memory usage */
442 extern HashTable dbHashtable;
443 int ixEthDBNumHashElements(void);
445 int ixEthDBNumHashElements(void)
449 HashTable *hashTable = &dbHashtable;
451 for (bucketIndex = 0 ; bucketIndex < hashTable->numBuckets ; bucketIndex++)
453 if (hashTable->hashBuckets[bucketIndex] != NULL)
455 HashNode *node = hashTable->hashBuckets[bucketIndex];
469 UINT32 ixEthDBSearchTreeUsageGet(MacTreeNode *tree)
477 return 1 /* this node */ + ixEthDBSearchTreeUsageGet(tree->left) + ixEthDBSearchTreeUsageGet(tree->right);
481 int ixEthDBShowMemoryStatus(void)
491 int totalTreeUsage = 0;
492 int totalDescriptorUsage = 0;
493 int totalCloneDescriptorUsage = 0;
494 int totalNodeUsage = 0;
512 if (macCounter > MAC_POOL_SIZE)
522 tree = tree->nextFree;
524 if (treeCounter > TREE_POOL_SIZE)
534 node = node->nextFree;
536 if (nodeCounter > NODE_POOL_SIZE)
542 for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
544 int treeUsage = ixEthDBSearchTreeUsageGet(ixEthDBPortInfo[portIndex].updateMethod.searchTree);
546 totalTreeUsage += treeUsage;
547 totalCloneDescriptorUsage += treeUsage; /* each tree node contains a descriptor */
550 totalNodeUsage = ixEthDBNumHashElements();
551 totalDescriptorUsage += totalNodeUsage; /* each hash table entry contains a descriptor */
557 printf("Ethernet database memory usage stats:\n\n");
559 if (macCounter <= MAC_POOL_SIZE)
561 printf("\tMAC descriptor pool : %d free out of %d entries (%d%%)\n", macCounter, MAC_POOL_SIZE, macCounter * 100 / MAC_POOL_SIZE);
565 printf("\tMAC descriptor pool : invalid state (ring within the pool), normally %d entries\n", MAC_POOL_SIZE);
568 if (treeCounter <= TREE_POOL_SIZE)
570 printf("\tTree node pool : %d free out of %d entries (%d%%)\n", treeCounter, TREE_POOL_SIZE, treeCounter * 100 / TREE_POOL_SIZE);
574 printf("\tTREE descriptor pool : invalid state (ring within the pool), normally %d entries\n", TREE_POOL_SIZE);
577 if (nodeCounter <= NODE_POOL_SIZE)
579 printf("\tHash node pool : %d free out of %d entries (%d%%)\n", nodeCounter, NODE_POOL_SIZE, nodeCounter * 100 / NODE_POOL_SIZE);
583 printf("\tNODE descriptor pool : invalid state (ring within the pool), normally %d entries\n", NODE_POOL_SIZE);
587 printf("\tMAC descriptor usage : %d entries, %d cloned\n", totalDescriptorUsage, totalCloneDescriptorUsage);
588 printf("\tTree node usage : %d entries\n", totalTreeUsage);
589 printf("\tHash node usage : %d entries\n", totalNodeUsage);
592 /* search for duplicate nodes in the mac pool */
594 MacDescriptor *reference = macPool;
596 while (reference != NULL)
598 MacDescriptor *comparison = reference->nextFree;
600 while (comparison != NULL)
602 if (reference == comparison)
604 printf("Warning: reached a duplicate (%p), invalid MAC pool state\n", reference);
609 comparison = comparison->nextFree;
612 reference = reference->nextFree;
616 printf("No duplicates found in the MAC pool (sanity check ok)\n");
624 * @} EthMemoryManagement