mirror of
https://git.proxmox.com/git/pve-manager
synced 2025-11-05 21:36:57 +00:00
Currently, when we have a PCI resource mapping, we manually check only the available models for the first PCI entry. This often works, but not always, since one could have completely different devices in one mapping, or with the new NVIDIA sysfs api we don't get the generally available models. To improve this, extend the parameter for the PCI ID to accept both, PCI IDs or named mappings, and for the latter mappings, iterate over all local PCI devices in it and extract the mdev types. Rename also the parameter to better reflect what it accepts. While the this is changing a API parameter, it's not a breaking change in this specific case because the parameter is derived from the URL path, and any attempt to include the parameter with a name manually is not possible and will result in an error: duplicate parameter (already defined in URI) with conflicting values! Since we cannot reach the API handler without giving the parameter already via the URL, there is no way to give it via name. Accepting named mappings directly in this API endpoint also vastly simplifies the UI code, since we now only have to give the mapping to the selector instead of an (arbitrarily selected) PCI id from that mapping. Signed-off-by: Dominik Csapak <d.csapak@proxmox.com> [ TL: also split pciid into pci-id for readability and reword message slightly ] Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
247 lines
5.8 KiB
Perl
247 lines
5.8 KiB
Perl
package PVE::API2::Hardware::PCI;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use PVE::JSONSchema qw(get_standard_option);
|
|
|
|
use PVE::RESTHandler;
|
|
use PVE::SysFSTools;
|
|
|
|
use base qw(PVE::RESTHandler);
|
|
|
|
my $default_class_blacklist = "05;06;0b";
|
|
|
|
__PACKAGE__->register_method ({
|
|
name => 'pciscan',
|
|
path => '',
|
|
method => 'GET',
|
|
description => "List local PCI devices.",
|
|
protected => 1,
|
|
proxyto => "node",
|
|
permissions => {
|
|
check => ['perm', '/', ['Sys.Audit', 'Sys.Modify'], any => 1],
|
|
},
|
|
parameters => {
|
|
additionalProperties => 0,
|
|
properties => {
|
|
node => get_standard_option('pve-node'),
|
|
'pci-class-blacklist' => {
|
|
type => 'string',
|
|
format => 'string-list',
|
|
default => $default_class_blacklist,
|
|
optional => 1,
|
|
description => "A list of blacklisted PCI classes, which will ".
|
|
"not be returned. Following are filtered by ".
|
|
"default: Memory Controller (05), Bridge (06) and ".
|
|
"Processor (0b).",
|
|
},
|
|
verbose => {
|
|
type => 'boolean',
|
|
default => 1,
|
|
optional => 1,
|
|
description => "If disabled, does only print the PCI IDs. "
|
|
."Otherwise, additional information like vendor "
|
|
."and device will be returned.",
|
|
},
|
|
},
|
|
},
|
|
returns => {
|
|
links => [ { rel => 'child', href => "{id}" } ],
|
|
type => 'array',
|
|
items => {
|
|
type => "object",
|
|
properties => {
|
|
id => {
|
|
type => 'string',
|
|
description => "The PCI ID.",
|
|
},
|
|
class => {
|
|
type => 'string',
|
|
description => 'The PCI Class of the device.',
|
|
},
|
|
vendor => {
|
|
type => 'string',
|
|
description => 'The Vendor ID.',
|
|
},
|
|
vendor_name => {
|
|
type => 'string',
|
|
optional => 1,
|
|
},
|
|
device => {
|
|
type => 'string',
|
|
description => 'The Device ID.',
|
|
},
|
|
device_name => {
|
|
type => 'string',
|
|
optional => 1,
|
|
},
|
|
subsystem_vendor => {
|
|
type => 'string',
|
|
description => 'The Subsystem Vendor ID.',
|
|
optional => 1,
|
|
},
|
|
subsystem_vendor_name => {
|
|
type => 'string',
|
|
optional => 1,
|
|
},
|
|
subsystem_device => {
|
|
type => 'string',
|
|
description => 'The Subsystem Device ID.',
|
|
optional => 1,
|
|
},
|
|
subsystem_device_name => {
|
|
type => 'string',
|
|
optional => 1,
|
|
},
|
|
iommugroup => {
|
|
type => 'integer',
|
|
description => "The IOMMU group in which the device is in.".
|
|
" If no IOMMU group is detected, it is set to -1.",
|
|
},
|
|
mdev => {
|
|
type => 'boolean',
|
|
optional => 1,
|
|
description => "If set, marks that the device is capable "
|
|
."of creating mediated devices.",
|
|
}
|
|
},
|
|
},
|
|
},
|
|
code => sub {
|
|
my ($param) = @_;
|
|
|
|
my $blacklist = $param->{'pci-class-blacklist'} // $default_class_blacklist;
|
|
my $class_regex = join('|', PVE::Tools::split_list($blacklist));
|
|
|
|
my $filter;
|
|
|
|
if ($class_regex ne '') {
|
|
$filter = sub {
|
|
my ($pcidevice) = @_;
|
|
|
|
if ($pcidevice->{class} =~ m/^0x(?:$class_regex)/) {
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
};
|
|
}
|
|
|
|
my $verbose = $param->{verbose} // 1;
|
|
|
|
return PVE::SysFSTools::lspci($filter, $verbose);
|
|
}});
|
|
|
|
__PACKAGE__->register_method ({
|
|
name => 'pciindex',
|
|
path => '{pci-id-or-mapping}',
|
|
method => 'GET',
|
|
description => "Index of available pci methods",
|
|
permissions => {
|
|
user => 'all',
|
|
},
|
|
parameters => {
|
|
additionalProperties => 0,
|
|
properties => {
|
|
node => get_standard_option('pve-node'),
|
|
'pci-id-or-mapping' => {
|
|
type => 'string',
|
|
pattern => '(?:(?:[0-9a-fA-F]{4}:)?[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9a-fA-F])|([a-zA-Z][a-zA-Z0-9_-]+)',
|
|
},
|
|
},
|
|
},
|
|
returns => {
|
|
type => 'array',
|
|
items => {
|
|
type => "object",
|
|
properties => { method => { type => 'string'} },
|
|
},
|
|
links => [ { rel => 'child', href => "{method}" } ],
|
|
},
|
|
code => sub {
|
|
my ($param) = @_;
|
|
|
|
my $res = [
|
|
{ method => 'mdev' },
|
|
];
|
|
|
|
return $res;
|
|
}});
|
|
|
|
__PACKAGE__->register_method ({
|
|
name => 'mdevscan',
|
|
path => '{pci-id-or-mapping}/mdev',
|
|
method => 'GET',
|
|
description => "List mediated device types for given PCI device.",
|
|
protected => 1,
|
|
proxyto => "node",
|
|
permissions => {
|
|
check => ['perm', '/', ['Sys.Audit', 'Sys.Modify'], any => 1],
|
|
},
|
|
parameters => {
|
|
additionalProperties => 0,
|
|
properties => {
|
|
node => get_standard_option('pve-node'),
|
|
'pci-id-or-mapping' => {
|
|
type => 'string',
|
|
pattern => '(?:(?:[0-9a-fA-F]{4}:)?[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9a-fA-F])|([a-zA-Z][a-zA-Z0-9_-]+)',
|
|
description => "The PCI ID or mapping to list the mdev types for."
|
|
},
|
|
},
|
|
},
|
|
returns => {
|
|
type => 'array',
|
|
items => {
|
|
type => "object",
|
|
properties => {
|
|
type => {
|
|
type => 'string',
|
|
description => "The name of the mdev type.",
|
|
},
|
|
available => {
|
|
type => 'integer',
|
|
description => "The number of still available instances of"
|
|
." this type.",
|
|
},
|
|
description => {
|
|
type => 'string',
|
|
description => "Additional description of the type."
|
|
},
|
|
name => {
|
|
type => 'string',
|
|
optional => 1,
|
|
description => 'A human readable name for the type.',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
code => sub {
|
|
my ($param) = @_;
|
|
|
|
if ($param->{'pci-id-or-mapping'} =~ m/^(?:[0-9a-fA-F]{4}:)?[0-9a-fA-F]{2}:[0-9a-fA-F]{2}\.[0-9a-fA-F]$/) {
|
|
return PVE::SysFSTools::get_mdev_types($param->{'pci-id-or-mapping'}); # PCI ID
|
|
} else {
|
|
my $mapping = $param->{'pci-id-or-mapping'};
|
|
|
|
my $types = {};
|
|
my $devices = PVE::Mapping::PCI::find_on_current_node($mapping);
|
|
for my $device ($devices->@*) {
|
|
my $id = $device->{path};
|
|
next if $id =~ m/;/; # mdev not supported for multifunction devices
|
|
|
|
my $device_types = PVE::SysFSTools::get_mdev_types($id);
|
|
|
|
for my $type_definition ($device_types->@*) {
|
|
my $type = $type_definition->{type};
|
|
if (!defined($types->{$type})) {
|
|
$types->{$type} = $type_definition;
|
|
}
|
|
}
|
|
}
|
|
|
|
return [sort { $a->{type} cmp $b->{type} } values($types->%*)];
|
|
}
|
|
|
|
}});
|