[minigraph] For egress ACL attaching to vlan, break them into vlan members (#6895)

#### Why I did it
Some platforms have difficult to attach egress ACL to vlan.

#### How I did it
For egress ACL attaching to vlan, break them into vlan members.

#### How to verify it
Unit test
Tested in DUT
This commit is contained in:
Qi Luo 2021-02-26 10:41:49 -08:00 committed by Guohan Lu
parent 57085e4a6a
commit 1650777723
4 changed files with 35 additions and 12 deletions

View File

@ -522,7 +522,6 @@ def parse_dpg(dpg, hname):
dpg_ecmp_content['ipv4'] = ipv4_content dpg_ecmp_content['ipv4'] = ipv4_content
dpg_ecmp_content['ipv6'] = ipv6_content dpg_ecmp_content['ipv6'] = ipv6_content
vlanintfs = child.find(str(QName(ns, "VlanInterfaces"))) vlanintfs = child.find(str(QName(ns, "VlanInterfaces")))
vlan_intfs = []
vlans = {} vlans = {}
vlan_members = {} vlan_members = {}
vlantype_name = "" vlantype_name = ""
@ -551,7 +550,7 @@ def parse_dpg(dpg, hname):
else: else:
vlan_members[(sonic_vlan_member_name, vmbr_list[i])] = {'tagging_mode': 'untagged'} vlan_members[(sonic_vlan_member_name, vmbr_list[i])] = {'tagging_mode': 'untagged'}
vlan_attributes = {'vlanid': vlanid} vlan_attributes = {'vlanid': vlanid, 'members': vmbr_list }
# If this VLAN requires a DHCP relay agent, it will contain a <DhcpRelays> element # If this VLAN requires a DHCP relay agent, it will contain a <DhcpRelays> element
# containing a list of DHCP server IPs # containing a list of DHCP server IPs
@ -579,7 +578,7 @@ def parse_dpg(dpg, hname):
aclname = aclintf.find(str(QName(ns, "OutAcl"))).text.upper().replace(" ", "_").replace("-", "_") aclname = aclintf.find(str(QName(ns, "OutAcl"))).text.upper().replace(" ", "_").replace("-", "_")
stage = "egress" stage = "egress"
else: else:
system.exit("Error: 'AclInterface' must contain either an 'InAcl' or 'OutAcl' subelement.") sys.exit("Error: 'AclInterface' must contain either an 'InAcl' or 'OutAcl' subelement.")
aclattach = aclintf.find(str(QName(ns, "AttachTo"))).text.split(';') aclattach = aclintf.find(str(QName(ns, "AttachTo"))).text.split(';')
acl_intfs = [] acl_intfs = []
is_mirror = False is_mirror = False
@ -596,7 +595,11 @@ def parse_dpg(dpg, hname):
# to LAG will be applied to all the LAG members internally by SAI/SDK # to LAG will be applied to all the LAG members internally by SAI/SDK
acl_intfs.append(member) acl_intfs.append(member)
elif member in vlans: elif member in vlans:
acl_intfs.append(member) # For egress ACL attaching to vlan, we break them into vlan members
if stage == "egress":
acl_intfs.extend(vlans[member]['members'])
else:
acl_intfs.append(member)
elif member in port_alias_map: elif member in port_alias_map:
acl_intfs.append(port_alias_map[member]) acl_intfs.append(port_alias_map[member])
# Give a warning if trying to attach ACL to a LAG member interface, correct way is to attach ACL to the LAG interface # Give a warning if trying to attach ACL to a LAG member interface, correct way is to attach ACL to the LAG interface
@ -620,9 +623,15 @@ def parse_dpg(dpg, hname):
acl_intfs.append(panel_port) acl_intfs.append(panel_port)
break break
if acl_intfs: if acl_intfs:
# Remove duplications
dedup_intfs = []
for intf in acl_intfs:
if intf not in dedup_intfs:
dedup_intfs.append(intf)
acls[aclname] = {'policy_desc': aclname, acls[aclname] = {'policy_desc': aclname,
'stage': stage, 'stage': stage,
'ports': acl_intfs} 'ports': dedup_intfs}
if is_mirror: if is_mirror:
acls[aclname]['type'] = 'MIRROR' acls[aclname]['type'] = 'MIRROR'
elif is_mirror_v6: elif is_mirror_v6:

View File

@ -260,6 +260,20 @@
<MacAddress i:nil="true"/> <MacAddress i:nil="true"/>
<SecondarySubnets/> <SecondarySubnets/>
</VlanInterface> </VlanInterface>
<VlanInterface>
<Name>Vlan98</Name>
<AttachTo>fortyGigE0/100;PortChannel01;PortChannel03</AttachTo>
<NoDhcpRelay>False</NoDhcpRelay>
<StaticDHCPRelay>0.0.0.0/0</StaticDHCPRelay>
<FhrpProtoType i:nil="true"/>
<Type>UserDefinedL2Vlan</Type>
<DhcpRelays>192.0.0.1;192.0.0.2</DhcpRelays>
<VlanID>98</VlanID>
<Tag>98</Tag>
<Subnets/>
<MacAddress i:nil="true"/>
<SecondarySubnets/>
</VlanInterface>
</VlanInterfaces> </VlanInterfaces>
<IPInterfaces> <IPInterfaces>
<IPInterface> <IPInterface>
@ -331,7 +345,7 @@
<Type>DataPlane</Type> <Type>DataPlane</Type>
</AclInterface> </AclInterface>
<AclInterface> <AclInterface>
<AttachTo>PortChannel01;PortChannel02</AttachTo> <AttachTo>PortChannel01;PortChannel02;Vlan98</AttachTo>
<OutAcl>DataAclEgress</OutAcl> <OutAcl>DataAclEgress</OutAcl>
<Type>DataPlane</Type> <Type>DataPlane</Type>
</AclInterface> </AclInterface>

View File

@ -177,7 +177,7 @@ class TestCfgGen(TestCase):
"'DATAACLINGRESS': {'stage': 'ingress', 'type': 'L3', 'ports': ['PortChannel01', 'PortChannel02', 'PortChannel03', 'PortChannel04'], 'policy_desc': 'DATAACLINGRESS'}, " "'DATAACLINGRESS': {'stage': 'ingress', 'type': 'L3', 'ports': ['PortChannel01', 'PortChannel02', 'PortChannel03', 'PortChannel04'], 'policy_desc': 'DATAACLINGRESS'}, "
"'SNMP_ACL': {'services': ['SNMP'], 'type': 'CTRLPLANE', 'policy_desc': 'SNMP_ACL', 'stage': 'ingress'}, " "'SNMP_ACL': {'services': ['SNMP'], 'type': 'CTRLPLANE', 'policy_desc': 'SNMP_ACL', 'stage': 'ingress'}, "
"'SSH_ACL': {'services': ['SSH'], 'type': 'CTRLPLANE', 'policy_desc': 'SSH_ACL', 'stage': 'ingress'}, " "'SSH_ACL': {'services': ['SSH'], 'type': 'CTRLPLANE', 'policy_desc': 'SSH_ACL', 'stage': 'ingress'}, "
"'DATAACLEGRESS': {'stage': 'egress', 'type': 'L3', 'ports': ['PortChannel01', 'PortChannel02'], 'policy_desc': 'DATAACLEGRESS'}, " "'DATAACLEGRESS': {'stage': 'egress', 'type': 'L3', 'ports': ['PortChannel01', 'PortChannel02', 'Ethernet100', 'PortChannel03'], 'policy_desc': 'DATAACLEGRESS'}, "
"'EVERFLOWV6': {'stage': 'ingress', 'type': 'MIRRORV6', 'ports': ['PortChannel01', 'PortChannel02', 'PortChannel03', 'PortChannel04', 'Ethernet4', 'Ethernet100'], 'policy_desc': 'EVERFLOWV6'}}" "'EVERFLOWV6': {'stage': 'ingress', 'type': 'MIRRORV6', 'ports': ['PortChannel01', 'PortChannel02', 'PortChannel03', 'PortChannel04', 'Ethernet4', 'Ethernet100'], 'policy_desc': 'EVERFLOWV6'}}"
) )
) )
@ -207,10 +207,10 @@ class TestCfgGen(TestCase):
self.assertEqual( self.assertEqual(
utils.to_dict(output.strip()), utils.to_dict(output.strip()),
utils.to_dict( utils.to_dict(
"{'Vlan1000': {'alias': 'ab1', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '1000'}, " "{'Vlan1000': {'alias': 'ab1', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '1000', 'members': ['Ethernet8']}, "
"'Vlan2001': {'alias': 'ab3', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '2001'}," "'Vlan2001': {'alias': 'ab3', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '2001', 'members': ['Ethernet12']},"
"'Vlan2000': {'alias': 'ab2', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '2000'}," "'Vlan2000': {'alias': 'ab2', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '2000', 'members': ['Ethernet12']},"
"'Vlan2020': {'alias': 'kk1', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '2020'}}" "'Vlan2020': {'alias': 'kk1', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '2020', 'members': ['Ethernet12']}}"
) )
) )

View File

@ -94,7 +94,7 @@ class TestCfgGenCaseInsensitive(TestCase):
output = self.run_script(argument) output = self.run_script(argument)
self.assertEqual( self.assertEqual(
utils.to_dict(output.strip()), utils.to_dict(output.strip()),
utils.to_dict("{'Vlan1000': {'alias': 'ab1', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '1000', 'mac': '00:aa:bb:cc:dd:ee' }}") utils.to_dict("{'Vlan1000': {'alias': 'ab1', 'dhcp_servers': ['192.0.0.1', '192.0.0.2'], 'vlanid': '1000', 'mac': '00:aa:bb:cc:dd:ee', 'members': ['Ethernet8'] }}")
) )
def test_minigraph_vlan_members(self): def test_minigraph_vlan_members(self):