/**
 * @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;
}
Example #2
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;
}
Example #3
0
/**
 * @brief Restore the states of EthDB Features
 *
 * @param portID ID of the port
 *
 * See IxEthDB.h for more details.
 */
IX_ETH_DB_PUBLIC 
IxEthDBStatus ixEthDBFeatureStatesRestore(IxEthDBPortId portID)
{
    PortInfo *portInfo = &ixEthDBPortInfo[portID];

    /* Check whether port if enabled */
    IX_ETH_DB_CHECK_PORT_INITIALIZED(portID);
    IX_ETH_DB_CHECK_PORT(portID);

   /* ========================  Basic ==========================
    *  Set up Port MAC Address
    */
    if (ixEthDBPortAddressSet(portID, &(portInfo->macAddr)) != IX_SUCCESS)
    {
        return IX_ETH_DB_FAIL;
    }
   
    /*
     * Set up Port Max Rx/Tx frame lengths
     */ 
    if(ixEthDBPortFrameLengthsUpdate(portID) != IX_SUCCESS)
    {
        return IX_ETH_DB_FAIL;
    }

    /* ========================  VLAN/QoS ==========================         
     * Only performs VLAN feature update if it is enabled before
     */ 
    if ((portInfo->featureStatus & IX_ETH_DB_VLAN_QOS) != 0)
    {
      /* Set VLAN Rx tag mode */
      if (ixEthDBIngressVlanModeUpdate(portID) != IX_SUCCESS)
      {
         return IX_ETH_DB_FAIL;
      }

      /* Set Default Rx VID */
      if (ixEthDBPortVlanTagSet(portID, portInfo->vlanTag) != IX_SUCCESS)
      {
         return IX_ETH_DB_FAIL;
      }
 
      /* Set PortID extraction mode */
      if (ixEthDBVlanPortExtractionEnable(portID, portInfo->portIdExtractionEnable) != IX_SUCCESS)
      {
         return IX_ETH_DB_FAIL;   
      }

      /* Set VLAN Table */
      if (ixEthDBVlanTableRangeUpdate(portID) != IX_SUCCESS)
      {
         return IX_ETH_DB_FAIL; 
      }
    } /* VLAN/QoS */

   /* ========================  Firewall ==========================         
    * Only performs Firewall feature update if it is enabled before
    */    
    if ((portInfo->featureStatus & IX_ETH_DB_FIREWALL) != 0)
    {
      if(ixEthDBFirewallTableDownload(portID) != IX_SUCCESS)
      {
	return IX_ETH_DB_FAIL;
      }  
    } /* Firewall */
  
   /* ===================== Header Conversion ==========================         
    * Only performs Header Conversion feature update if it is enabled before
    */   
    if ((portInfo->featureStatus & IX_ETH_DB_WIFI_HEADER_CONVERSION) != 0)
    {
      /* Update WiFi FC & DID */
      if (ixEthDBWiFiFrameControlDurationIDUpdate(portID) != IX_SUCCESS)
      {      
	return IX_ETH_DB_FAIL; 
      }

      /* Update BSSID */
      if (ixEthDBWiFiBSSIDSet(portID, (IxEthDBMacAddr *) portInfo->bssid) != IX_SUCCESS)
      {
	return IX_ETH_DB_FAIL;
      }

      /* Update Header Conversion Table & AP MAC Table */
      if (ixEthDBWiFiConversionTableDownload(portID) != IX_ETH_DB_SUCCESS)
      {
	return IX_ETH_DB_FAIL;
      }
    } /* Header Conversion */
  
   /* ====================== Learning & Filtering ==========================         
    * Learning & Filtering feature update is not neccessary as we can rely 
    * on EthNPE to learn the src address again. As for the entry added by client
    * earlier, it will be lost. This is the constraint as the mechanism to retrieve
    * the entry that has been added by client from NPE is not trivial.
    */

   /* ============================== STP ===================================         
    * Only performs STP feature update if it is enabled before
    */
    if ((portInfo->featureStatus & IX_ETH_DB_SPANNING_TREE_PROTOCOL) != 0)
    {    
      if (ixEthDBSpanningTreeBlockingStateSet(portID, portInfo->stpBlocked) != IX_SUCCESS)
      {
	return IX_ETH_DB_FAIL;
      }
    }

    return IX_ETH_DB_SUCCESS;
}