I am trying to capture the syn queue len and accept queue len by setting a kprobe on tcp_v4_syn_recv_sock
, the logic would get the third param of it (request_sock) and get ir_num
of the sock.
I have searched for it, and the ir_num
seems to be the "local port". In my opinion, the "local port" is the listening port. However, the ir_num
is very different from the listening port.
The ebpf code:
static __always_inline int request_sock_to_ring(struct filler_data *data, struct request_sock *sk)
{
u16 sport = 0;
u16 dport = 0;
u32 saddr = 0;
u32 daddr = 0;
u16 family = 0;
const struct inet_request_sock *ireq = inet_rsk(sk);
bpf_probe_read(&sport, sizeof(sport), (void *)&ireq->ir_rmt_port);
bpf_probe_read(&dport, sizeof(dport), (void *)&ireq->ir_num);
bpf_probe_read(&saddr, sizeof(saddr), (void *)&ireq->ir_rmt_addr);
bpf_probe_read(&daddr, sizeof(daddr), (void *)&ireq->ir_loc_addr);
bpf_probe_read(&family, sizeof(family), (void *)&sk->__req_common.skc_family);
sport = ntohs(sport);
int size = 1 + 4 + 4 + 2 + 2;
data->buf[data->state->tail_ctx.curoff & SCRATCH_SIZE_HALF] = socket_family_to_scap(family);
memcpy(&data->buf[(data->state->tail_ctx.curoff + 1) & SCRATCH_SIZE_HALF], &saddr, 4);
memcpy(&data->buf[(data->state->tail_ctx.curoff + 5) & SCRATCH_SIZE_HALF], &sport, 2);
memcpy(&data->buf[(data->state->tail_ctx.curoff + 7) & SCRATCH_SIZE_HALF], &daddr, 4);
memcpy(&data->buf[(data->state->tail_ctx.curoff + 11) & SCRATCH_SIZE_HALF], &dport, 2);
data->curarg_already_on_frame = true;
return bpf_val_to_ring_len(data, 0, size);
}
The log:
wrk-4122915 [003] dNs11 4843677.931047: bpf_trace_printk: saddr 16777343 daddr 16777343
wrk-4122915 [003] dNs11 4843677.931055: bpf_trace_printk: saddr 16777343 sport 33112 dport 16415
You can see the sport is 16415, but the real port is actually 8000. Do I get it wrong?