This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[FAQ] TDA4VM: How to Configure CPSW 5G/9G ALE

Part Number: TDA4VM

How to configure CPSW 5G/9G to add static entries ?

  • About

    ALE stands for Address Lookup Engine and it is a module inside CPSW 5G/9G module which is used to implement features specified in IEEE 802.1 Q protocol like VLAN tagging, Learning, Forwarding, Filtering, Rate control, Mirroring etc. (A full list is beyond the scope of this guide). It is how the switch knows which packets are to be forwarded to which ports. Details about the module are described in Section 12.2.2.4.6.1 of TRM.

    Programmers can use the features of ALE to setup complicated rules to:

    1. Filter packets based on VLAN, Ethernet Type, Source MAC, Destination MAC, IP address etc (For a full list please see TRM and API Guide)
    2. Set up forwarding rules between ports (re-direct traffic)
    3. Perform rate limitation
    4. Implement Automotive security features such as
      1. Disallow IP fragmentation
      2. Drop invalid SA
      3. Setup black lists based on SA or DA
    5. Combine various features to setup complicated rules for forwarding/policing

    This guide will first explain the basics of Forwarding without re-iterating what is already covered in TRM and User Guide and then explain key use-cases with examples.

    NOTE : There are a lot of ALE features and not everything will be covered here, readers are expected to use this as a foundation and go through the TRM and API Guide

    Ingress and Forwarding

    When a packet is received it goes through three stages, this is part of IEEE 802.3 Q protocol and not specific to the HW

    1. Ingress Filtering : Port State check for Unicast and Multicast frames
    2. VLAN Aware Lookup Process : Check whether the port is part of VLAN group, whether VLAN entry exists in table etc
    3. Egress Process : Egress Port states are checked

    If the 3 checks pass, then the packet is forwarded to the respective port (Host or Physical ports), else it gets dropped. See below:

    For the CPSW IP, Host port can mean any of the cores in the SoC, either the Main R5F 2_0 which is running the Ethernet Firmware or any of the remote cores (A72, MCU R5F) which are running virtual clients. The destination is decided based on the Flow ID (Unique DMA ID) and CoreID (Unique ID for each core).

    Without getting too much into concepts of Flow ID and Core ID it's enough to understand that they are required to tie any data flow to a particular core for the DMA and it is how packets are routed by CPSW within the SoC.

    For this reason, whenever a rule is created in CPSW ALE to forward packets to Host Port it must also be tied to the relevant Core and Flow ID. This part is handled by the API's provided by ENET-LLD as we will later see with examples.

    To know more about Flow ID's, please read the NAVSS Functional Description (Section 10.2.1.3) in TRM.

    NOTE : Currently a packet can only be sent to one core as driver does not handle duplication. This is an issue for Multicast/Broadcast frames as multiple cores can subscribe to these frames, there is currently no workaround for this. So for example both Main R5F and A72 cannot receive broadcast frames but either one of them can.

    This feature will be implemented in SDK 8.1 (Nov 2021)

    Parts of ALE

    Port State/Rules

    Each Port has the following states as per IEEE 802.1 Q

    1. Disabled
    2. Forwarding
    3. Learning
    4. Blocked

    They can be configured using the IOCTL 'CPSW_ALE_IOCTL_SET_PORT_STATE'  ,the corresponding HW register for this is 'CPSW_Iy_ALE_PORTCTL0_y'  and the corresponding field Iy_REG_Py_PORTSTATE

    In addition to port states, one can also set rules like Drop Untagged, Trunk Enable, MAC Only etc. See the TRM and API Guide for more details

    Tables

    The ALE has multiple tables

    1. VLAN Tables : Inner and Outer
    2. EtherType Table Entry
    3. IPv4 Table
    4. IPv6 Table

    Right now, we will just focus on VLAN tables

    There are two VLAN Tables, Inner VLAN Table and Outer VLAN Table. They are identical in all respects and the two of them are used to implement dual tagging (Q in Q) feature. For single VLAN tag, users must only use Inner VLAN Table. To create a VLAN based FDB rule, users must first create a corresponding VLAN entry in the Inner VLAN Table.

    The IOCTL to add a VLAN entry is 'CPSW_ALE_IOCTL_ADD_VLAN' and the IOCTL to delete is 'CPSW_ALE_IOCTL_REMOVE_VLAN'

    The entries for VLAN table are shown below:

    FDB Entries

    The FDB entries are of four types (classified by ENTRY_TYPE[0:1] field)

    1. Empty
    2. Address Based Entry : Unicast/Multicast
    3. VLAN Entry
    4. Unicast/Multicast with VLAN

    See below:

    Multicast/Unicast without VLAN

    VLAN/Unicast Entry

    Classifier and Policing

    Classifiers are used to create rules using Multicast/Unicast entries, VLAN and other Table entries. They are applied per port and can be configured to look for one or multiple conditions. For example a classifier can match for a particular VLAN or DA or both.

    Use-Case with Examples

    There is currently no support to add an entry dynamically to the ALE from the remote cores (A72, MCU R5F) so one must add the entry in Ethernet Firmware and compile it before hand. This is done by adding a callback function to the MAC callback handler CpswProxyServer_registerMacHandlerCb() which adds a static configuration.

    See flow-chart below:

    Adding a multicast entry for A72

    See this reference patch for Ethernet Firmware (On top of SDK 7.3) for adding a static Multicast entry for A72 core

    static_multicast_config_patch.txt
    From 4850b72c76d1bfc1ed88b8633b9266bd32275edc Mon Sep 17 00:00:00 2001
    From: Vineet Roy <vroy@ti.com>
    Date: Thu, 17 Jun 2021 23:32:12 +0530
    Subject: [PATCH 1/4] Static Multicast configuration for Linux
    
    ---
     .../mcu_2_0/main_tirtos.c                     | 172 ++++++++++++++++++
     ethfw/ethfw.h                                 |  35 ++++
     ethfw/src/ethfw.c                             |  18 ++
     .../server/include/cpsw_proxy_server.h        |  34 ++++
     ethremotecfg/server/src/cpsw_proxy_server.c   |  46 +++++
     5 files changed, 305 insertions(+)
    
    diff --git a/apps/app_remoteswitchcfg_server/mcu_2_0/main_tirtos.c b/apps/app_remoteswitchcfg_server/mcu_2_0/main_tirtos.c
    index 74cc0df..304d560 100644
    --- a/apps/app_remoteswitchcfg_server/mcu_2_0/main_tirtos.c
    +++ b/apps/app_remoteswitchcfg_server/mcu_2_0/main_tirtos.c
    @@ -207,6 +207,14 @@ static void EthApp_startSwInterVlan(char *recvBuff,
     static void EthApp_startHwInterVlan(char *recvBuff,
                                         char *sendBuff);
     
    +static int32_t EthApp_addRemoteCoreStaticCfg(Enet_Handle hEnet,
    +                                             uint32_t coreId,
    +                                             uint32_t flowId);
    +
    +static void EthApp_delRemoteCoreStaticCfg(Enet_Handle hEnet,
    +                                          uint32_t coreId,
    +                                          uint32_t flowId);
    +
     /* ========================================================================== */
     /*                          Extern variables                                  */
     /* ========================================================================== */
    @@ -563,6 +571,11 @@ static int32_t EthApp_initEthFw(void)
                                          ethFwCfg.ports[i].portNum);
         }
     
    +    /* Set static configuration functions */
    +    ethFwCfg.addStaticCfg = &EthApp_addRemoteCoreStaticCfg;
    +    ethFwCfg.delStaticCfg = &EthApp_delRemoteCoreStaticCfg;
    +
    +
         /* Initialize the EthFw */
         gEthAppObj.hEthFw = EthFw_init(gEthAppObj.enetType, &ethFwCfg);
         if (gEthAppObj.hEthFw == NULL)
    @@ -815,3 +828,162 @@ void EthApp_traceBufCacheWb(void)
             }
         }
     }
    +
    +
    +static int32_t EthApp_addMpu10StaticCfg(Enet_Handle hEnet,
    +                                        uint32_t coreId,
    +                                        uint32_t flowId)
    +{
    +    const uint8_t mcastAddr[ENET_MAC_ADDR_LEN] = {0x01, 0x99, 0xc2, 0x00, 0x01, 0x0E};
    +    CpswAle_SetPolicerEntryInArgs polInArgs;
    +    CpswAle_SetPolicerEntryOutArgs polOutArgs;
    +    CpswAle_SetMcastEntryInArgs mcastInArgs;
    +    Enet_IoctlPrms prms;
    +    uint32_t entry;
    +    int32_t status;
    +
    +    polInArgs.policerMatch.policerMatchEnMask = 0U;
    +
    +    /* Add policer entry for port 1 and dstmac */
    +    polInArgs.policerMatch.policerMatchEnMask = CPSW_ALE_POLICER_MATCH_PORT;
    +    polInArgs.policerMatch.portNum = CPSW_ALE_MACPORT_TO_ALEPORT(ENET_MAC_PORT_1);
    +    polInArgs.policerMatch.portIsTrunk = false;
    +
    +    polInArgs.policerMatch.policerMatchEnMask |= CPSW_ALE_POLICER_MATCH_MACDST;
    +    polInArgs.policerMatch.dstMacAddrInfo.portNum = CPSW_ALE_HOST_PORT_NUM;
    +    polInArgs.policerMatch.dstMacAddrInfo.addr.vlanId = 0U;
    +    EnetUtils_copyMacAddr(&polInArgs.policerMatch.dstMacAddrInfo.addr.addr[0], &mcastAddr[0]);
    +
    +    polInArgs.threadIdEn = true;
    +    polInArgs.threadId   = flowId;
    +    polInArgs.peakRateInBitsPerSec   = 0U;
    +    polInArgs.commitRateInBitsPerSec = 0U;
    +
    +    ENET_IOCTL_SET_INOUT_ARGS(&prms, &polInArgs, &polOutArgs);
    +
    +    status = Enet_ioctl(hEnet, gEthAppObj.coreId, CPSW_ALE_IOCTL_SET_POLICER, &prms);
    +    if (status != ENET_SOK)
    +    {
    +        appLogPrintf("Failed to register PORT1 | MACDST policer: %d\n", status);
    +    }
    +
    +    /* Add policer entry for port 3 and dstmac */
    +    if (status == ENET_SOK)
    +    {
    +        polInArgs.policerMatch.portNum = CPSW_ALE_MACPORT_TO_ALEPORT(ENET_MAC_PORT_3);
    +
    +        ENET_IOCTL_SET_INOUT_ARGS(&prms, &polInArgs, &polOutArgs);
    +
    +        status = Enet_ioctl(hEnet, gEthAppObj.coreId, CPSW_ALE_IOCTL_SET_POLICER, &prms);
    +        if (status != ENET_SOK)
    +        {
    +            appLogPrintf("Failed to register PORT3 | MACDST policer: %d\n", status);
    +        }
    +    }
    +
    +    /* Add multicast entry with port mask: host port, MAC port 1 and MAC port 3 */
    +    if (status == ENET_SOK)
    +    {
    +        mcastInArgs.addr.vlanId = 0U;
    +        EnetUtils_copyMacAddr(&mcastInArgs.addr.addr[0], &mcastAddr[0]);
    +
    +        mcastInArgs.info.super    = false;
    +        mcastInArgs.info.fwdState = CPSW_ALE_FWDSTLVL_FWD;
    +        mcastInArgs.info.portMask = (CPSW_ALE_HOST_PORT_MASK |
    +                                     CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_1) |
    +                                     CPSW_ALE_MACPORT_TO_PORTMASK(ENET_MAC_PORT_3));
    +        mcastInArgs.info.numIgnBits = 0U;
    +
    +        ENET_IOCTL_SET_INOUT_ARGS(&prms, &mcastInArgs, &entry);
    +
    +        status = Enet_ioctl(hEnet, gEthAppObj.coreId, CPSW_ALE_IOCTL_ADD_MCAST, &prms);
    +        if (status != ENET_SOK)
    +        {
    +            appLogPrintf("Failed to add mcast ports: %d\n", status);
    +        }
    +    }
    +
    +    return status;
    +}
    +
    +static void EthApp_delMpu10StaticCfg(Enet_Handle hEnet,
    +                                     uint32_t coreId,
    +                                     uint32_t flowId)
    +{
    +    const uint8_t mcastAddr[ENET_MAC_ADDR_LEN] = {0x01, 0x80, 0xc2, 0x00, 0x01, 0x0E};
    +    CpswAle_DelPolicerEntryInArgs polInArgs;
    +    Enet_IoctlPrms prms;
    +    int32_t status;
    +
    +    polInArgs.policerMatch.policerMatchEnMask = 0U;
    +
    +    /* Delete policer entry for port 1 and dstmac */
    +    polInArgs.policerMatch.policerMatchEnMask = CPSW_ALE_POLICER_MATCH_PORT;
    +    polInArgs.policerMatch.portNum = CPSW_ALE_MACPORT_TO_ALEPORT(ENET_MAC_PORT_1);
    +    polInArgs.policerMatch.portIsTrunk = false;
    +
    +    polInArgs.policerMatch.policerMatchEnMask |= CPSW_ALE_POLICER_MATCH_MACDST;
    +    polInArgs.policerMatch.dstMacAddrInfo.portNum = CPSW_ALE_HOST_PORT_NUM;
    +    polInArgs.policerMatch.dstMacAddrInfo.addr.vlanId = 0U;
    +    EnetUtils_copyMacAddr(&polInArgs.policerMatch.dstMacAddrInfo.addr.addr[0], &mcastAddr[0]);
    +
    +    polInArgs.aleEntryMask = CPSW_ALE_POLICER_MATCH_PORT;
    +
    +    ENET_IOCTL_SET_IN_ARGS(&prms, &polInArgs);
    +
    +    status = Enet_ioctl(hEnet, gEthAppObj.coreId, CPSW_ALE_IOCTL_DEL_POLICER, &prms);
    +    if (status != ENET_SOK)
    +    {
    +        appLogPrintf("Failed to delete PORT1 | MACDST policer: %d\n", status);
    +    }
    +
    +    /* Delete policer entry for port 3 and dstmac */
    +    if (status == ENET_SOK)
    +    {
    +        polInArgs.policerMatch.portNum = CPSW_ALE_MACPORT_TO_ALEPORT(ENET_MAC_PORT_3);
    +
    +        ENET_IOCTL_SET_IN_ARGS(&prms, &polInArgs);
    +
    +        status = Enet_ioctl(hEnet, gEthAppObj.coreId, CPSW_ALE_IOCTL_DEL_POLICER, &prms);
    +        if (status != ENET_SOK)
    +        {
    +            appLogPrintf("Failed to delete PORT3 | MACDST policer: %d\n", status);
    +        }
    +    }
    +}
    +
    +static int32_t EthApp_addRemoteCoreStaticCfg(Enet_Handle hEnet,
    +                                             uint32_t coreId,
    +                                             uint32_t flowId)
    +{
    +    int32_t status = ENET_SOK;
    +
    +    switch (coreId)
    +    {
    +        case IPC_MPU1_0:
    +            appLogPrintf("Add static config for mpu1_0\n");
    +            status = EthApp_addMpu10StaticCfg(hEnet, coreId, flowId);
    +            break;
    +
    +        default:
    +            break;
    +    }
    +
    +    return status;
    +}
    +
    +static void EthApp_delRemoteCoreStaticCfg(Enet_Handle hEnet,
    +                                          uint32_t coreId,
    +                                          uint32_t flowId)
    +{
    +    switch (coreId)
    +    {
    +        case IPC_MPU1_0:
    +            appLogPrintf("Delete static config for mpu1_0\n");
    +            EthApp_delMpu10StaticCfg(hEnet, coreId, flowId);
    +            break;
    +
    +        default:
    +            break;
    +    }
    +}
    diff --git a/ethfw/ethfw.h b/ethfw/ethfw.h
    index ef4a8c9..cafab00 100644
    --- a/ethfw/ethfw.h
    +++ b/ethfw/ethfw.h
    @@ -178,6 +178,35 @@ typedef struct EthFw_PortConfig_s
         EnetPort_VlanCfg vlanCfg;
     } EthFw_Port;
     
    +/*!
    + * \brief Add static configuration.
    + *
    + * Add static configuration that is applicable only to specific remote cores.
    + *
    + * \param hEnet        Handle to Enet LLD
    + * \param coreId       Remote core's IPC core id
    + * \param flowId       Remote core's flow id
    + *
    + * \return 0 if no error. Negative value otherwise.
    + */
    +typedef int32_t (*EthFw_addStaticCfg)(Enet_Handle hEnet,
    +                                      uint32_t coreId,
    +                                      uint32_t flowId);
    +
    +/*!
    + * \brief Delete static configuration.
    + *
    + * Delete static configuration that is applicable only to specific remote cores.
    + *
    + * \param hEnet        Handle to Enet LLD
    + * \param coreId       Remote core's IPC core id
    + * \param flowId       Remote core's flow id
    + */
    +typedef void (*EthFw_delStaticCfg)(Enet_Handle hEnet,
    +                                   uint32_t coreId,
    +                                   uint32_t flowId);
    +
    +
     /*!
      * \brief Ethernet Firmware configuration
      *
    @@ -195,6 +224,12 @@ typedef struct EthFw_Config_s
         /*! Number of MAC ports owned by EthFw, that is, the size of
          *  EthFw_Config::ports array */
         uint32_t numPorts;
    +
    +    /* Add static configuration that is applicable only to specific remote cores */
    +    EthFw_addStaticCfg addStaticCfg;
    +
    +    /* Delete static configuration that is applicable only to specific remote cores */
    +    EthFw_delStaticCfg delStaticCfg;
     } EthFw_Config;
     
     /*!
    diff --git a/ethfw/src/ethfw.c b/ethfw/src/ethfw.c
    index f8eeb7e..e12e425 100644
    --- a/ethfw/src/ethfw.c
    +++ b/ethfw/src/ethfw.c
    @@ -182,6 +182,12 @@ typedef struct EthFw_Obj_s
         /* Handle to PTP stack */
         TimeSyncPtp_Handle timeSyncPtp;
     
    +    /* Add static configuration that is applicable only to specific remote cores */
    +    EthFw_addStaticCfg addStaticCfg;
    +
    +    /* Delete static configuration that is applicable only to specific remote cores */
    +    EthFw_delStaticCfg delStaticCfg;
    +
     } EthFw_Obj;
     
     /* ========================================================================== */
    @@ -268,6 +274,10 @@ void EthFw_initConfigParams(Enet_Type enetType,
         CpswHostPort_Cfg *hostPortCfg = &cpswCfg->hostPortCfg;
         EnetRm_ResCfg *resCfg = &cpswCfg->resCfg;
     
    +    /* Initialize Static config function pointers */
    +    config->addStaticCfg = NULL;
    +    config->delStaticCfg = NULL;
    +
         /* MAC port ownership */
         config->ports = NULL;
         config->numPorts = 0U;
    @@ -306,6 +316,10 @@ EthFw_Handle EthFw_init(Enet_Type enetType,
     
         memset(&gEthFwObj, 0, sizeof(gEthFwObj));
     
    +    /* Save static config function pointers */
    +    gEthFwObj.addStaticCfg = config->addStaticCfg;
    +    gEthFwObj.delStaticCfg = config->delStaticCfg;
    +
         /* Save config parameters */
         gEthFwObj.cpswCfg = config->cpswCfg;
         gEthFwObj.numPorts = config->numPorts;
    @@ -419,6 +433,10 @@ int32_t EthFw_initRemoteConfig(EthFw_Handle hEthFw)
         cfg.notifyServiceRemoteCoreId[0] = IPC_MPU1_0;
         cfg.notifyServiceRemoteCoreId[1] = IPC_MCU2_1;
     
    +    /* Static configuration callbacks */
    +    cfg.addStaticCfg = gEthFwObj.addStaticCfg;
    +    cfg.delStaticCfg = gEthFwObj.delStaticCfg;
    +
         status = CpswProxyServer_init(&cfg);
         if (status != ENET_SOK)
         {
    diff --git a/ethremotecfg/server/include/cpsw_proxy_server.h b/ethremotecfg/server/include/cpsw_proxy_server.h
    index c1acfa9..23098f1 100644
    --- a/ethremotecfg/server/include/cpsw_proxy_server.h
    +++ b/ethremotecfg/server/include/cpsw_proxy_server.h
    @@ -162,6 +162,34 @@ typedef struct CpswProxyServer_RemoteCoreConfig_s
         char     serverName[ETHREMOTECFG_SERVER_MAX_NAME_LEN];
     } CpswProxyServer_RemoteCoreConfig;
     
    +/*!
    + * \brief Add static configuration.
    + *
    + * Add static configuration that is applicable only to specific remote cores.
    + *
    + * \param hEnet        Handle to Enet LLD
    + * \param coreId       Remote core's IPC core id
    + * \param flowId       Remote core's flow id
    + *
    + * \return 0 if no error. Negative value otherwise.
    + */
    +typedef int32_t (*CpswProxyServer_addStaticCfg)(Enet_Handle hEnet,
    +                                                uint32_t coreId,
    +                                                uint32_t flowId);
    +
    +/*!
    + * \brief Delete static configuration.
    + *
    + * Delete static configuration that is applicable only to specific remote cores.
    + *
    + * \param hEnet        Handle to Enet LLD
    + * \param coreId       Remote core's IPC core id
    + * \param flowId       Remote core's flow id
    + */
    +typedef void (*CpswProxyServer_delStaticCfg)(Enet_Handle hEnet,
    +                                             uint32_t coreId,
    +                                             uint32_t flowId);
    +
     /*!
      * \brief Cpsw Proxy Server Remote Configuration structure
      *
    @@ -199,6 +227,12 @@ typedef struct CpswProxyServer_Config_s
     
         /*! Remote Core configuration */
         CpswProxyServer_RemoteCoreConfig remoteCoreCfg[ETHREMOTECFG_SERVER_MAX_INSTANCES];
    +
    +    /* Add static configuration that is applicable only to specific remote cores */
    +    CpswProxyServer_addStaticCfg addStaticCfg;
    +
    +    /* Delete static configuration that is applicable only to specific remote cores */
    +    CpswProxyServer_delStaticCfg delStaticCfg;
     } CpswProxyServer_Config_t;
     
     /*!
    diff --git a/ethremotecfg/server/src/cpsw_proxy_server.c b/ethremotecfg/server/src/cpsw_proxy_server.c
    index 4c01eaa..295b781 100644
    --- a/ethremotecfg/server/src/cpsw_proxy_server.c
    +++ b/ethremotecfg/server/src/cpsw_proxy_server.c
    @@ -184,6 +184,12 @@ typedef struct CpswProxyServer_Obj_s
         SemaphoreP_Handle                     rdevStartSem;
         CpswProxyServer_EthDriverObj          ethDrvObj;
         CpswProxyServer_NotifyServiceObj      notifyServiceObj;
    +
    +    /* Add static configuration that is applicable only to specific remote cores */
    +    CpswProxyServer_addStaticCfg addStaticCfg;
    +
    +    /* Delete static configuration that is applicable only to specific remote cores */
    +    CpswProxyServer_delStaticCfg delStaticCfg;
     } CpswProxyServer_Obj;
     
     /* ========================================================================== */
    @@ -592,10 +598,13 @@ static int32_t CpswProxyServer_registerMacHandlerCb(uint32_t host_id,
                                                         u8 *mac_address,
                                                         uint32_t flow_idx)
     {
    +    CpswProxyServer_Obj *hProxyServer;
         int32_t status;
         Enet_Handle hEnet = (Enet_Handle)((uintptr_t)handle);
         uint32_t start_flow_idx, flow_idx_offset;
     
    +    hProxyServer = CpswProxyServer_getHandle();
    +
         CpswProxyServer_validateHandle(hEnet);
         EnetAppUtils_absFlowIdx2FlowIdxOffset(hEnet, host_id, flow_idx, &start_flow_idx, &flow_idx_offset);
         appLogPrintf("Function:%s,HostId:%u,Handle:%p,CoreKey:%x, MacAddress:%x:%x:%x:%x:%x:%x, FlowIdx:%u, FlowIdxOffset:%u\n",
    @@ -618,6 +627,23 @@ static int32_t CpswProxyServer_registerMacHandlerCb(uint32_t host_id,
             appLogPrintf("EnetAppUtils_regDstMacRxFlow() failed CPSW_ALE_IOCTL_SET_POLICER: %d\n", status);
             status = RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_EFAIL;
         }
    +
    +    if (ENET_SOK == status)
    +    {
    +        if (hProxyServer->addStaticCfg != NULL)
    +        {
    +            status = hProxyServer->addStaticCfg(hEnet, host_id, flow_idx_offset);
    +            if (ENET_SOK != status)
    +            {
    +                appLogPrintf("Failed to add static config for coreId=%u: %d\n", host_id, status);
    +            }
    +        }
    +    }
    +
    +    if (status != ENET_SOK)
    +    {
    +        status = RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_EFAIL;
    +    }
         else
         {
             status = RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK;
    @@ -632,10 +658,13 @@ static int32_t CpswProxyServer_unregisterMacHandlerCb(uint32_t host_id,
                                                           u8 *mac_address,
                                                           uint32_t flow_idx)
     {
    +    CpswProxyServer_Obj *hProxyServer;
         int32_t status;
         Enet_Handle hEnet = (Enet_Handle)((uintptr_t)handle);
         uint32_t start_flow_idx, flow_idx_offset;
     
    +    hProxyServer = CpswProxyServer_getHandle();
    +
         CpswProxyServer_validateHandle(hEnet);
         EnetAppUtils_absFlowIdx2FlowIdxOffset(hEnet, host_id, flow_idx, &start_flow_idx, &flow_idx_offset);
         appLogPrintf("Function:%s,HostId:%u,Handle:%p,CoreKey:%x, MacAddress:%x:%x:%x:%x:%x:%x, FlowIdx:%u, FlowIdOffset:%u\n",
    @@ -653,6 +682,19 @@ static int32_t CpswProxyServer_unregisterMacHandlerCb(uint32_t host_id,
                      flow_idx_offset);
     
         status = EnetAppUtils_unregDstMacRxFlow(hEnet, core_key, host_id, start_flow_idx, flow_idx_offset, mac_address);
    +    if (status != ENET_SOK)
    +    {
    +        appLogPrintf("Failed EnetAppUtils_unregDstMacRxFlow: %d\n", status);
    +    }
    +
    +    if (ENET_SOK == status)
    +    {
    +        if (hProxyServer->delStaticCfg != NULL)
    +        {
    +            hProxyServer->delStaticCfg(hEnet, host_id, flow_idx_offset);
    +        }
    +    }
    +
         if (status != ENET_SOK)
         {
             appLogPrintf("Failed EnetAppUtils_unregDstMacRxFlow: %d\n", status);
    @@ -1657,6 +1699,10 @@ int32_t CpswProxyServer_init(CpswProxyServer_Config_t *cfg)
     
         hProxyServer->initDone = true;
         appLogPrintf("Remote demo device (core : mcu2_0) .....\r\n");
    +
    +    hProxyServer->addStaticCfg = cfg->addStaticCfg;
    +    hProxyServer->delStaticCfg = cfg->delStaticCfg;
    +
         return ENET_SOK;
     }
     
    -- 
    2.25.1
    
    

    Main Functions :

    1. EthApp_addMpu10StaticCfg() : used to create a classifier entry for matching DA and a multicast MAC using the IOCTL CPSW_ALE_IOCTL_SET_POLICER and then add an entry in Multicast Table using the IOCTL CPSW_ALE_IOCTL_ADD_MCAST
    2. EthApp_delMpu10StaticCfg() : Remove the entries created by EthApp_addMpu10StaticCfg() using CPSW_ALE_IOCTL_DEL_POLICER
    3. EthApp_addRemoteCoreStaticCfg() andEthApp_delRemoteCoreStaticCfg() : This is used to check the CoreID and make sure thatEthApp_addMpu10StaticCfg() and EthApp_delMpu10StaticCfg() are invoked only for A72 Core

    The relevant structures to understand here are CpswAle_PolicerMatchParams and CpswAle_SetMcastEntryInArgs

    Note:

    1. As you can see from the Policer/Classifier entry,  we set the policerMatchEnMask field to CPSW_ALE_POLICER_MATCH_MACDST so that it matches the Destination MAC
    2. Since packets are going to A72, Host port must be added as a destination port and Mask for all port settings

    Adding a VLAN entry for A72 only for Port 1

    Refer to the patch below for adding a VLAN entry (VID  = 70) for Port 1 and Host Port. This patch binds the VID TEST_VID_A72 to Port 1 and enables strict VID check (inArgs.vidIngressCheck = true) so that if this packet is received by any other port then it is dropped.

    vlan_config_patch.txt
    diff --git a/apps/app_remoteswitchcfg_server/mcu_2_0/main_tirtos.c b/apps/app_remoteswitchcfg_server/mcu_2_0/main_tirtos.c
    index 74cc0df..6e5b2c0 100644
    --- a/apps/app_remoteswitchcfg_server/mcu_2_0/main_tirtos.c
    +++ b/apps/app_remoteswitchcfg_server/mcu_2_0/main_tirtos.c
    @@ -147,6 +147,8 @@
     /* Define A72_QNX_OS if A72 is running Qnx. Qnx doesn't load resource table. */
     /* #define A72_QNX_OS */
     
    +#define TEST_VID_A72                    (70U)
    +
     /* ========================================================================== */
     /*                         Structure Declarations                             */
     /* ========================================================================== */
    @@ -207,6 +209,14 @@ static void EthApp_startSwInterVlan(char *recvBuff,
     static void EthApp_startHwInterVlan(char *recvBuff,
                                         char *sendBuff);
     
    +static int32_t EthApp_addRemoteCoreStaticCfg(Enet_Handle hEnet,
    +                                             uint32_t coreId,
    +                                             uint32_t flowId);
    +
    +static void EthApp_delRemoteCoreStaticCfg(Enet_Handle hEnet,
    +                                          uint32_t coreId,
    +                                          uint32_t flowId);
    +
     /* ========================================================================== */
     /*                          Extern variables                                  */
     /* ========================================================================== */
    @@ -563,6 +573,11 @@ static int32_t EthApp_initEthFw(void)
                                          ethFwCfg.ports[i].portNum);
         }
     
    +    /* Set static configuration functions */
    +    ethFwCfg.addStaticCfg = &EthApp_addRemoteCoreStaticCfg;
    +    ethFwCfg.delStaticCfg = &EthApp_delRemoteCoreStaticCfg;
    +
    +
         /* Initialize the EthFw */
         gEthAppObj.hEthFw = EthFw_init(gEthAppObj.enetType, &ethFwCfg);
         if (gEthAppObj.hEthFw == NULL)
    @@ -815,3 +830,148 @@ void EthApp_traceBufCacheWb(void)
             }
         }
     }
    +
    +
    +static int32_t EthApp_addMpu10StaticCfg(Enet_Handle hEnet,
    +                                        uint32_t coreId,
    +                                        uint32_t flowId)
    +{
    +    CpswAle_SetPolicerEntryInArgs polInArgs;
    +    CpswAle_SetPolicerEntryOutArgs polOutArgs;
    +    Enet_IoctlPrms prms;
    +    int32_t status;
    +
    +    CpswAle_VlanEntryInfo inArgs;
    +    uint32_t outArgs;
    +
    +    /* Add VLAN entry */
    +    memset(&inArgs, 0U, sizeof (CpswAle_VlanEntryInfo));
    +    inArgs.vlanIdInfo.vlanId = TEST_VID_A72;
    +    inArgs.vlanIdInfo.tagType = ENET_VLAN_TAG_TYPE_INNER;
    +    inArgs.vlanMemberList = (1 << CPSW_ALE_MACPORT_TO_ALEPORT(ENET_MAC_PORT_1)) | CPSW_ALE_HOST_PORT_MASK;
    +    inArgs.unregMcastFloodMask = (1 << CPSW_ALE_MACPORT_TO_ALEPORT(ENET_MAC_PORT_1)) | CPSW_ALE_HOST_PORT_MASK;
    +    inArgs.regMcastFloodMask = (1 << CPSW_ALE_MACPORT_TO_ALEPORT(ENET_MAC_PORT_1)) | CPSW_ALE_HOST_PORT_MASK;
    +    inArgs.forceUntaggedEgressMask = 0;
    +    inArgs.noLearnMask = 0U;
    +    inArgs.vidIngressCheck = true;
    +    inArgs.limitIPNxtHdr = false;
    +    inArgs.disallowIPFrag = false;
    +
    +    ENET_IOCTL_SET_INOUT_ARGS(&prms, &inArgs, &outArgs);
    +
    +    status = Enet_ioctl(hEnet, gEthAppObj.coreId, CPSW_ALE_IOCTL_ADD_VLAN, &prms);
    +    if (status != ENET_SOK)
    +    {
    +        appLogPrintf("%s() failed ADD_VLAN ioctl failed: %d\n", __func__, status);
    +    }
    +
    +    polInArgs.policerMatch.policerMatchEnMask = 0U;
    +
    +    /* Add policer entry for port 1 and dstmac */
    +    polInArgs.policerMatch.policerMatchEnMask = CPSW_ALE_POLICER_MATCH_PORT;
    +    polInArgs.policerMatch.portNum = CPSW_ALE_MACPORT_TO_ALEPORT(ENET_MAC_PORT_1);
    +    polInArgs.policerMatch.portIsTrunk = false;
    +
    +    polInArgs.policerMatch.policerMatchEnMask |= CPSW_ALE_POLICER_MATCH_IVLAN;
    +    polInArgs.policerMatch.dstMacAddrInfo.portNum = CPSW_ALE_HOST_PORT_NUM;
    +    polInArgs.policerMatch.dstMacAddrInfo.addr.vlanId = TEST_VID_A72;
    +
    +    polInArgs.threadIdEn = true;
    +    polInArgs.threadId   = flowId;
    +    polInArgs.peakRateInBitsPerSec   = 0U;
    +    polInArgs.commitRateInBitsPerSec = 0U;
    +    polInArgs.policerMatch.portNum = CPSW_ALE_MACPORT_TO_ALEPORT(ENET_MAC_PORT_1);
    +
    +    ENET_IOCTL_SET_INOUT_ARGS(&prms, &polInArgs, &polOutArgs);
    +
    +    status = Enet_ioctl(hEnet, gEthAppObj.coreId, CPSW_ALE_IOCTL_SET_POLICER, &prms);
    +    if (status != ENET_SOK)
    +    {
    +        appLogPrintf("Failed to register PORT1 | MACDST policer: %d\n", status);
    +    }
    +    return status;
    +}
    +
    +static void EthApp_delMpu10StaticCfg(Enet_Handle hEnet,
    +                                     uint32_t coreId,
    +                                     uint32_t flowId)
    +{
    +    const uint8_t mcastAddr[ENET_MAC_ADDR_LEN] = {0x01, 0x99, 0xc2, 0x00, 0x01, 0x0E};
    +    CpswAle_DelPolicerEntryInArgs polInArgs;
    +    Enet_IoctlPrms prms;
    +    int32_t status;
    +
    +    CpswAle_VlanEntryInfo inArgs;
    +
    +    /* Delete VLAN entry */
    +    memset(&inArgs, 0U, sizeof (CpswAle_VlanEntryInfo));
    +    inArgs.vlanIdInfo.vlanId = TEST_VID_A72;
    +    inArgs.vlanIdInfo.tagType = ENET_VLAN_TAG_TYPE_INNER;
    +
    +    ENET_IOCTL_SET_IN_ARGS(&prms, &inArgs);
    +
    +    status = Enet_ioctl(hEnet, gEthAppObj.coreId, CPSW_ALE_IOCTL_REMOVE_VLAN, &prms);
    +
    +    if (status != ENET_SOK)
    +    {
    +        appLogPrintf("Failed to delete VLAN entry: %d\n", status);
    +    }
    +
    +    polInArgs.policerMatch.policerMatchEnMask = 0U;
    +
    +    /* Delete policer entry for port 1 and dstmac */
    +    polInArgs.policerMatch.policerMatchEnMask = CPSW_ALE_POLICER_MATCH_PORT;
    +    polInArgs.policerMatch.portNum = CPSW_ALE_MACPORT_TO_ALEPORT(ENET_MAC_PORT_1);
    +    polInArgs.policerMatch.portIsTrunk = false;
    +
    +    polInArgs.policerMatch.policerMatchEnMask |= CPSW_ALE_POLICER_MATCH_MACDST;
    +    polInArgs.policerMatch.dstMacAddrInfo.portNum = CPSW_ALE_HOST_PORT_NUM;
    +    polInArgs.policerMatch.dstMacAddrInfo.addr.vlanId = 0U;
    +    EnetUtils_copyMacAddr(&polInArgs.policerMatch.dstMacAddrInfo.addr.addr[0], &mcastAddr[0]);
    +
    +    polInArgs.aleEntryMask = CPSW_ALE_POLICER_MATCH_PORT;
    +    polInArgs.policerMatch.portNum = CPSW_ALE_MACPORT_TO_ALEPORT(ENET_MAC_PORT_1);
    +    ENET_IOCTL_SET_IN_ARGS(&prms, &polInArgs);
    +
    +    status = Enet_ioctl(hEnet, gEthAppObj.coreId, CPSW_ALE_IOCTL_DEL_POLICER, &prms);
    +    if (status != ENET_SOK)
    +    {
    +        appLogPrintf("Failed to delete PORT1 | MACDST policer: %d\n", status);
    +    }
    +}
    +
    +static int32_t EthApp_addRemoteCoreStaticCfg(Enet_Handle hEnet,
    +                                             uint32_t coreId,
    +                                             uint32_t flowId)
    +{
    +    int32_t status = ENET_SOK;
    +
    +    switch (coreId)
    +    {
    +        case IPC_MPU1_0:
    +            appLogPrintf("Add static config for mpu1_0\n");
    +            status = EthApp_addMpu10StaticCfg(hEnet, coreId, flowId);
    +            break;
    +
    +        default:
    +            break;
    +    }
    +
    +    return status;
    +}
    +
    +static void EthApp_delRemoteCoreStaticCfg(Enet_Handle hEnet,
    +                                          uint32_t coreId,
    +                                          uint32_t flowId)
    +{
    +    switch (coreId)
    +    {
    +        case IPC_MPU1_0:
    +            appLogPrintf("Delete static config for mpu1_0\n");
    +            EthApp_delMpu10StaticCfg(hEnet, coreId, flowId);
    +            break;
    +
    +        default:
    +            break;
    +    }
    +}
    diff --git a/ethfw/ethfw.h b/ethfw/ethfw.h
    index ef4a8c9..cafab00 100644
    --- a/ethfw/ethfw.h
    +++ b/ethfw/ethfw.h
    @@ -178,6 +178,35 @@ typedef struct EthFw_PortConfig_s
         EnetPort_VlanCfg vlanCfg;
     } EthFw_Port;
     
    +/*!
    + * \brief Add static configuration.
    + *
    + * Add static configuration that is applicable only to specific remote cores.
    + *
    + * \param hEnet        Handle to Enet LLD
    + * \param coreId       Remote core's IPC core id
    + * \param flowId       Remote core's flow id
    + *
    + * \return 0 if no error. Negative value otherwise.
    + */
    +typedef int32_t (*EthFw_addStaticCfg)(Enet_Handle hEnet,
    +                                      uint32_t coreId,
    +                                      uint32_t flowId);
    +
    +/*!
    + * \brief Delete static configuration.
    + *
    + * Delete static configuration that is applicable only to specific remote cores.
    + *
    + * \param hEnet        Handle to Enet LLD
    + * \param coreId       Remote core's IPC core id
    + * \param flowId       Remote core's flow id
    + */
    +typedef void (*EthFw_delStaticCfg)(Enet_Handle hEnet,
    +                                   uint32_t coreId,
    +                                   uint32_t flowId);
    +
    +
     /*!
      * \brief Ethernet Firmware configuration
      *
    @@ -195,6 +224,12 @@ typedef struct EthFw_Config_s
         /*! Number of MAC ports owned by EthFw, that is, the size of
          *  EthFw_Config::ports array */
         uint32_t numPorts;
    +
    +    /* Add static configuration that is applicable only to specific remote cores */
    +    EthFw_addStaticCfg addStaticCfg;
    +
    +    /* Delete static configuration that is applicable only to specific remote cores */
    +    EthFw_delStaticCfg delStaticCfg;
     } EthFw_Config;
     
     /*!
    diff --git a/ethfw/src/ethfw.c b/ethfw/src/ethfw.c
    index f8eeb7e..e12e425 100644
    --- a/ethfw/src/ethfw.c
    +++ b/ethfw/src/ethfw.c
    @@ -182,6 +182,12 @@ typedef struct EthFw_Obj_s
         /* Handle to PTP stack */
         TimeSyncPtp_Handle timeSyncPtp;
     
    +    /* Add static configuration that is applicable only to specific remote cores */
    +    EthFw_addStaticCfg addStaticCfg;
    +
    +    /* Delete static configuration that is applicable only to specific remote cores */
    +    EthFw_delStaticCfg delStaticCfg;
    +
     } EthFw_Obj;
     
     /* ========================================================================== */
    @@ -268,6 +274,10 @@ void EthFw_initConfigParams(Enet_Type enetType,
         CpswHostPort_Cfg *hostPortCfg = &cpswCfg->hostPortCfg;
         EnetRm_ResCfg *resCfg = &cpswCfg->resCfg;
     
    +    /* Initialize Static config function pointers */
    +    config->addStaticCfg = NULL;
    +    config->delStaticCfg = NULL;
    +
         /* MAC port ownership */
         config->ports = NULL;
         config->numPorts = 0U;
    @@ -306,6 +316,10 @@ EthFw_Handle EthFw_init(Enet_Type enetType,
     
         memset(&gEthFwObj, 0, sizeof(gEthFwObj));
     
    +    /* Save static config function pointers */
    +    gEthFwObj.addStaticCfg = config->addStaticCfg;
    +    gEthFwObj.delStaticCfg = config->delStaticCfg;
    +
         /* Save config parameters */
         gEthFwObj.cpswCfg = config->cpswCfg;
         gEthFwObj.numPorts = config->numPorts;
    @@ -419,6 +433,10 @@ int32_t EthFw_initRemoteConfig(EthFw_Handle hEthFw)
         cfg.notifyServiceRemoteCoreId[0] = IPC_MPU1_0;
         cfg.notifyServiceRemoteCoreId[1] = IPC_MCU2_1;
     
    +    /* Static configuration callbacks */
    +    cfg.addStaticCfg = gEthFwObj.addStaticCfg;
    +    cfg.delStaticCfg = gEthFwObj.delStaticCfg;
    +
         status = CpswProxyServer_init(&cfg);
         if (status != ENET_SOK)
         {
    diff --git a/ethremotecfg/server/include/cpsw_proxy_server.h b/ethremotecfg/server/include/cpsw_proxy_server.h
    index c1acfa9..23098f1 100644
    --- a/ethremotecfg/server/include/cpsw_proxy_server.h
    +++ b/ethremotecfg/server/include/cpsw_proxy_server.h
    @@ -162,6 +162,34 @@ typedef struct CpswProxyServer_RemoteCoreConfig_s
         char     serverName[ETHREMOTECFG_SERVER_MAX_NAME_LEN];
     } CpswProxyServer_RemoteCoreConfig;
     
    +/*!
    + * \brief Add static configuration.
    + *
    + * Add static configuration that is applicable only to specific remote cores.
    + *
    + * \param hEnet        Handle to Enet LLD
    + * \param coreId       Remote core's IPC core id
    + * \param flowId       Remote core's flow id
    + *
    + * \return 0 if no error. Negative value otherwise.
    + */
    +typedef int32_t (*CpswProxyServer_addStaticCfg)(Enet_Handle hEnet,
    +                                                uint32_t coreId,
    +                                                uint32_t flowId);
    +
    +/*!
    + * \brief Delete static configuration.
    + *
    + * Delete static configuration that is applicable only to specific remote cores.
    + *
    + * \param hEnet        Handle to Enet LLD
    + * \param coreId       Remote core's IPC core id
    + * \param flowId       Remote core's flow id
    + */
    +typedef void (*CpswProxyServer_delStaticCfg)(Enet_Handle hEnet,
    +                                             uint32_t coreId,
    +                                             uint32_t flowId);
    +
     /*!
      * \brief Cpsw Proxy Server Remote Configuration structure
      *
    @@ -199,6 +227,12 @@ typedef struct CpswProxyServer_Config_s
     
         /*! Remote Core configuration */
         CpswProxyServer_RemoteCoreConfig remoteCoreCfg[ETHREMOTECFG_SERVER_MAX_INSTANCES];
    +
    +    /* Add static configuration that is applicable only to specific remote cores */
    +    CpswProxyServer_addStaticCfg addStaticCfg;
    +
    +    /* Delete static configuration that is applicable only to specific remote cores */
    +    CpswProxyServer_delStaticCfg delStaticCfg;
     } CpswProxyServer_Config_t;
     
     /*!
    diff --git a/ethremotecfg/server/src/cpsw_proxy_server.c b/ethremotecfg/server/src/cpsw_proxy_server.c
    index 4c01eaa..295b781 100644
    --- a/ethremotecfg/server/src/cpsw_proxy_server.c
    +++ b/ethremotecfg/server/src/cpsw_proxy_server.c
    @@ -184,6 +184,12 @@ typedef struct CpswProxyServer_Obj_s
         SemaphoreP_Handle                     rdevStartSem;
         CpswProxyServer_EthDriverObj          ethDrvObj;
         CpswProxyServer_NotifyServiceObj      notifyServiceObj;
    +
    +    /* Add static configuration that is applicable only to specific remote cores */
    +    CpswProxyServer_addStaticCfg addStaticCfg;
    +
    +    /* Delete static configuration that is applicable only to specific remote cores */
    +    CpswProxyServer_delStaticCfg delStaticCfg;
     } CpswProxyServer_Obj;
     
     /* ========================================================================== */
    @@ -592,10 +598,13 @@ static int32_t CpswProxyServer_registerMacHandlerCb(uint32_t host_id,
                                                         u8 *mac_address,
                                                         uint32_t flow_idx)
     {
    +    CpswProxyServer_Obj *hProxyServer;
         int32_t status;
         Enet_Handle hEnet = (Enet_Handle)((uintptr_t)handle);
         uint32_t start_flow_idx, flow_idx_offset;
     
    +    hProxyServer = CpswProxyServer_getHandle();
    +
         CpswProxyServer_validateHandle(hEnet);
         EnetAppUtils_absFlowIdx2FlowIdxOffset(hEnet, host_id, flow_idx, &start_flow_idx, &flow_idx_offset);
         appLogPrintf("Function:%s,HostId:%u,Handle:%p,CoreKey:%x, MacAddress:%x:%x:%x:%x:%x:%x, FlowIdx:%u, FlowIdxOffset:%u\n",
    @@ -618,6 +627,23 @@ static int32_t CpswProxyServer_registerMacHandlerCb(uint32_t host_id,
             appLogPrintf("EnetAppUtils_regDstMacRxFlow() failed CPSW_ALE_IOCTL_SET_POLICER: %d\n", status);
             status = RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_EFAIL;
         }
    +
    +    if (ENET_SOK == status)
    +    {
    +        if (hProxyServer->addStaticCfg != NULL)
    +        {
    +            status = hProxyServer->addStaticCfg(hEnet, host_id, flow_idx_offset);
    +            if (ENET_SOK != status)
    +            {
    +                appLogPrintf("Failed to add static config for coreId=%u: %d\n", host_id, status);
    +            }
    +        }
    +    }
    +
    +    if (status != ENET_SOK)
    +    {
    +        status = RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_EFAIL;
    +    }
         else
         {
             status = RPMSG_KDRV_TP_ETHSWITCH_CMDSTATUS_OK;
    @@ -632,10 +658,13 @@ static int32_t CpswProxyServer_unregisterMacHandlerCb(uint32_t host_id,
                                                           u8 *mac_address,
                                                           uint32_t flow_idx)
     {
    +    CpswProxyServer_Obj *hProxyServer;
         int32_t status;
         Enet_Handle hEnet = (Enet_Handle)((uintptr_t)handle);
         uint32_t start_flow_idx, flow_idx_offset;
     
    +    hProxyServer = CpswProxyServer_getHandle();
    +
         CpswProxyServer_validateHandle(hEnet);
         EnetAppUtils_absFlowIdx2FlowIdxOffset(hEnet, host_id, flow_idx, &start_flow_idx, &flow_idx_offset);
         appLogPrintf("Function:%s,HostId:%u,Handle:%p,CoreKey:%x, MacAddress:%x:%x:%x:%x:%x:%x, FlowIdx:%u, FlowIdOffset:%u\n",
    @@ -653,6 +682,19 @@ static int32_t CpswProxyServer_unregisterMacHandlerCb(uint32_t host_id,
                      flow_idx_offset);
     
         status = EnetAppUtils_unregDstMacRxFlow(hEnet, core_key, host_id, start_flow_idx, flow_idx_offset, mac_address);
    +    if (status != ENET_SOK)
    +    {
    +        appLogPrintf("Failed EnetAppUtils_unregDstMacRxFlow: %d\n", status);
    +    }
    +
    +    if (ENET_SOK == status)
    +    {
    +        if (hProxyServer->delStaticCfg != NULL)
    +        {
    +            hProxyServer->delStaticCfg(hEnet, host_id, flow_idx_offset);
    +        }
    +    }
    +
         if (status != ENET_SOK)
         {
             appLogPrintf("Failed EnetAppUtils_unregDstMacRxFlow: %d\n", status);
    @@ -1657,6 +1699,10 @@ int32_t CpswProxyServer_init(CpswProxyServer_Config_t *cfg)
     
         hProxyServer->initDone = true;
         appLogPrintf("Remote demo device (core : mcu2_0) .....\r\n");
    +
    +    hProxyServer->addStaticCfg = cfg->addStaticCfg;
    +    hProxyServer->delStaticCfg = cfg->delStaticCfg;
    +
         return ENET_SOK;
     }
     
    

    Note:

    1. First VLAN configuration must be created using the IOCTL CPSW_ALE_IOCTL_ADD_VLAN
    2. Same VID (TEST_VID_A72) must be configured for both Policer and VLAN Table
    3. Only Inner VLAN is used
    4. For Policer, the match critiera mask checks for Inner VLAN entry (policerMatchEnMask = CPSW_ALE_POLICER_MATCH_IVLAN)

    Verifying ALE Entries

    Users can either run the GEL script cpsw_ale_print_table.gel on R5F (requires CCS and JTAG) or use the script below on A72 to print it. Both of these methods scan the entire ALE table and print all populated entries.

    cpsw_all_reg_print.c
     
    #include <ctype.h>
    #include <error.h>
    #include <fcntl.h>
    #include <stdarg.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/mman.h>
    #include <unistd.h>
    
    #define MEMORY "/dev/mem"
    
    #define CPSW_9G_PORT_NUM        8
    #define CPSW_5G_PORT_NUM        4
    #define CPSW_2G_PORT_NUM        1
    
    #define ALE_TBLCTL_2G              0x4603E020
    #define ALE_TBLW2_2G               0x4603E034
    #define ALE_TBLW1_2G               0x4603E038
    #define ALE_TBLW0_2G               0x4603E03C
    
    #define ALE_TBLCTL_9G              0x0C03E020
    #define ALE_TBLW2_9G               0x0C03E034
    #define ALE_TBLW1_9G               0x0C03E038
    #define ALE_TBLW0_9G               0x0C03E03C
    
    #define ALE_TABLE_DEPTH_2G         64
    #define ALE_TABLE_DEPTH_5G         512
    #define ALE_TABLE_DEPTH_9G         1024
    
    
    #define ALE_ENTRY_EMTPY         0x0
    #define ALE_ENTRY_ADDR          0x1
    #define ALE_ENTRY_VLAN          0x2
    #define ALE_ENTRY_VLAN_ADDR     0x3
    
    int      fd;
    
    unsigned page_size, mapped_size, offset_in_page;
    void *   map_base, *virt_addr;
    int      fd;
    
    uint32_t mmio_read_32(unsigned long int addr);
    void mmio_write_32(unsigned long int addr, uint32_t value);
    
    static void unmap_address(void)
    {
        if (munmap(map_base, mapped_size) == -1)
            fprintf(stderr, "munmap");
        close(fd);
    }
    
    static int map_address(off_t target)
    {
        unsigned int width = 8 * sizeof(uint64_t);
    
        fd = open(MEMORY, (O_RDWR | O_SYNC));
        if (fd < 0)
        {
            fprintf(stderr, "Could not open %s!\n", MEMORY);
            return -5;
        }
    
        mapped_size = page_size = getpagesize();
        offset_in_page          = (unsigned)target & (page_size - 1);
        if (offset_in_page + width > page_size)
        {
            /*
             * This access spans pages.
             * Must map two pages to make it possible:
             */
            mapped_size *= 2;
        }
        map_base = mmap(NULL, mapped_size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, target & ~(off_t)(page_size - 1));
        if (map_base == MAP_FAILED)
        {
            fprintf(stderr, "Map fail\n");
            return -1;
        }
    
        virt_addr = (char *)map_base + offset_in_page;
        return 0;
    }
    
    static uint64_t read_reg(int width)
    {
        uint64_t read_result = 0x0;
    
        switch (width)
        {
            case 8:
                read_result = *(volatile uint8_t *)virt_addr;
                break;
            case 16:
                read_result = *(volatile uint16_t *)virt_addr;
                break;
            case 32:
                read_result = *(volatile uint32_t *)virt_addr;
                break;
            case 64:
                read_result = *(volatile uint64_t *)virt_addr;
                break;
            default:
                fprintf(stderr, "bad width");
        }
    
        return read_result;
    }
    
    static void write_reg(int width, uint64_t writeval)
    {
        switch (width)
        {
            case 8:
                *(volatile uint8_t *)virt_addr = writeval;
                break;
            case 16:
                *(volatile uint16_t *)virt_addr = writeval;
                break;
            case 32:
                *(volatile uint32_t *)virt_addr = writeval;
                break;
            case 64:
                *(volatile uint64_t *)virt_addr = writeval;
                break;
            default:
                fprintf(stderr, "bad width");
        }
    }
    
    uint32_t mmio_read_32(unsigned long int addr)
    {
        uint32_t v = 0;
        int      r;
    
        r = map_address(addr);
        if (r)
            return 0;
        v = read_reg(32);
        unmap_address();
        return v;
    }
    
    void mmio_write_32(unsigned long int addr, uint32_t value)
    {
        int r;
    
        r = map_address(addr);
        if (r)
            return;
        write_reg(32, value);
        unmap_address();
    }
    
    void cpsw_print_stat_with_index_nonzero(char* regName, uint32_t portnum, uint32_t regIdx, unsigned long int regAddr)
    {
        uint32_t regVal = mmio_read_32(regAddr);
        if (0 != regVal)
        {
            printf("STAT_%d_%s[%d]= %x\n", portnum, regName, regIdx, regVal);
        }
    }
    
    void cpsw_print_stat_nonzero(char* regName, uint32_t portnum, unsigned long int regAddr)
    {
        uint32_t regVal = mmio_read_32(regAddr);
        if (0 != regVal)
        {
            printf("STAT_%d_%s= %x\n",portnum, regName, regVal);
        }
    }
    
    void cpsw_2g_statsprint_nonzero()
    {
        uint32_t i, regAddr, portnum;
    
        printf("          STATS          \n");
    
        portnum = 0;
        printf("--------------------------------\n");
        printf("          PORT%d STATS          \n",portnum);
        printf("--------------------------------\n");
        cpsw_print_stat_nonzero("RXGOODFRAMES              ", portnum, (0x4603A000U));
        cpsw_print_stat_nonzero("RXBROADCASTFRAMES         ", portnum, (0x4603A004U));
        cpsw_print_stat_nonzero("RXMULTICASTFRAMES         ", portnum, (0x4603A008U));
        cpsw_print_stat_nonzero("RXCRCERRORS               ", portnum, (0x4603A010U));
        cpsw_print_stat_nonzero("RXOVERSIZEDFRAMES         ", portnum, (0x4603A018U));
        cpsw_print_stat_nonzero("RXUNDERSIZEDFRAMES        ", portnum, (0x4603A020U));
        cpsw_print_stat_nonzero("RXFRAGMENTS               ", portnum, (0x4603A024U));
        cpsw_print_stat_nonzero("ALE_DROP                  ", portnum, (0x4603A028U));
        cpsw_print_stat_nonzero("ALE_OVERRUN_DROP          ", portnum, (0x4603A02CU));
        cpsw_print_stat_nonzero("RXOCTETS                  ", portnum, (0x4603A030U));
        cpsw_print_stat_nonzero("TXGOODFRAMES              ", portnum, (0x4603A034U));
        cpsw_print_stat_nonzero("TXBROADCASTFRAMES         ", portnum, (0x4603A038U));
        cpsw_print_stat_nonzero("TXMULTICASTFRAMES         ", portnum, (0x4603A03CU));
        cpsw_print_stat_nonzero("TXOCTETS                  ", portnum, (0x4603A064U));
        cpsw_print_stat_nonzero("OCTETFRAMES64             ", portnum, (0x4603A068U));
        cpsw_print_stat_nonzero("OCTETFRAMES65T127         ", portnum, (0x4603A06CU));
        cpsw_print_stat_nonzero("OCTETFRAMES128T255        ", portnum, (0x4603A070U));
        cpsw_print_stat_nonzero("OCTETFRAMES256T511        ", portnum, (0x4603A074U));
        cpsw_print_stat_nonzero("OCTETFRAMES512T1023       ", portnum, (0x4603A078U));
        cpsw_print_stat_nonzero("OCTETFRAMES1024TUP        ", portnum, (0x4603A07CU));
        cpsw_print_stat_nonzero("NETOCTETS                 ", portnum, (0x4603A080U));
        cpsw_print_stat_nonzero("RX_BOTTOM_OF_FIFO_DROP    ", portnum, (0x4603A084U));
        cpsw_print_stat_nonzero("PORTMASK_DROP             ", portnum, (0x4603A088U));
        cpsw_print_stat_nonzero("RX_TOP_OF_FIFO_DROP       ", portnum, (0x4603A08CU));
        cpsw_print_stat_nonzero("ALE_RATE_LIMIT_DROP       ", portnum, (0x4603A090U));
        cpsw_print_stat_nonzero("ALE_VID_INGRESS_DROP      ", portnum, (0x4603A094U));
        cpsw_print_stat_nonzero("ALE_DA_EQ_SA_DROP         ", portnum, (0x4603A098U));
        cpsw_print_stat_nonzero("ALE_BLOCK_DROP            ", portnum, (0x4603A09CU));
        cpsw_print_stat_nonzero("ALE_SECURE_DROP           ", portnum, (0x4603A0A0U));
        cpsw_print_stat_nonzero("ALE_AUTH_DROP             ", portnum, (0x4603A0A4U));
        cpsw_print_stat_nonzero("ALE_UNKN_UNI              ", portnum, (0x4603A0A8U));
        cpsw_print_stat_nonzero("ALE_UNKN_UNI_BCNT         ", portnum, (0x4603A0ACU));
        cpsw_print_stat_nonzero("ALE_UNKN_MLT              ", portnum, (0x4603A0B0U));
        cpsw_print_stat_nonzero("ALE_UNKN_MLT_BCNT         ", portnum, (0x4603A0B4U));
        cpsw_print_stat_nonzero("ALE_UNKN_BRD              ", portnum, (0x4603A0B8U));
        cpsw_print_stat_nonzero("ALE_UNKN_BRD_BCNT         ", portnum, (0x4603A0BCU));
        cpsw_print_stat_nonzero("ALE_POL_MATCH             ", portnum, (0x4603A0C0U));
        cpsw_print_stat_nonzero("ALE_POL_MATCH_RED         ", portnum, (0x4603A0C4U));
        cpsw_print_stat_nonzero("ALE_POL_MATCH_YELLOW      ", portnum, (0x4603A0C8U));
        cpsw_print_stat_nonzero("TX_MEMORY_PROTECT_ERROR   ", portnum, (0x4603A17CU));
    
        portnum = 1;
        printf("--------------------------------\n");
        printf("          PORT%d STATS          \n",portnum);
        printf("--------------------------------\n");
        cpsw_print_stat_nonzero("RXGOODFRAMES              ", portnum, (0x4603A200U));
        cpsw_print_stat_nonzero("RXBROADCASTFRAMES         ", portnum, (0x4603A204U));
        cpsw_print_stat_nonzero("RXMULTICASTFRAMES         ", portnum, (0x4603A208U));
        cpsw_print_stat_nonzero("RXPAUSEFRAMES             ", portnum, (0x4603A20CU));
        cpsw_print_stat_nonzero("RXCRCERRORS               ", portnum, (0x4603A210U));
        cpsw_print_stat_nonzero("RXALIGNCODEERRORS         ", portnum, (0x4603A214U));
        cpsw_print_stat_nonzero("RXOVERSIZEDFRAMES         ", portnum, (0x4603A218U));
        cpsw_print_stat_nonzero("RXJABBERFRAMES            ", portnum, (0x4603A21CU));
        cpsw_print_stat_nonzero("RXUNDERSIZEDFRAMES        ", portnum, (0x4603A220U));
        cpsw_print_stat_nonzero("RXFRAGMENTS               ", portnum, (0x4603A224U));
        cpsw_print_stat_nonzero("ALE_DROP                  ", portnum, (0x4603A228U));
        cpsw_print_stat_nonzero("ALE_OVERRUN_DROP          ", portnum, (0x4603A22CU));
        cpsw_print_stat_nonzero("RXOCTETS                  ", portnum, (0x4603A230U));
        cpsw_print_stat_nonzero("TXGOODFRAMES              ", portnum, (0x4603A234U));
        cpsw_print_stat_nonzero("TXBROADCASTFRAMES         ", portnum, (0x4603A238U));
        cpsw_print_stat_nonzero("TXMULTICASTFRAMES         ", portnum, (0x4603A23CU));
        cpsw_print_stat_nonzero("TXPAUSEFRAMES             ", portnum, (0x4603A240U));
        cpsw_print_stat_nonzero("TXDEFERREDFRAMES          ", portnum, (0x4603A244U));
        cpsw_print_stat_nonzero("TXCOLLISIONFRAMES         ", portnum, (0x4603A248U));
        cpsw_print_stat_nonzero("TXSINGLECOLLFRAMES        ", portnum, (0x4603A24CU));
        cpsw_print_stat_nonzero("TXMULTCOLLFRAMES          ", portnum, (0x4603A250U));
        cpsw_print_stat_nonzero("TXEXCESSIVECOLLISIONS     ", portnum, (0x4603A254U));
        cpsw_print_stat_nonzero("TXLATECOLLISIONS          ", portnum, (0x4603A258U));
        cpsw_print_stat_nonzero("RXIPGERROR                ", portnum, (0x4603A25CU));
        cpsw_print_stat_nonzero("TXCARRIERSENSEERRORS      ", portnum, (0x4603A260U));
        cpsw_print_stat_nonzero("TXOCTETS                  ", portnum, (0x4603A264U));
        cpsw_print_stat_nonzero("OCTETFRAMES64             ", portnum, (0x4603A268U));
        cpsw_print_stat_nonzero("OCTETFRAMES65T127         ", portnum, (0x4603A26CU));
        cpsw_print_stat_nonzero("OCTETFRAMES128T255        ", portnum, (0x4603A270U));
        cpsw_print_stat_nonzero("OCTETFRAMES256T511        ", portnum, (0x4603A274U));
        cpsw_print_stat_nonzero("OCTETFRAMES512T1023       ", portnum, (0x4603A278U));
        cpsw_print_stat_nonzero("OCTETFRAMES1024TUP        ", portnum, (0x4603A27CU));
        cpsw_print_stat_nonzero("NETOCTETS                 ", portnum, (0x4603A280U));
        cpsw_print_stat_nonzero("RX_BOTTOM_OF_FIFO_DROP    ", portnum, (0x4603A284U));
        cpsw_print_stat_nonzero("PORTMASK_DROP             ", portnum, (0x4603A288U));
        cpsw_print_stat_nonzero("RX_TOP_OF_FIFO_DROP       ", portnum, (0x4603A28CU));
        cpsw_print_stat_nonzero("ALE_RATE_LIMIT_DROP       ", portnum, (0x4603A290U));
        cpsw_print_stat_nonzero("ALE_VID_INGRESS_DROP      ", portnum, (0x4603A294U));
        cpsw_print_stat_nonzero("ALE_DA_EQ_SA_DROP         ", portnum, (0x4603A298U));
        cpsw_print_stat_nonzero("ALE_BLOCK_DROP            ", portnum, (0x4603A29CU));
        cpsw_print_stat_nonzero("ALE_SECURE_DROP           ", portnum, (0x4603A2A0U));
        cpsw_print_stat_nonzero("ALE_AUTH_DROP             ", portnum, (0x4603A2A4U));
        cpsw_print_stat_nonzero("ALE_UNKN_UNI              ", portnum, (0x4603A2A8U));
        cpsw_print_stat_nonzero("ALE_UNKN_UNI_BCNT         ", portnum, (0x4603A2ACU));
        cpsw_print_stat_nonzero("ALE_UNKN_MLT              ", portnum, (0x4603A2B0U));
        cpsw_print_stat_nonzero("ALE_UNKN_MLT_BCNT         ", portnum, (0x4603A2B4U));
        cpsw_print_stat_nonzero("ALE_UNKN_BRD              ", portnum, (0x4603A2B8U));
        cpsw_print_stat_nonzero("ALE_UNKN_BRD_BCNT         ", portnum, (0x4603A2BCU));
        cpsw_print_stat_nonzero("ALE_POL_MATCH             ", portnum, (0x4603A2C0U));
        cpsw_print_stat_nonzero("ALE_POL_MATCH_RED         ", portnum, (0x4603A2C4U));
        cpsw_print_stat_nonzero("ALE_POL_MATCH_YELLOW      ", portnum, (0x4603A2C8U));
        cpsw_print_stat_nonzero("TX_MEMORY_PROTECT_ERROR   ", portnum, (0x4603A37CU));
    
        for (i = 0; i < 8; i++)
        {
            regAddr = 0x4603A380U + (i * 0x4U);
            cpsw_print_stat_with_index_nonzero("TX_PRI_REG             ", portnum, i, regAddr);
        }
    
        for (i = 0; i < 8; i++)
        {
            regAddr = 0x4603A3A0U + (i * 0x4U);
            cpsw_print_stat_with_index_nonzero("TX_PRI_BCNT_REG        ", portnum, i, regAddr);
        }
    
        for (i = 0; i < 8; i++)
        {
            regAddr = 0x4603A3C0U + (i * 0x4U);
            cpsw_print_stat_with_index_nonzero("TX_PRI_DROP_REG        ", portnum, i, regAddr);
        }
    
        for (i = 0; i < 8; i++)
        {
            regAddr = 0x4603A3E0U + (i * 0x4U);
            cpsw_print_stat_with_index_nonzero("TX_PRI_DROP_BCNT_REG   ", portnum, i, regAddr);
        }
    }
    
    void cpsw_ng_statsprint_nonzero(uint32_t numMacPorts)
    {
        uint32_t i, regAddr, portnum;
        uint32_t baseAddr;
        printf("          STATS          \n");
    
        portnum = 0;
        printf("--------------------------------\n");
        printf("          PORT%d STATS          \n",portnum);
        printf("--------------------------------\n");
        cpsw_print_stat_nonzero("RXGOODFRAMES              ", portnum, (0x0C03A000U));
        cpsw_print_stat_nonzero("RXBROADCASTFRAMES         ", portnum, (0x0C03A004U));
        cpsw_print_stat_nonzero("RXMULTICASTFRAMES         ", portnum, (0x0C03A008U));
        cpsw_print_stat_nonzero("RXCRCERRORS               ", portnum, (0x0C03A010U));
        cpsw_print_stat_nonzero("RXOVERSIZEDFRAMES         ", portnum, (0x0C03A018U));
        cpsw_print_stat_nonzero("RXUNDERSIZEDFRAMES        ", portnum, (0x0C03A020U));
        cpsw_print_stat_nonzero("RXFRAGMENTS               ", portnum, (0x0C03A024U));
        cpsw_print_stat_nonzero("ALE_DROP                  ", portnum, (0x0C03A028U));
        cpsw_print_stat_nonzero("ALE_OVERRUN_DROP          ", portnum, (0x0C03A02CU));
        cpsw_print_stat_nonzero("RXOCTETS                  ", portnum, (0x0C03A030U));
        cpsw_print_stat_nonzero("TXGOODFRAMES              ", portnum, (0x0C03A034U));
        cpsw_print_stat_nonzero("TXBROADCASTFRAMES         ", portnum, (0x0C03A038U));
        cpsw_print_stat_nonzero("TXMULTICASTFRAMES         ", portnum, (0x0C03A03CU));
        cpsw_print_stat_nonzero("TXOCTETS                  ", portnum, (0x0C03A064U));
        cpsw_print_stat_nonzero("OCTETFRAMES64             ", portnum, (0x0C03A068U));
        cpsw_print_stat_nonzero("OCTETFRAMES65T127         ", portnum, (0x0C03A06CU));
        cpsw_print_stat_nonzero("OCTETFRAMES128T255        ", portnum, (0x0C03A070U));
        cpsw_print_stat_nonzero("OCTETFRAMES256T511        ", portnum, (0x0C03A074U));
        cpsw_print_stat_nonzero("OCTETFRAMES512T1023       ", portnum, (0x0C03A078U));
        cpsw_print_stat_nonzero("OCTETFRAMES1024TUP        ", portnum, (0x0C03A07CU));
        cpsw_print_stat_nonzero("NETOCTETS                 ", portnum, (0x0C03A080U));
        cpsw_print_stat_nonzero("RX_BOTTOM_OF_FIFO_DROP    ", portnum, (0x0C03A084U));
        cpsw_print_stat_nonzero("PORTMASK_DROP             ", portnum, (0x0C03A088U));
        cpsw_print_stat_nonzero("RX_TOP_OF_FIFO_DROP       ", portnum, (0x0C03A08CU));
        cpsw_print_stat_nonzero("ALE_RATE_LIMIT_DROP       ", portnum, (0x0C03A090U));
        cpsw_print_stat_nonzero("ALE_VID_INGRESS_DROP      ", portnum, (0x0C03A094U));
        cpsw_print_stat_nonzero("ALE_DA_EQ_SA_DROP         ", portnum, (0x0C03A098U));
        cpsw_print_stat_nonzero("ALE_BLOCK_DROP            ", portnum, (0x0C03A09CU));
        cpsw_print_stat_nonzero("ALE_SECURE_DROP           ", portnum, (0x0C03A0A0U));
        cpsw_print_stat_nonzero("ALE_AUTH_DROP             ", portnum, (0x0C03A0A4U));
        cpsw_print_stat_nonzero("ALE_UNKN_UNI              ", portnum, (0x0C03A0A8U));
        cpsw_print_stat_nonzero("ALE_UNKN_UNI_BCNT         ", portnum, (0x0C03A0ACU));
        cpsw_print_stat_nonzero("ALE_UNKN_MLT              ", portnum, (0x0C03A0B0U));
        cpsw_print_stat_nonzero("ALE_UNKN_MLT_BCNT         ", portnum, (0x0C03A0B4U));
        cpsw_print_stat_nonzero("ALE_UNKN_BRD              ", portnum, (0x0C03A0B8U));
        cpsw_print_stat_nonzero("ALE_UNKN_BRD_BCNT         ", portnum, (0x0C03A0BCU));
        cpsw_print_stat_nonzero("ALE_POL_MATCH             ", portnum, (0x0C03A0C0U));
        cpsw_print_stat_nonzero("ALE_POL_MATCH_RED         ", portnum, (0x0C03A0C4U));
        cpsw_print_stat_nonzero("ALE_POL_MATCH_YELLOW      ", portnum, (0x0C03A0C8U));
        cpsw_print_stat_nonzero("TX_MEMORY_PROTECT_ERROR   ", portnum, (0x0C03A17CU));
    
        for (i = 0; i < 8; i++)
        {
            regAddr = 0x0C03A180U + (i * 0x4U);
            cpsw_print_stat_with_index_nonzero("TX_PRI_REG             ", portnum, i, regAddr);
        }
    
        for (i = 0; i < 8; i++)
        {
            regAddr = 0x0C03A1A0U + (i * 0x4U);
            cpsw_print_stat_with_index_nonzero("TX_PRI_BCNT_REG        ", portnum, i, regAddr);
        }
    
        for (i = 0; i < 8; i++)
        {
            regAddr = 0x0C03A1C0U + (i * 0x4U);
            cpsw_print_stat_with_index_nonzero("TX_PRI_DROP_REG        ", portnum, i, regAddr);
        }
    
        for (i = 0; i < 8; i++)
        {
            regAddr = 0x0C03A1E0U + (i * 0x4U);
            cpsw_print_stat_with_index_nonzero("TX_PRI_DROP_BCNT_REG   ", portnum, i, regAddr);
        }
    
        for (portnum = 1; portnum <= numMacPorts; portnum++)
        {
            printf("--------------------------------\n");
            printf("          PORT%d STATS          \n",portnum);
            printf("--------------------------------\n");
            baseAddr = 0x0C03A200U + ((portnum-1) * 0x200);
    
            cpsw_print_stat_nonzero("RXGOODFRAMES              ", portnum, (baseAddr));
            cpsw_print_stat_nonzero("RXBROADCASTFRAMES         ", portnum, (baseAddr + 0x4U));
            cpsw_print_stat_nonzero("RXMULTICASTFRAMES         ", portnum, (baseAddr + 0x8U));
            cpsw_print_stat_nonzero("RXPAUSEFRAMES             ", portnum, (baseAddr + 0xCU));
            cpsw_print_stat_nonzero("RXCRCERRORS               ", portnum, (baseAddr + 0x10U));
            cpsw_print_stat_nonzero("RXALIGNCODEERRORS         ", portnum, (baseAddr + 0x14U));
            cpsw_print_stat_nonzero("RXOVERSIZEDFRAMES         ", portnum, (baseAddr + 0x18U));
            cpsw_print_stat_nonzero("RXJABBERFRAMES            ", portnum, (baseAddr + 0x1CU));
            cpsw_print_stat_nonzero("RXUNDERSIZEDFRAMES        ", portnum, (baseAddr + 0x20U));
            cpsw_print_stat_nonzero("RXFRAGMENTS               ", portnum, (baseAddr + 0x24U));
            cpsw_print_stat_nonzero("ALE_DROP                  ", portnum, (baseAddr + 0x28U));
            cpsw_print_stat_nonzero("ALE_OVERRUN_DROP          ", portnum, (baseAddr + 0x2CU));
            cpsw_print_stat_nonzero("RXOCTETS                  ", portnum, (baseAddr + 0x30U));
            cpsw_print_stat_nonzero("TXGOODFRAMES              ", portnum, (baseAddr + 0x34U));
            cpsw_print_stat_nonzero("TXBROADCASTFRAMES         ", portnum, (baseAddr + 0x38U));
            cpsw_print_stat_nonzero("TXMULTICASTFRAMES         ", portnum, (baseAddr + 0x3CU));
            cpsw_print_stat_nonzero("TXPAUSEFRAMES             ", portnum, (baseAddr + 0x40U));
            cpsw_print_stat_nonzero("TXDEFERREDFRAMES          ", portnum, (baseAddr + 0x44U));
            cpsw_print_stat_nonzero("TXCOLLISIONFRAMES         ", portnum, (baseAddr + 0x48U));
            cpsw_print_stat_nonzero("TXSINGLECOLLFRAMES        ", portnum, (baseAddr + 0x4CU));
            cpsw_print_stat_nonzero("TXMULTCOLLFRAMES          ", portnum, (baseAddr + 0x50U));
            cpsw_print_stat_nonzero("TXEXCESSIVECOLLISIONS     ", portnum, (baseAddr + 0x54U));
            cpsw_print_stat_nonzero("TXLATECOLLISIONS          ", portnum, (baseAddr + 0x58U));
            cpsw_print_stat_nonzero("RXIPGERROR                ", portnum, (baseAddr + 0x5CU));
            cpsw_print_stat_nonzero("TXCARRIERSENSEERRORS      ", portnum, (baseAddr + 0x60U));
            cpsw_print_stat_nonzero("TXOCTETS                  ", portnum, (baseAddr + 0x64U));
            cpsw_print_stat_nonzero("OCTETFRAMES64             ", portnum, (baseAddr + 0x68U));
            cpsw_print_stat_nonzero("OCTETFRAMES65T127         ", portnum, (baseAddr + 0x6CU));
            cpsw_print_stat_nonzero("OCTETFRAMES128T255        ", portnum, (baseAddr + 0x70U));
            cpsw_print_stat_nonzero("OCTETFRAMES256T511        ", portnum, (baseAddr + 0x74U));
            cpsw_print_stat_nonzero("OCTETFRAMES512T1023       ", portnum, (baseAddr + 0x78U));
            cpsw_print_stat_nonzero("OCTETFRAMES1024TUP        ", portnum, (baseAddr + 0x7CU));
            cpsw_print_stat_nonzero("NETOCTETS                 ", portnum, (baseAddr + 0x80U));
            cpsw_print_stat_nonzero("RX_BOTTOM_OF_FIFO_DROP    ", portnum, (baseAddr + 0x84U));
            cpsw_print_stat_nonzero("PORTMASK_DROP             ", portnum, (baseAddr + 0x88U));
            cpsw_print_stat_nonzero("RX_TOP_OF_FIFO_DROP       ", portnum, (baseAddr + 0x8CU));
            cpsw_print_stat_nonzero("ALE_RATE_LIMIT_DROP       ", portnum, (baseAddr + 0x90U));
            cpsw_print_stat_nonzero("ALE_VID_INGRESS_DROP      ", portnum, (baseAddr + 0x94U));
            cpsw_print_stat_nonzero("ALE_DA_EQ_SA_DROP         ", portnum, (baseAddr + 0x98U));
            cpsw_print_stat_nonzero("ALE_BLOCK_DROP            ", portnum, (baseAddr + 0x9CU));
            cpsw_print_stat_nonzero("ALE_SECURE_DROP           ", portnum, (baseAddr + 0xA0U));
            cpsw_print_stat_nonzero("ALE_AUTH_DROP             ", portnum, (baseAddr + 0xA4U));
            cpsw_print_stat_nonzero("ALE_UNKN_UNI              ", portnum, (baseAddr + 0xA8U));
            cpsw_print_stat_nonzero("ALE_UNKN_UNI_BCNT         ", portnum, (baseAddr + 0xACU));
            cpsw_print_stat_nonzero("ALE_UNKN_MLT              ", portnum, (baseAddr + 0xB0U));
            cpsw_print_stat_nonzero("ALE_UNKN_MLT_BCNT         ", portnum, (baseAddr + 0xB4U));
            cpsw_print_stat_nonzero("ALE_UNKN_BRD              ", portnum, (baseAddr + 0xB8U));
            cpsw_print_stat_nonzero("ALE_UNKN_BRD_BCNT         ", portnum, (baseAddr + 0xBCU));
            cpsw_print_stat_nonzero("ALE_POL_MATCH             ", portnum, (baseAddr + 0xC0U));
            cpsw_print_stat_nonzero("ALE_POL_MATCH_RED         ", portnum, (baseAddr + 0xC4U));
            cpsw_print_stat_nonzero("ALE_POL_MATCH_YELLOW      ", portnum, (baseAddr + 0xC8U));
            cpsw_print_stat_nonzero("TX_MEMORY_PROTECT_ERROR   ", portnum, (baseAddr + 0x17CU));
    
            for (i = 0; i < 8; i++)
            {
                regAddr = (baseAddr + 0x180U) + (i * 0x4U);
                cpsw_print_stat_with_index_nonzero("TX_PRI_REG             ", portnum, i, regAddr);
            }
    
            for (i = 0; i < 8; i++)
            {
                regAddr = (baseAddr + 0x1A0U) + (i * 0x4U);
                cpsw_print_stat_with_index_nonzero("TX_PRI_BCNT_REG        ", portnum, i, regAddr);
            }
    
            for (i = 0; i < 8; i++)
            {
                regAddr = (baseAddr + 0x1C0U) + (i * 0x4U);
                cpsw_print_stat_with_index_nonzero("TX_PRI_DROP_REG        ", portnum, i, regAddr);
            }
    
            for (i = 0; i < 8; i++)
            {
                regAddr = (baseAddr + 0x1E0U) + (i * 0x4U);
                cpsw_print_stat_with_index_nonzero("TX_PRI_DROP_BCNT_REG   ", portnum, i, regAddr);
            }
        }
    }
    
    void cpsw_5g_statsprint_nonzero()
    {
        cpsw_ng_statsprint_nonzero(CPSW_5G_PORT_NUM);
    }
    
    void cpsw_9g_statsprint_nonzero()
    {
        cpsw_ng_statsprint_nonzero(CPSW_9G_PORT_NUM);
    }
    
    void cpsw_clear_stat(uint32_t regAddr)
    {
        uint32_t regVal = mmio_read_32(regAddr);
        mmio_write_32(regAddr, regVal);
    }
    
    void cpsw_2g_clear_stats()
    {
        uint32_t portnum, baseAddr, numStats;
    
        for (portnum = 0; portnum <= CPSW_2G_PORT_NUM; portnum++)
        {
            baseAddr = 0x4603A000U + (portnum * 0x200);
    
            printf("Clearing stats for port[%d]\n", portnum);
            for (numStats = 0; numStats < 128U; numStats++)
            {
                cpsw_clear_stat(baseAddr + (numStats*0x4));
            }
        }
    
        printf("--------CLEARED ALL STATS-------\n");
    }
    
    void show_ale_entry_multicast_2g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - Multicast\n", index);
        printf("---------------------------------------------\n");
        printf("PORT_MASK        = %x\n", (word2 >>  2) & 0x1FF);
        printf("SUPER            = %u\n", (word2 >>  1) & 0x1);
        printf("MCAST_FWD_STATE  = %u\n", (word1 >> 30) & 0x3);
        printf("ENTRY_TYPE       = %u\n", (word1 >> 28) & 0x3);
        printf("MULTICAST_ADDR   = %x %x\n", (word1 >>  0) & 0xFFFF, word0);
    }
    
    void show_ale_entry_multicast_9g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - Multicast\n", index);
        printf("---------------------------------------------\n");
        printf("PORT_MASK        = %x\n", (word2 >>  2) & 0x1FF);
        printf("SUPER            = %u\n", (word2 >>  1) & 0x1);
        printf("MCAST IGNORE BITS= %u\n", (word2 >>  0) & 0x1);
        printf("MCAST_FWD_STATE  = %u\n", (word1 >> 30) & 0x3);
        printf("ENTRY_TYPE       = %u\n", (word1 >> 28) & 0x3);
        printf("MULTICAST_ADDR   = %x %x\n", (word1 >>  0) & 0xFFFF, word0);
    }
    
    void show_ale_entry_vlan_multicast_2g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - VLAN/Multicast\n", index);
        printf("---------------------------------------------\n");
        printf("PORT_MASK        = %x\n", (word2 >>  2) & 0x1FF);
        printf("SUPER            = %u\n", (word2 >>  1) & 0x1);
        printf("MCAST_FWD_STATE  = %u\n", (word1 >> 30) & 0x3);
        printf("ENTRY_TYPE       = %u\n", (word1 >> 28) & 0x3);
        printf("VLAN_ID          = %u\n", (word1 >> 16) & 0xFFF);
        printf("MULTICAST_ADDR   = %x %x\n", (word1 >>  0) & 0xFFFF, word0);
    }
    
    void show_ale_entry_vlan_multicast_9g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - VLAN/Multicast\n", index);
        printf("---------------------------------------------\n");
        printf("PORT_MASK        = %x\n", (word2 >>  2) & 0x1FF);
        printf("SUPER            = %u\n", (word2 >>  1) & 0x1);
        printf("MCAST_FWD_STATE  = %u\n", (word1 >> 30) & 0x3);
        printf("ENTRY_TYPE       = %u\n", (word1 >> 28) & 0x3);
        printf("VLAN_ID          = %u\n", (word1 >> 16) & 0xFFF);
        printf("MULTICAST_ADDR   = %x %x\n", (word1 >>  0) & 0xFFFF, word0);
    }
    
    void show_ale_entry_unicast_2g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - Unicast\n", index);
        printf("---------------------------------------------\n");
        printf("PORT_NUMBER      = %u\n", (word2 >>  2) & 0x1FF);
        printf("BLOCK            = %u\n", (word2 >>  1) & 0x1);
        printf("SECURE           = %u\n", (word2 >>  0) & 0x1);
        printf("UNICAST_TYPE     = %u\n", (word1 >> 30) & 0x3);
        printf("ENTRY_TYPE       = %u\n", (word1 >> 28) & 0x3);
        printf("UNICAST_ADDR     = %x %x\n", (word1 >>  0) & 0xFFFF, word0);
    }
    
    void show_ale_entry_unicast_9g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - Unicast\n", index);
        printf("---------------------------------------------\n");
        printf("TRUNK            = %u\n", (word2 >> 10) & 0x1);
        printf("PORT_NUMBER      = %u\n", (word2 >> 2) & 0xF);
        printf("BLOCK            = %u\n", (word2 >> 1) & 0x1);
        printf("SECURE           = %u\n", (word2 >> 0) & 0x1);
        printf("TOUCH            = %u\n", (word1 >> 31) & 0x1);
        printf("AGEABLE          = %u\n", (word1 >> 30) & 0x1);
        printf("ENTRY_TYPE       = %u\n", (word1 >> 28) & 0x3);
        printf("UNICAST_ADDR     = %x %x\n", (word1 >>  0) & 0xFFFF, word0);
    }
    
    void show_ale_entry_oui_unicast_2g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - OUI Unicast\n", index);
        printf("---------------------------------------------\n");
        printf("UNICAST_TYPE     = %u\n", (word1 >> 30) & 0x3);
        printf("ENTRY_TYPE       = %u\n", (word1 >> 28) & 0x3);
        printf("UNICAST_OUI      = %x %x\n", (word1 >>  0) & 0xFFFF, (word0 >> 24) & 0xFF);
    }
    
    void show_ale_entry_oui_unicast_9g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - OUI Unicast\n", index);
        printf("---------------------------------------------\n");
        printf("ENTRY_TYPE       = %u\n", (word1 >> 28) & 0x3);
        printf("UNICAST_OUI      = %x %x\n", (word1 >>  0) & 0xFFFF, (word0 >> 24) & 0xFF);
    }
    
    void show_ale_entry_vlan_unicast_2g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - VLAN/Unicast\n", index);
        printf("---------------------------------------------\n");
        printf("PORT_NUMBER       = %u\n", (word2 >>  2) & 0x1FF);
        printf("BLOCK             = %u\n", (word2 >>  1) & 0x1);
        printf("SECURE            = %u\n", (word2 >>  0) & 0x1);
        printf("UNICAST_TYPE      = %u\n", (word1 >> 30) & 0x3);
        printf("ENTRY_TYPE        = %u\n", (word1 >> 28) & 0x3);
        printf("VLAN_ID           = %u\n", (word1 >> 16) & 0xFFF);
        printf("UNICAST_ADDR      = %x %x\n", (word1 >>  0) & 0xFFFF, word0);
    }
    
    void show_ale_entry_vlan_unicast_9g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - VLAN/Unicast\n", index);
        printf("---------------------------------------------\n");
        printf("TRUNK             = %u\n", (word2 >> 10) & 0x1);
        printf("PORT_NUMBER       = %u\n", (word2 >> 2) & 0x1FF);
        printf("BLOCK             = %u\n", (word2 >> 1) & 0x1);
        printf("TOUCH             = %u\n", (word1 >> 31) & 0x1);
        printf("AGEABLE           = %u\n", (word1 >> 30) & 0x1);
        printf("SECURE            = %u\n", (word2 >> 0) & 0x1);
        printf("ENTRY_TYPE        = %u\n", (word1 >> 28) & 0x3);
        printf("VLAN_ID           = %u\n", (word1 >> 16) & 0xFFF);
        printf("UNICAST_ADDR      = %x %x\n", (word1 >> 0) & 0xFFFF, word0);
    }
    
    void show_ale_entry_vlan_2g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - VLAN\n", index);
        printf("---------------------------------------------\n");
        printf("ENTRY_TYPE        = %u\n", (word1 >> 28) & 0x3);
        printf("VLAN_ID           = %u\n", (word1 >> 16) & 0xFFF);
        printf("FORCE_UNTAG_EG    = %u\n", (word0 >> 24) & 0x1FF);
        printf("REG_MCAST_FLOOD   = %u\n", (word0 >> 16) & 0x1FF);
        printf("UNREG_MCAST_FLOOD = %u\n", (word0 >>  8) & 0x1FF);
        printf("VLAN_MEMBER_LIST  = %u\n", (word0 >>  0) & 0x1FF);
    }
    
    void show_ale_entry_vlan_inner_9g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - VLAN INNER \n", index);
        printf("---------------------------------------------\n");
        printf("ENTRY_TYPE        = %u\n", (word1 >> 28) & 0x3);
        printf("IVLAN_ID           = %u\n", (word1 >> 16) & 0xFFF);
        printf("NO FRAG           = %u\n", (word1 >> 15) & 0x1);
        printf("REG_MCAST_FLOOD   = %u\n", (word1 >> 4) & 0x1FF);
        printf("VLAN FWD Untagged Egress = %u\n",
                                    ((word1 >> 0U) << 0x100) + (word0 >> 24) & 0x1FF);
        printf("LMT NEXT HDR      = %u\n", (word0 >> 23) & 0x1);
        printf("UNREG_MCAST_FLOOD = %u\n", (word0 >> 12) & 0x1FF);
        printf("VLAN_MEMBER_LIST  = %u\n", (word0 >>  0) & 0x1FF);
    }
    
    void show_ale_entry_vlan_outer_9g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - VLAN OUTER\n", index);
        printf("---------------------------------------------\n");
        printf("ENTRY_TYPE        = %u\n", (word1 >> 28) & 0x3);
        printf("OVLAN_ID           = %u\n", (word1 >> 16) & 0xFFF);
        printf("NO FRAG           = %u\n", (word1 >> 15) & 0x1);
        printf("REG_MCAST_FLOOD   = %u\n", (word1 >> 4) & 0x1FF);
        printf("VLAN FWD Untagged Egress = %u\n",
                                    ((word1 >> 0U) << 0x100) + (word0 >> 24) & 0x1FF);
        printf("LMT NEXT HDR      = %u\n", (word0 >> 23) & 0x1);
        printf("UNREG_MCAST_FLOOD = %u\n", (word0 >> 12) & 0x1FF);
        printf("VLAN_MEMBER_LIST  = %u\n", (word0 >>  0) & 0x1FF);
    }
    
    void show_ale_entry_vlan_ethertype_9g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - VLAN ETHERTYPE \n", index);
        printf("---------------------------------------------\n");
        printf("ENTRY_TYPE        = %u\n", (word1 >> 28) & 0x3);
        printf("ETHERTYPE  = %u\n", (word0 >>  0) & 0xFFFF);
    }
    
    void show_ale_entry_vlan_ip4_9g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - VLAN IPV4 \n", index);
        printf("---------------------------------------------\n");
        printf("IGNORE BITS       = %u\n", (word2 >> 1) & 0x1F);
        printf("ENTRY_TYPE        = %u\n", (word1 >> 28) & 0x3);
        printf("IPV4 ADDR  = %u\n", word0);
    }
    
    void show_ale_entry_vlan_ip6_9g(uint32_t index, uint32_t word0, uint32_t word1, uint32_t word2)
    {
        printf("---------------------------------------------\n");
        printf(" Entry %u - VLAN IPV6 \n", index);
        printf("---------------------------------------------\n");
        printf("Understanding Gap hence not printing :(");
    }
    
    void cpsw_print_ale_table_2g()
    {
        uint32_t word0, word1, word2;
        uint32_t type;
        int i;
    
        printf("---------------------------------------------\n");
        printf("-------CPSW2G ALE TABLE----------------------\n");
        printf("---------------------------------------------\n");
    
        for (i = 0; i < ALE_TABLE_DEPTH_2G; i++)
        {
            mmio_write_32(ALE_TBLCTL_2G, i);
    
            word0 = mmio_read_32(ALE_TBLW0_2G);
            word1 = mmio_read_32(ALE_TBLW1_2G);
            word2 = mmio_read_32(ALE_TBLW2_2G);
    
            if (0)
            {
    
                printf("WORD1  = %u\n", word0);
                printf("WORD1  = %u\n", word1);
                printf("WORD1  = %u\n", word2);
            }
    
            /* ENTRY_TYPE (bits 61:60) */
            type = (word1 >> 28) & 0x3;
    
            if (type == ALE_ENTRY_EMTPY) {
                //printf(" Entry %u - Empty\n", i);
            } else if (type == ALE_ENTRY_ADDR) {
                if ((word1 >> 8) & 0x1) {
                    show_ale_entry_multicast_2g(i, word0, word1, word2);
    //            } else if ((word1 >> 30) & 0x3) {
    //                show_ale_entry_oui_unicast(i, word0, word1, word2);
                } else {
                    show_ale_entry_unicast_2g(i, word0, word1, word2);
                }
            } else if (type == ALE_ENTRY_VLAN) {
                show_ale_entry_vlan_2g(i, word0, word1, word2);
            } else if (type == ALE_ENTRY_VLAN_ADDR) {
                if ((word1 >> 8) & 0x1) {
                    show_ale_entry_vlan_multicast_2g(i, word0, word1, word2);
                } else {
                    show_ale_entry_vlan_unicast_2g(i, word0, word1, word2);
                }
            }
        }
    
        printf("Completed analysis of %u ALE entries\n", i);
    }
    
    void cpsw_print_ale_table_ng(numAleEntries)
    {
        uint32_t word0, word1, word2;
        uint32_t type;
        uint32_t vlanEntryType;
        int i;
    
        printf("---------------------------------------------\n");
        printf("-------CPSWnG ALE TABLE----------------------\n");
        printf("---------------------------------------------\n");
        for (i = 0; i < numAleEntries; i++)
        {
            mmio_write_32(ALE_TBLCTL_9G, i);
    
            word0 = mmio_read_32(ALE_TBLW0_9G);
            word1 = mmio_read_32(ALE_TBLW1_9G);
            word2 = mmio_read_32(ALE_TBLW2_9G);
    
            if (0)
            {
                printf("WORD0  = %x\n", word0);
                printf("WORD1  = %x\n", word1);
                printf("WORD2  = %x\n", word2);
            }
    
            /* ENTRY_TYPE (bits 61:60) */
            type = (word1 >> 28) & 0x3;
    
            if (type == ALE_ENTRY_EMTPY)
            {
                //printf(" Entry %u - Empty\n", i);
            }
            else if (type == ALE_ENTRY_ADDR)
            {
                if ((word1 >> 8) & 0x1)
                {
                    show_ale_entry_multicast_9g(i, word0, word1, word2);
                }
                else if ( ((word1 >> 30) & 0x3) == 0x2 )
                {
                   show_ale_entry_oui_unicast_9g(i, word0, word1, word2);
                }
                else
                {
                    show_ale_entry_unicast_9g(i, word0, word1, word2);
                }
            }
            else if (type == ALE_ENTRY_VLAN)
            {
                vlanEntryType = ((word1 >> 30) & 0x3);
                vlanEntryType |= ((word2 >> 0) & 0x1);
    
                if ( 0x0 == vlanEntryType)
                {
                    show_ale_entry_vlan_inner_9g(i, word0, word1, word2);
                }
                else if ( 0x2 == vlanEntryType)
                {
                    show_ale_entry_vlan_outer_9g(i, word0, word1, word2);
                }
                else if ( 0x4 == vlanEntryType)
                {
                    show_ale_entry_vlan_ethertype_9g(i, word0, word1, word2);
                }
                else if ( 0x6 == vlanEntryType )
                {
                    show_ale_entry_vlan_ip4_9g(i, word0, word1, word2);
                }
                else if ((word1 >> 30) & 0x1)
                {
                    show_ale_entry_vlan_ip6_9g(i, word0, word1, word2);
                }
    
            }
            else if (type == ALE_ENTRY_VLAN_ADDR)
            {
                if ((word1 >> 8) & 0x1)
                {
                    show_ale_entry_vlan_multicast_9g(i, word0, word1, word2);
                }
                else {
                    show_ale_entry_vlan_unicast_9g(i, word0, word1, word2);
                }
            }
        }
    
        printf("Completed analysis of %u ALE entries\n", i);
    }
    
    void cpsw_print_ale_table_5g()
    {
        cpsw_print_ale_table_ng(ALE_TABLE_DEPTH_5G);
    }
    
    void cpsw_print_ale_table_9g()
    {
        cpsw_print_ale_table_ng(ALE_TABLE_DEPTH_9G);
    }
    
    void cpsw_ng_clear_stats(uint32_t numMacPorts)
    {
        uint32_t portnum, baseAddr, numStats;
    
        for (portnum = 0; portnum <= numMacPorts; portnum++)
        {
            baseAddr = 0x0C03A000U + (portnum * 0x200);
    
            printf("Clearing stats for port[%d]\n",portnum);
            for (numStats = 0; numStats < 128U; numStats++)
            {
                cpsw_clear_stat(baseAddr + (numStats*0x4));
            }
        }
    
        printf("--------CLEARED ALL STATS-------\n");
    }
    
    void cpsw_5g_clear_stats()
    {
        cpsw_ng_clear_stats(CPSW_5G_PORT_NUM);
    }
    
    void cpsw_9g_clear_stats()
    {
        cpsw_ng_clear_stats(CPSW_9G_PORT_NUM);
    }
    
    int main()
    {
        //cpsw_9g_statsprint_nonzero();
        cpsw_print_ale_table_5g();
        
    }
    

    This file needs to be compiled on the device using GCC and executed. It has functions for various tasks, from print statistics to printing ALE entries.

    References

    1. DRA829 Technical Reference Manual
    2. Ethernet Firmware User Guide
    3. ENET ALE API Guide
    4. 802.1 Q - 2014

    Regards

    Vineet