inspektor-gadget

Форк
0
178 строк · 4.3 Кб
1
// Copyright 2019-2023 The Inspektor Gadget authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
//go:build !withoutebpf
16

17
package tracer
18

19
import (
20
	"errors"
21
	"fmt"
22
	"os"
23
	"unsafe"
24

25
	"github.com/cilium/ebpf"
26
	"github.com/cilium/ebpf/link"
27
	"github.com/cilium/ebpf/perf"
28

29
	gadgetcontext "github.com/inspektor-gadget/inspektor-gadget/pkg/gadget-context"
30
	"github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets"
31
	"github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/oomkill/types"
32
	eventtypes "github.com/inspektor-gadget/inspektor-gadget/pkg/types"
33
)
34

35
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags ${CFLAGS} -type data_t oomkill ./bpf/oomkill.bpf.c -- -I./bpf/
36

37
type Config struct {
38
	MountnsMap *ebpf.Map
39
}
40

41
type Tracer struct {
42
	config        *Config
43
	objs          oomkillObjects
44
	oomLink       link.Link
45
	reader        *perf.Reader
46
	enricher      gadgets.DataEnricherByMntNs
47
	eventCallback func(*types.Event)
48
}
49

50
func NewTracer(c *Config, enricher gadgets.DataEnricherByMntNs, eventCallback func(*types.Event)) (*Tracer, error) {
51
	t := &Tracer{
52
		config:        c,
53
		enricher:      enricher,
54
		eventCallback: eventCallback,
55
	}
56

57
	if err := t.install(); err != nil {
58
		t.close()
59
		return nil, err
60
	}
61

62
	go t.run()
63

64
	return t, nil
65
}
66

67
// Stop stops the tracer
68
// TODO: Remove after refactoring
69
func (t *Tracer) Stop() {
70
	t.close()
71
}
72

73
func (t *Tracer) close() {
74
	t.oomLink = gadgets.CloseLink(t.oomLink)
75

76
	if t.reader != nil {
77
		t.reader.Close()
78
	}
79

80
	t.objs.Close()
81
}
82

83
func (t *Tracer) install() error {
84
	spec, err := loadOomkill()
85
	if err != nil {
86
		return fmt.Errorf("loading ebpf program: %w", err)
87
	}
88

89
	if err := gadgets.LoadeBPFSpec(t.config.MountnsMap, spec, nil, &t.objs); err != nil {
90
		return fmt.Errorf("loading ebpf spec: %w", err)
91
	}
92

93
	kprobe, err := link.Kprobe("oom_kill_process", t.objs.IgOomKill, nil)
94
	if err != nil {
95
		return fmt.Errorf("attaching kprobe: %w", err)
96
	}
97
	t.oomLink = kprobe
98

99
	reader, err := perf.NewReader(t.objs.oomkillMaps.Events, gadgets.PerfBufferPages*os.Getpagesize())
100
	if err != nil {
101
		return fmt.Errorf("creating perf ring buffer: %w", err)
102
	}
103
	t.reader = reader
104

105
	return nil
106
}
107

108
func (t *Tracer) run() {
109
	for {
110
		record, err := t.reader.Read()
111
		if err != nil {
112
			if errors.Is(err, perf.ErrClosed) {
113
				// nothing to do, we're done
114
				return
115
			}
116

117
			msg := fmt.Sprintf("Error reading perf ring buffer: %s", err)
118
			t.eventCallback(types.Base(eventtypes.Err(msg)))
119
			return
120
		}
121

122
		bpfEvent := (*oomkillDataT)(unsafe.Pointer(&record.RawSample[0]))
123

124
		event := types.Event{
125
			Event: eventtypes.Event{
126
				Type:      eventtypes.NORMAL,
127
				Timestamp: gadgets.WallTimeFromBootTime(bpfEvent.Timestamp),
128
			},
129
			TriggeredPid:  bpfEvent.Fpid,
130
			TriggeredUid:  bpfEvent.Fuid,
131
			TriggeredGid:  bpfEvent.Fgid,
132
			TriggeredComm: gadgets.FromCString(bpfEvent.Fcomm[:]),
133
			KilledPid:     bpfEvent.Tpid,
134
			KilledComm:    gadgets.FromCString(bpfEvent.Tcomm[:]),
135
			Pages:         bpfEvent.Pages,
136
			WithMountNsID: eventtypes.WithMountNsID{MountNsID: bpfEvent.MountNsId},
137
		}
138

139
		if t.enricher != nil {
140
			t.enricher.EnrichByMntNs(&event.CommonData, event.MountNsID)
141
		}
142

143
		t.eventCallback(&event)
144
	}
145
}
146

147
// --- Registry changes
148

149
func (t *Tracer) Run(gadgetCtx gadgets.GadgetContext) error {
150
	defer t.close()
151
	if err := t.install(); err != nil {
152
		return fmt.Errorf("installing tracer: %w", err)
153
	}
154

155
	go t.run()
156
	gadgetcontext.WaitForTimeoutOrDone(gadgetCtx)
157

158
	return nil
159
}
160

161
func (t *Tracer) SetMountNsMap(mountnsMap *ebpf.Map) {
162
	t.config.MountnsMap = mountnsMap
163
}
164

165
func (t *Tracer) SetEventHandler(handler any) {
166
	nh, ok := handler.(func(ev *types.Event))
167
	if !ok {
168
		panic("event handler invalid")
169
	}
170
	t.eventCallback = nh
171
}
172

173
func (g *GadgetDesc) NewInstance() (gadgets.Gadget, error) {
174
	tracer := &Tracer{
175
		config: &Config{},
176
	}
177
	return tracer, nil
178
}
179

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.