/**
 * @file IxEthDBAPISupport.c
 *
 * @brief Public API support functions
 *
 * @par
 * IXP400 SW Release version 2.0
 *
 * -- Copyright Notice --
 *
 * @par
 * Copyright 2001-2005, Intel Corporation.
 * All rights reserved.
 *
 * @par
 * SPDX-License-Identifier:	BSD-3-Clause
 * @par
 * -- End of Copyright Notice --
 */

#include <IxEthDB.h>
#include <IxNpeMh.h>
#include <IxFeatureCtrl.h>

#include "IxEthDB_p.h"
#include "IxEthDBMessages_p.h"
#include "IxEthDB_p.h"
#include "IxEthDBLog_p.h"

#ifdef IX_UNIT_TEST

int dbAccessCounter = 0;
int overflowEvent   = 0;

#endif

/*
 * External declaration
 */
extern HashTable dbHashtable;

/*
 * Internal declaration
 */
IX_ETH_DB_PUBLIC
PortInfo ixEthDBPortInfo[IX_ETH_DB_NUMBER_OF_PORTS];

IX_ETH_DB_PRIVATE
struct
{
    BOOL saved;
    IxEthDBPriorityTable priorityTable;
    IxEthDBVlanSet vlanMembership;
    IxEthDBVlanSet transmitTaggingInfo;
    IxEthDBFrameFilter frameFilter;
    IxEthDBTaggingAction taggingAction;
    IxEthDBFirewallMode firewallMode;
    BOOL stpBlocked;
    BOOL srcAddressFilterEnabled;
    UINT32 maxRxFrameSize;
    UINT32 maxTxFrameSize;
} ixEthDBPortState[IX_ETH_DB_NUMBER_OF_PORTS];

#define IX_ETH_DB_DEFAULT_FRAME_SIZE (1518)

/**
 * @brief initializes a port
 *
 * @param portID ID of the port to be initialized
 *
 * Note that redundant initializations are silently
 * dealt with and do not constitute an error
 *
 * This function is fully documented in the main
 * header file, IxEthDB.h
 */
IX_ETH_DB_PUBLIC
void ixEthDBPortInit(IxEthDBPortId portID)
{
    PortInfo *portInfo;

    if (portID >= IX_ETH_DB_NUMBER_OF_PORTS)
    {
        return;
    }

    portInfo = &ixEthDBPortInfo[portID];

    if (ixEthDBSingleEthNpeCheck(portID) != IX_ETH_DB_SUCCESS)
    {
        WARNING_LOG("EthDB: Unavailable Eth %d: Cannot initialize EthDB Port.\n", (UINT32) portID);

        return;
    }

    if (portInfo->initialized)
    {
        /* redundant */
        return;
    }

    /* initialize core fields */
    portInfo->portID = portID;
    SET_DEPENDENCY_MAP(portInfo->dependencyPortMap, portID);

    /* default values */
    portInfo->agingEnabled       = false;
    portInfo->enabled            = false;
    portInfo->macAddressUploaded = false;
    portInfo->maxRxFrameSize     = IX_ETHDB_DEFAULT_FRAME_SIZE;
    portInfo->maxTxFrameSize     = IX_ETHDB_DEFAULT_FRAME_SIZE;

    /* default update control values */
    portInfo->updateMethod.searchTree              = NULL;
    portInfo->updateMethod.searchTreePendingWrite  = false;
    portInfo->updateMethod.treeInitialized         = false;
    portInfo->updateMethod.updateEnabled           = false;
    portInfo->updateMethod.userControlled          = false;

    /* default WiFi parameters */
    memset(portInfo->bbsid, 0, sizeof (portInfo->bbsid));
    portInfo->frameControlDurationID = 0;

    /* Ethernet NPE-specific initializations */
    if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
    {
        /* update handler */
        portInfo->updateMethod.updateHandler = ixEthDBNPEUpdateHandler;
    }

    /* initialize state save */
    ixEthDBPortState[portID].saved = false;

    portInfo->initialized = true;
}

/**
 * @brief enables a port
 *
 * @param portID ID of the port to enable
 *
 * This function is fully documented in the main
 * header file, IxEthDB.h
 *
 * @return IX_ETH_DB_SUCCESS if enabling was
 * accomplished, or a meaningful error message otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBPortEnable(IxEthDBPortId portID)
{
    IxEthDBPortMap triggerPorts;
    PortInfo *portInfo;

    IX_ETH_DB_CHECK_PORT_EXISTS(portID);

    IX_ETH_DB_CHECK_SINGLE_NPE(portID);

    portInfo = &ixEthDBPortInfo[portID];

    if (portInfo->enabled)
    {
        /* redundant */
        return IX_ETH_DB_SUCCESS;
    }

    SET_DEPENDENCY_MAP(triggerPorts, portID);

    /* mark as enabled */
    portInfo->enabled = true;

    /* Operation stops here when Ethernet Learning is not enabled */
    if(IX_FEATURE_CTRL_SWCONFIG_DISABLED ==
       ixFeatureCtrlSwConfigurationCheck(IX_FEATURECTRL_ETH_LEARNING))
    {
        return IX_ETH_DB_SUCCESS;
    }

    if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE && !portInfo->macAddressUploaded)
    {
        IX_ETH_DB_SUPPORT_TRACE("DB: (Support) MAC address not set on port %d, enable failed\n", portID);

        /* must use UnicastAddressSet() before enabling an NPE port */
        return IX_ETH_DB_MAC_UNINITIALIZED;
    }

    if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
    {
        IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Attempting to enable the NPE callback for port %d...\n", portID);

        if (!portInfo->updateMethod.userControlled
                && ((portInfo->featureCapability & IX_ETH_DB_FILTERING) != 0))
        {
            portInfo->updateMethod.updateEnabled = true;
        }

        /* if this is first time initialization then we already have
           write access to the tree and can AccessRelease directly */
        if (!portInfo->updateMethod.treeInitialized)
        {
            IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Initializing tree for port %d\n", portID);

            /* create an initial tree and release access into it */
            ixEthDBUpdatePortLearningTrees(triggerPorts);

            /* mark tree as being initialized */
            portInfo->updateMethod.treeInitialized = true;
        }
    }

    if (ixEthDBPortState[portID].saved)
    {
        /* previous configuration data stored, restore state */
        if ((portInfo->featureCapability & IX_ETH_DB_FIREWALL) != 0)
        {
            ixEthDBFirewallModeSet(portID, ixEthDBPortState[portID].firewallMode);
            ixEthDBFirewallInvalidAddressFilterEnable(portID, ixEthDBPortState[portID].srcAddressFilterEnabled);
        }

#if 0 /* test-only */
        if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0)
        {
            ixEthDBAcceptableFrameTypeSet(portID, ixEthDBPortState[portID].frameFilter);
            ixEthDBIngressVlanTaggingEnabledSet(portID, ixEthDBPortState[portID].taggingAction);

            ixEthDBEgressVlanTaggingEnabledSet(portID, ixEthDBPortState[portID].transmitTaggingInfo);
            ixEthDBPortVlanMembershipSet(portID, ixEthDBPortState[portID].vlanMembership);

            ixEthDBPriorityMappingTableSet(portID, ixEthDBPortState[portID].priorityTable);
        }
#endif

        if ((portInfo->featureCapability & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0)
        {
            ixEthDBSpanningTreeBlockingStateSet(portID, ixEthDBPortState[portID].stpBlocked);
        }

        ixEthDBFilteringPortMaximumRxFrameSizeSet(portID, ixEthDBPortState[portID].maxRxFrameSize);
        ixEthDBFilteringPortMaximumTxFrameSizeSet(portID, ixEthDBPortState[portID].maxTxFrameSize);

        /* discard previous save */
        ixEthDBPortState[portID].saved = false;
    }

    IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Enabling succeeded for port %d\n", portID);

    return IX_ETH_DB_SUCCESS;
}

/**
 * @brief disables a port
 *
 * @param portID ID of the port to disable
 *
 * This function is fully documented in the
 * main header file, IxEthDB.h
 *
 * @return IX_ETH_DB_SUCCESS if disabling was
 * successful or an appropriate error message
 * otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBPortDisable(IxEthDBPortId portID)
{
    HashIterator iterator;
    IxEthDBPortMap triggerPorts; /* ports who will have deleted records and therefore will need updating */
    BOOL result;
    PortInfo *portInfo;
    IxEthDBFeature learningEnabled;
#if 0 /* test-only */
    IxEthDBPriorityTable classZeroTable;
#endif

    IX_ETH_DB_CHECK_PORT_EXISTS(portID);

    IX_ETH_DB_CHECK_SINGLE_NPE(portID);

    portInfo = &ixEthDBPortInfo[portID];

    if (!portInfo->enabled)
    {
        /* redundant */
        return IX_ETH_DB_SUCCESS;
    }

    if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
    {
        /* save filtering state */
        ixEthDBPortState[portID].firewallMode            = portInfo->firewallMode;
        ixEthDBPortState[portID].frameFilter             = portInfo->frameFilter;
        ixEthDBPortState[portID].taggingAction           = portInfo->taggingAction;
        ixEthDBPortState[portID].stpBlocked              = portInfo->stpBlocked;
        ixEthDBPortState[portID].srcAddressFilterEnabled = portInfo->srcAddressFilterEnabled;
        ixEthDBPortState[portID].maxRxFrameSize          = portInfo->maxRxFrameSize;
        ixEthDBPortState[portID].maxTxFrameSize          = portInfo->maxTxFrameSize;

        memcpy(ixEthDBPortState[portID].vlanMembership, portInfo->vlanMembership, sizeof (IxEthDBVlanSet));
        memcpy(ixEthDBPortState[portID].transmitTaggingInfo, portInfo->transmitTaggingInfo, sizeof (IxEthDBVlanSet));
        memcpy(ixEthDBPortState[portID].priorityTable, portInfo->priorityTable, sizeof (IxEthDBPriorityTable));

        ixEthDBPortState[portID].saved = true;

        /* now turn off all EthDB filtering features on the port */

#if 0 /* test-only */
        /* VLAN & QoS */
        if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0)
        {
            ixEthDBPortVlanMembershipRangeAdd((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID);
            ixEthDBEgressVlanRangeTaggingEnabledSet((IxEthDBPortId) portID, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID, false);
            ixEthDBAcceptableFrameTypeSet((IxEthDBPortId) portID, IX_ETH_DB_ACCEPT_ALL_FRAMES);
            ixEthDBIngressVlanTaggingEnabledSet((IxEthDBPortId) portID, IX_ETH_DB_PASS_THROUGH);

            memset(classZeroTable, 0, sizeof (classZeroTable));
            ixEthDBPriorityMappingTableSet((IxEthDBPortId) portID, classZeroTable);
        }
#endif

        /* STP */
        if ((portInfo->featureCapability & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0)
        {
            ixEthDBSpanningTreeBlockingStateSet((IxEthDBPortId) portID, false);
        }

        /* Firewall */
        if ((portInfo->featureCapability & IX_ETH_DB_FIREWALL) != 0)
        {
            ixEthDBFirewallModeSet((IxEthDBPortId) portID, IX_ETH_DB_FIREWALL_BLACK_LIST);
            ixEthDBFirewallTableDownload((IxEthDBPortId) portID);
            ixEthDBFirewallInvalidAddressFilterEnable((IxEthDBPortId) portID, false);
        }

        /* Frame size filter */
        ixEthDBFilteringPortMaximumFrameSizeSet((IxEthDBPortId) portID, IX_ETH_DB_DEFAULT_FRAME_SIZE);

        /* WiFi */
        if ((portInfo->featureCapability & IX_ETH_DB_WIFI_HEADER_CONVERSION) != 0)
        {
            ixEthDBWiFiConversionTableDownload((IxEthDBPortId) portID);
        }

        /* save and disable the learning feature bit */
        learningEnabled          = portInfo->featureStatus & IX_ETH_DB_LEARNING;
        portInfo->featureStatus &= ~IX_ETH_DB_LEARNING;
    }
    else
    {
        /* save the learning feature bit */
        learningEnabled          = portInfo->featureStatus & IX_ETH_DB_LEARNING;
    }

    SET_EMPTY_DEPENDENCY_MAP(triggerPorts);

    ixEthDBUpdateLock();

    /* wipe out current entries for this port */
    BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));

    while (IS_ITERATOR_VALID(&iterator))
    {
        MacDescriptor *descriptor =  (MacDescriptor *) iterator.node->data;

        /* check if the port match. If so, remove the entry  */
        if (descriptor->portID == portID
                && (descriptor->type == IX_ETH_DB_FILTERING_RECORD || descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD)
                && !descriptor->recordData.filteringData.staticEntry)
        {
            /* delete entry */
            BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator));

            /* add port to the set of update trigger ports */
            JOIN_PORT_TO_MAP(triggerPorts, portID);
        }
        else
        {
            /* move to the next record */
            BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator));
        }
    }

    if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
    {
        if (portInfo->updateMethod.searchTree != NULL)
        {
            ixEthDBFreeMacTreeNode(portInfo->updateMethod.searchTree);
            portInfo->updateMethod.searchTree = NULL;
        }

        ixEthDBNPEUpdateHandler(portID, IX_ETH_DB_FILTERING_RECORD);
    }

    /* mark as disabled */
    portInfo->enabled = false;

    /* disable updates unless the user has specifically altered the default behavior */
    if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
    {
        if (!portInfo->updateMethod.userControlled)
        {
            portInfo->updateMethod.updateEnabled = false;
        }

        /* make sure we re-initialize the NPE learning tree when the port is re-enabled */
        portInfo->updateMethod.treeInitialized = false;
    }

    ixEthDBUpdateUnlock();

    /* restore learning feature bit */
    portInfo->featureStatus |= learningEnabled;

    /* if we've removed any records or lost any events make sure to force an update */
    IS_EMPTY_DEPENDENCY_MAP(result, triggerPorts);

    if (!result)
    {
        ixEthDBUpdatePortLearningTrees(triggerPorts);
    }

    return IX_ETH_DB_SUCCESS;
}

/**
 * @brief sends the updated maximum Tx/Rx frame lengths to the NPE
 *
 * @param portID ID of the port to update
 *
 * @return IX_ETH_DB_SUCCESS if the update completed
 * successfully or an appropriate error message otherwise
 *
 * @internal
 */
IX_ETH_DB_PRIVATE
IxEthDBStatus ixEthDBPortFrameLengthsUpdate(IxEthDBPortId portID)
{
    IxNpeMhMessage message;
    PortInfo *portInfo = &ixEthDBPortInfo[portID];
    IX_STATUS result;

    FILL_SETMAXFRAMELENGTHS_MSG(message, portID, portInfo->maxRxFrameSize, portInfo->maxTxFrameSize);

    IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);

    return result;
}

/**
 * @brief sets the port maximum Rx frame size
 *
 * @param portID ID of the port to set the frame size on
 * @param maximumRxFrameSize maximum Rx frame size
 *
 * This function updates the internal data structures and
 * calls ixEthDBPortFrameLengthsUpdate() for NPE update.
 *
 * This function is fully documented in the main header
 * file, IxEthDB.h.
 *
 * @return IX_ETH_DB_SUCCESS if the operation was
 * successfull or an appropriate error message otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBFilteringPortMaximumRxFrameSizeSet(IxEthDBPortId portID, UINT32 maximumRxFrameSize)
{
    IX_ETH_DB_CHECK_PORT_EXISTS(portID);

    IX_ETH_DB_CHECK_SINGLE_NPE(portID);

	if (!ixEthDBPortInfo[portID].initialized)
	{
		return IX_ETH_DB_PORT_UNINITIALIZED;
	}

    if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
    {
	if ((maximumRxFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) ||
	    (maximumRxFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE))
	{
	    return IX_ETH_DB_INVALID_ARG;
	}
    }
    else
    {
        return IX_ETH_DB_NO_PERMISSION;
    }

    /* update internal structure */
    ixEthDBPortInfo[portID].maxRxFrameSize = maximumRxFrameSize;

    /* update the maximum frame size in the NPE */
    return ixEthDBPortFrameLengthsUpdate(portID);
}

/**
 * @brief sets the port maximum Tx frame size
 *
 * @param portID ID of the port to set the frame size on
 * @param maximumTxFrameSize maximum Tx frame size
 *
 * This function updates the internal data structures and
 * calls ixEthDBPortFrameLengthsUpdate() for NPE update.
 *
 * This function is fully documented in the main header
 * file, IxEthDB.h.
 *
 * @return IX_ETH_DB_SUCCESS if the operation was
 * successfull or an appropriate error message otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBFilteringPortMaximumTxFrameSizeSet(IxEthDBPortId portID, UINT32 maximumTxFrameSize)
{
    IX_ETH_DB_CHECK_PORT_EXISTS(portID);

    IX_ETH_DB_CHECK_SINGLE_NPE(portID);

	if (!ixEthDBPortInfo[portID].initialized)
	{
		return IX_ETH_DB_PORT_UNINITIALIZED;
	}

    if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
    {
	if ((maximumTxFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) ||
	    (maximumTxFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE))
	{
	    return IX_ETH_DB_INVALID_ARG;
	}
    }
    else
    {
        return IX_ETH_DB_NO_PERMISSION;
    }

    /* update internal structure */
    ixEthDBPortInfo[portID].maxTxFrameSize = maximumTxFrameSize;

    /* update the maximum frame size in the NPE */
    return ixEthDBPortFrameLengthsUpdate(portID);
}

/**
 * @brief sets the port maximum Tx and Rx frame sizes
 *
 * @param portID ID of the port to set the frame size on
 * @param maximumFrameSize maximum Tx and Rx frame sizes
 *
 * This function updates the internal data structures and
 * calls ixEthDBPortFrameLengthsUpdate() for NPE update.
 *
 * Note that both the maximum Tx and Rx frame size are set
 * to the same value. This function is kept for compatibility
 * reasons.
 *
 * This function is fully documented in the main header
 * file, IxEthDB.h.
 *
 * @return IX_ETH_DB_SUCCESS if the operation was
 * successfull or an appropriate error message otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBFilteringPortMaximumFrameSizeSet(IxEthDBPortId portID, UINT32 maximumFrameSize)
{
    IX_ETH_DB_CHECK_PORT_EXISTS(portID);

    IX_ETH_DB_CHECK_SINGLE_NPE(portID);

    if (!ixEthDBPortInfo[portID].initialized)
    {
        return IX_ETH_DB_PORT_UNINITIALIZED;
    }

    if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
    {
	if ((maximumFrameSize < IX_ETHDB_MIN_NPE_FRAME_SIZE) ||
	    (maximumFrameSize > IX_ETHDB_MAX_NPE_FRAME_SIZE))
	{
	    return IX_ETH_DB_INVALID_ARG;
	}
    }
    else
    {
        return IX_ETH_DB_NO_PERMISSION;
    }

    /* update internal structure */
    ixEthDBPortInfo[portID].maxRxFrameSize = maximumFrameSize;
    ixEthDBPortInfo[portID].maxTxFrameSize = maximumFrameSize;

    /* update the maximum frame size in the NPE */
    return ixEthDBPortFrameLengthsUpdate(portID);
}

/**
 * @brief sets the MAC address of an NPE port
 *
 * @param portID port ID to set the MAC address on
 * @param macAddr pointer to the 6-byte MAC address
 *
 * This function is called by the EthAcc
 * ixEthAccUnicastMacAddressSet() and should not be
 * manually invoked unless required by special circumstances.
 *
 * @return IX_ETH_DB_SUCCESS if the operation succeeded
 * or an appropriate error message otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBPortAddressSet(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
{
    IxNpeMhMessage message;
    IX_STATUS result;

    /* use this macro instead CHECK_PORT
       as the port doesn't need to be enabled */
    IX_ETH_DB_CHECK_PORT_EXISTS(portID);

    IX_ETH_DB_CHECK_REFERENCE(macAddr);

    if (!ixEthDBPortInfo[portID].initialized)
    {
        return IX_ETH_DB_PORT_UNINITIALIZED;
    }

    /* Operation stops here when Ethernet Learning is not enabled */
    if(IX_FEATURE_CTRL_SWCONFIG_DISABLED ==
       ixFeatureCtrlSwConfigurationCheck(IX_FEATURECTRL_ETH_LEARNING))
    {
        return IX_ETH_DB_SUCCESS;
    }

    IX_ETH_DB_CHECK_SINGLE_NPE(portID);

    /* exit if the port is not an Ethernet NPE */
    if (ixEthDBPortDefinitions[portID].type != IX_ETH_NPE)
    {
        return IX_ETH_DB_INVALID_PORT;
    }

    /* populate message */
    FILL_SETPORTADDRESS_MSG(message, portID, macAddr->macAddress);

    IX_ETH_DB_SUPPORT_TRACE("DB: (Support) Sending SetPortAddress on port %d...\n", portID);

    /* send a SetPortAddress message */
    IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);

    if (result == IX_SUCCESS)
    {
        ixEthDBPortInfo[portID].macAddressUploaded = true;
    }

    return result;
}
