Skip to content

Commit 002335a

Browse files
arlakshmqiluo-msft
authored andcommitted
[config]: Loopback Interface changes for multi ASIC devices (sonic-net#4825)
* Loopback IP changes for multi ASIC devices multi ASIC will have 2 Loopback Interfaces - Loopback0 has globally unique IP address, which is advertised by the multi ASIC device to its peers. This way all the external devices will see this device as a single device. - Loopback4096 is assigned an IP address which has a scope is within the device. Each ASIC has a different ip address for Loopback4096. This ip address will be used as Router-Id by the bgp instance on multi ASIC devices. This PR implements this change for multi ASIC devices Signed-off-by: Arvindsrinivasan Lakshmi Narasimhan <[email protected]>
1 parent 2b137fb commit 002335a

File tree

6 files changed

+120
-16
lines changed

6 files changed

+120
-16
lines changed

dockers/docker-fpm-frr/frr/bgpd/bgpd.main.conf.j2

+15-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ ipv6 prefix-list PL_LoopbackV6 permit {{ get_ipv6_loopback_address(LOOPBACK_INTE
1515
{% endif %}
1616
!
1717
!
18-
{% if DEVICE_METADATA['localhost']['sub_role'] == 'FrontEnd' %}
18+
{% if multi_asic() %}
1919
route-map HIDE_INTERNAL permit 10
2020
set community local-AS
2121
!
@@ -38,16 +38,30 @@ router bgp {{ DEVICE_METADATA['localhost']['bgp_asn'] }}
3838
{% endif %}
3939
!
4040
{# set router-id #}
41+
{% if multi_asic() %}
42+
bgp router-id {{ get_ipv4_loopback_address(LOOPBACK_INTERFACE, "Loopback4096") | ip }}
43+
{% else %}
4144
bgp router-id {{ get_ipv4_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | ip }}
45+
{% endif %}
4246
!
4347
{# advertise loopback #}
4448
network {{ get_ipv4_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | ip }}/32
49+
{% if multi_asic() %}
50+
network {{ get_ipv4_loopback_address(LOOPBACK_INTERFACE, "Loopback4096") | ip }}/32 route-map HIDE_INTERNAL
51+
{% endif %}
4552
!
4653
{% if get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") != 'None' %}
4754
address-family ipv6
4855
network {{ get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback0") | ip }}/64
4956
exit-address-family
5057
{% endif %}
58+
{% if multi_asic() %}
59+
{% if get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback4096") != 'None' %}
60+
address-family ipv6
61+
network {{ get_ipv6_loopback_address(LOOPBACK_INTERFACE, "Loopback4096") | ip }}/64 route-map HIDE_INTERNAL
62+
exit-address-family
63+
{% endif %}
64+
{% endif %}
5165
{% endblock bgp_init %}
5266
!
5367
{% block vlan_advertisement %}

src/sonic-config-engine/minigraph.py

+25-7
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,15 @@ def parse_asic_png(png, asic_name, hostname):
251251
devices[name] = device_data
252252
return (neighbors, devices, port_speeds)
253253

254+
def parse_loopback_intf(child):
255+
lointfs = child.find(str(QName(ns, "LoopbackIPInterfaces")))
256+
lo_intfs = {}
257+
for lointf in lointfs.findall(str(QName(ns1, "LoopbackIPInterface"))):
258+
intfname = lointf.find(str(QName(ns, "AttachTo"))).text
259+
ipprefix = lointf.find(str(QName(ns1, "PrefixStr"))).text
260+
lo_intfs[(intfname, ipprefix)] = {}
261+
return lo_intfs
262+
254263
def parse_dpg(dpg, hname):
255264
aclintfs = None
256265
mgmtintfs = None
@@ -269,7 +278,6 @@ def parse_dpg(dpg, hname):
269278
"""
270279
if mgmtintfs is None and child.find(str(QName(ns, "ManagementIPInterfaces"))) is not None:
271280
mgmtintfs = child.find(str(QName(ns, "ManagementIPInterfaces")))
272-
273281
hostname = child.find(str(QName(ns, "Hostname")))
274282
if hostname.text.lower() != hname.lower():
275283
continue
@@ -290,12 +298,7 @@ def parse_dpg(dpg, hname):
290298
ipprefix = ipintf.find(str(QName(ns, "Prefix"))).text
291299
intfs[(intfname, ipprefix)] = {}
292300

293-
lointfs = child.find(str(QName(ns, "LoopbackIPInterfaces")))
294-
lo_intfs = {}
295-
for lointf in lointfs.findall(str(QName(ns1, "LoopbackIPInterface"))):
296-
intfname = lointf.find(str(QName(ns, "AttachTo"))).text
297-
ipprefix = lointf.find(str(QName(ns1, "PrefixStr"))).text
298-
lo_intfs[(intfname, ipprefix)] = {}
301+
lo_intfs = parse_loopback_intf(child)
299302

300303
mvrfConfigs = child.find(str(QName(ns, "MgmtVrfConfigs")))
301304
mvrf = {}
@@ -452,6 +455,13 @@ def parse_dpg(dpg, hname):
452455
return intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni
453456
return None, None, None, None, None, None, None, None, None, None
454457

458+
def parse_host_loopback(dpg, hname):
459+
for child in dpg:
460+
hostname = child.find(str(QName(ns, "Hostname")))
461+
if hostname.text.lower() != hname.lower():
462+
continue
463+
lo_intfs = parse_loopback_intf(child)
464+
return lo_intfs
455465

456466
def parse_cpg(cpg, hname):
457467
bgp_sessions = {}
@@ -826,6 +836,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
826836
cloudtype = None
827837
hostname = None
828838
linkmetas = {}
839+
host_lo_intfs = None
829840

830841
# hostname is the asic_name, get the asic_id from the asic_name
831842
if asic_name is not None:
@@ -867,6 +878,7 @@ def parse_xml(filename, platform=None, port_config_file=None, asic_name=None, hw
867878
else:
868879
if child.tag == str(QName(ns, "DpgDec")):
869880
(intfs, lo_intfs, mvrf, mgmt_intf, vlans, vlan_members, pcs, pc_members, acls, vni) = parse_dpg(child, asic_name)
881+
host_lo_intfs = parse_host_loopback(child, hostname)
870882
elif child.tag == str(QName(ns, "CpgDec")):
871883
(bgp_sessions, bgp_asn, bgp_peers_with_range, bgp_monitors) = parse_cpg(child, asic_name)
872884
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
930942
for lo_intf in lo_intfs:
931943
results['LOOPBACK_INTERFACE'][lo_intf] = lo_intfs[lo_intf]
932944
results['LOOPBACK_INTERFACE'][lo_intf[0]] = {}
945+
946+
if host_lo_intfs is not None:
947+
for host_lo_intf in host_lo_intfs:
948+
results['LOOPBACK_INTERFACE'][host_lo_intf] = host_lo_intfs[host_lo_intf]
949+
results['LOOPBACK_INTERFACE'][host_lo_intf[0]] = {}
950+
933951
results['MGMT_VRF_CONFIG'] = mvrf
934952

935953
phyport_intfs = {}

src/sonic-config-engine/sonic-cfggen

+3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ from sonic_device_util import get_machine_info
4545
from sonic_device_util import get_platform_info
4646
from sonic_device_util import get_system_mac
4747
from sonic_device_util import get_npu_id_from_name
48+
from sonic_device_util import is_multi_npu
4849
from config_samples import generate_sample_config
4950
from config_samples import get_available_config
5051
from swsssdk import SonicV2Connector, ConfigDBConnector, SonicDBConfig
@@ -344,6 +345,8 @@ def main():
344345
env.filters['ip_network'] = ip_network
345346
for attr in ['ip', 'network', 'prefixlen', 'netmask', 'broadcast']:
346347
env.filters[attr] = partial(prefix_attr, attr)
348+
# Pass the is_multi_npu function as global
349+
env.globals['multi_asic'] = is_multi_npu
347350
template = env.get_template(template_file)
348351
print(template.render(sort_data(data)))
349352

src/sonic-config-engine/sonic_device_util.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,20 @@ def get_npu_id_from_name(npu_name):
4444
else:
4545
return None
4646

47+
def get_asic_conf_file_path(platform):
48+
asic_conf_path_candidates = []
49+
asic_conf_path_candidates.append(os.path.join('/usr/share/sonic/platform', ASIC_CONF_FILENAME))
50+
if platform is not None:
51+
asic_conf_path_candidates.append(os.path.join(SONIC_DEVICE_PATH, platform, ASIC_CONF_FILENAME))
52+
for asic_conf_file_path in asic_conf_path_candidates:
53+
if os.path.isfile(asic_conf_file_path):
54+
return asic_conf_file_path
55+
return None
56+
4757
def get_num_npus():
4858
platform = get_platform_info(get_machine_info())
49-
if not platform:
50-
return 1
51-
asic_conf_file_path = os.path.join(SONIC_DEVICE_PATH, platform, ASIC_CONF_FILENAME)
52-
if not os.path.isfile(asic_conf_file_path):
59+
asic_conf_file_path = get_asic_conf_file_path(platform)
60+
if asic_conf_file_path is None:
5361
return 1
5462
with open(asic_conf_file_path) as asic_conf_file:
5563
for line in asic_conf_file:

src/sonic-config-engine/tests/multi_npu_data/sample-minigraph.xml

+36-4
Original file line numberDiff line numberDiff line change
@@ -387,12 +387,20 @@
387387
<a:LoopbackIPInterface>
388388
<ElementType>LoopbackInterface</ElementType>
389389
<Name>HostIP</Name>
390-
<AttachTo>Loopback0</AttachTo>
390+
<AttachTo>Loopback4096</AttachTo>
391391
<a:Prefix xmlns:b="Microsoft.Search.Autopilot.NetMux">
392392
<b:IPPrefix>8.0.0.0/32</b:IPPrefix>
393393
</a:Prefix>
394394
<a:PrefixStr>8.0.0.0/32</a:PrefixStr>
395395
</a:LoopbackIPInterface>
396+
<a:LoopbackIPInterface>
397+
<Name>HostIP1</Name>
398+
<AttachTo>Loopback4096</AttachTo>
399+
<a:Prefix xmlns:b="Microsoft.Search.Autopilot.Evolution">
400+
<b:IPPrefix>FD00:1::32/128</b:IPPrefix>
401+
</a:Prefix>
402+
<a:PrefixStr>FD00:1::32/128</a:PrefixStr>
403+
</a:LoopbackIPInterface>
396404
</LoopbackIPInterfaces>
397405
<ManagementIPInterfaces xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
398406
<ManagementVIPInterfaces xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
@@ -457,12 +465,20 @@
457465
<a:LoopbackIPInterface>
458466
<ElementType>LoopbackInterface</ElementType>
459467
<Name>HostIP</Name>
460-
<AttachTo>Loopback0</AttachTo>
468+
<AttachTo>Loopback4096</AttachTo>
461469
<a:Prefix xmlns:b="Microsoft.Search.Autopilot.NetMux">
462470
<b:IPPrefix>8.0.0.1/32</b:IPPrefix>
463471
</a:Prefix>
464472
<a:PrefixStr>8.0.0.1/32</a:PrefixStr>
465473
</a:LoopbackIPInterface>
474+
<a:LoopbackIPInterface>
475+
<Name>HostIP1</Name>
476+
<AttachTo>Loopback4096</AttachTo>
477+
<a:Prefix xmlns:b="Microsoft.Search.Autopilot.Evolution">
478+
<b:IPPrefix>FD00:2::32/128</b:IPPrefix>
479+
</a:Prefix>
480+
<a:PrefixStr>FD00:2::32/128</a:PrefixStr>
481+
</a:LoopbackIPInterface>
466482
</LoopbackIPInterfaces>
467483
<ManagementIPInterfaces xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
468484
<ManagementVIPInterfaces xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
@@ -526,12 +542,20 @@
526542
<a:LoopbackIPInterface>
527543
<ElementType>LoopbackInterface</ElementType>
528544
<Name>HostIP</Name>
529-
<AttachTo>Loopback0</AttachTo>
545+
<AttachTo>Loopback4096</AttachTo>
530546
<a:Prefix xmlns:b="Microsoft.Search.Autopilot.NetMux">
531547
<b:IPPrefix>8.0.0.4/32</b:IPPrefix>
532548
</a:Prefix>
533549
<a:PrefixStr>8.0.0.4/32</a:PrefixStr>
534550
</a:LoopbackIPInterface>
551+
<a:LoopbackIPInterface>
552+
<Name>HostIP1</Name>
553+
<AttachTo>Loopback4096</AttachTo>
554+
<a:Prefix xmlns:b="Microsoft.Search.Autopilot.Evolution">
555+
<b:IPPrefix>FD00:3::32/128</b:IPPrefix>
556+
</a:Prefix>
557+
<a:PrefixStr>FD00:3::32/128</a:PrefixStr>
558+
</a:LoopbackIPInterface>
535559
</LoopbackIPInterfaces>
536560
<ManagementIPInterfaces xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
537561
<ManagementVIPInterfaces xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
@@ -580,12 +604,20 @@
580604
<a:LoopbackIPInterface>
581605
<ElementType>LoopbackInterface</ElementType>
582606
<Name>HostIP</Name>
583-
<AttachTo>Loopback0</AttachTo>
607+
<AttachTo>Loopback4096</AttachTo>
584608
<a:Prefix xmlns:b="Microsoft.Search.Autopilot.NetMux">
585609
<b:IPPrefix>8.0.0.5/32</b:IPPrefix>
586610
</a:Prefix>
587611
<a:PrefixStr>8.0.0.5/32</a:PrefixStr>
588612
</a:LoopbackIPInterface>
613+
<a:LoopbackIPInterface>
614+
<Name>HostIP1</Name>
615+
<AttachTo>Loopback4096</AttachTo>
616+
<a:Prefix xmlns:b="Microsoft.Search.Autopilot.Evolution">
617+
<b:IPPrefix>FD00:4::32/128</b:IPPrefix>
618+
</a:Prefix>
619+
<a:PrefixStr>FD00:4::32/128</a:PrefixStr>
620+
</a:LoopbackIPInterface>
589621
</LoopbackIPInterfaces>
590622
<ManagementIPInterfaces xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>
591623
<ManagementVIPInterfaces xmlns:a="http://schemas.datacontract.org/2004/07/Microsoft.Search.Autopilot.Evolution"/>

src/sonic-config-engine/tests/test_multinpu_cfggen.py

+29
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,32 @@ def test_back_end_asic_acl(self):
245245
argument = "-m {} -p {} -n asic3 --var-json \"ACL_TABLE\"".format(self.sample_graph, self.port_config[3])
246246
output = json.loads(self.run_script(argument))
247247
self.assertDictEqual(output, {})
248+
249+
def test_loopback_intfs(self):
250+
argument = "-m {} --var-json \"LOOPBACK_INTERFACE\"".format(self.sample_graph)
251+
output = json.loads(self.run_script(argument))
252+
self.assertDictEqual(output, {\
253+
"Loopback0": {},
254+
"Loopback0|10.1.0.32/32": {},
255+
"Loopback0|FC00:1::32/128": {}})
256+
257+
# The asic configuration should have 2 loopback interfaces
258+
argument = "-m {} -n asic0 --var-json \"LOOPBACK_INTERFACE\"".format(self.sample_graph)
259+
output = json.loads(self.run_script(argument))
260+
self.assertDictEqual(output, { \
261+
"Loopback0": {},
262+
"Loopback4096": {},
263+
"Loopback0|10.1.0.32/32": {},
264+
"Loopback0|FC00:1::32/128": {},
265+
"Loopback4096|8.0.0.0/32": {},
266+
"Loopback4096|FD00:1::32/128": {}})
267+
268+
argument = "-m {} -n asic3 --var-json \"LOOPBACK_INTERFACE\"".format(self.sample_graph)
269+
output = json.loads(self.run_script(argument))
270+
self.assertDictEqual(output, {\
271+
"Loopback0": {},
272+
"Loopback4096": {},
273+
"Loopback0|10.1.0.32/32": {},
274+
"Loopback0|FC00:1::32/128": {},
275+
"Loopback4096|8.0.0.5/32": {},
276+
"Loopback4096|FD00:4::32/128": {}})

0 commit comments

Comments
 (0)