diff --git a/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2 b/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2
index ef98dcf9f16a..5fe7a2b01051 100644
--- a/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2
+++ b/dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2
@@ -15,7 +15,7 @@ ipv6 prefix-list PL_LoopbackV6 permit {{ get_ipv6_loopback_address(LOOPBACK_INTE
{% endif %}
!
!
-{% if DEVICE_METADATA['localhost']['sub_role'] == 'FrontEnd' %}
+{% if DEVICE_METADATA['localhost']['sub_role'] == 'FrontEnd' or DEVICE_METADATA['localhost']['sub_role'] == 'BackEnd' %}
route-map HIDE_INTERNAL permit 10
set community local-AS
!
@@ -38,16 +38,30 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
{% endif %}
!
{# set router-id #}
+{% if multi_asic() %}
+ bgp router-id {{ get_ipv4_loopback_address(LOOPBACK_INTERFACE, "Loopback4096") | ip }}
+{% else %}
bgp router-id {{ get_ipv4_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | ip }}
+{% endif %}
!
{# advertise loopback #}
network {{ get_ipv4_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | ip }}/32
+{% if multi_asic() %}
+ network {{ get_ipv4_loopback_address(LOOPBACK_INTERFACE, "Loopback4096") | ip }}/32 route-map HIDE_INTERNAL
+{% endif %}
!
{% if get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") != 'None' %}
address-family ipv6
network {{ get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | ip }}/64
exit-address-family
{% endif %}
+{% if multi_asic() %}
+{% if get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback4096") != 'None' %}
+ address-family ipv6
+ network {{ get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback4096") | ip }}/64 route-map HIDE_INTERNAL
+ exit-address-family
+{% endif %}
+{% endif %}
{% endblock bgp_init %}
!
{% block vlan_advertisement %}
diff --git a/src/sonic-config-engine/minigraph.py b/src/sonic-config-engine/minigraph.py
index 79e553e0191d..2fe699987279 100644
--- a/src/sonic-config-engine/minigraph.py
+++ b/src/sonic-config-engine/minigraph.py
@@ -251,6 +251,15 @@ def parse_asic_png(png, asic_name, hostname):
devices[name] = device_data
return (neighbors, devices, port_speeds)
+def parse_loopback_intf(child):
+ 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
+ lo_intfs[(intfname, ipprefix)] = {}
+ return lo_intfs
+
def parse_dpg(dpg, hname):
aclintfs = None
mgmtintfs = None
@@ -269,7 +278,6 @@ def parse_dpg(dpg, hname):
"""
if mgmtintfs is None and child.find(str(QName(ns, "ManagementIPInterfaces"))) is not None:
mgmtintfs = child.find(str(QName(ns, "ManagementIPInterfaces")))
-
hostname = child.find(str(QName(ns, "Hostname")))
if hostname.text.lower() != hname.lower():
continue
@@ -290,12 +298,7 @@ def parse_dpg(dpg, hname):
ipprefix = ipintf.find(str(QName(ns, "Prefix"))).text
intfs[(intfname, ipprefix)] = {}
- 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
- lo_intfs[(intfname, ipprefix)] = {}
+ lo_intfs = parse_loopback_intf(child)
mvrfConfigs = child.find(str(QName(ns, "MgmtVrfConfigs")))
mvrf = {}
@@ -452,6 +455,13 @@ def parse_dpg(dpg, hname):
return intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni
return None, None, None, None, None, None, None, None, None, None
+def parse_host_loopback(dpg, hname):
+ for child in dpg:
+ hostname = child.find(str(QName(ns, "Hostname")))
+ if hostname.text.lower() != hname.lower():
+ continue
+ lo_intfs = parse_loopback_intf(child)
+ return lo_intfs
def parse_cpg(cpg, hname):
bgp_sessions = {}
@@ -826,6 +836,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
cloudtype = None
hostname = None
linkmetas = {}
+ host_lo_intfs = None
# hostname is the asic_name, get the asic_id from the asic_name
if asic_name is not None:
@@ -867,6 +878,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
else:
if child.tag == str(QName(ns, "DpgDec")):
(intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni) = parse_dpg(child, asic_name)
+ host_lo_intfs = parse_host_loopback(child, hostname)
elif child.tag == str(QName(ns, "CpgDec")):
(bgp_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, asic_name)
enable_internal_bgp_session(bgp_sessions, filename, asic_name)
@@ -930,6 +942,12 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
for lo_intf in lo_intfs:
results['LOOPBACK_INTERFACE'][lo_intf] = lo_intfs[lo_intf]
results['LOOPBACK_INTERFACE'][lo_intf[0]] = {}
+
+ if host_lo_intfs is not None:
+ for host_lo_intf in host_lo_intfs:
+ results['LOOPBACK_INTERFACE'][host_lo_intf] = host_lo_intfs[host_lo_intf]
+ results['LOOPBACK_INTERFACE'][host_lo_intf[0]] = {}
+
results['MGMT_VRF_CONFIG'] = mvrf
phyport_intfs = {}
diff --git a/src/sonic-config-engine/sonic-cfggen b/src/sonic-config-engine/sonic-cfggen
index 1118703458db..9bda72071937 100755
--- a/src/sonic-config-engine/sonic-cfggen
+++ b/src/sonic-config-engine/sonic-cfggen
@@ -45,6 +45,7 @@ from sonic_device_util import get_machine_info
from sonic_device_util import get_platform_info
from sonic_device_util import get_system_mac
from sonic_device_util import get_npu_id_from_name
+from sonic_device_util import is_multi_npu
from config_samples import generate_sample_config
from config_samples import get_available_config
from swsssdk import SonicV2Connector, ConfigDBConnector, SonicDBConfig
@@ -344,6 +345,8 @@ def main():
env.filters['ip_network'] = ip_network
for attr in ['ip', 'network', 'prefixlen', 'netmask', 'broadcast']:
env.filters[attr] = partial(prefix_attr, attr)
+ # Pass the is_multi_npu function as global
+ env.globals['multi_asic'] = is_multi_npu
template = env.get_template(template_file)
print(template.render(sort_data(data)))
diff --git a/src/sonic-config-engine/sonic_device_util.py b/src/sonic-config-engine/sonic_device_util.py
index 5984a7047fe7..ddfa751250c5 100644
--- a/src/sonic-config-engine/sonic_device_util.py
+++ b/src/sonic-config-engine/sonic_device_util.py
@@ -44,12 +44,20 @@ def get_npu_id_from_name(npu_name):
else:
return None
+def get_asic_conf_file_path(platform):
+ asic_conf_path_candidates = []
+ asic_conf_path_candidates.append(os.path.join('/usr/share/sonic/platform', ASIC_CONF_FILENAME))
+ if platform is not None:
+ asic_conf_path_candidates.append(os.path.join(SONIC_DEVICE_PATH, platform, ASIC_CONF_FILENAME))
+ for asic_conf_file_path in asic_conf_path_candidates:
+ if os.path.isfile(asic_conf_file_path):
+ return asic_conf_file_path
+ return None
+
def get_num_npus():
platform = get_platform_info(get_machine_info())
- if not platform:
- return 1
- asic_conf_file_path = os.path.join(SONIC_DEVICE_PATH, platform, ASIC_CONF_FILENAME)
- if not os.path.isfile(asic_conf_file_path):
+ asic_conf_file_path = get_asic_conf_file_path(platform)
+ if asic_conf_file_path is None:
return 1
with open(asic_conf_file_path) as asic_conf_file:
for line in asic_conf_file:
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 8ca17925c6ec..412262315b4e 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
@@ -387,12 +387,20 @@
LoopbackInterface
HostIP
- Loopback0
+ Loopback4096
8.0.0.0/32
8.0.0.0/32
+
+ HostIP1
+ Loopback4096
+
+ FD00:1::32/128
+
+ FD00:1::32/128
+
@@ -457,12 +465,20 @@
LoopbackInterface
HostIP
- Loopback0
+ Loopback4096
8.0.0.1/32
8.0.0.1/32
+
+ HostIP1
+ Loopback4096
+
+ FD00:2::32/128
+
+ FD00:2::32/128
+
@@ -526,12 +542,20 @@
LoopbackInterface
HostIP
- Loopback0
+ Loopback4096
8.0.0.4/32
8.0.0.4/32
+
+ HostIP1
+ Loopback4096
+
+ FD00:3::32/128
+
+ FD00:3::32/128
+
@@ -580,12 +604,20 @@
LoopbackInterface
HostIP
- Loopback0
+ Loopback4096
8.0.0.5/32
8.0.0.5/32
+
+ HostIP1
+ Loopback4096
+
+ FD00:4::32/128
+
+ FD00:4::32/128
+
diff --git a/src/sonic-config-engine/tests/test_multinpu_cfggen.py b/src/sonic-config-engine/tests/test_multinpu_cfggen.py
index c3307b482b79..7511ce9bcdd1 100644
--- a/src/sonic-config-engine/tests/test_multinpu_cfggen.py
+++ b/src/sonic-config-engine/tests/test_multinpu_cfggen.py
@@ -245,3 +245,32 @@ 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, {})
+
+ def test_loopback_intfs(self):
+ argument = "-m {} --var-json \"LOOPBACK_INTERFACE\"".format(self.sample_graph)
+ output = json.loads(self.run_script(argument))
+ self.assertDictEqual(output, {\
+ "Loopback0": {},
+ "Loopback0|10.1.0.32/32": {},
+ "Loopback0|FC00:1::32/128": {}})
+
+ # The asic configuration should have 2 loopback interfaces
+ argument = "-m {} -n asic0 --var-json \"LOOPBACK_INTERFACE\"".format(self.sample_graph)
+ output = json.loads(self.run_script(argument))
+ self.assertDictEqual(output, { \
+ "Loopback0": {},
+ "Loopback4096": {},
+ "Loopback0|10.1.0.32/32": {},
+ "Loopback0|FC00:1::32/128": {},
+ "Loopback4096|8.0.0.0/32": {},
+ "Loopback4096|FD00:1::32/128": {}})
+
+ argument = "-m {} -n asic3 --var-json \"LOOPBACK_INTERFACE\"".format(self.sample_graph)
+ output = json.loads(self.run_script(argument))
+ self.assertDictEqual(output, {\
+ "Loopback0": {},
+ "Loopback4096": {},
+ "Loopback0|10.1.0.32/32": {},
+ "Loopback0|FC00:1::32/128": {},
+ "Loopback4096|8.0.0.5/32": {},
+ "Loopback4096|FD00:4::32/128": {}})