Skip to content

Conversation

@SimonFair
Copy link
Contributor

@SimonFair SimonFair commented Jan 10, 2026

Summary by CodeRabbit

  • New Features

    • SR-IOV expanded to support display controllers in addition to network controllers.
    • UI and settings flow became class-aware, exposing per-device class options and controls.
  • Bug Fixes

    • Improved MAC address handling: only applied for network-class devices and validated more strictly.
    • More reliable VFIO/SR-IOV apply/save behavior with clearer status and error feedback.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 10, 2026

Walkthrough

Propagated a new class_id through VFIO/SR-IOV UI, backend, helper, and scripts; added PCI class exposure for VFs and conditional MAC handling (only for 0x02 network class); extended VFSETTINGS format to include class_id.

Changes

Cohort / File(s) Summary
UI + Apply/Save Flow
emhttp/plugins/dynamix/SysDevs.page
Added class_id parameter to saveVFSettingsConfig, applyVFSettings, doVFSettingApply signatures and call sites; propagate class_id through apply/save workflow; conditional MAC handling and UI elements based on class_id.
PCI Class Exposure & Helpers
emhttp/plugins/dynamix/include/SriovHelpers.php
Expose per-VF class and class_id; extend allowed classes to ['0x02','0x03']; parse and store PCI class info for each VF.
Class-aware UI generation
emhttp/plugins/dynamix/include/SysDevs.php
Generate class-specific UI: network (0x02) shows MAC input and MAC-related actions; display (0x03) shows VFIO actions; pass class_id in action links.
Backend apply logic
emhttp/plugins/dynamix/include/apply.sriov-cfg.php
Read class_id from settings/POST; gate MAC processing to class_id == '0x02'; propagate class_id to external command invocations; adjust VFIO rebind conditions accordingly.
Settings update and format
emhttp/plugins/dynamix/include/update.sriov-cfg.php, sbin/sriov
VFSETTINGS format changed from 4 to 5 fields: `pciid
Script for VF settings
sbin/sriov-vfsettings.sh
Add CLASS_ID arg and reposition VFIO/MAC args; validate MAC; gate MAC operations to CLASS_ID == 0x02; enhanced PF/VF discovery, unbind/rebind driver, stronger error handling and logging; preserve VFIO bind step (now receives class_id).

Sequence Diagram(s)

sequenceDiagram
    participant UI as Browser UI
    participant Page as SysDevs.page (JS)
    participant Helper as SriovHelpers
    participant Apply as apply.sriov-cfg.php
    participant Script as sbin/sriov-vfsettings.sh

    UI->>Page: user triggers "Apply VF settings" (includes class_id)
    Page->>Helper: get VF details (includes class_id)
    Page->>Page: applyVFSettings(...) routes by class_id
    alt class_id == '0x02' (Network)
        Page->>Apply: doVFSettingApply(pciId, vd, vfio, mac, ..., class_id)
        Apply->>Script: invoke sriov-vfsettings.sh with class_id, vfio, mac
        Script->>Script: validate MAC, unbind VF, set MAC, rebind, bind vfio if requested
    else class_id == '0x03' (Display)
        Page->>Apply: doVFSettingApply(pciId, vd, vfio, null, ..., class_id)
        Apply->>Script: invoke sriov-vfsettings.sh with class_id, vfio (MAC skipped)
        Script->>Script: skip MAC path, perform VFIO bind if requested
    end
    Script-->>Apply: success/failure
    Apply-->>Page: response
    Page->>Helper: saveVFSettingsConfig(..., class_id)
    Helper-->>Page: persisted
    Page-->>UI: display result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰
I hopped through classes, code in paw,
0x02 and 0x03 I saw,
Passing class_id down the trail,
MACs set where networks prevail,
A tiny rabbit clap — hooray for the veil!

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Feature: SRIOV GPU Changes' is vague and generic, lacking specificity about what SRIOV GPU changes are being made. Use a more descriptive title that specifies the main change, such as 'Add GPU device class support to SRIOV configuration' or 'Extend SRIOV to support display controllers (0x03 class)'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions
Copy link

github-actions bot commented Jan 10, 2026

🔧 PR Test Plugin Available

A test plugin has been generated for this PR that includes the modified files.

Version: 2026.01.10.1720
Build: View Workflow Run

📥 Installation Instructions:

Install via Unraid Web UI:

  1. Go to Plugins → Install Plugin
  2. Copy and paste this URL:
https://preview.dl.unraid.net/pr-plugins/pr-2512/webgui-pr-2512.plg
  1. Click Install

Alternative: Direct Download

⚠️ Important Notes:

  • Testing only: This plugin is for testing PR changes
  • Backup included: Original files are automatically backed up
  • Easy removal: Files are restored when plugin is removed
  • Conflicts: Remove this plugin before installing production updates

📝 Modified Files:

Click to expand file list
emhttp/plugins/dynamix/SysDevs.page
emhttp/plugins/dynamix/include/SriovHelpers.php
emhttp/plugins/dynamix/include/SysDevs.php
emhttp/plugins/dynamix/include/apply.sriov-cfg.php
emhttp/plugins/dynamix/include/update.sriov-cfg.php

🔄 To Remove:

Navigate to Plugins → Installed Plugins and remove webgui-pr-2512, or run:

plugin remove webgui-pr-2512

🤖 This comment is automatically generated and will be updated with each new push to this PR.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 Fix all issues with AI agents
In @emhttp/plugins/dynamix/include/SriovHelpers.php:
- Around line 84-95: The PF's class variables ($class, $class_id, $name) are
being overwritten by VF loop assignments from getPciClassNameAndId($vf_pci);
rename the VF-specific variables (e.g., $vf_class, $vf_class_id, $vf_name)
inside the VF loop and use those new names when populating $vf_entry['class']
and $vf_entry['class_id'] so the original PF $class/$class_id/$name values (set
earlier) remain unchanged for $results[$pci]; update all references in the VF
loop accordingly (including where you set $vf_entry['class'] and
$vf_entry['class_id']) to prevent shadowing.

In @emhttp/plugins/dynamix/include/SysDevs.php:
- Around line 424-448: The switch on $class_id can leave $mac undefined for
unhandled classes, causing a warning where $mac is later used (e.g., around the
usage near line 460); initialize $mac before the switch (e.g., $mac = null) or
ensure the switch's default case sets $mac = null (and any related variables
like $action/$saveaction) so $mac is always defined regardless of $class_id,
referencing the existing variables $class_id, $vrf, $pciaddress and the switch
block in SysDevs.php.
- Around line 454-458: The echo calling applyVFSettings uses $current_mac even
for non-network classes, causing an undefined variable; ensure $current_mac is
initialized before it's used (e.g., set a default empty string or null) prior to
the switch that sets it for class_id "0x02", or ensure you pass a safe value
when calling applyVFSettings; update the code around the applyVFSettings echo
and the switch that sets $current_mac so $current_mac is always defined when
used with applyVFSettings (references: applyVFSettings(), $current_mac, $vrf,
$class_id).

In @emhttp/plugins/dynamix/SysDevs.page:
- Around line 431-435: The function applyVFSettings assigns to mac without a
declaration, creating an implicit global; update the code in applyVFSettings to
declare mac locally (e.g., use let mac = ... or const mac = (class_id == '0x02'
? document.getElementById("vfmac" + pciId).value : null)); mirror the same fix
you applied to saveVFSettingsConfig so mac is not a global variable.
- Around line 203-208: In saveVFSettingsConfig, mac is assigned without a
declaration making it an implicit global; fix this by declaring mac with let (or
const if not reassigned) before use (e.g., initialize let mac = null), then set
mac = document.getElementById("vfmac" + pciId).value only when class_id ==
'0x02'; ensure vfio remains read from document.getElementById("vfvfio" +
pciId).checked and update the $.post call to use the locally scoped mac
variable.
🧹 Nitpick comments (1)
emhttp/plugins/dynamix/include/apply.sriov-cfg.php (1)

225-225: Consider validating class_id input.

The class_id is retrieved from POST without validation. While it's used in string comparisons, validating it against expected values ('0x02', '0x03') would add defense-in-depth.

♻️ Optional: Add validation for class_id
        $mac         = _var($_POST, 'mac');
        $class_id    = _var($_POST, 'class_id');
+       // Validate class_id if provided
+       if ($class_id !== '' && !in_array($class_id, ['0x02', '0x03'], true)) {
+           json_response(false, _("Invalid device class"));
+       }
        $vfio        = _var($_POST, 'vfio');
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4a1e8f3 and 37df059.

📒 Files selected for processing (4)
  • emhttp/plugins/dynamix/SysDevs.page
  • emhttp/plugins/dynamix/include/SriovHelpers.php
  • emhttp/plugins/dynamix/include/SysDevs.php
  • emhttp/plugins/dynamix/include/apply.sriov-cfg.php
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-14T15:18:55.567Z
Learnt from: SimonFair
Repo: unraid/webgui PR: 2443
File: emhttp/plugins/dynamix/include/SriovHelpers.php:16-16
Timestamp: 2025-11-14T15:18:55.567Z
Learning: In the file emhttp/plugins/dynamix/include/SriovHelpers.php, the global variable $allowedPCIClass is defined and is used in emhttp/plugins/dynamix/include/SysDevs.php which includes SriovHelpers.php. This variable should not be flagged as unused.

Applied to files:

  • emhttp/plugins/dynamix/include/SysDevs.php
  • emhttp/plugins/dynamix/include/apply.sriov-cfg.php
  • emhttp/plugins/dynamix/include/SriovHelpers.php
  • emhttp/plugins/dynamix/SysDevs.page
📚 Learning: 2025-12-28T15:54:58.673Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2496
File: emhttp/plugins/dynamix/Browse.page:901-906
Timestamp: 2025-12-28T15:54:58.673Z
Learning: In the unraid/webgui codebase, CSRF validation is centralized in the global auto_prepend_file (local_prepend.php) which runs before every PHP request. Do not add per-script CSRF checks in individual files like Browse.page or Control.php. If a script relies on global validation, ensure it does not duplicate CSRF logic; otherwise extend the central preface to cover the needed checks.

Applied to files:

  • emhttp/plugins/dynamix/include/SysDevs.php
  • emhttp/plugins/dynamix/include/apply.sriov-cfg.php
  • emhttp/plugins/dynamix/include/SriovHelpers.php
🧬 Code graph analysis (1)
emhttp/plugins/dynamix/include/apply.sriov-cfg.php (1)
emhttp/plugins/dynamix/include/Wrappers.php (1)
  • _var (106-108)
🔇 Additional comments (5)
emhttp/plugins/dynamix/include/SriovHelpers.php (1)

16-16: LGTM!

The extension of $allowedPCIClass to include '0x03' (Display class) alongside '0x02' (Network class) correctly enables SR-IOV support for GPUs. Based on learnings, this global variable is used in SysDevs.php which includes this file.

emhttp/plugins/dynamix/include/apply.sriov-cfg.php (1)

241-262: LGTM - Class-aware MAC and VFIO handling.

The logic correctly separates concerns:

  1. MAC changes only apply to network class (0x02) devices
  2. VFIO rebinding for non-network devices (e.g., GPU 0x03) proceeds without MAC considerations

The control flow ensures that when both MAC and VFIO change for network devices, the MAC path handles the driver rebind, preventing duplicate operations.

emhttp/plugins/dynamix/include/SysDevs.php (1)

449-449: LGTM - Proper class_id propagation to save action.

The saveVFSettingsConfig call correctly passes class_id to enable class-aware configuration saving.

emhttp/plugins/dynamix/SysDevs.page (2)

135-137: LGTM - Correctly enables display filter when SR-IOV filter is active.

Since SR-IOV now supports both network (0x02) and display (0x03) device classes, enabling showdisplay alongside shownetwork when showsriov is activated ensures all SR-IOV capable devices are visible.


487-528: LGTM - Proper class_id propagation through the apply workflow.

The doVFSettingApply function correctly:

  1. Accepts class_id as a parameter
  2. Includes it in the POST payload to apply.sriov-cfg.php
  3. Passes it to saveVFSettingsConfig on successful application

This ensures consistent class-aware handling throughout the configuration flow.

Comment on lines +84 to 95
// Device class + numeric class + name
[$class, $class_id, $name] = getPciClassNameAndId($vf_pci);
if ($includeVfDetails) {
// Vendor:Device formatted string
$vendorFile = "/sys/bus/pci/devices/{$vf_pci}/vendor";
$deviceFile = "/sys/bus/pci/devices/{$vf_pci}/device";
$vendor = is_readable($vendorFile) ? trim(file_get_contents($vendorFile)) : null;
$device = is_readable($deviceFile) ? trim(file_get_contents($deviceFile)) : null;
$vf_entry['vd'] = ($vendor && $device) ? sprintf('%s:%s', substr($vendor, 2), substr($device, 2)) : null;

$vf_entry['class'] = $class;
$vf_entry['class_id'] = $class_id;
// Network interface info
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Variable shadowing overwrites PF class info with VF class info.

The variables $class, $class_id, and $name are first set at line 76 for the Physical Function (PF), but line 85 reassigns them inside the VF loop. After the loop completes, $results[$pci] (lines 127-129) will incorrectly contain the last VF's class information instead of the PF's class info.

🐛 Proposed fix: Use distinct variable names for VF class info
            // Device class + numeric class + name
-            [$class, $class_id, $name] = getPciClassNameAndId($vf_pci);
+            [$vf_class, $vf_class_id, $vf_name] = getPciClassNameAndId($vf_pci);
            if ($includeVfDetails) {
                // Vendor:Device formatted string
                $vendorFile = "/sys/bus/pci/devices/{$vf_pci}/vendor";
                $deviceFile = "/sys/bus/pci/devices/{$vf_pci}/device";
                $vendor = is_readable($vendorFile) ? trim(file_get_contents($vendorFile)) : null;
                $device = is_readable($deviceFile) ? trim(file_get_contents($deviceFile)) : null;
                $vf_entry['vd'] = ($vendor && $device) ? sprintf('%s:%s', substr($vendor, 2), substr($device, 2)) : null;
-                $vf_entry['class'] = $class;
-                $vf_entry['class_id'] = $class_id;
+                $vf_entry['class'] = $vf_class;
+                $vf_entry['class_id'] = $vf_class_id;
📝 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
// Device class + numeric class + name
[$class, $class_id, $name] = getPciClassNameAndId($vf_pci);
if ($includeVfDetails) {
// Vendor:Device formatted string
$vendorFile = "/sys/bus/pci/devices/{$vf_pci}/vendor";
$deviceFile = "/sys/bus/pci/devices/{$vf_pci}/device";
$vendor = is_readable($vendorFile) ? trim(file_get_contents($vendorFile)) : null;
$device = is_readable($deviceFile) ? trim(file_get_contents($deviceFile)) : null;
$vf_entry['vd'] = ($vendor && $device) ? sprintf('%s:%s', substr($vendor, 2), substr($device, 2)) : null;
$vf_entry['class'] = $class;
$vf_entry['class_id'] = $class_id;
// Network interface info
// Device class + numeric class + name
[$vf_class, $vf_class_id, $vf_name] = getPciClassNameAndId($vf_pci);
if ($includeVfDetails) {
// Vendor:Device formatted string
$vendorFile = "/sys/bus/pci/devices/{$vf_pci}/vendor";
$deviceFile = "/sys/bus/pci/devices/{$vf_pci}/device";
$vendor = is_readable($vendorFile) ? trim(file_get_contents($vendorFile)) : null;
$device = is_readable($deviceFile) ? trim(file_get_contents($deviceFile)) : null;
$vf_entry['vd'] = ($vendor && $device) ? sprintf('%s:%s', substr($vendor, 2), substr($device, 2)) : null;
$vf_entry['class'] = $vf_class;
$vf_entry['class_id'] = $vf_class_id;
// Network interface info
🤖 Prompt for AI Agents
In @emhttp/plugins/dynamix/include/SriovHelpers.php around lines 84 - 95, The
PF's class variables ($class, $class_id, $name) are being overwritten by VF loop
assignments from getPciClassNameAndId($vf_pci); rename the VF-specific variables
(e.g., $vf_class, $vf_class_id, $vf_name) inside the VF loop and use those new
names when populating $vf_entry['class'] and $vf_entry['class_id'] so the
original PF $class/$class_id/$name values (set earlier) remain unchanged for
$results[$pci]; update all references in the VF loop accordingly (including
where you set $vf_entry['class'] and $vf_entry['class_id']) to prevent
shadowing.

Comment on lines +424 to 448
$class_id = substr($vrf['class_id'],0,4);
switch ($class_id) {
case "0x02": # Network controller
if (isset($sriov_devices_settings[$pciaddress])) {
$mac = $sriov_devices_settings[$pciaddress]['mac'];
} else {
$mac = null;
}
$placeholder = empty($mac) ? _('Dynamic allocation') : '';
$saved_mac = empty($mac) ? '' : htmlspecialchars($mac, ENT_QUOTES);
$current_mac = empty($vrf['mac']) ? '' : htmlspecialchars(strtoupper($vrf['mac']), ENT_QUOTES);
echo '<label for="mac_address">'._("MAC Address").':</label>';
echo "<input class='narrow' type=\"text\" name=\"vfmac$pciaddress\" id=\"vfmac$pciaddress\" value=\"$saved_mac\" placeholder=\"$placeholder\">";
echo ' <a class="info" href="#" title="'._("Generate MAC").'" onclick="generateMAC(\''.htmlentities($pciaddress).'\'); return false;"><i class="fa fa-refresh mac_generate"> </i></a>';
$action = _("Apply now VFIO and MAC Address");
$saveaction = _("Save MAC and vfio config");
break;
case "0x03": # Display controller
echo '<span>'._($vrf['class']).'</span>';
$mac = null;
$action = _("Apply now VFIO binding");
$saveaction = _("Save Vfio config");
break;
default:
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential undefined variable $mac for unhandled device classes.

If $class_id is neither '0x02' nor '0x03', the switch falls through to the empty default case without setting $mac. This could cause an undefined variable warning on line 460 where $mac is used.

🐛 Proposed fix: Initialize $mac before switch or handle in default
            echo "<tr><td></td><td></td><td></td><td></td><td>";
            $class_id = substr($vrf['class_id'],0,4);
+           $mac = null;
+           $current_mac = '';
+           $action = _("Apply now VFIO binding");
+           $saveaction = _("Save Vfio config");
            switch ($class_id) {   
              case "0x02": # Network controller

Or add explicit handling in default:

              case "0x03": # Display controller
                echo '<span>'._($vrf['class']).'</span>';
-                $mac = null;
                $action = _("Apply now VFIO binding");
                $saveaction = _("Save Vfio config");
                break;
              default:
+               $action = _("Apply now VFIO binding");
+               $saveaction = _("Save Vfio config");
+               break;
            }
📝 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
$class_id = substr($vrf['class_id'],0,4);
switch ($class_id) {
case "0x02": # Network controller
if (isset($sriov_devices_settings[$pciaddress])) {
$mac = $sriov_devices_settings[$pciaddress]['mac'];
} else {
$mac = null;
}
$placeholder = empty($mac) ? _('Dynamic allocation') : '';
$saved_mac = empty($mac) ? '' : htmlspecialchars($mac, ENT_QUOTES);
$current_mac = empty($vrf['mac']) ? '' : htmlspecialchars(strtoupper($vrf['mac']), ENT_QUOTES);
echo '<label for="mac_address">'._("MAC Address").':</label>';
echo "<input class='narrow' type=\"text\" name=\"vfmac$pciaddress\" id=\"vfmac$pciaddress\" value=\"$saved_mac\" placeholder=\"$placeholder\">";
echo ' <a class="info" href="#" title="'._("Generate MAC").'" onclick="generateMAC(\''.htmlentities($pciaddress).'\'); return false;"><i class="fa fa-refresh mac_generate"> </i></a>';
$action = _("Apply now VFIO and MAC Address");
$saveaction = _("Save MAC and vfio config");
break;
case "0x03": # Display controller
echo '<span>'._($vrf['class']).'</span>';
$mac = null;
$action = _("Apply now VFIO binding");
$saveaction = _("Save Vfio config");
break;
default:
}
$class_id = substr($vrf['class_id'],0,4);
$mac = null;
$current_mac = '';
$action = _("Apply now VFIO binding");
$saveaction = _("Save Vfio config");
switch ($class_id) {
case "0x02": # Network controller
if (isset($sriov_devices_settings[$pciaddress])) {
$mac = $sriov_devices_settings[$pciaddress]['mac'];
} else {
$mac = null;
}
$placeholder = empty($mac) ? _('Dynamic allocation') : '';
$saved_mac = empty($mac) ? '' : htmlspecialchars($mac, ENT_QUOTES);
$current_mac = empty($vrf['mac']) ? '' : htmlspecialchars(strtoupper($vrf['mac']), ENT_QUOTES);
echo '<label for="mac_address">'._("MAC Address").':</label>';
echo "<input class='narrow' type=\"text\" name=\"vfmac$pciaddress\" id=\"vfmac$pciaddress\" value=\"$saved_mac\" placeholder=\"$placeholder\">";
echo ' <a class="info" href="#" title="'._("Generate MAC").'" onclick="generateMAC(\''.htmlentities($pciaddress).'\'); return false;"><i class="fa fa-refresh mac_generate"> </i></a>';
$action = _("Apply now VFIO and MAC Address");
$saveaction = _("Save MAC and vfio config");
break;
case "0x03": # Display controller
echo '<span>'._($vrf['class']).'</span>';
$mac = null;
$action = _("Apply now VFIO binding");
$saveaction = _("Save Vfio config");
break;
default:
}
🤖 Prompt for AI Agents
In @emhttp/plugins/dynamix/include/SysDevs.php around lines 424 - 448, The
switch on $class_id can leave $mac undefined for unhandled classes, causing a
warning where $mac is later used (e.g., around the usage near line 460);
initialize $mac before the switch (e.g., $mac = null) or ensure the switch's
default case sets $mac = null (and any related variables like
$action/$saveaction) so $mac is always defined regardless of $class_id,
referencing the existing variables $class_id, $vrf, $pciaddress and the switch
block in SysDevs.php.

Comment on lines +454 to +458
echo ' <a class="info" href="#" title="'._("Action VFs update").'" onclick="applyVFSettings(\''.htmlentities($pciaddress).'\',\''.htmlentities($vd).'\',\''.htmlentities($vfiocheck).'\',\''.$current_mac.'\',\''.$class_id.'\'); return false;"><i title="'.$action.'" class="fa fa-play"></i></a> ';
if ($class_id == "0x02") {
if ($vrf['driver'] != "vfio-pci" ) echo _("Current").": ";
echo $vrf['driver'] == "vfio-pci" ? _("Bound to VFIO") : strtoupper($vrf['mac']);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

$current_mac may be undefined for non-network device classes.

The variable $current_mac is only set in the 0x02 case (line 434), but it's used in applyVFSettings() call on line 454 for all device classes. For 0x03 (Display) devices, this will trigger an undefined variable warning.

🐛 Proposed fix: Initialize $current_mac before the switch
            $class_id = substr($vrf['class_id'],0,4);
+           $current_mac = '';
            switch ($class_id) {   
              case "0x02": # Network controller
🤖 Prompt for AI Agents
In @emhttp/plugins/dynamix/include/SysDevs.php around lines 454 - 458, The echo
calling applyVFSettings uses $current_mac even for non-network classes, causing
an undefined variable; ensure $current_mac is initialized before it's used
(e.g., set a default empty string or null) prior to the switch that sets it for
class_id "0x02", or ensure you pass a safe value when calling applyVFSettings;
update the code around the applyVFSettings echo and the switch that sets
$current_mac so $current_mac is always defined when used with applyVFSettings
(references: applyVFSettings(), $current_mac, $vrf, $class_id).

Comment on lines +203 to +208
function saveVFSettingsConfig(pciId,vd,class_id,interactive=1) {
var message = "_(System Devices)_: _(A reboot is required to apply changes)_";
var mac = document.getElementById("vfmac" + pciId).value;
if (class_id == '0x02') mac = document.getElementById("vfmac" + pciId).value; else mac = null;
var vfio = document.getElementById("vfvfio" + pciId).checked;

$.post( "/plugins/dynamix/include/update.sriov-cfg.php", { type:"sriovsettings", pciid: pciId, vd:vd, vfio:vfio, mac:mac } )
$.post( "/plugins/dynamix/include/update.sriov-cfg.php", { type:"sriovsettings", pciid: pciId, vd:vd, vfio:vfio, mac:mac, class_id:class_id } )
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Implicit global variable mac - missing var/let/const declaration.

On line 205, mac is assigned without a declaration keyword, making it an implicit global variable. This can cause unintended side effects and is considered bad practice.

🐛 Proposed fix: Declare mac with let or const
 function saveVFSettingsConfig(pciId,vd,class_id,interactive=1) {
   var message = "_(System Devices)_: _(A reboot is required to apply changes)_";
-  if (class_id == '0x02') mac = document.getElementById("vfmac" + pciId).value; else mac = null;
+  const mac = (class_id == '0x02') ? document.getElementById("vfmac" + pciId).value : null;
   var vfio = document.getElementById("vfvfio" + pciId).checked;
📝 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
function saveVFSettingsConfig(pciId,vd,class_id,interactive=1) {
var message = "_(System Devices)_: _(A reboot is required to apply changes)_";
var mac = document.getElementById("vfmac" + pciId).value;
if (class_id == '0x02') mac = document.getElementById("vfmac" + pciId).value; else mac = null;
var vfio = document.getElementById("vfvfio" + pciId).checked;
$.post( "/plugins/dynamix/include/update.sriov-cfg.php", { type:"sriovsettings", pciid: pciId, vd:vd, vfio:vfio, mac:mac } )
$.post( "/plugins/dynamix/include/update.sriov-cfg.php", { type:"sriovsettings", pciid: pciId, vd:vd, vfio:vfio, mac:mac, class_id:class_id } )
function saveVFSettingsConfig(pciId,vd,class_id,interactive=1) {
var message = "_(System Devices)_: _(A reboot is required to apply changes)_";
const mac = (class_id == '0x02') ? document.getElementById("vfmac" + pciId).value : null;
var vfio = document.getElementById("vfvfio" + pciId).checked;
$.post( "/plugins/dynamix/include/update.sriov-cfg.php", { type:"sriovsettings", pciid: pciId, vd:vd, vfio:vfio, mac:mac, class_id:class_id } )
🤖 Prompt for AI Agents
In @emhttp/plugins/dynamix/SysDevs.page around lines 203 - 208, In
saveVFSettingsConfig, mac is assigned without a declaration making it an
implicit global; fix this by declaring mac with let (or const if not reassigned)
before use (e.g., initialize let mac = null), then set mac =
document.getElementById("vfmac" + pciId).value only when class_id == '0x02';
ensure vfio remains read from document.getElementById("vfvfio" + pciId).checked
and update the $.post call to use the locally scoped mac variable.

Comment on lines +431 to 435
function applyVFSettings(pciId, vd, currentvfio, currentmac,class_id) {

const message = "_(System Devices)_: _(A reboot is required to apply changes)_";
const mac = document.getElementById("vfmac" + pciId).value;
if (class_id == '0x02') mac = document.getElementById("vfmac" + pciId).value; else mac = null;
const vfio = document.getElementById("vfvfio" + pciId).checked;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Same implicit global variable issue for mac.

Line 434 has the same issue as saveVFSettingsConfig - mac is assigned without a declaration keyword.

🐛 Proposed fix: Declare mac with let or const
 function applyVFSettings(pciId, vd, currentvfio, currentmac,class_id) {

   const message = "_(System Devices)_: _(A reboot is required to apply changes)_";
-  if (class_id == '0x02') mac = document.getElementById("vfmac" + pciId).value; else mac = null;
+  const mac = (class_id == '0x02') ? document.getElementById("vfmac" + pciId).value : null;
   const vfio = document.getElementById("vfvfio" + pciId).checked;
📝 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
function applyVFSettings(pciId, vd, currentvfio, currentmac,class_id) {
const message = "_(System Devices)_: _(A reboot is required to apply changes)_";
const mac = document.getElementById("vfmac" + pciId).value;
if (class_id == '0x02') mac = document.getElementById("vfmac" + pciId).value; else mac = null;
const vfio = document.getElementById("vfvfio" + pciId).checked;
function applyVFSettings(pciId, vd, currentvfio, currentmac,class_id) {
const message = "_(System Devices)_: _(A reboot is required to apply changes)_";
const mac = (class_id == '0x02') ? document.getElementById("vfmac" + pciId).value : null;
const vfio = document.getElementById("vfvfio" + pciId).checked;
🤖 Prompt for AI Agents
In @emhttp/plugins/dynamix/SysDevs.page around lines 431 - 435, The function
applyVFSettings assigns to mac without a declaration, creating an implicit
global; update the code in applyVFSettings to declare mac locally (e.g., use let
mac = ... or const mac = (class_id == '0x02' ? document.getElementById("vfmac" +
pciId).value : null)); mirror the same fix you applied to saveVFSettingsConfig
so mac is not a global variable.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
sbin/sriov (1)

56-56: Typo: /n should be \n for newline.

The escape sequence for newline is \n, not /n.

Proposed fix
-echo -e "Loading settings config from $CFG_VFS/n"
+echo -e "Loading settings config from $CFG_VFS\n"
🤖 Fix all issues with AI agents
In @sbin/sriov-vfsettings.sh:
- Around line 162-165: The error message in the VF_INDEX check wrongly uses $BDF
(the VF address) as the PF; update the string in the if-block that checks
VF_INDEX (the lines around the VF_INDEX, VF_PCI check) to reference the actual
PF variable (e.g. $PF or $PF_BDF) instead of $BDF, and ensure that the chosen PF
variable is defined earlier in the script so the message reads like "Error: VF
index not found for $VF_PCI under PF $PF" (or use the exact PF variable name
used elsewhere, e.g. $PF_BDF).
🧹 Nitpick comments (3)
emhttp/plugins/dynamix/include/SriovHelpers.php (1)

84-95: Variable shadowing is intentional but consider renaming for clarity.

The $class, $class_id, and $name variables from line 76 are shadowed here. While this is intentional to get the VF's class info, the $name is fetched but not added to the VF entry. Consider either:

  1. Using distinct variable names (e.g., $vf_class, $vf_class_id) for clarity
  2. Adding $name to the VF entry if useful, or omit fetching it
emhttp/plugins/dynamix/include/update.sriov-cfg.php (1)

60-60: Consider validating class_id format.

The class_id is read from POST but not validated. While the regex in parseVFSettings() enforces 0x prefix on read, malformed input could be written to the config file.

Proposed validation
 $class_id = _var($_POST,'class_id');
+if (!preg_match('/^0x[0-9a-fA-F]{2}$/', $class_id)) {
+    echo 0;
+    exit;
+}
 $vfio= _var($_POST,'vfio');
sbin/sriov-vfsettings.sh (1)

140-143: Consider replacing ls | grep with a glob-based approach.

Shellcheck flags the ls | grep pattern as potentially problematic with non-alphanumeric filenames. While PCI paths are typically well-structured, a safer approach uses globs.

Proposed alternative
 PF_IFACE=$(basename "$(readlink -f "$PF_PATH/net"/* 2>/dev/null)")
 if [ -z "$PF_IFACE" ]; then
-    PF_IFACE=$(basename "$(ls -d /sys/class/net/*/device 2>/dev/null | grep "$PF_PATH" | head -n1 | cut -d/ -f5)")
+    for netdev in /sys/class/net/*/device; do
+        [ -e "$netdev" ] || continue
+        if [ "$(readlink -f "$netdev")" = "$PF_PATH" ]; then
+            PF_IFACE=$(basename "$(dirname "$netdev")")
+            break
+        fi
+    done
 fi
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 37df059 and b7c5d3a.

📒 Files selected for processing (5)
  • emhttp/plugins/dynamix/include/SriovHelpers.php
  • emhttp/plugins/dynamix/include/apply.sriov-cfg.php
  • emhttp/plugins/dynamix/include/update.sriov-cfg.php
  • sbin/sriov
  • sbin/sriov-vfsettings.sh
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-11-14T15:18:55.567Z
Learnt from: SimonFair
Repo: unraid/webgui PR: 2443
File: emhttp/plugins/dynamix/include/SriovHelpers.php:16-16
Timestamp: 2025-11-14T15:18:55.567Z
Learning: In the file emhttp/plugins/dynamix/include/SriovHelpers.php, the global variable $allowedPCIClass is defined and is used in emhttp/plugins/dynamix/include/SysDevs.php which includes SriovHelpers.php. This variable should not be flagged as unused.

Applied to files:

  • emhttp/plugins/dynamix/include/apply.sriov-cfg.php
  • emhttp/plugins/dynamix/include/SriovHelpers.php
  • emhttp/plugins/dynamix/include/update.sriov-cfg.php
📚 Learning: 2025-12-28T15:54:58.673Z
Learnt from: mgutt
Repo: unraid/webgui PR: 2496
File: emhttp/plugins/dynamix/Browse.page:901-906
Timestamp: 2025-12-28T15:54:58.673Z
Learning: In the unraid/webgui codebase, CSRF validation is centralized in the global auto_prepend_file (local_prepend.php) which runs before every PHP request. Do not add per-script CSRF checks in individual files like Browse.page or Control.php. If a script relies on global validation, ensure it does not duplicate CSRF logic; otherwise extend the central preface to cover the needed checks.

Applied to files:

  • emhttp/plugins/dynamix/include/apply.sriov-cfg.php
  • emhttp/plugins/dynamix/include/SriovHelpers.php
  • emhttp/plugins/dynamix/include/update.sriov-cfg.php
📚 Learning: 2025-10-04T05:22:33.141Z
Learnt from: Squidly271
Repo: unraid/webgui PR: 2421
File: emhttp/plugins/dynamix/include/DefaultPageLayout/MainContentTabless.php:23-0
Timestamp: 2025-10-04T05:22:33.141Z
Learning: In the Unraid webgui repository, `emhttp/webGui` is a symlink that points to `plugins/dynamix`. Therefore, paths using `$docroot/webGui/...` correctly resolve to `$docroot/plugins/dynamix/...` at runtime.

Applied to files:

  • emhttp/plugins/dynamix/include/update.sriov-cfg.php
🧬 Code graph analysis (2)
emhttp/plugins/dynamix/include/apply.sriov-cfg.php (1)
emhttp/plugins/dynamix/include/Wrappers.php (1)
  • _var (106-108)
emhttp/plugins/dynamix/include/update.sriov-cfg.php (1)
emhttp/plugins/dynamix/include/Wrappers.php (1)
  • _var (106-108)
🪛 Shellcheck (0.11.0)
sbin/sriov-vfsettings.sh

[warning] 142-142: Don't use ls | grep. Use a glob or a for loop with a condition to allow non-alphanumeric filenames.

(SC2010)

🔇 Additional comments (13)
sbin/sriov (2)

14-15: LGTM!

The updated comment correctly documents the new 5-field VFSETTINGS format including class_id.


68-70: LGTM!

The 5-field parsing and forwarding to sriov-vfsettings.sh is correctly implemented and consistent with the new format.

emhttp/plugins/dynamix/include/SriovHelpers.php (2)

16-16: LGTM!

Extending the allowed PCI class list to include 0x03 (display class) for GPU SR-IOV support is correct.


312-333: LGTM!

The updated regex and parsing correctly handle the new 5-field VFSETTINGS format with class_id validation.

emhttp/plugins/dynamix/include/apply.sriov-cfg.php (3)

121-126: LGTM!

Correctly gates MAC processing to network-class VFs only (class_id 0x02), which aligns with the design intent.


133-138: LGTM!

The command construction correctly includes class_id in the proper position with proper escaping.


246-267: LGTM!

The conditional logic correctly handles:

  1. MAC changes (network class only) with appropriate driver binding
  2. VFIO-only changes for non-network classes or when MAC is unchanged

The setVfMacAddress call on line 249 already handles the driver binding based on the target VFIO state, so combined MAC+VFIO changes are properly addressed.

emhttp/plugins/dynamix/include/update.sriov-cfg.php (1)

71-76: LGTM!

The entry construction correctly uses the 5-field format for both update and insert operations.

sbin/sriov-vfsettings.sh (5)

64-68: LGTM!

The updated argument count check and usage message correctly document the new 5-parameter interface.


71-92: LGTM!

The argument parsing correctly handles the positional parameters with appropriate pattern matching. The use of -z checks ensures proper ordering of CLASS_ID before VFIO parsing.


167-175: LGTM!

MAC validation is appropriate for network-class VFs. The caller is expected to provide a MAC address (or the reset value 00:00:00:00:00:00).


183-207: LGTM!

The driver unbind/rebind flow around MAC setting is correctly implemented, and the non-network class path appropriately skips MAC operations.


209-214: LGTM!

VFIO binding is correctly applied regardless of device class, which is appropriate since both network and GPU VFs can be passed through to VMs.

Comment on lines +162 to 165
if [ -z "$VF_INDEX" ]; then
echo "Error: VF index not found for $VF_PCI under PF $BDF"
exit 1
fi
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Error message references incorrect variable.

The error message says "under PF $BDF" but $BDF is the VF's address, not the PF's. This could confuse debugging.

Proposed fix
 if [ -z "$VF_INDEX" ]; then
-    echo "Error: VF index not found for $VF_PCI under PF $BDF"
+    echo "Error: VF index not found for $VF_PCI under PF $(basename "$PF_PATH")"
     exit 1
 fi
📝 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 [ -z "$VF_INDEX" ]; then
echo "Error: VF index not found for $VF_PCI under PF $BDF"
exit 1
fi
if [ -z "$VF_INDEX" ]; then
echo "Error: VF index not found for $VF_PCI under PF $(basename "$PF_PATH")"
exit 1
fi
🤖 Prompt for AI Agents
In @sbin/sriov-vfsettings.sh around lines 162 - 165, The error message in the
VF_INDEX check wrongly uses $BDF (the VF address) as the PF; update the string
in the if-block that checks VF_INDEX (the lines around the VF_INDEX, VF_PCI
check) to reference the actual PF variable (e.g. $PF or $PF_BDF) instead of
$BDF, and ensure that the chosen PF variable is defined earlier in the script so
the message reads like "Error: VF index not found for $VF_PCI under PF $PF" (or
use the exact PF variable name used elsewhere, e.g. $PF_BDF).

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