123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- // Copyright 2020 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"
- )
- // A ConntrackStatEntry represents one line from net/stat/nf_conntrack
- // and contains netfilter conntrack statistics at one CPU core.
- type ConntrackStatEntry struct {
- Entries uint64
- Found uint64
- Invalid uint64
- Ignore uint64
- Insert uint64
- InsertFailed uint64
- Drop uint64
- EarlyDrop uint64
- SearchRestart uint64
- }
- // ConntrackStat retrieves netfilter's conntrack statistics, split by CPU cores.
- func (fs FS) ConntrackStat() ([]ConntrackStatEntry, error) {
- return readConntrackStat(fs.proc.Path("net", "stat", "nf_conntrack"))
- }
- // Parses a slice of ConntrackStatEntries from the given filepath.
- func readConntrackStat(path string) ([]ConntrackStatEntry, error) {
- // This file is small and can be read with one syscall.
- b, err := util.ReadFileNoStat(path)
- if err != nil {
- // Do not wrap this error so the caller can detect os.IsNotExist and
- // similar conditions.
- return nil, err
- }
- stat, err := parseConntrackStat(bytes.NewReader(b))
- if err != nil {
- return nil, fmt.Errorf("failed to read conntrack stats from %q: %w", path, err)
- }
- return stat, nil
- }
- // Reads the contents of a conntrack statistics file and parses a slice of ConntrackStatEntries.
- func parseConntrackStat(r io.Reader) ([]ConntrackStatEntry, error) {
- var entries []ConntrackStatEntry
- scanner := bufio.NewScanner(r)
- scanner.Scan()
- for scanner.Scan() {
- fields := strings.Fields(scanner.Text())
- conntrackEntry, err := parseConntrackStatEntry(fields)
- if err != nil {
- return nil, err
- }
- entries = append(entries, *conntrackEntry)
- }
- return entries, nil
- }
- // Parses a ConntrackStatEntry from given array of fields.
- func parseConntrackStatEntry(fields []string) (*ConntrackStatEntry, error) {
- if len(fields) != 17 {
- return nil, fmt.Errorf("invalid conntrackstat entry, missing fields")
- }
- entry := &ConntrackStatEntry{}
- entries, err := parseConntrackStatField(fields[0])
- if err != nil {
- return nil, err
- }
- entry.Entries = entries
- found, err := parseConntrackStatField(fields[2])
- if err != nil {
- return nil, err
- }
- entry.Found = found
- invalid, err := parseConntrackStatField(fields[4])
- if err != nil {
- return nil, err
- }
- entry.Invalid = invalid
- ignore, err := parseConntrackStatField(fields[5])
- if err != nil {
- return nil, err
- }
- entry.Ignore = ignore
- insert, err := parseConntrackStatField(fields[8])
- if err != nil {
- return nil, err
- }
- entry.Insert = insert
- insertFailed, err := parseConntrackStatField(fields[9])
- if err != nil {
- return nil, err
- }
- entry.InsertFailed = insertFailed
- drop, err := parseConntrackStatField(fields[10])
- if err != nil {
- return nil, err
- }
- entry.Drop = drop
- earlyDrop, err := parseConntrackStatField(fields[11])
- if err != nil {
- return nil, err
- }
- entry.EarlyDrop = earlyDrop
- searchRestart, err := parseConntrackStatField(fields[16])
- if err != nil {
- return nil, err
- }
- entry.SearchRestart = searchRestart
- return entry, nil
- }
- // Parses a uint64 from given hex in string.
- func parseConntrackStatField(field string) (uint64, error) {
- val, err := strconv.ParseUint(field, 16, 64)
- if err != nil {
- return 0, fmt.Errorf("couldn't parse %q field: %w", field, err)
- }
- return val, err
- }
|