-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathtcptop.yaml
146 lines (143 loc) · 4.97 KB
/
tcptop.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
programs:
- name: tcptop
metrics:
counters:
- name: ipv4_send_bytes
help: tcp_top
table: ipv4_send_bytes
labels:
- name: pid
size: 4
decoders:
- name: uint
- name: saddr
size: 4
decoders:
- name: inet_ip
- name: daddr
size: 4
decoders:
- name: inet_ip
- name: lport
size: 2
decoders:
- name: uint
- name: dport
size: 2
decoders:
- name: uint
- name: ipv4_recv_bytes
help: tcp_top
table: ipv4_recv_bytes
labels:
- name: pid
size: 4
decoders:
- name: uint
- name: saddr
size: 4
decoders:
- name: inet_ip
- name: daddr
size: 4
decoders:
- name: inet_ip
- name: lport
size: 2
decoders:
- name: uint
- name: dport
size: 2
decoders:
- name: uint
kprobes:
tcp_sendmsg: tcp_sendmsg
tcp_cleanup_rbuf: tcp_cleanup_rbuf
code: |
#include <linux/nsproxy.h>
#include <linux/mount.h>
#include <linux/ns_common.h>
#include <uapi/linux/ptrace.h>
#include <net/sock.h>
#include <bcc/proto.h>
struct ipv4_key_t {
u32 pid;
u32 saddr;
u32 daddr;
u16 lport;
u16 dport;
};
BPF_HASH(ipv4_send_bytes, struct ipv4_key_t);
BPF_HASH(ipv4_recv_bytes, struct ipv4_key_t);
struct ipv6_key_t {
unsigned __int128 saddr;
unsigned __int128 daddr;
u32 pid;
u16 lport;
u16 dport;
u64 __pad__;
};
BPF_HASH(ipv6_send_bytes, struct ipv6_key_t);
BPF_HASH(ipv6_recv_bytes, struct ipv6_key_t);
int tcp_sendmsg(struct pt_regs *ctx, struct sock *sk,
struct msghdr *msg, size_t size)
{
u32 pid = bpf_get_current_pid_tgid() >> 32;
u16 dport = 0, family = sk->__sk_common.skc_family;
if (family == AF_INET) {
struct ipv4_key_t ipv4_key = {.pid = pid};
ipv4_key.saddr = sk->__sk_common.skc_rcv_saddr;
ipv4_key.daddr = sk->__sk_common.skc_daddr;
ipv4_key.lport = sk->__sk_common.skc_num;
dport = sk->__sk_common.skc_dport;
ipv4_key.dport = ntohs(dport);
ipv4_send_bytes.increment(ipv4_key, size);
} else if (family == AF_INET6) {
struct ipv6_key_t ipv6_key = {.pid = pid};
bpf_probe_read_kernel(&ipv6_key.saddr, sizeof(ipv6_key.saddr),
&sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
bpf_probe_read_kernel(&ipv6_key.daddr, sizeof(ipv6_key.daddr),
&sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32);
ipv6_key.lport = sk->__sk_common.skc_num;
dport = sk->__sk_common.skc_dport;
ipv6_key.dport = ntohs(dport);
ipv6_send_bytes.increment(ipv6_key, size);
}
// else drop
return 0;
}
/*
* tcp_recvmsg() would be obvious to trace, but is less suitable because:
* - we'd need to trace both entry and return, to have both sock and size
* - misses tcp_read_sock() traffic
* we'd much prefer tracepoints once they are available.
*/
int tcp_cleanup_rbuf(struct pt_regs *ctx, struct sock *sk, int copied)
{
u32 pid = bpf_get_current_pid_tgid() >> 32;
u16 dport = 0, family = sk->__sk_common.skc_family;
u64 *val, zero = 0;
if (copied <= 0)
return 0;
if (family == AF_INET) {
struct ipv4_key_t ipv4_key = {.pid = pid};
ipv4_key.saddr = sk->__sk_common.skc_rcv_saddr;
ipv4_key.daddr = sk->__sk_common.skc_daddr;
ipv4_key.lport = sk->__sk_common.skc_num;
dport = sk->__sk_common.skc_dport;
ipv4_key.dport = ntohs(dport);
ipv4_recv_bytes.increment(ipv4_key, copied);
} else if (family == AF_INET6) {
struct ipv6_key_t ipv6_key = {.pid = pid};
bpf_probe_read_kernel(&ipv6_key.saddr, sizeof(ipv6_key.saddr),
&sk->__sk_common.skc_v6_rcv_saddr.in6_u.u6_addr32);
bpf_probe_read_kernel(&ipv6_key.daddr, sizeof(ipv6_key.daddr),
&sk->__sk_common.skc_v6_daddr.in6_u.u6_addr32);
ipv6_key.lport = sk->__sk_common.skc_num;
dport = sk->__sk_common.skc_dport;
ipv6_key.dport = ntohs(dport);
ipv6_recv_bytes.increment(ipv6_key, copied);
}
// else drop
return 0;
}