diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py index fb462dada594..1f99bb16c8cd 100644 --- a/src/sonic-config-engine/minigraph.py +++ b/src/sonic-config-engine/minigraph.py @@ -35,7 +35,11 @@ VLAN_SUB_INTERFACE_SEPARATOR = '.' VLAN_SUB_INTERFACE_VLAN_ID = '10' -# Default Virtual Network Index (VNI) +FRONTEND_ASIC_SUB_ROLE = 'FrontEnd' +BACKEND_ASIC_SUB_ROLE = 'BackEnd' +BACKEND_ASIC_INTERFACE_NAME_PREFIX = 'Ethernet-BP' + +# Default Virtual Network Index (VNI) vni_default = 8000 ############################################################################### @@ -401,7 +405,9 @@ def parse_dpg(dpg, hname): # later after the rest of the minigraph has been parsed. acl_intfs = pc_intfs[:] for panel_port in port_alias_map.values(): - if panel_port not in intfs_inpc: + # because of port_alias_asic_map we can have duplicate in port_alias_map + # so check if already present do not add + if panel_port not in intfs_inpc and panel_port not in acl_intfs: acl_intfs.append(panel_port) break if acl_intfs: @@ -687,27 +693,61 @@ def parse_spine_chassis_fe(results, vni, lo_intfs, phyport_intfs, pc_intfs, pc_m # ############################################################################### -def filter_acl_mirror_table_bindings(acls, neighbors, port_channels): - """ - Filters out inactive front-panel ports from the binding list for mirror - ACL tables. We define an "active" port as one that is a member of a - port channel or one that is connected to a neighboring device. - """ +def filter_acl_table_bindings(acls, neighbors, port_channels, sub_role): + filter_acls = {} + + # If the asic role is BackEnd no ACL Table (Ctrl/Data/Everflow) is binded. + # This will be applicable in Multi-NPU Platforms. + + if sub_role == BACKEND_ASIC_SUB_ROLE: + return filter_acls + + front_port_channel_intf = [] + + # Get the front panel port channel. It will use port_alias_asic_map + # which will get populated from port_config.ini for Multi-NPU + # architecture + for port_channel_intf in port_channels: + backend_port_channel = any(lag_member in port_alias_asic_map \ + and lag_member.startswith(BACKEND_ASIC_INTERFACE_NAME_PREFIX) \ + for lag_member in port_channels[port_channel_intf]['members']) + if not backend_port_channel: + front_port_channel_intf.append(port_channel_intf) for acl_table, group_params in acls.iteritems(): group_type = group_params.get('type', None) + filter_acls[acl_table] = acls[acl_table] + # For Control Plane and Data ACL no filtering is needed + # Control Plane ACL has no Interface associated and + # Data Plane ACL Interface are attached via minigraph + # AclInterface. if group_type != 'MIRROR' and group_type != 'MIRRORV6': continue - active_ports = [ port for port in group_params.get('ports', []) if port in neighbors.keys() or port in port_channels ] - + # Filters out back-panel ports from the binding list for Everflow (Mirror) + # ACL tables. We define an "back-panel" port as one that is a member of a + # port channel connected to back asic or directly connected to back asic. + # This will be applicable in Multi-NPU Platforms. + front_panel_ports = [] + for port in group_params.get('ports', []): + if port in port_alias_asic_map and port.startswith(BACKEND_ASIC_INTERFACE_NAME_PREFIX): + continue + if port in port_channels and port not in front_port_channel_intf: + continue + front_panel_ports.append(port) + + # Filters out inactive front-panel ports from the binding list for mirror + # ACL tables. We define an "active" port as one that is a member of a + # front pannel port channel or one that is connected to a neighboring device via front panel port. + active_ports = [port for port in front_panel_ports if port in neighbors.keys() or port in front_port_channel_intf] + if not active_ports: print >> sys.stderr, 'Warning: mirror table {} in ACL_TABLE does not have any ports bound to it'.format(acl_table) - acls[acl_table]['ports'] = active_ports + filter_acls[acl_table]['ports'] = active_ports - return acls + return filter_acls ############################################################################### # @@ -1020,7 +1060,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None): results['DHCP_SERVER'] = dict((item, {}) for item in dhcp_servers) results['NTP_SERVER'] = dict((item, {}) for item in ntp_servers) results['TACPLUS_SERVER'] = dict((item, {'priority': '1', 'tcp_port': '49'}) for item in tacacs_servers) - results['ACL_TABLE'] = filter_acl_mirror_table_bindings(acls, neighbors, pcs) + results['ACL_TABLE'] = filter_acl_table_bindings(acls, neighbors, pcs, sub_role) results['FEATURE'] = { 'telemetry': { 'status': 'enabled' diff --git a/src/sonic-config-engine/tests/multi_npu_data/sample-minigraph.xml b/src/sonic-config-engine/tests/multi_npu_data/sample-minigraph.xml index 118202d9b52e..8ca17925c6ec 100644 --- a/src/sonic-config-engine/tests/multi_npu_data/sample-minigraph.xml +++ b/src/sonic-config-engine/tests/multi_npu_data/sample-minigraph.xml @@ -650,14 +650,14 @@ 05T2 Ethernet1 multi_npu_platform_01 - Ethernet1/8 + Ethernet1/5 DeviceInterfaceLink 05T2 Ethernet2 multi_npu_platform_01 - Ethernet1/9 + Ethernet1/6 DeviceInterfaceLink diff --git a/src/sonic-config-engine/tests/test_multinpu_cfggen.py b/src/sonic-config-engine/tests/test_multinpu_cfggen.py index 4aefbb78fc61..0ef29eb6d9b4 100644 --- a/src/sonic-config-engine/tests/test_multinpu_cfggen.py +++ b/src/sonic-config-engine/tests/test_multinpu_cfggen.py @@ -220,3 +220,28 @@ def test_device_asic_metadata(self): self.assertEqual(output['localhost']['sub_role'], 'FrontEnd') else: self.assertEqual(output['localhost']['sub_role'], 'BackEnd') + + def test_global_asic_acl(self): + argument = "-m {} --var-json \"ACL_TABLE\"".format(self.sample_graph) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, {\ + 'DATAACL': {'policy_desc': 'DATAACL', 'ports': ['PortChannel0002','PortChannel0008'], 'stage': 'ingress', 'type': 'L3'}, + 'EVERFLOW': {'policy_desc': 'EVERFLOW', 'ports': ['PortChannel0002','PortChannel0008'], 'stage': 'ingress', 'type': 'MIRROR'}, + 'EVERFLOWV6':{'policy_desc': 'EVERFLOWV6', 'ports': ['PortChannel0002','PortChannel0008'], 'stage': 'ingress', 'type': 'MIRRORV6'}, + 'SNMP_ACL': {'policy_desc': 'SNMP_ACL', 'services': ['SNMP'], 'stage': 'ingress', 'type': 'CTRLPLANE'}, + 'SSH_ONLY': {'policy_desc': 'SSH_ONLY', 'services': ['SSH'], 'stage': 'ingress', 'type': 'CTRLPLANE'}}) + + def test_front_end_asic_acl(self): + argument = "-m {} -p {} -n asic0 --var-json \"ACL_TABLE\"".format(self.sample_graph, self.port_config[0]) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, {\ + 'DATAACL': {'policy_desc': 'DATAACL', 'ports': ['PortChannel0002'], 'stage': 'ingress', 'type': 'L3'}, + 'EVERFLOW': {'policy_desc': 'EVERFLOW', 'ports': ['PortChannel0002'], 'stage': 'ingress', 'type': 'MIRROR'}, + 'EVERFLOWV6':{'policy_desc': 'EVERFLOWV6', 'ports': ['PortChannel0002'], 'stage': 'ingress', 'type': 'MIRRORV6'}, + 'SNMP_ACL': {'policy_desc': 'SNMP_ACL', 'services': ['SNMP'], 'stage': 'ingress', 'type': 'CTRLPLANE'}, + 'SSH_ONLY': {'policy_desc': 'SSH_ONLY', 'services': ['SSH'], 'stage': 'ingress', 'type': 'CTRLPLANE'}}) + + def test_back_end_asic_acl(self): + argument = "-m {} -p {} -n asic3 --var-json \"ACL_TABLE\"".format(self.sample_graph, self.port_config[3]) + output = json.loads(self.run_script(argument)) + self.assertDictEqual(output, {})