Skip to content

Commit

Permalink
[SmartSwitch] Extend implementation of the DPU chassis daemon. (#563)
Browse files Browse the repository at this point in the history
  • Loading branch information
oleksandrivantsiv authored Nov 20, 2024
1 parent e772183 commit b276e41
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 2 deletions.
55 changes: 54 additions & 1 deletion sonic-chassisd/scripts/chassisd
Original file line number Diff line number Diff line change
Expand Up @@ -791,21 +791,74 @@ class ChassisdDaemon(daemon_base.DaemonBase):
self.log_info("Shutting down...")


class DpuStateManagerTask(ProcessTaskBase):

def __init__(self, log_identifier, dpu_state_updater):
super(DpuStateManagerTask, self).__init__()

self.logger = logger.Logger(log_identifier)
self.dpu_state_updater = dpu_state_updater
self.state_db = daemon_base.db_connect('STATE_DB')
self.app_db = daemon_base.db_connect('APPL_DB')

def task_worker(self):
sel = swsscommon.Select()
selectable = [
swsscommon.SubscriberStateTable(self.app_db, 'PORT_TABLE'),
swsscommon.SubscriberStateTable(self.state_db, 'SYSTEM_READY')
]

for s in selectable:
sel.addSelectable(s)

try:
while True:
(state, c) = sel.select(SELECT_TIMEOUT)

if state == swsscommon.Select.TIMEOUT:
continue

if state != swsscommon.Select.OBJECT:
continue

for s in selectable:
s.pops()

self.dpu_state_updater.update_state()

except KeyboardInterrupt:
pass


class DpuChassisdDaemon(ChassisdDaemon):

def run(self):
self.log_info("Starting up...")

poll_dpu_state = True
if not try_get(self.platform_chassis.get_dataplane_state, default=None) and not \
try_get(self.platform_chassis.get_controlplane_state, default=None):
poll_dpu_state = False

dpu_updater = DpuStateUpdater(SYSLOG_IDENTIFIER, self.platform_chassis)
dpu_state_mng = None

if not poll_dpu_state:
dpu_state_mng = DpuStateManagerTask(SYSLOG_IDENTIFIER, dpu_updater)
dpu_state_mng.task_run()

# Start main loop
self.log_info("Start daemon main loop")

while not self.stop.wait(CHASSIS_INFO_UPDATE_PERIOD_SECS):
dpu_updater.update_state()
if poll_dpu_state:
dpu_updater.update_state()

self.log_info("Stop daemon main loop")

if dpu_state_mng:
dpu_state_mng.task_stop()

dpu_updater.deinit()

self.log_info("Shutting down...")
Expand Down
8 changes: 7 additions & 1 deletion sonic-chassisd/tests/mock_swsscommon.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def __init__(self, fvs):
pass

class Select:
OBJECT = 0
TIMEOUT = 1

def addSelectable(self, selectable):
Expand All @@ -66,7 +67,12 @@ def select(self, timeout=-1, interrupt_on_signal=False):
return self.TIMEOUT, None

class SubscriberStateTable(Table):
pass

def pop(self):
return None

def pops(self):
return None

class RedisPipeline:
def __init__(self, db):
Expand Down
46 changes: 46 additions & 0 deletions sonic-chassisd/tests/test_dpu_chassisd.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,52 @@ def hset(key, field, value):
'dpu_control_plane_state': 'down', 'dpu_control_plane_time': '2000-01-01 00:00:00'}}


@pytest.mark.parametrize('dpu_id, dp_state, cp_state, expected_state', [
(0, False, False, {'DPU0':
{'dpu_data_plane_state': 'down', 'dpu_data_plane_time': '2000-01-01 00:00:00',
'dpu_control_plane_state': 'down', 'dpu_control_plane_time': '2000-01-01 00:00:00'}}),
(0, False, True, {'DPU0':
{'dpu_data_plane_state': 'down', 'dpu_data_plane_time': '2000-01-01 00:00:00',
'dpu_control_plane_state': 'up', 'dpu_control_plane_time': '2000-01-01 00:00:00'}}),
(0, True, True, {'DPU0':
{'dpu_data_plane_state': 'up', 'dpu_data_plane_time': '2000-01-01 00:00:00',
'dpu_control_plane_state': 'up', 'dpu_control_plane_time': '2000-01-01 00:00:00'}}),
])
def test_dpu_state_manager(dpu_id, dp_state, cp_state, expected_state):
chassis = MockDpuChassis()

chassis.get_dpu_id = MagicMock(return_value=dpu_id)
chassis.get_dataplane_state = MagicMock(return_value=dp_state)
chassis.get_controlplane_state = MagicMock(return_value=cp_state)

chassis_state_db = {}

def hset(key, field, value):
print(key, field, value)
if key not in chassis_state_db:
chassis_state_db[key] = {}

chassis_state_db[key][field] = value

with mock.patch.object(swsscommon.Table, 'hset', side_effect=hset):
with mock.patch.object(swsscommon.Select, 'select', side_effect=((swsscommon.Select.OBJECT, None), (swsscommon.Select.OBJECT, None), KeyboardInterrupt)):
dpu_updater = DpuStateUpdater(SYSLOG_IDENTIFIER, chassis)
dpu_updater._time_now = MagicMock(return_value='2000-01-01 00:00:00')

dpu_state_mng = DpuStateManagerTask(SYSLOG_IDENTIFIER, dpu_updater)

dpu_state_mng.task_worker()

assert chassis_state_db == expected_state

dpu_updater.deinit()

# After the deinit we assume that the DPU state is down.
assert chassis_state_db == {'DPU0':
{'dpu_data_plane_state': 'down', 'dpu_data_plane_time': '2000-01-01 00:00:00',
'dpu_control_plane_state': 'down', 'dpu_control_plane_time': '2000-01-01 00:00:00'}}


def test_dpu_chassis_daemon():
# Test the chassisd run
chassis = MockDpuChassis()
Expand Down

0 comments on commit b276e41

Please sign in to comment.