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

Add support for auto detecting TCX #1533

Merged
merged 6 commits into from
Jan 16, 2025
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/vale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ jobs:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- uses: grafana/writers-toolkit/vale-action@4b1248585248751e3b12fd020cf7ac91540ca09c # vale-action/v1.0.0
- uses: grafana/writers-toolkit/vale-action@13205961f20ad13843505a9b84fdf032f911a3f4 # vale-action/v1.1.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
1 change: 1 addition & 0 deletions .vale.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ MinAlertLevel = warning

[*]
BasedOnStyles = Grafana
TokenIgnores = (<http[^\n]+>+?), \*\*[^\n]+\*\*
11 changes: 6 additions & 5 deletions docs/sources/configure/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -500,17 +500,18 @@ generation of Beyla metrics.

| YAML | Environment variable | Type | Default |
| ------------------------- | --------------------------------- | ------- | ------- |
| `traffic_control_backend` | `BEYLA_BPF_TC_BACKEND` | string | `tc` |
| `traffic_control_backend` | `BEYLA_BPF_TC_BACKEND` | string | `auto` |

Chooses which backend to use for the attachment of traffic control probes.
Linux 6.6 has added support for a file-descriptor based traffic control
attachment called TCX, providing a more robust way of attaching traffic
control probes (it does not require explicit qdisc management, and provides a
deterministic way to chain probes). We recommend the usage of the `tcx`
backend for kernels >= 6.6 for this reason.
deterministic way to chain probes).
We recommend the usage of the `tcx` backend for kernels >= 6.6 for this reason.
When set to `auto`, Beyla picks the most suitable backend based on the underlying kernel.

The accepted backends are `tc` and `tcx`. An empty or unset value defaults to
`tc`.
The accepted backends are `tc`, `tcx`, and `auto.
An empty or unset value defaults to `auto`.

| YAML | Environment variable | Type | Default |
| ----------------------- | ---------------------------------- | ------- | ------- |
Expand Down
2 changes: 1 addition & 1 deletion pkg/beyla/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ var DefaultConfig = Config{
BatchLength: 100,
BatchTimeout: time.Second,
HTTPRequestTimeout: 30 * time.Second,
TCBackend: tcmanager.TCBackendTC,
TCBackend: tcmanager.TCBackendAuto,
},
Grafana: otel.GrafanaConfig{
OTLP: otel.GrafanaOTLP{
Expand Down
2 changes: 1 addition & 1 deletion pkg/beyla/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ network:
BatchLength: 100,
BatchTimeout: time.Second,
HTTPRequestTimeout: 30 * time.Second,
TCBackend: tcmanager.TCBackendTC,
TCBackend: tcmanager.TCBackendAuto,
},
Grafana: otel.GrafanaConfig{
OTLP: otel.GrafanaOTLP{
Expand Down
4 changes: 4 additions & 0 deletions pkg/internal/ebpf/tcmanager/ifacemanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ func NewInterfaceManager() *InterfaceManager {
}

func (im *InterfaceManager) Start(ctx context.Context) {
im.log.Debug("Starting InterfaceManager", "monitor_mode", im.monitorMode)

if im.registerer != nil {
return
}
Expand All @@ -62,6 +64,8 @@ func (im *InterfaceManager) Start(ctx context.Context) {

registerer := ifaces.NewRegisterer(informer, im.channelBufferLen)

im.log.Debug("Subscribing for events")

ifaceEvents, err := registerer.Subscribe(ctx)

if err != nil {
Expand Down
63 changes: 61 additions & 2 deletions pkg/internal/ebpf/tcmanager/tcmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,22 @@ package tcmanager

import (
"fmt"
"log/slog"
"strings"
"sync"
"time"

"github.com/cilium/ebpf"
"github.com/cilium/ebpf/asm"
"github.com/cilium/ebpf/link"
)

type TCBackend uint8

const (
TCBackendTC = TCBackend(iota + 1)
TCBackendTCX
TCBackendAuto
)

type AttachmentType uint8
Expand Down Expand Up @@ -42,15 +47,32 @@ type TCManager interface {
SetInterfaceManager(im *InterfaceManager)
}

func newTCManagerAuto() TCManager {
log := slog.With("component", "tc_manager")

log.Debug("Auto detecting TCX support")

if IsTCXSupported() {
log.Debug("TCX support detected")
return NewTCXManager()
}

log.Debug("TCX not supported, using netlink")

return NewNetlinkManager()
}

func NewTCManager(backend TCBackend) TCManager {
switch backend {
case TCBackendTC:
return NewNetlinkManager()
case TCBackendTCX:
return NewTCXManager()
case TCBackendAuto:
return newTCManagerAuto()
}

return NewNetlinkManager() // default
return newTCManagerAuto() // default
}

func (b *TCBackend) UnmarshalText(text []byte) error {
Expand All @@ -61,16 +83,53 @@ func (b *TCBackend) UnmarshalText(text []byte) error {
case "tcx":
*b = TCBackendTCX
return nil
case "auto":
*b = TCBackendAuto
return nil
}

return fmt.Errorf("invalid TCBakend value: '%s'", text)
}

func (b TCBackend) Valid() bool {
switch b {
case TCBackendTC, TCBackendTCX:
case TCBackendTC, TCBackendTCX, TCBackendAuto:
return true
}

return false
}

var IsTCXSupported = sync.OnceValue(func() bool {
prog, err := ebpf.NewProgram(&ebpf.ProgramSpec{
Type: ebpf.SchedCLS,
Instructions: asm.Instructions{
asm.Mov.Imm(asm.R0, 0),
asm.Return(),
},
License: "Apache-2.0",
})

if err != nil {
return false
}

defer prog.Close()

l, err := link.AttachTCX(link.TCXOptions{
Program: prog,
Attach: ebpf.AttachTCXIngress,
Interface: 1, // lo
Anchor: link.Tail(),
})

if err != nil {
return false
}

if err := l.Close(); err != nil {
return false
}

return true
})
Loading