From 661a4012df45994e9f0c92ce28ca4401ef97f2d0 Mon Sep 17 00:00:00 2001 From: mssonicbld <79238446+mssonicbld@users.noreply.github.com> Date: Tue, 16 Jun 2026 04:13:18 +1000 Subject: [PATCH 1/2] Fixes #4579: Fix pfc prio config errors (#4616) #### What I did if PFC is not enabled on a port, unable to configure PFC via CLI. it generates the error as shown in the ticket. #### How I did it SImilar to "show pfc prio", if there is no entry for "pfc_enable" under PORT_QOS_MAP for that part, just treat as empty and add the new PFC prio instead out erroring out. #### How to verify it ``` Before the fix: admin@humm223:~$ show pfc prio Interface Lossless priorities ----------- --------------------- Ethernet32 N/A Ethernet36 3,4 Ethernet40 3,4 Ethernet44 3,4 Ethernet160 3,4 Ethernet164 3,4 admin@humm223:~$ sudo config interface pfc priority Ethernet32 3 on Traceback (most recent call last): File "/usr/local/bin/pfc", line 8, in sys.exit(cli()) ~~~^^ File "/usr/lib/python3/dist-packages/click/core.py", line 1161, in __call__ return self.main(*args, **kwargs) ~~~~~~~~~^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/click/core.py", line 1082, in main rv = self.invoke(ctx) File "/usr/lib/python3/dist-packages/click/core.py", line 1697, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ File "/usr/lib/python3/dist-packages/click/core.py", line 1697, in invoke return _process_result(sub_ctx.command.invoke(sub_ctx)) ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^ File "/usr/lib/python3/dist-packages/click/core.py", line 1443, in invoke return ctx.invoke(self.callback, **ctx.params) ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/click/core.py", line 788, in invoke return __callback(*args, **kwargs) File "/usr/local/lib/python3.13/dist-packages/pfc/main.py", line 177, in configPrio Pfc(namespace).configPfcPrio(status, interface, priority) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.13/dist-packages/utilities_common/multi_asic.py", line 153, in wrapped_run_on_all_asics func(self, *args, **kwargs) ~~~~^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.13/dist-packages/pfc/main.py", line 87, in configPfcPrio enable_prio = entry.get('pfc_enable').split(',') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'NoneType' object has no attribute 'split' admin@humm223:~$ WITH THE FIX: admin@humm223:~$ sudo config interface pfc priority Ethernet32 3 on admin@humm223:~$ show pfc pri Interface Lossless priorities ----------- --------------------- Ethernet32 3 Ethernet36 3,4 Ethernet40 3,4 Ethernet44 3,4 Ethernet160 3,4 Ethernet164 3,4 admin@humm223:~$ ``` Signed-off-by: Sonic Build Admin #### Previous command output (if the output of a command-line utility has changed) #### New command output (if the output of a command-line utility has changed) --- pfc/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pfc/main.py b/pfc/main.py index f894a5d7c..626c26931 100644 --- a/pfc/main.py +++ b/pfc/main.py @@ -84,7 +84,7 @@ def configPfcPrio(self, status, interface, priority): """Current lossless priorities on the interface""" entry = self.config_db.get_entry('PORT_QOS_MAP', interface) - enable_prio = entry.get('pfc_enable').split(',') + enable_prio = entry.get('pfc_enable', '').split(',') """Avoid '' in enable_prio""" enable_prio = [x.strip() for x in enable_prio if x.strip()] From 431278d75c77332ec292a7ef65499640c5e0ba57 Mon Sep 17 00:00:00 2001 From: Hemanth Kumar Tirupati Date: Mon, 15 Jun 2026 14:41:47 -0700 Subject: [PATCH 2/2] [reload] stop timers on reload (#4021) (#4617) What I did I implemented a fix to stop timers upon reload/load_minigraph. If "config reload" or "config load_minigraph" is executed soon after system has started a timer may expire in the middle of the command causing subsequent failures. Here's what is observed: 2025 Aug 6 18:29:35.532425 sonic INFO python[36429]: ansible-command Invoked with _uses_shell=True _raw_params=config load_minigraph --override_config -y warn=True stdin_add_newline=True strip_empty_ends=True argv=None chdir=None execut able=None creates=None removes=None stdin=None 2025 Aug 6 18:29:35.754152 sonic NOTICE switch_trimming: 'load_minigraph' executing with command: config load_minigraph --override_config -y 2025 Aug 6 18:30:30.306602 sonic INFO systemd[1]: Stopped target sonic.target - SONiC services target.. 2025 Aug 6 18:30:31.333507 sonic DEBUG systemd[1]: tacacs-config.timer: Timer elapsed. 2025 Aug 6 18:30:31.334003 sonic DEBUG systemd[1]: sonic.target: Installed new job sonic.target/start as 2793 2025 Aug 6 18:30:32.371292 sonic DEBUG systemd[1]: sonic.target changed dead -> active How I did it Stop timers associated with sonic.target How to verify it I put a breakpoint after stopping sonic.target. Soon after reboot I execute "config reload" command. I then wait for ~5-6 min, no services start. Without this fix, services would start. Signed-off-by: Hemanth Kumar Tirupati Co-authored-by: Stepan Blyshchak <38952541+stepanblyschak@users.noreply.github.com> --- config/main.py | 6 ++++++ tests/config_test.py | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/config/main.py b/config/main.py index b6c500393..592b7284e 100644 --- a/config/main.py +++ b/config/main.py @@ -1008,6 +1008,12 @@ def _stop_services(): except subprocess.CalledProcessError as err: pass + # Get the list of dependencies for sonic.target to fetch timer units + for service in _get_sonic_services(): + if service.endswith('.timer'): + # Stop the timer unit + clicommon.run_command(['sudo', 'systemctl', 'stop', service], display_cmd=True) + click.echo("Stopping SONiC target ...") clicommon.run_command(['sudo', 'systemctl', 'stop', 'sonic.target', '--job-mode', 'replace-irreversibly']) diff --git a/tests/config_test.py b/tests/config_test.py index 67c824d5a..9736a571b 100644 --- a/tests/config_test.py +++ b/tests/config_test.py @@ -53,6 +53,7 @@ load_minigraph_command_output="""\ Acquired lock on {0} Disabling container and routeCheck monitoring ... +Running command: sudo systemctl stop featured.timer Stopping SONiC target ... Running command: /usr/local/bin/sonic-cfggen -H -m --write-to-db Running command: config qos reload --no-dynamic-buffer --no-delay @@ -70,6 +71,7 @@ load_minigraph_command_bypass_lock_output = """\ Bypass lock on {} +Running command: sudo systemctl stop featured.timer Stopping SONiC target ... Running command: /usr/local/bin/sonic-cfggen -H -m --write-to-db Running command: config qos reload --no-dynamic-buffer --no-delay @@ -81,6 +83,7 @@ load_minigraph_platform_plugin_command_output="""\ Acquired lock on {0} +Running command: sudo systemctl stop featured.timer Stopping SONiC target ... Running command: /usr/local/bin/sonic-cfggen -H -m --write-to-db Running command: config qos reload --no-dynamic-buffer --no-delay @@ -165,6 +168,7 @@ RELOAD_CONFIG_DB_OUTPUT = """\ Acquired lock on {0} +Running command: sudo systemctl stop featured.timer Stopping SONiC target ... Running command: /usr/local/bin/sonic-cfggen -j /tmp/config.json --write-to-db Restarting SONiC target ... @@ -178,6 +182,7 @@ RELOAD_CONFIG_DB_BYPASS_LOCK_OUTPUT = """\ Bypass lock on {0} +Running command: sudo systemctl stop featured.timer Stopping SONiC target ... Running command: /usr/local/bin/sonic-cfggen -j /tmp/config.json --write-to-db Restarting SONiC target ... @@ -186,6 +191,7 @@ RELOAD_YANG_CFG_OUTPUT = """\ Acquired lock on {0} +Running command: sudo systemctl stop featured.timer Stopping SONiC target ... Running command: /usr/local/bin/sonic-cfggen -Y /tmp/config.json --write-to-db Restarting SONiC target ... @@ -195,6 +201,7 @@ RELOAD_MASIC_CONFIG_DB_OUTPUT = """\ Acquired lock on {0} +Running command: sudo systemctl stop featured.timer Stopping SONiC target ... Running command: /usr/local/bin/sonic-cfggen -j /tmp/config.json --write-to-db Running command: /usr/local/bin/sonic-cfggen -j /tmp/config0.json -n asic0 --write-to-db @@ -219,6 +226,7 @@ reload_config_masic_onefile_output = """\ Acquired lock on {0} +Running command: sudo systemctl stop featured.timer Stopping SONiC target ... Restarting SONiC target ... Reloading Monit configuration ... @@ -227,6 +235,7 @@ reload_config_masic_onefile_gen_sysinfo_output = """\ Acquired lock on {0} +Running command: sudo systemctl stop featured.timer Stopping SONiC target ... Running command: /usr/local/bin/sonic-cfggen -H -k Mellanox-SN3800-D112C8 --write-to-db Running command: /usr/local/bin/sonic-cfggen -H -k multi_asic -n asic0 --write-to-db @@ -1148,7 +1157,7 @@ def test_load_minigraph(self, mock_check_call, get_cmd_module, setup_single_broa # Verify "systemctl reset-failed" is called for services under sonic.target mock_run_command.assert_any_call(['systemctl', 'reset-failed', 'swss']) mock_run_command.assert_any_call(['systemctl', 'reset-failed', 'pmon']) - assert mock_run_command.call_count == 21 + assert mock_run_command.call_count == 23 @mock.patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', mock.MagicMock(return_value=("dummy_path", None))) @@ -1194,7 +1203,7 @@ def test_load_minigraph_bypass_lock(self, get_cmd_module, setup_single_broadcom_ load_minigraph_command_bypass_lock_output.format(config.SYSTEM_RELOAD_LOCK) mock_run_command.assert_any_call(['systemctl', 'reset-failed', 'swss']) mock_run_command.assert_any_call(['systemctl', 'reset-failed', 'pmon']) - assert mock_run_command.call_count == 15 + assert mock_run_command.call_count == 17 finally: flock.release_flock(fd) @@ -1213,7 +1222,7 @@ def test_load_minigraph_platform_plugin(self, get_cmd_module, setup_single_broad # Verify "systemctl reset-failed" is called for services under sonic.target mock_run_command.assert_any_call(['systemctl', 'reset-failed', 'swss']) mock_run_command.assert_any_call(['systemctl', 'reset-failed', 'pmon']) - assert mock_run_command.call_count == 15 + assert mock_run_command.call_count == 17 @mock.patch('sonic_py_common.device_info.get_paths_to_platform_and_hwsku_dirs', mock.MagicMock(return_value=(load_minigraph_platform_false_path, None))) def test_load_minigraph_platform_plugin_fail(self, get_cmd_module, setup_single_broadcom_asic):