From 3a098cfdea7d73d91ebb401b97f93d7aca1e47c5 Mon Sep 17 00:00:00 2001
From: abdosi <58047199+abdosi@users.noreply.github.com>
Date: Fri, 2 Jun 2023 16:04:14 -0700
Subject: [PATCH] Update AclInterface and Management Interfaces parsing for
multi-asic case (#14952)
* AclInterface and Management Interfaces are parsed on finding first valid node for it.
Above logic works for multi-asic scenarios where ACL Interface and Management Interfaces are present in DPG order {Host, Asicx, Asicy} but not when DPG is in {Asicx, Asicy, Host} order.
---
src/sonic-config-engine/minigraph.py | 16 +--
.../tests/sample-chassis-packet-lc-graph.xml | 134 ++++++++++--------
src/sonic-config-engine/tests/test_cfggen.py | 15 ++
3 files changed, 101 insertions(+), 64 deletions(-)
diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py
index 846b0a6b6d..8dc82b40d7 100644
--- a/src/sonic-config-engine/minigraph.py
+++ b/src/sonic-config-engine/minigraph.py
@@ -453,8 +453,8 @@ def parse_loopback_intf(child):
def parse_dpg(dpg, hname):
- aclintfs = None
- mgmtintfs = None
+ aclintfs = {}
+ mgmtintfs = {}
subintfs = None
intfs= {}
lo_intfs= {}
@@ -480,15 +480,15 @@ def parse_dpg(dpg, hname):
There is just one aclintf node in the minigraph
Get the aclintfs node first.
"""
- if aclintfs is None and child.find(str(QName(ns, "AclInterfaces"))) is not None:
- aclintfs = child.find(str(QName(ns, "AclInterfaces")))
+ if not aclintfs and child.find(str(QName(ns, "AclInterfaces"))) is not None and child.find(str(QName(ns, "AclInterfaces"))).findall(str(QName(ns, "AclInterface"))):
+ aclintfs = child.find(str(QName(ns, "AclInterfaces"))).findall(str(QName(ns, "AclInterface")))
"""
In Multi-NPU platforms the mgmt intfs are defined only for the host not for individual asic
There is just one mgmtintf node in the minigraph
Get the mgmtintfs node first. We need mgmt intf to get mgmt ip in per asic dockers.
"""
- if mgmtintfs is None and child.find(str(QName(ns, "ManagementIPInterfaces"))) is not None:
- mgmtintfs = child.find(str(QName(ns, "ManagementIPInterfaces")))
+ if not mgmtintfs and child.find(str(QName(ns, "ManagementIPInterfaces"))) is not None and child.find(str(QName(ns, "ManagementIPInterfaces"))).findall(str(QName(ns1, "ManagementIPInterface"))):
+ mgmtintfs = child.find(str(QName(ns, "ManagementIPInterfaces"))).findall(str(QName(ns1, "ManagementIPInterface")))
hostname = child.find(str(QName(ns, "Hostname")))
if hostname.text.lower() != hname.lower():
continue
@@ -531,7 +531,7 @@ def parse_dpg(dpg, hname):
mvrf["vrf_global"] = {"mgmtVrfEnabled": mvrf_en_flag}
mgmt_intf = {}
- for mgmtintf in mgmtintfs.findall(str(QName(ns1, "ManagementIPInterface"))):
+ for mgmtintf in mgmtintfs:
intfname = mgmtintf.find(str(QName(ns, "AttachTo"))).text
ipprefix = mgmtintf.find(str(QName(ns1, "PrefixStr"))).text
mgmtipn = ipaddress.ip_network(UNICODE_TYPE(ipprefix), False)
@@ -685,7 +685,7 @@ def parse_dpg(dpg, hname):
vlans[sonic_vlan_name] = vlan_attributes
vlan_member_list[sonic_vlan_name] = vmbr_list
- for aclintf in aclintfs.findall(str(QName(ns, "AclInterface"))):
+ for aclintf in aclintfs:
if aclintf.find(str(QName(ns, "InAcl"))) is not None:
aclname = aclintf.find(str(QName(ns, "InAcl"))).text.upper().replace(" ", "_").replace("-", "_")
stage = "ingress"
diff --git a/src/sonic-config-engine/tests/sample-chassis-packet-lc-graph.xml b/src/sonic-config-engine/tests/sample-chassis-packet-lc-graph.xml
index debefcc15d..c0a69c29e0 100644
--- a/src/sonic-config-engine/tests/sample-chassis-packet-lc-graph.xml
+++ b/src/sonic-config-engine/tests/sample-chassis-packet-lc-graph.xml
@@ -79,60 +79,7 @@
-
-
-
-
- HostIP
- Loopback0
-
- 10.0.1.6/32
-
- 10.0.1.6/32
-
-
-
-
- HostIP
- eth0
-
- 10.3.147.97/23
-
- 10.3.147.97/23
-
-
-
-
-
-
- str2-8808-lc2-1
-
-
-
-
-
- Eth1/1/47
- 27.1.1.1/24
-
-
-
-
-
-
- IPNextHop
-
- 8.0.0.1
- PortChannel40,192.168.1.2;PortChannel50,192.168.2.2
- StaticRoute
-
-
-
-
-
-
-
-
-
+
@@ -211,11 +158,86 @@
IPNextHop
- 8.0.0.1
+ 8.0.0.1
PortChannel40,192.168.1.2;PortChannel50,192.168.2.2
- StaticRoute
+ StaticRoute
+
+
+ SNMP_ACL
+ SNMP
+ SNMP
+
+
+ VTY_LINE
+ ssh-only
+ SSH
+
+
+
+
+
+
+
+ HostIP
+ Loopback0
+
+ 10.0.1.6/32
+
+ 10.0.1.6/32
+
+
+
+
+ HostIP
+ eth0
+
+ 10.3.147.97/23
+
+ 10.3.147.97/23
+
+
+
+
+
+
+ str2-8808-lc2-1
+
+
+
+
+
+ Eth1/1/47
+ 27.1.1.1/24
+
+
+
+
+
+
+ IPNextHop
+
+ 8.0.0.1
+ PortChannel40,192.168.1.2;PortChannel50,192.168.2.2
+ StaticRoute
+
+
+
+
+
+ SNMP_ACL
+ SNMP
+ SNMP
+
+
+ VTY_LINE
+ ssh-only
+ SSH
+
+
+
+
diff --git a/src/sonic-config-engine/tests/test_cfggen.py b/src/sonic-config-engine/tests/test_cfggen.py
index 29d21f6b55..d159508e84 100644
--- a/src/sonic-config-engine/tests/test_cfggen.py
+++ b/src/sonic-config-engine/tests/test_cfggen.py
@@ -982,6 +982,21 @@ class TestCfgGen(TestCase):
"'Vlan2000': {'dhcpv6_servers': ['fc02:2000::3', 'fc02:2000::4']}}"
)
)
+
+ def test_minigraph_packet_chassis_acl(self):
+ argument = ['-m', self.packet_chassis_graph, '-p', self.packet_chassis_port_ini, '-v', "ACL_TABLE"]
+ output = self.run_script(argument)
+ self.assertEqual(
+ utils.to_dict(output.strip()),
+ utils.to_dict("{'SNMP_ACL': {'policy_desc': 'SNMP_ACL', 'type': 'CTRLPLANE', 'stage': 'ingress', 'services': ['SNMP']}, 'SSH_ONLY': {'policy_desc': 'SSH_ONLY', 'type': 'CTRLPLANE', 'stage': 'ingress', 'services': ['SSH']}}")
+ )
+
+ argument = ['-m', self.packet_chassis_graph, '-p', self.packet_chassis_port_ini, '-n', "asic1", '-v', "ACL_TABLE"]
+ output = self.run_script(argument)
+ self.assertEqual(
+ utils.to_dict(output.strip()),
+ utils.to_dict("{'SNMP_ACL': {'policy_desc': 'SNMP_ACL', 'type': 'CTRLPLANE', 'stage': 'ingress', 'services': ['SNMP']}, 'SSH_ONLY': {'policy_desc': 'SSH_ONLY', 'type': 'CTRLPLANE', 'stage': 'ingress', 'services': ['SSH']}}")
+ )
def test_minigraph_bgp_packet_chassis_peer(self):
argument = ['-m', self.packet_chassis_graph, '-p', self.packet_chassis_port_ini, '-n', "asic1", '-v', "BGP_INTERNAL_NEIGHBOR[\'8.0.0.1\']"]