// 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 { // nolint:revive 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 TCPRcvQDrop *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 { // nolint:revive 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 := parseProcNetstat(bytes.NewReader(data), filename) procNetstat.PID = p.PID return procNetstat, err } // parseProcNetstat parses the metrics from proc/<pid>/net/netstat file // and returns a ProcNetstat structure. func parseProcNetstat(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("%w: mismatch field count mismatch in %s: %s", ErrFileParse, 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 "TCPRcvQDrop": procNetstat.TcpExt.TCPRcvQDrop = &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() }