Skip to content

Commit a511135

Browse files
committed
cgrouprate: refactor base registration code
Instead of using base objects directly, it's cleaner to operate on the contents of the sensor object passed at registration time. Add some helper functions to identify these objects and use them instead. Also, refactor the global state so that everything is under a single object for easier access. Move everything into a single file for clarity. Signed-off-by: Kornilios Kourtis <kornilios@isovalent.com>
1 parent 5d50928 commit a511135

File tree

9 files changed

+117
-87
lines changed

9 files changed

+117
-87
lines changed

cmd/tetragon/main.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,9 @@ func tetragonExecuteCtx(ctx context.Context, cancel context.CancelFunc, ready fu
492492
return err
493493
}
494494

495-
cgrouprate.NewCgroupRate(ctx, pm, &option.Config.CgroupRate)
495+
if err := cgrouprate.NewCgroupRate(ctx, pm, &option.Config.CgroupRate); err != nil {
496+
return err
497+
}
496498
cgrouprate.Config()
497499

498500
err = loadTpFromDir(ctx, option.Config.TracingPolicyDir)

pkg/cgrouprate/bpf.go

Lines changed: 0 additions & 27 deletions
This file was deleted.

pkg/cgrouprate/cgrouprate.go

Lines changed: 89 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ package cgrouprate
2323

2424
import (
2525
"context"
26+
"fmt"
2627
"sync"
2728
"time"
2829

@@ -36,6 +37,8 @@ import (
3637
"github.com/cilium/tetragon/pkg/observer"
3738
"github.com/cilium/tetragon/pkg/option"
3839
"github.com/cilium/tetragon/pkg/reader/notify"
40+
"github.com/cilium/tetragon/pkg/sensors"
41+
"github.com/cilium/tetragon/pkg/sensors/base"
3942
"github.com/cilium/tetragon/pkg/sensors/program"
4043
"github.com/sirupsen/logrus"
4144
)
@@ -44,12 +47,18 @@ const (
4447
aliveCnt = 5
4548
cleanupInterval = time.Minute
4649
cleanupInactiveTime = time.Minute
50+
cgRateMaxEntries = 32768 // this value could be fine tuned
4751
)
4852

49-
var (
50-
handle *CgroupRate
51-
handleLock sync.RWMutex
52-
)
53+
type globalState struct {
54+
cgRateMap *program.Map
55+
cgRateOptionsMap *program.Map
56+
57+
handle *CgroupRate
58+
mu sync.RWMutex
59+
}
60+
61+
var glSt globalState
5362

5463
type cgroupQueue struct {
5564
id uint64
@@ -84,26 +93,30 @@ func newCgroupRate(
8493

8594
func NewCgroupRate(ctx context.Context,
8695
listener observer.Listener,
87-
opts *option.CgroupRate) {
96+
opts *option.CgroupRate) error {
8897

8998
if opts.Events == 0 || opts.Interval == 0 {
9099
logger.GetLogger().Infof("Cgroup rate disabled (%d/%s)",
91100
opts.Events, time.Duration(opts.Interval).String())
92-
return
101+
return nil
93102
}
94103

95-
handleLock.Lock()
96-
defer handleLock.Unlock()
104+
glSt.mu.Lock()
105+
defer glSt.mu.Unlock()
106+
if glSt.cgRateMap == nil {
107+
return fmt.Errorf("cgrouprate has not been registered to base sensor")
108+
}
97109

98-
handle = newCgroupRate(listener, cgroupRateMap, opts)
99-
go handle.process(ctx)
110+
glSt.handle = newCgroupRate(listener, glSt.cgRateMap, opts)
111+
go glSt.handle.process(ctx)
112+
return nil
100113
}
101114

102115
func NewTestCgroupRate(listener observer.Listener,
103116
hash *program.Map,
104117
opts *option.CgroupRate) {
105118

106-
handle = newCgroupRate(listener, hash, opts)
119+
glSt.handle = newCgroupRate(listener, hash, opts)
107120
}
108121

109122
func (r *CgroupRate) notify(msg notify.Message) {
@@ -117,6 +130,11 @@ func (r *CgroupRate) process(ctx context.Context) {
117130
r.log.Infof("Cgroup rate started (%d/%s)",
118131
r.opts.Events, time.Duration(r.opts.Interval).String())
119132

133+
defer func() {
134+
// cleanup
135+
glSt.handle = nil
136+
}()
137+
120138
for {
121139
select {
122140
case <-ctx.Done():
@@ -263,14 +281,14 @@ func (r *CgroupRate) processCgroup(id uint64, cgroup string, last uint64) bool {
263281
// Called from event handlers to kick off the cgroup rate
264282
// periodical check for event's cgroup.
265283
func Check(kube *processapi.MsgK8s, ktime uint64) {
266-
if handle == nil {
284+
if glSt.handle == nil {
267285
return
268286
}
269287

270-
handleLock.RLock()
271-
defer handleLock.RUnlock()
288+
glSt.mu.RLock()
289+
defer glSt.mu.RUnlock()
272290

273-
if handle == nil {
291+
if glSt.handle == nil {
274292
return
275293
}
276294

@@ -280,27 +298,76 @@ func Check(kube *processapi.MsgK8s, ktime uint64) {
280298
name: string(kube.Docker[:]),
281299
}
282300

283-
handle.ch <- cq
301+
glSt.handle.ch <- cq
284302
cgroupratemetrics.CgroupRateTotalInc(cgroupratemetrics.Check)
285303
}
286304

287305
func Config() {
288-
if handle == nil {
306+
if glSt.handle == nil {
289307
return
290308
}
291309

292-
if cgroupRateOptionsMap.MapHandle == nil {
293-
handle.log.Warn("failed to update cgroup rate options map")
310+
if glSt.cgRateOptionsMap.MapHandle == nil {
311+
glSt.handle.log.Warn("failed to update cgroup rate options map")
294312
return
295313
}
296314

297315
key := uint32(0)
298316
opts := processapi.CgroupRateOptions{
299-
Events: handle.opts.Events,
300-
Interval: handle.opts.Interval,
317+
Events: glSt.handle.opts.Events,
318+
Interval: glSt.handle.opts.Interval,
301319
}
302320

303-
if err := cgroupRateOptionsMap.MapHandle.Put(key, opts); err != nil {
321+
if err := glSt.cgRateOptionsMap.MapHandle.Put(key, opts); err != nil {
304322
cgroupratemetrics.CgroupRateTotalInc(cgroupratemetrics.UpdateFail)
305323
}
306324
}
325+
326+
func RegisterCgroupRate(sensor *sensors.Sensor) (*sensors.Sensor, error) {
327+
if !option.CgroupRateEnabled() {
328+
return sensor, nil
329+
}
330+
331+
glSt.mu.Lock()
332+
defer glSt.mu.Unlock()
333+
334+
if glSt.handle != nil {
335+
return nil, fmt.Errorf("cgrouprate: handle is already set, need to cleanup first")
336+
}
337+
338+
var rateProgs []*program.Program
339+
var optsProgs []*program.Program
340+
for _, p := range sensor.Progs {
341+
if base.IsExecve(p) || base.IsFork(p) || base.IsExit(p) {
342+
rateProgs = append(rateProgs, p)
343+
}
344+
if base.IsExecve(p) {
345+
optsProgs = append(optsProgs, p)
346+
}
347+
}
348+
349+
if len(optsProgs) == 0 || len(rateProgs) == 0 {
350+
return nil, fmt.Errorf("failed to find base programs")
351+
}
352+
353+
cgRmdirProg := program.Builder(
354+
"bpf_cgroup.o",
355+
"cgroup/cgroup_rmdir",
356+
"raw_tracepoint/cgroup_rmdir",
357+
"tg_cgroup_rmdir",
358+
"raw_tracepoint",
359+
).SetPolicy(optsProgs[0].Policy)
360+
rateProgs = append(rateProgs, cgRmdirProg)
361+
362+
glSt.cgRateMap = program.MapBuilder("cgroup_rate_map", rateProgs...)
363+
glSt.cgRateMap.SetMaxEntries(cgRateMaxEntries)
364+
glSt.cgRateOptionsMap = program.MapBuilder("cgroup_rate_options_map", optsProgs...)
365+
366+
sensor.Progs = append(sensor.Progs, cgRmdirProg)
367+
sensor.Maps = append(sensor.Maps, glSt.cgRateMap, glSt.cgRateOptionsMap)
368+
return sensor, nil
369+
}
370+
371+
func init() {
372+
base.RegisterExtensionAtInit("cgroup_rate", RegisterCgroupRate)
373+
}

pkg/cgrouprate/cgrouprate_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,8 @@ func TestProcessCgroup(t *testing.T) {
240240
NewTestCgroupRate(l, hash, &d.opts)
241241

242242
// setup cgrouprate cgroup
243-
handle.cgroups[key.Id] = cgroup
244-
assert.NotEqual(t, nil, handle)
243+
glSt.handle.cgroups[key.Id] = cgroup
244+
assert.NotEqual(t, nil, glSt.handle)
245245

246246
// store hash values
247247
values[0] = d.values[0]
@@ -252,7 +252,7 @@ func TestProcessCgroup(t *testing.T) {
252252
}
253253

254254
t.Logf("Test %d", idx)
255-
ret := handle.processCgroup(key.Id, cgroup, d.last)
255+
ret := glSt.handle.processCgroup(key.Id, cgroup, d.last)
256256

257257
assert.Equal(t, d.ret, ret)
258258
assert.Equal(t, d.throttle, l.throttle)

pkg/cgrouprate/sensor.go

Lines changed: 0 additions & 30 deletions
This file was deleted.

pkg/observer/observertesthelper/observer_test_helper.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,8 +423,7 @@ func loadExporter(tb testing.TB, ctx context.Context, obs *observer.Observer, op
423423
obs.RemoveListener(processManager)
424424
})
425425

426-
cgrouprate.NewCgroupRate(ctx, processManager, &option.Config.CgroupRate)
427-
return nil
426+
return cgrouprate.NewCgroupRate(ctx, processManager, &option.Config.CgroupRate)
428427
}
429428

430429
func loadObserver(tb testing.TB, ctx context.Context, base *sensors.Sensor,

pkg/sensors/base/base.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ func initBaseSensor() *sensors.Sensor {
139139
setupPrograms()
140140
sensor.Progs = GetDefaultPrograms()
141141
sensor.Maps = GetDefaultMaps()
142-
return applyExtensions(&sensor)
142+
return ApplyExtensions(&sensor)
143143
}
144144

145145
func initBaseSensorFn() func(tb testing.TB) *sensors.Sensor {

pkg/sensors/base/extensions.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func RegisterExtensionAtInit(name string, fn ExtensionFn) {
2727
})
2828
}
2929

30-
func applyExtensions(s *sensors.Sensor) *sensors.Sensor {
30+
func ApplyExtensions(s *sensors.Sensor) *sensors.Sensor {
3131
for _, ext := range extensions {
3232
newS, err := ext.fn(s)
3333
if err != nil {

pkg/sensors/base/utils.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// Copyright Authors of Tetragon
3+
4+
package base
5+
6+
import "github.com/cilium/tetragon/pkg/sensors/program"
7+
8+
// IsExecve returns true if this is a base execve program
9+
func IsExecve(p *program.Program) bool {
10+
return p.PinName == "event_execve" && p.Policy == basePolicy
11+
}
12+
13+
func IsFork(p *program.Program) bool {
14+
return p.PinName == "kprobe_pid_clear" && p.Policy == basePolicy
15+
}
16+
17+
func IsExit(p *program.Program) bool {
18+
return p.PinName == "event_exit" && p.Policy == basePolicy
19+
}

0 commit comments

Comments
 (0)