@@ -4,17 +4,22 @@ package tcmanager
4
4
5
5
import (
6
6
"fmt"
7
+ "log/slog"
7
8
"strings"
9
+ "sync"
8
10
"time"
9
11
10
12
"github.com/cilium/ebpf"
13
+ "github.com/cilium/ebpf/asm"
14
+ "github.com/cilium/ebpf/link"
11
15
)
12
16
13
17
type TCBackend uint8
14
18
15
19
const (
16
20
TCBackendTC = TCBackend (iota + 1 )
17
21
TCBackendTCX
22
+ TCBackendAuto
18
23
)
19
24
20
25
type AttachmentType uint8
@@ -42,15 +47,32 @@ type TCManager interface {
42
47
SetInterfaceManager (im * InterfaceManager )
43
48
}
44
49
50
+ func newTCManagerAuto () TCManager {
51
+ log := slog .With ("component" , "tc_manager" )
52
+
53
+ log .Debug ("Auto detecting TCX support" )
54
+
55
+ if IsTCXSupported () {
56
+ log .Debug ("TCX support detected" )
57
+ return NewTCXManager ()
58
+ }
59
+
60
+ log .Debug ("TCX not supported, using netlink" )
61
+
62
+ return NewNetlinkManager ()
63
+ }
64
+
45
65
func NewTCManager (backend TCBackend ) TCManager {
46
66
switch backend {
47
67
case TCBackendTC :
48
68
return NewNetlinkManager ()
49
69
case TCBackendTCX :
50
70
return NewTCXManager ()
71
+ case TCBackendAuto :
72
+ return newTCManagerAuto ()
51
73
}
52
74
53
- return NewNetlinkManager () // default
75
+ return newTCManagerAuto () // default
54
76
}
55
77
56
78
func (b * TCBackend ) UnmarshalText (text []byte ) error {
@@ -61,16 +83,53 @@ func (b *TCBackend) UnmarshalText(text []byte) error {
61
83
case "tcx" :
62
84
* b = TCBackendTCX
63
85
return nil
86
+ case "auto" :
87
+ * b = TCBackendAuto
88
+ return nil
64
89
}
65
90
66
91
return fmt .Errorf ("invalid TCBakend value: '%s'" , text )
67
92
}
68
93
69
94
func (b TCBackend ) Valid () bool {
70
95
switch b {
71
- case TCBackendTC , TCBackendTCX :
96
+ case TCBackendTC , TCBackendTCX , TCBackendAuto :
72
97
return true
73
98
}
74
99
75
100
return false
76
101
}
102
+
103
+ var IsTCXSupported = sync .OnceValue (func () bool {
104
+ prog , err := ebpf .NewProgram (& ebpf.ProgramSpec {
105
+ Type : ebpf .SchedCLS ,
106
+ Instructions : asm.Instructions {
107
+ asm .Mov .Imm (asm .R0 , 0 ),
108
+ asm .Return (),
109
+ },
110
+ License : "Apache-2.0" ,
111
+ })
112
+
113
+ if err != nil {
114
+ return false
115
+ }
116
+
117
+ defer prog .Close ()
118
+
119
+ l , err := link .AttachTCX (link.TCXOptions {
120
+ Program : prog ,
121
+ Attach : ebpf .AttachTCXIngress ,
122
+ Interface : 1 , // lo
123
+ Anchor : link .Tail (),
124
+ })
125
+
126
+ if err != nil {
127
+ return false
128
+ }
129
+
130
+ if err := l .Close (); err != nil {
131
+ return false
132
+ }
133
+
134
+ return true
135
+ })
0 commit comments