1
2
3
4
5
6
7
8
9
10
11
12
13
14 package procfs
15
16 import (
17 "bufio"
18 "errors"
19 "os"
20 "sort"
21 "strconv"
22 "strings"
23 )
24
25
26 type NetDevLine struct {
27 Name string `json:"name"`
28 RxBytes uint64 `json:"rx_bytes"`
29 RxPackets uint64 `json:"rx_packets"`
30 RxErrors uint64 `json:"rx_errors"`
31 RxDropped uint64 `json:"rx_dropped"`
32 RxFIFO uint64 `json:"rx_fifo"`
33 RxFrame uint64 `json:"rx_frame"`
34 RxCompressed uint64 `json:"rx_compressed"`
35 RxMulticast uint64 `json:"rx_multicast"`
36 TxBytes uint64 `json:"tx_bytes"`
37 TxPackets uint64 `json:"tx_packets"`
38 TxErrors uint64 `json:"tx_errors"`
39 TxDropped uint64 `json:"tx_dropped"`
40 TxFIFO uint64 `json:"tx_fifo"`
41 TxCollisions uint64 `json:"tx_collisions"`
42 TxCarrier uint64 `json:"tx_carrier"`
43 TxCompressed uint64 `json:"tx_compressed"`
44 }
45
46
47
48 type NetDev map[string]NetDevLine
49
50
51 func (fs FS) NetDev() (NetDev, error) {
52 return newNetDev(fs.proc.Path("net/dev"))
53 }
54
55
56 func (p Proc) NetDev() (NetDev, error) {
57 return newNetDev(p.path("net/dev"))
58 }
59
60
61 func newNetDev(file string) (NetDev, error) {
62 f, err := os.Open(file)
63 if err != nil {
64 return NetDev{}, err
65 }
66 defer f.Close()
67
68 netDev := NetDev{}
69 s := bufio.NewScanner(f)
70 for n := 0; s.Scan(); n++ {
71
72 if n < 2 {
73 continue
74 }
75
76 line, err := netDev.parseLine(s.Text())
77 if err != nil {
78 return netDev, err
79 }
80
81 netDev[line.Name] = *line
82 }
83
84 return netDev, s.Err()
85 }
86
87
88
89 func (netDev NetDev) parseLine(rawLine string) (*NetDevLine, error) {
90 idx := strings.LastIndex(rawLine, ":")
91 if idx == -1 {
92 return nil, errors.New("invalid net/dev line, missing colon")
93 }
94 fields := strings.Fields(strings.TrimSpace(rawLine[idx+1:]))
95
96 var err error
97 line := &NetDevLine{}
98
99
100 line.Name = strings.TrimSpace(rawLine[:idx])
101 if line.Name == "" {
102 return nil, errors.New("invalid net/dev line, empty interface name")
103 }
104
105
106 line.RxBytes, err = strconv.ParseUint(fields[0], 10, 64)
107 if err != nil {
108 return nil, err
109 }
110 line.RxPackets, err = strconv.ParseUint(fields[1], 10, 64)
111 if err != nil {
112 return nil, err
113 }
114 line.RxErrors, err = strconv.ParseUint(fields[2], 10, 64)
115 if err != nil {
116 return nil, err
117 }
118 line.RxDropped, err = strconv.ParseUint(fields[3], 10, 64)
119 if err != nil {
120 return nil, err
121 }
122 line.RxFIFO, err = strconv.ParseUint(fields[4], 10, 64)
123 if err != nil {
124 return nil, err
125 }
126 line.RxFrame, err = strconv.ParseUint(fields[5], 10, 64)
127 if err != nil {
128 return nil, err
129 }
130 line.RxCompressed, err = strconv.ParseUint(fields[6], 10, 64)
131 if err != nil {
132 return nil, err
133 }
134 line.RxMulticast, err = strconv.ParseUint(fields[7], 10, 64)
135 if err != nil {
136 return nil, err
137 }
138
139
140 line.TxBytes, err = strconv.ParseUint(fields[8], 10, 64)
141 if err != nil {
142 return nil, err
143 }
144 line.TxPackets, err = strconv.ParseUint(fields[9], 10, 64)
145 if err != nil {
146 return nil, err
147 }
148 line.TxErrors, err = strconv.ParseUint(fields[10], 10, 64)
149 if err != nil {
150 return nil, err
151 }
152 line.TxDropped, err = strconv.ParseUint(fields[11], 10, 64)
153 if err != nil {
154 return nil, err
155 }
156 line.TxFIFO, err = strconv.ParseUint(fields[12], 10, 64)
157 if err != nil {
158 return nil, err
159 }
160 line.TxCollisions, err = strconv.ParseUint(fields[13], 10, 64)
161 if err != nil {
162 return nil, err
163 }
164 line.TxCarrier, err = strconv.ParseUint(fields[14], 10, 64)
165 if err != nil {
166 return nil, err
167 }
168 line.TxCompressed, err = strconv.ParseUint(fields[15], 10, 64)
169 if err != nil {
170 return nil, err
171 }
172
173 return line, nil
174 }
175
176
177
178 func (netDev NetDev) Total() NetDevLine {
179 total := NetDevLine{}
180
181 names := make([]string, 0, len(netDev))
182 for _, ifc := range netDev {
183 names = append(names, ifc.Name)
184 total.RxBytes += ifc.RxBytes
185 total.RxPackets += ifc.RxPackets
186 total.RxErrors += ifc.RxErrors
187 total.RxDropped += ifc.RxDropped
188 total.RxFIFO += ifc.RxFIFO
189 total.RxFrame += ifc.RxFrame
190 total.RxCompressed += ifc.RxCompressed
191 total.RxMulticast += ifc.RxMulticast
192 total.TxBytes += ifc.TxBytes
193 total.TxPackets += ifc.TxPackets
194 total.TxErrors += ifc.TxErrors
195 total.TxDropped += ifc.TxDropped
196 total.TxFIFO += ifc.TxFIFO
197 total.TxCollisions += ifc.TxCollisions
198 total.TxCarrier += ifc.TxCarrier
199 total.TxCompressed += ifc.TxCompressed
200 }
201 sort.Strings(names)
202 total.Name = strings.Join(names, ", ")
203
204 return total
205 }
206
View as plain text