diff options
author | Simon Rettberg | 2021-09-24 12:40:42 +0200 |
---|---|---|
committer | Simon Rettberg | 2021-09-24 12:40:42 +0200 |
commit | c32dd3654eaf99121cc44a3f828883a69e7760e5 (patch) | |
tree | fee100b5ed24a9a5c679c586e72194b59e03221f | |
parent | [statistics/passthrough] Fixes (diff) | |
download | slx-admin-c32dd3654eaf99121cc44a3f828883a69e7760e5.tar.gz slx-admin-c32dd3654eaf99121cc44a3f828883a69e7760e5.tar.xz slx-admin-c32dd3654eaf99121cc44a3f828883a69e7760e5.zip |
[statistics/passthrough] WIP
-rw-r--r-- | modules-available/passthrough/inc/passthrough.inc.php | 17 | ||||
-rw-r--r-- | modules-available/passthrough/page.inc.php | 39 | ||||
-rw-r--r-- | modules-available/passthrough/templates/hardware-list.html | 39 | ||||
-rw-r--r-- | modules-available/statistics/api.inc.php | 2 | ||||
-rw-r--r-- | modules-available/statistics/inc/hardwareinfo.inc.php | 19 | ||||
-rw-r--r-- | modules-available/statistics/inc/hardwareparser.inc.php | 6 | ||||
-rw-r--r-- | modules-available/statistics/inc/hardwarequery.inc.php | 22 | ||||
-rw-r--r-- | modules-available/statistics/inc/pciid.inc.php | 15 | ||||
-rw-r--r-- | modules-available/statistics/page.inc.php | 24 |
9 files changed, 156 insertions, 27 deletions
diff --git a/modules-available/passthrough/inc/passthrough.inc.php b/modules-available/passthrough/inc/passthrough.inc.php index 51fe7214..524aea5e 100644 --- a/modules-available/passthrough/inc/passthrough.inc.php +++ b/modules-available/passthrough/inc/passthrough.inc.php @@ -3,16 +3,27 @@ class Passthrough { - public static function getGroupDropdown(array $row): array + public static function getGroupDropdown(array &$row): array { + $out = []; + if ($row['class'] === '0300') { + foreach (['GPU', 'GVT'] as $id) { + $out[] = [ + 'ptid' => $id, + 'ptname' => $id, + 'selected' => ($row['@PASSTHROUGH'] === $id ? 'selected' : ''), + ]; + } + return $out; + } static $list = false; if ($list === false) { $list = Database::queryKeyValueList("SELECT groupid, title FROM passthrough_group ORDER BY groupid"); self::ensurePrepopulated($list); } - $out = []; + $row['custom_groups'] = true; foreach ($list as $id => $title) { - if ($row['class'] !== '0300' && ($id === 'GPU' || $id === 'GVT')) + if ($id === 'GPU' || $id === 'GVT') continue; $item = ['ptid' => $id, 'ptname' => $id . ' (' . $title . ')']; if ($row['@PASSTHROUGH'] === $id) { diff --git a/modules-available/passthrough/page.inc.php b/modules-available/passthrough/page.inc.php index 33f2e4a3..0911550c 100644 --- a/modules-available/passthrough/page.inc.php +++ b/modules-available/passthrough/page.inc.php @@ -87,11 +87,42 @@ class Page_Passthrough extends Page return 1; return hexdec($a) - hexdec($b); }); - foreach ($rows as &$row) { - $row['vendor_name'] = PciId::getPciId(PciId::VENDOR, $row['vendor'] ?? '', true); - $row['device_name'] = PciId::getPciId(PciId::DEVICE, $row['vendor'] . ':' . $row['device'], true); + $finalRows = []; + $missing = []; + $lastClass = ''; + foreach ($rows as $row) { + if ($row['class'] !== $lastClass) { + // Add class row header + $lastClass = $row['class']; + $finalRows[] = [ + 'class' => $row['class'], + 'class_name' => PciId::getPciId(PciId::DEVCLASS, $row['class'], true) ?: 'Unknown', + ]; + } + $row['vendor_name'] = PciId::getPciId(PciId::VENDOR, $row['vendor'] ?? ''); + $row['device_name'] = PciId::getPciId(PciId::DEVICE, $row['vendor'] . ':' . $row['device']); + $finalRows[] = $row; + // Build up query + if ($row['vendor_name'] === false) { + $missing[$row['vendor']] = true; + } + if ($row['device_name'] === false) { + $missing[$row['vendor'] . ':' . $row['device']] = true; + } } - Render::addTemplate('hardware-list', ['list' => $rows]); + Render::addTemplate('hardware-list', [ + 'list' => $finalRows, + 'missing_ids' => json_encode(array_keys($missing)), + ]); + } + + /* + * + */ + + protected function doAjax() + { + // } }
\ No newline at end of file diff --git a/modules-available/passthrough/templates/hardware-list.html b/modules-available/passthrough/templates/hardware-list.html index 2450e457..d331acb5 100644 --- a/modules-available/passthrough/templates/hardware-list.html +++ b/modules-available/passthrough/templates/hardware-list.html @@ -3,7 +3,6 @@ <table class="table"> <thead> <tr> - <th class="slx-smallcol">{{lang_class}}</th> <th class="slx-smallcol">{{lang_deviceIdNumeric}}</th> <th>{{lang_deviceName}}</th> <th class="slx-smallcol">{{lang_useCount}}</th> @@ -13,25 +12,35 @@ <tbody> {{#list}} <tr> - <td>{{class}}</td> + {{#class_name}} + <td colspan="4"> + <span>{{class}}</span> – <strong>{{class_name}}</strong> + </td> + {{/class_name}} + {{^class_name}} <td>{{vendor}}:{{device}}</td> <td> <table class="slx-ellipsis"> <tr> - <td>{{device_name}}</td> + <td {{^device_name}}class="query-{{vendor}}-{{device}}"{{/device_name}}> + {{device_name}} + </td> </tr> </table> - <div class="small">{{vendor_name}}</div> + <div class="small {{^vendor_name}}query-{{vendor}}{{/vendor_name}}"> + {{vendor_name}} + </div> </td> <td class="text-right">{{connected_count}}</td> <td> - <select name="ptgroup[{{hwid}}]" class="form-control ptgroup-select"> + <select name="ptgroup[{{hwid}}]" class="form-control {{#custom_groups}}ptgroup-select{{/custom_groups}}"> <option value="">{{lang_noPassthroughGroup}}</option> {{#ptlist}} <option value="{{ptid}}" {{selected}}>{{ptname}}</option> {{/ptlist}} </select> </td> + {{/class_name}} </tr> {{/list}} </tbody> @@ -92,5 +101,25 @@ $(this).append($('<option>').attr('value', gid).text(gid + ' (' + title + ')')); }); }); + var missing = {{{missing_ids}}}; + var doQuery = function() { + if (missing && missing.length > 0) { + $.ajax({ + url: '?do=statistics', dataType: "json", method: "POST", data: { + token: TOKEN, + action: 'json-lookup', + list: missing.splice(0, 10) // Query 10 at a time max + } + }).done(function (data) { + if (!data) + return; + for (var k in data) { + $('.query-' + k.replace(':', '-')).text(data[k]); + } + doQuery(); + }); + } + } + doQuery(); }); </script>
\ No newline at end of file diff --git a/modules-available/statistics/api.inc.php b/modules-available/statistics/api.inc.php index 749557a6..b06d4503 100644 --- a/modules-available/statistics/api.inc.php +++ b/modules-available/statistics/api.inc.php @@ -1,7 +1,7 @@ <?php if (Request::any('action') === 'test' && isLocalExecution()) { - error_log(HardwareInfo::getKclModifications('0A5D9E23-80F4-9C43-912C-96D80AE7E80B')); + error_log(HardwareInfo::getKclModifications()); exit; $x = new HardwareQuery(HardwareInfo::PCI_DEVICE); //$x->addCompare(false, 'Memory Slot Occupied', '>=', true, 'Memory Slot Count'); diff --git a/modules-available/statistics/inc/hardwareinfo.inc.php b/modules-available/statistics/inc/hardwareinfo.inc.php index 90b8975b..5f1a4372 100644 --- a/modules-available/statistics/inc/hardwareinfo.inc.php +++ b/modules-available/statistics/inc/hardwareinfo.inc.php @@ -44,14 +44,18 @@ class HardwareInfo $hw->addWhere(true, '@PASSTHROUGH', 'IN', ['GPU', 'GVT']); $hw->addColumn(true, 'vendor'); $hw->addColumn(true, 'device'); + $hw->addColumn(false, 'slot'); $res = $hw->query(); $passthrough = []; + $slots = []; $gvt = false; foreach ($res as $row) { if ($row['@PASSTHROUGH'] === 'GVT') { $gvt = true; } else { - $passthrough[] = $row['vendor'] . ':' . $row['device']; + $passthrough[$row['vendor'] . ':' . $row['device']] = 1; + error_log('Passthouorgh: ' . $row['vendor'] . ':' . $row['device']); + $slots[preg_replace('/\.[0-9]+$/', '', $row['slot'])] = 1; } } $kcl = ''; @@ -59,7 +63,18 @@ class HardwareInfo $kcl = '-iommu -intel_iommu iommu=pt intel_iommu=on'; // TODO AMD } if (!empty($passthrough)) { - $kcl .= ' vfio-pci.ids=' . implode(',', $passthrough); + foreach (array_keys($slots) as $slot) { + error_log('Querying slot ' . $slot); + $hw = new HardwareQuery(self::PCI_DEVICE, $best['machineuuid'], true); + $hw->addWhere(false, 'slot', 'LIKE', $slot . '.%'); + $hw->addColumn(true, 'vendor'); + $hw->addColumn(true, 'device'); + foreach ($hw->query() as $row) { + $passthrough[$row['vendor'] . ':' . $row['device']] = 1; + error_log('Extra PT: ' . $row['vendor'] . ':' . $row['device']); + } + } + $kcl .= ' vfio-pci.ids=' . implode(',', array_keys($passthrough)); } if ($gvt) { $kcl .= ' i915.enable_gvt=1'; diff --git a/modules-available/statistics/inc/hardwareparser.inc.php b/modules-available/statistics/inc/hardwareparser.inc.php index 562c5948..5ba1e3dd 100644 --- a/modules-available/statistics/inc/hardwareparser.inc.php +++ b/modules-available/statistics/inc/hardwareparser.inc.php @@ -714,8 +714,10 @@ class HardwareParser // ---- lspci ------------------------------------ $pciHwIds = []; foreach (($data['lspci'] ?? []) as $dev) { - $hwid = self::writeGlobalHardwareData(HardwareInfo::PCI_DEVICE, - self::propsFromArray($dev, 'vendor', 'device', 'rev', 'class')); + $props = self::propsFromArray($dev, 'vendor', 'device', 'rev', 'class'); + if (!isset($props['vendor']) || !isset($props['device'])) + continue; + $hwid = self::writeGlobalHardwareData(HardwareInfo::PCI_DEVICE, $props); $mappingId = self::writeLocalHardwareData($uuid, $hwid, $dev['slot'] ?? 'unknown', self::propsFromArray($dev, 'slot', 'subsystem', 'subsystem_vendor', 'iommu_group')); $pciHwIds[] = $mappingId; diff --git a/modules-available/statistics/inc/hardwarequery.inc.php b/modules-available/statistics/inc/hardwarequery.inc.php index b0b7d6ee..c7ecb35e 100644 --- a/modules-available/statistics/inc/hardwarequery.inc.php +++ b/modules-available/statistics/inc/hardwarequery.inc.php @@ -68,6 +68,18 @@ class HardwareQuery $this->columns[$prop] = "$tid.`value` AS `$prop`"; } + public function addMachineWhere(string $column, string $op, $value) + { + if (isset($this->columns[$column])) + return; + $valueCol = ($op === '<' || $op === '>' || $op === '<=' || $op === '>=') ? 'numeric' : 'value'; + $vid = $this->id(); + $this->joins['machine'] = 'INNER JOIN machine m USING (machineuuid)'; + $this->where[] = "m.$column $op :$vid"; + $this->args[$vid] = $value; + $this->columns[$column] = "m.$column"; + } + public function addCompare(bool $global1, string $prop1, string $op, string $global2, string $prop2) { $this->fillTableVars($global1, $srcTable1, $table1, $column1); @@ -86,6 +98,16 @@ class HardwareQuery $this->columns[$prop1] = "$tid1.`value` AS `$prop1`"; } + public function addGlobalColumn(string $prop) + { + $this->addColumn(true, $prop); + } + + public function addLocalColumn(string $prop) + { + $this->addColumn(false, $prop); + } + public function addColumn(bool $global, string $prop) { if (isset($this->columns[$prop])) diff --git a/modules-available/statistics/inc/pciid.inc.php b/modules-available/statistics/inc/pciid.inc.php index 6bf852e6..65edf570 100644 --- a/modules-available/statistics/inc/pciid.inc.php +++ b/modules-available/statistics/inc/pciid.inc.php @@ -6,10 +6,11 @@ class PciId const DEVICE = 'DEVICE'; const VENDOR = 'VENDOR'; const DEVCLASS = 'CLASS'; + const AUTO = 'AUTO'; /** - * @param string $cat type of query - self::DEVICE, self::VENDOR or self::DEVCLASS + * @param string $cat type of query - self::DEVICE, self::VENDOR, self::DEVCLASS or self::AUTO for auto detection * @param string $id the id to query - depends on $cat * @return string|false Name of Class/Vendor/Device, false if not found */ @@ -19,6 +20,18 @@ class PciId if ($cat === self::DEVCLASS && $id[1] !== '.') { $id = 'c.' . $id; } + if ($cat === self::AUTO) { + if (preg_match('/^([a-f0-9]{4}):([a-f0-9]{4})$/', $id, $out)) { + $cat = 'DEVICE'; + } elseif (preg_match('/^([a-f0-9]{4})$/', $id, $out)) { + $cat = 'VENDOR'; + } elseif (preg_match('/^c\.([a-f0-9]{2})([a-f0-9]{2})$/', $id, $out)) { + $cat = 'CLASS'; + } else { + error_log('Invalid PCIID lookup format: ' . $id); + return false; + } + } $key = $cat . '-' . $id; if (isset($cache[$key])) return $cache[$key]; diff --git a/modules-available/statistics/page.inc.php b/modules-available/statistics/page.inc.php index d26649b6..baddd093 100644 --- a/modules-available/statistics/page.inc.php +++ b/modules-available/statistics/page.inc.php @@ -251,11 +251,24 @@ class Page_Statistics extends Page { if (!User::load()) return; - if (Request::any('action') === 'bios') { + $action = Request::any('action'); + if ($action === 'bios') { require_once 'modules/statistics/pages/machine.inc.php'; SubPage::ajaxCheckBios(); return; } + if ($action === 'json-lookup') { + $reply = []; + foreach (Request::post('list', [], 'array') as $item) { + $name = PciId::getPciId(PciId::AUTO, $item, true); + if ($name === false) { + $name = '?????'; + } + $reply[$item] = $name; + } + header('Content-Type: application/json'); + die(json_encode($reply)); + } $param = Request::any('lookup', false, 'string'); if ($param === false) { @@ -263,16 +276,9 @@ class Page_Statistics extends Page } $add = ''; if (preg_match('/^([a-f0-9]{4}):([a-f0-9]{4})$/', $param, $out)) { - $cat = 'DEVICE'; $add = ' (' . $param . ')'; - } elseif (preg_match('/^([a-f0-9]{4})$/', $param, $out)) { - $cat = 'VENDOR'; - } elseif (preg_match('/^c\.([a-f0-9]{2})([a-f0-9]{2})$/', $param, $out)) { - $cat = 'CLASS'; - } else { - die('Invalid format requested'); } - $cached = PciId::getPciId($cat, $param, true); + $cached = PciId::getPciId(PciId::AUTO, $param, true); if ($cached === false) { $cached = 'Unknown'; } |