Skip to content

[transceiver/cdb_firmware_upgrade] Add CDB firmware download and activation tests - #26869

Open
pnakka28 wants to merge 3 commits into
sonic-net:masterfrom
pnakka28:cdb_firmware_tests_2
Open

[transceiver/cdb_firmware_upgrade] Add CDB firmware download and activation tests#26869
pnakka28 wants to merge 3 commits into
sonic-net:masterfrom
pnakka28:cdb_firmware_tests_2

Conversation

@pnakka28

@pnakka28 pnakka28 commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Description of PR

Summary:

Adds the two CDB firmware upgrade test cases to the transceiver suite: TC3 downloads a firmware image to a CMIS active-optical module's inactive bank and verifies the download, and TC4 activates the inactive-bank firmware and verifies the running image changed. Both the test cases serve as individual as well as base tests for future firmware upgrade test case.

Fixes #

Type of change

  • Bug fix
  • Testbed and Framework(new/improvement)
  • New Test case
    • Skipped for non-supported platforms
  • Test case improvement

Back port request

  • 202311
  • 202405
  • 202411
  • 202505
  • 202511
  • 202512
  • 202605

Tracking issue/work item for backport/cherry-pick request:
Failure type:

Approach

What is the motivation for this PR?

The pre-checks (TC1/TC2) confirm each module starts on its gold firmware and advertises CDB abort support. The next step is to exercise the CDB firmware lifecycle end-to-end. TC3 and TC4 validate that sfputil firmware download, run, and commit work on real CMIS active-optical modules.

Prerequisites

  • DOM monitoring must be disabled on the ports under test. The firmware operations and sfputil show fwversion read the module over CDB and if DOM polling accesses the same module concurrently, its I2C/CDB access can interleave and corrupt the reply.
  • Firmware binaries for each module's firmware_versions must be available.
  • Per-PN inventory attributes firmware_versions, gold_firmware_version, and inactive_firmware_version must be configured.

How did you do it?

  • New transceiver/cdb_firmware_upgrade/test_firmware_download.py and test_firmware_activation.py.
  • firmware_operations.py - containing all firmware related operations including download, activation etc.
  • conftest.py - session-scoped fixtures that stage firmware once, restore every qualifying module to its original banks before and after the session, and disable DOM polling per test.
  • Supporting helpers: cli_helpers, scenario_ops, dmesg_helpers, cli_parser_helper.

How did you verify/test it?

  • Ran both tests on CDB supported modules and verified both tests pass on all qualified ports.
  • Verified the download lands in the inactive bank, activation swaps banks and the running image changes, links recover to oper-up, and no new I2C errors appear in dmesg.
  • Verified every module is restored to its original firmware baseline at the end of the session.
  • Non-CMIS-active-optical optics are skipped.

Any platform specific information?

Supported testbed topology if it's a new test case?

Physical testbeds with real CMIS active-optical transceivers. Ports not supporting CDB are skipped automatically.

Documentation

N/A

Test Logs

root@sonic:sonic-mgmt/tests# ./run_tests.sh -c transceiver/cdb_firmware_upgrade -n testbed_name --skip_sanity --disable_loganalyzer --skip_transceiver_template_validation" -r                                                                                                                           

transceiver/cdb_firmware_upgrade/test_firmware_abort_versions.py::test_firmware_versions PASSED                                           [ 20%]
transceiver/cdb_firmware_upgrade/test_firmware_abort_versions.py::test_cdb_abort_support PASSED                                           [ 40%]
transceiver/cdb_firmware_upgrade/test_firmware_activation.py::test_firmware_activation PASSED                                             [ 60%]
transceiver/cdb_firmware_upgrade/test_firmware_download.py::test_firmware_download PASSED                                                 [ 80%]
transceiver/cdb_firmware_upgrade/test_firmware_upgrade.py::TestFirmwareUpgrade::test_transceiver_firmware_download PASSED

transceiver/cdb_firmware_upgrade/test_firmware_abort_versions.py::test_firmware_versions
transceiver/cdb_firmware_upgrade/test_firmware_abort_versions.py::test_firmware_versions
transceiver/cdb_firmware_upgrade/test_firmware_abort_versions.py::test_firmware_versions
transceiver/cdb_firmware_upgrade/test_firmware_abort_versions.py::test_firmware_versions
transceiver/cdb_firmware_upgrade/test_firmware_abort_versions.py::test_cdb_abort_support
transceiver/cdb_firmware_upgrade/test_firmware_activation.py::test_firmware_activation
transceiver/cdb_firmware_upgrade/test_firmware_download.py::test_firmware_download
transceiver/cdb_firmware_upgrade/test_firmware_upgrade.py::TestFirmwareUpgrade::test_transceiver_firmware_download[None]

================================================= 5 passed in 1151.05s (0:19:11) ==================================================
root@sonic:sonic-mgmt/tests/logs# grep -nE "CMIS CDB firmware|staging firmware|firmware staged|original firmware baseline|DOM polling|pre-download CDB abort|firmware files cleanup" test.log
132350:06/08/2026 21:49:19 conftest.stage_latest_firmware_binaries_ L0083 INFO   | Staging latest CMIS CDB firmware binaries on DUT
132357:06/08/2026 21:49:20 conftest.stage_latest_firmware_binaries_ L0096 INFO   | Download mode: staging firmware from server/cmis_cdb_firmware
132391:06/08/2026 21:49:27 conftest.stage_latest_firmware_binaries_ L0111 INFO   | All latest firmware staged to /tmp/cmis_cdb_firmware
132416:06/08/2026 21:49:38 conftest._restore                        L0198 INFO   | Pre-session original firmware baseline on 1 port(s)
132510:06/08/2026 21:49:53 conftest.dom_polling_disabled            L0169 INFO   | Disabled DOM polling on 1 port(s); waiting 5s
132553:06/08/2026 21:50:06 test_firmware_abort_versions.test_firmwa L0178 INFO   | Verified firmware version on 1 port(s)
132626:06/08/2026 21:50:13 conftest.dom_polling_disabled            L0178 INFO   | Re-enabled DOM polling on 1 port(s)
132713:06/08/2026 21:50:20 conftest.dom_polling_disabled            L0169 INFO   | Disabled DOM polling on 1 port(s); waiting 5s
132757:06/08/2026 21:50:32 test_firmware_abort_versions.test_cdb_ab L0197 INFO   | Verified CDB abort support on 1 port(s)
132830:06/08/2026 21:50:38 conftest.dom_polling_disabled            L0178 INFO   | Re-enabled DOM polling on 1 port(s)
132957:06/08/2026 21:50:56 conftest.dom_polling_disabled            L0169 INFO   | Disabled DOM polling on 1 port(s); waiting 5s
133017:06/08/2026 21:51:18 firmware_operations.perform_firmware_act L0243 INFO   | Port EthernetXX: firmware run took 7.1s
133020:06/08/2026 21:51:20 firmware_operations.perform_firmware_act L0249 INFO   | Port EthernetXX: firmware commit took 1.5s
133133:06/08/2026 21:51:55 conftest.dom_polling_disabled            L0178 INFO   | Re-enabled DOM polling on 1 port(s)
133260:06/08/2026 21:52:09 conftest.dom_polling_disabled            L0169 INFO   | Disabled DOM polling on 1 port(s); waiting 5s
133311:06/08/2026 21:52:23 firmware_operations.perform_firmware_dow L0152 INFO   | Port EthernetXX: pre-download CDB abort -> status=1 err=None
133316:06/08/2026 21:59:00 firmware_operations.perform_firmware_dow L0168 INFO   | Port EthernetXX: firmware download firmware_version took 396.4s
133399:06/08/2026 21:59:10 conftest.dom_polling_disabled            L0178 INFO   | Re-enabled DOM polling on 1 port(s)
133767:06/08/2026 22:06:34 firmware_operations.perform_firmware_dow L0168 INFO   | Port EthernetXX: firmware download gold_version took 403.9s
133792:06/08/2026 22:06:48 firmware_operations.perform_firmware_act L0243 INFO   | Port EthernetXX: firmware run took 6.9s
133795:06/08/2026 22:06:50 firmware_operations.perform_firmware_act L0249 INFO   | Port EthernetXX: firmware commit took 1.6s
133855:06/08/2026 22:07:22 conftest._restore                        L0198 INFO   | Post-session original firmware baseline on 1 port(s)
133856:06/08/2026 22:07:22 conftest.firmware_files_cleanup          L0218 INFO   | Starting firmware files cleanup...

MSFT ADO - 39030975

Signed-off-by: Pavan Kalyan Nakka <pnakka@microsoft.com>
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds end-to-end CMIS CDB firmware lifecycle coverage to the transceiver test suite by introducing pre-checks plus dedicated download (TC3) and activation (TC4) test cases, along with shared helpers/fixtures to stage firmware and validate operational safety signals (links, dmesg I2C errors, etc.).

Changes:

  • Add new CDB firmware test cases for pre-checks (TC1/TC2), firmware download (TC3), and firmware activation (TC4).
  • Introduce shared firmware operation helpers (download/run/commit/reset) and dmesg-scoped error scanning.
  • Update CDB firmware conftest to stage firmware once per session and restore modules to original baseline before/after the session.

Reviewed changes

Copilot reviewed 9 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/transceiver/common/scenario_ops.py Adds reusable sfputil reset operation helper for scenarios.
tests/transceiver/common/dmesg_helpers.py New helper to watermark and scan dmesg for operation-window errors using monotonic timestamps.
tests/transceiver/common/cli_parser_helper.py Adds centralized constants for sfputil show fwversion field labels.
tests/transceiver/common/cli_helpers.py Adds firmware CLI wrappers (download/run/commit/reset) and CDB abort helper; switches DOM polling toggle to command.
tests/transceiver/cdb_firmware_upgrade/utils/firmware_utils.py Refactors required firmware metadata selection to use per-port configured firmware_versions; tracks staged DUT paths.
tests/transceiver/cdb_firmware_upgrade/test_firmware_download.py New TC3 test that runs the per-port firmware download operation and aggregates failures.
tests/transceiver/cdb_firmware_upgrade/test_firmware_activation.py New TC4 test that activates firmware (including single-bank flow) and aggregates failures.
tests/transceiver/cdb_firmware_upgrade/test_firmware_abort_versions.py New TC1/TC2 baseline checks for gold firmware state and CDB abort support.
tests/transceiver/cdb_firmware_upgrade/firmware_operations.py New implementation of per-port firmware download/activation/restore operations with link and dmesg checks.
tests/transceiver/cdb_firmware_upgrade/conftest.py Session fixtures for qualifying ports, staging firmware, per-test DOM polling disable, session baseline restore, and cleanup.

Comment thread tests/transceiver/common/scenario_ops.py
Comment thread tests/transceiver/cdb_firmware_upgrade/test_firmware_download.py
Comment thread tests/transceiver/cdb_firmware_upgrade/conftest.py
Comment thread tests/transceiver/cdb_firmware_upgrade/test_firmware_activation.py
Comment thread tests/transceiver/cdb_firmware_upgrade/firmware_operations.py Fixed
Comment thread tests/transceiver/cdb_firmware_upgrade/firmware_operations.py Fixed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 10 changed files in this pull request and generated no new comments.

Suppressed comments (6)

tests/transceiver/cdb_firmware_upgrade/conftest.py:196

  • These pre/post-session restores run outside the function-scoped dom_polling_disabled fixture, so firmware download/activation and show fwversion access the modules while DOM polling is enabled. That violates the stated CDB prerequisite and can interleave I2C transactions during the safety restore itself; disable DOM polling around each restore while preserving its prior state.
        failures, ports = run_firmware_op_on_ports(
            duthost, port_attributes_dict, cdb_firmware_qualifying_ports,
            lport_to_pport, required_firmware_metadata_for_all_transceivers,
            restore_module_to_original,

tests/transceiver/cdb_firmware_upgrade/firmware_operations.py:254

  • The dmesg scan happens before the mandatory sfputil reset below, so I2C errors caused by reset/recovery are outside the checked operation window even though reset is part of activation. Perform the final scan after reset and port recovery (and keep the watermark available across failure paths).
        if not failures:
            failures += _scan_i2c_errors(duthost, dmesg_start_uptime, "activation")

tests/transceiver/cdb_firmware_upgrade/firmware_operations.py:259

  • thermalctld_stopped is cleared even when _start_thermalctld reports failure. The finally block then skips its restart attempt and can leave thermal management stopped after the test. Clear the flag only after a successful restart so teardown retries failures.
        thermal_err = _start_thermalctld(duthost, thermalctld_stopped)
        thermalctld_stopped = False
        if thermal_err:
            failures.append(f"failed to restart thermalctld: {thermal_err}")

tests/transceiver/cdb_firmware_upgrade/conftest.py:202

  • The pre-session restore rewrites the firmware banks before test_firmware_versions runs, so TC1 cannot detect a module that did not initially start on its configured gold/inactive firmware—the condition this PR says TC1 validates. Capture and assert the initial bank state before modifying it, or defer restoration until after the pre-check.
    _restore("Pre-session")

tests/transceiver/common/cli_helpers.py:450

  • NO_CDB is printed with exit code 0, so this helper returns (“NO_CDB”, None) and the download path treats an unavailable CDB API as a successful abort. Convert this sentinel into an error before proceeding with firmware download.
    result = duthost.shell('python3 -c "{}"'.format(pycode), module_ignore_errors=True)
    if result.get("rc", RC_FAILURE) != 0:
        return None, f"CDB abort failed with rc={result.get('rc')} ({_error_detail(result)})"
    return " ".join(result.get("stdout_lines") or []).strip(), None

tests/transceiver/cdb_firmware_upgrade/firmware_operations.py:196

  • The dual-bank check only verifies the new active version and bank letter. It can pass even if the old active firmware was not moved to the inactive bank, so it does not actually verify the bank swap claimed by TC4. Also assert after Inactive Firmware == before Active Firmware.

This issue also appears in the following locations of the same file:

  • line 253
  • line 256
    if dual_bank_supported:
        if after_banks.get(FW_ACTIVE) != before_banks.get(FW_INACTIVE):
            failures.append("firmware activation failed")
        if after_banks.get(FW_RUNNING_IMAGE) == before_banks.get(FW_RUNNING_IMAGE):
            failures.append("Running Image did not change after activation")

Signed-off-by: Pavan Kalyan Nakka <pnakka@microsoft.com>
@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@mssonicbld

Copy link
Copy Markdown
Collaborator

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).

@pnakka28 pnakka28 added the Transceiver Test Dev 🔌 Action item for transceiver test development label Aug 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Transceiver Test Dev 🔌 Action item for transceiver test development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants