Skip to content

Commit

Permalink
Collect asic info and store in CHASSIS_STATE_DB (#175)
Browse files Browse the repository at this point in the history
Chassisd inside pmon queries asic information from platform modules and stores it into CHASSIS_STATE_DB of redis_chassis.

The reason we keep information in CHASSIS_STATE_DB because it's accessible by swss containers.

Asic information includes asic pci address, module name, and asic id in the module. For example, CHASSIS_STATE_DB will look like below:

127.0.0.1:6379[6]> HGETALL "CHASSIS_ASIC_TABLE|ASIC0"
1) "asic_pci_address"
2) "0000:09:00.0"
3) "module_name"
4) "FABRIC-CARD0"
5) "asic_id_in_module"
6) "0"
  • Loading branch information
ngoc-do authored Jun 23, 2021
1 parent 53639de commit b2c6102
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 3 deletions.
42 changes: 41 additions & 1 deletion sonic-chassisd/scripts/chassisd
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ CHASSIS_MODULE_INFO_NAME_FIELD = 'name'
CHASSIS_MODULE_INFO_DESC_FIELD = 'desc'
CHASSIS_MODULE_INFO_SLOT_FIELD = 'slot'
CHASSIS_MODULE_INFO_OPERSTATUS_FIELD = 'oper_status'
CHASSIS_MODULE_INFO_NUM_ASICS_FIELD = 'num_asics'
CHASSIS_MODULE_INFO_ASICS = 'asics'

CHASSIS_ASIC_INFO_TABLE = 'CHASSIS_ASIC_TABLE'
CHASSIS_ASIC = 'asic'
CHASSIS_ASIC_PCI_ADDRESS_FIELD = 'asic_pci_address'
CHASSIS_ASIC_ID_IN_MODULE_FIELD = 'asic_id_in_module'

CHASSIS_MIDPLANE_INFO_TABLE = 'CHASSIS_MIDPLANE_TABLE'
CHASSIS_MIDPLANE_INFO_KEY_TEMPLATE = 'CHASSIS_MIDPLANE {}'
Expand Down Expand Up @@ -163,6 +170,9 @@ class ModuleUpdater(logger.Logger):
CHASSIS_MODULE_INFO_SLOT_FIELD,
CHASSIS_MODULE_INFO_OPERSTATUS_FIELD]

chassis_state_db = daemon_base.db_connect("CHASSIS_STATE_DB")
self.asic_table = swsscommon.Table(chassis_state_db, CHASSIS_ASIC_INFO_TABLE)

self.midplane_initialized = try_get(chassis.init_midplane_switch, default=False)
if not self.midplane_initialized:
self.log_error("Chassisd midplane intialization failed")
Expand All @@ -182,6 +192,11 @@ class ModuleUpdater(logger.Logger):
if self.chassis_table is not None:
self.chassis_table._del(CHASSIS_INFO_KEY_TEMPLATE.format(1))

if self.asic_table is not None:
asics = list(self.asic_table.getKeys())
for asic in asics:
self.asic_table._del(asic)

def modules_num_update(self):
# Check if module list is populated
num_modules = self.chassis.get_num_modules()
Expand All @@ -194,6 +209,8 @@ class ModuleUpdater(logger.Logger):
self.chassis_table.set(CHASSIS_INFO_KEY_TEMPLATE.format(1), fvs)

def module_db_update(self):
notOnlineModules = []

for module_index in range(0, self.num_modules):
module_info_dict = self._get_module_info(module_index)
if module_info_dict is not None:
Expand All @@ -211,9 +228,29 @@ class ModuleUpdater(logger.Logger):
fvs = swsscommon.FieldValuePairs([(CHASSIS_MODULE_INFO_DESC_FIELD, module_info_dict[CHASSIS_MODULE_INFO_DESC_FIELD]),
(CHASSIS_MODULE_INFO_SLOT_FIELD,
module_info_dict[CHASSIS_MODULE_INFO_SLOT_FIELD]),
(CHASSIS_MODULE_INFO_OPERSTATUS_FIELD, module_info_dict[CHASSIS_MODULE_INFO_OPERSTATUS_FIELD])])
(CHASSIS_MODULE_INFO_OPERSTATUS_FIELD, module_info_dict[CHASSIS_MODULE_INFO_OPERSTATUS_FIELD]),
(CHASSIS_MODULE_INFO_NUM_ASICS_FIELD, str(len(module_info_dict[CHASSIS_MODULE_INFO_ASICS])))])
self.module_table.set(key, fvs)

if module_info_dict[CHASSIS_MODULE_INFO_OPERSTATUS_FIELD] != str(ModuleBase.MODULE_STATUS_ONLINE):
notOnlineModules.append(key)
continue

for asic_id, asic in enumerate(module_info_dict[CHASSIS_MODULE_INFO_ASICS]):
asic_global_id, asic_pci_addr = asic
asic_key = "%s%s" % (CHASSIS_ASIC, asic_global_id)
asic_fvs = swsscommon.FieldValuePairs([(CHASSIS_ASIC_PCI_ADDRESS_FIELD, asic_pci_addr),
(CHASSIS_MODULE_INFO_NAME_FIELD, key),
(CHASSIS_ASIC_ID_IN_MODULE_FIELD, str(asic_id))])
self.asic_table.set(asic_key, asic_fvs)

# Asics that are on the "not online" modules need to be cleaned up
asics = list(self.asic_table.getKeys())
for asic in asics:
fvs = self.asic_table.get(asic)
if fvs[CHASSIS_MODULE_INFO_NAME_FIELD] in notOnlineModules:
self.asic_table._del(asic)

def _get_module_info(self, module_index):
"""
Retrieves module info of this module
Expand All @@ -225,11 +262,14 @@ class ModuleUpdater(logger.Logger):
slot = try_get(self.chassis.get_module(module_index).get_slot, default=INVALID_SLOT)
status = try_get(self.chassis.get_module(module_index).get_oper_status,
default=ModuleBase.MODULE_STATUS_OFFLINE)
asics = try_get(self.chassis.get_module(module_index).get_all_asics,
default=[])

module_info_dict[CHASSIS_MODULE_INFO_NAME_FIELD] = name
module_info_dict[CHASSIS_MODULE_INFO_DESC_FIELD] = str(desc)
module_info_dict[CHASSIS_MODULE_INFO_SLOT_FIELD] = str(slot)
module_info_dict[CHASSIS_MODULE_INFO_OPERSTATUS_FIELD] = str(status)
module_info_dict[CHASSIS_MODULE_INFO_ASICS] = asics

return module_info_dict

Expand Down
9 changes: 7 additions & 2 deletions sonic-chassisd/tests/mock_platform.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ def get_serial(self):


class MockModule(MockDevice):
def __init__(self, module_index, module_name, module_desc, module_type, module_slot):
def __init__(self, module_index, module_name, module_desc, module_type, module_slot,
asic_list=[]):
self.module_index = module_index
self.module_name = module_name
self.module_desc = module_desc
Expand All @@ -29,7 +30,8 @@ def __init__(self, module_index, module_name, module_desc, module_type, module_s
self.admin_state = 1
self.supervisor_slot = 16
self.midplane_access = False

self.asic_list = asic_list

def get_name(self):
return self.module_name

Expand Down Expand Up @@ -69,6 +71,9 @@ def is_midplane_reachable(self):
def set_midplane_reachable(self, up):
self.midplane_access = up

def get_all_asics(self):
return self.asic_list

class MockChassis:
def __init__(self):
self.module_list = []
Expand Down
3 changes: 3 additions & 0 deletions sonic-chassisd/tests/mock_swsscommon.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ def get(self, key):
return self.mock_dict[key]
return None

def getKeys(self):
return list(self.mock_dict)

def size(self):
return len(self.mock_dict)

Expand Down
75 changes: 75 additions & 0 deletions sonic-chassisd/tests/test_chassisd.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
CHASSIS_INFO_KEY_TEMPLATE = 'CHASSIS {}'
CHASSIS_INFO_CARD_NUM_FIELD = 'module_num'

CHASSIS_ASIC_PCI_ADDRESS_FIELD = 'asic_pci_address'
CHASSIS_ASIC_ID_IN_MODULE_FIELD = 'asic_id_in_module'

def setup_function():
ModuleUpdater.log_notice = MagicMock()
Expand Down Expand Up @@ -366,3 +368,76 @@ def test_midplane_presence_supervisor():
module_updater.deinit()
fvs = midplane_table.get(name)
assert fvs == None

def test_asic_presence():
chassis = MockChassis()

#Supervisor
index = 0
name = "SUPERVISOR0"
desc = "Supervisor card"
slot = 16
module_type = ModuleBase.MODULE_TYPE_SUPERVISOR
supervisor = MockModule(index, name, desc, module_type, slot)
supervisor.set_midplane_ip()
chassis.module_list.append(supervisor)

#Linecard
index = 1
name = "LINE-CARD0"
desc = "36 port 400G card"
slot = 1
module_type = ModuleBase.MODULE_TYPE_LINE
module = MockModule(index, name, desc, module_type, slot)
module.set_midplane_ip()
chassis.module_list.append(module)

#Fabric-card with asics
index = 1
name = "FABRIC-CARD0"
desc = "Switch fabric card"
slot = 17
module_type = ModuleBase.MODULE_TYPE_FABRIC
fabric_asic_list = [("4", "0000:04:00.0"), ("5", "0000:05:00.0")]
fabric = MockModule(index, name, desc, module_type, slot, fabric_asic_list)
chassis.module_list.append(fabric)

#Run on supervisor
module_updater = ModuleUpdater(SYSLOG_IDENTIFIER, chassis)
module_updater.supervisor_slot = supervisor.get_slot()
module_updater.my_slot = supervisor.get_slot()
module_updater.modules_num_update()
module_updater.module_db_update()
module_updater.check_midplane_reachability()

#Asic presence on fabric module
fabric.set_oper_status(ModuleBase.MODULE_STATUS_ONLINE)
module_updater.module_db_update()
fabric_asic_table = module_updater.asic_table
assert len(fabric_asic_table.getKeys()) == 2

def verify_fabric_asic(asic_name, asic_pci_address, module_name, asic_id_in_module):
fvs = fabric_asic_table.get(asic_name)
assert fvs[CHASSIS_ASIC_PCI_ADDRESS_FIELD] == asic_pci_address
assert fvs[CHASSIS_MODULE_INFO_NAME_FIELD] == module_name
assert fvs[CHASSIS_ASIC_ID_IN_MODULE_FIELD] == asic_id_in_module

verify_fabric_asic("asic4", "0000:04:00.0", name, "0")
verify_fabric_asic("asic5", "0000:05:00.0", name, "1")

#Card goes down and asics should be gone
fabric.set_oper_status(ModuleBase.MODULE_STATUS_OFFLINE)
module_updater.module_db_update()
assert len(fabric_asic_table.getKeys()) == 0

#Deinit
fabric.set_oper_status(ModuleBase.MODULE_STATUS_ONLINE)
module_updater.module_db_update()
module_updater.deinit()
midplane_table = module_updater.midplane_table
fvs = midplane_table.get(name)
assert fvs == None
fvs = fabric_asic_table.get("asic4")
assert fvs == None
fvs = fabric_asic_table.get("asic5")
assert fvs == None

0 comments on commit b2c6102

Please sign in to comment.