/**
 * @file IxEthDBAPI.c
 *
 * @brief Implementation of the public API
 * 
 * @par
 * IXP400 SW Release version 2.0
 * 
 * -- Copyright Notice --
 * 
 * @par
 * Copyright 2001-2005, Intel Corporation.
 * All rights reserved.
 * 
 * @par
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Intel Corporation nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 * 
 * @par
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * 
 * @par
 * -- End of Copyright Notice --
 */

#include "IxEthDB_p.h"

/* forward prototypes */
IX_ETH_DB_PUBLIC
MacTreeNode *ixEthDBGatewaySelect(MacTreeNode *stations);

/**
 * @brief sets the BBSID value for the WiFi header conversion feature
 *
 * @param portID ID of the port
 * @param bbsid pointer to the 6-byte BBSID value
 *
 * Note that this function is documented in the main component
 * header file, IxEthDB.h.
 *
 * @return IX_ETH_DB_SUCCESS if the operation completed successfully
 * or an appropriate error message otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBWiFiBBSIDSet(IxEthDBPortId portID, IxEthDBMacAddr *bbsid)
{
    IxNpeMhMessage message;
    IX_STATUS result;
    
    IX_ETH_DB_CHECK_PORT(portID);
    
    IX_ETH_DB_CHECK_SINGLE_NPE(portID);
    
    IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);
 
    IX_ETH_DB_CHECK_REFERENCE(bbsid);
    
    memcpy(ixEthDBPortInfo[portID].bbsid, bbsid, sizeof (IxEthDBMacAddr));

    FILL_SETBBSID_MSG(message, portID, bbsid);

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

/**
 * @brief updates the Frame Control and Duration/ID WiFi header
 * conversion parameters in an NPE
 *
 * @param portID ID of the port
 *
 * This function will send a message to the NPE updating the 
 * frame conversion parameters for 802.3 => 802.11 header conversion.
 *
 * @return IX_ETH_DB_SUCCESS if the operation completed successfully
 * or IX_ETH_DB_FAIL otherwise
 *
 * @internal
 */
IX_ETH_DB_PRIVATE
IxEthDBStatus ixEthDBWiFiFrameControlDurationIDUpdate(IxEthDBPortId portID)
{
    IxNpeMhMessage message;
    IX_STATUS result;

    FILL_SETFRAMECONTROLDURATIONID(message, portID, ixEthDBPortInfo[portID].frameControlDurationID);
    
    IX_ETHDB_SEND_NPE_MSG(IX_ETH_DB_PORT_ID_TO_NPE(portID), message, result);
    
    return result;
}

/**
 * @brief sets the Duration/ID WiFi frame header conversion parameter
 *
 * @param portID ID of the port
 * @param durationID 16-bit value containing the new Duration/ID parameter
 *
 * Note that this function is documented in the main component
 * header file, IxEthDB.h.
 *
 * @return IX_ETH_DB_SUCCESS if the operation completed successfully
 * or an appropriate error message otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBWiFiDurationIDSet(IxEthDBPortId portID, UINT16 durationID)
{
    IX_ETH_DB_CHECK_PORT(portID);
    
    IX_ETH_DB_CHECK_SINGLE_NPE(portID);
    
    IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);

    ixEthDBPortInfo[portID].frameControlDurationID = (ixEthDBPortInfo[portID].frameControlDurationID & 0xFFFF0000) | durationID;
    
    return ixEthDBWiFiFrameControlDurationIDUpdate(portID);
}

/**
 * @brief sets the Frame Control WiFi frame header conversion parameter
 *
 * @param portID ID of the port
 * @param durationID 16-bit value containing the new Frame Control parameter
 *
 * Note that this function is documented in the main component
 * header file, IxEthDB.h.
 *
 * @return IX_ETH_DB_SUCCESS if the operation completed successfully
 * or an appropriate error message otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBWiFiFrameControlSet(IxEthDBPortId portID, UINT16 frameControl)
{
    IX_ETH_DB_CHECK_PORT(portID);
    
    IX_ETH_DB_CHECK_SINGLE_NPE(portID);
    
    IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);

    ixEthDBPortInfo[portID].frameControlDurationID = (ixEthDBPortInfo[portID].frameControlDurationID & 0xFFFF) | (frameControl << 16); 
    
    return ixEthDBWiFiFrameControlDurationIDUpdate(portID);
}

/**
 * @brief removes a WiFi header conversion record
 *
 * @param portID ID of the port
 * @param macAddr MAC address of the record to remove
 *
 * Note that this function is documented in the main
 * component header file, IxEthDB.h.
 *
 * @return IX_ETH_DB_SUCCESS if the operation completed
 * successfully or an appropriate error message otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBWiFiEntryRemove(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
{
    MacDescriptor recordTemplate;
    
    IX_ETH_DB_CHECK_PORT(portID);
    
    IX_ETH_DB_CHECK_SINGLE_NPE(portID);
    
    IX_ETH_DB_CHECK_REFERENCE(macAddr);
    
    IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);
    
    memcpy(recordTemplate.macAddress, macAddr, sizeof (IxEthDBMacAddr));
    
    recordTemplate.type   = IX_ETH_DB_WIFI_RECORD;
    recordTemplate.portID = portID;
    
    return ixEthDBRemove(&recordTemplate, NULL);
}

/**
 * @brief adds a WiFi header conversion record
 *
 * @param portID ID of the port
 * @param macAddr MAC address of the record to add
 * @param gatewayMacAddr address of the gateway (or
 * NULL if this is a station record)
 *
 * This function adds a record of type AP_TO_AP (gateway is not NULL)
 * or AP_TO_STA (gateway is NULL) in the main database as a 
 * WiFi header conversion record.
 *
 * @return IX_ETH_DB_SUCCESS if the operation completed
 * successfully or an appropriate error message otherwise
 *
 * @internal
 */
IX_ETH_DB_PRIVATE
IxEthDBStatus ixEthDBWiFiEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr, IxEthDBMacAddr *gatewayMacAddr)
{
    MacDescriptor recordTemplate;

    IX_ETH_DB_CHECK_PORT(portID);

    IX_ETH_DB_CHECK_SINGLE_NPE(portID);

    IX_ETH_DB_CHECK_REFERENCE(macAddr);
    
    IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);

    memcpy(recordTemplate.macAddress, macAddr, sizeof (IxEthDBMacAddr));
    
    recordTemplate.type   = IX_ETH_DB_WIFI_RECORD;
    recordTemplate.portID = portID;
    
    if (gatewayMacAddr != NULL)
    {
        memcpy(recordTemplate.recordData.wifiData.gwMacAddress, gatewayMacAddr, sizeof (IxEthDBMacAddr));
        
        recordTemplate.recordData.wifiData.type = IX_ETH_DB_WIFI_AP_TO_AP;
    }
    else
    {
        memset(recordTemplate.recordData.wifiData.gwMacAddress, 0, sizeof (IxEthDBMacAddr));

        recordTemplate.recordData.wifiData.type = IX_ETH_DB_WIFI_AP_TO_STA;
    }
    
    return ixEthDBAdd(&recordTemplate, NULL);
}

/**
 * @brief adds a WiFi header conversion record
 *
 * @param portID ID of the port
 * @param macAddr MAC address of the record to add
 * @param gatewayMacAddr address of the gateway 
 *
 * This function adds a record of type AP_TO_AP
 * in the main database as a WiFi header conversion record.
 *
 * This is simply a wrapper over @ref ixEthDBWiFiEntryAdd().
 *
 * Note that this function is documented in the main
 * component header file, IxEthDB.h.
 *
 * @return IX_ETH_DB_SUCCESS if the operation completed
 * successfully or an appropriate error message otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBWiFiAccessPointEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr, IxEthDBMacAddr *gatewayMacAddr)
{
    IX_ETH_DB_CHECK_REFERENCE(gatewayMacAddr);

    return ixEthDBWiFiEntryAdd(portID, macAddr, gatewayMacAddr);
}

/**
 * @brief adds a WiFi header conversion record
 *
 * @param portID ID of the port
 * @param macAddr MAC address of the record to add
 *
 * This function adds a record of type AP_TO_STA
 * in the main database as a WiFi header conversion record.
 *
 * This is simply a wrapper over @ref ixEthDBWiFiEntryAdd().
 *
 * Note that this function is documented in the main
 * component header file, IxEthDB.h.
 *
 * @return IX_ETH_DB_SUCCESS if the operation completed
 * successfully or an appropriate error message otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBWiFiStationEntryAdd(IxEthDBPortId portID, IxEthDBMacAddr *macAddr)
{
    return ixEthDBWiFiEntryAdd(portID, macAddr, NULL);
}

/**
 * @brief selects a set of gateways from a tree of 
 * WiFi header conversion records
 *
 * @param stations binary tree containing pointers to WiFi header
 * conversion records
 *
 * This function browses through the input binary tree, identifies
 * records of type AP_TO_AP, clones these records and appends them
 * to a vine (a single right-branch binary tree) which is returned
 * as result. A maximum of MAX_GW_SIZE entries containing gateways
 * will be cloned from the original tree.
 *
 * @return vine (linear binary tree) containing record
 * clones of AP_TO_AP type, which have a gateway field
 *
 * @internal
 */
IX_ETH_DB_PUBLIC
MacTreeNode *ixEthDBGatewaySelect(MacTreeNode *stations)
{
    MacTreeNodeStack *stack;
    MacTreeNode *gateways, *insertionPlace;
    UINT32 gwIndex = 1; /* skip the empty root */
    
    if (stations == NULL)
    {
        return NULL;
    }

    stack = ixOsalCacheDmaMalloc(sizeof (MacTreeNodeStack));

    if (stack == NULL)
    {
        ERROR_LOG("DB: (WiFi) failed to allocate the node stack for gateway tree linearization, out of memory?\n");
        return NULL;
    }
    
    /* initialize root node */
    gateways = insertionPlace = NULL;
        
    /* start browsing the station tree */
    NODE_STACK_INIT(stack);
    
    /* initialize stack by pushing the tree root at offset 0 */
    NODE_STACK_PUSH(stack, stations, 0);
    
    while (NODE_STACK_NONEMPTY(stack))
    {
        MacTreeNode *node;
        UINT32 offset;
       
        NODE_STACK_POP(stack, node, offset);

        /* we can store maximum 31 (32 total, 1 empty root) entries in the gateway tree */
        if (offset > (MAX_GW_SIZE - 1)) break;
        
        /* check if this record has a gateway address */
        if (node->descriptor != NULL && node->descriptor->recordData.wifiData.type == IX_ETH_DB_WIFI_AP_TO_AP)
        {
            /* found a record, create an insertion place */
            if (insertionPlace != NULL)
            {
                insertionPlace->right = ixEthDBAllocMacTreeNode();
                insertionPlace        = insertionPlace->right;
            }
            else
            {
                gateways       = ixEthDBAllocMacTreeNode();
                insertionPlace = gateways;
            }

            if (insertionPlace == NULL)
            {
                /* no nodes left, bail out with what we have */
                ixOsalCacheDmaFree(stack);
                return gateways;
            }
            
            /* clone the original record for the gateway tree */
            insertionPlace->descriptor = ixEthDBCloneMacDescriptor(node->descriptor);
            
            /* insert and update the offset in the original record */
            node->descriptor->recordData.wifiData.gwAddressIndex = gwIndex++;
        }
        
        /* browse the tree */
        if (node->left != NULL)
        {
            NODE_STACK_PUSH(stack, node->left, LEFT_CHILD_OFFSET(offset));
        }

        if (node->right != NULL)
        {
            NODE_STACK_PUSH(stack, node->right, RIGHT_CHILD_OFFSET(offset));
        }
    }
    
    ixOsalCacheDmaFree(stack);
    return gateways;    
}

/**
 * @brief downloads the WiFi header conversion table to an NPE
 *
 * @param portID ID of the port
 *
 * This function prepares the WiFi header conversion tables and
 * downloads them to the specified NPE port.
 *
 * The header conversion tables consist in the main table of
 * addresses and the secondary table of gateways. AP_TO_AP records
 * from the first table contain index fields into the second table
 * for gateway selection.
 *
 * Note that this function is documented in the main component
 * header file, IxEthDB.h.
 *
 * @return IX_ETH_DB_SUCCESS if the operation completed successfully
 * or an appropriate error message otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBWiFiConversionTableDownload(IxEthDBPortId portID)
{
    IxEthDBPortMap query;
    MacTreeNode *stations = NULL, *gateways = NULL, *gateway = NULL;
    IxNpeMhMessage message;
    PortInfo *portInfo;
    IX_STATUS result;

    IX_ETH_DB_CHECK_PORT(portID);

    IX_ETH_DB_CHECK_SINGLE_NPE(portID);
    
    IX_ETH_DB_CHECK_FEATURE(portID, IX_ETH_DB_WIFI_HEADER_CONVERSION);

    portInfo = &ixEthDBPortInfo[portID];
   
    SET_DEPENDENCY_MAP(query, portID);
    
    ixEthDBUpdateLock();

    stations = ixEthDBQuery(NULL, query, IX_ETH_DB_WIFI_RECORD, MAX_ELT_SIZE);
    gateways = ixEthDBGatewaySelect(stations);
    
    /* clean up gw area */
    memset((void *) portInfo->updateMethod.npeGwUpdateZone, FULL_GW_BYTE_SIZE, 0);

    /* write all gateways */
    gateway = gateways;

    while (gateway != NULL)
    {
        ixEthDBNPEGatewayNodeWrite((void *) (((UINT32) portInfo->updateMethod.npeGwUpdateZone) 
            + gateway->descriptor->recordData.wifiData.gwAddressIndex * ELT_ENTRY_SIZE), 
            gateway);

        gateway = gateway->right;
    }

    /* free the gateway tree */
    if (gateways != NULL)
    {
        ixEthDBFreeMacTreeNode(gateways);
    }

    FILL_SETAPMACTABLE_MSG(message, 
        IX_OSAL_MMU_VIRT_TO_PHYS(portInfo->updateMethod.npeGwUpdateZone));

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

    if (result == IX_SUCCESS)
    {
        /* update the main tree (the stations tree) */
        portInfo->updateMethod.searchTree = stations;
        
        result = ixEthDBNPEUpdateHandler(portID, IX_ETH_DB_WIFI_RECORD);
    }

    ixEthDBUpdateUnlock();

    return result;
}
