Skip to content

Commit d7fbdcf

Browse files
authored
Support for minigraph generation for packet based chassis. (#4479)
1. Changes for Generation LC-Graph for packet-based chassis. 2. Added Support Ipv6 Peering on Loopback4096 for voq also 3. Updated asic topology yml files to be offset of slot 4. Made slot_num to take string slot<number> instead of number 5. Consolidated template_dpg_voq_asic.j2 into dpg_asic.j2 6. Remove Loopback4096 from asic topology and parse as dut invertory for multi-asic 7. Updated topo_facts parsing for asic topology_ 8. Internal BGP Session rename from <VoqChassisInternal> to <ChassisInternal> and take switch_type as value.
1 parent b2ad821 commit d7fbdcf

20 files changed

+1432
-1285
lines changed

ansible/config_sonic_basedon_testbed.yml

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
card_type: "{{ card_type | default('fixed') }}"
9494
hostname: "{{ inventory_hostname | default('') }}"
9595
switchids: "{{ switchids | default([]) }}"
96+
slotid: "{{ slot_num | default(None) }}"
9697
delegate_to: localhost
9798
when: deploy is not defined or deploy|bool == false
9899

@@ -101,19 +102,44 @@
101102
num_fabric_asic: "{{ num_fabric_asics | default(0) }}"
102103
asics_host_basepfx: "{{ asics_host_ip | default(None) }}"
103104
asics_host_basepfx6: "{{ asics_host_ipv6 | default(None) }}"
105+
delegate_to: localhost
104106

105107
- name: set all VoQ system ports information
106108
set_fact:
107109
all_sysports: "{{ all_sysports | default( [] ) + hostvars[item]['sysports'] }}"
108110
when: hostvars[item]['sysports'] is defined
109111
loop: "{{ ansible_play_batch }}"
110112

111-
- name: set all VoQ information for iBGP
113+
- name: set all v4 Inband Ip information for iBGP chassis voq
112114
set_fact:
113115
all_inbands: "{{ all_inbands | default( {} ) | combine( { item : hostvars[item]['voq_inband_ip']}) }}"
114116
when: hostvars[item]['voq_inband_ip'] is defined
115117
loop: "{{ ansible_play_batch }}"
116118

119+
- name: set all v6 Inband Ip information for iBGP chassis voq
120+
set_fact:
121+
all_inbands_ipv6: "{{ all_inbands_ipv6 | default( {} ) | combine( { item : hostvars[item]['voq_inband_ipv6']}) }}"
122+
when: hostvars[item]['voq_inband_ipv6'] is defined
123+
loop: "{{ ansible_play_batch }}"
124+
125+
- name: set all Loopback4096 information for iBGP chassis
126+
set_fact:
127+
all_loopback4096: "{{ all_loopback4096 | default( {} ) | combine( { item : hostvars[item]['loopback4096_ip']}) }}"
128+
when: hostvars[item]['loopback4096_ip'] is defined
129+
loop: "{{ ansible_play_batch }}"
130+
131+
- name: set all Loopback4096 ipv6 information for iBGP chassis
132+
set_fact:
133+
all_loopback4096_ipv6: "{{ all_loopback4096_ipv6 | default( {} ) | combine( { item : hostvars[item]['loopback4096_ipv6']}) }}"
134+
when: hostvars[item]['loopback4096_ipv6'] is defined
135+
loop: "{{ ansible_play_batch }}"
136+
137+
- name: set all slot information for chassis
138+
set_fact:
139+
all_slots: "{{ all_slots | default( {} ) | combine( { item : hostvars[item]['slot_num']}) }}"
140+
when: hostvars[item]['slot_num'] is defined
141+
loop: "{{ ansible_play_batch }}"
142+
117143
- name: find all enabled host_interfaces
118144
set_fact:
119145
host_if_indexes: "{{ vm_topo_config['host_interfaces_by_dut'][dut_index|int] | difference(vm_topo_config['disabled_host_interfaces_by_dut'][dut_index|int]) }}"

ansible/lab

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ all:
1212
sonic_a7260:
1313
sonic_multi_asic:
1414
sonic_multi_asic_2:
15+
sonic_msft_sup:
16+
sonic_msft_lc_100G:
1517
fanout:
1618
hosts:
1719
str-7260-10:
@@ -148,3 +150,39 @@ sonic_multi_asic_2:
148150
vlab-08:
149151
ansible_host: 10.250.0.112
150152
ansible_hostv6: fec0::ffff:afa:c
153+
154+
sonic_msft_sup:
155+
vars:
156+
HwSku: msft-RP-O
157+
slot_num: slot0
158+
card_type: supervisor
159+
hosts:
160+
lab-msft-sup-1:
161+
ansible_host: 2.2.2.2
162+
hwsku: msft-RP-O
163+
num_asics: 2
164+
165+
sonic_msft_lc_100G:
166+
vars:
167+
switch_type: chassis-packet
168+
num_asics: 2
169+
frontend_asics: [0,1]
170+
hosts:
171+
lab-msft-lc0-1:
172+
hwsku: msft-LC-48H-O
173+
slot_num: slot1
174+
loopback4096_ip: [3.3.3.3/32,3.3.3.4/32]
175+
loopback4096_ipv6: [2603:10e2:400::3/128,2603:10e2:400::4/128]
176+
ansible_host: 2.2.2.3
177+
lab-msft-lc1-1:
178+
hwsku: msft-LC-48H-O
179+
slot_num: slot2
180+
loopback4096_ip: [3.3.3.5/32,3.3.3.6/32]
181+
loopback4096_ipv6: [2603:10e2:400::5/128,2603:10e2:400::6/128]
182+
ansible_host: 2.2.2.4
183+
lab-msft-lc2-1:
184+
hwsku: msft-LC-48H-O
185+
slot_num: slot3
186+
loopback4096_ip: [3.3.3.7/32,3.3.3.8/32]
187+
loopback4096_ipv6: [2603:10e2:400::7/128,2603:10e2:400::8/128]
188+
ansible_host: 2.2.2.5

ansible/library/port_alias.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,20 +78,22 @@ def get_platform_type(self):
7878
return value
7979
return None
8080

81-
def get_portconfig_path(self, asic_id=None):
81+
def get_portconfig_path(self, slotid=None, asic_id=None):
8282
platform = self.get_platform_type()
8383
if platform is None:
8484
return None
85-
if asic_id is None:
85+
if asic_id is None or asic_id == '':
8686
portconfig = os.path.join(FILE_PATH, platform, self.hwsku, PORTMAP_FILE)
87-
else:
87+
elif slotid is None or slotid == '':
8888
portconfig = os.path.join(FILE_PATH, platform, self.hwsku, str(asic_id), PORTMAP_FILE)
89+
else:
90+
portconfig = os.path.join(FILE_PATH, platform, self.hwsku, str(slotid), str(asic_id), PORTMAP_FILE)
8991
if os.path.exists(portconfig):
9092
return portconfig
9193
return None
9294

9395
def get_portmap(self, asic_id=None, include_internal=False,
94-
hostname=None, switchid=None):
96+
hostname=None, switchid=None, slotid=None):
9597
aliases = []
9698
portmap = {}
9799
aliasmap = {}
@@ -107,7 +109,7 @@ def get_portmap(self, asic_id=None, include_internal=False,
107109
# default to Asic0 as minigraph.py parsing code has that assumption.
108110
asic_name = "Asic0" if asic_id is None else "asic" + str(asic_id)
109111

110-
filename = self.get_portconfig_path(asic_id)
112+
filename = self.get_portconfig_path(slotid, asic_id)
111113
if filename is None:
112114
raise Exception("Something wrong when trying to find the portmap file, either the hwsku is not available or file location is not correct")
113115
with open(filename) as f:
@@ -209,7 +211,8 @@ def main():
209211
include_internal=dict(required=False, type='bool', default=False),
210212
card_type=dict(type='str', required=False),
211213
hostname=dict(type='str', required=False),
212-
switchids=dict(type='list', required=False)
214+
switchids=dict(type='list', required=False),
215+
slotid=dict(type='str', required=False)
213216
),
214217
supports_check_mode=True
215218
)
@@ -236,8 +239,12 @@ def main():
236239
return
237240
allmap = SonicPortAliasMap(m_args['hwsku'])
238241
switchids = None
242+
slotid = None
239243
if 'switchids' in m_args and m_args['switchids'] != None and len(m_args['switchids']):
240244
switchids = m_args['switchids']
245+
246+
if 'slotid' in m_args and m_args['slotid'] != None:
247+
slotid = m_args['slotid']
241248
# When this script is invoked on sonic-mgmt docker, num_asic
242249
# parameter is passed.
243250
if m_args['num_asic'] is not None:
@@ -269,7 +276,7 @@ def main():
269276
if num_asic == 1:
270277
asic_id = None
271278
(aliases_asic, portmap_asic, aliasmap_asic, portspeed_asic, front_panel_asic, asicifnames_asic,
272-
sysport_asic) = allmap.get_portmap(asic_id, include_internal, hostname, switchid)
279+
sysport_asic) = allmap.get_portmap(asic_id, include_internal, hostname, switchid, slotid)
273280
if aliases_asic is not None:
274281
aliases.extend(aliases_asic)
275282
if portmap_asic is not None:

ansible/library/topo_facts.py

Lines changed: 84 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ def __init__(self):
8383
self.asic_topo_config = {}
8484

8585
def parse_topo_defintion(self, topo_definition, po_map, dut_num, neigh_type='VMs'):
86-
dut_asn = topo_definition['configuration_properties']['common']['dut_asn']
8786
vmconfig = dict()
8887
for vm in topo_definition['topology'][neigh_type]:
8988
vmconfig[vm] = dict()
@@ -106,77 +105,93 @@ def parse_topo_defintion(self, topo_definition, po_map, dut_num, neigh_type='VMs
106105
for asic_intf in topo_definition['topology'][neigh_type][vm]['asic_intfs']:
107106
vmconfig[vm]['asic_intfs'][dut_index].append(asic_intf)
108107

108+
109109
# physical interface
110-
for intf in topo_definition['configuration'][vm]['interfaces']:
111-
if (neigh_type == 'VMs' and 'Ethernet' in intf) or \
112-
(neigh_type == 'NEIGH_ASIC' and re.match("Eth(\d+)-", intf)):
113-
dut_index = 0
114-
if 'dut_index' in topo_definition['configuration'][vm]['interfaces'][intf]:
115-
dut_index = topo_definition['configuration'][vm]['interfaces'][intf]['dut_index']
116-
if 'lacp' in topo_definition['configuration'][vm]['interfaces'][intf]:
117-
po_map[topo_definition['configuration'][vm]['interfaces'][intf]['lacp']] = dut_index
118-
119-
vmconfig[vm]['intfs'][dut_index].append(intf)
110+
if 'configuration' in topo_definition:
111+
if 'interfaces' in topo_definition['configuration'][vm]:
112+
for intf in topo_definition['configuration'][vm]['interfaces']:
113+
dut_index = 0
114+
if neigh_type == 'NEIGH_ASIC' and re.match("Eth(\d+)-", intf):
115+
vmconfig[vm]['intfs'][dut_index].append(intf)
116+
elif 'Ethernet' in intf:
117+
if 'dut_index' in topo_definition['configuration'][vm]['interfaces'][intf]:
118+
dut_index = topo_definition['configuration'][vm]['interfaces'][intf]['dut_index']
119+
if 'lacp' in topo_definition['configuration'][vm]['interfaces'][intf]:
120+
po_map[topo_definition['configuration'][vm]['interfaces'][intf]['lacp']] = dut_index
121+
vmconfig[vm]['intfs'][dut_index].append(intf)
120122

121123
# ip interface
122124
vmconfig[vm]['ip_intf'] = [None] * dut_num
123125
vmconfig[vm]['peer_ipv4'] = [None] * dut_num
124126
vmconfig[vm]['ipv4mask'] = [None] * dut_num
125127
vmconfig[vm]['peer_ipv6'] = [None] * dut_num
126128
vmconfig[vm]['ipv6mask'] = [None] * dut_num
127-
128-
129-
for intf in topo_definition['configuration'][vm]['interfaces']:
130-
dut_index = 0
131-
if (neigh_type == 'VMs' and 'Ethernet' in intf) or \
132-
(neigh_type == 'NEIGH_ASIC' and re.match("Eth(\d+)-", intf)):
133-
if 'dut_index' in topo_definition['configuration'][vm]['interfaces'][intf]:
134-
dut_index = topo_definition['configuration'][vm]['interfaces'][intf]['dut_index']
135-
elif 'Port-Channel' in intf:
136-
m = re.search("(\d+)", intf)
137-
dut_index = po_map[int(m.group(1))]
138-
139-
if 'ipv4' in topo_definition['configuration'][vm]['interfaces'][intf] and ('loopback' not in intf.lower()):
140-
(peer_ipv4, ipv4_mask) = topo_definition['configuration'][vm]['interfaces'][intf]['ipv4'].split('/')
141-
vmconfig[vm]['peer_ipv4'][dut_index] = peer_ipv4
142-
vmconfig[vm]['ipv4mask'][dut_index] = ipv4_mask
143-
vmconfig[vm]['ip_intf'][dut_index] = intf
144-
if 'ipv6' in topo_definition['configuration'][vm]['interfaces'][intf] and ('loopback' not in intf.lower()):
145-
(ipv6_addr, ipv6_mask) = topo_definition['configuration'][vm]['interfaces'][intf]['ipv6'].split('/')
146-
vmconfig[vm]['peer_ipv6'][dut_index] = ipv6_addr.upper()
147-
vmconfig[vm]['ipv6mask'][dut_index] = ipv6_mask
148-
vmconfig[vm]['ip_intf'][dut_index] = intf
149-
150-
# bgp
151129
vmconfig[vm]['bgp_ipv4'] = [None] * dut_num
152130
vmconfig[vm]['bgp_ipv6'] = [None] * dut_num
153-
vmconfig[vm]['bgp_asn'] = topo_definition['configuration'][vm]['bgp']['asn']
154-
for ipstr in topo_definition['configuration'][vm]['bgp']['peers'][dut_asn]:
155-
if sys.version_info < (3, 0):
156-
ip = ipaddress.ip_address(ipstr.decode('utf8'))
157-
else:
158-
ip = ipaddress.ip_address(ipstr)
159-
for dut_index in range(0, dut_num):
160-
if ip.version == 4:
161-
# Each VM might not be connected to all the DUT's, so check if this VM is a peer to DUT at dut_index
162-
if vmconfig[vm]['peer_ipv4'][dut_index]:
163-
ipsubnet_str = vmconfig[vm]['peer_ipv4'][dut_index]+'/'+vmconfig[vm]['ipv4mask'][dut_index]
164-
if sys.version_info < (3, 0):
165-
ipsubnet = ipaddress.ip_interface(ipsubnet_str.decode('utf8'))
166-
else:
167-
ipsubnet = ipaddress.ip_interface(ipsubnet_str)
168-
if ip in ipsubnet.network:
131+
vmconfig[vm]['bgp_asn'] = None
132+
133+
134+
if 'configuration' in topo_definition:
135+
if 'interfaces' in topo_definition['configuration'][vm]:
136+
for intf in topo_definition['configuration'][vm]['interfaces']:
137+
dut_index = 0
138+
if neigh_type == 'NEIGH_ASIC':
139+
pass
140+
elif 'Ethernet' in intf:
141+
if 'dut_index' in topo_definition['configuration'][vm]['interfaces'][intf]:
142+
dut_index = topo_definition['configuration'][vm]['interfaces'][intf]['dut_index']
143+
elif 'Port-Channel' in intf:
144+
m = re.search("(\d+)", intf)
145+
dut_index = po_map[int(m.group(1))]
146+
147+
if isinstance(topo_definition['configuration'][vm]['interfaces'],dict) and 'ipv4' in topo_definition['configuration'][vm]['interfaces'][intf] and ('loopback' not in intf.lower()):
148+
(peer_ipv4, ipv4_mask) = topo_definition['configuration'][vm]['interfaces'][intf]['ipv4'].split('/')
149+
vmconfig[vm]['peer_ipv4'][dut_index] = peer_ipv4
150+
vmconfig[vm]['ipv4mask'][dut_index] = ipv4_mask
151+
vmconfig[vm]['ip_intf'][dut_index] = intf
152+
if isinstance(topo_definition['configuration'][vm]['interfaces'],dict) and 'ipv6' in topo_definition['configuration'][vm]['interfaces'][intf] and ('loopback' not in intf.lower()):
153+
(ipv6_addr, ipv6_mask) = topo_definition['configuration'][vm]['interfaces'][intf]['ipv6'].split('/')
154+
vmconfig[vm]['peer_ipv6'][dut_index] = ipv6_addr.upper()
155+
vmconfig[vm]['ipv6mask'][dut_index] = ipv6_mask
156+
vmconfig[vm]['ip_intf'][dut_index] = intf
157+
# bgp
158+
vmconfig[vm]['bgp_asn'] = topo_definition['configuration'][vm]['bgp']['asn']
159+
dut_asn = topo_definition['configuration_properties']['common']['dut_asn']
160+
for ipstr in topo_definition['configuration'][vm]['bgp']['peers'][dut_asn]:
161+
ip_mask = None
162+
if '/' in ipstr:
163+
(ipstr, ip_mask) = ipstr.split('/')
164+
if sys.version_info < (3, 0):
165+
ip = ipaddress.ip_address(ipstr.decode('utf8'))
166+
else:
167+
ip = ipaddress.ip_address(ipstr)
168+
for dut_index in range(0, dut_num):
169+
if ip.version == 4:
170+
# Each VM might not be connected to all the DUT's, so check if this VM is a peer to DUT at dut_index
171+
if vmconfig[vm]['peer_ipv4'][dut_index]:
172+
ipsubnet_str = vmconfig[vm]['peer_ipv4'][dut_index]+'/'+vmconfig[vm]['ipv4mask'][dut_index]
173+
if sys.version_info < (3, 0):
174+
ipsubnet = ipaddress.ip_interface(ipsubnet_str.decode('utf8'))
175+
else:
176+
ipsubnet = ipaddress.ip_interface(ipsubnet_str)
177+
if ip in ipsubnet.network:
178+
vmconfig[vm]['bgp_ipv4'][dut_index] = ipstr.upper()
179+
elif neigh_type == "NEIGH_ASIC":
169180
vmconfig[vm]['bgp_ipv4'][dut_index] = ipstr.upper()
170-
elif ip.version == 6:
171-
# Each VM might not be connected to all the DUT's, so check if this VM is a peer to DUT at dut_index
172-
if vmconfig[vm]['peer_ipv6'][dut_index]:
173-
ipsubnet_str = vmconfig[vm]['peer_ipv6'][dut_index]+'/'+vmconfig[vm]['ipv6mask'][dut_index]
174-
if sys.version_info < (3, 0):
175-
ipsubnet = ipaddress.ip_interface(ipsubnet_str.decode('utf8'))
176-
else:
177-
ipsubnet = ipaddress.ip_interface(ipsubnet_str)
178-
if ip in ipsubnet.network:
181+
vmconfig[vm]['ipv4mask'][dut_index] = ip_mask if ip_mask else '32'
182+
elif ip.version == 6:
183+
# Each VM might not be connected to all the DUT's, so check if this VM is a peer to DUT at dut_index
184+
if vmconfig[vm]['peer_ipv6'][dut_index]:
185+
ipsubnet_str = vmconfig[vm]['peer_ipv6'][dut_index]+'/'+vmconfig[vm]['ipv6mask'][dut_index]
186+
if sys.version_info < (3, 0):
187+
ipsubnet = ipaddress.ip_interface(ipsubnet_str.decode('utf8'))
188+
else:
189+
ipsubnet = ipaddress.ip_interface(ipsubnet_str)
190+
if ip in ipsubnet.network:
191+
vmconfig[vm]['bgp_ipv6'][dut_index] = ipstr.upper()
192+
elif neigh_type == "NEIGH_ASIC":
179193
vmconfig[vm]['bgp_ipv6'][dut_index] = ipstr.upper()
194+
vmconfig[vm]['ipv6mask'][dut_index] = ip_mask if ip_mask else '128'
180195
return vmconfig
181196

182197
def get_topo_config(self, topo_name, hwsku):
@@ -201,10 +216,10 @@ def get_topo_config(self, topo_name, hwsku):
201216
topo_definition = yaml.load(f)
202217

203218
if not os.path.isfile(asic_topo_filename):
204-
asic_definition = {}
219+
slot_definition = {}
205220
else:
206221
with open(asic_topo_filename) as f:
207-
asic_definition = yaml.load(f)
222+
slot_definition = yaml.load(f)
208223

209224
### parse topo file specified in vars/ to reverse as dut config
210225
dut_num = 1
@@ -225,17 +240,13 @@ def get_topo_config(self, topo_name, hwsku):
225240
vm_topo_config['dut_type'] = topo_definition['configuration_properties']['common']['dut_type']
226241
vm_topo_config['dut_asn'] = dut_asn
227242

228-
229-
for asic in asic_definition:
230-
po_map_asic = [None] * 16 # maximum 16 port channel interfaces
231-
asic_topo_config[asic] = dict()
232-
asic_topo_config[asic]['dut_asn'] = asic_definition[asic]['configuration_properties']['common']['dut_asn']
233-
asic_topo_config[asic]['asic_type'] = asic_definition[asic]['configuration_properties']['common']['asic_type']
234-
asic_topo_config[asic]['Loopback4096'] = []
235-
for lo4096 in asic_definition[asic]['configuration_properties']['common']['Loopback4096']:
236-
asic_topo_config[asic]['Loopback4096'].append(lo4096)
237-
238-
asic_topo_config[asic]['neigh_asic'] = self.parse_topo_defintion(asic_definition[asic], po_map_asic, 1, 'NEIGH_ASIC')
243+
for slot,asic_definition in slot_definition.items():
244+
asic_topo_config[slot] = dict()
245+
for asic in asic_definition:
246+
po_map_asic = [None] * 16 # maximum 16 port channel interfaces
247+
asic_topo_config[slot][asic] = dict()
248+
asic_topo_config[slot][asic]['asic_type'] = asic_definition[asic]['configuration_properties']['common']['asic_type']
249+
asic_topo_config[slot][asic]['neigh_asic'] = self.parse_topo_defintion(asic_definition[asic], po_map_asic, 1, 'NEIGH_ASIC')
239250

240251
vm_topo_config['host_interfaces_by_dut'] = [[] for i in range(dut_num)]
241252
if 'host_interfaces' in topo_definition['topology']:

0 commit comments

Comments
 (0)