From ff6a5adb50049fb865a68517715aeb2aade59cff Mon Sep 17 00:00:00 2001
From: SimonFair <39065407+SimonFair@users.noreply.github.com>
Date: Thu, 13 Nov 2025 16:29:40 +0000
Subject: [PATCH] Update WIP
---
emhttp/plugins/dynamix/SysDevs.page | 158 +++--
emhttp/plugins/dynamix/api/SysDevs.page | 583 ++++++++++++++++++
.../plugins/dynamix/include/SriovHelpers.php | 109 ++--
.../dynamix/include/SysDriversInit.php | 2 +-
.../dynamix/include/apply.sriov-cfg.php | 86 ++-
.../dynamix/include/update.sriov-cfg.php | 10 +-
sbin/sriov | 2 +-
sbin/sriov-setvfs.sh | 2 +-
sbin/sriov-vfsettings.sh | 5 +
9 files changed, 798 insertions(+), 159 deletions(-)
create mode 100644 emhttp/plugins/dynamix/api/SysDevs.page
diff --git a/emhttp/plugins/dynamix/SysDevs.page b/emhttp/plugins/dynamix/SysDevs.page
index 95225e9f0..53da3f50e 100644
--- a/emhttp/plugins/dynamix/SysDevs.page
+++ b/emhttp/plugins/dynamix/SysDevs.page
@@ -55,19 +55,19 @@ function saveVFSettingsConfig(pciId,vd,interactive=1) {
$.post( "/plugins/dynamix/include/update.sriov-cfg.php", { type:"sriovsettings", pciid: pciId, vd:vd, vfio:vfio, mac:mac } )
.done(function(d) {
if (d==1) {
- addRebootNotice(message);
- document.getElementById("warning").innerHTML = "_(ALERT)_: _(Changes saved)_. _(Reboot to take effect)_. ";
+ //addRebootNotice(message);
+ // document.getElementById("warning").innerHTML = "_(ALERT)_: _(Changes saved)_. _(Reboot to take effect)_. ";
if (interactive == 1)
swal({
- title: "VF Settings",
- text: "Configuration saved.",
+ title: _("VF Settings"),
+ text: _("Configuration saved") + ".",
type: "success",
timer: 3000,
showConfirmButton: false
});
} else {
- removeRebootNotice(message);
- document.getElementById("warning").innerHTML = "_(No changes)_. ";
+//removeRebootNotice(message);
+//document.getElementById("warning").innerHTML = "_(No changes)_. ";
}
});
}
@@ -78,19 +78,19 @@ function saveVFsConfig(pciId,vd,interactive=1) {
$.post( "/plugins/dynamix/include/update.sriov-cfg.php", { type:"sriov", pciid: pciId, vd:vd, numvfs:numvfs } )
.done(function(d) {
if (d==1) {
- addRebootNotice(message);
- document.getElementById("warning").innerHTML = "_(ALERT)_: _(Changes saved)_. _(Reboot to take effect)_. ";
+ // addRebootNotice(message);
+ // document.getElementById("warning").innerHTML = "_(ALERT)_: _(Changes saved)_. _(Reboot to take effect)_. ";
if (interactive == 1)
swal({
title: "VFs",
- text: "Configuration saved.",
+ text: _("Configuration saved") + ".",
type: "success",
timer: 3000,
showConfirmButton: false
});
} else {
- removeRebootNotice(message);
- document.getElementById("warning").innerHTML = "_(No changes)_. ";
+ // removeRebootNotice(message);
+ // document.getElementById("warning").innerHTML = "_(No changes)_. ";
}
if (interactive == 1) $('#t1').load('/webGui/include/SysDevs.php', { table: 't1' });
});
@@ -99,7 +99,7 @@ function saveVFsConfig(pciId,vd,interactive=1) {
function generateMAC(pciId) {
if (!pciId) {
- swal("Error", "No PCI ID provided to generateMAC()", "error");
+ swal("Error", _("No PCI ID provided to generateMAC()"), "error");
return;
}
@@ -107,7 +107,7 @@ function generateMAC(pciId) {
var pciPattern = /^([0-9a-fA-F]{4}):([0-9a-fA-F]{2}):([0-9a-fA-F]{2})\.([0-7])$/;
var match = pciId.match(pciPattern);
if (!match) {
- swal("Invalid PCI ID", "Expected format: 0000:03:00.2", "error");
+ swal(_("Invalid PCI ID"), _("Expected format: 0000:03:00.2"), "error");
return;
}
@@ -314,11 +314,7 @@ function applyVFSettings(pciId, vd, currentvfio, currentmac) {
return;
}
- saveVFSettingsConfig(pciId, vd, 0);
-
-
- doVFSettingApply(pciId, vd, vfio, mac, currentvfio,currentmac,message);
-
+ doVFSettingApply(pciId, vd, vfio, mac, currentvfio,currentmac,message);
})
.fail(function (xhr, status, error) {
console.error("Active check failed:", status, error, xhr.responseText);
@@ -370,9 +366,9 @@ function doVFSettingApply(pciId, vd, vfio, mac, currentvfio, currentmac, message
// Handle structured PHP result
if (data.success) {
- addRebootNotice(message);
- document.getElementById("warning").innerHTML =
- "_(ALERT)_: _(Changes saved)_. _(Reboot to take effect)_. ";
+ //addRebootNotice(message);
+ // document.getElementById("warning").innerHTML =
+ // "_(ALERT)_: _(Changes saved)_. _(Reboot to take effect)_. ";
saveVFSettingsConfig(pciId, vd, 0);
swal({
title: "Update Complete",
@@ -382,8 +378,8 @@ function doVFSettingApply(pciId, vd, vfio, mac, currentvfio, currentmac, message
showConfirmButton: false
});
} else {
- removeRebootNotice(message);
- const errorMsg = data.error || "No changes detected or operation failed.";
+ //removeRebootNotice(message);
+ // const errorMsg = data.error || "No changes detected or operation failed.";
document.getElementById("warning").innerHTML = "" + errorMsg + " ";
swal({
@@ -407,6 +403,18 @@ function doVFSettingApply(pciId, vd, vfio, mac, currentvfio, currentmac, message
});
}
+ // Helper: safely stringify nested structures
+ function formatDetails(details) {
+ if (details == null) return "";
+ if (typeof details === "string") return details;
+ if (Array.isArray(details))
+ return details.map(formatDetails).join("\n");
+ if (typeof details === "object")
+ return Object.entries(details)
+ .map(([k, v]) => `${k}: ${formatDetails(v)}`)
+ .join("\n\n");
+ return String(details);
+ }
function doVFApply(pciId, vd, numvfs, message) {
// Show "updating" alert
@@ -426,55 +434,73 @@ function doVFApply(pciId, vd, numvfs, message) {
vd: vd,
numvfs: numvfs
})
-.done(function (data) {
- // Normalize to JSON object
- if (typeof data === "string") {
- try { data = JSON.parse(data); }
- catch (e) {
- data = { success: false, error: "Invalid JSON: " + e.message };
+ .done(function (data) {
+ // Parse JSON safely
+ if (typeof data === "string") {
+ try { data = JSON.parse(data); }
+ catch (e) {
+ data = { success: false, error: "Invalid JSON: " + e.message };
+ }
}
- }
- // Extract a clean message
- let msg = "Configuration successfully applied.";
+ // Helper: recursively format details to plain text
+ function formatDetails(obj, indent = 0) {
+ const pad = " ".repeat(indent);
+ if (obj == null) return "";
+ if (typeof obj === "string") return pad + obj;
+ if (typeof obj === "number" || typeof obj === "boolean") return pad + obj;
+ if (Array.isArray(obj)) return obj.map(x => formatDetails(x, indent)).join("\n");
+ if (typeof obj === "object") {
+ return Object.entries(obj).map(([key, val]) => {
+ if (typeof val === "object" && val !== null) {
+ // Special case for VF result objects
+ if ("success" in val || "error" in val || "details" in val) {
+ const symbol = val.success ? "✔" : "✖";
+ const msg = val.error || val.details || "";
+ return `${pad}${key}\n${pad} ${symbol} ${msg}`;
+ }
+ return `${pad}${key}:\n${formatDetails(val, indent + 1)}`;
+ }
+ return `${pad}${key}: ${val}`;
+ }).join("\n");
+ }
+ return pad + String(obj);
+ }
-if (data.error) {
- msg = "Error: " + data.error;
-} else if (data.details) {
- if (Array.isArray(data.details)) {
- msg = data.details.join("\n");
- } else if (typeof data.details === "object") {
- msg = Object.entries(data.details)
- .map(([k, v]) => `${k}: ${JSON.stringify(v, null, 2)}`)
- .join("\n\n");
- } else if (typeof data.details === "string") {
- msg = data.details;
- }
-}
+ // Build message
+ let msg = "";
+ if (data.error) {
+ msg = "Error: " + data.error;
+ } else if (data.details) {
+ msg = formatDetails(data.details);
+ } else {
+ msg = "Configuration successfully applied.";
+ }
- // Pick alert type
+ // Show alert
const ok = data.success === true || data.success === 1;
- saveVFsConfig(pciId, vd, 0);
- // Show success or failure alert
- swal({
- title: data.success ? "Update Complete" : "Update Failed",
- text: msg,
- type: data.success ? "success" : "error",
- timer: data.success ? 3000 : null,
- showConfirmButton: !data.success
- });
- // Always reload the table after handling
- $('#t1').load('/webGui/include/SysDevs.php', { table: 't1' });
- })
- .fail(function (xhr, status, error) {
- swal({
- title: "Network Error",
- text: "Failed to communicate with the server.\n" + (error || status),
- type: "error",
- showConfirmButton: true
- });
- });
+ saveVFsConfig(pciId, vd, 0);
+
+ swal({
+ title: ok ? "Update Complete" : "Update Failed",
+ text: msg,
+ type: ok ? "success" : "error",
+ timer: ok ? 3000: null,
+ showConfirmButton: !ok
+ });
+
+ // Reload table
+ $('#t1').load('/webGui/include/SysDevs.php', { table: 't1' });
+})
+.fail(function (xhr, status, error) {
+ swal({
+ title: "Network Error",
+ text: "Failed to communicate with the server.\n" + (error || status),
+ type: "error",
+ showConfirmButton: true
+ });
+});
}
diff --git a/emhttp/plugins/dynamix/api/SysDevs.page b/emhttp/plugins/dynamix/api/SysDevs.page
new file mode 100644
index 000000000..2d4686aac
--- /dev/null
+++ b/emhttp/plugins/dynamix/api/SysDevs.page
@@ -0,0 +1,583 @@
+Menu="UNRAID-OS"
+Title="System Devices"
+Icon="icon-hardware"
+Tag="server"
+---
+
+
+
+
+ 0):?>
+**_(PCI Devices and IOMMU Groups)_**
+
+**_(PCI Devices (No IOMMU Groups Available))_**
+
+
+:sysdevs_iommu_groups_help:
+
+
+
_(Warning)_: _(Your system has booted with the PCIe ACS Override setting enabled)_. _(The below list doesn't not reflect the way IOMMU would naturally group devices)_.
+=my_hyperlink(_("To see natural IOMMU groups for your hardware, go to the [VM Manager] page and set the **PCIe ACS override** setting to **Disabled**"),'/Settings/VMSettings')?>.
+
+
+
+
+**_(CPU Thread Pairings)_**
+
+:sysdevs_thread_pairings_help:
+
+
+
+**_(USB Devices)_**
+
+:sysdevs_usb_devices_help:
+
+
+
+**_(SCSI Devices)_**
+
+:sysdevs_scsi_devices_help:
+
+
+
diff --git a/emhttp/plugins/dynamix/include/SriovHelpers.php b/emhttp/plugins/dynamix/include/SriovHelpers.php
index c5125bec0..6b2017979 100644
--- a/emhttp/plugins/dynamix/include/SriovHelpers.php
+++ b/emhttp/plugins/dynamix/include/SriovHelpers.php
@@ -13,16 +13,11 @@
?>
-
-#$allowedPCIClass = ['0x02','0x03'];
$allowedPCIClass = ['0x02'];
$docroot ??= ($_SERVER['DOCUMENT_ROOT'] ?: '/usr/local/emhttp');
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt.php";
require_once "$docroot/plugins/dynamix.vm.manager/include/libvirt_helpers.php";
-
-
-
/**
* Get available kernel modules for this PCI device based on its modalias
*/
@@ -35,7 +30,6 @@ function getModulesFromModalias(string $pci): array {
return $out ? preg_split('/\s+/', $out) : [];
}
-
/**
* Enumerate SR-IOV capable PCI devices (keyed by PCI address).
*
@@ -150,14 +144,14 @@ function rebindVfDriver($vf, $sriov, $target = 'original')
$res = ['pci'=>$vf,'success'=>false,'error'=>null,'details'=>[]];
$vf_path = "/sys/bus/pci/devices/$vf";
$physfn = "$vf_path/physfn";
- if (!is_link($physfn)) return $res + ['error'=>"Missing physfn link"];
+ if (!is_link($physfn)) return $res + ['error'=>_("Missing physfn link")];
$pf = basename(readlink($physfn));
$vf_info = $sriov[$pf]['vfs'][$vf] ?? null;
- if (!$vf_info) return $res + ['error'=>"VF not found in \$sriov for PF $pf"];
+ if (!$vf_info) return $res + ['error'=>_("VF not found in sriov for PF")." $pf"];
$orig_mod = $vf_info['modules'][0] ?? $sriov[$pf]['module'] ?? null;
$curr_drv = $vf_info['driver'] ?? null;
- if (!$orig_mod) return $res + ['error'=>"No module info for $vf"];
+ if (!$orig_mod) return $res + ['error'=>_("No module info for")." $vf"];
$drv_override = "$vf_path/driver_override";
@@ -187,13 +181,12 @@ function rebindVfDriver($vf, $sriov, $target = 'original')
$bound = basename(readlink($drv_link));
if ($bound === $new_drv) {
$res['success'] = true;
- $res['details'][] = "Bound to $new_drv";
+ $res['details'][] = _("Bound to")." $new_drv";
return $res;
}
- return $res + ['error'=>"Bound to $bound instead of $new_drv"];
+ return $res + ['error'=> sprintf(_("Bound to %s instead of %s"),$bound,$new_drv)];
}
-
- return $res + ['error'=>"No driver link after reprobe"];
+ return $res + ['error'=>_("No driver link after reprobe")];
}
@@ -268,7 +261,7 @@ function getVfListByIommuGroup(): array {
$iommu_group = "unknown";
}
- $groups[] = "IOMMU group " . $iommu_group;
+ $groups[] = "IOMMU group " . $iommu_group;
$groups[] = $vf_pci;
}
@@ -280,28 +273,26 @@ function getVfListByIommuGroup(): array {
// Parse SR-IOV VF counts
// ----------------------
function parseVFvalues() {
- $sriov_devices = [];
- $DBDF_SRIOV_REGEX = '/^[[:xdigit:]]{4}:[[:xdigit:]]{2}:[[:xdigit:]]{2}\.[[:xdigit:]]\|[[:xdigit:]]{4}:[[:xdigit:]]{4}\|[[:digit:]]+$/';
- if (is_file("/boot/config/sriov.cfg")) {
- $file = trim(file_get_contents("/boot/config/sriov.cfg"));
- $file = preg_replace('/^VFS=/', '', $file); // Remove prefix
- $entries = preg_split('/\s+/', $file, -1, PREG_SPLIT_NO_EMPTY);
+ $sriov_devices = [];
+ $DBDF_SRIOV_REGEX = '/^[[:xdigit:]]{4}:[[:xdigit:]]{2}:[[:xdigit:]]{2}\.[[:xdigit:]]\|[[:xdigit:]]{4}:[[:xdigit:]]{4}\|[[:digit:]]+$/';
+ if (is_file("/boot/config/sriov.cfg")) {
+ $file = trim(file_get_contents("/boot/config/sriov.cfg"));
+ $file = preg_replace('/^VFS=/', '', $file); // Remove prefix
+ $entries = preg_split('/\s+/', $file, -1, PREG_SPLIT_NO_EMPTY);
- foreach ($entries as $entry) {
- if (preg_match($DBDF_SRIOV_REGEX, $entry)) {
- // Format: ||
- [$dbdf, $ven_dev, $vf_count] = explode('|', $entry);
- $sriov_devices[$dbdf] = [
- 'dbdf' => $dbdf,
- 'vendor' => $ven_dev,
- 'vf_count' => (int)$vf_count,
- ];
- }
- }
-
- # $sriov_devices = array_values(array_unique($sriov_devices, SORT_REGULAR));
+ foreach ($entries as $entry) {
+ if (preg_match($DBDF_SRIOV_REGEX, $entry)) {
+ // Format: ||
+ [$dbdf, $ven_dev, $vf_count] = explode('|', $entry);
+ $sriov_devices[$dbdf] = [
+ 'dbdf' => $dbdf,
+ 'vendor' => $ven_dev,
+ 'vf_count' => (int)$vf_count,
+ ];
+ }
+ }
+ }
return $sriov_devices;
- }
}
// ---------------------------------
@@ -311,27 +302,25 @@ function parseVFSettings() {
$sriov_devices_settings = [];
$DBDF_SRIOV_SETTINGS_REGEX = '/^[[:xdigit:]]{4}:[[:xdigit:]]{2}:[[:xdigit:]]{2}\.[[:xdigit:]]\|[[:xdigit:]]{4}:[[:xdigit:]]{4}\|[01]\|([[:xdigit:]]{2}:){5}[[:xdigit:]]{2}$/';
if (is_file("/boot/config/sriovvfs.cfg")) {
- $file = trim(file_get_contents("/boot/config/sriovvfs.cfg"));
- $file = preg_replace('/^VFSETTINGS=/', '', $file); // Remove prefix
- $entries = preg_split('/\s+/', $file, -1, PREG_SPLIT_NO_EMPTY);
+ $file = trim(file_get_contents("/boot/config/sriovvfs.cfg"));
+ $file = preg_replace('/^VFSETTINGS=/', '', $file); // Remove prefix
+ $entries = preg_split('/\s+/', $file, -1, PREG_SPLIT_NO_EMPTY);
- foreach ($entries as $entry) {
- if (preg_match($DBDF_SRIOV_SETTINGS_REGEX, $entry)) {
- // Format: |||
- [$dbdf, $ven_dev, $vfio_flag, $mac] = explode('|', $entry);
- if ($mac == "00:00:00:00:00:00") $mac = "";
- $sriov_devices_settings[$dbdf] = [
- 'dbdf' => $dbdf,
- 'vendor' => $ven_dev,
- 'vfio' => (int)$vfio_flag,
- 'mac' => strtoupper($mac),
- ];
- }
- }
-
- # $sriov_devices_settings = array_values(array_unique($sriov_devices_settings, SORT_REGULAR));
+ foreach ($entries as $entry) {
+ if (preg_match($DBDF_SRIOV_SETTINGS_REGEX, $entry)) {
+ // Format: |||
+ [$dbdf, $ven_dev, $vfio_flag, $mac] = explode('|', $entry);
+ if ($mac == "00:00:00:00:00:00") $mac = "";
+ $sriov_devices_settings[$dbdf] = [
+ 'dbdf' => $dbdf,
+ 'vendor' => $ven_dev,
+ 'vfio' => (int)$vfio_flag,
+ 'mac' => strtoupper($mac),
+ ];
+ }
+ }
+ }
return $sriov_devices_settings;
- }
}
/**
@@ -364,14 +353,14 @@ function setVfMacAddress(string $vf_pci, string $mac, ?string $rebindDriver = nu
];
if (!is_dir($vf_path)) {
- $result['error'] = "VF path not found: $vf_path";
+ $result['error'] = _("VF path not found").": $vf_path";
return $result;
}
// --- Find parent PF (Physical Function) ---
$pf_link = "$vf_path/physfn";
if (!is_link($pf_link)) {
- $result['error'] = "No PF link for $vf_pci (not an SR-IOV VF?)";
+ $result['error'] = sprintf("No PF link for %s (not an SR-IOV VF?)",$vf_pci);
return $result;
}
$pf_pci = basename(readlink($pf_link));
@@ -381,7 +370,7 @@ function setVfMacAddress(string $vf_pci, string $mac, ?string $rebindDriver = nu
$pf_net = glob("/sys/bus/pci/devices/{$pf_pci}/net/*");
$pf_iface = ($pf_net && isset($pf_net[0])) ? basename($pf_net[0]) : null;
if (!$pf_iface) {
- $result['error'] = "Could not detect PF interface for $pf_pci";
+ $result['error'] = _("Could not detect PF interface for")." $pf_pci";
return $result;
}
$result['pf_iface'] = $pf_iface;
@@ -389,7 +378,7 @@ function setVfMacAddress(string $vf_pci, string $mac, ?string $rebindDriver = nu
// --- Detect VF index ---
$vf_index = getVfIndex($pf_pci, $vf_pci);
if ($vf_index === null) {
- $result['error'] = "Could not determine VF index for $vf_pci under $pf_pci";
+ $result['error'] = sprintf(_("Could not determine VF index for %s under %s"),$vf_pci,$pf_pci);
return $result;
}
$result['vf_index'] = $vf_index;
@@ -406,7 +395,7 @@ function setVfMacAddress(string $vf_pci, string $mac, ?string $rebindDriver = nu
file_put_contents($unbind_path, $vf_pci);
$result['unbind'] = true;
} else {
- $result['error'] = "Cannot unbind VF $vf_pci from $vf_driver (permissions)";
+ $result['error'] = sprintf(_("Cannot unbind VF %s from %s (permissions)"),$vf_pci,$vf_driver);
return $result;
}
}
@@ -424,7 +413,7 @@ function setVfMacAddress(string $vf_pci, string $mac, ?string $rebindDriver = nu
if ($ret === 0) {
$result['mac_set'] = true;
} else {
- $result['error'] = "Failed to set MAC: " . implode("; ", $output);
+ $result['error'] = _("Failed to set MAC").": " . implode("; ", $output);
}
// --- Rebind logic ---
@@ -437,7 +426,7 @@ function setVfMacAddress(string $vf_pci, string $mac, ?string $rebindDriver = nu
$result['rebind'] = true;
$result['driver_after'] = $target_driver;
} else {
- $result['error'] = "Cannot rebind VF $vf_pci to $target_driver (permissions)";
+ $result['error'] = sprintf(_("Cannot rebind VF %s to %s (permissions)"),$vf_pci,$target_driver);
}
}
}
diff --git a/emhttp/plugins/dynamix/include/SysDriversInit.php b/emhttp/plugins/dynamix/include/SysDriversInit.php
index 03e1c83a2..afd9272b2 100755
--- a/emhttp/plugins/dynamix/include/SysDriversInit.php
+++ b/emhttp/plugins/dynamix/include/SysDriversInit.php
@@ -1,4 +1,4 @@
- #!/usr/bin/php
+#!/usr/bin/php
$details
];
- echo json_encode($response, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
+ $json = json_encode($response, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
+ file_put_contents("/tmp/vfactionjson",$json);
+ echo $json;
exit;
}
+function safe_file_put_contents($path, $data)
+{
+ // Check that the file or its directory is writable
+ $dir = is_dir($path) ? $path : dirname($path);
+ if (!is_writable($dir)) {
+ throw new RuntimeException("Path not writable: $path");
+ }
+
+ $result = @file_put_contents($path, $data);
+ if ($result === false) {
+ $err = error_get_last();
+ throw new RuntimeException("Failed to write to $path: " . ($err['message'] ?? 'unknown error'));
+ }
+
+ return $result;
+}
+
function action_settings($pciid)
{
@@ -64,6 +84,8 @@ function action_settings($pciid)
// Skip if no action needed
if ($vfio == 0 && $mac == "") continue;
+ if ($mac == "") $mac="00:00:00:00:00:00";
+
$cmd = "/usr/local/sbin/sriov-vfsettings.sh " .
escapeshellarg($vfpci) . " " .
escapeshellarg($vf['vd']) . " " .
@@ -77,19 +99,17 @@ function action_settings($pciid)
// Clean output: remove blank lines and trim whitespace
$output = array_filter(array_map('trim', $output));
- file_put_contents("/tmp/vfaction", "$ret\n$cmd\n" . json_encode($output) . "\n");
-
if ($ret !== 0) {
// Only include relevant lines for error reporting
- $results[] = [
+ $results[$vfpci] = [
'success' => false,
- 'error' => implode("\n", $output) ?: "Unknown error (exit code $ret)"
+ 'error' => implode("\n", $output) ?: sprintf(_("Unknown error (exit code %s)"),$ret)
];
} else {
// Success: include minimal details or last few lines
- $results[] = [
+ $results[$vfpci] = [
'success' => true,
- 'details' => 'Applied VF settings'
+ 'details' => _('Applied VF settings')
];
}
}
@@ -103,47 +123,63 @@ $pciid = _var($_POST, 'pciid');
$vd = _var($_POST, 'vd');
if (!isset($pciid) || !isset($vd)) {
- echo json_response(false, "Missing PCI ID or virtual device");
+ echo json_response(false, _("Missing PCI ID or virtual device"));
exit;
}
+
+
switch ($type) {
// --------------------------------------------------------
// SR-IOV enable/disable & VF count changes
// --------------------------------------------------------
case "sriov":
- $numvfs = _var($_POST, 'numvfs');
+ $numvfs = _var($_POST, 'numvfs');
$currentvfs = _var($_POST, 'currentvfs');
- $filepath = "/sys/bus/pci/devices/$pciid/sriov_numvfs";
+ $filepath = "/sys/bus/pci/devices/$pciid/sriov_numvfs";
if (!is_writable($filepath)) {
- echo json_response(false, "Cannot modify $filepath");
- break;
+ json_response(false, "Cannot modify $filepath");
}
try {
+ // Disable all VFs
if ($numvfs == 0) {
- file_put_contents($filepath, 0);
- echo json_response(true, null, ["Disabled all VFs"]);
- break;
+ safe_file_put_contents($filepath, 0);
+ json_response(true, null, [_("Disabled all VFs")]);
}
+ // Change VF count
if ($numvfs != $currentvfs) {
- file_put_contents($filepath, 0);
- file_put_contents($filepath, $numvfs);
+ safe_file_put_contents($filepath, 0);
+ safe_file_put_contents($filepath, $numvfs);
+
$results = action_settings($pciid);
- echo json_response(true, null, ["Changed VF count to $numvfs", $results]);
- break;
+
+ $all_success = array_reduce($results, fn($ok, $r) => $ok && ($r['success'] ?? false), true);
+
+ safe_file_put_contents(
+ "/tmp/vfactionres2",
+ json_encode(['all_success' => $all_success, 'results' => $results], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
+ );
+
+ json_response(true, null, [sprintf(_("Changed VF count to %d"), $numvfs), $results]);
}
- file_put_contents($filepath, $numvfs);
+ // Reapply VF settings
+ safe_file_put_contents($filepath, $numvfs);
$results = action_settings($pciid);
- echo json_response(true, null, ["Reapplied VF settings", $results]);
+ json_response(true, null, [_("Reapplied VF settings"), $results]);
+
} catch (Throwable $e) {
- echo json_response(false, "Failed to change VF count: " . $e->getMessage());
+ // Log internal details for debugging
+ @file_put_contents("/tmp/vfaction_error.log", date('c') . " " . $e->getMessage() . "\n", FILE_APPEND);
+
+ json_response(false, _("Failed to change VF count") . ": " . $e->getMessage());
}
break;
+
// --------------------------------------------------------
// VF driver binding, MAC changes
// --------------------------------------------------------
@@ -181,9 +217,9 @@ switch ($type) {
}
// Nothing changed
- echo json_response(true, null, ["No changes detected"]);
+ echo json_response(true, null, [_("No changes detected")]);
} catch (Throwable $e) {
- echo json_response(false, "Error applying VF settings: " . $e->getMessage());
+ echo json_response(false, _("Error applying VF settings").": ".$e->getMessage());
}
break;
@@ -197,7 +233,7 @@ switch ($type) {
break;
default:
- echo json_response(false, "Unknown request type: $type");
+ echo json_response(false, _("Unknown request type").": $type");
break;
}
diff --git a/emhttp/plugins/dynamix/include/update.sriov-cfg.php b/emhttp/plugins/dynamix/include/update.sriov-cfg.php
index c4e214774..cf818ea1f 100644
--- a/emhttp/plugins/dynamix/include/update.sriov-cfg.php
+++ b/emhttp/plugins/dynamix/include/update.sriov-cfg.php
@@ -49,7 +49,7 @@ if (isset($pciid) && isset($vd)) {
}
}
}
- if (!$found) $newexplode[] = $newelement_check.$numvfs;
+ if (!$found && $numvfs != "0") $newexplode[] = $newelement_check.$numvfs;
$new = "VFS=".implode(" ",$newexplode);
$file = $sriov;
break;
@@ -73,10 +73,10 @@ if (isset($pciid) && isset($vd)) {
}
}
}
- if (!$found) $newexplode[] = $newelement_check.$vfio."|".$mac;
- $new = "VFSETTINGS=".implode(" ",$newexplode);
- $file = $sriovvfs;
- break;
+ if (!$found && $vfio != 0) $newexplode[] = $newelement_check.$vfio."|".$mac;
+ $new = "VFSETTINGS=".implode(" ",$newexplode);
+ $file = $sriovvfs;
+ break;
}
}
diff --git a/sbin/sriov b/sbin/sriov
index 8884260d7..815009c83 100755
--- a/sbin/sriov
+++ b/sbin/sriov
@@ -14,7 +14,7 @@
# accepts space-separated list of or followed by an optional "|" and |
# example:VFSETTINGS=0000:04:11.5|8086:1520|62:00:04:11:05:01
-SRIOV_ENABLED_FILE=/boot/config/sriov_enabled
+SRIOV_DISABLED_FILE=/boot/config/sriov_disabled
if [[ -f $SRIOV_DISABLED_FILE ]] ; then
echo 'SRIOV Processing disabled.'
exit
diff --git a/sbin/sriov-setvfs.sh b/sbin/sriov-setvfs.sh
index 204c4f87b..44f8c404a 100755
--- a/sbin/sriov-setvfs.sh
+++ b/sbin/sriov-setvfs.sh
@@ -53,7 +53,7 @@ if [[ $EUID -ne 0 ]]; then
exit 1
fi
-if [[ -z "$@" ]]; then
+if [[ $# -eq 0 ]]; then
echo "Error: Please provide Domain:Bus:Device.Function (dddd:bb:dd.f) and/or Vendor:Device (vvvv:dddd)" 1>&2
exit 1
fi
diff --git a/sbin/sriov-vfsettings.sh b/sbin/sriov-vfsettings.sh
index d9ca60457..6bc15f698 100755
--- a/sbin/sriov-vfsettings.sh
+++ b/sbin/sriov-vfsettings.sh
@@ -90,6 +90,11 @@ for arg in "$@"; do
fi
done
+if [[ -z "$BDF" ]]; then
+ echo "Error: No valid Bus:Device.Function provided" 1>&2
+ exit 1
+fi
+
TARGET_DEV_SYSFS_PATH="/sys/bus/pci/devices/$BDF"
if [[ ! -d $TARGET_DEV_SYSFS_PATH ]]; then