Skip to content

[mellanox_firmware] PCC collector (opt in)#104

Open
DanGoldberg wants to merge 11 commits into
NVIDIA:mainfrom
DanGoldberg:ppcc-collector
Open

[mellanox_firmware] PCC collector (opt in)#104
DanGoldberg wants to merge 11 commits into
NVIDIA:mainfrom
DanGoldberg:ppcc-collector

Conversation

@DanGoldberg

@DanGoldberg DanGoldberg commented Apr 28, 2026

Copy link
Copy Markdown

Add a new PCC collector.
This collection is disabled by default and requires
adding "-k mellanox_firmware.pcc=true" to the command line
to enable it.

Key changes:

  • PCC collection via PPCC register with either mlxreg or mstreg
  • BaseTool: added subdir parameter for saving the output under
    a dedicated directory within mellanox_firmware output directory
    to reduce clutter

Signed-off-by: Dan Goldberg dgoldberg@nvidia.com


Please place an 'X' inside each '[]' to confirm you adhere to our Contributor Guidelines

  • Is the commit message split over multiple lines and hard-wrapped at 72 characters?
  • Is the subject and message clear and concise?
  • Does the subject start with [plugin_name] if submitting a plugin patch or a [section_name] if part of the core sosreport code?
  • Does the commit contain a Signed-off-by: First Lastname email@example.com?
  • Are any related Issues or existing PRs properly referenced via a Closes (Issue) or Resolved (PR) line?
  • Are all passwords or private data gathered by this PR obfuscated?

Summary by CodeRabbit

Summary

  • New Features

    • Added optional Performance Counter Collection (PCC) to gather PPCC firmware register information and DOCA PCC counters for enhanced diagnostics.
    • Enabled via a new pcc plugin setting (disabled by default).
  • Improvements

    • Command outputs collected by the tool can now be stored under a specified subdirectory for better organization.
    • Increased Mellanox and related plugin timeouts to 2160 seconds and adjusted per-device timeout expectations used for warnings.

@coderabbitai

coderabbitai Bot commented Apr 28, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This pull request adds optional PCC collection to the Mellanox firmware suite, including PPCC register data gathering, DOCA PCC counter collection, tool integration, manager orchestration, and expanded timeout settings.

Changes

PCC collection flow

Layer / File(s) Summary
Manager and plugin enablement
sos/report/mellanox_firmware_suite/collectors/collector_manager.py, sos/report/plugins/mellanox_firmware.py, sos-nvdebug.conf, sos-nvidia.conf
CollectorManager gates PCC collection behind the pcc option and runs both PCC collectors per device context; plugin and configuration timeout values are increased.
PPCC command and output handling
sos/report/mellanox_firmware_suite/collectors/pcc_collector.py
PPCC command values, register indexes, deterministic filenames, output parsing, and centralized command failure logging are added.
PPCC slot data collection
sos/report/mellanox_firmware_suite/collectors/pcc_collector.py
PccCollector discovers algorithm slots, collects status, counters, metadata, and parameters, and falls back to individual parameter queries when bulk retrieval fails.
DOCA PCC counter collection
sos/report/mellanox_firmware_suite/collectors/doca_pcc_collector.py
DocaPccCollector validates device and tool prerequisites, then executes DOCA PCC counter setup and query commands while collecting query output.

Estimated code review effort: 4 (Complex) | ~55 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: an opt-in PCC collector for the mellanox_firmware plugin.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@DanGoldberg
DanGoldberg marked this pull request as ready for review April 30, 2026 13:37

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@sos/report/mellanox_firmware_suite/tools/base_tool.py`:
- Around line 49-52: The cache early-return in execute_cmd is skipping the
required side-effect of writing artifacts when filename or subdir is provided;
modify execute_cmd so that when filename or subdir is set it does not
short-circuit on a cache hit but still calls _collect_cmd_output (or an
equivalent helper) to create/write the file into the requested subdir, while
still returning the cached stdout when appropriate; use the existing
cache_key/self.ctx.cache logic to retrieve stdout but ensure
_collect_cmd_output(cmd, output, filename, subdir) is invoked before returning
if filename or subdir are non-empty.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: cf45634c-fd07-4972-a83c-11ebe05c891d

📥 Commits

Reviewing files that changed from the base of the PR and between d690337 and 7006fb3.

📒 Files selected for processing (6)
  • sos/report/mellanox_firmware_suite/collectors/collector_manager.py
  • sos/report/mellanox_firmware_suite/collectors/pcc_collector.py
  • sos/report/mellanox_firmware_suite/tools/MFT/mlxreg.py
  • sos/report/mellanox_firmware_suite/tools/MSTFlint/mstreg.py
  • sos/report/mellanox_firmware_suite/tools/base_tool.py
  • sos/report/plugins/mellanox_firmware.py

Comment on lines 49 to +52
if get_cached and cache_key in self.ctx.cache:
return self.ctx.cache[cache_key]

rc, output = self._run_command(cmd, timeout, filename)
rc, output = self._run_command(cmd, timeout, filename, subdir=subdir)

@coderabbitai coderabbitai Bot Apr 30, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't short-circuit archival calls on cache hits.

When filename/subdir is provided, execute_cmd() has a required side effect: it must write the collected artifact. The cache guard returns before _collect_cmd_output() runs, so a repeated call for the same command can hand back cached stdout and never create the requested file in the requested subdirectory.

Suggested fix
-        if get_cached and cache_key in self.ctx.cache:
+        if filename is None and get_cached and cache_key in self.ctx.cache:
             return self.ctx.cache[cache_key]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if get_cached and cache_key in self.ctx.cache:
return self.ctx.cache[cache_key]
rc, output = self._run_command(cmd, timeout, filename)
rc, output = self._run_command(cmd, timeout, filename, subdir=subdir)
if filename is None and get_cached and cache_key in self.ctx.cache:
return self.ctx.cache[cache_key]
rc, output = self._run_command(cmd, timeout, filename, subdir=subdir)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@sos/report/mellanox_firmware_suite/tools/base_tool.py` around lines 49 - 52,
The cache early-return in execute_cmd is skipping the required side-effect of
writing artifacts when filename or subdir is provided; modify execute_cmd so
that when filename or subdir is set it does not short-circuit on a cache hit but
still calls _collect_cmd_output (or an equivalent helper) to create/write the
file into the requested subdir, while still returning the cached stdout when
appropriate; use the existing cache_key/self.ctx.cache logic to retrieve stdout
but ensure _collect_cmd_output(cmd, output, filename, subdir) is invoked before
returning if filename or subdir are non-empty.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Pre-existing execute_cmd cache behavior from the modular collector refactor — this PR only adds subdir passthrough and doesn't change caching. Not a regression, and PCC isn't affected: each ppcc_get has a unique cache key.
Out of scope for this PR.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@DanGoldberg, understood — thanks for the context. Since each ppcc_get uses a unique cache key the early-return path won't be hit for those calls, so there's no practical regression here.

The general concern (cache hit suppressing a file-write side-effect) still exists for any future caller that reuses a cache key with a filename/subdir argument, so it would be worth addressing eventually. Would you like me to open a follow-up GitHub issue to track it?

(ミ ^ ᆺ ^ ミ)


🧠 Learnings used
Learnt from: anton-metsner
Repo: NVIDIA/doca-sosreport PR: 91
File: sos/report/mellanox_firmware_suite/collectors/cable_collector.py:54-111
Timestamp: 2026-01-22T22:39:45.230Z
Learning: In the sos plugin framework (sos/report/plugins), directory creation is handled by the setup flow and path helper methods (e.g., plugin.archive.get_archive_path() and plugin._make_command_filename()). Do not add explicit os.makedirs() calls before writing files to paths produced by these methods, as directories will be created automatically when needed. This applies to Python files under the sos/report directory and its plugins.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
sos/report/plugins/mellanox_firmware.py (1)

80-93: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Timeout warning threshold doesn't account for pcc being opt-in.

collect_pcc_info() in collector_manager.py only runs PccCollector per device when plugin.get_option("pcc", default=False) is true. But this expected_timeout calculation unconditionally assumes ~4 min/device (device_count * 240), which is the PCC-inclusive estimate. For the default case (pcc=False), the actual expected per-device time is far lower (previously ~180s), so this will now emit misleading "timeout may be too low" warnings even when PCC collection isn't running at all.

Consider branching the multiplier on whether the pcc option is enabled:

🐛 Proposed fix
     `@property`
     def timeout(self):
         base_timeout = super().timeout
         device_count = len([d for d in self.device_contexts if d.primary])
-        expected_timeout = device_count * 240
+        per_device_seconds = 240 if self.get_option("pcc") else 180
+        expected_timeout = device_count * per_device_seconds

         if base_timeout < expected_timeout:
             self._log_warn(
                 f"Plugin timeout {base_timeout}s may be too low for "
                 f"{device_count} device(s). Expected ~{expected_timeout}s "
-                f"(~4 minutes per device)."
+                f"(~{per_device_seconds // 60} minutes per device)."
             )

         return base_timeout
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sos/report/plugins/mellanox_firmware.py` around lines 80 - 93, The timeout
warning in the timeout property of MellanoxFirmwarePlugin is using a
PCC-inclusive per-device estimate even when pcc is disabled, which makes the
warning inaccurate by default. Update the expected_timeout calculation to branch
on the plugin’s pcc option (via get_option("pcc", default=False)) so the warning
uses the higher 240s/device only when PccCollector runs, and a lower baseline
estimate otherwise; keep the warning/logging logic in the timeout property and
_log_warn call unchanged apart from the adjusted threshold.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@sos/report/plugins/mellanox_firmware.py`:
- Around line 80-93: The timeout warning in the timeout property of
MellanoxFirmwarePlugin is using a PCC-inclusive per-device estimate even when
pcc is disabled, which makes the warning inaccurate by default. Update the
expected_timeout calculation to branch on the plugin’s pcc option (via
get_option("pcc", default=False)) so the warning uses the higher 240s/device
only when PccCollector runs, and a lower baseline estimate otherwise; keep the
warning/logging logic in the timeout property and _log_warn call unchanged apart
from the adjusted threshold.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 5362f727-6199-4a80-bea4-9c946e3fb71b

📥 Commits

Reviewing files that changed from the base of the PR and between 7a6e8d3 and 854db61.

📒 Files selected for processing (3)
  • sos-nvdebug.conf
  • sos-nvidia.conf
  • sos/report/plugins/mellanox_firmware.py
✅ Files skipped from review due to trivial changes (2)
  • sos-nvdebug.conf
  • sos-nvidia.conf

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
sos/report/mellanox_firmware_suite/collectors/collector_manager.py (1)

33-41: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider merging the two device-context loops.

collect_pcc_info() iterates self.device_contexts twice — once for PccCollector, once for DocaPccCollector. Since both collectors are independently gated and there's no ordering dependency evident here, a single loop running both collectors per ctx would be simpler and avoid double iteration.

♻️ Proposed refactor
     def collect_pcc_info(self):
         if not self.plugin.get_option("pcc", default=False):
             return

         for ctx in self.device_contexts:
             PccCollector().run(self.plugin, ctx)
-
-        for ctx in self.device_contexts:
             DocaPccCollector().run(self.plugin, ctx)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sos/report/mellanox_firmware_suite/collectors/collector_manager.py` around
lines 33 - 41, Merge the two iterations in collect_pcc_info into a single loop
over self.device_contexts, invoking both PccCollector().run and
DocaPccCollector().run for each ctx. Preserve the existing pcc option guard and
collector invocation order.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@sos/report/mellanox_firmware_suite/collectors/doca_pcc_collector.py`:
- Around line 45-56: Update _collect so the side-effecting PCC “set” exec_cmd
runs only when allow_system_changes is enabled, using the plugin’s existing
change-gating mechanism. Preserve the current failure logging and early-return
behavior when the gated command is executed, while skipping the set step
entirely when changes are not allowed.

---

Nitpick comments:
In `@sos/report/mellanox_firmware_suite/collectors/collector_manager.py`:
- Around line 33-41: Merge the two iterations in collect_pcc_info into a single
loop over self.device_contexts, invoking both PccCollector().run and
DocaPccCollector().run for each ctx. Preserve the existing pcc option guard and
collector invocation order.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 90f17b56-fdd3-4e00-ac2f-71058fa546bb

📥 Commits

Reviewing files that changed from the base of the PR and between 854db61 and 2b63e94.

📒 Files selected for processing (2)
  • sos/report/mellanox_firmware_suite/collectors/collector_manager.py
  • sos/report/mellanox_firmware_suite/collectors/doca_pcc_collector.py

Comment on lines +45 to +56
def _collect(self, plugin, ctx):
mst_dev = ctx.mst_device

result = plugin.exec_cmd(cmd=f"{self._TOOL_PATH} set {mst_dev}")
rc = result.get("status", 1)

if rc != 0:
plugin._log_info(
f"doca_pcc: setting counters failed for {mst_dev} (rc={rc}); "
"skipping query"
)
return

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the collector and the surrounding plugin APIs.
git ls-files | rg '^sos/report/mellanox_firmware_suite/collectors/doca_pcc_collector\.py$|^sos/|^docs/|README|CHANGELOG' || true

echo
echo "== outline: doca_pcc_collector.py =="
ast-grep outline sos/report/mellanox_firmware_suite/collectors/doca_pcc_collector.py --view expanded || true

echo
echo "== search exec_cmd / allow_system_changes / changes gating =="
rg -n "def exec_cmd|allow_system_changes|changes=True|changes=|system-changes|skip.*changes|set_option|get_option" sos -g'*.py' -g'*.md' || true

echo
echo "== search doca_pcc references =="
rg -n "doca_pcc|mellanox_firmware.pcc|TOOL_PATH|mst_device" sos -g'*.py' || true

Repository: NVIDIA/doca-sosreport

Length of output: 50377


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '^sos/report/mellanox_firmware_suite/collectors/doca_pcc_collector\.py$|^sos/|^docs/|README|CHANGELOG' || true

echo
echo "== outline: doca_pcc_collector.py =="
ast-grep outline sos/report/mellanox_firmware_suite/collectors/doca_pcc_collector.py --view expanded || true

echo
echo "== search exec_cmd / allow_system_changes / changes gating =="
rg -n "def exec_cmd|allow_system_changes|changes=True|changes=|system-changes|skip.*changes|set_option|get_option" sos -g'*.py' -g'*.md' || true

echo
echo "== search doca_pcc references =="
rg -n "doca_pcc|mellanox_firmware.pcc|TOOL_PATH|mst_device" sos -g'*.py' || true

Repository: NVIDIA/doca-sosreport

Length of output: 50377


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== doca_pcc_collector.py =="
sed -n '1,140p' sos/report/mellanox_firmware_suite/collectors/doca_pcc_collector.py | cat -n

echo
echo "== plugin exec_cmd / cmd gating =="
sed -n '1138,1185p' sos/report/plugins/__init__.py | cat -n
echo
sed -n '2040,2075p' sos/report/plugins/__init__.py | cat -n
echo
sed -n '2098,2235p' sos/report/plugins/__init__.py | cat -n
echo
sed -n '2610,2665p' sos/report/plugins/__init__.py | cat -n

echo
echo "== allow_system_changes handling in doca/mellanox paths =="
sed -n '1,120p' sos/report/mellanox_firmware_suite/collectors/collector_manager.py | cat -n
echo
sed -n '1,140p' sos/report/plugins/mellanox_firmware.py | cat -n
echo
sed -n '1,90p' sos/report/plugins/omnipath_client.py | cat -n
echo
sed -n '1,90p' sos/report/plugins/firewall_tables.py | cat -n

Repository: NVIDIA/doca-sosreport

Length of output: 30293


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
from pathlib import Path

# Print only the relevant sections with stable line numbers.
files = {
    "sos/report/mellanox_firmware_suite/collectors/doca_pcc_collector.py": (1, 140),
    "sos/report/plugins/__init__.py": [(1140, 1185), (2040, 2075), (2098, 2235), (2610, 2665)],
    "sos/report/mellanox_firmware_suite/collectors/collector_manager.py": (1, 120),
    "sos/report/plugins/mellanox_firmware.py": (1, 140),
    "sos/report/plugins/omnipath_client.py": (1, 90),
    "sos/report/plugins/firewall_tables.py": (1, 90),
}
for path, spans in files.items():
    print(f"\n== {path} ==")
    p = Path(path)
    text = p.read_text().splitlines()
    if isinstance(spans[0], int):
        spans = [spans]
    for start, end in spans:
        print(f"-- lines {start}-{end} --")
        for i in range(start - 1, min(end, len(text))):
            print(f"{i+1:4d}: {text[i]}")
PY

Repository: NVIDIA/doca-sosreport

Length of output: 29908


Gate the PCC set step behind --allow-system-changes.
plugin.exec_cmd() here has no changes gate, unlike add_cmd_output(..., changes=True), so enabling mellanox_firmware.pcc alone still runs a side-effecting command. Skip this step unless allow_system_changes is set, or move it onto the change-aware path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sos/report/mellanox_firmware_suite/collectors/doca_pcc_collector.py` around
lines 45 - 56, Update _collect so the side-effecting PCC “set” exec_cmd runs
only when allow_system_changes is enabled, using the plugin’s existing
change-gating mechanism. Preserve the current failure logging and early-return
behavior when the gated command is executed, while skipping the set step
entirely when changes are not allowed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant