| // Copyright 2022 The Prometheus Authors |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package procfs |
| |
| import ( |
| "bufio" |
| "bytes" |
| "fmt" |
| "io" |
| "strconv" |
| "strings" |
| |
| "github.com/prometheus/procfs/internal/util" |
| ) |
| |
| // ProcNetstat models the content of /proc/<pid>/net/netstat. |
| type ProcNetstat struct { |
| // The process ID. |
| PID int |
| TcpExt |
| IpExt |
| } |
| |
| type TcpExt struct { |
| SyncookiesSent float64 |
| SyncookiesRecv float64 |
| SyncookiesFailed float64 |
| EmbryonicRsts float64 |
| PruneCalled float64 |
| RcvPruned float64 |
| OfoPruned float64 |
| OutOfWindowIcmps float64 |
| LockDroppedIcmps float64 |
| ArpFilter float64 |
| TW float64 |
| TWRecycled float64 |
| TWKilled float64 |
| PAWSActive float64 |
| PAWSEstab float64 |
| DelayedACKs float64 |
| DelayedACKLocked float64 |
| DelayedACKLost float64 |
| ListenOverflows float64 |
| ListenDrops float64 |
| TCPHPHits float64 |
| TCPPureAcks float64 |
| TCPHPAcks float64 |
| TCPRenoRecovery float64 |
| TCPSackRecovery float64 |
| TCPSACKReneging float64 |
| TCPSACKReorder float64 |
| TCPRenoReorder float64 |
| TCPTSReorder float64 |
| TCPFullUndo float64 |
| TCPPartialUndo float64 |
| TCPDSACKUndo float64 |
| TCPLossUndo float64 |
| TCPLostRetransmit float64 |
| TCPRenoFailures float64 |
| TCPSackFailures float64 |
| TCPLossFailures float64 |
| TCPFastRetrans float64 |
| TCPSlowStartRetrans float64 |
| TCPTimeouts float64 |
| TCPLossProbes float64 |
| TCPLossProbeRecovery float64 |
| TCPRenoRecoveryFail float64 |
| TCPSackRecoveryFail float64 |
| TCPRcvCollapsed float64 |
| TCPDSACKOldSent float64 |
| TCPDSACKOfoSent float64 |
| TCPDSACKRecv float64 |
| TCPDSACKOfoRecv float64 |
| TCPAbortOnData float64 |
| TCPAbortOnClose float64 |
| TCPAbortOnMemory float64 |
| TCPAbortOnTimeout float64 |
| TCPAbortOnLinger float64 |
| TCPAbortFailed float64 |
| TCPMemoryPressures float64 |
| TCPMemoryPressuresChrono float64 |
| TCPSACKDiscard float64 |
| TCPDSACKIgnoredOld float64 |
| TCPDSACKIgnoredNoUndo float64 |
| TCPSpuriousRTOs float64 |
| TCPMD5NotFound float64 |
| TCPMD5Unexpected float64 |
| TCPMD5Failure float64 |
| TCPSackShifted float64 |
| TCPSackMerged float64 |
| TCPSackShiftFallback float64 |
| TCPBacklogDrop float64 |
| PFMemallocDrop float64 |
| TCPMinTTLDrop float64 |
| TCPDeferAcceptDrop float64 |
| IPReversePathFilter float64 |
| TCPTimeWaitOverflow float64 |
| TCPReqQFullDoCookies float64 |
| TCPReqQFullDrop float64 |
| TCPRetransFail float64 |
| TCPRcvCoalesce float64 |
| TCPOFOQueue float64 |
| TCPOFODrop float64 |
| TCPOFOMerge float64 |
| TCPChallengeACK float64 |
| TCPSYNChallenge float64 |
| TCPFastOpenActive float64 |
| TCPFastOpenActiveFail float64 |
| TCPFastOpenPassive float64 |
| TCPFastOpenPassiveFail float64 |
| TCPFastOpenListenOverflow float64 |
| TCPFastOpenCookieReqd float64 |
| TCPFastOpenBlackhole float64 |
| TCPSpuriousRtxHostQueues float64 |
| BusyPollRxPackets float64 |
| TCPAutoCorking float64 |
| TCPFromZeroWindowAdv float64 |
| TCPToZeroWindowAdv float64 |
| TCPWantZeroWindowAdv float64 |
| TCPSynRetrans float64 |
| TCPOrigDataSent float64 |
| TCPHystartTrainDetect float64 |
| TCPHystartTrainCwnd float64 |
| TCPHystartDelayDetect float64 |
| TCPHystartDelayCwnd float64 |
| TCPACKSkippedSynRecv float64 |
| TCPACKSkippedPAWS float64 |
| TCPACKSkippedSeq float64 |
| TCPACKSkippedFinWait2 float64 |
| TCPACKSkippedTimeWait float64 |
| TCPACKSkippedChallenge float64 |
| TCPWinProbe float64 |
| TCPKeepAlive float64 |
| TCPMTUPFail float64 |
| TCPMTUPSuccess float64 |
| TCPWqueueTooBig float64 |
| } |
| |
| type IpExt struct { |
| InNoRoutes float64 |
| InTruncatedPkts float64 |
| InMcastPkts float64 |
| OutMcastPkts float64 |
| InBcastPkts float64 |
| OutBcastPkts float64 |
| InOctets float64 |
| OutOctets float64 |
| InMcastOctets float64 |
| OutMcastOctets float64 |
| InBcastOctets float64 |
| OutBcastOctets float64 |
| InCsumErrors float64 |
| InNoECTPkts float64 |
| InECT1Pkts float64 |
| InECT0Pkts float64 |
| InCEPkts float64 |
| ReasmOverlaps float64 |
| } |
| |
| func (p Proc) Netstat() (ProcNetstat, error) { |
| filename := p.path("net/netstat") |
| data, err := util.ReadFileNoStat(filename) |
| if err != nil { |
| return ProcNetstat{PID: p.PID}, err |
| } |
| procNetstat, err := parseNetstat(bytes.NewReader(data), filename) |
| procNetstat.PID = p.PID |
| return procNetstat, err |
| } |
| |
| // parseNetstat parses the metrics from proc/<pid>/net/netstat file |
| // and returns a ProcNetstat structure. |
| func parseNetstat(r io.Reader, fileName string) (ProcNetstat, error) { |
| var ( |
| scanner = bufio.NewScanner(r) |
| procNetstat = ProcNetstat{} |
| ) |
| |
| for scanner.Scan() { |
| nameParts := strings.Split(scanner.Text(), " ") |
| scanner.Scan() |
| valueParts := strings.Split(scanner.Text(), " ") |
| // Remove trailing :. |
| protocol := strings.TrimSuffix(nameParts[0], ":") |
| if len(nameParts) != len(valueParts) { |
| return procNetstat, fmt.Errorf("mismatch field count mismatch in %s: %s", |
| fileName, protocol) |
| } |
| for i := 1; i < len(nameParts); i++ { |
| value, err := strconv.ParseFloat(valueParts[i], 64) |
| if err != nil { |
| return procNetstat, err |
| } |
| key := nameParts[i] |
| |
| switch protocol { |
| case "TcpExt": |
| switch key { |
| case "SyncookiesSent": |
| procNetstat.TcpExt.SyncookiesSent = value |
| case "SyncookiesRecv": |
| procNetstat.TcpExt.SyncookiesRecv = value |
| case "SyncookiesFailed": |
| procNetstat.TcpExt.SyncookiesFailed = value |
| case "EmbryonicRsts": |
| procNetstat.TcpExt.EmbryonicRsts = value |
| case "PruneCalled": |
| procNetstat.TcpExt.PruneCalled = value |
| case "RcvPruned": |
| procNetstat.TcpExt.RcvPruned = value |
| case "OfoPruned": |
| procNetstat.TcpExt.OfoPruned = value |
| case "OutOfWindowIcmps": |
| procNetstat.TcpExt.OutOfWindowIcmps = value |
| case "LockDroppedIcmps": |
| procNetstat.TcpExt.LockDroppedIcmps = value |
| case "ArpFilter": |
| procNetstat.TcpExt.ArpFilter = value |
| case "TW": |
| procNetstat.TcpExt.TW = value |
| case "TWRecycled": |
| procNetstat.TcpExt.TWRecycled = value |
| case "TWKilled": |
| procNetstat.TcpExt.TWKilled = value |
| case "PAWSActive": |
| procNetstat.TcpExt.PAWSActive = value |
| case "PAWSEstab": |
| procNetstat.TcpExt.PAWSEstab = value |
| case "DelayedACKs": |
| procNetstat.TcpExt.DelayedACKs = value |
| case "DelayedACKLocked": |
| procNetstat.TcpExt.DelayedACKLocked = value |
| case "DelayedACKLost": |
| procNetstat.TcpExt.DelayedACKLost = value |
| case "ListenOverflows": |
| procNetstat.TcpExt.ListenOverflows = value |
| case "ListenDrops": |
| procNetstat.TcpExt.ListenDrops = value |
| case "TCPHPHits": |
| procNetstat.TcpExt.TCPHPHits = value |
| case "TCPPureAcks": |
| procNetstat.TcpExt.TCPPureAcks = value |
| case "TCPHPAcks": |
| procNetstat.TcpExt.TCPHPAcks = value |
| case "TCPRenoRecovery": |
| procNetstat.TcpExt.TCPRenoRecovery = value |
| case "TCPSackRecovery": |
| procNetstat.TcpExt.TCPSackRecovery = value |
| case "TCPSACKReneging": |
| procNetstat.TcpExt.TCPSACKReneging = value |
| case "TCPSACKReorder": |
| procNetstat.TcpExt.TCPSACKReorder = value |
| case "TCPRenoReorder": |
| procNetstat.TcpExt.TCPRenoReorder = value |
| case "TCPTSReorder": |
| procNetstat.TcpExt.TCPTSReorder = value |
| case "TCPFullUndo": |
| procNetstat.TcpExt.TCPFullUndo = value |
| case "TCPPartialUndo": |
| procNetstat.TcpExt.TCPPartialUndo = value |
| case "TCPDSACKUndo": |
| procNetstat.TcpExt.TCPDSACKUndo = value |
| case "TCPLossUndo": |
| procNetstat.TcpExt.TCPLossUndo = value |
| case "TCPLostRetransmit": |
| procNetstat.TcpExt.TCPLostRetransmit = value |
| case "TCPRenoFailures": |
| procNetstat.TcpExt.TCPRenoFailures = value |
| case "TCPSackFailures": |
| procNetstat.TcpExt.TCPSackFailures = value |
| case "TCPLossFailures": |
| procNetstat.TcpExt.TCPLossFailures = value |
| case "TCPFastRetrans": |
| procNetstat.TcpExt.TCPFastRetrans = value |
| case "TCPSlowStartRetrans": |
| procNetstat.TcpExt.TCPSlowStartRetrans = value |
| case "TCPTimeouts": |
| procNetstat.TcpExt.TCPTimeouts = value |
| case "TCPLossProbes": |
| procNetstat.TcpExt.TCPLossProbes = value |
| case "TCPLossProbeRecovery": |
| procNetstat.TcpExt.TCPLossProbeRecovery = value |
| case "TCPRenoRecoveryFail": |
| procNetstat.TcpExt.TCPRenoRecoveryFail = value |
| case "TCPSackRecoveryFail": |
| procNetstat.TcpExt.TCPSackRecoveryFail = value |
| case "TCPRcvCollapsed": |
| procNetstat.TcpExt.TCPRcvCollapsed = value |
| case "TCPDSACKOldSent": |
| procNetstat.TcpExt.TCPDSACKOldSent = value |
| case "TCPDSACKOfoSent": |
| procNetstat.TcpExt.TCPDSACKOfoSent = value |
| case "TCPDSACKRecv": |
| procNetstat.TcpExt.TCPDSACKRecv = value |
| case "TCPDSACKOfoRecv": |
| procNetstat.TcpExt.TCPDSACKOfoRecv = value |
| case "TCPAbortOnData": |
| procNetstat.TcpExt.TCPAbortOnData = value |
| case "TCPAbortOnClose": |
| procNetstat.TcpExt.TCPAbortOnClose = value |
| case "TCPDeferAcceptDrop": |
| procNetstat.TcpExt.TCPDeferAcceptDrop = value |
| case "IPReversePathFilter": |
| procNetstat.TcpExt.IPReversePathFilter = value |
| case "TCPTimeWaitOverflow": |
| procNetstat.TcpExt.TCPTimeWaitOverflow = value |
| case "TCPReqQFullDoCookies": |
| procNetstat.TcpExt.TCPReqQFullDoCookies = value |
| case "TCPReqQFullDrop": |
| procNetstat.TcpExt.TCPReqQFullDrop = value |
| case "TCPRetransFail": |
| procNetstat.TcpExt.TCPRetransFail = value |
| case "TCPRcvCoalesce": |
| procNetstat.TcpExt.TCPRcvCoalesce = value |
| case "TCPOFOQueue": |
| procNetstat.TcpExt.TCPOFOQueue = value |
| case "TCPOFODrop": |
| procNetstat.TcpExt.TCPOFODrop = value |
| case "TCPOFOMerge": |
| procNetstat.TcpExt.TCPOFOMerge = value |
| case "TCPChallengeACK": |
| procNetstat.TcpExt.TCPChallengeACK = value |
| case "TCPSYNChallenge": |
| procNetstat.TcpExt.TCPSYNChallenge = value |
| case "TCPFastOpenActive": |
| procNetstat.TcpExt.TCPFastOpenActive = value |
| case "TCPFastOpenActiveFail": |
| procNetstat.TcpExt.TCPFastOpenActiveFail = value |
| case "TCPFastOpenPassive": |
| procNetstat.TcpExt.TCPFastOpenPassive = value |
| case "TCPFastOpenPassiveFail": |
| procNetstat.TcpExt.TCPFastOpenPassiveFail = value |
| case "TCPFastOpenListenOverflow": |
| procNetstat.TcpExt.TCPFastOpenListenOverflow = value |
| case "TCPFastOpenCookieReqd": |
| procNetstat.TcpExt.TCPFastOpenCookieReqd = value |
| case "TCPFastOpenBlackhole": |
| procNetstat.TcpExt.TCPFastOpenBlackhole = value |
| case "TCPSpuriousRtxHostQueues": |
| procNetstat.TcpExt.TCPSpuriousRtxHostQueues = value |
| case "BusyPollRxPackets": |
| procNetstat.TcpExt.BusyPollRxPackets = value |
| case "TCPAutoCorking": |
| procNetstat.TcpExt.TCPAutoCorking = value |
| case "TCPFromZeroWindowAdv": |
| procNetstat.TcpExt.TCPFromZeroWindowAdv = value |
| case "TCPToZeroWindowAdv": |
| procNetstat.TcpExt.TCPToZeroWindowAdv = value |
| case "TCPWantZeroWindowAdv": |
| procNetstat.TcpExt.TCPWantZeroWindowAdv = value |
| case "TCPSynRetrans": |
| procNetstat.TcpExt.TCPSynRetrans = value |
| case "TCPOrigDataSent": |
| procNetstat.TcpExt.TCPOrigDataSent = value |
| case "TCPHystartTrainDetect": |
| procNetstat.TcpExt.TCPHystartTrainDetect = value |
| case "TCPHystartTrainCwnd": |
| procNetstat.TcpExt.TCPHystartTrainCwnd = value |
| case "TCPHystartDelayDetect": |
| procNetstat.TcpExt.TCPHystartDelayDetect = value |
| case "TCPHystartDelayCwnd": |
| procNetstat.TcpExt.TCPHystartDelayCwnd = value |
| case "TCPACKSkippedSynRecv": |
| procNetstat.TcpExt.TCPACKSkippedSynRecv = value |
| case "TCPACKSkippedPAWS": |
| procNetstat.TcpExt.TCPACKSkippedPAWS = value |
| case "TCPACKSkippedSeq": |
| procNetstat.TcpExt.TCPACKSkippedSeq = value |
| case "TCPACKSkippedFinWait2": |
| procNetstat.TcpExt.TCPACKSkippedFinWait2 = value |
| case "TCPACKSkippedTimeWait": |
| procNetstat.TcpExt.TCPACKSkippedTimeWait = value |
| case "TCPACKSkippedChallenge": |
| procNetstat.TcpExt.TCPACKSkippedChallenge = value |
| case "TCPWinProbe": |
| procNetstat.TcpExt.TCPWinProbe = value |
| case "TCPKeepAlive": |
| procNetstat.TcpExt.TCPKeepAlive = value |
| case "TCPMTUPFail": |
| procNetstat.TcpExt.TCPMTUPFail = value |
| case "TCPMTUPSuccess": |
| procNetstat.TcpExt.TCPMTUPSuccess = value |
| case "TCPWqueueTooBig": |
| procNetstat.TcpExt.TCPWqueueTooBig = value |
| } |
| case "IpExt": |
| switch key { |
| case "InNoRoutes": |
| procNetstat.IpExt.InNoRoutes = value |
| case "InTruncatedPkts": |
| procNetstat.IpExt.InTruncatedPkts = value |
| case "InMcastPkts": |
| procNetstat.IpExt.InMcastPkts = value |
| case "OutMcastPkts": |
| procNetstat.IpExt.OutMcastPkts = value |
| case "InBcastPkts": |
| procNetstat.IpExt.InBcastPkts = value |
| case "OutBcastPkts": |
| procNetstat.IpExt.OutBcastPkts = value |
| case "InOctets": |
| procNetstat.IpExt.InOctets = value |
| case "OutOctets": |
| procNetstat.IpExt.OutOctets = value |
| case "InMcastOctets": |
| procNetstat.IpExt.InMcastOctets = value |
| case "OutMcastOctets": |
| procNetstat.IpExt.OutMcastOctets = value |
| case "InBcastOctets": |
| procNetstat.IpExt.InBcastOctets = value |
| case "OutBcastOctets": |
| procNetstat.IpExt.OutBcastOctets = value |
| case "InCsumErrors": |
| procNetstat.IpExt.InCsumErrors = value |
| case "InNoECTPkts": |
| procNetstat.IpExt.InNoECTPkts = value |
| case "InECT1Pkts": |
| procNetstat.IpExt.InECT1Pkts = value |
| case "InECT0Pkts": |
| procNetstat.IpExt.InECT0Pkts = value |
| case "InCEPkts": |
| procNetstat.IpExt.InCEPkts = value |
| case "ReasmOverlaps": |
| procNetstat.IpExt.ReasmOverlaps = value |
| } |
| } |
| } |
| } |
| return procNetstat, scanner.Err() |
| } |