예제 #1
0
파일: IxEthDBCore.c 프로젝트: JamesAng/ub
/**
 * @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;
}
예제 #2
0
/**
 * @brief inserts a mac descriptor into an tree
 *
 * @param searchTree tree where the insertion is to be performed (may be NULL)
 * @param descriptor descriptor to insert into tree
 *
 * @return the tree root
 *
 * @internal
 */
IX_ETH_DB_PRIVATE
MacTreeNode* ixEthDBTreeInsert(MacTreeNode *searchTree, MacDescriptor *descriptor)
{
    MacTreeNode *currentNode    = searchTree;
    MacTreeNode *insertLocation = NULL;
    MacTreeNode *newNode;
    INT32 insertPosition = RIGHT;

    if (descriptor == NULL)
    {
        return searchTree;
    }

    /* create a new node */
    newNode = ixEthDBAllocMacTreeNode();

    if (newNode == NULL)
    {
        /* out of memory */
        ERROR_LOG("Warning: ixEthDBAllocMacTreeNode returned NULL in file %s:%d (out of memory?)\n", __FILE__, __LINE__);

        ixEthDBFreeMacDescriptor(descriptor);

        return NULL;
    }

    /* populate node */
    newNode->descriptor = descriptor;

    /* an empty initial tree is a special case */
    if (searchTree == NULL)
    {
        return newNode;
    }

    /* get insertion location */
    while (insertLocation == NULL)
    {
        MacTreeNode *nextNode;

        /* compare given key with current node key */
        insertPosition = ixEthDBAddressCompare(descriptor->macAddress, currentNode->descriptor->macAddress);

        /* navigate down */
        if (insertPosition == RIGHT)
        {
            nextNode = currentNode->right;
        }
        else if (insertPosition == LEFT)
        {
            nextNode = currentNode->left;
        }
        else
        {
            /* error, duplicate key */
            ERROR_LOG("Warning: trapped insertion of a duplicate MAC address in an NPE search tree\n");

            /* this will free the MAC descriptor as well */
            ixEthDBFreeMacTreeNode(newNode);

            return searchTree;
        }

        /* when we can no longer dive through the tree we found the insertion place */
        if (nextNode != NULL)
        {
            currentNode = nextNode;
        }
        else
        {
            insertLocation = currentNode;
        }
    }

    /* insert node */
    if (insertPosition == RIGHT)
    {
        insertLocation->right = newNode;
    }
    else
    {
        insertLocation->left = newNode;
    }

    return searchTree;
}