| 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 | // ProcNetstat models the content of /proc/<pid>/net/netstat. |
| 28 | type ProcNetstat struct { |
| 29 | // The process ID. |
| 30 | PID int |
| 31 | TcpExt |
| 32 | IpExt |
| 33 | } |
| 34 | |
| 35 | type TcpExt struct { // nolint:revive |
| 36 | SyncookiesSent *float64 |
| 37 | SyncookiesRecv *float64 |
| 38 | SyncookiesFailed *float64 |
| 39 | EmbryonicRsts *float64 |
| 40 | PruneCalled *float64 |
| 41 | RcvPruned *float64 |
| 42 | OfoPruned *float64 |
| 43 | OutOfWindowIcmps *float64 |
| 44 | LockDroppedIcmps *float64 |
| 45 | ArpFilter *float64 |
| 46 | TW *float64 |
| 47 | TWRecycled *float64 |
| 48 | TWKilled *float64 |
| 49 | PAWSActive *float64 |
| 50 | PAWSEstab *float64 |
| 51 | DelayedACKs *float64 |
| 52 | DelayedACKLocked *float64 |
| 53 | DelayedACKLost *float64 |
| 54 | ListenOverflows *float64 |
| 55 | ListenDrops *float64 |
| 56 | TCPHPHits *float64 |
| 57 | TCPPureAcks *float64 |
| 58 | TCPHPAcks *float64 |
| 59 | TCPRenoRecovery *float64 |
| 60 | TCPSackRecovery *float64 |
| 61 | TCPSACKReneging *float64 |
| 62 | TCPSACKReorder *float64 |
| 63 | TCPRenoReorder *float64 |
| 64 | TCPTSReorder *float64 |
| 65 | TCPFullUndo *float64 |
| 66 | TCPPartialUndo *float64 |
| 67 | TCPDSACKUndo *float64 |
| 68 | TCPLossUndo *float64 |
| 69 | TCPLostRetransmit *float64 |
| 70 | TCPRenoFailures *float64 |
| 71 | TCPSackFailures *float64 |
| 72 | TCPLossFailures *float64 |
| 73 | TCPFastRetrans *float64 |
| 74 | TCPSlowStartRetrans *float64 |
| 75 | TCPTimeouts *float64 |
| 76 | TCPLossProbes *float64 |
| 77 | TCPLossProbeRecovery *float64 |
| 78 | TCPRenoRecoveryFail *float64 |
| 79 | TCPSackRecoveryFail *float64 |
| 80 | TCPRcvCollapsed *float64 |
| 81 | TCPDSACKOldSent *float64 |
| 82 | TCPDSACKOfoSent *float64 |
| 83 | TCPDSACKRecv *float64 |
| 84 | TCPDSACKOfoRecv *float64 |
| 85 | TCPAbortOnData *float64 |
| 86 | TCPAbortOnClose *float64 |
| 87 | TCPAbortOnMemory *float64 |
| 88 | TCPAbortOnTimeout *float64 |
| 89 | TCPAbortOnLinger *float64 |
| 90 | TCPAbortFailed *float64 |
| 91 | TCPMemoryPressures *float64 |
| 92 | TCPMemoryPressuresChrono *float64 |
| 93 | TCPSACKDiscard *float64 |
| 94 | TCPDSACKIgnoredOld *float64 |
| 95 | TCPDSACKIgnoredNoUndo *float64 |
| 96 | TCPSpuriousRTOs *float64 |
| 97 | TCPMD5NotFound *float64 |
| 98 | TCPMD5Unexpected *float64 |
| 99 | TCPMD5Failure *float64 |
| 100 | TCPSackShifted *float64 |
| 101 | TCPSackMerged *float64 |
| 102 | TCPSackShiftFallback *float64 |
| 103 | TCPBacklogDrop *float64 |
| 104 | PFMemallocDrop *float64 |
| 105 | TCPMinTTLDrop *float64 |
| 106 | TCPDeferAcceptDrop *float64 |
| 107 | IPReversePathFilter *float64 |
| 108 | TCPTimeWaitOverflow *float64 |
| 109 | TCPReqQFullDoCookies *float64 |
| 110 | TCPReqQFullDrop *float64 |
| 111 | TCPRetransFail *float64 |
| 112 | TCPRcvCoalesce *float64 |
| 113 | TCPRcvQDrop *float64 |
| 114 | TCPOFOQueue *float64 |
| 115 | TCPOFODrop *float64 |
| 116 | TCPOFOMerge *float64 |
| 117 | TCPChallengeACK *float64 |
| 118 | TCPSYNChallenge *float64 |
| 119 | TCPFastOpenActive *float64 |
| 120 | TCPFastOpenActiveFail *float64 |
| 121 | TCPFastOpenPassive *float64 |
| 122 | TCPFastOpenPassiveFail *float64 |
| 123 | TCPFastOpenListenOverflow *float64 |
| 124 | TCPFastOpenCookieReqd *float64 |
| 125 | TCPFastOpenBlackhole *float64 |
| 126 | TCPSpuriousRtxHostQueues *float64 |
| 127 | BusyPollRxPackets *float64 |
| 128 | TCPAutoCorking *float64 |
| 129 | TCPFromZeroWindowAdv *float64 |
| 130 | TCPToZeroWindowAdv *float64 |
| 131 | TCPWantZeroWindowAdv *float64 |
| 132 | TCPSynRetrans *float64 |
| 133 | TCPOrigDataSent *float64 |
| 134 | TCPHystartTrainDetect *float64 |
| 135 | TCPHystartTrainCwnd *float64 |
| 136 | TCPHystartDelayDetect *float64 |
| 137 | TCPHystartDelayCwnd *float64 |
| 138 | TCPACKSkippedSynRecv *float64 |
| 139 | TCPACKSkippedPAWS *float64 |
| 140 | TCPACKSkippedSeq *float64 |
| 141 | TCPACKSkippedFinWait2 *float64 |
| 142 | TCPACKSkippedTimeWait *float64 |
| 143 | TCPACKSkippedChallenge *float64 |
| 144 | TCPWinProbe *float64 |
| 145 | TCPKeepAlive *float64 |
| 146 | TCPMTUPFail *float64 |
| 147 | TCPMTUPSuccess *float64 |
| 148 | TCPWqueueTooBig *float64 |
| 149 | } |
| 150 | |
| 151 | type IpExt struct { // nolint:revive |
| 152 | InNoRoutes *float64 |
| 153 | InTruncatedPkts *float64 |
| 154 | InMcastPkts *float64 |
| 155 | OutMcastPkts *float64 |
| 156 | InBcastPkts *float64 |
| 157 | OutBcastPkts *float64 |
| 158 | InOctets *float64 |
| 159 | OutOctets *float64 |
| 160 | InMcastOctets *float64 |
| 161 | OutMcastOctets *float64 |
| 162 | InBcastOctets *float64 |
| 163 | OutBcastOctets *float64 |
| 164 | InCsumErrors *float64 |
| 165 | InNoECTPkts *float64 |
| 166 | InECT1Pkts *float64 |
| 167 | InECT0Pkts *float64 |
| 168 | InCEPkts *float64 |
| 169 | ReasmOverlaps *float64 |
| 170 | } |
| 171 | |
| 172 | func (p Proc) Netstat() (ProcNetstat, error) { |
| 173 | filename := p.path("net/netstat") |
| 174 | data, err := util.ReadFileNoStat(filename) |
| 175 | if err != nil { |
| 176 | return ProcNetstat{PID: p.PID}, err |
| 177 | } |
| 178 | procNetstat, err := parseProcNetstat(bytes.NewReader(data), filename) |
| 179 | procNetstat.PID = p.PID |
| 180 | return procNetstat, err |
| 181 | } |
| 182 | |
| 183 | // parseProcNetstat parses the metrics from proc/<pid>/net/netstat file |
| 184 | // and returns a ProcNetstat structure. |
| 185 | func parseProcNetstat(r io.Reader, fileName string) (ProcNetstat, error) { |
| 186 | var ( |
| 187 | scanner = bufio.NewScanner(r) |
| 188 | procNetstat = ProcNetstat{} |
| 189 | ) |
| 190 | |
| 191 | for scanner.Scan() { |
| 192 | nameParts := strings.Split(scanner.Text(), " ") |
| 193 | scanner.Scan() |
| 194 | valueParts := strings.Split(scanner.Text(), " ") |
| 195 | // Remove trailing :. |
| 196 | protocol := strings.TrimSuffix(nameParts[0], ":") |
| 197 | if len(nameParts) != len(valueParts) { |
| 198 | return procNetstat, fmt.Errorf("%w: mismatch field count mismatch in %s: %s", |
| 199 | ErrFileParse, fileName, protocol) |
| 200 | } |
| 201 | for i := 1; i < len(nameParts); i++ { |
| 202 | value, err := strconv.ParseFloat(valueParts[i], 64) |
| 203 | if err != nil { |
| 204 | return procNetstat, err |
| 205 | } |
| 206 | key := nameParts[i] |
| 207 | |
| 208 | switch protocol { |
| 209 | case "TcpExt": |
| 210 | switch key { |
| 211 | case "SyncookiesSent": |
| 212 | procNetstat.SyncookiesSent = &value |
| 213 | case "SyncookiesRecv": |
| 214 | procNetstat.SyncookiesRecv = &value |
| 215 | case "SyncookiesFailed": |
| 216 | procNetstat.SyncookiesFailed = &value |
| 217 | case "EmbryonicRsts": |
| 218 | procNetstat.EmbryonicRsts = &value |
| 219 | case "PruneCalled": |
| 220 | procNetstat.PruneCalled = &value |
| 221 | case "RcvPruned": |
| 222 | procNetstat.RcvPruned = &value |
| 223 | case "OfoPruned": |
| 224 | procNetstat.OfoPruned = &value |
| 225 | case "OutOfWindowIcmps": |
| 226 | procNetstat.OutOfWindowIcmps = &value |
| 227 | case "LockDroppedIcmps": |
| 228 | procNetstat.LockDroppedIcmps = &value |
| 229 | case "ArpFilter": |
| 230 | procNetstat.ArpFilter = &value |
| 231 | case "TW": |
| 232 | procNetstat.TW = &value |
| 233 | case "TWRecycled": |
| 234 | procNetstat.TWRecycled = &value |
| 235 | case "TWKilled": |
| 236 | procNetstat.TWKilled = &value |
| 237 | case "PAWSActive": |
| 238 | procNetstat.PAWSActive = &value |
| 239 | case "PAWSEstab": |
| 240 | procNetstat.PAWSEstab = &value |
| 241 | case "DelayedACKs": |
| 242 | procNetstat.DelayedACKs = &value |
| 243 | case "DelayedACKLocked": |
| 244 | procNetstat.DelayedACKLocked = &value |
| 245 | case "DelayedACKLost": |
| 246 | procNetstat.DelayedACKLost = &value |
| 247 | case "ListenOverflows": |
| 248 | procNetstat.ListenOverflows = &value |
| 249 | case "ListenDrops": |
| 250 | procNetstat.ListenDrops = &value |
| 251 | case "TCPHPHits": |
| 252 | procNetstat.TCPHPHits = &value |
| 253 | case "TCPPureAcks": |
| 254 | procNetstat.TCPPureAcks = &value |
| 255 | case "TCPHPAcks": |
| 256 | procNetstat.TCPHPAcks = &value |
| 257 | case "TCPRenoRecovery": |
| 258 | procNetstat.TCPRenoRecovery = &value |
| 259 | case "TCPSackRecovery": |
| 260 | procNetstat.TCPSackRecovery = &value |
| 261 | case "TCPSACKReneging": |
| 262 | procNetstat.TCPSACKReneging = &value |
| 263 | case "TCPSACKReorder": |
| 264 | procNetstat.TCPSACKReorder = &value |
| 265 | case "TCPRenoReorder": |
| 266 | procNetstat.TCPRenoReorder = &value |
| 267 | case "TCPTSReorder": |
| 268 | procNetstat.TCPTSReorder = &value |
| 269 | case "TCPFullUndo": |
| 270 | procNetstat.TCPFullUndo = &value |
| 271 | case "TCPPartialUndo": |
| 272 | procNetstat.TCPPartialUndo = &value |
| 273 | case "TCPDSACKUndo": |
| 274 | procNetstat.TCPDSACKUndo = &value |
| 275 | case "TCPLossUndo": |
| 276 | procNetstat.TCPLossUndo = &value |
| 277 | case "TCPLostRetransmit": |
| 278 | procNetstat.TCPLostRetransmit = &value |
| 279 | case "TCPRenoFailures": |
| 280 | procNetstat.TCPRenoFailures = &value |
| 281 | case "TCPSackFailures": |
| 282 | procNetstat.TCPSackFailures = &value |
| 283 | case "TCPLossFailures": |
| 284 | procNetstat.TCPLossFailures = &value |
| 285 | case "TCPFastRetrans": |
| 286 | procNetstat.TCPFastRetrans = &value |
| 287 | case "TCPSlowStartRetrans": |
| 288 | procNetstat.TCPSlowStartRetrans = &value |
| 289 | case "TCPTimeouts": |
| 290 | procNetstat.TCPTimeouts = &value |
| 291 | case "TCPLossProbes": |
| 292 | procNetstat.TCPLossProbes = &value |
| 293 | case "TCPLossProbeRecovery": |
| 294 | procNetstat.TCPLossProbeRecovery = &value |
| 295 | case "TCPRenoRecoveryFail": |
| 296 | procNetstat.TCPRenoRecoveryFail = &value |
| 297 | case "TCPSackRecoveryFail": |
| 298 | procNetstat.TCPSackRecoveryFail = &value |
| 299 | case "TCPRcvCollapsed": |
| 300 | procNetstat.TCPRcvCollapsed = &value |
| 301 | case "TCPDSACKOldSent": |
| 302 | procNetstat.TCPDSACKOldSent = &value |
| 303 | case "TCPDSACKOfoSent": |
| 304 | procNetstat.TCPDSACKOfoSent = &value |
| 305 | case "TCPDSACKRecv": |
| 306 | procNetstat.TCPDSACKRecv = &value |
| 307 | case "TCPDSACKOfoRecv": |
| 308 | procNetstat.TCPDSACKOfoRecv = &value |
| 309 | case "TCPAbortOnData": |
| 310 | procNetstat.TCPAbortOnData = &value |
| 311 | case "TCPAbortOnClose": |
| 312 | procNetstat.TCPAbortOnClose = &value |
| 313 | case "TCPDeferAcceptDrop": |
| 314 | procNetstat.TCPDeferAcceptDrop = &value |
| 315 | case "IPReversePathFilter": |
| 316 | procNetstat.IPReversePathFilter = &value |
| 317 | case "TCPTimeWaitOverflow": |
| 318 | procNetstat.TCPTimeWaitOverflow = &value |
| 319 | case "TCPReqQFullDoCookies": |
| 320 | procNetstat.TCPReqQFullDoCookies = &value |
| 321 | case "TCPReqQFullDrop": |
| 322 | procNetstat.TCPReqQFullDrop = &value |
| 323 | case "TCPRetransFail": |
| 324 | procNetstat.TCPRetransFail = &value |
| 325 | case "TCPRcvCoalesce": |
| 326 | procNetstat.TCPRcvCoalesce = &value |
| 327 | case "TCPRcvQDrop": |
| 328 | procNetstat.TCPRcvQDrop = &value |
| 329 | case "TCPOFOQueue": |
| 330 | procNetstat.TCPOFOQueue = &value |
| 331 | case "TCPOFODrop": |
| 332 | procNetstat.TCPOFODrop = &value |
| 333 | case "TCPOFOMerge": |
| 334 | procNetstat.TCPOFOMerge = &value |
| 335 | case "TCPChallengeACK": |
| 336 | procNetstat.TCPChallengeACK = &value |
| 337 | case "TCPSYNChallenge": |
| 338 | procNetstat.TCPSYNChallenge = &value |
| 339 | case "TCPFastOpenActive": |
| 340 | procNetstat.TCPFastOpenActive = &value |
| 341 | case "TCPFastOpenActiveFail": |
| 342 | procNetstat.TCPFastOpenActiveFail = &value |
| 343 | case "TCPFastOpenPassive": |
| 344 | procNetstat.TCPFastOpenPassive = &value |
| 345 | case "TCPFastOpenPassiveFail": |
| 346 | procNetstat.TCPFastOpenPassiveFail = &value |
| 347 | case "TCPFastOpenListenOverflow": |
| 348 | procNetstat.TCPFastOpenListenOverflow = &value |
| 349 | case "TCPFastOpenCookieReqd": |
| 350 | procNetstat.TCPFastOpenCookieReqd = &value |
| 351 | case "TCPFastOpenBlackhole": |
| 352 | procNetstat.TCPFastOpenBlackhole = &value |
| 353 | case "TCPSpuriousRtxHostQueues": |
| 354 | procNetstat.TCPSpuriousRtxHostQueues = &value |
| 355 | case "BusyPollRxPackets": |
| 356 | procNetstat.BusyPollRxPackets = &value |
| 357 | case "TCPAutoCorking": |
| 358 | procNetstat.TCPAutoCorking = &value |
| 359 | case "TCPFromZeroWindowAdv": |
| 360 | procNetstat.TCPFromZeroWindowAdv = &value |
| 361 | case "TCPToZeroWindowAdv": |
| 362 | procNetstat.TCPToZeroWindowAdv = &value |
| 363 | case "TCPWantZeroWindowAdv": |
| 364 | procNetstat.TCPWantZeroWindowAdv = &value |
| 365 | case "TCPSynRetrans": |
| 366 | procNetstat.TCPSynRetrans = &value |
| 367 | case "TCPOrigDataSent": |
| 368 | procNetstat.TCPOrigDataSent = &value |
| 369 | case "TCPHystartTrainDetect": |
| 370 | procNetstat.TCPHystartTrainDetect = &value |
| 371 | case "TCPHystartTrainCwnd": |
| 372 | procNetstat.TCPHystartTrainCwnd = &value |
| 373 | case "TCPHystartDelayDetect": |
| 374 | procNetstat.TCPHystartDelayDetect = &value |
| 375 | case "TCPHystartDelayCwnd": |
| 376 | procNetstat.TCPHystartDelayCwnd = &value |
| 377 | case "TCPACKSkippedSynRecv": |
| 378 | procNetstat.TCPACKSkippedSynRecv = &value |
| 379 | case "TCPACKSkippedPAWS": |
| 380 | procNetstat.TCPACKSkippedPAWS = &value |
| 381 | case "TCPACKSkippedSeq": |
| 382 | procNetstat.TCPACKSkippedSeq = &value |
| 383 | case "TCPACKSkippedFinWait2": |
| 384 | procNetstat.TCPACKSkippedFinWait2 = &value |
| 385 | case "TCPACKSkippedTimeWait": |
| 386 | procNetstat.TCPACKSkippedTimeWait = &value |
| 387 | case "TCPACKSkippedChallenge": |
| 388 | procNetstat.TCPACKSkippedChallenge = &value |
| 389 | case "TCPWinProbe": |
| 390 | procNetstat.TCPWinProbe = &value |
| 391 | case "TCPKeepAlive": |
| 392 | procNetstat.TCPKeepAlive = &value |
| 393 | case "TCPMTUPFail": |
| 394 | procNetstat.TCPMTUPFail = &value |
| 395 | case "TCPMTUPSuccess": |
| 396 | procNetstat.TCPMTUPSuccess = &value |
| 397 | case "TCPWqueueTooBig": |
| 398 | procNetstat.TCPWqueueTooBig = &value |
| 399 | } |
| 400 | case "IpExt": |
| 401 | switch key { |
| 402 | case "InNoRoutes": |
| 403 | procNetstat.InNoRoutes = &value |
| 404 | case "InTruncatedPkts": |
| 405 | procNetstat.InTruncatedPkts = &value |
| 406 | case "InMcastPkts": |
| 407 | procNetstat.InMcastPkts = &value |
| 408 | case "OutMcastPkts": |
| 409 | procNetstat.OutMcastPkts = &value |
| 410 | case "InBcastPkts": |
| 411 | procNetstat.InBcastPkts = &value |
| 412 | case "OutBcastPkts": |
| 413 | procNetstat.OutBcastPkts = &value |
| 414 | case "InOctets": |
| 415 | procNetstat.InOctets = &value |
| 416 | case "OutOctets": |
| 417 | procNetstat.OutOctets = &value |
| 418 | case "InMcastOctets": |
| 419 | procNetstat.InMcastOctets = &value |
| 420 | case "OutMcastOctets": |
| 421 | procNetstat.OutMcastOctets = &value |
| 422 | case "InBcastOctets": |
| 423 | procNetstat.InBcastOctets = &value |
| 424 | case "OutBcastOctets": |
| 425 | procNetstat.OutBcastOctets = &value |
| 426 | case "InCsumErrors": |
| 427 | procNetstat.InCsumErrors = &value |
| 428 | case "InNoECTPkts": |
| 429 | procNetstat.InNoECTPkts = &value |
| 430 | case "InECT1Pkts": |
| 431 | procNetstat.InECT1Pkts = &value |
| 432 | case "InECT0Pkts": |
| 433 | procNetstat.InECT0Pkts = &value |
| 434 | case "InCEPkts": |
| 435 | procNetstat.InCEPkts = &value |
| 436 | case "ReasmOverlaps": |
| 437 | procNetstat.ReasmOverlaps = &value |
| 438 | } |
| 439 | } |
| 440 | } |
| 441 | } |
| 442 | return procNetstat, scanner.Err() |
| 443 | } |