/** * @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) { IxNpeDlImageId imageId, npeAImageId; IxEthDBPortId portIndex; PortInfo *portInfo; IxEthDBPriorityTable defaultPriorityTable; IX_STATUS result; UINT32 queueIndex; UINT32 queueStructureIndex; UINT32 trafficClassDefinitionIndex; /* read version of NPE A - required to set the AQM queues for B and C */ npeAImageId.functionalityId = 0; ixNpeDlLoadedImageGet(IX_NPEDL_NPEID_NPEA, &npeAImageId); for (portIndex = 0 ; portIndex < IX_ETH_DB_NUMBER_OF_PORTS ; portIndex++) { IxNpeMhMessage msg; portInfo = &ixEthDBPortInfo[portIndex]; /* check and bypass if NPE 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 (ixNpeDlLoadedImageGet(IX_ETH_DB_PORT_ID_TO_NPE(portIndex), &imageId) != IX_SUCCESS) { 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_ETH_DB_PORT_ID_TO_NPE(portIndex), msg, result); if (result != IX_SUCCESS) { WARNING_LOG("DB: (FeatureScan) warning, could not send message to the NPE\n"); continue; } if (imageId.functionalityId == 0x00 || imageId.functionalityId == 0x03 || imageId.functionalityId == 0x04 || imageId.functionalityId == 0x80) { portInfo->featureCapability |= IX_ETH_DB_FILTERING; portInfo->featureCapability |= IX_ETH_DB_FIREWALL; portInfo->featureCapability |= IX_ETH_DB_SPANNING_TREE_PROTOCOL; } else if (imageId.functionalityId == 0x01 || imageId.functionalityId == 0x81) { 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 (imageId.functionalityId == 0x02 || imageId.functionalityId == 0x82) { 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; } /* reset AQM queues */ memset(portInfo->ixEthDBTrafficClassAQMAssignments, 0, sizeof (portInfo->ixEthDBTrafficClassAQMAssignments)); /* ensure there's at least one traffic class record in the definition table, otherwise we have no default case, hence no queues */ IX_ENSURE(sizeof (ixEthDBTrafficClassDefinitions) != 0, "DB: no traffic class definitions found, check IxEthDBQoS.h"); /* find the traffic class definition index compatible with the current NPE A functionality ID */ for (trafficClassDefinitionIndex = 0 ; trafficClassDefinitionIndex < sizeof (ixEthDBTrafficClassDefinitions) / sizeof (ixEthDBTrafficClassDefinitions[0]); trafficClassDefinitionIndex++) { if (ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_NPE_A_FUNCTIONALITY_ID_INDEX] == npeAImageId.functionalityId) { /* found it */ break; } } /* select the default case if we went over the array boundary */ if (trafficClassDefinitionIndex == sizeof (ixEthDBTrafficClassDefinitions) / sizeof (ixEthDBTrafficClassDefinitions[0])) { trafficClassDefinitionIndex = 0; /* the first record is the default case */ } /* select queue assignment structure based on the traffic class configuration index */ queueStructureIndex = ixEthDBTrafficClassDefinitions[trafficClassDefinitionIndex][IX_ETH_DB_QUEUE_ASSIGNMENT_INDEX]; /* 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; #define CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */ #ifdef CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */ /* 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 */ #endif /* test-only */ { /* 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]; } } #ifdef CONFIG_WITH_VLAN /* test-only: VLAN support not included to save space!!! */ /* download priority mapping table and Rx queue configuration */ memset (defaultPriorityTable, 0, sizeof (defaultPriorityTable)); ixEthDBPriorityMappingTableSet(portIndex, defaultPriorityTable); #endif /* by default we turn off invalid source MAC address filtering */ ixEthDBFirewallInvalidAddressFilterEnable(portIndex, FALSE); /* 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 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; } } } } }