From 9ef5cfdbd5923c8c2c895b2871e4e3c3cbc8e8b3 Mon Sep 17 00:00:00 2001 From: Sonic Build Admin Date: Wed, 3 Dec 2025 21:18:11 +0000 Subject: [PATCH] Add cache for local chassis table Previously Every sync cycle (every 10 seconds by default) would unconditionally: Delete the LLDP_LOC_CHASSIS table from Redis Write all chassis attributes back to Redis for the LLDP_LOC_CHASSIS table, This leads to race conditions, since there is a possibility to perform an snmp query at the same time leading to missing data: `2025 Oct 19 00:41:14.530572 sonic WARNING snmp#snmp-subagent [sonic_ax_impl] WARNING: Missing lldp_loc_man_addr from APPL DB` The change which is done compares new chassis data with the cached version Only performs DB operations (delete + set) if data has actually changed Skips all DB writes when chassis data is unchanged Unit test: ``` tests/test_lldpSyncDaemon.py::TestLldpSyncDaemon::test_chassis_cache_no_db_calls_when_unchanged PASSED [ 21%] ``` **Required for 202505 branch** --- src/lldp_syncd/daemon.py | 1 + tests/test_lldpSyncDaemon.py | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/lldp_syncd/daemon.py b/src/lldp_syncd/daemon.py index dd172f7..e949ad1 100644 --- a/src/lldp_syncd/daemon.py +++ b/src/lldp_syncd/daemon.py @@ -386,6 +386,7 @@ def sync(self, parsed_update): for k, v in chassis_update.items(): self.db_connector.set(self.db_connector.APPL_DB, LldpSyncDaemon.LLDP_LOC_CHASSIS_TABLE, k, v, blocking=True) + self.chassis_cache = chassis_update logger.debug("sync'd: {}".format(json.dumps(chassis_update, indent=3))) new, changed, deleted = self.cache_diff(self.interfaces_cache, parsed_update) diff --git a/tests/test_lldpSyncDaemon.py b/tests/test_lldpSyncDaemon.py index dec48ec..8dd0df7 100644 --- a/tests/test_lldpSyncDaemon.py +++ b/tests/test_lldpSyncDaemon.py @@ -271,3 +271,30 @@ def test_changed_interface(self): self.assertEqual(jo[k], 'Ethernet1') else: jo[k] = db.get_all(db.APPL_DB, k) + + def test_chassis_cache_no_db_calls_when_unchanged(self): + """ + Test that database operations are not called when chassis data hasn't changed. + """ + # First sync to populate chassis_cache + parsed_update = self.daemon.parse_update(self._json) + self.daemon.sync(parsed_update) + initial_cache = self.daemon.chassis_cache.copy() + + # Sync again with same data - DB operations should NOT be called + parsed_update_same = self.daemon.parse_update(self._json) + + with mock.patch.object(self.daemon.db_connector, 'delete') as mock_delete, \ + mock.patch.object(self.daemon.db_connector, 'set') as mock_set: + + self.daemon.sync(parsed_update_same) + + # Verify chassis DB operations were NOT called + chassis_deletes = [c for c in mock_delete.call_args_list + if len(c[0]) > 1 and c[0][1] == 'LLDP_LOC_CHASSIS'] + chassis_sets = [c for c in mock_set.call_args_list + if len(c[0]) > 1 and c[0][1] == 'LLDP_LOC_CHASSIS'] + + self.assertEqual(len(chassis_deletes), 0) + self.assertEqual(len(chassis_sets), 0) + self.assertEqual(self.daemon.chassis_cache, initial_cache)