diff --git a/files/image_config/interfaces/interfaces.j2 b/files/image_config/interfaces/interfaces.j2
index 425badf7f21..40b2cc1746a 100644
--- a/files/image_config/interfaces/interfaces.j2
+++ b/files/image_config/interfaces/interfaces.j2
@@ -20,11 +20,13 @@ iface lo {{ 'inet' if minigraph_lo_interface['addr'] | ipv4 else 'inet6' }} stat
{% block mgmt_interface %}
# The management network interface
auto eth0
-{% if minigraph_mgmt_interface['addr'] %}
+{% if minigraph_mgmt_interfaces | length %}
+{% for minigraph_mgmt_interface in minigraph_mgmt_interfaces %}
+{% if minigraph_mgmt_interface['addr'] | ipv4 %}
iface eth0 inet static
address {{ minigraph_mgmt_interface['addr'] }}
netmask {{ minigraph_mgmt_interface['mask'] }}
- ########## management network policy routing rules
+ ## management network policy routing rules ##
# management port up rules
up ip route add default via {{ minigraph_mgmt_interface['gwaddr'] }} dev eth0 table default
up ip rule add from {{ minigraph_mgmt_interface['addr'] }}/32 table default
@@ -39,9 +41,16 @@ iface eth0 inet static
{% endfor %}
{# TODO: COPP policy type rules #}
{% else %}
-iface eth0 inet dhcp
+iface eth0 inet6 static
+ address {{ minigraph_mgmt_interface['addr'] }}
+ netmask {{ minigraph_mgmt_interface['mask'] }}
{% endif %}
#
+{% endfor %}
+{% else %}
+iface eth0 inet dhcp
+#
+{% endif %}
{% endblock mgmt_interface %}
{% block front_panel_interfaces %}
# The switch front panel interfaces
diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py
index 1fd16f376fa..c9cf73c417a 100644
--- a/src/sonic-config-engine/minigraph.py
+++ b/src/sonic-config-engine/minigraph.py
@@ -167,32 +167,23 @@ def parse_dpg(dpg, hname):
intf['peer_addr'] = ipaddress.IPAddress(peer_addr_val)
intfs.append(intf)
- lointfs = child.find(str(QName(ns, "LoopbackIPInterfaces")))
- lo_intfs = []
- for lointf in lointfs.findall(str(QName(ns1, "LoopbackIPInterface"))):
- intfname = lointf.find(str(QName(ns, "AttachTo"))).text
- ipprefix = lointf.find(str(QName(ns1, "PrefixStr"))).text
- ipn = ipaddress.IPNetwork(ipprefix)
- ipaddr = ipn.ip
- prefix_len = ipn.prefixlen
- ipmask = ipn.netmask
- lo_intf = {'name': intfname, 'addr': ipaddr, 'prefixlen': prefix_len}
- if isinstance(ipn, ipaddress.IPv4Network):
- lo_intf['mask'] = ipmask
- else:
- lo_intf['mask'] = str(prefix_len)
- lo_intfs.append(lo_intf)
-
- mgmtintfs = child.find(str(QName(ns, "ManagementIPInterfaces")))
- mgmt_intf = None
- for mgmtintf in mgmtintfs.findall(str(QName(ns1, "ManagementIPInterface"))):
- ipprefix = mgmtintf.find(str(QName(ns1, "PrefixStr"))).text
- mgmtipn = ipaddress.IPNetwork(ipprefix)
- ipaddr = mgmtipn.ip
- prefix_len = str(mgmtipn.prefixlen)
- ipmask = mgmtipn.netmask
- gwaddr = ipaddress.IPAddress(int(mgmtipn.network) + 1)
- mgmt_intf = {'addr': ipaddr, 'prefixlen': prefix_len, 'mask': ipmask, 'gwaddr': gwaddr}
+ def _parse_ip_interface(interfaces, interface):
+ intfs = child.find(str(QName(ns, interfaces)))
+ rv = []
+ for intf in intfs.findall(str(QName(ns1, interface))):
+ intf_name = intf.find(str(QName(ns, "AttachTo"))).text
+ intf_ip = ipaddress.IPNetwork(intf.find(str(QName(ns1, "PrefixStr"))).text)
+ intf = {'name': intf_name, 'addr': intf_ip.ip, 'prefixlen': intf_ip.prefixlen}
+ if intf_ip.version == 4:
+ intf['mask'] = intf_ip.netmask
+ else:
+ intf['mask'] = str(intf_ip.prefixlen)
+ intf['gwaddr'] = ipaddress.IPAddress(int(intf_ip.network) + 1)
+ rv.append(intf)
+ return rv
+
+ lo_intfs = _parse_ip_interface("LoopbackIPInterfaces", "LoopbackIPInterface")
+ mgmt_intfs = _parse_ip_interface("ManagementIPInterfaces", "ManagementIPInterface")
pcintfs = child.find(str(QName(ns, "PortChannelInterfaces")))
pc_intfs = []
@@ -241,7 +232,7 @@ def parse_dpg(dpg, hname):
break;
if acl_intfs:
acls[aclname] = { 'AttachTo': acl_intfs, 'IsMirror': is_mirror }
- return intfs, lo_intfs, mgmt_intf, vlans, pcs, acls
+ return intfs, lo_intfs, mgmt_intfs, vlans, pcs, acls
return None, None, None, None, None, None
@@ -404,8 +395,8 @@ def parse_xml(filename, platform=None, port_config_file=None):
pc_intfs = None
vlans = None
pcs = None
- mgmt_intf = None
- lo_intf = None
+ lo_intfs = None
+ mgmt_intfs = None
neighbors = None
devices = None
hostname = None
@@ -429,7 +420,7 @@ def parse_xml(filename, platform=None, port_config_file=None):
for child in root:
if child.tag == str(QName(ns, "DpgDec")):
- (intfs, lo_intfs, mgmt_intf, vlans, pcs, acls) = parse_dpg(child, hostname)
+ (intfs, lo_intfs, mgmt_intfs, vlans, pcs, acls) = parse_dpg(child, hostname)
elif child.tag == str(QName(ns, "CpgDec")):
(bgp_sessions, bgp_asn, bgp_peers_with_range) = parse_cpg(child, hostname)
elif child.tag == str(QName(ns, "PngDec")):
@@ -467,7 +458,7 @@ def parse_xml(filename, platform=None, port_config_file=None):
results['minigraph_ports'] = ports
results['minigraph_vlans'] = vlans
results['minigraph_portchannels'] = pcs
- results['minigraph_mgmt_interface'] = mgmt_intf
+ results['minigraph_mgmt_interfaces'] = mgmt_intfs
results['minigraph_lo_interfaces'] = lo_intfs
results['minigraph_acls'] = acls
results['minigraph_neighbors'] = neighbors
diff --git a/src/sonic-config-engine/tests/sample_output/interfaces b/src/sonic-config-engine/tests/sample_output/interfaces
new file mode 100644
index 00000000000..af21a79b2f9
--- /dev/null
+++ b/src/sonic-config-engine/tests/sample_output/interfaces
@@ -0,0 +1,263 @@
+#
+# =============== Managed by SONiC Config Engine DO NOT EDIT! ===============
+# generated from /usr/share/sonic/templates/interfaces.j2 using sonic-cfggen
+# file: /etc/network/interfaces
+#
+# The loopback network interface
+auto lo
+iface lo inet loopback
+# Use command 'ip addr list dev lo' to check all addresses
+iface lo inet static
+ address 10.1.0.32
+ netmask 255.255.255.255
+#
+iface lo inet6 static
+ address fc00:1::32
+ netmask 128
+#
+# The management network interface
+auto eth0
+iface eth0 inet static
+ address 10.0.0.100
+ netmask 255.255.255.0
+ ## management network policy routing rules ##
+ # management port up rules
+ up ip route add default via 10.0.0.1 dev eth0 table default
+ up ip rule add from 10.0.0.100/32 table default
+ # management port down rules
+ down ip route delete default via 10.0.0.1 dev eth0 table default
+ down ip rule delete from 10.0.0.100/32 table default
+#
+iface eth0 inet6 static
+ address 2603:10e2:0:2903::7
+ netmask 64
+#
+# The switch front panel interfaces
+# "|| true" is added to suppress the error when interface is already a member of VLAN
+allow-hotplug fortyGigE0/4
+iface fortyGigE0/4 inet manual
+ pre-up ifconfig fortyGigE0/4 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/4 || true
+ post-down ifconfig fortyGigE0/4 down
+#
+allow-hotplug fortyGigE0/8
+iface fortyGigE0/8 inet manual
+ pre-up ifconfig fortyGigE0/8 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/8 || true
+ post-down ifconfig fortyGigE0/8 down
+#
+allow-hotplug fortyGigE0/12
+iface fortyGigE0/12 inet manual
+ pre-up ifconfig fortyGigE0/12 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/12 || true
+ post-down ifconfig fortyGigE0/12 down
+#
+allow-hotplug fortyGigE0/16
+iface fortyGigE0/16 inet manual
+ pre-up ifconfig fortyGigE0/16 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/16 || true
+ post-down ifconfig fortyGigE0/16 down
+#
+allow-hotplug fortyGigE0/20
+iface fortyGigE0/20 inet manual
+ pre-up ifconfig fortyGigE0/20 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/20 || true
+ post-down ifconfig fortyGigE0/20 down
+#
+allow-hotplug fortyGigE0/24
+iface fortyGigE0/24 inet manual
+ pre-up ifconfig fortyGigE0/24 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/24 || true
+ post-down ifconfig fortyGigE0/24 down
+#
+allow-hotplug fortyGigE0/28
+iface fortyGigE0/28 inet manual
+ pre-up ifconfig fortyGigE0/28 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/28 || true
+ post-down ifconfig fortyGigE0/28 down
+#
+allow-hotplug fortyGigE0/32
+iface fortyGigE0/32 inet manual
+ pre-up ifconfig fortyGigE0/32 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/32 || true
+ post-down ifconfig fortyGigE0/32 down
+#
+allow-hotplug fortyGigE0/36
+iface fortyGigE0/36 inet manual
+ pre-up ifconfig fortyGigE0/36 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/36 || true
+ post-down ifconfig fortyGigE0/36 down
+#
+allow-hotplug fortyGigE0/40
+iface fortyGigE0/40 inet manual
+ pre-up ifconfig fortyGigE0/40 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/40 || true
+ post-down ifconfig fortyGigE0/40 down
+#
+allow-hotplug fortyGigE0/44
+iface fortyGigE0/44 inet manual
+ pre-up ifconfig fortyGigE0/44 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/44 || true
+ post-down ifconfig fortyGigE0/44 down
+#
+allow-hotplug fortyGigE0/48
+iface fortyGigE0/48 inet manual
+ pre-up ifconfig fortyGigE0/48 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/48 || true
+ post-down ifconfig fortyGigE0/48 down
+#
+allow-hotplug fortyGigE0/52
+iface fortyGigE0/52 inet manual
+ pre-up ifconfig fortyGigE0/52 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/52 || true
+ post-down ifconfig fortyGigE0/52 down
+#
+allow-hotplug fortyGigE0/56
+iface fortyGigE0/56 inet manual
+ pre-up ifconfig fortyGigE0/56 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/56 || true
+ post-down ifconfig fortyGigE0/56 down
+#
+allow-hotplug fortyGigE0/60
+iface fortyGigE0/60 inet manual
+ pre-up ifconfig fortyGigE0/60 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/60 || true
+ post-down ifconfig fortyGigE0/60 down
+#
+allow-hotplug fortyGigE0/64
+iface fortyGigE0/64 inet manual
+ pre-up ifconfig fortyGigE0/64 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/64 || true
+ post-down ifconfig fortyGigE0/64 down
+#
+allow-hotplug fortyGigE0/68
+iface fortyGigE0/68 inet manual
+ pre-up ifconfig fortyGigE0/68 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/68 || true
+ post-down ifconfig fortyGigE0/68 down
+#
+allow-hotplug fortyGigE0/72
+iface fortyGigE0/72 inet manual
+ pre-up ifconfig fortyGigE0/72 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/72 || true
+ post-down ifconfig fortyGigE0/72 down
+#
+allow-hotplug fortyGigE0/76
+iface fortyGigE0/76 inet manual
+ pre-up ifconfig fortyGigE0/76 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/76 || true
+ post-down ifconfig fortyGigE0/76 down
+#
+allow-hotplug fortyGigE0/80
+iface fortyGigE0/80 inet manual
+ pre-up ifconfig fortyGigE0/80 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/80 || true
+ post-down ifconfig fortyGigE0/80 down
+#
+allow-hotplug fortyGigE0/84
+iface fortyGigE0/84 inet manual
+ pre-up ifconfig fortyGigE0/84 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/84 || true
+ post-down ifconfig fortyGigE0/84 down
+#
+allow-hotplug fortyGigE0/88
+iface fortyGigE0/88 inet manual
+ pre-up ifconfig fortyGigE0/88 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/88 || true
+ post-down ifconfig fortyGigE0/88 down
+#
+allow-hotplug fortyGigE0/92
+iface fortyGigE0/92 inet manual
+ pre-up ifconfig fortyGigE0/92 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/92 || true
+ post-down ifconfig fortyGigE0/92 down
+#
+allow-hotplug fortyGigE0/96
+iface fortyGigE0/96 inet manual
+ pre-up ifconfig fortyGigE0/96 up mtu 9216
+ post-up brctl addif Vlan1000 fortyGigE0/96 || true
+ post-down ifconfig fortyGigE0/96 down
+#
+# "|| true" is added to suppress the error when interface is already a member of LAG
+# "ip link show | grep -q master" is added to ensure interface is enslaved
+allow-hotplug fortyGigE0/112
+iface fortyGigE0/112 inet manual
+ pre-up teamdctl PortChannel01 port add fortyGigE0/112 || true
+ post-up ip link show fortyGigE0/112 | grep -q master && ifconfig fortyGigE0/112 up
+ post-down ifconfig fortyGigE0/112 down
+#
+allow-hotplug fortyGigE0/116
+iface fortyGigE0/116 inet manual
+ pre-up teamdctl PortChannel02 port add fortyGigE0/116 || true
+ post-up ip link show fortyGigE0/116 | grep -q master && ifconfig fortyGigE0/116 up
+ post-down ifconfig fortyGigE0/116 down
+#
+allow-hotplug fortyGigE0/120
+iface fortyGigE0/120 inet manual
+ pre-up teamdctl PortChannel03 port add fortyGigE0/120 || true
+ post-up ip link show fortyGigE0/120 | grep -q master && ifconfig fortyGigE0/120 up
+ post-down ifconfig fortyGigE0/120 down
+#
+allow-hotplug fortyGigE0/124
+iface fortyGigE0/124 inet manual
+ pre-up teamdctl PortChannel04 port add fortyGigE0/124 || true
+ post-up ip link show fortyGigE0/124 | grep -q master && ifconfig fortyGigE0/124 up
+ post-down ifconfig fortyGigE0/124 down
+#
+# Vlan interfaces
+auto Vlan1000
+iface Vlan1000 inet static
+ bridge_ports none
+ address 192.168.0.1
+ netmask 255.255.255.224
+#
+# Portchannel interfaces
+allow-hotplug PortChannel01
+iface PortChannel01 inet static
+ mtu 9216
+ address 10.0.0.56
+ netmask 255.255.255.254
+#
+allow-hotplug PortChannel01
+iface PortChannel01 inet6 static
+ mtu 9216
+ address fc00::71
+ netmask 126
+#
+allow-hotplug PortChannel02
+iface PortChannel02 inet static
+ mtu 9216
+ address 10.0.0.58
+ netmask 255.255.255.254
+#
+allow-hotplug PortChannel02
+iface PortChannel02 inet6 static
+ mtu 9216
+ address fc00::75
+ netmask 126
+#
+allow-hotplug PortChannel03
+iface PortChannel03 inet static
+ mtu 9216
+ address 10.0.0.60
+ netmask 255.255.255.254
+#
+allow-hotplug PortChannel03
+iface PortChannel03 inet6 static
+ mtu 9216
+ address fc00::79
+ netmask 126
+#
+allow-hotplug PortChannel04
+iface PortChannel04 inet static
+ mtu 9216
+ address 10.0.0.62
+ netmask 255.255.255.254
+#
+allow-hotplug PortChannel04
+iface PortChannel04 inet6 static
+ mtu 9216
+ address fc00::7d
+ netmask 126
+#
+
diff --git a/src/sonic-config-engine/tests/t0-sample-graph.xml b/src/sonic-config-engine/tests/t0-sample-graph.xml
index e359b4fa629..f92e5d5a4cd 100644
--- a/src/sonic-config-engine/tests/t0-sample-graph.xml
+++ b/src/sonic-config-engine/tests/t0-sample-graph.xml
@@ -163,6 +163,14 @@
10.0.0.100/24
+
+ HostIP
+ eth0
+
+ 2603:10e2:0:2903::7/64
+
+ 2603:10e2:0:2903::7/64
+
diff --git a/src/sonic-config-engine/tests/test_j2files.py b/src/sonic-config-engine/tests/test_j2files.py
index 238d8c81551..809acea0512 100644
--- a/src/sonic-config-engine/tests/test_j2files.py
+++ b/src/sonic-config-engine/tests/test_j2files.py
@@ -20,8 +20,9 @@ def run_script(self, argument):
def test_interfaces(self):
interfaces_template = os.path.join(self.test_dir, '..', '..', '..', 'files', 'image_config', 'interfaces', 'interfaces.j2')
- argument = '-m "' + self.t0_minigraph + '" -p "' + self.t0_port_config + '" -t "' + interfaces_template + '"'
- output = self.run_script(argument)
+ argument = '-m ' + self.t0_minigraph + ' -t ' + interfaces_template + ' > ' + self.output_file
+ self.run_script(argument)
+ self.assertTrue(filecmp.cmp(self.output_file, os.path.join(self.test_dir, 'sample_output', 'interfaces')))
def test_alias_map(self):
alias_map_template = os.path.join(self.test_dir, '..', '..', '..', 'dockers', 'docker-snmp-sv2', 'alias_map.j2')