-
Notifications
You must be signed in to change notification settings - Fork 3.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add tcpdrop tool #1790
add tcpdrop tool #1790
Conversation
tools/tcpdrop.py
Outdated
| // separate data structs for ipv4 and ipv6 | ||
| struct ipv4_data_t { | ||
| // XXX: switch some to u32's when supported |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should be able to switch to u32/u16...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll try. I'm on llvm-5.0, and there's still issues. My ipv6_data_t struct was originally:
struct ipv6_data_t {
u64 stack_id;
u64 pid;
u64 ip;
unsigned __int128 saddr;
unsigned __int128 daddr;
u64 sport;
u64 dport;
u64 state;
u64 tcpflags;
};
which doesn't work:
Traceback (most recent call last):
File "_ctypes/callbacks.c", line 315, in 'calling callback function'
File "/usr/lib/python2.7/dist-packages/bcc/table.py", line 561, in raw_cb_
callback(cpu, data, size)
File "./tcpdrop.py", line 198, in print_ipv6_event
tcp.tcpstate[event.state], tcp.flags2str(event.tcpflags)))
KeyError: 53740L
But if I move the stack_id to the end, it works. I imagine it's alignment of those __int128's.
I'll see how far I can get improving the other members.
| # initialize BPF | ||
| b = BPF(text=bpf_text) | ||
| if b.get_kprobe_functions("tcp_drop"): | ||
| b.attach_kprobe(event="tcp_drop", fn_name="trace_tcp_drop") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checked the latest bpf-next code. I got
[yhs@localhost net]$ egrep -r tcp_drop
ipv4/tcp_input.c:static void tcp_drop(struct sock *sk, struct sk_buff *skb)
ipv4/tcp_input.c: tcp_drop(sk, skb);
ipv4/tcp_input.c: tcp_drop(sk, skb);
ipv4/tcp_input.c: tcp_drop(sk, skb1);
ipv4/tcp_input.c: tcp_drop(sk, skb);
ipv4/tcp_input.c: tcp_drop(sk, rb_to_skb(node));
ipv4/tcp_input.c: tcp_drop(sk, skb);
ipv4/tcp_input.c: tcp_drop(sk, skb);
ipv4/tcp_input.c: tcp_drop(sk, skb);
ipv4/tcp_input.c: tcp_drop(sk, skb);
[yhs@localhost net]$ pwd
/home/yhs/work/bpf-next/net
[yhs@localhost net]$ uname -r
4.17.0-rc6+
[yhs@localhost net]$
Looks like tcp_drop is only for ipv4? I did not find an appropriate place to trace tcp packet drop for ipv6.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, thanks. So I don't know yet what's going on, but IPv6 is traceable:
# ./tcpdrop.py
TIME PID IP SADDR:SPORT > DADDR:DPORT STATE (FLAGS)
21:07:37 7411 6 ::1:23 > ::1:53834 CLOSE (RST|ACK)
tcp_drop+0x1
tcp_v6_do_rcv+0x1ca
__release_sock+0x88
release_sock+0x30
__inet_stream_connect+0x172
inet_stream_connect+0x3b
SYSC_connect+0x9e
sys_connect+0xe
do_syscall_64+0x73
entry_SYSCALL_64_after_hwframe+0x3d
And yet if I look at tcp_v6_do_rcv(), it doesn't call tcp_drop. Maybe something is inlined?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just checked tcp_ipv6.c. tcp_v6_do_rcv calls tcp_rcv_established which is defined in net/ipv4/tcp_input.c and calls tcp_drop. Therefore, indeed, v6 packets could call tcp_drop.
|
[buildbot, ok to test] |
|
Looks good. Thanks! |
Needed this for a production issue.
This is the first tool (that I know of) to dig into the TCP and IP headers, and I've created a new tcp bcc library to help a bit with that.