@@ -149,38 +149,70 @@ func isIgnoredDevice(ifName string) bool {
149
149
const netstatsLine = `%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d`
150
150
151
151
func scanInterfaceStats (netStatsFile string ) ([]info.InterfaceStats , error ) {
152
- var (
153
- bkt uint64
154
- )
155
-
156
- stats := []info.InterfaceStats {}
157
-
158
152
file , err := os .Open (netStatsFile )
159
153
if err != nil {
160
- return stats , fmt .Errorf ("failure opening %s: %v" , netStatsFile , err )
154
+ return nil , fmt .Errorf ("failure opening %s: %v" , netStatsFile , err )
161
155
}
162
156
defer file .Close ()
163
157
164
158
scanner := bufio .NewScanner (file )
165
159
160
+ // Discard header lines
161
+ for i := 0 ; i < 2 ; i ++ {
162
+ if b := scanner .Scan (); ! b {
163
+ return nil , scanner .Err ()
164
+ }
165
+ }
166
+
167
+ stats := []info.InterfaceStats {}
166
168
for scanner .Scan () {
167
169
line := scanner .Text ()
168
170
line = strings .Replace (line , ":" , "" , - 1 )
169
171
170
- i := info.InterfaceStats {}
172
+ fields := strings .Fields (line )
173
+ // If the format of the line is invalid then don't trust any of the stats
174
+ // in this file.
175
+ if len (fields ) != 17 {
176
+ return nil , fmt .Errorf ("invalid interface stats line: %v" , line )
177
+ }
178
+
179
+ devName := fields [0 ]
180
+ if isIgnoredDevice (devName ) {
181
+ continue
182
+ }
183
+
184
+ i := info.InterfaceStats {
185
+ Name : devName ,
186
+ }
171
187
172
- _ , err := fmt .Sscanf (line , netstatsLine ,
173
- & i .Name , & i .RxBytes , & i .RxPackets , & i .RxErrors , & i .RxDropped , & bkt , & bkt , & bkt ,
174
- & bkt , & i .TxBytes , & i .TxPackets , & i .TxErrors , & i .TxDropped , & bkt , & bkt , & bkt , & bkt )
188
+ statFields := append (fields [1 :5 ], fields [9 :13 ]... )
189
+ statPointers := []* uint64 {
190
+ & i .RxBytes , & i .RxPackets , & i .RxErrors , & i .RxDropped ,
191
+ & i .TxBytes , & i .TxPackets , & i .TxErrors , & i .TxDropped ,
192
+ }
175
193
176
- if err == nil && ! isIgnoredDevice (i .Name ) {
177
- stats = append (stats , i )
194
+ err := setInterfaceStatValues (statFields , statPointers )
195
+ if err != nil {
196
+ return nil , fmt .Errorf ("cannot parse interface stats (%v): %v" , err , line )
178
197
}
198
+
199
+ stats = append (stats , i )
179
200
}
180
201
181
202
return stats , nil
182
203
}
183
204
205
+ func setInterfaceStatValues (fields []string , pointers []* uint64 ) error {
206
+ for i , v := range fields {
207
+ val , err := strconv .ParseUint (v , 10 , 64 )
208
+ if err != nil {
209
+ return err
210
+ }
211
+ * pointers [i ] = val
212
+ }
213
+ return nil
214
+ }
215
+
184
216
func tcpStatsFromProc (rootFs string , pid int , file string ) (info.TcpStat , error ) {
185
217
tcpStatsFile := path .Join (rootFs , "proc" , strconv .Itoa (pid ), file )
186
218
@@ -221,8 +253,7 @@ func scanTcpStats(tcpStatsFile string) (info.TcpStat, error) {
221
253
scanner .Split (bufio .ScanLines )
222
254
223
255
// Discard header line
224
- b := scanner .Scan ()
225
- if ! b {
256
+ if b := scanner .Scan (); ! b {
226
257
return stats , scanner .Err ()
227
258
}
228
259
0 commit comments