Skip to content

Commit ca21918

Browse files
Refactor eBPF logger for modularity
1 parent c970d77 commit ca21918

File tree

2 files changed

+163
-62
lines changed

2 files changed

+163
-62
lines changed

cmd/listener/main.go

Lines changed: 54 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,90 +1,82 @@
1+
// main.go
12
package main
23

34
import (
4-
"bytes"
5-
"encoding/binary"
5+
"flag"
6+
"fmt"
67
"log"
78
"os"
89
"os/signal"
910
"syscall"
1011

11-
"go-ebp-logger/internal/event"
12+
"go-ebp-logger/internal/bpfmanager"
13+
"go-ebp-logger/internal/event"
1214

13-
"github.com/cilium/ebpf"
14-
"github.com/cilium/ebpf/link"
15-
"github.com/cilium/ebpf/ringbuf"
15+
"github.com/cilium/ebpf/ringbuf"
1616
)
1717

1818
func main() {
19-
bpfObj := "monitor.bpf.o"
20-
spec, err := ebpf.LoadCollectionSpec(bpfObj)
21-
if err != nil {
22-
log.Fatalf("Failed to load BPF spec: %v", err)
19+
20+
done := make(chan struct{})
21+
flag.Usage = func() {
22+
fmt.Fprintf(os.Stderr, "Usage: %s <bpf-object-file>\n", os.Args[0])
23+
}
24+
flag.Parse()
25+
if flag.NArg() < 1 {
26+
flag.Usage()
27+
os.Exit(1)
2328
}
29+
bpfObjPath := flag.Arg(0)
2430

25-
coll, err := ebpf.NewCollection(spec)
31+
bpfManager, err := bpfmanager.NewBPFManager(bpfObjPath)
2632
if err != nil {
27-
log.Fatalf("Failed to load BPF collection: %v", err)
33+
log.Fatalf("Failed to initialize BPF manager: %v", err)
2834
}
29-
defer coll.Close()
35+
defer bpfManager.Close()
3036

31-
prog := coll.Programs["trace_read"]
32-
if prog == nil {
33-
log.Fatalf("Program 'trace_read' not found")
34-
}
3537

36-
kp, err := link.Kprobe("vfs_read", prog, nil)
37-
if err != nil {
38-
log.Fatalf("Failed to attach kprobe: %v", err)
38+
if err := bpfManager.AttachKprobe("vfs_read", "trace_read"); err != nil {
39+
log.Fatalf("Failed to attach kprobe for vfs_read: %v", err)
3940
}
40-
defer kp.Close()
41-
42-
monitoredInodeMap := coll.Maps["monitored_inodes"]
43-
if monitoredInodeMap == nil {
44-
log.Printf("Map 'monitored_inode' not found in collection. Skipping pinning.")
45-
} else {
46-
pinPath := "/sys/fs/bpf/monitored_inode"
47-
if err := os.Remove(pinPath); err != nil && !os.IsNotExist(err) {
48-
log.Printf("Warning: failed to remove existing pin at %s: %v", pinPath, err)
49-
}
50-
51-
if err := monitoredInodeMap.Pin(pinPath); err != nil {
52-
log.Fatalf("Failed to pin map 'monitored_inode' to %s: %v", pinPath, err)
53-
}
54-
log.Printf("Map 'monitored_inode' pinned to %s", pinPath)
55-
}
56-
57-
58-
events := coll.Maps["events"]
59-
if events == nil {
60-
log.Fatalf("Map 'events' not found")
41+
42+
43+
if err := bpfManager.PinMap("monitored_inodes", "/sys/fs/bpf/monitored_inode"); err != nil {
44+
log.Fatalf("Failed to pin 'monitored_inodes' map: %v", err)
6145
}
6246

63-
rd, err := ringbuf.NewReader(events)
64-
if err != nil {
65-
log.Fatalf("Failed to create ring buffer reader: %v", err)
47+
48+
if err := bpfManager.InitRingBufferReader("events"); err != nil {
49+
log.Fatalf("Failed to initialize event reader: %v", err)
6650
}
67-
defer rd.Close()
51+
rd := bpfManager.GetEventReader()
52+
53+
fmt.Println("Waiting for events... Press Ctrl+C to stop.")
54+
6855

69-
log.Println("Listening for events... Press Ctrl+C to stop.")
7056
sigCh := make(chan os.Signal, 1)
7157
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
7258

73-
loop:
74-
for {
75-
select {
76-
case <-sigCh:
77-
break loop
78-
default:
79-
record, err := rd.Read()
80-
if err != nil {
81-
log.Printf("Failed to read from ring buffer: %v", err)
82-
continue
83-
}
84-
var e event.Data
85-
if err := binary.Read(bytes.NewReader(record.RawSample), binary.LittleEndian, &e); err == nil {
86-
event.Print(e)
59+
go func() {
60+
for {
61+
select {
62+
case <-done:
63+
return
64+
default:
65+
record, err := rd.Read()
66+
if err != nil {
67+
if ringbuf.Is (err) {
68+
log.Println("Ring buffer reader closed, exiting event processing goroutine.")
69+
return
70+
}
71+
log.Printf("Failed to read from ring buffer: %v", err)
72+
continue
73+
}
74+
event.Print(record.RawSample)
8775
}
8876
}
89-
}
90-
}
77+
}()
78+
79+
<-sigCh
80+
close(done)
81+
fmt.Println("\nExiting...")
82+
}

internal/ebpfmanager/bpfmanager.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package bpfmanager
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
8+
"github.com/cilium/ebpf"
9+
"github.com/cilium/ebpf/link"
10+
"github.com/cilium/ebpf/ringbuf"
11+
)
12+
13+
type BPFManager struct {
14+
collection *ebpf.Collection
15+
reader *ringbuf.Reader
16+
links []link.Link
17+
}
18+
19+
20+
func NewBPFManager(bpfObjPath string) (*BPFManager, error) {
21+
spec, err := ebpf.LoadCollectionSpec(bpfObjPath)
22+
if err != nil {
23+
return nil, fmt.Errorf("failed to load BPF spec from %s: %w", bpfObjPath, err)
24+
}
25+
coll, err := ebpf.NewCollection(spec)
26+
if err != nil {
27+
return nil, fmt.Errorf("failed to load BPF collection: %w", err)
28+
}
29+
return &BPFManager{
30+
collection: coll,
31+
links: make([]link.Link, 0),
32+
}, nil
33+
}
34+
35+
36+
37+
func (bm *BPFManager) AttachKprobe(kernelSymbol string, programName string) error {
38+
prog := bm.collection.Programs[programName]
39+
if prog == nil {
40+
return fmt.Errorf("eBPF program '%s' not found in collection", programName)
41+
}
42+
kp, err := link.Kprobe(kernelSymbol, prog, nil)
43+
if err != nil {
44+
return fmt.Errorf("failed to attach kprobe to '%s' using program '%s': %w", kernelSymbol, programName, err)
45+
}
46+
bm.links = append(bm.links, kp)
47+
log.Printf("Successfully attached kprobe: %s -> %s", kernelSymbol, programName)
48+
return nil
49+
}
50+
51+
52+
53+
func (bm *BPFManager) InitRingBufferReader(mapName string) error {
54+
eventsMap := bm.collection.Maps[mapName]
55+
if eventsMap == nil {
56+
return fmt.Errorf("eBPF map '%s' not found in collection", mapName)
57+
}
58+
rd, err := ringbuf.NewReader(eventsMap)
59+
if err != nil {
60+
return fmt.Errorf("failed to create ring buffer reader for map '%s': %w", mapName, err)
61+
}
62+
bm.reader = rd
63+
log.Printf("Initialized ring buffer reader for map: %s", mapName)
64+
return nil
65+
}
66+
67+
68+
69+
func (bm *BPFManager) GetEventReader() *ringbuf.Reader {
70+
return bm.reader
71+
}
72+
73+
74+
75+
func (bm *BPFManager) PinMap(mapName string, pinPath string) error {
76+
bpfMap := bm.collection.Maps[mapName]
77+
if bpfMap == nil {
78+
log.Printf("Map '%s' not found in collection. Skipping pinning.", mapName)
79+
return nil
80+
}
81+
if err := os.Remove(pinPath); err != nil && !os.IsNotExist(err) {
82+
log.Printf("Warning: failed to remove existing pin at %s: %v", pinPath, err)
83+
}
84+
if err := bpfMap.Pin(pinPath); err != nil {
85+
return fmt.Errorf("failed to pin map '%s' to %s: %w", mapName, pinPath, err)
86+
}
87+
log.Printf("Map '%s' pinned to %s", mapName, pinPath)
88+
return nil
89+
}
90+
91+
92+
func (bm *BPFManager) Close() {
93+
for _, l := range bm.links {
94+
if err := l.Close(); err != nil {
95+
log.Printf("Error closing BPF link: %v", err)
96+
}
97+
}
98+
if bm.reader != nil {
99+
if err := bm.reader.Close(); err != nil {
100+
log.Printf("Error closing ring buffer reader: %v", err)
101+
}
102+
}
103+
if bm.collection != nil {
104+
if err := bm.collection.Close(); err != nil {
105+
log.Printf("Error closing BPF collection: %v", err)
106+
}
107+
}
108+
log.Println("All eBPF resources released.")
109+
}

0 commit comments

Comments
 (0)