| Abhay Kumar | a2ae599 | 2025-11-10 14:02:24 +0000 | [diff] [blame^] | 1 | // Copyright 2022 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 | 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 | // ProcSnmp models the content of /proc/<pid>/net/snmp. |
| 28 | type ProcSnmp struct { |
| 29 | // The process ID. |
| 30 | PID int |
| 31 | Ip |
| 32 | Icmp |
| 33 | IcmpMsg |
| 34 | Tcp |
| 35 | Udp |
| 36 | UdpLite |
| 37 | } |
| 38 | |
| 39 | type Ip struct { // nolint:revive |
| 40 | Forwarding *float64 |
| 41 | DefaultTTL *float64 |
| 42 | InReceives *float64 |
| 43 | InHdrErrors *float64 |
| 44 | InAddrErrors *float64 |
| 45 | ForwDatagrams *float64 |
| 46 | InUnknownProtos *float64 |
| 47 | InDiscards *float64 |
| 48 | InDelivers *float64 |
| 49 | OutRequests *float64 |
| 50 | OutDiscards *float64 |
| 51 | OutNoRoutes *float64 |
| 52 | ReasmTimeout *float64 |
| 53 | ReasmReqds *float64 |
| 54 | ReasmOKs *float64 |
| 55 | ReasmFails *float64 |
| 56 | FragOKs *float64 |
| 57 | FragFails *float64 |
| 58 | FragCreates *float64 |
| 59 | } |
| 60 | |
| 61 | type Icmp struct { // nolint:revive |
| 62 | InMsgs *float64 |
| 63 | InErrors *float64 |
| 64 | InCsumErrors *float64 |
| 65 | InDestUnreachs *float64 |
| 66 | InTimeExcds *float64 |
| 67 | InParmProbs *float64 |
| 68 | InSrcQuenchs *float64 |
| 69 | InRedirects *float64 |
| 70 | InEchos *float64 |
| 71 | InEchoReps *float64 |
| 72 | InTimestamps *float64 |
| 73 | InTimestampReps *float64 |
| 74 | InAddrMasks *float64 |
| 75 | InAddrMaskReps *float64 |
| 76 | OutMsgs *float64 |
| 77 | OutErrors *float64 |
| 78 | OutDestUnreachs *float64 |
| 79 | OutTimeExcds *float64 |
| 80 | OutParmProbs *float64 |
| 81 | OutSrcQuenchs *float64 |
| 82 | OutRedirects *float64 |
| 83 | OutEchos *float64 |
| 84 | OutEchoReps *float64 |
| 85 | OutTimestamps *float64 |
| 86 | OutTimestampReps *float64 |
| 87 | OutAddrMasks *float64 |
| 88 | OutAddrMaskReps *float64 |
| 89 | } |
| 90 | |
| 91 | type IcmpMsg struct { |
| 92 | InType3 *float64 |
| 93 | OutType3 *float64 |
| 94 | } |
| 95 | |
| 96 | type Tcp struct { // nolint:revive |
| 97 | RtoAlgorithm *float64 |
| 98 | RtoMin *float64 |
| 99 | RtoMax *float64 |
| 100 | MaxConn *float64 |
| 101 | ActiveOpens *float64 |
| 102 | PassiveOpens *float64 |
| 103 | AttemptFails *float64 |
| 104 | EstabResets *float64 |
| 105 | CurrEstab *float64 |
| 106 | InSegs *float64 |
| 107 | OutSegs *float64 |
| 108 | RetransSegs *float64 |
| 109 | InErrs *float64 |
| 110 | OutRsts *float64 |
| 111 | InCsumErrors *float64 |
| 112 | } |
| 113 | |
| 114 | type Udp struct { // nolint:revive |
| 115 | InDatagrams *float64 |
| 116 | NoPorts *float64 |
| 117 | InErrors *float64 |
| 118 | OutDatagrams *float64 |
| 119 | RcvbufErrors *float64 |
| 120 | SndbufErrors *float64 |
| 121 | InCsumErrors *float64 |
| 122 | IgnoredMulti *float64 |
| 123 | } |
| 124 | |
| 125 | type UdpLite struct { // nolint:revive |
| 126 | InDatagrams *float64 |
| 127 | NoPorts *float64 |
| 128 | InErrors *float64 |
| 129 | OutDatagrams *float64 |
| 130 | RcvbufErrors *float64 |
| 131 | SndbufErrors *float64 |
| 132 | InCsumErrors *float64 |
| 133 | IgnoredMulti *float64 |
| 134 | } |
| 135 | |
| 136 | func (p Proc) Snmp() (ProcSnmp, error) { |
| 137 | filename := p.path("net/snmp") |
| 138 | data, err := util.ReadFileNoStat(filename) |
| 139 | if err != nil { |
| 140 | return ProcSnmp{PID: p.PID}, err |
| 141 | } |
| 142 | procSnmp, err := parseSnmp(bytes.NewReader(data), filename) |
| 143 | procSnmp.PID = p.PID |
| 144 | return procSnmp, err |
| 145 | } |
| 146 | |
| 147 | // parseSnmp parses the metrics from proc/<pid>/net/snmp file |
| 148 | // and returns a map contains those metrics (e.g. {"Ip": {"Forwarding": 2}}). |
| 149 | func parseSnmp(r io.Reader, fileName string) (ProcSnmp, error) { |
| 150 | var ( |
| 151 | scanner = bufio.NewScanner(r) |
| 152 | procSnmp = ProcSnmp{} |
| 153 | ) |
| 154 | |
| 155 | for scanner.Scan() { |
| 156 | nameParts := strings.Split(scanner.Text(), " ") |
| 157 | scanner.Scan() |
| 158 | valueParts := strings.Split(scanner.Text(), " ") |
| 159 | // Remove trailing :. |
| 160 | protocol := strings.TrimSuffix(nameParts[0], ":") |
| 161 | if len(nameParts) != len(valueParts) { |
| 162 | return procSnmp, fmt.Errorf("%w: mismatch field count mismatch in %s: %s", |
| 163 | ErrFileParse, fileName, protocol) |
| 164 | } |
| 165 | for i := 1; i < len(nameParts); i++ { |
| 166 | value, err := strconv.ParseFloat(valueParts[i], 64) |
| 167 | if err != nil { |
| 168 | return procSnmp, err |
| 169 | } |
| 170 | key := nameParts[i] |
| 171 | |
| 172 | switch protocol { |
| 173 | case "Ip": |
| 174 | switch key { |
| 175 | case "Forwarding": |
| 176 | procSnmp.Forwarding = &value |
| 177 | case "DefaultTTL": |
| 178 | procSnmp.DefaultTTL = &value |
| 179 | case "InReceives": |
| 180 | procSnmp.InReceives = &value |
| 181 | case "InHdrErrors": |
| 182 | procSnmp.InHdrErrors = &value |
| 183 | case "InAddrErrors": |
| 184 | procSnmp.InAddrErrors = &value |
| 185 | case "ForwDatagrams": |
| 186 | procSnmp.ForwDatagrams = &value |
| 187 | case "InUnknownProtos": |
| 188 | procSnmp.InUnknownProtos = &value |
| 189 | case "InDiscards": |
| 190 | procSnmp.InDiscards = &value |
| 191 | case "InDelivers": |
| 192 | procSnmp.InDelivers = &value |
| 193 | case "OutRequests": |
| 194 | procSnmp.OutRequests = &value |
| 195 | case "OutDiscards": |
| 196 | procSnmp.OutDiscards = &value |
| 197 | case "OutNoRoutes": |
| 198 | procSnmp.OutNoRoutes = &value |
| 199 | case "ReasmTimeout": |
| 200 | procSnmp.ReasmTimeout = &value |
| 201 | case "ReasmReqds": |
| 202 | procSnmp.ReasmReqds = &value |
| 203 | case "ReasmOKs": |
| 204 | procSnmp.ReasmOKs = &value |
| 205 | case "ReasmFails": |
| 206 | procSnmp.ReasmFails = &value |
| 207 | case "FragOKs": |
| 208 | procSnmp.FragOKs = &value |
| 209 | case "FragFails": |
| 210 | procSnmp.FragFails = &value |
| 211 | case "FragCreates": |
| 212 | procSnmp.FragCreates = &value |
| 213 | } |
| 214 | case "Icmp": |
| 215 | switch key { |
| 216 | case "InMsgs": |
| 217 | procSnmp.InMsgs = &value |
| 218 | case "InErrors": |
| 219 | procSnmp.Icmp.InErrors = &value |
| 220 | case "InCsumErrors": |
| 221 | procSnmp.Icmp.InCsumErrors = &value |
| 222 | case "InDestUnreachs": |
| 223 | procSnmp.InDestUnreachs = &value |
| 224 | case "InTimeExcds": |
| 225 | procSnmp.InTimeExcds = &value |
| 226 | case "InParmProbs": |
| 227 | procSnmp.InParmProbs = &value |
| 228 | case "InSrcQuenchs": |
| 229 | procSnmp.InSrcQuenchs = &value |
| 230 | case "InRedirects": |
| 231 | procSnmp.InRedirects = &value |
| 232 | case "InEchos": |
| 233 | procSnmp.InEchos = &value |
| 234 | case "InEchoReps": |
| 235 | procSnmp.InEchoReps = &value |
| 236 | case "InTimestamps": |
| 237 | procSnmp.InTimestamps = &value |
| 238 | case "InTimestampReps": |
| 239 | procSnmp.InTimestampReps = &value |
| 240 | case "InAddrMasks": |
| 241 | procSnmp.InAddrMasks = &value |
| 242 | case "InAddrMaskReps": |
| 243 | procSnmp.InAddrMaskReps = &value |
| 244 | case "OutMsgs": |
| 245 | procSnmp.OutMsgs = &value |
| 246 | case "OutErrors": |
| 247 | procSnmp.OutErrors = &value |
| 248 | case "OutDestUnreachs": |
| 249 | procSnmp.OutDestUnreachs = &value |
| 250 | case "OutTimeExcds": |
| 251 | procSnmp.OutTimeExcds = &value |
| 252 | case "OutParmProbs": |
| 253 | procSnmp.OutParmProbs = &value |
| 254 | case "OutSrcQuenchs": |
| 255 | procSnmp.OutSrcQuenchs = &value |
| 256 | case "OutRedirects": |
| 257 | procSnmp.OutRedirects = &value |
| 258 | case "OutEchos": |
| 259 | procSnmp.OutEchos = &value |
| 260 | case "OutEchoReps": |
| 261 | procSnmp.OutEchoReps = &value |
| 262 | case "OutTimestamps": |
| 263 | procSnmp.OutTimestamps = &value |
| 264 | case "OutTimestampReps": |
| 265 | procSnmp.OutTimestampReps = &value |
| 266 | case "OutAddrMasks": |
| 267 | procSnmp.OutAddrMasks = &value |
| 268 | case "OutAddrMaskReps": |
| 269 | procSnmp.OutAddrMaskReps = &value |
| 270 | } |
| 271 | case "IcmpMsg": |
| 272 | switch key { |
| 273 | case "InType3": |
| 274 | procSnmp.InType3 = &value |
| 275 | case "OutType3": |
| 276 | procSnmp.OutType3 = &value |
| 277 | } |
| 278 | case "Tcp": |
| 279 | switch key { |
| 280 | case "RtoAlgorithm": |
| 281 | procSnmp.RtoAlgorithm = &value |
| 282 | case "RtoMin": |
| 283 | procSnmp.RtoMin = &value |
| 284 | case "RtoMax": |
| 285 | procSnmp.RtoMax = &value |
| 286 | case "MaxConn": |
| 287 | procSnmp.MaxConn = &value |
| 288 | case "ActiveOpens": |
| 289 | procSnmp.ActiveOpens = &value |
| 290 | case "PassiveOpens": |
| 291 | procSnmp.PassiveOpens = &value |
| 292 | case "AttemptFails": |
| 293 | procSnmp.AttemptFails = &value |
| 294 | case "EstabResets": |
| 295 | procSnmp.EstabResets = &value |
| 296 | case "CurrEstab": |
| 297 | procSnmp.CurrEstab = &value |
| 298 | case "InSegs": |
| 299 | procSnmp.InSegs = &value |
| 300 | case "OutSegs": |
| 301 | procSnmp.OutSegs = &value |
| 302 | case "RetransSegs": |
| 303 | procSnmp.RetransSegs = &value |
| 304 | case "InErrs": |
| 305 | procSnmp.InErrs = &value |
| 306 | case "OutRsts": |
| 307 | procSnmp.OutRsts = &value |
| 308 | case "InCsumErrors": |
| 309 | procSnmp.Tcp.InCsumErrors = &value |
| 310 | } |
| 311 | case "Udp": |
| 312 | switch key { |
| 313 | case "InDatagrams": |
| 314 | procSnmp.Udp.InDatagrams = &value |
| 315 | case "NoPorts": |
| 316 | procSnmp.Udp.NoPorts = &value |
| 317 | case "InErrors": |
| 318 | procSnmp.Udp.InErrors = &value |
| 319 | case "OutDatagrams": |
| 320 | procSnmp.Udp.OutDatagrams = &value |
| 321 | case "RcvbufErrors": |
| 322 | procSnmp.Udp.RcvbufErrors = &value |
| 323 | case "SndbufErrors": |
| 324 | procSnmp.Udp.SndbufErrors = &value |
| 325 | case "InCsumErrors": |
| 326 | procSnmp.Udp.InCsumErrors = &value |
| 327 | case "IgnoredMulti": |
| 328 | procSnmp.Udp.IgnoredMulti = &value |
| 329 | } |
| 330 | case "UdpLite": |
| 331 | switch key { |
| 332 | case "InDatagrams": |
| 333 | procSnmp.UdpLite.InDatagrams = &value |
| 334 | case "NoPorts": |
| 335 | procSnmp.UdpLite.NoPorts = &value |
| 336 | case "InErrors": |
| 337 | procSnmp.UdpLite.InErrors = &value |
| 338 | case "OutDatagrams": |
| 339 | procSnmp.UdpLite.OutDatagrams = &value |
| 340 | case "RcvbufErrors": |
| 341 | procSnmp.UdpLite.RcvbufErrors = &value |
| 342 | case "SndbufErrors": |
| 343 | procSnmp.UdpLite.SndbufErrors = &value |
| 344 | case "InCsumErrors": |
| 345 | procSnmp.UdpLite.InCsumErrors = &value |
| 346 | case "IgnoredMulti": |
| 347 | procSnmp.UdpLite.IgnoredMulti = &value |
| 348 | } |
| 349 | } |
| 350 | } |
| 351 | } |
| 352 | return procSnmp, scanner.Err() |
| 353 | } |