Skip to content

Commit d9d95c9

Browse files
authored
add sriov, power state and numa node info in PciDevice (#748)
* support for sriov, numa and power management config Signed-off-by: Jain Johny <[email protected]> * use uint32 Signed-off-by: Jain Johny <[email protected]> * adjust bitsize for parseuint Signed-off-by: Jain Johny <[email protected]> * parseuint for total_msix Signed-off-by: Jain Johny <[email protected]> * revert accidental corruption of fixtures.ttar Signed-off-by: Jain Johny <[email protected]> * fix unintended fixtures changes Signed-off-by: root <[email protected]> Signed-off-by: Jain Johny <[email protected]> * make numa_node optional Signed-off-by: Jain Johny <[email protected]> --------- Signed-off-by: Jain Johny <[email protected]> Signed-off-by: root <[email protected]>
1 parent e9627e2 commit d9d95c9

File tree

3 files changed

+1083
-4
lines changed

3 files changed

+1083
-4
lines changed

sysfs/pci_device.go

Lines changed: 149 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,24 @@ import (
2626
"github.com/prometheus/procfs/internal/util"
2727
)
2828

29+
// PciPowerState represents the power state of a PCI device.
30+
type PciPowerState string
31+
32+
const (
33+
PciPowerStateUnknown PciPowerState = "unknown"
34+
PciPowerStateError PciPowerState = "error"
35+
PciPowerStateD0 PciPowerState = "D0"
36+
PciPowerStateD1 PciPowerState = "D1"
37+
PciPowerStateD2 PciPowerState = "D2"
38+
PciPowerStateD3Hot PciPowerState = "D3hot"
39+
PciPowerStateD3Cold PciPowerState = "D3cold"
40+
)
41+
42+
// String returns the string representation of the power state.
43+
func (p PciPowerState) String() string {
44+
return string(p)
45+
}
46+
2947
const pciDevicesPath = "bus/pci/devices"
3048

3149
// PciDeviceLocation represents the location of the device attached.
@@ -63,10 +81,23 @@ type PciDevice struct {
6381
SubsystemDevice uint32 // /sys/bus/pci/devices/<Location>/subsystem_device
6482
Revision uint32 // /sys/bus/pci/devices/<Location>/revision
6583

84+
NumaNode *int32 // /sys/bus/pci/devices/<Location>/numa_node
85+
6686
MaxLinkSpeed *float64 // /sys/bus/pci/devices/<Location>/max_link_speed
6787
MaxLinkWidth *float64 // /sys/bus/pci/devices/<Location>/max_link_width
6888
CurrentLinkSpeed *float64 // /sys/bus/pci/devices/<Location>/current_link_speed
6989
CurrentLinkWidth *float64 // /sys/bus/pci/devices/<Location>/current_link_width
90+
91+
SriovDriversAutoprobe *bool // /sys/bus/pci/devices/<Location>/sriov_drivers_autoprobe
92+
SriovNumvfs *uint32 // /sys/bus/pci/devices/<Location>/sriov_numvfs
93+
SriovOffset *uint32 // /sys/bus/pci/devices/<Location>/sriov_offset
94+
SriovStride *uint32 // /sys/bus/pci/devices/<Location>/sriov_stride
95+
SriovTotalvfs *uint32 // /sys/bus/pci/devices/<Location>/sriov_totalvfs
96+
SriovVfDevice *uint32 // /sys/bus/pci/devices/<Location>/sriov_vf_device
97+
SriovVfTotalMsix *uint64 // /sys/bus/pci/devices/<Location>/sriov_vf_total_msix
98+
99+
D3coldAllowed *bool // /sys/bus/pci/devices/<Location>/d3cold_allowed
100+
PowerState *PciPowerState // /sys/bus/pci/devices/<Location>/power_state
70101
}
71102

72103
func (pd PciDevice) Name() string {
@@ -204,7 +235,7 @@ func (fs FS) parsePciDevice(name string) (*PciDevice, error) {
204235
}
205236
}
206237

207-
for _, f := range [...]string{"max_link_speed", "max_link_width", "current_link_speed", "current_link_width"} {
238+
for _, f := range [...]string{"max_link_speed", "max_link_width", "current_link_speed", "current_link_width", "numa_node"} {
208239
name := filepath.Join(path, f)
209240
valueStr, err := util.SysReadFile(name)
210241
if err != nil {
@@ -254,6 +285,123 @@ func (fs FS) parsePciDevice(name string) (*PciDevice, error) {
254285
case "current_link_width":
255286
device.CurrentLinkWidth = &v
256287
}
288+
289+
case "numa_node":
290+
value, err := strconv.ParseInt(valueStr, 10, 32)
291+
if err != nil {
292+
return nil, fmt.Errorf("failed to parse %s %q: %w", f, valueStr, err)
293+
}
294+
v := int32(value)
295+
device.NumaNode = &v
296+
}
297+
}
298+
299+
// Parse SR-IOV files (these are optional and may not exist for all devices)
300+
for _, f := range [...]string{"sriov_drivers_autoprobe", "sriov_numvfs", "sriov_offset", "sriov_stride", "sriov_totalvfs", "sriov_vf_device", "sriov_vf_total_msix"} {
301+
name := filepath.Join(path, f)
302+
valueStr, err := util.SysReadFile(name)
303+
if err != nil {
304+
if os.IsNotExist(err) {
305+
continue // SR-IOV files are optional
306+
}
307+
return nil, fmt.Errorf("failed to read SR-IOV file %q: %w", name, err)
308+
}
309+
310+
valueStr = strings.TrimSpace(valueStr)
311+
if valueStr == "" {
312+
continue
313+
}
314+
315+
switch f {
316+
case "sriov_drivers_autoprobe":
317+
// sriov_drivers_autoprobe is a boolean (0 or 1)
318+
value, err := strconv.ParseInt(valueStr, 10, 32)
319+
if err != nil {
320+
return nil, fmt.Errorf("failed to parse SR-IOV boolean %q: %w", valueStr, err)
321+
}
322+
v := value != 0
323+
device.SriovDriversAutoprobe = &v
324+
325+
case "sriov_numvfs":
326+
value, err := strconv.ParseUint(valueStr, 10, 32)
327+
if err != nil {
328+
return nil, fmt.Errorf("failed to parse SR-IOV integer %q: %w", valueStr, err)
329+
}
330+
v := uint32(value)
331+
device.SriovNumvfs = &v
332+
333+
case "sriov_offset":
334+
value, err := strconv.ParseUint(valueStr, 10, 32)
335+
if err != nil {
336+
return nil, fmt.Errorf("failed to parse SR-IOV integer %q: %w", valueStr, err)
337+
}
338+
v := uint32(value)
339+
device.SriovOffset = &v
340+
341+
case "sriov_stride":
342+
value, err := strconv.ParseUint(valueStr, 10, 32)
343+
if err != nil {
344+
return nil, fmt.Errorf("failed to parse SR-IOV integer %q: %w", valueStr, err)
345+
}
346+
v := uint32(value)
347+
device.SriovStride = &v
348+
349+
case "sriov_totalvfs":
350+
value, err := strconv.ParseUint(valueStr, 10, 32)
351+
if err != nil {
352+
return nil, fmt.Errorf("failed to parse SR-IOV integer %q: %w", valueStr, err)
353+
}
354+
v := uint32(value)
355+
device.SriovTotalvfs = &v
356+
357+
case "sriov_vf_device":
358+
value, err := strconv.ParseUint(valueStr, 10, 32)
359+
if err != nil {
360+
return nil, fmt.Errorf("failed to parse SR-IOV integer %q: %w", valueStr, err)
361+
}
362+
v := uint32(value)
363+
device.SriovVfDevice = &v
364+
365+
case "sriov_vf_total_msix":
366+
value, err := strconv.ParseUint(valueStr, 10, 64)
367+
if err != nil {
368+
return nil, fmt.Errorf("failed to parse SR-IOV integer %q: %w", valueStr, err)
369+
}
370+
v := uint64(value)
371+
device.SriovVfTotalMsix = &v
372+
}
373+
}
374+
375+
// Parse power management files (these are optional and may not exist for all devices)
376+
for _, f := range [...]string{"d3cold_allowed", "power_state"} {
377+
name := filepath.Join(path, f)
378+
valueStr, err := util.SysReadFile(name)
379+
if err != nil {
380+
if os.IsNotExist(err) {
381+
continue // Power management files are optional
382+
}
383+
return nil, fmt.Errorf("failed to read power management file %q: %w", name, err)
384+
}
385+
386+
valueStr = strings.TrimSpace(valueStr)
387+
if valueStr == "" {
388+
continue
389+
}
390+
391+
switch f {
392+
case "d3cold_allowed":
393+
// d3cold_allowed is a boolean (0 or 1)
394+
value, err := strconv.ParseInt(valueStr, 10, 32)
395+
if err != nil {
396+
return nil, fmt.Errorf("failed to parse d3cold_allowed boolean %q: %w", valueStr, err)
397+
}
398+
v := value != 0
399+
device.D3coldAllowed = &v
400+
401+
case "power_state":
402+
// power_state is a string (one of: "unknown", "error", "D0", "D1", "D2", "D3hot", "D3cold")
403+
powerState := PciPowerState(valueStr)
404+
device.PowerState = &powerState
257405
}
258406
}
259407

sysfs/pci_device_test.go

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,25 @@ func TestPciDevices(t *testing.T) {
3434
}
3535

3636
var (
37-
LinkSpeed8GTs = 8.0
38-
LinkWidth4 = 4.0
39-
LinkWidth8 = 8.0
37+
LinkSpeed8GTs = 8.0
38+
LinkSpeed16GTs = 16.0
39+
LinkWidth4 = 4.0
40+
LinkWidth8 = 8.0
41+
42+
// SR-IOV test values
43+
SriovDriversAutoprobe = true
44+
SriovNumvfs = uint32(0)
45+
SriovOffset = uint32(8)
46+
SriovStride = uint32(1)
47+
SriovTotalvfs = uint32(128)
48+
SriovVfDevice = uint32(1889)
49+
SriovVfTotalMsix = uint64(4294967033)
50+
51+
// Optional device test values
52+
NumaNode = int32(1)
53+
NumaNodeNeg1 = int32(-1)
54+
D3coldAllowed = true
55+
PowerState = PciPowerStateD0
4056
)
4157
want := PciDevices{
4258
"0000:00:02:1": PciDevice{
@@ -54,11 +70,15 @@ func TestPciDevices(t *testing.T) {
5470
SubsystemVendor: 0x17aa,
5571
SubsystemDevice: 0x5095,
5672
Revision: 0x00,
73+
NumaNode: &NumaNodeNeg1,
5774

5875
MaxLinkSpeed: &LinkSpeed8GTs,
5976
MaxLinkWidth: &LinkWidth8,
6077
CurrentLinkSpeed: &LinkSpeed8GTs,
6178
CurrentLinkWidth: &LinkWidth4,
79+
80+
D3coldAllowed: &D3coldAllowed,
81+
PowerState: &PowerState,
6282
},
6383
"0000:01:00:0": PciDevice{
6484
Location: PciDeviceLocation{
@@ -80,11 +100,50 @@ func TestPciDevices(t *testing.T) {
80100
SubsystemVendor: 0xc0a9,
81101
SubsystemDevice: 0x5021,
82102
Revision: 0x01,
103+
NumaNode: &NumaNodeNeg1,
83104

84105
MaxLinkSpeed: &LinkSpeed8GTs,
85106
MaxLinkWidth: &LinkWidth4,
86107
CurrentLinkSpeed: &LinkSpeed8GTs,
87108
CurrentLinkWidth: &LinkWidth4,
109+
110+
D3coldAllowed: &D3coldAllowed,
111+
PowerState: &PowerState,
112+
},
113+
"0000:a2:00:0": PciDevice{
114+
Location: PciDeviceLocation{
115+
Segment: 0,
116+
Bus: 0xa2,
117+
Device: 0,
118+
Function: 0,
119+
},
120+
ParentLocation: nil,
121+
122+
Class: 0x020000,
123+
Vendor: 0x8086,
124+
Device: 0x159b,
125+
SubsystemVendor: 0x8086,
126+
SubsystemDevice: 0x0003,
127+
Revision: 0x02,
128+
NumaNode: &NumaNode,
129+
130+
MaxLinkSpeed: &LinkSpeed16GTs,
131+
MaxLinkWidth: &LinkWidth8,
132+
CurrentLinkSpeed: &LinkSpeed16GTs,
133+
CurrentLinkWidth: &LinkWidth8,
134+
135+
// SR-IOV fields
136+
SriovDriversAutoprobe: &SriovDriversAutoprobe,
137+
SriovNumvfs: &SriovNumvfs,
138+
SriovOffset: &SriovOffset,
139+
SriovStride: &SriovStride,
140+
SriovTotalvfs: &SriovTotalvfs,
141+
SriovVfDevice: &SriovVfDevice,
142+
SriovVfTotalMsix: &SriovVfTotalMsix,
143+
144+
// Power management fields
145+
D3coldAllowed: &D3coldAllowed,
146+
PowerState: &PowerState,
88147
},
89148
}
90149

0 commit comments

Comments
 (0)