/** * @brief search a record in the Ethernet datbase * * @param macAddress MAC address to perform the search on * @param portID port ID to perform the search on * @param typeFilter type of records to consider for matching * * @warning if searching is successful an implicit write lock * to the search result is granted, therefore unlock the * entry using @ref ixEthDBReleaseHashNode() as soon as possible. * * @see ixEthDBReleaseHashNode() * * @return the search result, or NULL if a record with the given * MAC address/port ID combination was not found * * @internal */ IX_ETH_DB_PUBLIC HashNode* ixEthDBPortSearch(IxEthDBMacAddr *macAddress, IxEthDBPortId portID, IxEthDBRecordType typeFilter) { HashNode *searchResult = NULL; MacDescriptor reference; if (macAddress == NULL) { return NULL; } /* fill search fields */ memcpy(reference.macAddress, macAddress, sizeof (IxEthDBMacAddr)); reference.portID = portID; /* set acceptable record types */ reference.type = typeFilter; BUSY_RETRY(ixEthDBSearchHashEntry(&dbHashtable, IX_ETH_DB_MAC_PORT_KEY, &reference, &searchResult)); return searchResult; }
/** * @brief search a record in the Ethernet datbase * * @param macAddress MAC address to perform the search on * @param vlanID VLAN ID to perform the search on * @param typeFilter type of records to consider for matching * * @warning if searching is successful an implicit write lock * to the search result is granted, therefore unlock the * entry using @ref ixEthDBReleaseHashNode() as soon as possible. * * @see ixEthDBReleaseHashNode() * * @return the search result, or NULL if a record with the given * MAC address/VLAN ID combination was not found * * @internal */ IX_ETH_DB_PUBLIC HashNode* ixEthDBVlanSearch(IxEthDBMacAddr *macAddress, IxEthDBVlanId vlanID, IxEthDBRecordType typeFilter) { HashNode *searchResult = NULL; MacDescriptor reference; if (macAddress == NULL) { return NULL; } /* fill search fields */ memcpy(reference.macAddress, macAddress, sizeof (IxEthDBMacAddr)); reference.recordData.filteringVlanData.ieee802_1qTag = IX_ETH_DB_SET_VLAN_ID(reference.recordData.filteringVlanData.ieee802_1qTag, vlanID); /* set acceptable record types */ reference.type = typeFilter; BUSY_RETRY(ixEthDBSearchHashEntry(&dbHashtable, IX_ETH_DB_MAC_VLAN_KEY, &reference, &searchResult)); return searchResult; }
/** * @brief search a record in the Ethernet datbase * * @param macAddress MAC address to perform the search on * @param typeFilter type of records to consider for matching * * @warning if searching is successful an implicit write lock * to the search result is granted, therefore unlock the * entry using @ref ixEthDBReleaseHashNode() as soon as possible. * * @see ixEthDBReleaseHashNode() * * @return the search result, or NULL if a record with the given * MAC address was not found * * @internal */ IX_ETH_DB_PUBLIC HashNode* ixEthDBSearch(IxEthDBMacAddr *macAddress, IxEthDBRecordType typeFilter) { HashNode *searchResult = NULL; MacDescriptor reference; TEST_FIXTURE_INCREMENT_DB_CORE_ACCESS_COUNTER; if (macAddress == NULL) { return NULL; } /* fill search fields */ memcpy(reference.macAddress, macAddress, sizeof (IxEthDBMacAddr)); /* set acceptable record types */ reference.type = typeFilter; BUSY_RETRY(ixEthDBSearchHashEntry(&dbHashtable, IX_ETH_DB_MAC_KEY, &reference, &searchResult)); return searchResult; }
/** * @brief adds a new entry to the Ethernet database * * @param newRecordTemplate address of the record template to use * @param updateTrigger port map containing the update triggers * resulting from this update operation * * Creates a new database entry, populates it with the data * copied from the given template and adds the record to the * database hash table. * It also checks whether the new record type is registered to trigger * automatic updates; if it is, the update trigger will contain the * port on which the record insertion was performed, as well as the * old port in case the addition was a record migration (from one port * to the other). The caller can use the updateTrigger to trigger * automatic updates on the ports changed as a result of this addition. * * @retval IX_ETH_DB_SUCCESS addition successful * @retval IX_ETH_DB_NOMEM insertion failed, no memory left in the mac descriptor memory pool * @retval IX_ETH_DB_BUSY database busy, cannot insert due to locking * * @internal */ IX_ETH_DB_PUBLIC IxEthDBStatus ixEthDBAdd(MacDescriptor *newRecordTemplate, IxEthDBPortMap updateTrigger) { IxEthDBStatus result; MacDescriptor *newDescriptor; IxEthDBPortId originalPortID; HashNode *node = NULL; BUSY_RETRY(ixEthDBSearchHashEntry(&dbHashtable, ixEthDBKeyType[newRecordTemplate->type], newRecordTemplate, &node)); TEST_FIXTURE_INCREMENT_DB_CORE_ACCESS_COUNTER; if (node == NULL) { /* not found, create a new one */ newDescriptor = ixEthDBAllocMacDescriptor(); if (newDescriptor == NULL) { return IX_ETH_DB_NOMEM; /* no memory */ } /* old port does not exist, avoid unnecessary updates */ originalPortID = newRecordTemplate->portID; } else { /* a node with the same key exists, will update node */ newDescriptor = (MacDescriptor *) node->data; /* save original port id */ originalPortID = newDescriptor->portID; } /* copy/update fields into new record */ memcpy(newDescriptor->macAddress, newRecordTemplate->macAddress, sizeof (IxEthDBMacAddr)); memcpy(&newDescriptor->recordData, &newRecordTemplate->recordData, sizeof (IxEthDBRecordData)); newDescriptor->type = newRecordTemplate->type; newDescriptor->portID = newRecordTemplate->portID; newDescriptor->user = newRecordTemplate->user; if (node == NULL) { /* new record, insert into hashtable */ BUSY_RETRY_WITH_RESULT(ixEthDBAddHashEntry(&dbHashtable, newDescriptor), result); if (result != IX_ETH_DB_SUCCESS) { ixEthDBFreeMacDescriptor(newDescriptor); return result; /* insertion failed */ } } if (node != NULL) { /* release access */ ixEthDBReleaseHashNode(node); } /* trigger add/remove update if required by type */ if (updateTrigger != NULL && ixEthDBPortUpdateRequired[newRecordTemplate->type]) { /* add new port to update list */ JOIN_PORT_TO_MAP(updateTrigger, newRecordTemplate->portID); /* check if record has moved, we'll need to update the old port as well */ if (originalPortID != newDescriptor->portID) { JOIN_PORT_TO_MAP(updateTrigger, originalPortID); } } return IX_ETH_DB_SUCCESS; }