#include <Copyright.h>
/********************************************************************************
* minizeCPUTraffic.c
*
* DESCRIPTION:
*        This sample shows how to setup the CPU port not to be a member of any
*        VLAN, while it still be a manager of a switch.
*
* DEPENDENCIES:
*        Please check the device's spec. if the device supports this feature.
*        At the moment this sample was written, 88E6095 was the only device support
*        this feature.
*
* FILE REVISION NUMBER:
*
* COMMENTS:
*******************************************************************************/

#include "msSample.h"

/*
    For the devices that support gsysSetARPDest API:

    0) Remove CPU port from VLAN Member Table.
       (this sample deals with Port Based Vlan only.)
    1) Mirror ARPs to the CPU with To_CPU Marvell Tag
    2) Convert unicast frames directed to the CPU into To_CPU Marvell Tag
    Assumption : Device ID, Cascading Port, CPU Port, and Interswitch Port are
        already set properly. For more information, please refer to the
        sample/MultiDevice/msApiInit.c
*/

GT_STATUS sampleMinimizeCPUTraffic1(GT_QD_DEV *dev, GT_U8* macAddr)
{
    GT_STATUS status;
    int i;
    GT_LPORT memPorts[16], cpuPort;
    GT_U8 memPortsLen, index;
    GT_ATU_ENTRY macEntry;

    cpuPort = (GT_LPORT)dev->cpuPortNum;

    /*
     *    Remove CPU port from VLAN Member Table.
    */
    for(i=0; i<dev->numOfPorts; i++)
    {
        if((status = gvlnGetPortVlanPorts(dev,(GT_LPORT)i,memPorts,&memPortsLen)) != GT_OK)
        {
            MSG_PRINT(("gvlnGetPortVlanPorts return Failed\n"));
            return status;
        }

        for(index=0; index<memPortsLen; index++)
        {
            if (memPorts[index] == cpuPort)
                break;
        }

        if(index != memPortsLen)
        {
            /* CPU Port is the member of the port vlan */
            if((memPortsLen-1) != index)
            {
                memPorts[index] = memPorts[memPortsLen-1];
            }
            memPortsLen--;

            if((status = gvlnSetPortVlanPorts(dev,(GT_LPORT)i,memPorts,memPortsLen)) != GT_OK)
            {
                MSG_PRINT(("gvlnSetPortVlanPorts return Failed\n"));
                return status;
            }
        }
    }

    /*
     *    Mirror ARPs to the CPU with To_CPU Marvell Tag.
    */
    if((status = gsysSetARPDest(dev,cpuPort)) != GT_OK)
    {
        MSG_PRINT(("gsysSetARPDest return Failed\n"));
        return status;
    }

    /*
     *    Convert unicast frames directed to the CPU into To_CPU Marvell Tag.
     *  This sample assumes that DBNum is not used. If DBNum is used,
     *  the macEntry has to be added for each DBNum used.
    */
    memset(&macEntry,0,sizeof(GT_ATU_ENTRY));
    memcpy(macEntry.macAddr.arEther,macAddr,6);
    macEntry.portVec = 1 << dev->cpuPortNum;
    macEntry.prio = 0;            /* Priority (2bits). When these bits are used they override
                                any other priority determined by the frame's data */
    macEntry.entryState.ucEntryState = GT_UC_TO_CPU_STATIC;
    macEntry.DBNum = 0;
    macEntry.trunkMember = GT_FALSE;

    if((status = gfdbAddMacEntry(dev,&macEntry)) != GT_OK)
    {
        MSG_PRINT(("gfdbAddMacEntry return Failed\n"));
        return status;
    }


    return GT_OK;
}


/*
    For the devices that support gprtSetARPtoCPU API:

    1) Enable ARP to CPU feature fore each port.
    2) Set Egress Flood Mode to be Block Unknown DA on CPU Port.
    3) Add CPU Port's MAC into address table.
    4) Remove Broadcast address from address table.
*/

GT_STATUS sampleMinimizeCPUTraffic2(GT_QD_DEV *dev, GT_U8* macAddr)
{
    GT_STATUS status;
    int i;
    GT_LPORT cpuPort;
    GT_ATU_ENTRY macEntry;

    cpuPort = (GT_LPORT)dev->cpuPortNum;

    /*
     *    Remove CPU port from VLAN Member Table.
    */
    for(i=0; i<dev->numOfPorts; i++)
    {
        if (i == cpuPort)
            continue;

        if((status = gprtSetARPtoCPU(dev,i,GT_TRUE)) != GT_OK)
        {
            MSG_PRINT(("gprtSetARPtoCPU return Failed\n"));
            return status;
        }
    }

    /*
     * Set Egress Flood Mode to be Block Unknown DA on CPU Port.
    */
    if((status = gprtSetEgressFlood(dev,cpuPort,GT_BLOCK_EGRESS_UNKNOWN)) != GT_OK)
    {
        MSG_PRINT(("gprtSetEgressFlood return Failed\n"));
        return status;
    }


    /*
     *    Add CPU's MAC into address table.
     *  This sample assumes that DBNum is not used. If DBNum is used,
     *  the macEntry has to be added for each DBNum used.
    */
    memset(&macEntry,0,sizeof(GT_ATU_ENTRY));
    memcpy(macEntry.macAddr.arEther,macAddr,6);
    macEntry.portVec = 1 << dev->cpuPortNum;
    macEntry.prio = 0;            /* Priority (2bits). When these bits are used they override
                                any other priority determined by the frame's data */
    macEntry.entryState.ucEntryState = GT_UC_STATIC;
    macEntry.DBNum = 0;
    macEntry.trunkMember = GT_FALSE;

    if((status = gfdbAddMacEntry(dev,&macEntry)) != GT_OK)
    {
        MSG_PRINT(("gfdbAddMacEntry return Failed\n"));
        return status;
    }

    /*
     *  Delete BroadCast Entry from address table if exists.
     *  This sample assumes that DBNum is not used. If DBNum is used,
     *  the macEntry has to be added for each DBNum used.
    */
    memset(&macEntry,0,sizeof(GT_ATU_ENTRY));
    memset(macEntry.macAddr.arEther,0xFF,6);
    gfdbDelAtuEntry(dev,&macEntry);

    return GT_OK;
}
