Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BPF] make conntrack timeouts configurable #9607

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -936,6 +970,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
Loading