...
1
2
3
4
5
6
7
8
9
10
11
12
13
14 package procfs
15
16 import (
17 "bufio"
18 "bytes"
19 "fmt"
20 "io"
21 "strconv"
22 "strings"
23
24 "github.com/prometheus/procfs/internal/util"
25 )
26
27
28
29
30
31
32
33
34
35 type SoftnetStat struct {
36
37 Processed uint32
38
39 Dropped uint32
40
41 TimeSqueezed uint32
42
43 CPUCollision uint32
44
45 ReceivedRps uint32
46
47 FlowLimitCount uint32
48
49 SoftnetBacklogLen uint32
50
51 Index uint32
52
53 Width int
54 }
55
56 var softNetProcFile = "net/softnet_stat"
57
58
59 func (fs FS) NetSoftnetStat() ([]SoftnetStat, error) {
60 b, err := util.ReadFileNoStat(fs.proc.Path(softNetProcFile))
61 if err != nil {
62 return nil, err
63 }
64
65 entries, err := parseSoftnet(bytes.NewReader(b))
66 if err != nil {
67 return nil, fmt.Errorf("%s: /proc/net/softnet_stat: %w", ErrFileParse, err)
68 }
69
70 return entries, nil
71 }
72
73 func parseSoftnet(r io.Reader) ([]SoftnetStat, error) {
74 const minColumns = 9
75
76 s := bufio.NewScanner(r)
77
78 var stats []SoftnetStat
79 cpuIndex := 0
80 for s.Scan() {
81 columns := strings.Fields(s.Text())
82 width := len(columns)
83 softnetStat := SoftnetStat{}
84
85 if width < minColumns {
86 return nil, fmt.Errorf("%w: detected %d columns, but expected at least %d", ErrFileParse, width, minColumns)
87 }
88
89
90 if width >= minColumns {
91 us, err := parseHexUint32s(columns[0:9])
92 if err != nil {
93 return nil, err
94 }
95
96 softnetStat.Processed = us[0]
97 softnetStat.Dropped = us[1]
98 softnetStat.TimeSqueezed = us[2]
99 softnetStat.CPUCollision = us[8]
100 }
101
102
103 if width >= 10 {
104 us, err := parseHexUint32s(columns[9:10])
105 if err != nil {
106 return nil, err
107 }
108
109 softnetStat.ReceivedRps = us[0]
110 }
111
112
113 if width >= 11 {
114 us, err := parseHexUint32s(columns[10:11])
115 if err != nil {
116 return nil, err
117 }
118
119 softnetStat.FlowLimitCount = us[0]
120 }
121
122
123 if width >= 13 {
124 us, err := parseHexUint32s(columns[11:13])
125 if err != nil {
126 return nil, err
127 }
128
129 softnetStat.SoftnetBacklogLen = us[0]
130 softnetStat.Index = us[1]
131 } else {
132
133 softnetStat.Index = uint32(cpuIndex)
134 }
135 softnetStat.Width = width
136 stats = append(stats, softnetStat)
137 cpuIndex++
138 }
139
140 return stats, nil
141 }
142
143 func parseHexUint32s(ss []string) ([]uint32, error) {
144 us := make([]uint32, 0, len(ss))
145 for _, s := range ss {
146 u, err := strconv.ParseUint(s, 16, 32)
147 if err != nil {
148 return nil, err
149 }
150
151 us = append(us, uint32(u))
152 }
153
154 return us, nil
155 }
156
View as plain text