Skip to content

Commit

Permalink
pkg: net: report backing device address
Browse files Browse the repository at this point in the history
Report the backing device address - currently PCI only -
in the network interface data.
This allows the client code to fetch the device information using
the specific package, for example `pkg/pci`.

We prefer to add the address, and not a pointer to the relevant
backing device object, the make the net module less coupled with
the other hardware modules.

Signed-off-by: Francesco Romani <[email protected]>
  • Loading branch information
ffromani committed Jan 21, 2021
1 parent efbe6fd commit 617636e
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 2 deletions.
8 changes: 6 additions & 2 deletions pkg/net/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,17 @@ type NICCapability struct {
CanEnable bool `json:"can_enable"`
}

type NICAddress struct {
PCI string `json:"pci"`
// TODO(fromani): add other hw addresses (USB) when we support them
}

type NIC struct {
Name string `json:"name"`
MacAddress string `json:"mac_address"`
IsVirtual bool `json:"is_virtual"`
Capabilities []*NICCapability `json:"capabilities"`
// TODO(jaypipes): Add PCI field for accessing PCI device information
// PCI *PCIDevice `json:"pci"`
HWAddress NICAddress `json:"hw_address"`
}

func (n *NIC) String() string {
Expand Down
56 changes: 56 additions & 0 deletions pkg/net/net_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ func nics(ctx *context.Context) []*NIC {
} else {
nic.Capabilities = []*NICCapability{}
}

nic.HWAddress = netDeviceHWAddress(paths.SysClassNet, filename)

nics = append(nics, nic)
}
return nics
Expand Down Expand Up @@ -163,3 +166,56 @@ func netParseEthtoolFeature(line string) *NICCapability {
CanEnable: !fixed,
}
}

func netDeviceHWAddress(netDevDir, netDevName string) NICAddress {
nicAddr := NICAddress{}

// what we do here is not that hard in the end: we need to navigate the sysfs
// up to the directory belonging to the device backing the network interface.
// we can make few relatively safe assumptions, but the safest way is follow
// the right links. And so we go.
// First of all, knowing the network device name we need to resolve the backing
// device path to its full sysfs path.
// say we start with netDevDir="/sys/class/net" and netDevName="enp0s31f6"
netPath := filepath.Join(netDevDir, netDevName)
dest, err := os.Readlink(netPath)
if err != nil {
// bail out with empty value
return nicAddr
}
// now we have something like dest="../../devices/pci0000:00/0000:00:1f.6/net/enp0s31f6"
// remember the path is relative to netDevDir="/sys/class/net"

netDev := filepath.Clean(filepath.Join(netDevDir, dest))
// so we clean "/sys/class/net/../../devices/pci0000:00/0000:00:1f.6/net/enp0s31f6"
// leading to "/sys/devices/pci0000:00/0000:00:1f.6/net/enp0s31f6"
// still not there. We need to access the data of the pci device. So we jump into the path
// linked to the "device" pseudofile
dest, err = os.Readlink(filepath.Join(netDev, "device"))
if err != nil {
// bail out with empty value
return nicAddr
}
// we expect something like="../../../0000:00:1f.6"

devPath := filepath.Clean(filepath.Join(netDev, dest))
// so we clean "/sys/devices/pci0000:00/0000:00:1f.6/net/enp0s31f6/../../../0000:00:1f.6"
// leading to "/sys/devices/pci0000:00/0000:00:1f.6/"
// finally here!

// to which bus is this device connected to?
dest, err = os.Readlink(filepath.Join(devPath, "subsystem"))
if err != nil {
// bail out with empty value
return nicAddr
}
// ok, this is hacky, but since we need the last *two* path components and we know we
// are running on linux...
if !strings.HasSuffix(dest, "/bus/pci") {
// unsupported and unexpected bus!
return nicAddr
}

nicAddr.PCI = filepath.Base(devPath)
return nicAddr
}

0 comments on commit 617636e

Please sign in to comment.