Skip to content

Commit

Permalink
Changes for Generation LC-Graph for packet-based chassis.
Browse files Browse the repository at this point in the history
Signed-off-by: Abhishek Dosi <abdosi@microsoft.com>
  • Loading branch information
abdosi committed Oct 9, 2021
1 parent 1768db3 commit 0e13fa3
Show file tree
Hide file tree
Showing 14 changed files with 549 additions and 171 deletions.
16 changes: 12 additions & 4 deletions ansible/config_sonic_basedon_testbed.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@
num_asic: "{{ num_asics }}"
card_type: "{{ card_type | default('fixed') }}"
hostname: "{{ inventory_hostname | default('') }}"
switchids: "{{ switchids | default([0]) }}"
switchids: "{{ switchids | default(None) }}"
slotid: "{{ slot_num | default(None) }}"
delegate_to: localhost
when: deploy is not defined or deploy|bool == false

Expand All @@ -101,17 +102,24 @@
num_fabric_asic: "{{ num_fabric_asics | default(0) }}"
asics_host_basepfx: "{{ asics_host_ip | default(None) }}"
asics_host_basepfx6: "{{ asics_host_ipv6 | default(None) }}"
delegate_to: localhost

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

- name: set all VoQ information for iBGP
- name: set all Loopback4096 information for iBGP chassis
set_fact:
all_loopback4096: "{{ all_loopback4096 | default( {} ) | combine( { item : hostvars[item]['loopback4096_ip']}) }}"
when: hostvars[item]['loopback4096_ip'] is defined
loop: "{{ ansible_play_batch }}"

- name: set all slot information for chassis
set_fact:
all_inbands: "{{ all_inbands | default( {} ) | combine( { item : hostvars[item]['voq_inband_ip']}) }}"
when: hostvars[item]['voq_inband_ip'] is defined
all_slots: "{{ all_slots | default( {} ) | combine( { item : hostvars[item]['slot_num']}) }}"
when: hostvars[item]['slot_num'] is defined
loop: "{{ ansible_play_batch }}"

- name: find all enabled host_interfaces
Expand Down
53 changes: 53 additions & 0 deletions ansible/lab
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ all:
sonic_a7260:
sonic_multi_asic:
sonic_multi_asic_2:
sonic_sup:
sonic_lc_100G:
fanout:
hosts:
str-7260-10:
Expand Down Expand Up @@ -148,3 +150,54 @@ sonic_multi_asic_2:
vlab-08:
ansible_host: 10.250.0.112
ansible_hostv6: fec0::ffff:afa:c

sonic_sup:
vars:
HwSku: 8800-RP-O
sonic_hwsku: 8800-RP-O
sonic_hw_platform: x86_64-8800_rp_o-r0
slot_num: slot0
card_type: supervisor
hosts:
lab-8800-sup-1:
ansible_host: 10.3.147.95
hwsku: 8800-RP-O
num_asics: 2


sonic_lc_100G:
vars:
switch_type: chassis-packet
num_asics: 2
frontend_asics: [0,1]
hosts:
lab-8808-lc0-1:
hwsku: 8800-LC-48H-O
sonic_hwsku: 8800-LC-48H-O
sonic_hw_platform: x86_64-8800_lc_48h_o-r0
slot_num: slot1
loopback4096_ip: [3.3.3.3/32,3.3.3.4/32]
loopback4096_ipv6: [2603:10e2:400::3/128,2603:10e2:400::4/128]
serial: SSN20220006
base_mac: fc:bd:67:67:e4:1C
ansible_host: 10.3.147.96
lab-8808-lc1-1:
hwsku: 8800-LC-48H-O
sonic_hwsku: 8800-LC-48H-O
sonic_hw_platform: x86_64-8800_lc_48h_o-r0
slot_num: slot2
loopback4096_ip: [3.3.3.5/32,3.3.3.6/32]
loopback4096_ipv6: [2603:10e2:400::5/128,2603:10e2:400::6/128]
serial: SSN20220006
base_mac: fc:bd:67:67:d9:30
ansible_host: 10.3.147.97
lab-8808-lc2-1:
hwsku: 8800-LC-48H-O
sonic_hwsku: 8800-LC-48H-O
sonic_hw_platform: x86_64-8800_lc_48h_o-r0
slot_num: slot3
loopback4096_ip: [3.3.3.7/32,3.3.3.8/32]
loopback4096_ipv6: [2603:10e2:400::7/128,2603:10e2:400::8/128]
serial: SSN20220011
base_mac: fc:bd:67:67:de:5b
ansible_host: 10.3.147.98
23 changes: 15 additions & 8 deletions ansible/library/port_alias.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,20 +78,22 @@ def get_platform_type(self):
return value
return None

def get_portconfig_path(self, asic_id=None):
def get_portconfig_path(self, slotid=None, asic_id=None):
platform = self.get_platform_type()
if platform is None:
return None
if asic_id is None:
portconfig = os.path.join(FILE_PATH, platform, self.hwsku, PORTMAP_FILE)
else:
elif slotid is None:
portconfig = os.path.join(FILE_PATH, platform, self.hwsku, str(asic_id), PORTMAP_FILE)
else:
portconfig = os.path.join(FILE_PATH, platform, self.hwsku, str(slotid), str(asic_id), PORTMAP_FILE)
if os.path.exists(portconfig):
return portconfig
return None

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

filename = self.get_portconfig_path(asic_id)
filename = self.get_portconfig_path(slotid, asic_id)
if filename is None:
raise Exception("Something wrong when trying to find the portmap file, either the hwsku is not available or file location is not correct")
with open(filename) as f:
Expand Down Expand Up @@ -209,7 +211,8 @@ def main():
include_internal=dict(required=False, type='bool', default=False),
card_type=dict(type='str', required=False),
hostname=dict(type='str', required=False),
switchids=dict(type='list', required=False)
switchids=dict(type='list', required=False),
slotid=dict(type='str', required=False)
),
supports_check_mode=True
)
Expand All @@ -236,8 +239,12 @@ def main():
return
allmap = SonicPortAliasMap(m_args['hwsku'])
switchids = None
if 'switchids' in m_args and m_args['switchids'] != None:
slotid = None
if 'switchids' in m_args and m_args['switchids']:
switchids = m_args['switchids']

if 'slotid' in m_args and m_args['slotid'] != None:
slotid = m_args['slotid']
# When this script is invoked on sonic-mgmt docker, num_asic
# parameter is passed.
if m_args['num_asic'] is not None:
Expand All @@ -264,12 +271,12 @@ def main():
if 'hostname' in m_args:
hostname = m_args['hostname']
for asic_id in range(num_asic):
if switchids and asic_id is not None:
if asic_id is not None and asic_id < len(switchids) and switchids[asic_id]:
switchid = switchids[asic_id]
if num_asic == 1:
asic_id = None
(aliases_asic, portmap_asic, aliasmap_asic, portspeed_asic, front_panel_asic, asicifnames_asic,
sysport_asic) = allmap.get_portmap(asic_id, include_internal, hostname, switchid)
sysport_asic) = allmap.get_portmap(asic_id, include_internal, hostname, switchid, slotid)
if aliases_asic is not None:
aliases.extend(aliases_asic)
if portmap_asic is not None:
Expand Down
157 changes: 84 additions & 73 deletions ansible/library/topo_facts.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ def __init__(self):
self.asic_topo_config = {}

def parse_topo_defintion(self, topo_definition, po_map, dut_num, neigh_type='VMs'):
dut_asn = topo_definition['configuration_properties']['common']['dut_asn']
vmconfig = dict()
for vm in topo_definition['topology'][neigh_type]:
vmconfig[vm] = dict()
Expand All @@ -106,77 +105,93 @@ def parse_topo_defintion(self, topo_definition, po_map, dut_num, neigh_type='VMs
for asic_intf in topo_definition['topology'][neigh_type][vm]['asic_intfs']:
vmconfig[vm]['asic_intfs'][dut_index].append(asic_intf)


# physical interface
for intf in topo_definition['configuration'][vm]['interfaces']:
if (neigh_type == 'VMs' and 'Ethernet' in intf) or \
(neigh_type == 'NEIGH_ASIC' and re.match("Eth(\d+)-", intf)):
dut_index = 0
if 'dut_index' in topo_definition['configuration'][vm]['interfaces'][intf]:
dut_index = topo_definition['configuration'][vm]['interfaces'][intf]['dut_index']
if 'lacp' in topo_definition['configuration'][vm]['interfaces'][intf]:
po_map[topo_definition['configuration'][vm]['interfaces'][intf]['lacp']] = dut_index

vmconfig[vm]['intfs'][dut_index].append(intf)
if 'configuration' in topo_definition:
if 'interfaces' in topo_definition['configuration'][vm]:
for intf in topo_definition['configuration'][vm]['interfaces']:
dut_index = 0
if neigh_type == 'NEIGH_ASIC':
vmconfig[vm]['intfs'][dut_index].append(intf)
elif 'Ethernet' in intf:
if 'dut_index' in topo_definition['configuration'][vm]['interfaces'][intf]:
dut_index = topo_definition['configuration'][vm]['interfaces'][intf]['dut_index']
if 'lacp' in topo_definition['configuration'][vm]['interfaces'][intf]:
po_map[topo_definition['configuration'][vm]['interfaces'][intf]['lacp']] = dut_index
vmconfig[vm]['intfs'][dut_index].append(intf)

# ip interface
vmconfig[vm]['ip_intf'] = [None] * dut_num
vmconfig[vm]['peer_ipv4'] = [None] * dut_num
vmconfig[vm]['ipv4mask'] = [None] * dut_num
vmconfig[vm]['peer_ipv6'] = [None] * dut_num
vmconfig[vm]['ipv6mask'] = [None] * dut_num


for intf in topo_definition['configuration'][vm]['interfaces']:
dut_index = 0
if (neigh_type == 'VMs' and 'Ethernet' in intf) or \
(neigh_type == 'NEIGH_ASIC' and re.match("Eth(\d+)-", intf)):
if 'dut_index' in topo_definition['configuration'][vm]['interfaces'][intf]:
dut_index = topo_definition['configuration'][vm]['interfaces'][intf]['dut_index']
elif 'Port-Channel' in intf:
m = re.search("(\d+)", intf)
dut_index = po_map[int(m.group(1))]

if 'ipv4' in topo_definition['configuration'][vm]['interfaces'][intf] and ('loopback' not in intf.lower()):
(peer_ipv4, ipv4_mask) = topo_definition['configuration'][vm]['interfaces'][intf]['ipv4'].split('/')
vmconfig[vm]['peer_ipv4'][dut_index] = peer_ipv4
vmconfig[vm]['ipv4mask'][dut_index] = ipv4_mask
vmconfig[vm]['ip_intf'][dut_index] = intf
if 'ipv6' in topo_definition['configuration'][vm]['interfaces'][intf] and ('loopback' not in intf.lower()):
(ipv6_addr, ipv6_mask) = topo_definition['configuration'][vm]['interfaces'][intf]['ipv6'].split('/')
vmconfig[vm]['peer_ipv6'][dut_index] = ipv6_addr.upper()
vmconfig[vm]['ipv6mask'][dut_index] = ipv6_mask
vmconfig[vm]['ip_intf'][dut_index] = intf

# bgp
vmconfig[vm]['bgp_ipv4'] = [None] * dut_num
vmconfig[vm]['bgp_ipv6'] = [None] * dut_num
vmconfig[vm]['bgp_asn'] = topo_definition['configuration'][vm]['bgp']['asn']
for ipstr in topo_definition['configuration'][vm]['bgp']['peers'][dut_asn]:
if sys.version_info < (3, 0):
ip = ipaddress.ip_address(ipstr.decode('utf8'))
else:
ip = ipaddress.ip_address(ipstr)
for dut_index in range(0, dut_num):
if ip.version == 4:
# Each VM might not be connected to all the DUT's, so check if this VM is a peer to DUT at dut_index
if vmconfig[vm]['peer_ipv4'][dut_index]:
ipsubnet_str = vmconfig[vm]['peer_ipv4'][dut_index]+'/'+vmconfig[vm]['ipv4mask'][dut_index]
if sys.version_info < (3, 0):
ipsubnet = ipaddress.ip_interface(ipsubnet_str.decode('utf8'))
else:
ipsubnet = ipaddress.ip_interface(ipsubnet_str)
if ip in ipsubnet.network:
vmconfig[vm]['bgp_asn'] = None


if 'configuration' in topo_definition:
if 'interfaces' in topo_definition['configuration'][vm]:
for intf in topo_definition['configuration'][vm]['interfaces']:
dut_index = 0
if neigh_type == 'NEIGH_ASIC':
pass
elif 'Ethernet' in intf:
if 'dut_index' in topo_definition['configuration'][vm]['interfaces'][intf]:
dut_index = topo_definition['configuration'][vm]['interfaces'][intf]['dut_index']
elif 'Port-Channel' in intf:
m = re.search("(\d+)", intf)
dut_index = po_map[int(m.group(1))]

if isinstance(topo_definition['configuration'][vm]['interfaces'],dict) and 'ipv4' in topo_definition['configuration'][vm]['interfaces'][intf] and ('loopback' not in intf.lower()):
(peer_ipv4, ipv4_mask) = topo_definition['configuration'][vm]['interfaces'][intf]['ipv4'].split('/')
vmconfig[vm]['peer_ipv4'][dut_index] = peer_ipv4
vmconfig[vm]['ipv4mask'][dut_index] = ipv4_mask
vmconfig[vm]['ip_intf'][dut_index] = intf
if isinstance(topo_definition['configuration'][vm]['interfaces'],dict) and 'ipv6' in topo_definition['configuration'][vm]['interfaces'][intf] and ('loopback' not in intf.lower()):
(ipv6_addr, ipv6_mask) = topo_definition['configuration'][vm]['interfaces'][intf]['ipv6'].split('/')
vmconfig[vm]['peer_ipv6'][dut_index] = ipv6_addr.upper()
vmconfig[vm]['ipv6mask'][dut_index] = ipv6_mask
vmconfig[vm]['ip_intf'][dut_index] = intf
# bgp
vmconfig[vm]['bgp_asn'] = topo_definition['configuration'][vm]['bgp']['asn']
dut_asn = topo_definition['configuration_properties']['common']['dut_asn']
for ipstr in topo_definition['configuration'][vm]['bgp']['peers'][dut_asn]:
ip_mask = None
if '/' in ipstr:
(ipstr, ip_mask) = ipstr.split('/')
if sys.version_info < (3, 0):
ip = ipaddress.ip_address(ipstr.decode('utf8'))
else:
ip = ipaddress.ip_address(ipstr)
for dut_index in range(0, dut_num):
if ip.version == 4:
# Each VM might not be connected to all the DUT's, so check if this VM is a peer to DUT at dut_index
if vmconfig[vm]['peer_ipv4'][dut_index]:
ipsubnet_str = vmconfig[vm]['peer_ipv4'][dut_index]+'/'+vmconfig[vm]['ipv4mask'][dut_index]
if sys.version_info < (3, 0):
ipsubnet = ipaddress.ip_interface(ipsubnet_str.decode('utf8'))
else:
ipsubnet = ipaddress.ip_interface(ipsubnet_str)
if ip in ipsubnet.network:
vmconfig[vm]['bgp_ipv4'][dut_index] = ipstr.upper()
elif neigh_type == "NEIGH_ASIC":
vmconfig[vm]['bgp_ipv4'][dut_index] = ipstr.upper()
elif ip.version == 6:
# Each VM might not be connected to all the DUT's, so check if this VM is a peer to DUT at dut_index
if vmconfig[vm]['peer_ipv6'][dut_index]:
ipsubnet_str = vmconfig[vm]['peer_ipv6'][dut_index]+'/'+vmconfig[vm]['ipv6mask'][dut_index]
if sys.version_info < (3, 0):
ipsubnet = ipaddress.ip_interface(ipsubnet_str.decode('utf8'))
else:
ipsubnet = ipaddress.ip_interface(ipsubnet_str)
if ip in ipsubnet.network:
vmconfig[vm]['ipv4mask'][dut_index] = ip_mask if ip_mask else '32'
elif ip.version == 6:
# Each VM might not be connected to all the DUT's, so check if this VM is a peer to DUT at dut_index
if vmconfig[vm]['peer_ipv6'][dut_index]:
ipsubnet_str = vmconfig[vm]['peer_ipv6'][dut_index]+'/'+vmconfig[vm]['ipv6mask'][dut_index]
if sys.version_info < (3, 0):
ipsubnet = ipaddress.ip_interface(ipsubnet_str.decode('utf8'))
else:
ipsubnet = ipaddress.ip_interface(ipsubnet_str)
if ip in ipsubnet.network:
vmconfig[vm]['bgp_ipv6'][dut_index] = ipstr.upper()
elif neigh_type == "NEIGH_ASIC":
vmconfig[vm]['bgp_ipv6'][dut_index] = ipstr.upper()
vmconfig[vm]['ipv6mask'][dut_index] = ip_mask if ip_mask else '128'
return vmconfig

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

if not os.path.isfile(asic_topo_filename):
asic_definition = {}
slot_definition = {}
else:
with open(asic_topo_filename) as f:
asic_definition = yaml.load(f)
slot_definition = yaml.load(f)

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


for asic in asic_definition:
po_map_asic = [None] * 16 # maximum 16 port channel interfaces
asic_topo_config[asic] = dict()
asic_topo_config[asic]['dut_asn'] = asic_definition[asic]['configuration_properties']['common']['dut_asn']
asic_topo_config[asic]['asic_type'] = asic_definition[asic]['configuration_properties']['common']['asic_type']
asic_topo_config[asic]['Loopback4096'] = []
for lo4096 in asic_definition[asic]['configuration_properties']['common']['Loopback4096']:
asic_topo_config[asic]['Loopback4096'].append(lo4096)

asic_topo_config[asic]['neigh_asic'] = self.parse_topo_defintion(asic_definition[asic], po_map_asic, 1, 'NEIGH_ASIC')
for slot,asic_definition in slot_definition.items():
asic_topo_config[slot] = dict()
for asic in asic_definition:
po_map_asic = [None] * 16 # maximum 16 port channel interfaces
asic_topo_config[slot][asic] = dict()
asic_topo_config[slot][asic]['asic_type'] = asic_definition[asic]['configuration_properties']['common']['asic_type']
asic_topo_config[slot][asic]['neigh_asic'] = self.parse_topo_defintion(asic_definition[asic], po_map_asic, 1, 'NEIGH_ASIC')

vm_topo_config['host_interfaces_by_dut'] = [[] for i in range(dut_num)]
if 'host_interfaces' in topo_definition['topology']:
Expand Down
Loading

0 comments on commit 0e13fa3

Please sign in to comment.