IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBPortDependencyMapGet(IxEthDBPortId portID, IxEthDBPortMap dependencyPortMap) { IX_ETH_DB_CHECK_PORT(portID); IX_ETH_DB_CHECK_SINGLE_NPE(portID); IX_ETH_DB_CHECK_REFERENCE(dependencyPortMap); IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FILTERING); COPY_DEPENDENCY_MAP(dependencyPortMap, ixEthDBPortInfo[portID].dependencyPortMap); return IX_ETH_DB_SUCCESS; }
IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBPortDependencyMapSet(IxEthDBPortId portID, IxEthDBPortMap dependencyPortMap) { IX_ETH_DB_CHECK_PORT(portID); IX_ETH_DB_CHECK_SINGLE_NPE(portID); IX_ETH_DB_CHECK_REFERENCE(dependencyPortMap); IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_FILTERING); /* force bit at offset 255 to 0 (reserved) */ dependencyPortMap[31] &= 0xFE; COPY_DEPENDENCY_MAP(ixEthDBPortInfo[portID].dependencyPortMap, dependencyPortMap); return IX_ETH_DB_SUCCESS; }
/** * @brief creates learning trees and calls the port update handlers * * @param updatePorts set of ports in need of learning trees * * This function determines the optimal method of creating learning * trees using a minimal number of database queries, keeping in mind * that different ports can either use the same learning trees or they * can partially share them. The actual tree building routine is * @ref ixEthDBQuery. * * @internal */ IX_ETH_DB_PRIVATE void ixEthDBCreateTrees(IxEthDBPortMap updatePorts) { UINT32 portIndex; BOOL result; BOOL portsLeft = TRUE; while (portsLeft) { /* get port with minimal dependency map and NULL search tree */ UINT32 minPortIndex = MAX_PORT_SIZE; UINT32 minimalSize = MAX_PORT_SIZE; for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++) { UINT32 size; PortInfo *port = &ixEthDBPortInfo[portIndex]; /* generate trees only for ports that need them */ if (!port->updateMethod.searchTreePendingWrite && IS_PORT_INCLUDED(portIndex, updatePorts)) { GET_MAP_SIZE(port->dependencyPortMap, size); IX_ETH_DB_UPDATE_TRACE("DB: (Update) Dependency map for port %d: size %d\n", portIndex, size); if (size < minimalSize) { minPortIndex = portIndex; minimalSize = size; } } else { IX_ETH_DB_UPDATE_TRACE("DB: (Update) Skipped port %d from tree diff (%s)\n", portIndex, port->updateMethod.searchTreePendingWrite ? "pending write access" : "ignored by query"); } } /* if a port was found than minimalSize is not MAX_PORT_SIZE */ if (minimalSize != MAX_PORT_SIZE) { /* minPortIndex is the port we seek */ PortInfo *port = &ixEthDBPortInfo[minPortIndex]; IxEthDBPortMap query; MacTreeNode *baseTree; /* now try to find a port with minimal map difference */ PortInfo *minimalDiffPort = NULL; UINT32 minimalDiff = MAX_PORT_SIZE; IX_ETH_DB_UPDATE_TRACE("DB: (Update) Minimal size port is %d\n", minPortIndex); for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++) { PortInfo *diffPort = &ixEthDBPortInfo[portIndex]; BOOL mapIsSubset; IS_MAP_SUBSET(mapIsSubset, diffPort->dependencyPortMap, port->dependencyPortMap); if (portIndex != minPortIndex && diffPort->updateMethod.searchTree != NULL && mapIsSubset) { /* compute size and pick only minimal size difference */ UINT32 diffPortSize; UINT32 sizeDifference; GET_MAP_SIZE(diffPort->dependencyPortMap, diffPortSize); IX_ETH_DB_UPDATE_TRACE("DB: (Update) Checking port %d for differences...\n", portIndex); sizeDifference = minimalSize - diffPortSize; if (sizeDifference < minimalDiff) { minimalDiffPort = diffPort; minimalDiff = sizeDifference; IX_ETH_DB_UPDATE_TRACE("DB: (Update) Minimal difference 0x%x was found on port %d\n", minimalDiff, portIndex); } } } /* check if filtering is enabled on this port */ if ((port->featureStatus & IX_ETH_DB_FILTERING) != 0) { /* if minimalDiff is not MAX_PORT_SIZE minimalDiffPort points to the most similar port */ if (minimalDiff != MAX_PORT_SIZE) { baseTree = ixEthDBCloneMacTreeNode(minimalDiffPort->updateMethod.searchTree); DIFF_MAPS(query, port->dependencyPortMap , minimalDiffPort->dependencyPortMap); IX_ETH_DB_UPDATE_TRACE("DB: (Update) Found minimal diff, extending tree %d on query\n", minimalDiffPort->portID); } else /* .. otherwise no similar port was found, build tree from scratch */ { baseTree = NULL; COPY_DEPENDENCY_MAP(query, port->dependencyPortMap); IX_ETH_DB_UPDATE_TRACE("DB: (Update) No similar diff, creating tree from query\n"); } IS_EMPTY_DEPENDENCY_MAP(result, query); if (!result) /* otherwise we don't need anything more on top of the cloned tree */ { IX_ETH_DB_UPDATE_TRACE("DB: (Update) Adding query tree to port %d\n", minPortIndex); /* build learning tree */ port->updateMethod.searchTree = ixEthDBQuery(baseTree, query, IX_ETH_DB_ALL_FILTERING_RECORDS, MAX_ELT_SIZE - 1); } else { IX_ETH_DB_UPDATE_TRACE("DB: (Update) Query is empty, assuming identical nearest tree\n"); port->updateMethod.searchTree = baseTree; } } else { /* filtering is not enabled, will download an empty tree */ if (port->updateMethod.searchTree != NULL) { ixEthDBFreeMacTreeNode(port->updateMethod.searchTree); } port->updateMethod.searchTree = NULL; } /* mark tree as valid */ port->updateMethod.searchTreePendingWrite = TRUE; } else { portsLeft = FALSE; IX_ETH_DB_UPDATE_TRACE("DB: (Update) No trees to create this round\n"); } } for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++) { PortInfo *updatePort = &ixEthDBPortInfo[portIndex]; if (updatePort->updateMethod.searchTreePendingWrite) { IX_ETH_DB_UPDATE_TRACE("DB: (PortUpdate) Starting procedure to upload new search tree (%snull) into NPE %d\n", updatePort->updateMethod.searchTree != NULL ? "not " : "", portIndex); updatePort->updateMethod.updateHandler(portIndex, IX_ETH_DB_FILTERING_RECORD); } } }