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

    IX_ETH_DB_CHECK_PORT_EXISTS(portID);

    IX_ETH_DB_CHECK_SINGLE_NPE(portID);
    
    portInfo = &ixEthDBPortInfo[portID];

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

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

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

        ixEthDBPortState[portID].saved = TRUE;

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

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

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

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

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

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

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

        /* save and disable the learning feature bit */
        learningEnabled          = portInfo->featureStatus & IX_ETH_DB_LEARNING;
        portInfo->featureStatus &= ~IX_ETH_DB_LEARNING;
    }
    else
    {
        /* save the learning feature bit */
        learningEnabled          = portInfo->featureStatus & IX_ETH_DB_LEARNING;
    }
    
    SET_EMPTY_DEPENDENCY_MAP(triggerPorts);
    
    ixEthDBUpdateLock();
    
    /* wipe out current entries for this port */
    BUSY_RETRY(ixEthDBInitHashIterator(&dbHashtable, &iterator));

    while (IS_ITERATOR_VALID(&iterator))
    {
        MacDescriptor *descriptor =  (MacDescriptor *) iterator.node->data;
    
        /* check if the port match. If so, remove the entry  */
        if (descriptor->portID == portID 
                && (descriptor->type == IX_ETH_DB_FILTERING_RECORD || descriptor->type == IX_ETH_DB_FILTERING_VLAN_RECORD)
                && !descriptor->recordData.filteringData.staticEntry)
        {
            /* delete entry */
            BUSY_RETRY(ixEthDBRemoveEntryAtHashIterator(&dbHashtable, &iterator));
            
            /* add port to the set of update trigger ports */
            JOIN_PORT_TO_MAP(triggerPorts, portID);
        }
        else
        {
            /* move to the next record */
            BUSY_RETRY(ixEthDBIncrementHashIterator(&dbHashtable, &iterator));
        }
    }
    
    if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
    {
        if (portInfo->updateMethod.searchTree != NULL)
        {
            ixEthDBFreeMacTreeNode(portInfo->updateMethod.searchTree);
            portInfo->updateMethod.searchTree = NULL;
        }

        ixEthDBNPEUpdateHandler(portID, IX_ETH_DB_FILTERING_RECORD);
    }

    /* mark as disabled */
    portInfo->enabled = FALSE;
    
    /* disable updates unless the user has specifically altered the default behavior */
    if (ixEthDBPortDefinitions[portID].type == IX_ETH_NPE)
    {
        if (!portInfo->updateMethod.userControlled)
        {  
            portInfo->updateMethod.updateEnabled = FALSE;
        }
            
        /* make sure we re-initialize the NPE learning tree when the port is re-enabled */
        portInfo->updateMethod.treeInitialized = FALSE;
    }

    ixEthDBUpdateUnlock();

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

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

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

    IX_ETH_DB_CHECK_PORT_EXISTS(portID);

    IX_ETH_DB_CHECK_SINGLE_NPE(portID);
    
    portInfo = &ixEthDBPortInfo[portID];
    
    if (portInfo->enabled)
    {
        /* redundant */
        return IX_ETH_DB_SUCCESS;
    }

    SET_DEPENDENCY_MAP(triggerPorts, portID);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    return IX_ETH_DB_SUCCESS;
}
Esempio n. 3
0
/**
 * @brief scans the capabilities of the loaded NPE images
 *
 * This function MUST be called by the ixEthDBInit() function.
 * No EthDB features (including learning and filtering) are enabled
 * before this function is called.
 *
 * @return none
 *
 * @internal
 */
IX_ETH_DB_PUBLIC
void ixEthDBFeatureCapabilityScan(void)
{
    UINT8 functionalityId, npeAFunctionalityId;
    IxEthDBPortId portIndex;
    PortInfo *portInfo;
    IxEthDBPriorityTable defaultPriorityTable;
    IX_STATUS result;
    UINT32 queueIndex;
    UINT32 queueStructureIndex;
    UINT32 trafficClassDefinitionIndex, totalTrafficClass;

    totalTrafficClass = sizeof (ixEthDBTrafficClassDefinitions) / sizeof (ixEthDBTrafficClassDefinitions[0]);

    /* ensure there's at least 2 traffic class records in the definition table, otherwise we have no default cases, hence no queues */
    IX_ENSURE(totalTrafficClass >= 2, 
	"DB: no traffic class definitions found, check IxEthDBQoS.h");

    /* read version of NPE A - required to set the AQM queues for B and C */
    npeAFunctionalityId = 0;

    if(IX_FAIL == ixNpeDlLoadedImageFunctionalityGet(IX_NPEDL_NPEID_NPEA, &npeAFunctionalityId))
    {
        /* IX_FAIL is returned when there is no image loaded in NPEA.  Then we can use all 8 queues */
        trafficClassDefinitionIndex = 1; /* the second record is the default if no image loaded */
    } 
    else 
    {
        /* find the traffic class definition index compatible with the current NPE A functionality ID */
        for (trafficClassDefinitionIndex = 0 ; 
             trafficClassDefinitionIndex < totalTrafficClass ;
             trafficClassDefinitionIndex++)
        {
            if (ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_NPE_A_FUNCTIONALITY_ID_INDEX] == npeAFunctionalityId)
            {
                /* found it */
                break;
            }
        }

        /* select the default case if we went over the array boundary */
        if (trafficClassDefinitionIndex == totalTrafficClass)
        {
            trafficClassDefinitionIndex = 0; /* the first record is the default case */
        }
    }

    /* To decide port definition for NPE A - IX_ETH_NPE or IX_ETH_GENERIC 
       IX_ETH_NPE will be set for NPE A when the functionality id is ranged from 0x80 to 0x8F
       and ethernet + hss co-exists images range from 0x90 to 0x9F. For the rest of functionality 
       Ids, the port type will be set to IX_ETH_GENERIC. */
    if ((npeAFunctionalityId & 0xF0) != 0x80 && (npeAFunctionalityId & 0xF0) != 0x90)
    {
        /* NPEA is not Ethernet capable. Override default port definition */
	ixEthDBPortDefinitions[IX_NPEA_PORT].type = IX_ETH_GENERIC;
    }

    /* select queue assignment structure based on the traffic class configuration index */
    queueStructureIndex = ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_QUEUE_ASSIGNMENT_INDEX];

    for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++)
    {
        IxNpeMhMessage msg;

        portInfo = &ixEthDBPortInfo[portIndex];

        /* check and bypass if NPE A, B or C is fused out */
        if (ixEthDBSingleEthNpeCheck(portIndex) != IX_ETH_DB_SUCCESS) continue;
        
        /* all ports are capable of LEARNING by default */
        portInfo->featureCapability = IX_ETH_DB_LEARNING;
        portInfo->featureStatus     = IX_ETH_DB_LEARNING;

        if (ixEthDBPortDefinitions[portIndex].type == IX_ETH_NPE)
        {

            if (IX_SUCCESS != ixNpeDlLoadedImageFunctionalityGet(IX_ETHNPE_PHYSICAL_ID_TO_NODE(portIndex), &functionalityId))
            {
                WARNING_LOG("DB: (FeatureScan) NpeDl did not provide the image ID for NPE port %d\n", portIndex);
            }
            else
            {
                /* initialize and empty NPE response mutex */
                ixOsalMutexInit(&portInfo->npeAckLock);
		ixOsalMutexLock(&portInfo->npeAckLock, IX_OSAL_WAIT_FOREVER);
                /* check NPE response to GetStatus */
                msg.data[0] = IX_ETHNPE_NPE_GETSTATUS << 24;
                msg.data[1] = 0;
                IX_ETHDB_SEND_NPE_MSG(IX_ETHNPE_PHYSICAL_ID_TO_NODE(portIndex), msg, result);
                if (result != IX_SUCCESS)
                {
                    WARNING_LOG("DB: (FeatureScan) warning, %d port could not send message to the NPE\n", portIndex);
                    continue;
                }

                if (functionalityId == 0x00
                    || functionalityId == 0x03
                    || functionalityId == 0x04
                    || functionalityId == 0x80)
                {
                    portInfo->featureCapability |= IX_ETH_DB_FILTERING;
                    portInfo->featureCapability |= IX_ETH_DB_FIREWALL;
                    portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
                }
                else if (functionalityId == 0x01
                         || functionalityId == 0x81
                         || functionalityId == 0x0B
                         || functionalityId == 0x8B
                         || functionalityId == 0x90)
                {
                    portInfo->featureCapability |= IX_ETH_DB_FILTERING;
                    portInfo->featureCapability |= IX_ETH_DB_FIREWALL;
                    portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
                    portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS;
                }
                else if (functionalityId == 0x02
                         || functionalityId == 0x82
                         || functionalityId == 0x0D
                         || functionalityId == 0x8D
                         || functionalityId == 0x91)
                {
                    portInfo->featureCapability |= IX_ETH_DB_WIFI_HEADER_CONVERSION;
                    portInfo->featureCapability |= IX_ETH_DB_FIREWALL;
                    portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
                    portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS;
                }
                else if (functionalityId == 0x0C
			 || functionalityId == 0x8C)
                {
                    portInfo->featureCapability |= IX_ETH_DB_WIFI_HEADER_CONVERSION;
                    portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL;
                    portInfo->featureCapability |= IX_ETH_DB_VLAN_QOS;
                }

                /* check if image supports mask based firewall */
                if (functionalityId == 0x0B
                    || functionalityId == 0x8B
                    || functionalityId == 0x0D
                    || functionalityId == 0x8D
                    || functionalityId == 0x90
                    || functionalityId == 0x91)
                {
                    /* this feature is always on and is based on the NPE */
                    portInfo->featureStatus |= IX_ETH_DB_ADDRESS_MASKING;
                    portInfo->featureCapability |= IX_ETH_DB_ADDRESS_MASKING;
                }

                /* reset AQM queues */
                ixOsalMemSet(portInfo->ixEthDBTrafficClassAQMAssignments, 0, sizeof (portInfo->ixEthDBTrafficClassAQMAssignments));

                /* only traffic class 0 is active at initialization time */
                portInfo->ixEthDBTrafficClassCount = 1;

                /* enable port, VLAN and Firewall feature bits to initialize QoS/VLAN/Firewall configuration */
                portInfo->featureStatus |= IX_ETH_DB_VLAN_QOS;
                portInfo->featureStatus |= IX_ETH_DB_FIREWALL;
                portInfo->enabled        = TRUE;

                /* set VLAN initial configuration (permissive) */
                if ((portInfo->featureCapability & IX_ETH_DB_VLAN_QOS) != 0) /* QoS-enabled image */
                {
                    /* QoS capable */
                    portInfo->ixEthDBTrafficClassAvailable = ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_TRAFFIC_CLASS_COUNT_INDEX];

                    /* set AQM queues */
                    for (queueIndex = 0 ; queueIndex < IX_IEEE802_1Q_QOS_PRIORITY_COUNT ; queueIndex++)
                    {
                        portInfo->ixEthDBTrafficClassAQMAssignments[queueIndex] = ixEthDBQueueAssignments[queueStructureIndex][queueIndex];
                    }

                    /* set default PVID (0) and default traffic class 0 */
                    ixEthDBPortVlanTagSet(portIndex, 0);

                    /* enable reception of all frames */
                    ixEthDBAcceptableFrameTypeSet(portIndex, IX_ETH_DB_ACCEPT_ALL_FRAMES);

                    /* clear full VLAN membership */
                    ixEthDBPortVlanMembershipRangeRemove(portIndex, 0, IX_ETH_DB_802_1Q_MAX_VLAN_ID);

                    /* clear TTI table - no VLAN tagged frames will be transmitted */
                    ixEthDBEgressVlanRangeTaggingEnabledSet(portIndex, 0, 4094, FALSE);

                    /* set membership on 0, otherwise no Tx or Rx is working */
                    ixEthDBPortVlanMembershipAdd(portIndex, 0);
                }
                else /* QoS not available in this image */
                {
                    /* initialize traffic class availability (only class 0 is available) */
                    portInfo->ixEthDBTrafficClassAvailable = 1;

                    /* point all AQM queues to traffic class 0 */
                    for (queueIndex = 0 ; queueIndex < IX_IEEE802_1Q_QOS_PRIORITY_COUNT ; queueIndex++)
                    {
                        portInfo->ixEthDBTrafficClassAQMAssignments[queueIndex] = 
                            ixEthDBQueueAssignments[queueStructureIndex][0];
                    }
                }

                /* download priority mapping table and Rx queue configuration */
                ixOsalMemSet (defaultPriorityTable, 0, sizeof (defaultPriorityTable));
                ixEthDBPriorityMappingTableSet(portIndex, defaultPriorityTable);

                /* by default we turn on invalid source MAC address filtering */
                ixEthDBFirewallInvalidAddressFilterEnable(portIndex, TRUE);

                /* Notify VLAN tagging is disabled */
		if (ixEthDBIngressVlanTaggingEnabledSet(portIndex, IX_ETH_DB_DISABLE_VLAN)
		    != IX_SUCCESS)
		{
		  WARNING_LOG("DB: (FeatureScan) warning, %d port could not disable VLAN \n", portIndex);
		  continue;		  
		}

                /* disable port, VLAN, Firewall feature bits */
                portInfo->featureStatus &= ~IX_ETH_DB_VLAN_QOS;
                portInfo->featureStatus &= ~IX_ETH_DB_FIREWALL;
                portInfo->enabled        = FALSE;

                /* enable filtering by default if present */
                if ((portInfo->featureCapability & IX_ETH_DB_FILTERING) != 0)
                {
                    portInfo->featureStatus |= IX_ETH_DB_FILTERING;
                }
            }
        } 
    }
}
/**
 * @brief enables or disables a port capability
 *
 * @param portID ID of the port
 * @param feature feature to enable or disable
 * @param enabled TRUE to enable the selected feature or FALSE to disable it
 *
 * Note that this function is documented in the main component
 * header file, IxEthDB.h.
 *
 * @return IX_ETH_DB_SUCCESS if the operation completed
 * successfully or an appropriate error message otherwise
 */
IX_ETH_DB_PUBLIC
IxEthDBStatus ixEthDBFeatureEnable(IxEthDBPortId portID, IxEthDBFeature feature, BOOL enable)
{
    PortInfo *portInfo;
    IxEthDBPriorityTable defaultPriorityTable;
    IxEthDBVlanSet vlanSet;
    IxEthDBStatus status = IX_ETH_DB_SUCCESS;
    BOOL portEnabled;

    IX_ETH_DB_CHECK_PORT_INITIALIZED(portID);

    portInfo    = &ixEthDBPortInfo[portID];
    portEnabled = portInfo->enabled;

    /* check that only one feature is selected */
    if (!ixEthDBCheckSingleBitValue(feature))
    {
        return IX_ETH_DB_FEATURE_UNAVAILABLE;
    }

    /* port capable of this feature? */
    if ((portInfo->featureCapability & feature) == 0)
    {
        return IX_ETH_DB_FEATURE_UNAVAILABLE;
    }

    /* mutual exclusion between learning and WiFi header conversion */
    if (enable && ((feature | portInfo->featureStatus) & (IX_ETH_DB_FILTERING | IX_ETH_DB_WIFI_HEADER_CONVERSION))
            == (IX_ETH_DB_FILTERING | IX_ETH_DB_WIFI_HEADER_CONVERSION))
    {
        return IX_ETH_DB_NO_PERMISSION;
    }

    /* learning must be enabled before filtering */
    if (enable && (feature == IX_ETH_DB_FILTERING) && ((portInfo->featureStatus & IX_ETH_DB_LEARNING) == 0))
    {
        return IX_ETH_DB_NO_PERMISSION;
    }

    /* filtering must be disabled before learning */
    if (!enable && (feature == IX_ETH_DB_LEARNING) && ((portInfo->featureStatus & IX_ETH_DB_FILTERING) != 0))
    {
        return IX_ETH_DB_NO_PERMISSION;
    }

    /* redundant enabling or disabling */
    if ((!enable && ((portInfo->featureStatus & feature) == 0))
        || (enable && ((portInfo->featureStatus & feature) != 0)))
    {
        /* do nothing */
        return IX_ETH_DB_SUCCESS;
    }

    /* force port enabled */
    portInfo->enabled = TRUE;

    if (enable)
    {
        /* turn on enable bit */
        portInfo->featureStatus |= feature;

#ifdef CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */
        /* if this is VLAN/QoS set the default priority table */
        if (feature == IX_ETH_DB_VLAN_QOS)
        {
            /* turn on VLAN/QoS (most permissive mode):
                - set default 802.1Q priority mapping table, in accordance to the
                  availability of traffic classes
                - set the acceptable frame filter to accept all
                - set the Ingress tagging mode to pass-through
                - set full VLAN membership list
                - set full TTI table
                - set the default 802.1Q tag to 0 (VLAN ID 0, Pri 0, CFI 0)
                - enable TPID port extraction
            */

            portInfo->ixEthDBTrafficClassCount = portInfo->ixEthDBTrafficClassAvailable;

            /* set default 802.1Q priority mapping table - note that C indexing starts from 0, so we substract 1 here */
            memcpy (defaultPriorityTable,
                (const void *) ixEthIEEE802_1QUserPriorityToTrafficClassMapping[portInfo->ixEthDBTrafficClassCount - 1],
                sizeof (defaultPriorityTable));

            /* update priority mapping and AQM queue assignments */
            status = ixEthDBPriorityMappingTableSet(portID, defaultPriorityTable);

            if (status == IX_ETH_DB_SUCCESS)
            {
                status = ixEthDBAcceptableFrameTypeSet(portID, IX_ETH_DB_ACCEPT_ALL_FRAMES);
            }

            if (status == IX_ETH_DB_SUCCESS)
            {
                status = ixEthDBIngressVlanTaggingEnabledSet(portID, IX_ETH_DB_PASS_THROUGH);
            }

            /* set membership and TTI tables */
            memset (vlanSet, 0xFF, sizeof (vlanSet));

            if (status == IX_ETH_DB_SUCCESS)
            {
                /* use the internal function to bypass PVID check */
                status = ixEthDBPortVlanTableSet(portID, portInfo->vlanMembership, vlanSet);
            }

            if (status == IX_ETH_DB_SUCCESS)
            {
                /* use the internal function to bypass PVID check */
                status = ixEthDBPortVlanTableSet(portID, portInfo->transmitTaggingInfo, vlanSet);
            }

            /* reset the PVID */
            if (status == IX_ETH_DB_SUCCESS)
            {
                status = ixEthDBPortVlanTagSet(portID, 0);
            }

            /* enable TPID port extraction */
            if (status == IX_ETH_DB_SUCCESS)
            {
                status = ixEthDBVlanPortExtractionEnable(portID, TRUE);
            }
        }
        else if (feature == IX_ETH_DB_FIREWALL)
#endif
        {
            /* firewall starts in black-list mode unless otherwise configured before *
             * note that invalid source MAC address filtering is disabled by default */
            if (portInfo->firewallMode != IX_ETH_DB_FIREWALL_BLACK_LIST
                && portInfo->firewallMode != IX_ETH_DB_FIREWALL_WHITE_LIST)
            {
                status = ixEthDBFirewallModeSet(portID, IX_ETH_DB_FIREWALL_BLACK_LIST);

                if (status == IX_ETH_DB_SUCCESS)
                {
                    status = ixEthDBFirewallInvalidAddressFilterEnable(portID, FALSE);
                }
            }
        }

        if (status != IX_ETH_DB_SUCCESS)
        {
            /* checks failed, disable */
            portInfo->featureStatus &= ~feature;
        }
    }
    else
    {
        /* turn off features */
        if (feature == IX_ETH_DB_FIREWALL)
        {
            /* turning off the firewall is equivalent to:
                - set to black-list mode
                - clear all the entries and download the new table
                - turn off the invalid source address checking
            */

            status = ixEthDBDatabaseClear(portID, IX_ETH_DB_FIREWALL_RECORD);

            if (status == IX_ETH_DB_SUCCESS)
            {
                status = ixEthDBFirewallModeSet(portID, IX_ETH_DB_FIREWALL_BLACK_LIST);
            }

            if (status == IX_ETH_DB_SUCCESS)
            {
                status = ixEthDBFirewallInvalidAddressFilterEnable(portID, FALSE);
            }

            if (status == IX_ETH_DB_SUCCESS)
            {
                status = ixEthDBFirewallTableDownload(portID);
            }
        }
        else if (feature == IX_ETH_DB_WIFI_HEADER_CONVERSION)
        {
            /* turn off header conversion */
            status = ixEthDBDatabaseClear(portID, IX_ETH_DB_WIFI_RECORD);

            if (status == IX_ETH_DB_SUCCESS)
            {
                status = ixEthDBWiFiConversionTableDownload(portID);
            }
        }
#ifdef CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */
        else if (feature == IX_ETH_DB_VLAN_QOS)
        {
            /* turn off VLAN/QoS:
                - set a priority mapping table with one traffic class
                - set the acceptable frame filter to accept all
                - set the Ingress tagging mode to pass-through
                - clear the VLAN membership list
                - clear the TTI table
                - set the default 802.1Q tag to 0 (VLAN ID 0, Pri 0, CFI 0)
                - disable TPID port extraction
            */

            /* initialize all => traffic class 0 priority mapping table */
            memset (defaultPriorityTable, 0, sizeof (defaultPriorityTable));
            portInfo->ixEthDBTrafficClassCount = 1;
            status = ixEthDBPriorityMappingTableSet(portID, defaultPriorityTable);

            if (status == IX_ETH_DB_SUCCESS)
            {
                status = ixEthDBAcceptableFrameTypeSet(portID, IX_ETH_DB_ACCEPT_ALL_FRAMES);
            }

            if (status == IX_ETH_DB_SUCCESS)
            {
                status = ixEthDBIngressVlanTaggingEnabledSet(portID, IX_ETH_DB_PASS_THROUGH);
            }

            /* clear membership and TTI tables */
            memset (vlanSet, 0, sizeof (vlanSet));

            if (status == IX_ETH_DB_SUCCESS)
            {
                /* use the internal function to bypass PVID check */
                status = ixEthDBPortVlanTableSet(portID, portInfo->vlanMembership, vlanSet);
            }

            if (status == IX_ETH_DB_SUCCESS)
            {
                /* use the internal function to bypass PVID check */
                status = ixEthDBPortVlanTableSet(portID, portInfo->transmitTaggingInfo, vlanSet);
            }

            /* reset the PVID */
            if (status == IX_ETH_DB_SUCCESS)
            {
                status = ixEthDBPortVlanTagSet(portID, 0);
            }

            /* disable TPID port extraction */
            if (status == IX_ETH_DB_SUCCESS)
            {
                status = ixEthDBVlanPortExtractionEnable(portID, FALSE);
            }
        }
#endif

        if (status == IX_ETH_DB_SUCCESS)
        {
            /* checks passed, disable */
            portInfo->featureStatus &= ~feature;
        }
    }

    /* restore port enabled state */
    portInfo->enabled = portEnabled;

    return status;
}
Esempio n. 5
0
/*
 * Function definition: ixEthAccCodeletSwBridgeQoSStart()
 *
 * Configure QoS and Start bridge datapath
 */
IX_STATUS ixEthAccCodeletSwBridgeQoSStart(IxEthAccPortId firstPortId, 
					  IxEthAccPortId secondPortId)
{
    UINT32 firstPortCbTag = firstPortId | (secondPortId << 16);
    UINT32 secondPortCbTag = secondPortId | (firstPortId << 16);

    IxEthDBPriorityTable priorityTable = { 0,1,2,3,4,5,6,7};
    IxEthDBFeature featureSet = 0;

    if (firstPortId == secondPortId)
    {
	printf("SwBridgeQoS: Cannot configure a Bridge Operation between port %u and port %u (ports must be different)\n",
	       firstPortId, 
               secondPortId);
	return (IX_FAIL);
    }

    /* initialize pendingTx for both ports */
    pendingTx[firstPortId] = pendingTx[secondPortId] = 0;

    /* register the rx/tx callback */
    if ( ixEthAccCodeletPortConfigure(firstPortId, 
	      ixEthAccCodeletSwBridgeQoSTaggedToUntaggedRxCB, 
	      (IxEthAccPortMultiBufferRxCallback) NULL,
	      ixEthAccCodeletSwBridgeQoSTxCB,
	      firstPortCbTag) != IX_SUCCESS)
    {
	printf("SwBridgeQoS: Failed to configure the Bridge Operation for port %u\n",
	       firstPortId);
	return (IX_FAIL);
    }

    if ( ixEthAccCodeletPortConfigure(secondPortId, 
	      ixEthAccCodeletSwBridgeQoSUntaggedToTaggedRxCB, 
	      NULL,
	      ixEthAccCodeletSwBridgeQoSTxCB,
	      secondPortCbTag) != IX_SUCCESS)
    {
	printf("SwBridgeQoS: Failed to configure the Bridge Operation for port %u\n",
	       secondPortId);
	return (IX_FAIL);
    }

    /* Enable the VLAN/QoS Feature in EthDB for each port but first 
     * check that the Firmware downloaded to the NPE can support it
     */
    ixEthDBFeatureCapabilityGet((IxEthDBPortId)firstPortId, &featureSet);
    
    if ((featureSet & IX_ETH_DB_VLAN_QOS) == 0)
    {
	printf("SwBridgeQoS: Port %u NPE image not VLAN/QoS capable\n",
	       firstPortId);
	return (IX_FAIL);
    }

    if ( ixEthDBFeatureEnable((IxEthDBPortId)firstPortId, 
			      IX_ETH_DB_VLAN_QOS,
			      TRUE) != IX_ETH_DB_SUCCESS )
    {
	printf("SwBridgeQoS: Failed to enable VLAN/QoS on port %u\n",
	       firstPortId);
	return (IX_FAIL);
    }

    /* Enable the EthDB Port in order to configure and download the
     * VLAN/QoS configuration information
     */ 
    if ((ixEthDBPortEnable(firstPortId)) != IX_ETH_DB_SUCCESS)
    {
        printf("SwBridgeQoS: Cannot enable port %u\n", firstPortId);
        return (IX_FAIL);
    }
    if ((ixEthDBPortEnable(secondPortId)) != IX_ETH_DB_SUCCESS)
    {
        printf("SwBridgeQos: Cannot enable port %u\n", secondPortId);
        return (IX_FAIL);
    }

    /* Configure Xscale QoS : the access layer datapath 
     * prioritizes the different classes of traffic.
     */
    printf("Set Tx Scheduling discipline...\n");
    if (ixEthAccTxSchedulingDisciplineSet(firstPortId, 
					  FIFO_PRIORITY)
	!= IX_ETH_ACC_SUCCESS)
    {
	printf("SwBridgeQos: Failed to set Tx Scheduling for discipline port %u\n",
	       (UINT32)firstPortId);
	return (IX_FAIL);
    }

    if (ixEthAccTxSchedulingDisciplineSet(secondPortId, 
					  FIFO_PRIORITY)
	!= IX_ETH_ACC_SUCCESS)
    {
	printf("SwBridgeQos: Failed to set Tx Scheduling for discipline port %u\n",
	       (UINT32)secondPortId);
	return (IX_FAIL);
    }

    printf("Set Rx Scheduling discipline...\n");
    if (ixEthAccRxSchedulingDisciplineSet(FIFO_PRIORITY)
	!= IX_ETH_ACC_SUCCESS)
    {
	printf("SwBridgeQos: Failed to set Rx Scheduling discipline!\n");
	return (IX_FAIL);
    }

    /* NPE QoS : Configure VLAN traffic for highest priority 
     * on first port. Tagging is enabled on Egress (use default tag
     * for this port) and untagging is enabled on ingress.
     * The traffic running on this bridge will be untagged.
     */
    printf("Set VLAN default tag...\n");
    if (ixEthDBPortVlanTagSet(firstPortId, 
			      IX_ETHACC_CODELET_VLANID_DEFAULT)
	!= IX_ETH_DB_SUCCESS)
    {
	printf("SwBridgeQos: Failed to set the default VLAN ID for port %u\n",
	       firstPortId);
	return (IX_FAIL);
    }

    printf("Enable tagged frames...\n");
    if (ixEthDBAcceptableFrameTypeSet(firstPortId,
				      IX_ETH_DB_VLAN_TAGGED_FRAMES
				      | IX_ETH_DB_UNTAGGED_FRAMES)
	!= IX_ETH_DB_SUCCESS)
    {
	printf("SwBridgeQos: Failed to set the acceptable frame type for port %u\n",
	       firstPortId);
	return (IX_FAIL);
    }

    printf("Setting VLAN membership...\n");

    /* by default the entire VLAN range 0-4094 is included in the
       port VLAN membership table, therefore we need to remove all 
       VLAN IDs but 0 (which is required to accept untagged frames) */
    if (ixEthDBPortVlanMembershipRangeRemove(firstPortId, 
        1, IX_ETH_DB_802_1Q_MAX_VLAN_ID) != IX_ETH_DB_SUCCESS)
    {
        printf("SwBridgeQos: Failed to set VLAN membership for port %u\n", firstPortId);
        return (IX_FAIL);
    }

    /* now add the range used by this codelet */
    if (ixEthDBPortVlanMembershipRangeAdd(firstPortId, 
					  IX_ETHACC_CODELET_VLANID_MIN,
					  IX_ETHACC_CODELET_VLANID_MAX)
	!= IX_ETH_DB_SUCCESS)
    {
	printf("SwBridgeQos: Failed to set VLAN membership for port %u\n",
	       firstPortId);
	return (IX_FAIL);
    }

    printf("Enable Egress VLAN tagging...\n");
    if (ixEthDBEgressVlanRangeTaggingEnabledSet(firstPortId, 
						IX_ETHACC_CODELET_VLANID_MIN,
						IX_ETHACC_CODELET_VLANID_MAX,
						TRUE)
	!= IX_ETH_DB_SUCCESS)
    {
	printf("SwBridgeQos: Failed to enable VLAN Egress tagging for port %u\n",
	       firstPortId);
	return (IX_FAIL);
    }

    printf("Enable Ingress VLAN untagging...\n");
    if (ixEthDBIngressVlanTaggingEnabledSet(firstPortId, 
					    IX_ETH_DB_REMOVE_TAG)
	!= IX_ETH_DB_SUCCESS)
    {
	printf("SwBridgeQos: Failed to enable VLAN Ingress untagging for port %u\n",
	       firstPortId);
	return (IX_FAIL);
    }
    
    printf("Setup priority mapping table...\n");
    if (ixEthDBPriorityMappingTableSet(firstPortId,
				       priorityTable)
	!= IX_ETH_DB_SUCCESS)
    {
	printf("SwBridgeQos: Failed to set the priority mapping Table for port %u\n",
	       firstPortId);
	return (IX_FAIL);	
    }
    
    /* Configure 10 mb/s on second port to create a 
     * traffic congestion on the bridge : the high 
     * priority traffic should pass, the low priority
     * traffic should starve.
     */
    if (ixEthAccCodeletLinkSlowSpeedSet(secondPortId)
	!= IX_SUCCESS)
    {
	printf("SwBridgeQos: Failed to set port %u to 10 Mbit\n", 
	       secondPortId);
	return (IX_FAIL);
    }

    /* Allow RX and TX traffic to run */
    if ( ixEthAccPortEnable(firstPortId) != IX_SUCCESS)
    {
	printf("SwBridgeQos: Failed to start the Bridge Operation for port %u\n",
	       firstPortId);
	return (IX_FAIL);
    }

    if ( ixEthAccPortEnable(secondPortId) != IX_SUCCESS)
    {
	printf("SwBridgeQos: Failed to start the Bridge Operation for port %u\n",
	       secondPortId);
	return (IX_FAIL);
    }

    /* display the default settings for both ports */
    printf("Port %u configuration:\n", 
	   (UINT32)firstPortId);
    printf("- Accept Ingress VLAN-tagged traffic, VLAN tag range is [%u-%u]\n",
	   (UINT32)IX_ETHACC_CODELET_VLANID_MIN,
	   (UINT32)IX_ETHACC_CODELET_VLANID_MAX);
    printf("- Strip tag from ingress traffic\n");
    printf("- Bridge Ingress to port %u without tag\n",
	   (UINT32)secondPortId);
    printf("- Frame priorities may change the frame order (QoS enabled)\n");
    printf("- Insert a default tag [%u] to egress traffic\n",
	   (UINT32)IX_ETHACC_CODELET_VLANID_DEFAULT);
 
    printf("Port %u configuration:\n", 
	   (UINT32)secondPortId);
    printf("- Set as default\n\n");

    return (IX_SUCCESS);
}