3

I try to perform a test run for an XDP BPF program. The BPF program uses the bpf_xdp_adjust_meta() helper, to adjust the meta data.

I tried:

  1. to run bpf_prog_test_run()
  2. to run bpf_prog_test_run_xattr()

1. bpf_prog_test_run()
(The first time I tried my bpf program's debug messages told me that adjusting the data_meta field failed.) Now it can adjust the data_meta, but the iph.ihl field is apparently not set to 5.

2. bpf_prog_test_xattr()
This always returns -1, so something failed.

The Code

packet:

struct ipv4_packet pkt_v4 = {
    .eth.h_proto = __bpf_constant_htons(ETH_P_IP),
    .iph.ihl = 5,
    .iph.daddr = __bpf_constant_htonl(33554442),
    .iph.saddr = __bpf_constant_htonl(50331658),
    .iph.protocol = IPPROTO_TCP,
    .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES),
    .tcp.urg_ptr = 123,
    .tcp.doff = 5,
};

test attribute:

__u32 size, retval, duration;
char data_out[128];
struct xdp_md ctx_in, ctx_out;
struct bpf_prog_test_run_attr test_attr = {
    .prog_fd        = prog_fd,
    .repeat         = 100,
    .data_in        = &pkt_v4,
    .data_size_in   = sizeof(&pkt_v4),
    .data_out       = &data_out,
    .data_size_out  = sizeof(data_out),
    .ctx_in         = &ctx_in,
    .ctx_size_in    = sizeof(ctx_in),
    .ctx_out        = &ctx_out,
    .ctx_size_out   = sizeof(ctx_out),
    .retval         = &retval,
    .duration       = &duration,
};

test execution:
bpf_prog_test_run(main_prog_fd, 1, &pkt_v4, sizeof(pkt_v4), &data_out, &size, &retval, &duration) -> iph.ihl field is 0.

bpf_prog_test_run_xattr(&test_attr) -> returns -1.

Note

The program was already successfully attached to the hook point of a real network interface and ran as intended. I just replaced the code that attaches the program to the hook point with the above code for testing.

n1kb3rt
  • 111
  • 1
  • 8
  • 1
    I changed the title and deleted the old question since it based on false assumptions and the actual problem was something else – n1kb3rt Oct 05 '21 at 21:42

1 Answers1

3

The struct ipv4_packet pkt_v4 was not packed.

When I replace __packed with __attribute__ ((__packed__)) it works.

For information what happens without packing, see for example this question.
Basically the compiler adds padding bytes which leads to the fields in the packet being in different places than expected.

n1kb3rt
  • 111
  • 1
  • 8