diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 262525035..69f4baa74 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -397,6 +397,38 @@ func GetNetNames(pciAddr string) ([]string, error) { return names, nil } +// GetNetIndex returns host net interface index as int for a PCI device from its pci address +func GetNetIndex(pciAddr string) (int, error) { + // get interface name + names, err := GetNetNames(pciAddr) + if err != nil { + return -1, err + } + + // check we have exactly one interface name + if len(names) != 1 { + return -1, nil + } + + netDir := filepath.Join(sysBusPci, pciAddr, "net", names[0]) + if _, err := os.Lstat(netDir); err != nil { + return -1, fmt.Errorf("GetNetIndex(): no interface name directory under pci device %s: %q", pciAddr, err) + } + + // read the ifindex file from the interface folder + indexFile := filepath.Join(netDir, "ifindex") + ifIndex, err := os.ReadFile(indexFile) + if err != nil { + return -1, fmt.Errorf("GetNetIndex(): failed to read ifindex file %s: %q", indexFile, err) + } + + intIfIndex, err := strconv.Atoi(strings.TrimSpace(string(ifIndex))) + if err != nil { + return -1, fmt.Errorf("GetNetIndex(): failed to parse ifindex file content %s: %q", string(ifIndex), err) + } + return intIfIndex, nil +} + // GetDriverName returns current driver attached to a pci device from its pci address func GetDriverName(pciAddr string) (string, error) { driverLink := filepath.Join(sysBusPci, pciAddr, "driver") diff --git a/pkg/utils/utils_test.go b/pkg/utils/utils_test.go index 710b04597..e7e847d8d 100644 --- a/pkg/utils/utils_test.go +++ b/pkg/utils/utils_test.go @@ -403,6 +403,33 @@ var _ = Describe("In the utils package", func() { ), ) + FDescribeTable("getting interface index", + func(fs *FakeFilesystem, device string, expected int, shouldFail bool) { + defer fs.Use()() + actual, err := GetNetIndex(device) + Expect(actual).To(Equal(expected)) + assertShouldFail(err, shouldFail) + }, + Entry("device doesn't exist", &FakeFilesystem{}, "0000:01:10.0", -1, true), + Entry("net is not a directory", + &FakeFilesystem{ + Dirs: []string{"sys/bus/pci/devices/0000:01:10.0"}, + Files: map[string][]byte{"sys/bus/pci/devices/0000:01:10.0/net": []byte("junk")}, + }, + "0000:01:10.0", -1, true, + ), + Entry("ifindex is not a number", + &FakeFilesystem{Dirs: []string{"sys/bus/pci/devices/0000:01:10.0/net/fake0"}, + Files: map[string][]byte{"sys/bus/pci/devices/0000:01:10.0/net/fake0/ifindex": []byte("test")}}, + "0000:01:10.0", -1, true, + ), + Entry("single network interface", + &FakeFilesystem{Dirs: []string{"sys/bus/pci/devices/0000:01:10.0/net/fake0"}, + Files: map[string][]byte{"sys/bus/pci/devices/0000:01:10.0/net/fake0/ifindex": []byte("72")}}, + "0000:01:10.0", 72, false, + ), + ) + DescribeTable("getting PF names legacy", func(fs *FakeFilesystem, device string, expected string, shouldFail bool) { fakeNetlinkProvider := mocks.NetlinkProvider{}