blob: 316df5fbb74e69c713ef88d42df7395f017561ae [file] [log] [blame]
khenaidoo26721882021-08-11 17:42:52 -04001// Copyright 2020 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
14package procfs
15
16import (
17 "bufio"
18 "bytes"
19 "fmt"
20 "io"
khenaidoo26721882021-08-11 17:42:52 -040021 "strings"
22
23 "github.com/prometheus/procfs/internal/util"
24)
25
26// A ConntrackStatEntry represents one line from net/stat/nf_conntrack
Abhay Kumar40252eb2025-10-13 13:25:53 +000027// and contains netfilter conntrack statistics at one CPU core.
khenaidoo26721882021-08-11 17:42:52 -040028type ConntrackStatEntry struct {
29 Entries uint64
Abhay Kumar40252eb2025-10-13 13:25:53 +000030 Searched uint64
khenaidoo26721882021-08-11 17:42:52 -040031 Found uint64
Abhay Kumar40252eb2025-10-13 13:25:53 +000032 New uint64
khenaidoo26721882021-08-11 17:42:52 -040033 Invalid uint64
34 Ignore uint64
Abhay Kumar40252eb2025-10-13 13:25:53 +000035 Delete uint64
36 DeleteList uint64
khenaidoo26721882021-08-11 17:42:52 -040037 Insert uint64
38 InsertFailed uint64
39 Drop uint64
40 EarlyDrop uint64
41 SearchRestart uint64
42}
43
Abhay Kumar40252eb2025-10-13 13:25:53 +000044// ConntrackStat retrieves netfilter's conntrack statistics, split by CPU cores.
khenaidoo26721882021-08-11 17:42:52 -040045func (fs FS) ConntrackStat() ([]ConntrackStatEntry, error) {
46 return readConntrackStat(fs.proc.Path("net", "stat", "nf_conntrack"))
47}
48
Abhay Kumar40252eb2025-10-13 13:25:53 +000049// Parses a slice of ConntrackStatEntries from the given filepath.
khenaidoo26721882021-08-11 17:42:52 -040050func readConntrackStat(path string) ([]ConntrackStatEntry, error) {
51 // This file is small and can be read with one syscall.
52 b, err := util.ReadFileNoStat(path)
53 if err != nil {
54 // Do not wrap this error so the caller can detect os.IsNotExist and
55 // similar conditions.
56 return nil, err
57 }
58
59 stat, err := parseConntrackStat(bytes.NewReader(b))
60 if err != nil {
Abhay Kumar40252eb2025-10-13 13:25:53 +000061 return nil, fmt.Errorf("%w: Cannot read file: %v: %w", ErrFileRead, path, err)
khenaidoo26721882021-08-11 17:42:52 -040062 }
63
64 return stat, nil
65}
66
Abhay Kumar40252eb2025-10-13 13:25:53 +000067// Reads the contents of a conntrack statistics file and parses a slice of ConntrackStatEntries.
khenaidoo26721882021-08-11 17:42:52 -040068func parseConntrackStat(r io.Reader) ([]ConntrackStatEntry, error) {
69 var entries []ConntrackStatEntry
70
71 scanner := bufio.NewScanner(r)
72 scanner.Scan()
73 for scanner.Scan() {
74 fields := strings.Fields(scanner.Text())
75 conntrackEntry, err := parseConntrackStatEntry(fields)
76 if err != nil {
77 return nil, err
78 }
79 entries = append(entries, *conntrackEntry)
80 }
81
82 return entries, nil
83}
84
Abhay Kumar40252eb2025-10-13 13:25:53 +000085// Parses a ConntrackStatEntry from given array of fields.
khenaidoo26721882021-08-11 17:42:52 -040086func parseConntrackStatEntry(fields []string) (*ConntrackStatEntry, error) {
Abhay Kumar40252eb2025-10-13 13:25:53 +000087 entries, err := util.ParseHexUint64s(fields)
khenaidoo26721882021-08-11 17:42:52 -040088 if err != nil {
Abhay Kumar40252eb2025-10-13 13:25:53 +000089 return nil, fmt.Errorf("%w: Cannot parse entry: %d: %w", ErrFileParse, entries, err)
khenaidoo26721882021-08-11 17:42:52 -040090 }
Abhay Kumar40252eb2025-10-13 13:25:53 +000091 numEntries := len(entries)
92 if numEntries < 16 || numEntries > 17 {
93 return nil,
94 fmt.Errorf("%w: invalid conntrackstat entry, invalid number of fields: %d", ErrFileParse, numEntries)
khenaidoo26721882021-08-11 17:42:52 -040095 }
khenaidoo26721882021-08-11 17:42:52 -040096
Abhay Kumar40252eb2025-10-13 13:25:53 +000097 stats := &ConntrackStatEntry{
98 Entries: *entries[0],
99 Searched: *entries[1],
100 Found: *entries[2],
101 New: *entries[3],
102 Invalid: *entries[4],
103 Ignore: *entries[5],
104 Delete: *entries[6],
105 DeleteList: *entries[7],
106 Insert: *entries[8],
107 InsertFailed: *entries[9],
108 Drop: *entries[10],
109 EarlyDrop: *entries[11],
khenaidoo26721882021-08-11 17:42:52 -0400110 }
khenaidoo26721882021-08-11 17:42:52 -0400111
Abhay Kumar40252eb2025-10-13 13:25:53 +0000112 // Ignore missing search_restart on Linux < 2.6.35.
113 if numEntries == 17 {
114 stats.SearchRestart = *entries[16]
khenaidoo26721882021-08-11 17:42:52 -0400115 }
khenaidoo26721882021-08-11 17:42:52 -0400116
Abhay Kumar40252eb2025-10-13 13:25:53 +0000117 return stats, nil
khenaidoo26721882021-08-11 17:42:52 -0400118}