Skip to content

Commit 63ea993

Browse files
committed
sysfs: add NetClassPCIDevice and PciDeviceVFAddress for SR-IOV support
Add two new functions to support SR-IOV network VF metrics collection: - NetClassPCIDevice(iface string) (*PciDevice, error) in net_class.go: Resolves /sys/class/net/<iface>/device symlink and returns the backing PciDevice using the existing PCI device parser. This gives callers access to all PCI device properties (NumaNode, link speed, SR-IOV fields, etc.). - PciDeviceVFAddress(device *PciDevice, vfIndex uint32) (string, error) in pci_device.go: Returns the PCI BDF address of a Virtual Function by resolving the virtfn symlink at /sys/bus/pci/devices/<bdf>/virtfn<n>. Test fixtures added under testdata/fixtures/sys/class/net/enp3s0f0/ using the existing 0000:a2:00.0 PCI device fixture. Signed-off-by: Anthony Harivel <aharivel@redhat.com>
1 parent b380dd4 commit 63ea993

6 files changed

Lines changed: 170 additions & 52 deletions

File tree

sysfs/net_class.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,18 @@ func (fs FS) NetClassByIface(devicePath string) (*NetClassIface, error) {
9797
}
9898

9999
// NetClass returns info for all net interfaces (iface) read from /sys/class/net/<iface>.
100+
// NetClassPCIDevice returns the PciDevice backing the given network interface
101+
// by resolving the /sys/class/net/<iface>/device symlink and parsing the
102+
// corresponding PCI device via the existing PCI device parser.
103+
func (fs FS) NetClassPCIDevice(iface string) (*PciDevice, error) {
104+
deviceSymlink := fs.sys.Path(netclassPath, iface, "device")
105+
resolved, err := os.Readlink(deviceSymlink)
106+
if err != nil {
107+
return nil, fmt.Errorf("failed to resolve device symlink for %q: %w", iface, err)
108+
}
109+
return fs.parsePciDevice(filepath.Base(resolved))
110+
}
111+
100112
func (fs FS) NetClass() (NetClass, error) {
101113
devices, err := fs.NetClassDevices()
102114
if err != nil {

sysfs/net_class_aer_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ func TestAerCounters(t *testing.T) {
5050

5151
ac, _ := fs.AerCounters()
5252
aerCounters := AllAerCounters{
53+
"enp3s0f0": AerCounters{Name: "enp3s0f0"},
5354
"eth0": AerCounters{
5455
Name: "eth0",
5556
Correctable: CorrectableAerCounters{

sysfs/net_class_sriov_test.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
//go:build linux
15+
16+
package sysfs
17+
18+
import (
19+
"testing"
20+
)
21+
22+
func TestNetClassPCIDevice(t *testing.T) {
23+
fs, err := NewFS(sysTestFixtures)
24+
if err != nil {
25+
t.Fatal(err)
26+
}
27+
28+
dev, err := fs.NetClassPCIDevice("enp3s0f0")
29+
if err != nil {
30+
t.Fatal(err)
31+
}
32+
33+
if want := 0xa2; dev.Location.Bus != want {
34+
t.Errorf("NetClassPCIDevice() Bus = %#x, want %#x", dev.Location.Bus, want)
35+
}
36+
37+
if dev.NumaNode == nil {
38+
t.Fatal("expected NumaNode to be set")
39+
}
40+
if want := int32(1); *dev.NumaNode != want {
41+
t.Errorf("NumaNode = %d, want %d", *dev.NumaNode, want)
42+
}
43+
}
44+
45+
func TestNetClassPCIDeviceMissing(t *testing.T) {
46+
fs, err := NewFS(sysTestFixtures)
47+
if err != nil {
48+
t.Fatal(err)
49+
}
50+
51+
_, err = fs.NetClassPCIDevice("nonexistent")
52+
if err == nil {
53+
t.Error("expected error for non-existent interface, got nil")
54+
}
55+
}
56+
57+
func TestPciDeviceVFAddress(t *testing.T) {
58+
fs, err := NewFS(sysTestFixtures)
59+
if err != nil {
60+
t.Fatal(err)
61+
}
62+
63+
dev, err := fs.NetClassPCIDevice("enp3s0f0")
64+
if err != nil {
65+
t.Fatal(err)
66+
}
67+
68+
got, err := fs.PciDeviceVFAddress(dev, 0)
69+
if err != nil {
70+
t.Fatal(err)
71+
}
72+
73+
if want := "0000:a2:01.0"; got != want {
74+
t.Errorf("PciDeviceVFAddress() = %q, want %q", got, want)
75+
}
76+
}
77+
78+
func TestPciDeviceVFAddressMissing(t *testing.T) {
79+
fs, err := NewFS(sysTestFixtures)
80+
if err != nil {
81+
t.Fatal(err)
82+
}
83+
84+
dev, err := fs.NetClassPCIDevice("enp3s0f0")
85+
if err != nil {
86+
t.Fatal(err)
87+
}
88+
89+
_, err = fs.PciDeviceVFAddress(dev, 99)
90+
if err == nil {
91+
t.Error("expected error for non-existent VF, got nil")
92+
}
93+
}

sysfs/net_class_test.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,15 @@ func TestNewNetClassDevices(t *testing.T) {
3232
t.Fatal(err)
3333
}
3434

35-
if len(devices) != 1 {
36-
t.Errorf("Unexpected number of devices, want %d, have %d", 1, len(devices))
35+
found := false
36+
for _, d := range devices {
37+
if d == "eth0" {
38+
found = true
39+
break
40+
}
3741
}
38-
if devices[0] != "eth0" {
39-
t.Errorf("Found unexpected device, want %s, have %s", "eth0", devices[0])
42+
if !found {
43+
t.Errorf("expected device eth0 not found in %v", devices)
4044
}
4145
}
4246

@@ -94,6 +98,7 @@ func TestNetClass(t *testing.T) {
9498
)
9599

96100
netClass := NetClass{
101+
"enp3s0f0": {Name: "enp3s0f0"},
97102
"eth0": {
98103
Address: "01:01:01:01:01:01",
99104
AddrAssignType: &addrAssignType,

sysfs/pci_device.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,19 @@ func (pd PciDevice) Name() string {
103103
return pd.Location.String()
104104
}
105105

106+
// PciDeviceVFAddress returns the PCI BDF address of a Virtual Function by
107+
// resolving the virtfn symlink at /sys/bus/pci/devices/<bdf>/virtfn<vfIndex>.
108+
func (fs FS) PciDeviceVFAddress(device *PciDevice, vfIndex uint32) (string, error) {
109+
loc := device.Location
110+
bdf := fmt.Sprintf("%04x:%02x:%02x.%x", loc.Segment, loc.Bus, loc.Device, loc.Function)
111+
virtfnPath := fs.sys.Path(pciDevicesPath, bdf, fmt.Sprintf("virtfn%d", vfIndex))
112+
resolved, err := os.Readlink(virtfnPath)
113+
if err != nil {
114+
return "", fmt.Errorf("failed to read virtfn%d symlink for %q: %w", vfIndex, bdf, err)
115+
}
116+
return filepath.Base(resolved), nil
117+
}
118+
106119
// PciDevices is a collection of every PCI device in
107120
// /sys/bus/pci/devices .
108121
//

testdata/fixtures.ttar

Lines changed: 42 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6341,6 +6341,12 @@ Mode: 644
63416341
Directory: fixtures/sys/class/net
63426342
Mode: 755
63436343
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6344+
Directory: fixtures/sys/class/net/enp3s0f0
6345+
Mode: 755
6346+
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6347+
Path: fixtures/sys/class/net/enp3s0f0/device
6348+
SymlinkTo: ../../../devices/pci0000:a2/0000:a2:00.0
6349+
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
63446350
Directory: fixtures/sys/class/net/eth0
63456351
Mode: 755
63466352
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -6684,32 +6690,6 @@ Lines: 1
66846690
Samsung SSD 970 PRO 512GB
66856691
Mode: 644
66866692
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6687-
Directory: fixtures/sys/class/nvme/nvme0/nvme0c0n0
6688-
Mode: 755
6689-
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6690-
Path: fixtures/sys/class/nvme/nvme0/nvme0c0n0/ana_state
6691-
Lines: 1
6692-
optimized
6693-
Mode: 644
6694-
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6695-
Path: fixtures/sys/class/nvme/nvme0/nvme0c0n0/nuse
6696-
Lines: 1
6697-
488281250
6698-
Mode: 644
6699-
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6700-
Directory: fixtures/sys/class/nvme/nvme0/nvme0c0n0/queue
6701-
Mode: 755
6702-
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6703-
Path: fixtures/sys/class/nvme/nvme0/nvme0c0n0/queue/logical_block_size
6704-
Lines: 1
6705-
4096
6706-
Mode: 644
6707-
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6708-
Path: fixtures/sys/class/nvme/nvme0/nvme0c0n0/size
6709-
Lines: 1
6710-
3906250000
6711-
Mode: 644
6712-
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
67136693
Path: fixtures/sys/class/nvme/nvme0/serial
67146694
Lines: 1
67156695
S680HF8N190894I
@@ -17390,6 +17370,9 @@ Lines: 1
1739017370
0x8086
1739117371
Mode: 444
1739217372
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
17373+
Path: fixtures/sys/devices/pci0000:a2/0000:a2:00.0/virtfn0
17374+
SymlinkTo: ../0000:a2:01.0
17375+
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1739317376
Path: fixtures/sys/devices/pci0000:a2/0000:a2:00.0/vpd
1739417377
Lines: 0
1739517378
Mode: 600
@@ -18232,61 +18215,72 @@ Lines: 1
1823218215
Mode: 644
1823318216
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1823418217
Path: fixtures/sys/fs/bcachefs/deadbeef-1234-5678-9012-abcdefabcdef/btree_write_stats
18235-
Lines: 2
18236-
type count size
18237-
initial: 19088 1.0G
18218+
Lines: 3
18219+
nr size
18220+
initial: 19088 108k
18221+
journal_reclaim: 541080 405
1823818222
Mode: 644
1823918223
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1824018224
Path: fixtures/sys/fs/bcachefs/deadbeef-1234-5678-9012-abcdefabcdef/compression_stats
18241-
Lines: 2
18242-
compression compressed uncompressed average
18243-
lz4: 1.0G 2.0G 4k
18225+
Lines: 3
18226+
type compressed uncompressed average extent size
18227+
lz4: 19.3G 67.0G 112k
18228+
incompressible: 5.5G 5.5G 22k
1824418229
Mode: 644
1824518230
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1824618231
Directory: fixtures/sys/fs/bcachefs/deadbeef-1234-5678-9012-abcdefabcdef/counters
1824718232
Mode: 755
1824818233
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1824918234
Path: fixtures/sys/fs/bcachefs/deadbeef-1234-5678-9012-abcdefabcdef/counters/btree_node_read
1825018235
Lines: 2
18251-
since mount: 123
18252-
since filesystem creation: 67890
18236+
since mount: 12345
18237+
since filesystem creation: 67890
1825318238
Mode: 644
1825418239
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1825518240
Directory: fixtures/sys/fs/bcachefs/deadbeef-1234-5678-9012-abcdefabcdef/dev-1
1825618241
Mode: 755
1825718242
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1825818243
Path: fixtures/sys/fs/bcachefs/deadbeef-1234-5678-9012-abcdefabcdef/dev-1/bucket_size
1825918244
Lines: 1
18260-
128k
18245+
1.0M
1826118246
Mode: 644
1826218247
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1826318248
Path: fixtures/sys/fs/bcachefs/deadbeef-1234-5678-9012-abcdefabcdef/dev-1/durability
1826418249
Lines: 1
18265-
1
18250+
2
1826618251
Mode: 644
1826718252
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1826818253
Path: fixtures/sys/fs/bcachefs/deadbeef-1234-5678-9012-abcdefabcdef/dev-1/io_done
18269-
Lines: 6
18254+
Lines: 11
1827018255
read:
18271-
btree: 4411097088
18272-
data: 0
18256+
18257+
sb : 3989504
18258+
btree : 4411097088
18259+
user :5768222552064
18260+
1827318261
write:
18274-
btree: 0
18275-
data: 0
18262+
18263+
sb : 31417344
18264+
btree : 1171456
18265+
user : 39196815360
1827618266
Mode: 644
1827718267
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1827818268
Path: fixtures/sys/fs/bcachefs/deadbeef-1234-5678-9012-abcdefabcdef/dev-1/io_errors
18279-
Lines: 5
18269+
Lines: 9
1828018270
IO errors since filesystem creation
18281-
read: 197346
18282-
write: 0
18283-
IO errors since last mount
18284-
read: 0
18271+
18272+
read: 197346
18273+
write: 0
18274+
checksum:0
18275+
18276+
IO errors since 8 y ago
18277+
18278+
read: 197346
1828518279
Mode: 644
1828618280
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1828718281
Path: fixtures/sys/fs/bcachefs/deadbeef-1234-5678-9012-abcdefabcdef/dev-1/label
1828818282
Lines: 1
18289-
testdev
18283+
data0
1829018284
Mode: 644
1829118285
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1829218286
Path: fixtures/sys/fs/bcachefs/deadbeef-1234-5678-9012-abcdefabcdef/dev-1/nbuckets
@@ -18301,7 +18295,7 @@ Mode: 644
1830118295
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1830218296
Path: fixtures/sys/fs/bcachefs/deadbeef-1234-5678-9012-abcdefabcdef/errors
1830318297
Lines: 1
18304-
btree_node_read_err 5 0
18298+
btree_node_read_err 5 1234567890
1830518299
Mode: 644
1830618300
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1830718301
Directory: fixtures/sys/fs/btrfs

0 commit comments

Comments
 (0)