Skip to content

Commit

Permalink
Single bpf_ringbuf_output
Browse files Browse the repository at this point in the history
  • Loading branch information
jschwinger233 committed Jan 19, 2025
1 parent 7850a5d commit 0fc33e7
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 67 deletions.
2 changes: 1 addition & 1 deletion bpf/bpf.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package bpf

//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang -no-strip -target native -type event -type skb_data Bpf ./ktcpdump.c -- -I./headers -I. -Wall
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang-15 -no-strip -target native -type event Bpf ./ktcpdump.c -- -I./headers -I. -Wall
22 changes: 7 additions & 15 deletions bpf/bpf_x86_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified bpf/bpf_x86_bpfel.o
Binary file not shown.
49 changes: 21 additions & 28 deletions bpf/ktcpdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,7 @@ struct event {
u8 dev[16];
};

struct {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__type(key, u32);
__type(value, struct event);
__uint(max_entries, 1);
} event_stash SEC(".maps");
const struct event *_ __attribute__((unused));

struct skb_data {
u8 data[MAX_DATA_SIZE];
Expand All @@ -38,9 +33,9 @@ struct skb_data {
struct {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__type(key, u32);
__type(value, struct skb_data);
__type(value, u8[MAX_DATA_SIZE + sizeof(struct event)]);
__uint(max_entries, 1);
} skb_data_stash SEC(".maps");
} ringbuf_data SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
Expand All @@ -54,11 +49,6 @@ struct {
__uint(max_entries, 1<<29);
} event_ringbuf SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 1<<29);
} skb_data_ringbuf SEC(".maps");

#define is_skb_on_reg(r) \
reg = BPF_CORE_READ(ctx, r); \
if (reg && bpf_map_lookup_elem(&alive_skbs, &reg)) \
Expand Down Expand Up @@ -113,14 +103,16 @@ kprobe_pcap_filter_l2(void *_skb, void *__skb, void *___skb, void *data, void* d
}

static __always_inline bool
kprobe_pcap_filter(struct sk_buff *skb, u8 *has_mac)
kprobe_pcap_filter(struct sk_buff *skb, u8 *has_mac, u16 *off_l2_or_l3)
{
void *skb_head = BPF_CORE_READ(skb, head);
void *data_end = skb_head + BPF_CORE_READ(skb, tail);

u16 mac_header = BPF_CORE_READ(skb, mac_header);
u16 network_header = BPF_CORE_READ(skb, network_header);
*has_mac = BPF_CORE_READ(skb, dev, hard_header_len) && mac_header < network_header ? 1 : 0;
*off_l2_or_l3 = *has_mac ? mac_header : network_header;

if (!*has_mac) {
void *data = skb_head + BPF_CORE_READ(skb, network_header);
return kprobe_pcap_filter_l3((void *)skb, (void *)skb, (void *)skb,
Expand Down Expand Up @@ -197,38 +189,39 @@ int kprobe_skb_by_search(struct pt_regs *ctx)
if (!skb)
return BPF_OK;

struct event *event = bpf_map_lookup_elem(&event_stash, &ZERO);
if (!event)
u8 has_mac;
u16 off_l2_or_l3;
if (!kprobe_pcap_filter(skb, &has_mac, &off_l2_or_l3))
return BPF_OK;

if (!kprobe_pcap_filter(skb, &event->has_mac))
void *ringbuf = bpf_map_lookup_elem(&ringbuf_data, &ZERO);
if (!ringbuf)
return BPF_OK;

struct event *event = (struct event *)ringbuf;

event->at = PT_REGS_IP(ctx);
event->ts = bpf_ktime_get_boot_ns();
event->skb = (u64)skb;
event->has_mac = has_mac;
event->protocol = BPF_CORE_READ(skb, protocol);
BPF_CORE_READ_STR_INTO(&event->dev, skb, dev, name);
get_call_target(ctx, &event->call, bpf_get_attach_cookie(ctx));

u16 off_l2_or_l3 = event->has_mac
? BPF_CORE_READ(skb, mac_header)
: BPF_CORE_READ(skb, network_header);
event->data_len = BPF_CORE_READ(skb, tail) - (u32)off_l2_or_l3;

void *skb_head = BPF_CORE_READ(skb, head);
u32 data_len = event->data_len > MAX_DATA_SIZE
event->data_len = event->data_len > MAX_DATA_SIZE
? MAX_DATA_SIZE
: event->data_len;

struct skb_data *skb_data = bpf_map_lookup_elem(&skb_data_stash, &ZERO);
if (!skb_data)
return BPF_OK;
u32 data_len = event->data_len;

struct skb_data *skb_data = (struct skb_data *)(event + 1);

void *skb_head = BPF_CORE_READ(skb, head);

bpf_probe_read_kernel(&skb_data->data, data_len, (void *)(skb_head + off_l2_or_l3));
bpf_ringbuf_output(&event_ringbuf, ringbuf, sizeof(*event) + data_len, 0);

bpf_ringbuf_output(&event_ringbuf, event, sizeof(*event), 0);
bpf_ringbuf_output(&event_ringbuf, &skb_data->data, data_len, 0);
return BPF_OK;
}

Expand Down
32 changes: 9 additions & 23 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func main() {
verifierLog = fmt.Sprintf("Verifier error: %+v\n", ve)
}

log.Error("Failed to load objects", "verifierLog", verifierLog, "err", err)
log.Error(verifierLog, "err", err)
return
}

Expand Down Expand Up @@ -281,6 +281,8 @@ func main() {
return
}

sizeofEvent := binary.Size(bpf.BpfEvent{})

fmt.Printf("%-4s %-16s %-16s %-18s %-16s\n", "no", "skb", "skb->dev->name", "pc", "ksym")
i := 0

Expand Down Expand Up @@ -334,30 +336,14 @@ func main() {
}
fmt.Println()

rec, err = eventsReader.Read()
if err != nil {
if errors.Is(err, ringbuf.ErrClosed) {
return
}
log.Debug("failed to read ringbuf", "err", err)
continue
}
skbData := make([]byte, event.DataLen)

retried := false
RETRY:
if err = binary.Read(bytes.NewBuffer(rec.RawSample), binary.LittleEndian, &skbData); err != nil {
if !retried {
retried = true
time.Sleep(time.Millisecond)
goto RETRY
} else {
log.Warn("failed to parse ringbuf skbdata",
"skb", fmt.Sprintf("%x", event.Skb),
"data_len", event.DataLen,
"err", err)
continue
}
if err = binary.Read(bytes.NewBuffer(rec.RawSample[sizeofEvent:]), binary.LittleEndian, &skbData); err != nil {
log.Warn("failed to parse ringbuf skbdata",
"skb", fmt.Sprintf("%x", event.Skb),
"data_len", event.DataLen,
"err", err)
continue
}

captureInfo := gopacket.CaptureInfo{
Expand Down

0 comments on commit 0fc33e7

Please sign in to comment.