Skip to content

Commit

Permalink
[BPF] make conntrack timeouts configurable
Browse files Browse the repository at this point in the history
BPFConntrackTimers overides the default values for the specified conntrack timer if
set. It is a struct of values, where each value can be either a duration or `auto` to
pick the value from a Linux conntrack timeout.

Possible values for the keys are: CreationGracePeriod, TCPPreEstablished,
TCPEstablished, TCPFinsSeen, TCPResetSeen, UDPLastSeen, GenericIPLastSeen,
ICMPLastSeen.

Unset or incorrect values are replaced by the default values with a warning log for
incorrect values.

Current auto mappings:

TCPPreEstablished: nf_conntrack_tcp_timeout_syn_sent
TCPEstablished:    nf_conntrack_tcp_timeout_established
TCPFinsSeen:       nf_conntrack_tcp_timeout_time_wait
GenericIPLastSeen: nf_conntrack_generic_timeout
ICMPLastSeen:      nf_conntrack_icmp_timeout

If there is no mapping, 'auto' is replaced by the default value.

[Default:
     CreationGracePeriod: 10s
     TCPPreEstablished:   20s
     TCPEstablished:      1h
     TCPFinsSeen:         auto (30s is default)
     TCPResetSeen:        40s
     UDPLastSeen:         60s
     GenericIPLastSeen:   10m
     ICMPLastSeen:        5s
]
  • Loading branch information
tomastigera committed Dec 28, 2024
1 parent 810091a commit 2413c56
Show file tree
Hide file tree
Showing 20 changed files with 746 additions and 3 deletions.
48 changes: 48 additions & 0 deletions api/pkg/apis/projectcalico/v3/felixconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,40 @@ type FelixConfigurationSpec struct {
// [Default: Auto]
BPFConntrackCleanupMode *BPFConntrackMode `json:"bpfConntrackMode,omitempty" validate:"omitempty,oneof=Auto Userspace BPFProgram"`

// BPFConntrackTimers overides the default values for the specified conntrack timer if
// set. It is a key-value make, where each value can be either a duration or `auto` to
// pick the value from a Linux conntrack timeout.
//
// Possible values for the keys are: CreationGracePeriod, TCPPreEstablished,
// TCPEstablished, TCPFinsSeen, TCPResetSeen, UDPLastSeen, GenericIPLastSeen,
// ICMPLastSeen.
//
// Unset or incorrect values are replaced by the default values with a warning log for
// incorrect values.
//
// Current auto mappings:
//
// TCPPreEstablished: nf_conntrack_tcp_timeout_syn_sent
// TCPEstablished: nf_conntrack_tcp_timeout_established
// TCPFinsSeen: nf_conntrack_tcp_timeout_time_wait
// GenericIPLastSeen: nf_conntrack_generic_timeout
// ICMPLastSeen: nf_conntrack_icmp_timeout
//
// If there is no mapping, 'auto' is replaced by the default value.
//
// [Default:
// CreationGracePeriod: 10s
// TCPPreEstablished: 20s
// TCPEstablished: 1h
// TCPFinsSeen: auto (30s is default)
// TCPResetSeen: 40s
// UDPLastSeen: 60s
// GenericIPLastSeen: 10m
// ICMPLastSeen: 5s
// ]
// +optional
BPFConntrackTimeouts *BPFConntrackTimeouts `json:"bpfConntrackTimeouts,omitempty" validate:"omitempty"`

// BPFLogFilters is a map of key=values where the value is
// a pcap filter expression and the key is an interface name with 'all'
// denoting all interfaces, 'weps' all workload endpoints and 'heps' all host
Expand Down Expand Up @@ -941,6 +975,20 @@ type ProtoPort struct {
Net string `json:"net,omitempty"`
}

// +kubebuilder:validation:Pattern=`^(([0-9]*(\.[0-9]*)?(ms|s|h|m|us)+)+|auto)$`
type BPFConntrackTimeout string

type BPFConntrackTimeouts struct {
CreationGracePeriod BPFConntrackTimeout `json:"creationGracePeriod,omitempty"`
TCPPreEstablished BPFConntrackTimeout `json:"tcpPreEstablished,omitempty"`
TCPEstablished BPFConntrackTimeout `json:"tcpEstablished,omitempty"`
TCPFinsSeen BPFConntrackTimeout `json:"tcpFinsSeen,omitempty"`
TCPResetSeen BPFConntrackTimeout `json:"tcpResetSeen,omitempty"`
UDPLastSeen BPFConntrackTimeout `json:"udpLastSeen,omitempty"`
GenericIPLastSeen BPFConntrackTimeout `json:"genericIPLastSeen,omitempty"`
ICMPLastSeen BPFConntrackTimeout `json:"icmpLastSeen,omitempty"`
}

// New FelixConfiguration creates a new (zeroed) FelixConfiguration struct with the TypeMetadata
// initialized to the current version.
func NewFelixConfiguration() *FelixConfiguration {
Expand Down
21 changes: 21 additions & 0 deletions api/pkg/apis/projectcalico/v3/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

69 changes: 68 additions & 1 deletion api/pkg/openapi/generated.openapi.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

92 changes: 92 additions & 0 deletions felix/bpf/conntrack/timeouts.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
package conntrack

import (
"bufio"
"fmt"
"os"
"reflect"
"strconv"
"strings"
"time"

log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -99,3 +105,89 @@ func DefaultTimeouts() Timeouts {
ICMPLastSeen: 5 * time.Second,
}
}

var linuxSysctls = map[string]string{
"TCPPreEstablished": "nf_conntrack_tcp_timeout_syn_sent",
"TCPEstablished": "nf_conntrack_tcp_timeout_established",
"TCPFinsSeen": "nf_conntrack_tcp_timeout_time_wait",
"GenericIPLastSeen": "nf_conntrack_generic_timeout",
"ICMPLastSeen": "nf_conntrack_icmp_timeout",
}

func GetTimeouts(config map[string]string) Timeouts {
t := DefaultTimeouts()

v := reflect.ValueOf(&t)
v = v.Elem()

for key, value := range config {
field := v.FieldByName(key)
if !field.IsValid() {
log.WithField("value", key).Warn("Not a valid BPF conntrack timeout, skipping")
continue
}

d, err := time.ParseDuration(value)
if err == nil {
log.WithFields(log.Fields{"name": key, "value": d}).Info("BPF conntrack timeout set")
field.SetInt(int64(d))
continue
}

if value == "auto" {
sysctl := linuxSysctls[key]
if sysctl != "" {
seconds, err := readSecondsFromFile(sysctl)
if err == nil {
d := time.Duration(seconds) * time.Second
log.WithFields(log.Fields{"name": key, "value": d}).Infof("BPF conntrack timeout set from %s", sysctl)
field.SetInt(int64(d))
continue
}
}
}

log.WithField("value", key).Warnf("Not a valid BPF conntrack timeout value, using default %s",
time.Duration(field.Int()))
}

fields := make(log.Fields)

tt := reflect.TypeOf(t)

for i := 0; i < v.NumField(); i++ {
fields[tt.Field(i).Name] = v.Field(i).Interface()
}

log.WithFields(fields).Infof("BPF conntrack timers")

return t
}

func readSecondsFromFile(nfTimeout string) (int, error) {
filePath := "/proc/sys/net/netfilter/" + nfTimeout

file, err := os.Open(filePath)
if err != nil {
return 0, fmt.Errorf("error opening file: %w", err)
}
defer file.Close()

scanner := bufio.NewScanner(file)
if scanner.Scan() {
line := scanner.Text()
line = strings.TrimSpace(line)
seconds, err := strconv.Atoi(line)
if err != nil {
return 0, fmt.Errorf("error converting the value to an integer: %w", err)
}

return seconds, nil
}

if err := scanner.Err(); err != nil {
return 0, fmt.Errorf("error reading from file: %w", err)
}

return 0, fmt.Errorf("file is empty or cannot read a line")
}
1 change: 1 addition & 0 deletions felix/config/config_params.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ type Config struct {
BPFLogLevel string `config:"oneof(off,info,debug);off;non-zero"`
BPFConntrackLogLevel string `config:"oneof(off,debug);off;non-zero"`
BPFConntrackCleanupMode string `config:"oneof(Auto,Userspace,BPFProgram);Auto"`
BPFConntrackTimeouts map[string]string `config:"keyvaluelist;CreationGracePeriod=10s,TCPPreEstablished=20s,TCPEstablished=1h,TCPFinsSeen=auto,TCPResetSeen=40s,UDPLastSeen=60s,GenericIPLastSeen=10m,ICMPLastSeen=5s"`
BPFLogFilters map[string]string `config:"keyvaluelist;;"`
BPFCTLBLogFilter string `config:"oneof(all);;"`
BPFDataIfacePattern *regexp.Regexp `config:"regexp;^((en|wl|ww|sl|ib)[Popsx].*|(eth|wlan|wwan|bond).*)"`
Expand Down
2 changes: 1 addition & 1 deletion felix/dataplane/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ func StartDataplaneDriver(
BPFDisableGROForIfaces: configParams.BPFDisableGROForIfaces,
XDPEnabled: configParams.XDPEnabled,
XDPAllowGeneric: configParams.GenericXDPEnabled,
BPFConntrackTimeouts: conntrack.DefaultTimeouts(), // FIXME make timeouts configurable
BPFConntrackTimeouts: conntrack.GetTimeouts(configParams.BPFConntrackTimeouts),
BPFConntrackCleanupMode: apiv3.BPFConntrackMode(configParams.BPFConntrackCleanupMode),
RouteTableManager: routeTableIndexAllocator,
MTUIfacePattern: configParams.MTUIfacePattern,
Expand Down
26 changes: 26 additions & 0 deletions felix/docs/config-params.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions felix/docs/config-params.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 2413c56

Please sign in to comment.