in src/samplers/tcp/bpf.c [153:214]
int trace_inet_socket_accept_return(struct pt_regs *ctx)
{
// inet_socket_accept returns sock* directly, so we get from PT_REGS_RC.
struct sock *sk = (struct sock *)PT_REGS_RC(ctx);
if (!sk)
return 0;
// check this is TCP
u8 protocol = 0;
// unfortunately, we need to have different handling for pre-4.10 and 4.10+
// for pre-4.10, sk_wmem_queued is following sk_protocol field.
// for 4.10+ to 5.5, sk_gso_max_segs is following sk_protocol field.
// for 5.6+, sk_gso_max_segs is following sk_protocol field, but the sk_protocol becomes regular member
// instead of bitfield.
// in order to be compatible, we handle all cases.
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0)
// 5.6+, we can read sk_protocol as a regular field.
u16 p = 0;
bpf_probe_read_kernel(&p, sizeof(p), ((const char*)sk) +
offsetof(struct sock, sk_protocol));
protocol = (u8) p;
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0)
// from 4.10+ to 5.5, sk_protocol is a bit field
// see https://elixir.bootlin.com/linux/v5.4/source/include/net/sock.h#L455.
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
// get the sk_protocol bitfield
protocol = *(u8 *)((u64)&sk->sk_gso_max_segs - 3);
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
protocol = *(u8 *)((u64)&sk->sk_gso_max_segs - 1);
#else
#error "Fix your compiler's __BYTE_ORDER__?!"
#endif
#else
// for pre-4.10, sk_protocol is also a bit field
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
protocol = *(u8 *)((u64)&sk->sk_wmem_queued - 3);
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
protocol = *(u8 *)((u64)&sk->sk_wmem_queued - 1);
#else
#error "Fix your compiler's __BYTE_ORDER__?!"
#endif
#endif
// if the sock is not TCP, igonre.
if (protocol != IPPROTO_TCP)
return 0;
// create the sock stats for the new accepted connection.
struct sock_stats_t stats = {.pid = bpf_get_current_pid_tgid()};
struct tcp_sock *ts = tcp_sk(sk);
// we approximate the starting time to be current time minus the srtt.
stats.ts = bpf_ktime_get_ns() - get_srtt_us(ts) * 1000;
bpf_get_current_comm(&stats.task, sizeof(stats.task));
// store the sock's stats.
sock_stats_map.update(&sk, &stats);
// increment counter;
int loc = 0;
add_value(conn_accepted.lookup(&loc), 1);
return 0;
}