From 14b625ca50c4e1de11f5dc5fcb136da0385793df Mon Sep 17 00:00:00 2001
From: kellyyeh <42761586+kellyyeh@users.noreply.github.com>
Date: Thu, 12 Aug 2021 14:32:23 -0700
Subject: [PATCH 1/2] Cherry-pick Parse DHCP Table
---
src/sonic-config-engine/minigraph.py | 34 ++++++++++++++++---
.../tests/simple-sample-graph-case.xml | 12 +++++++
src/sonic-config-engine/tests/test_cfggen.py | 11 ++++++
.../tests/test_minigraph_case.py | 26 ++++++++++++++
4 files changed, 78 insertions(+), 5 deletions(-)
diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py
index c5057ebaee4..8ec270bedff 100644
--- a/src/sonic-config-engine/minigraph.py
+++ b/src/sonic-config-engine/minigraph.py
@@ -567,6 +567,29 @@ def parse_dpg(dpg, hname):
vlan_attributes['alias'] = vintfname
vlans[sonic_vlan_name] = vlan_attributes
+ dhcp = child.find(str(QName(ns, "Dhcp")))
+ dhcp_table = {}
+
+ if dhcp is not None:
+ for vintf in dhcp.findall(str(QName(ns, "VlanInterface"))):
+ vintfname = vintf.find(str(QName(ns, "Name"))).text
+
+ dhcp_attributes = {}
+
+ dhcp_node = vintf.find(str(QName(ns, "Dhcpv6Relays")))
+ if dhcp_node is not None and dhcp_node.text is not None:
+ dhcpservers = dhcp_node.text
+ vdhcpserver_list = dhcpservers.split(';')
+ dhcp_attributes['dhcpv6_servers'] = vdhcpserver_list
+
+ option_linklayer_addr = vintf.find(str(QName(ns, "Dhcpv6OptionRfc6939")))
+ if option_linklayer_addr is not None and option_linklayer_addr.text == "true":
+ dhcp_attributes['dhcpv6_option|rfc6939_support'] = "true"
+ elif option_linklayer_addr is not None and option_linklayer_addr.text == "false":
+ dhcp_attributes['dhcpv6_option|rfc6939_support'] = "false"
+
+ dhcp_table[vintfname] = dhcp_attributes
+
acls = {}
for aclintf in aclintfs.findall(str(QName(ns, "AclInterface"))):
if aclintf.find(str(QName(ns, "InAcl"))) is not None:
@@ -681,8 +704,8 @@ def parse_dpg(dpg, hname):
if mg_key in mg_tunnel.attrib:
tunnelintfs[tunnel_type][tunnel_name][table_key] = mg_tunnel.attrib[mg_key]
- return intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni, tunnelintfs, dpg_ecmp_content
- return None, None, None, None, None, None, None, None, None, None
+ return intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, dhcp_table, pcs, pc_members, acls, vni, tunnelintfs, dpg_ecmp_content
+ return None, None, None, None, None, None, None, None, None, None, None, None, None
def parse_host_loopback(dpg, hname):
for child in dpg:
@@ -1108,6 +1131,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
tunnel_intfs = None
vlans = None
vlan_members = None
+ dhcp_table = None
pcs = None
mgmt_intf = None
lo_intfs = None
@@ -1167,7 +1191,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
for child in root:
if asic_name is None:
if child.tag == str(QName(ns, "DpgDec")):
- (intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni, tunnel_intfs, dpg_ecmp_content) = parse_dpg(child, hostname)
+ (intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, dhcp_table, pcs, pc_members, acls, vni, tunnel_intfs, dpg_ecmp_content) = parse_dpg(child, hostname)
elif child.tag == str(QName(ns, "CpgDec")):
(bgp_sessions, bgp_internal_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, hostname)
elif child.tag == str(QName(ns, "PngDec")):
@@ -1182,7 +1206,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
(port_speeds_default, port_descriptions) = parse_deviceinfo(child, hwsku)
else:
if child.tag == str(QName(ns, "DpgDec")):
- (intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni, tunnel_intfs, dpg_ecmp_content) = parse_dpg(child, asic_name)
+ (intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, dhcp_table, pcs, pc_members, acls, vni, tunnel_intfs, dpg_ecmp_content) = parse_dpg(child, asic_name)
host_lo_intfs = parse_host_loopback(child, hostname)
elif child.tag == str(QName(ns, "CpgDec")):
(bgp_sessions, bgp_internal_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, asic_name, local_devices)
@@ -1499,7 +1523,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
results['DEVICE_NEIGHBOR_METADATA'] = { key:devices[key] for key in devices if key in {device['name'] for device in neighbors.values()} }
results['SYSLOG_SERVER'] = dict((item, {}) for item in syslog_servers)
results['DHCP_SERVER'] = dict((item, {}) for item in dhcp_servers)
- results['DHCPv6_SERVER'] = dict((item, {}) for item in dhcpv6_servers)
+ results['DHCP'] = dhcp_table
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_table_bindings(acls, neighbors, pcs, sub_role)
diff --git a/src/sonic-config-engine/tests/simple-sample-graph-case.xml b/src/sonic-config-engine/tests/simple-sample-graph-case.xml
index c1015b6b536..95398e6913c 100644
--- a/src/sonic-config-engine/tests/simple-sample-graph-case.xml
+++ b/src/sonic-config-engine/tests/simple-sample-graph-case.xml
@@ -148,6 +148,18 @@
+
+
+ Vlan1000
+ fc02:2000::1;fc02:2000::2
+ true
+
+
+ Vlan2000
+ fc02:2000::3;fc02:2000::4
+ false
+
+
diff --git a/src/sonic-config-engine/tests/test_cfggen.py b/src/sonic-config-engine/tests/test_cfggen.py
index e3f74fb9cf7..502c4b2e416 100644
--- a/src/sonic-config-engine/tests/test_cfggen.py
+++ b/src/sonic-config-engine/tests/test_cfggen.py
@@ -684,3 +684,14 @@ def test_show_run_interfaces(self):
argument = '-a \'{"key1":"value"}\' --var-json INTERFACE'
output = self.run_script(argument)
self.assertEqual(output, '')
+
+ def test_minigraph_dhcp(self):
+ argument = '-m "' + self.sample_graph_simple_case + '" -p "' + self.port_config + '" -v DHCP'
+ output = self.run_script(argument)
+ self.assertEqual(
+ utils.to_dict(output.strip()),
+ utils.to_dict(
+ "{'Vlan1000': {'dhcpv6_servers': ['fc02:2000::1', 'fc02:2000::2'], 'dhcpv6_option|rfc6939_support': 'true'}, "
+ "'Vlan2000': {'dhcpv6_servers': ['fc02:2000::3', 'fc02:2000::4'], 'dhcpv6_option|rfc6939_support': 'false'}}"
+ )
+ )
diff --git a/src/sonic-config-engine/tests/test_minigraph_case.py b/src/sonic-config-engine/tests/test_minigraph_case.py
index 3308c5641f4..998b66cfb9a 100644
--- a/src/sonic-config-engine/tests/test_minigraph_case.py
+++ b/src/sonic-config-engine/tests/test_minigraph_case.py
@@ -357,3 +357,29 @@ def test_minigraph_mux_cable_table(self):
utils.to_dict(output.strip()),
expected_table
)
+
+ def test_dhcp_table(self):
+ argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DHCP"'
+ expected = {
+ 'Vlan1000': {
+ 'dhcpv6_servers': [
+ "fc02:2000::1",
+ "fc02:2000::2"
+ ],
+ 'dhcpv6_option|rfc6939_support': 'true'
+ },
+ 'Vlan2000': {
+ 'dhcpv6_servers': [
+ "fc02:2000::3",
+ "fc02:2000::4"
+ ],
+ 'dhcpv6_option|rfc6939_support': 'false'
+ }
+ }
+ output = self.run_script(argument)
+ self.assertEqual(
+ utils.to_dict(output.strip()),
+ expected
+ )
+
+
From 04c78580947b34424d13ba5603fab80e0746bfd6 Mon Sep 17 00:00:00 2001
From: kellyyeh <42761586+kellyyeh@users.noreply.github.com>
Date: Fri, 20 Aug 2021 09:18:48 -0700
Subject: [PATCH 2/2] Cherry pick changing DHCP table to DHCP_RELAY
---
src/sonic-config-engine/minigraph.py | 38 +++++--------------
.../tests/simple-sample-graph-case.xml | 14 +------
src/sonic-config-engine/tests/test_cfggen.py | 6 +--
.../tests/test_minigraph_case.py | 12 +++---
4 files changed, 21 insertions(+), 49 deletions(-)
diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py
index 8ec270bedff..d4fffc21c43 100644
--- a/src/sonic-config-engine/minigraph.py
+++ b/src/sonic-config-engine/minigraph.py
@@ -516,6 +516,7 @@ def parse_dpg(dpg, hname):
vlanintfs = child.find(str(QName(ns, "VlanInterfaces")))
vlans = {}
vlan_members = {}
+ dhcp_relay_table = {}
vlantype_name = ""
intf_vlan_mbr = defaultdict(list)
for vintf in vlanintfs.findall(str(QName(ns, "VlanInterface"))):
@@ -543,6 +544,7 @@ def parse_dpg(dpg, hname):
vlan_members[(sonic_vlan_member_name, vmbr_list[i])] = {'tagging_mode': 'untagged'}
vlan_attributes = {'vlanid': vlanid, 'members': vmbr_list }
+ dhcp_attributes = {}
# If this VLAN requires a DHCP relay agent, it will contain a element
# containing a list of DHCP server IPs
@@ -557,6 +559,9 @@ def parse_dpg(dpg, hname):
vintfdhcpservers = vintf_node.text
vdhcpserver_list = vintfdhcpservers.split(';')
vlan_attributes['dhcpv6_servers'] = vdhcpserver_list
+ dhcp_attributes['dhcpv6_servers'] = vdhcpserver_list
+ sonic_vlan_member_name = "Vlan%s" % (vlanid)
+ dhcp_relay_table[sonic_vlan_member_name] = dhcp_attributes
vlanmac = vintf.find(str(QName(ns, "MacAddress")))
if vlanmac is not None and vlanmac.text is not None:
@@ -567,29 +572,6 @@ def parse_dpg(dpg, hname):
vlan_attributes['alias'] = vintfname
vlans[sonic_vlan_name] = vlan_attributes
- dhcp = child.find(str(QName(ns, "Dhcp")))
- dhcp_table = {}
-
- if dhcp is not None:
- for vintf in dhcp.findall(str(QName(ns, "VlanInterface"))):
- vintfname = vintf.find(str(QName(ns, "Name"))).text
-
- dhcp_attributes = {}
-
- dhcp_node = vintf.find(str(QName(ns, "Dhcpv6Relays")))
- if dhcp_node is not None and dhcp_node.text is not None:
- dhcpservers = dhcp_node.text
- vdhcpserver_list = dhcpservers.split(';')
- dhcp_attributes['dhcpv6_servers'] = vdhcpserver_list
-
- option_linklayer_addr = vintf.find(str(QName(ns, "Dhcpv6OptionRfc6939")))
- if option_linklayer_addr is not None and option_linklayer_addr.text == "true":
- dhcp_attributes['dhcpv6_option|rfc6939_support'] = "true"
- elif option_linklayer_addr is not None and option_linklayer_addr.text == "false":
- dhcp_attributes['dhcpv6_option|rfc6939_support'] = "false"
-
- dhcp_table[vintfname] = dhcp_attributes
-
acls = {}
for aclintf in aclintfs.findall(str(QName(ns, "AclInterface"))):
if aclintf.find(str(QName(ns, "InAcl"))) is not None:
@@ -704,7 +686,7 @@ def parse_dpg(dpg, hname):
if mg_key in mg_tunnel.attrib:
tunnelintfs[tunnel_type][tunnel_name][table_key] = mg_tunnel.attrib[mg_key]
- return intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, dhcp_table, pcs, pc_members, acls, vni, tunnelintfs, dpg_ecmp_content
+ return intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, dhcp_relay_table, pcs, pc_members, acls, vni, tunnelintfs, dpg_ecmp_content
return None, None, None, None, None, None, None, None, None, None, None, None, None
def parse_host_loopback(dpg, hname):
@@ -1131,7 +1113,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
tunnel_intfs = None
vlans = None
vlan_members = None
- dhcp_table = None
+ dhcp_relay_table = None
pcs = None
mgmt_intf = None
lo_intfs = None
@@ -1191,7 +1173,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
for child in root:
if asic_name is None:
if child.tag == str(QName(ns, "DpgDec")):
- (intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, dhcp_table, pcs, pc_members, acls, vni, tunnel_intfs, dpg_ecmp_content) = parse_dpg(child, hostname)
+ (intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, dhcp_relay_table, pcs, pc_members, acls, vni, tunnel_intfs, dpg_ecmp_content) = parse_dpg(child, hostname)
elif child.tag == str(QName(ns, "CpgDec")):
(bgp_sessions, bgp_internal_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, hostname)
elif child.tag == str(QName(ns, "PngDec")):
@@ -1206,7 +1188,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
(port_speeds_default, port_descriptions) = parse_deviceinfo(child, hwsku)
else:
if child.tag == str(QName(ns, "DpgDec")):
- (intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, dhcp_table, pcs, pc_members, acls, vni, tunnel_intfs, dpg_ecmp_content) = parse_dpg(child, asic_name)
+ (intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, dhcp_relay_table, pcs, pc_members, acls, vni, tunnel_intfs, dpg_ecmp_content) = parse_dpg(child, asic_name)
host_lo_intfs = parse_host_loopback(child, hostname)
elif child.tag == str(QName(ns, "CpgDec")):
(bgp_sessions, bgp_internal_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, asic_name, local_devices)
@@ -1523,7 +1505,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
results['DEVICE_NEIGHBOR_METADATA'] = { key:devices[key] for key in devices if key in {device['name'] for device in neighbors.values()} }
results['SYSLOG_SERVER'] = dict((item, {}) for item in syslog_servers)
results['DHCP_SERVER'] = dict((item, {}) for item in dhcp_servers)
- results['DHCP'] = dhcp_table
+ results['DHCP_RELAY'] = dhcp_relay_table
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_table_bindings(acls, neighbors, pcs, sub_role)
diff --git a/src/sonic-config-engine/tests/simple-sample-graph-case.xml b/src/sonic-config-engine/tests/simple-sample-graph-case.xml
index 95398e6913c..78e81bd6df7 100644
--- a/src/sonic-config-engine/tests/simple-sample-graph-case.xml
+++ b/src/sonic-config-engine/tests/simple-sample-graph-case.xml
@@ -134,6 +134,7 @@
ab1
fortyGigE0/8
192.0.0.1;192.0.0.2
+ fc02:2000::1;fc02:2000::2
1000
1000
192.168.0.0/27
@@ -143,23 +144,12 @@
ab2
fortyGigE0/4
192.0.0.1
+ fc02:2000::3;fc02:2000::4
2000
2000
-
-
- Vlan1000
- fc02:2000::1;fc02:2000::2
- true
-
-
- Vlan2000
- fc02:2000::3;fc02:2000::4
- false
-
-
diff --git a/src/sonic-config-engine/tests/test_cfggen.py b/src/sonic-config-engine/tests/test_cfggen.py
index 502c4b2e416..0a0dd54a76d 100644
--- a/src/sonic-config-engine/tests/test_cfggen.py
+++ b/src/sonic-config-engine/tests/test_cfggen.py
@@ -686,12 +686,12 @@ def test_show_run_interfaces(self):
self.assertEqual(output, '')
def test_minigraph_dhcp(self):
- argument = '-m "' + self.sample_graph_simple_case + '" -p "' + self.port_config + '" -v DHCP'
+ argument = '-m "' + self.sample_graph_simple_case + '" -p "' + self.port_config + '" -v DHCP_RELAY'
output = self.run_script(argument)
self.assertEqual(
utils.to_dict(output.strip()),
utils.to_dict(
- "{'Vlan1000': {'dhcpv6_servers': ['fc02:2000::1', 'fc02:2000::2'], 'dhcpv6_option|rfc6939_support': 'true'}, "
- "'Vlan2000': {'dhcpv6_servers': ['fc02:2000::3', 'fc02:2000::4'], 'dhcpv6_option|rfc6939_support': 'false'}}"
+ "{'Vlan1000': {'dhcpv6_servers': ['fc02:2000::1', 'fc02:2000::2']}, "
+ "'Vlan2000': {'dhcpv6_servers': ['fc02:2000::3', 'fc02:2000::4']}}"
)
)
diff --git a/src/sonic-config-engine/tests/test_minigraph_case.py b/src/sonic-config-engine/tests/test_minigraph_case.py
index 998b66cfb9a..560d0990fdc 100644
--- a/src/sonic-config-engine/tests/test_minigraph_case.py
+++ b/src/sonic-config-engine/tests/test_minigraph_case.py
@@ -102,6 +102,7 @@ def test_minigraph_vlans(self):
'Vlan1000': {
'alias': 'ab1',
'dhcp_servers': ['192.0.0.1', '192.0.0.2'],
+ 'dhcpv6_servers': ['fc02:2000::1', 'fc02:2000::2'],
'vlanid': '1000',
'mac': '00:aa:bb:cc:dd:ee',
'members': ['Ethernet8']
@@ -109,6 +110,7 @@ def test_minigraph_vlans(self):
'Vlan2000': {
'alias': 'ab2',
'dhcp_servers': ['192.0.0.1'],
+ 'dhcpv6_servers': ['fc02:2000::3', 'fc02:2000::4'],
'members': ['Ethernet4'],
'vlanid': '2000'
}
@@ -359,21 +361,19 @@ def test_minigraph_mux_cable_table(self):
)
def test_dhcp_table(self):
- argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DHCP"'
+ argument = '-m "' + self.sample_graph + '" -p "' + self.port_config + '" -v "DHCP_RELAY"'
expected = {
'Vlan1000': {
'dhcpv6_servers': [
"fc02:2000::1",
"fc02:2000::2"
- ],
- 'dhcpv6_option|rfc6939_support': 'true'
+ ]
},
- 'Vlan2000': {
+ 'Vlan2000': {
'dhcpv6_servers': [
"fc02:2000::3",
"fc02:2000::4"
- ],
- 'dhcpv6_option|rfc6939_support': 'false'
+ ]
}
}
output = self.run_script(argument)