inspektor-gadget

Форк
0
182 строки · 4.9 Кб
1
// Copyright 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
	"github.com/inspektor-gadget/inspektor-gadget/pkg/btfgen"
30
	gadgetcontext "github.com/inspektor-gadget/inspektor-gadget/pkg/gadget-context"
31
	"github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets"
32
	"github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/tcpretrans/types"
33
	"github.com/inspektor-gadget/inspektor-gadget/pkg/socketenricher"
34
	"github.com/inspektor-gadget/inspektor-gadget/pkg/tcpbits"
35
	eventtypes "github.com/inspektor-gadget/inspektor-gadget/pkg/types"
36
)
37

38
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags ${CFLAGS} -no-global-types -type event tcpretrans ./bpf/tcpretrans.bpf.c -- -I./bpf/
39

40
type Tracer struct {
41
	socketEnricherMap *ebpf.Map
42

43
	eventCallback func(*types.Event)
44

45
	objs              tcpretransObjects
46
	retransmitSkbLink link.Link
47
	reader            *perf.Reader
48
}
49

50
func (g *GadgetDesc) NewInstance() (gadgets.Gadget, error) {
51
	return &Tracer{}, nil
52
}
53

54
func (t *Tracer) Run(gadgetCtx gadgets.GadgetContext) error {
55
	defer t.close()
56
	if err := t.install(); err != nil {
57
		return fmt.Errorf("installing tracer: %w", err)
58
	}
59

60
	go t.run()
61
	gadgetcontext.WaitForTimeoutOrDone(gadgetCtx)
62

63
	return nil
64
}
65

66
func (t *Tracer) SetEventHandler(handler any) {
67
	nh, ok := handler.(func(ev *types.Event))
68
	if !ok {
69
		panic("event handler invalid")
70
	}
71
	t.eventCallback = nh
72
}
73

74
func (t *Tracer) SetSocketEnricherMap(m *ebpf.Map) {
75
	t.socketEnricherMap = m
76
}
77

78
func (t *Tracer) close() {
79
	t.retransmitSkbLink = gadgets.CloseLink(t.retransmitSkbLink)
80

81
	if t.reader != nil {
82
		t.reader.Close()
83
	}
84

85
	t.objs.Close()
86
}
87

88
func (t *Tracer) install() error {
89
	var err error
90

91
	spec, err := loadTcpretrans()
92
	if err != nil {
93
		return fmt.Errorf("loading ebpf program: %w", err)
94
	}
95

96
	gadgets.FixBpfKtimeGetBootNs(spec.Programs)
97

98
	opts := ebpf.CollectionOptions{
99
		Programs: ebpf.ProgramOptions{
100
			KernelTypes: btfgen.GetBTFSpec(),
101
		},
102
	}
103

104
	mapReplacements := map[string]*ebpf.Map{}
105
	mapReplacements[socketenricher.SocketsMapName] = t.socketEnricherMap
106
	opts.MapReplacements = mapReplacements
107

108
	if err := spec.LoadAndAssign(&t.objs, &opts); err != nil {
109
		return fmt.Errorf("loading ebpf program: %w", err)
110
	}
111

112
	t.retransmitSkbLink, err = link.Tracepoint("tcp", "tcp_retransmit_skb", t.objs.IgTcpretrans, nil)
113
	if err != nil {
114
		return fmt.Errorf("attaching tracepoint tcp_retransmit_skb: %w", err)
115
	}
116

117
	reader, err := perf.NewReader(t.objs.tcpretransMaps.Events, gadgets.PerfBufferPages*os.Getpagesize())
118
	if err != nil {
119
		return fmt.Errorf("creating perf ring buffer: %w", err)
120
	}
121
	t.reader = reader
122

123
	return nil
124
}
125

126
func (t *Tracer) run() {
127
	for {
128
		record, err := t.reader.Read()
129
		if err != nil {
130
			if errors.Is(err, perf.ErrClosed) {
131
				// nothing to do, we're done
132
				return
133
			}
134

135
			msg := fmt.Sprintf("reading perf ring buffer: %s", err)
136
			t.eventCallback(types.Base(eventtypes.Err(msg)))
137
			return
138
		}
139

140
		if record.LostSamples > 0 {
141
			msg := fmt.Sprintf("lost %d samples", record.LostSamples)
142
			t.eventCallback(types.Base(eventtypes.Warn(msg)))
143
			continue
144
		}
145

146
		bpfEvent := (*tcpretransEvent)(unsafe.Pointer(&record.RawSample[0]))
147

148
		ipversion := gadgets.IPVerFromAF(bpfEvent.Af)
149

150
		event := types.Event{
151
			Event: eventtypes.Event{
152
				Type:      eventtypes.NORMAL,
153
				Timestamp: gadgets.WallTimeFromBootTime(bpfEvent.Timestamp),
154
			},
155
			WithMountNsID: eventtypes.WithMountNsID{MountNsID: bpfEvent.ProcSocket.MountNsId},
156
			WithNetNsID:   eventtypes.WithNetNsID{NetNsID: uint64(bpfEvent.Netns)},
157
			Pid:           bpfEvent.ProcSocket.Pid,
158
			Uid:           bpfEvent.ProcSocket.Uid,
159
			Gid:           bpfEvent.ProcSocket.Gid,
160
			Comm:          gadgets.FromCString(bpfEvent.ProcSocket.Task[:]),
161
			IPVersion:     ipversion,
162
			SrcEndpoint: eventtypes.L4Endpoint{
163
				L3Endpoint: eventtypes.L3Endpoint{
164
					Addr:    gadgets.IPStringFromBytes(bpfEvent.Saddr, ipversion),
165
					Version: uint8(ipversion),
166
				},
167
				Port: gadgets.Htons(bpfEvent.Sport),
168
			},
169
			DstEndpoint: eventtypes.L4Endpoint{
170
				L3Endpoint: eventtypes.L3Endpoint{
171
					Addr:    gadgets.IPStringFromBytes(bpfEvent.Daddr, ipversion),
172
					Version: uint8(ipversion),
173
				},
174
				Port: gadgets.Htons(bpfEvent.Dport),
175
			},
176
			State:    tcpbits.TCPState(bpfEvent.State),
177
			Tcpflags: tcpbits.TCPFlags(bpfEvent.Tcpflags),
178
		}
179

180
		t.eventCallback(&event)
181
	}
182
}
183

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

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

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

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