mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-07-25 14:06:46 +00:00
helper function to standardize the PCIBusID device attribute for DRA drivers
Signed-off-by: Varun Ramachandra Sekar <vsekar@nvidia.com>
This commit is contained in:
@@ -30,6 +30,13 @@ const (
|
||||
// referring to a PCIe (Peripheral Component Interconnect Express) Root Complex.
|
||||
// This attribute can be used to identify devices that share the same PCIe Root Complex.
|
||||
StandardDeviceAttributePCIeRoot resourceapi.QualifiedName = StandardDeviceAttributePrefix + "pcieRoot"
|
||||
|
||||
// StandardDeviceAttributePCIBusID is a standard device attribute name
|
||||
// which describes the PCI Bus address of the PCI device.
|
||||
// The value is a string value in the extended BDF notation (Domain:Bus:Device.Function),
|
||||
// referring to a PCI (Peripheral Component Interconnect) device.
|
||||
// This attribute can be used to identify PCI devices.
|
||||
StandardDeviceAttributePCIBusID resourceapi.QualifiedName = StandardDeviceAttributePrefix + "pciBusID"
|
||||
)
|
||||
|
||||
// DeviceAttribute represents a device attribute name and its value
|
||||
|
||||
@@ -34,13 +34,8 @@ import (
|
||||
//
|
||||
// ref: https://wiki.xenproject.org/wiki/Bus:Device.Function_(BDF)_Notation
|
||||
func GetPCIeRootAttributeByPCIBusID(pciBusID string) (DeviceAttribute, error) {
|
||||
if pciBusID == "" {
|
||||
return DeviceAttribute{}, fmt.Errorf("PCI Bus ID cannot be empty")
|
||||
}
|
||||
|
||||
bdfRegexp := regexp.MustCompile(`^([0-9a-f]{4}):([0-9a-f]{2}):([0-9a-f]{2})\.([0-9a-f]{1})$`)
|
||||
if !bdfRegexp.MatchString(pciBusID) {
|
||||
return DeviceAttribute{}, fmt.Errorf("invalid PCI Bus ID format: %s", pciBusID)
|
||||
if err := verifyPCIBDFFormat(pciBusID); err != nil {
|
||||
return DeviceAttribute{}, err
|
||||
}
|
||||
|
||||
pcieRoot, err := resolvePCIeRoot(pciBusID)
|
||||
@@ -100,3 +95,39 @@ func resolvePCIeRoot(pciBusID string) (string, error) {
|
||||
|
||||
return pcieRootPart, nil
|
||||
}
|
||||
|
||||
// GetPCIBusIDAttribute returns a DeviceAttribute with the PCI Bus Address("<domain>:<bus>:<device>.<function>")
|
||||
// of a PCI device as a string value.
|
||||
//
|
||||
// It returns an error if the PCI Bus ID is empty or is not in
|
||||
// extended BDF (Domain:Bus:Device.Function) format, e.g., "0123:45:1e.7"
|
||||
//
|
||||
// ref: https://wiki.xenproject.org/wiki/Bus:Device.Function_(BDF)_Notation
|
||||
func GetPCIBusIDAttribute(pciBusID string) (DeviceAttribute, error) {
|
||||
if err := verifyPCIBDFFormat(pciBusID); err != nil {
|
||||
return DeviceAttribute{}, err
|
||||
}
|
||||
|
||||
attr := DeviceAttribute{
|
||||
Name: StandardDeviceAttributePCIBusID,
|
||||
Value: resourceapi.DeviceAttribute{StringValue: &pciBusID},
|
||||
}
|
||||
|
||||
return attr, nil
|
||||
}
|
||||
|
||||
// verifyPCIBDFFormat verifies that the PCI Bus ID is in extended BDF (Domain:Bus:Device.Function) format.
|
||||
//
|
||||
// ref: https://wiki.xenproject.org/wiki/Bus:Device.Function_(BDF)_Notation
|
||||
func verifyPCIBDFFormat(pciBusID string) error {
|
||||
if pciBusID == "" {
|
||||
return fmt.Errorf("PCI Bus ID cannot be empty")
|
||||
}
|
||||
|
||||
bdfRegexp := regexp.MustCompile(`^([0-9a-f]{4}):([0-9a-f]{2}):([0-9a-f]{2})\.([0-9a-f]{1})$`)
|
||||
if !bdfRegexp.MatchString(pciBusID) {
|
||||
return fmt.Errorf("invalid PCI Bus ID format: %s", pciBusID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -136,6 +136,61 @@ func TestGetPCIeRootAttributePCIBusID(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPCIBusIDAttribute(t *testing.T) {
|
||||
pciBusID := "0000:02:00.0"
|
||||
expectedAttribute := DeviceAttribute{
|
||||
Name: StandardDeviceAttributePCIBusID,
|
||||
Value: resourceapi.DeviceAttribute{StringValue: ptr.To(pciBusID)},
|
||||
}
|
||||
|
||||
tests := map[string]struct {
|
||||
address string
|
||||
expectedAttribute *DeviceAttribute
|
||||
expectsError bool
|
||||
expectedErrMsg string
|
||||
}{
|
||||
"valid": {
|
||||
address: pciBusID,
|
||||
expectedAttribute: &expectedAttribute,
|
||||
expectsError: false,
|
||||
},
|
||||
"invalid empty PCI Bus ID": {
|
||||
address: "",
|
||||
expectedAttribute: nil,
|
||||
expectsError: true,
|
||||
expectedErrMsg: "PCI Bus ID cannot be empty",
|
||||
},
|
||||
"invalid PCI Bus ID format": {
|
||||
address: "invalid-pci-id",
|
||||
expectedAttribute: nil,
|
||||
expectsError: true,
|
||||
expectedErrMsg: "invalid PCI Bus ID format: invalid-pci-id",
|
||||
},
|
||||
}
|
||||
for name, test := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
got, err := GetPCIBusIDAttribute(test.address)
|
||||
if test.expectsError {
|
||||
if err == nil {
|
||||
t.Errorf("Expected error but got none")
|
||||
return
|
||||
}
|
||||
if !strings.Contains(err.Error(), test.expectedErrMsg) {
|
||||
t.Errorf("Expected error message to contain %q, got %q", test.expectedErrMsg, err.Error())
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, *test.expectedAttribute) {
|
||||
t.Errorf("Expected attribute %v, got %v", test.expectedAttribute, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func touchFile(t *testing.T, path string) {
|
||||
t.Helper()
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user