whatcanGOwrong
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
//go:build ignore
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "bpf_endian.h"
|
||||
#include "bpf_tracing.h"
|
||||
|
||||
#define AF_INET 2
|
||||
|
||||
char __license[] SEC("license") = "Dual MIT/GPL";
|
||||
|
||||
/**
|
||||
* For CO-RE relocatable eBPF programs, __attribute__((preserve_access_index))
|
||||
* preserves the offset of the specified fields in the original kernel struct.
|
||||
* So here we don't need to include "vmlinux.h". Instead we only need to define
|
||||
* the kernel struct and their fields the eBPF program actually requires.
|
||||
*
|
||||
* Also note that BTF-enabled programs like fentry, fexit, fmod_ret, tp_btf,
|
||||
* lsm, etc. declared using the BPF_PROG macro can read kernel memory without
|
||||
* needing to call bpf_probe_read*().
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct sock_common is the minimal network layer representation of sockets.
|
||||
* This is a simplified copy of the kernel's struct sock_common.
|
||||
* This copy contains only the fields needed for this example to
|
||||
* fetch the source and destination port numbers and IP addresses.
|
||||
*/
|
||||
struct sock_common {
|
||||
union {
|
||||
struct {
|
||||
// skc_daddr is destination IP address
|
||||
__be32 skc_daddr;
|
||||
// skc_rcv_saddr is the source IP address
|
||||
__be32 skc_rcv_saddr;
|
||||
};
|
||||
};
|
||||
union {
|
||||
struct {
|
||||
// skc_dport is the destination TCP/UDP port
|
||||
__be16 skc_dport;
|
||||
// skc_num is the source TCP/UDP port
|
||||
__u16 skc_num;
|
||||
};
|
||||
};
|
||||
// skc_family is the network address family (2 for IPV4)
|
||||
short unsigned int skc_family;
|
||||
} __attribute__((preserve_access_index));
|
||||
|
||||
/**
|
||||
* struct sock is the network layer representation of sockets.
|
||||
* This is a simplified copy of the kernel's struct sock.
|
||||
* This copy is needed only to access struct sock_common.
|
||||
*/
|
||||
struct sock {
|
||||
struct sock_common __sk_common;
|
||||
} __attribute__((preserve_access_index));
|
||||
|
||||
/**
|
||||
* struct tcp_sock is the Linux representation of a TCP socket.
|
||||
* This is a simplified copy of the kernel's struct tcp_sock.
|
||||
* For this example we only need srtt_us to read the smoothed RTT.
|
||||
*/
|
||||
struct tcp_sock {
|
||||
u32 srtt_us;
|
||||
} __attribute__((preserve_access_index));
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_RINGBUF);
|
||||
__uint(max_entries, 1 << 24);
|
||||
} events SEC(".maps");
|
||||
|
||||
/**
|
||||
* The sample submitted to userspace over a ring buffer.
|
||||
* Emit struct event's type info into the ELF's BTF so bpf2go
|
||||
* can generate a Go type from it.
|
||||
*/
|
||||
struct event {
|
||||
u16 sport;
|
||||
u16 dport;
|
||||
u32 saddr;
|
||||
u32 daddr;
|
||||
u32 srtt;
|
||||
};
|
||||
struct event *unused_event __attribute__((unused));
|
||||
|
||||
SEC("fentry/tcp_close")
|
||||
int BPF_PROG(tcp_close, struct sock *sk) {
|
||||
if (sk->__sk_common.skc_family != AF_INET) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The input struct sock is actually a tcp_sock, so we can type-cast
|
||||
struct tcp_sock *ts = bpf_skc_to_tcp_sock(sk);
|
||||
if (!ts) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct event *tcp_info;
|
||||
tcp_info = bpf_ringbuf_reserve(&events, sizeof(struct event), 0);
|
||||
if (!tcp_info) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tcp_info->saddr = sk->__sk_common.skc_rcv_saddr;
|
||||
tcp_info->daddr = sk->__sk_common.skc_daddr;
|
||||
tcp_info->dport = bpf_ntohs(sk->__sk_common.skc_dport);
|
||||
tcp_info->sport = sk->__sk_common.skc_num;
|
||||
|
||||
tcp_info->srtt = ts->srtt_us >> 3;
|
||||
tcp_info->srtt /= 1000;
|
||||
|
||||
bpf_ringbuf_submit(tcp_info, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user