-2

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?

Paul Zhang
  • 305
  • 2
  • 7

1 Answers1

2

TL;DR. You're missing a call to ntohs for the destination port.


It's a common mistake so the first thing I checked is:

You can see the sport is 16415, but the real port is actually 8000. Do I get it wrong?

16415 is 0x401F; 8000 is 0x1F40. They just differ in byte ordering.

pchaigno
  • 11,313
  • 2
  • 29
  • 54