Skip to content

Commit 395f9b5

Browse files
committed
libbpf-tools: update tcpdrop to address reviewer feedback
- Use ksyms__load and ksyms__map_addr for kernel symbol resolution. - Follow Linux kernel coding style in tcpdrop.bpf.c and tcpdrop.c. - Optimize IPv6 address handling with __u32 arrays and in6_u.u6_addr32. - Remove bpf_printk debug statements from tcpdrop.bpf.c. - Add /tcpdrop to .gitignore to exclude the binary. - Define event struct in tcpdrop.h to prevent duplicate definitions. - Check drop reason with bpf_core_field_exists in tcpdrop.bpf.c. Signed-off-by: Zi Li <[email protected]> Signed-off-by: Amaindex <[email protected]>
1 parent 4da44bd commit 395f9b5

File tree

4 files changed

+523
-551
lines changed

4 files changed

+523
-551
lines changed

libbpf-tools/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
/tcpconnect
6161
/tcpconnlat
6262
/tcplife
63+
/tcpdrop
6364
/tcppktlat
6465
/tcptracer
6566
/tcprtt

libbpf-tools/tcpdrop.bpf.c

Lines changed: 144 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -1,186 +1,177 @@
1+
#include "tcpdrop.h"
12
#include "vmlinux.h"
2-
#include <bpf/bpf_helpers.h>
33
#include <bpf/bpf_core_read.h>
4-
#include <bpf/bpf_tracing.h>
54
#include <bpf/bpf_endian.h>
5+
#include <bpf/bpf_helpers.h>
6+
#include <bpf/bpf_tracing.h>
67

78
#ifndef AF_INET
89
#define AF_INET 2
910
#endif
1011
#ifndef AF_INET6
1112
#define AF_INET6 10
1213
#endif
13-
#ifndef TASK_COMM_LEN
14-
#define TASK_COMM_LEN 16
15-
#endif
1614
#ifndef ETH_P_IP
1715
#define ETH_P_IP 0x0800
1816
#endif
1917
#ifndef ETH_P_IPV6
2018
#define ETH_P_IPV6 0x86dd
2119
#endif
2220

23-
struct event {
24-
u64 timestamp;
25-
u32 pid;
26-
u32 drop_reason;
27-
u32 ip_version; // 4 for IPv4, 6 for IPv6
28-
union {
29-
u32 saddr_v4;
30-
unsigned __int128 saddr_v6;
31-
};
32-
union {
33-
u32 daddr_v4;
34-
unsigned __int128 daddr_v6;
35-
};
36-
u16 sport;
37-
u16 dport;
38-
u8 state;
39-
u8 tcpflags;
40-
char comm[TASK_COMM_LEN];
41-
u32 stack_id;
42-
};
43-
4421
struct {
45-
__uint(type, BPF_MAP_TYPE_RINGBUF);
46-
__uint(max_entries, 512);
22+
__uint(type, BPF_MAP_TYPE_RINGBUF);
23+
__uint(max_entries, 512);
4724
} events SEC(".maps");
4825

4926
#define MAX_STACK_DEPTH 15
5027
struct {
51-
__uint(type, BPF_MAP_TYPE_STACK_TRACE);
52-
__uint(max_entries, 512);
53-
__uint(key_size, sizeof(u32));
54-
__uint(value_size, MAX_STACK_DEPTH * sizeof(u64));
28+
__uint(type, BPF_MAP_TYPE_STACK_TRACE);
29+
__uint(max_entries, 512);
30+
__uint(key_size, sizeof(u32));
31+
__uint(value_size, MAX_STACK_DEPTH * sizeof(u64));
5532
} stack_traces SEC(".maps");
5633

5734
char ipv4_only = 0;
5835
char ipv6_only = 0;
5936
__u32 netns_id = 0;
6037

6138
SEC("tracepoint/skb/kfree_skb")
62-
int tp__skb_free_skb(struct trace_event_raw_kfree_skb *args)
39+
int tp__skb_free_skb(struct trace_event_raw_kfree_skb* args)
6340
{
64-
if (args->reason <= SKB_DROP_REASON_NOT_SPECIFIED) {
65-
return 0;
66-
}
67-
68-
if (bpf_ringbuf_query(&events, BPF_RB_AVAIL_DATA) >= 511) {
69-
bpf_printk("Ring buffer is almost full\n");
70-
return 0;
71-
}
72-
73-
u64 pid_tgid = bpf_get_current_pid_tgid();
74-
u32 pid = pid_tgid >> 32;
75-
76-
struct sk_buff *skb = args->skbaddr;
77-
if (!skb) {
78-
return 0;
79-
}
80-
struct sock *sk = NULL;
81-
bpf_core_read(&sk, sizeof(sk), &skb->sk);
82-
83-
// Get packet headers
84-
void *head;
85-
u16 network_header, transport_header;
86-
if (bpf_core_read(&head, sizeof(head), &skb->head) ||
87-
bpf_core_read(&network_header, sizeof(network_header), &skb->network_header) ||
88-
bpf_core_read(&transport_header, sizeof(transport_header), &skb->transport_header)) {
89-
bpf_printk("Failed to read skb headers\n");
90-
return 0;
91-
}
92-
93-
// Check protocol and filter by IP family
94-
u16 protocol = args->protocol;
95-
if (protocol != ETH_P_IP && protocol != ETH_P_IPV6) {
96-
bpf_printk("Unsupported protocol: %u\n", protocol);
97-
return 0;
98-
}
99-
if (ipv4_only && protocol != ETH_P_IP) {
100-
return 0;
101-
}
102-
if (ipv6_only && protocol != ETH_P_IPV6) {
103-
return 0;
104-
}
105-
106-
// Filter by network namespace
107-
if (netns_id && sk) {
108-
struct net *net = NULL;
109-
bpf_core_read(&net, sizeof(net), &sk->__sk_common.skc_net.net);
110-
if (net) {
111-
u32 inum;
112-
bpf_core_read(&inum, sizeof(inum), &net->ns.inum);
113-
if (inum != netns_id) {
114-
bpf_printk("Skipping packet from different netns: %u != %u\n", inum, netns_id);
115-
return 0;
116-
}
117-
}
118-
}
119-
120-
struct event *event = bpf_ringbuf_reserve(&events, sizeof(*event), 0);
121-
if (!event) {
122-
return 0;
123-
}
124-
125-
event->timestamp = bpf_ktime_get_ns();
126-
event->pid = pid;
127-
event->drop_reason = args->reason;
128-
bpf_get_current_comm(&event->comm, sizeof(event->comm));
129-
event->stack_id = bpf_get_stackid(args, &stack_traces, 0);
130-
event->state = 127;
131-
if (sk) {
132-
u8 state;
133-
if (!bpf_core_read(&state, sizeof(state), &sk->__sk_common.skc_state)) {
134-
event->state = state;
135-
}
136-
}
137-
138-
if (protocol == ETH_P_IP) {
139-
struct iphdr ip;
140-
if (bpf_core_read(&ip, sizeof(ip), head + network_header)) {
141-
bpf_ringbuf_discard(event, 0);
142-
return 0;
143-
}
144-
if (ip.protocol != IPPROTO_TCP) {
145-
bpf_ringbuf_discard(event, 0);
146-
return 0;
147-
}
148-
struct tcphdr tcp;
149-
if (bpf_core_read(&tcp, sizeof(tcp), head + transport_header)) {
150-
bpf_ringbuf_discard(event, 0);
151-
return 0;
152-
}
153-
event->ip_version = 4;
154-
event->saddr_v4 = ip.saddr;
155-
event->daddr_v4 = ip.daddr;
156-
event->sport = bpf_ntohs(tcp.source);
157-
event->dport = bpf_ntohs(tcp.dest);
158-
event->tcpflags = ((u8 *)&tcp)[13];
159-
} else {
160-
struct ipv6hdr ip6;
161-
if (bpf_core_read(&ip6, sizeof(ip6), head + network_header)) {
162-
bpf_ringbuf_discard(event, 0);
163-
return 0;
164-
}
165-
if (ip6.nexthdr != IPPROTO_TCP) {
166-
bpf_ringbuf_discard(event, 0);
167-
return 0;
168-
}
169-
struct tcphdr tcp;
170-
if (bpf_core_read(&tcp, sizeof(tcp), head + transport_header)) {
171-
bpf_ringbuf_discard(event, 0);
172-
return 0;
173-
}
174-
event->ip_version = 6;
175-
bpf_core_read(&event->saddr_v6, sizeof(event->saddr_v6), &ip6.saddr);
176-
bpf_core_read(&event->daddr_v6, sizeof(event->daddr_v6), &ip6.daddr);
177-
event->sport = bpf_ntohs(tcp.source);
178-
event->dport = bpf_ntohs(tcp.dest);
179-
event->tcpflags = ((u8 *)&tcp)[13];
180-
}
181-
182-
bpf_ringbuf_submit(event, 0);
183-
return 0;
41+
struct event* event = bpf_ringbuf_reserve(&events, sizeof(*event), 0);
42+
if(!event) {
43+
return 0;
44+
}
45+
46+
// Check if reason field is available
47+
if(bpf_core_field_exists(args->reason)) {
48+
if(args->reason <= SKB_DROP_REASON_NOT_SPECIFIED) {
49+
bpf_ringbuf_discard(event, 0);
50+
return 0;
51+
}
52+
event->drop_reason = args->reason;
53+
} else {
54+
event->drop_reason = -1;
55+
}
56+
57+
if(bpf_ringbuf_query(&events, BPF_RB_AVAIL_DATA) >= 511) {
58+
bpf_ringbuf_discard(event, 0);
59+
return 0;
60+
}
61+
62+
u64 pid_tgid = bpf_get_current_pid_tgid();
63+
u32 pid = pid_tgid >> 32;
64+
65+
struct sk_buff* skb = args->skbaddr;
66+
if(!skb) {
67+
bpf_ringbuf_discard(event, 0);
68+
return 0;
69+
}
70+
struct sock* sk = NULL;
71+
bpf_core_read(&sk, sizeof(sk), &skb->sk);
72+
73+
// Get packet headers
74+
void* head;
75+
u16 network_header, transport_header;
76+
if(bpf_core_read(&head, sizeof(head), &skb->head) ||
77+
bpf_core_read(&network_header, sizeof(network_header),
78+
&skb->network_header) ||
79+
bpf_core_read(&transport_header, sizeof(transport_header),
80+
&skb->transport_header)) {
81+
bpf_ringbuf_discard(event, 0);
82+
return 0;
83+
}
84+
85+
// Check protocol and filter by IP family
86+
u16 protocol = args->protocol;
87+
if(protocol != ETH_P_IP && protocol != ETH_P_IPV6) {
88+
bpf_ringbuf_discard(event, 0);
89+
return 0;
90+
}
91+
if(ipv4_only && protocol != ETH_P_IP) {
92+
bpf_ringbuf_discard(event, 0);
93+
return 0;
94+
}
95+
if(ipv6_only && protocol != ETH_P_IPV6) {
96+
bpf_ringbuf_discard(event, 0);
97+
return 0;
98+
}
99+
100+
// Filter by network namespace
101+
if(netns_id && sk) {
102+
struct net* net = NULL;
103+
bpf_core_read(&net, sizeof(net), &sk->__sk_common.skc_net.net);
104+
if(net) {
105+
u32 inum;
106+
bpf_core_read(&inum, sizeof(inum), &net->ns.inum);
107+
if(inum != netns_id) {
108+
bpf_ringbuf_discard(event, 0);
109+
return 0;
110+
}
111+
}
112+
}
113+
114+
event->timestamp = bpf_ktime_get_ns();
115+
event->pid = pid;
116+
bpf_get_current_comm(&event->comm, sizeof(event->comm));
117+
event->stack_id = bpf_get_stackid(args, &stack_traces, 0);
118+
event->state = 127;
119+
if(sk) {
120+
u8 state;
121+
if(!bpf_core_read(&state, sizeof(state),
122+
&sk->__sk_common.skc_state)) {
123+
event->state = state;
124+
}
125+
}
126+
127+
if(protocol == ETH_P_IP) {
128+
struct iphdr ip;
129+
if(bpf_core_read(&ip, sizeof(ip), head + network_header)) {
130+
bpf_ringbuf_discard(event, 0);
131+
return 0;
132+
}
133+
if(ip.protocol != IPPROTO_TCP) {
134+
bpf_ringbuf_discard(event, 0);
135+
return 0;
136+
}
137+
struct tcphdr tcp;
138+
if(bpf_core_read(&tcp, sizeof(tcp), head + transport_header)) {
139+
bpf_ringbuf_discard(event, 0);
140+
return 0;
141+
}
142+
event->ip_version = 4;
143+
event->saddr_v4 = ip.saddr;
144+
event->daddr_v4 = ip.daddr;
145+
event->sport = bpf_ntohs(tcp.source);
146+
event->dport = bpf_ntohs(tcp.dest);
147+
event->tcpflags = ((u8*) &tcp)[13];
148+
} else {
149+
struct ipv6hdr ip6;
150+
if(bpf_core_read(&ip6, sizeof(ip6), head + network_header)) {
151+
bpf_ringbuf_discard(event, 0);
152+
return 0;
153+
}
154+
if(ip6.nexthdr != IPPROTO_TCP) {
155+
bpf_ringbuf_discard(event, 0);
156+
return 0;
157+
}
158+
struct tcphdr tcp;
159+
if(bpf_core_read(&tcp, sizeof(tcp), head + transport_header)) {
160+
bpf_ringbuf_discard(event, 0);
161+
return 0;
162+
}
163+
event->ip_version = 6;
164+
bpf_core_read(&event->saddr_v6, sizeof(event->saddr_v6),
165+
&ip6.saddr.in6_u.u6_addr32);
166+
bpf_core_read(&event->daddr_v6, sizeof(event->daddr_v6),
167+
&ip6.daddr.in6_u.u6_addr32);
168+
event->sport = bpf_ntohs(tcp.source);
169+
event->dport = bpf_ntohs(tcp.dest);
170+
event->tcpflags = ((u8*) &tcp)[13];
171+
}
172+
173+
bpf_ringbuf_submit(event, 0);
174+
return 0;
184175
}
185176

186177
char _license[] SEC("license") = "Dual BSD/GPL";

0 commit comments

Comments
 (0)