Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions pkg/pci/pci.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ import (

type Device struct {
// The PCI address of the device
Address string `json:"address"`
Vendor *pcidb.Vendor `json:"vendor"`
Product *pcidb.Product `json:"product"`
Revision string `json:"revision"`
Subsystem *pcidb.Product `json:"subsystem"`
Address string `json:"address"`
// The PCI address of the parent device
ParentAddress string `json:"parent_address"`
Comment on lines +25 to +26
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm contemplating if we should add this at the end of the struct for abundant (excessive?) backward compatibility concerns. But OTOH we mostly (99%) serialize back/from YAML/JSON and clients just recompile, so it's probably OK

Vendor *pcidb.Vendor `json:"vendor"`
Product *pcidb.Product `json:"product"`
Revision string `json:"revision"`
Subsystem *pcidb.Product `json:"subsystem"`
// optional subvendor/sub-device information
Class *pcidb.Class `json:"class"`
// optional sub-class for the device
Expand All @@ -47,15 +49,17 @@ type devIdent struct {
}

type devMarshallable struct {
Driver string `json:"driver"`
Address string `json:"address"`
Vendor devIdent `json:"vendor"`
Product devIdent `json:"product"`
Revision string `json:"revision"`
Subsystem devIdent `json:"subsystem"`
Class devIdent `json:"class"`
Subclass devIdent `json:"subclass"`
Interface devIdent `json:"programming_interface"`
Driver string `json:"driver"`
Address string `json:"address"`
ParentAddress string `json:"parent_address"`
Vendor devIdent `json:"vendor"`
Product devIdent `json:"product"`
Revision string `json:"revision"`
Subsystem devIdent `json:"subsystem"`
Class devIdent `json:"class"`
Subclass devIdent `json:"subclass"`
Interface devIdent `json:"programming_interface"`
IOMMUGroup string `json:"iommu_group"`
}

// NOTE(jaypipes) Device has a custom JSON marshaller because we don't want
Expand All @@ -64,8 +68,9 @@ type devMarshallable struct {
// human-readable name of the vendor, product, class, etc.
func (d *Device) MarshalJSON() ([]byte, error) {
dm := devMarshallable{
Driver: d.Driver,
Address: d.Address,
Driver: d.Driver,
Address: d.Address,
ParentAddress: d.ParentAddress,
Vendor: devIdent{
ID: d.Vendor.ID,
Name: d.Vendor.Name,
Expand All @@ -91,6 +96,7 @@ func (d *Device) MarshalJSON() ([]byte, error) {
ID: d.ProgrammingInterface.ID,
Name: d.ProgrammingInterface.Name,
},
IOMMUGroup: d.IOMMUGroup,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I forgot add this in #430 so I am trying to sneakily add it here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I moved this into a separate commit

}
return json.Marshal(dm)
}
Expand Down
19 changes: 19 additions & 0 deletions pkg/pci/pci_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,24 @@ func getDeviceIommuGroup(ctx *context.Context, pciAddr *pciaddr.Address) string
return filepath.Base(dest)
}

func getDeviceParentAddress(ctx *context.Context, pciAddr *pciaddr.Address) string {
paths := linuxpath.New(ctx)
devPath := filepath.Join(paths.SysBusPciDevices, pciAddr.String())

dest, err := os.Readlink(devPath)
if err != nil {
return ""
}

parentAddr := filepath.Base(filepath.Dir(dest))

if pciaddr.FromString(parentAddr) == nil {
return ""
}

return parentAddr
}

func getDeviceDriver(ctx *context.Context, pciAddr *pciaddr.Address) string {
paths := linuxpath.New(ctx)
driverPath := filepath.Join(paths.SysBusPciDevices, pciAddr.String(), "driver")
Expand Down Expand Up @@ -342,6 +360,7 @@ func (info *Info) GetDevice(address string) *Device {
device.Node = getDeviceNUMANode(info.ctx, pciAddr)
}
device.Driver = getDeviceDriver(info.ctx, pciAddr)
device.ParentAddress = getDeviceParentAddress(info.ctx, pciAddr)
device.IOMMUGroup = getDeviceIommuGroup(info.ctx, pciAddr)
return device
}
Expand Down
23 changes: 23 additions & 0 deletions pkg/pci/pci_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

type pciTestCase struct {
addr string
parentAddr string
node int
revision string
driver string
Expand Down Expand Up @@ -95,6 +96,28 @@ func TestPCIDeviceRevision(t *testing.T) {
}
}

// nolint: gocyclo
func TestPCIParent(t *testing.T) {
info := pciTestSetupI7(t)
tCases := []pciTestCase{
{
addr: "0000:04:00.0",
parentAddr: "0000:00:06.0",
},
}
for _, tCase := range tCases {
t.Run(fmt.Sprintf("%s (%s)", tCase.addr, tCase.parentAddr), func(t *testing.T) {
dev := info.GetDevice(tCase.addr)
if dev == nil {
t.Fatalf("got nil device for address %q", tCase.addr)
}
if dev.ParentAddress != tCase.parentAddr {
t.Errorf("got parent %q expected %q", dev.ParentAddress, tCase.parentAddr)
}
})
}
}

// nolint: gocyclo
func TestPCIIommuGroup(t *testing.T) {
info := pciTestSetupI7(t)
Expand Down
Loading