Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Dec 9, 2025. It is now read-only.

Conversation

@gauravkghildiyal
Copy link
Member

The previous PCI address discovery assumed a fixed depth in the sysfs path gives the correct PCI address. That is correct for paths like /sys/devices/pci0000:00/0000:00:04.0/virtio1 which do not have a PCI hierarchy and we returne the 4th part (0000:00:04.0 as the PCI address)

This doesn't work when the device's sysfs path has a deeper hierarchy, like /sys/devices/pci0000:8c/0000:8c:00.0/0000:8d:00.0/0000:8e:02.0/0000:91:00.0/net/eth3, where the PCI address is not the 4th part and is instead 0000:91:00.0

@aojea
Copy link
Collaborator

aojea commented Aug 26, 2025

will this not be handled by the new library https://github.com/jaypipes/ghw ?

@gauravkghildiyal
Copy link
Member Author

Sadly no. It will also fail to interpret something like /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth2 (which has that virtio1 thing)

https://github.com/jaypipes/ghw/blob/0dc46647516d0bc4ff5951e22ed42f357fd77dda/pkg/net/net_linux.go#L239

@aojea
Copy link
Collaborator

aojea commented Aug 26, 2025

Sadly no. It will also fail to interpret something like /sys/devices/pci0000:00/0000:00:04.0/virtio1/net/eth2 (which has that virtio1 thing)

https://github.com/jaypipes/ghw/blob/0dc46647516d0bc4ff5951e22ed42f357fd77dda/pkg/net/net_linux.go#L239

should we report this to Jay so we do not have to keep the workaround?

@aojea
Copy link
Collaborator

aojea commented Aug 26, 2025

This is what gemini tells me

Robustly Finding the PCI Address
To correctly find the device's PCI address from its sysfs path, you should not rely on a fixed depth. Instead, you should find the directory that corresponds to the actual device.

For a network device like eth3, the kernel creates a symbolic link at /sys/class/net/eth3/device which points back to the correct device directory in the /sys/devices tree.

You can robustly get the PCI address with a command like this:

basename $(readlink -f /sys/class/net/eth3/device)

Explanation:

/sys/class/net/eth3/device: This is the symlink to the device's directory.

readlink -f: This command follows the symbolic link to get the full, canonical path (e.g., /sys/devices/pci.../0000:91:00.0).

basename: This extracts the last component of that path, which is the device's PCI address (0000:91:00.0).

This method works regardless of how many PCI bridges are in the path, making it the correct way to solve the problem you described.

it seems the basename is the key and AFAIK we are already using readlink

Copy link
Collaborator

@aojea aojea left a comment

Choose a reason for hiding this comment

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

I like to hold until we have more real evidance that using readlink to get the path is not valid

@gauravkghildiyal
Copy link
Member Author

gauravkghildiyal commented Aug 26, 2025

I like to hold until we have more real evidance that using readlink to get the path is not valid

I'm not sure what you mean by "real evidence", but the following is based on actual (different) machines:

  1. If eth1 does not use virtio driver, the device path is this
$ ls /sys/class/net/eth1 -l
lrwxrwxrwx 1 root root 0 Aug 24 01:23 /sys/class/net/eth1 -> ../../devices/pci0000:c0/0000:c0:14.0/net/eth1

...which means you get the PCI address if you follow the link

$ basename $(readlink -f /sys/class/net/eth0/device)
0000:00:13.0
  1. If eth2 uses a virtio driver, the device path is this
$ ls /sys/class/net/eth2 -l
lrwxrwxrwx 1 root root 0 Aug 24 01:47 /sys/class/net/eth2 -> ../../devices/pci0000:00/0000:00:06.0/virtio3/net/eth2

...which means the link takes you back to virtio3 and NOT it's PCI address.

$ basename $(readlink -f /sys/class/net/eth2/device)
virtio3

should we report this to Jay so we do not have to keep the workaround?

Sure I'll report it. But ghw is also not optimal (or atleast will require additional changes) since it can only list all NICs with their data and then we have to build a map on top of that. It does not (yet) expose a function where we simply pass in a single NIC and get back it's equivalent info. We can work towards improving in ghw (assuming that is seen acceptable to ghw maintainers) but it's going to take time.


// pciAddressRegex is used to identify a PCI address within a string.
// It matches patterns like "0000:00:04.0" or "00:04.0".
var pciAddressRegex = regexp.MustCompile(`^(?:([0-9a-fA-F]{4}):)?([0-9a-fA-F]{2}):([0-9a-fA-F]{2})\.([0-9a-fA-F])$`)
Copy link
Collaborator

Choose a reason for hiding this comment

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

ok, this always returns 5 elements in a match package main

import (
	"fmt"
	"regexp"
)

func main() {
	re := regexp.MustCompile(`^(?:([0-9a-fA-F]{4}):)?([0-9a-fA-F]{2}):([0-9a-fA-F]{2})\.([0-9a-fA-F])$`)
	fmt.Printf("%q\n", re.FindStringSubmatch("0000:00:04.0"))
	fmt.Printf("%q\n", re.FindStringSubmatch("00:04.0"))
}
["0000:00:04.0" "0000" "00" "04" "0"]
["00:04.0" "" "00" "04" "0"]

https://go.dev/play/p/5pTJYFVKQKx

f := strings.Split(pci[2], ".")
if len(f) != 2 {
return nil, fmt.Errorf("could not find corresponding PCI device and function: %v", pci)
if len(matches) == 5 {
Copy link
Collaborator

Choose a reason for hiding this comment

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

this was the part that needs a comment explaining that the regex always return 5 , it is very magic https://github.com/google/dranet/pull/210/files#r2304914785

Copy link
Member Author

Choose a reason for hiding this comment

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

Makes sense to document it. Added a comment.

aojea
aojea previously approved these changes Aug 27, 2025
Copy link
Collaborator

@aojea aojea left a comment

Choose a reason for hiding this comment

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

lgtm

we need to document the magic number 5 only, the rest LGTM

@gauravkghildiyal gauravkghildiyal force-pushed the fix-pci-address-of-interface branch from 448f4d0 to 0a8cb8d Compare August 27, 2025 18:16
@aojea aojea merged commit 5467cdd into google:main Aug 27, 2025
6 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants