Используемый вами фрагмент описывается в руководстве как псевдокод, он не является полным и функциональным примером. Давайте посмотрим на журнал верификатора:
Load XDP program...
libbpf: load bpf program failed: Permission denied
libbpf: -- BEGIN DUMP LOG ---
libbpf:
0: (bf) r6 = r1 // r6 points to ctx
1: (61) r1 = *(u32 *)(r6 +16) // [let's ignore that]
2: (63) *(u32 *)(r10 -4) = r1 // [and that]
3: (61) r7 = *(u32 *)(r6 +4) // r7 points to ctx->data_end
4: (61) r8 = *(u32 *)(r6 +0) // r8 points to ctx->data
5: (85) call bpf_ktime_get_ns#5 // r0 now contains timestamp
6: (bf) r1 = r8 // r1 points to ctx->data
7: (07) r1 += -8 // r1 = data - sizeof(unsigned long long)
8: (2d) if r1 > r7 goto pc+3 // if(data-sizeof(unsigned long long)>data_end) jump;
Теперь самое интересное. Мы пытаемся сделать:
ctx->data_meta = ctx->data - sizeof(unsigned long long);
memcpy(&ctx->data_meta, &kstamp, sizeof(unsigned long long));
И он производит:
R0_w=inv(id=0) R1_w=pkt(id=0,off=-8,r=0,imm=0) R6_w=ctx(id=0,off=0,imm=0)
R7_w=pkt_end(id=0,off=0,imm=0) R8_w=pkt(id=0,off=0,r=0,imm=0) R10=fp0 fp-8=mmmm????
9: (63) *(u32 *)(r6 +8) = r0
invalid bpf_context access off=8 size=4
r6
указывает на ctx
типа struct xdp_md
, поэтому r6 +8
равно ctx->data - sizeof(unsigned long long)
. Это потому, что по умолчанию ctx->data_meta
указывает на ctx->data
. Поэтому, когда вы пытаетесь скопировать метку времени в ctx->data_meta
, вы фактически пытаетесь записать ее за 8 байтов до начала пакетных данных. У вас нет определенного c места, зарезервированного для размещения метаданных, так что это внешний доступ: верификатор жалуется, что это неверно.
Но как мы можем создать, выделить некоторые место для метаданных, тогда? Это делается благодаря помощнику bpf_xdp_adjust_meta()
BPF, как в примере, на который вы ссылались .
Однако не все драйверы NI C поддерживают метаданные XDP , Некоторые из них вызывают внутреннюю функцию xdp_set_data_meta_invalid()
, которая устанавливает ctx->data_meta
в ctx->data + 1
вместо ctx->data
. Если bpf_xdp_adjust_meta()
, вызванный из программы BPF, обнаруживает, что эта настройка выполнена, выдает ошибку с -ENOTSUPP
и отказывается от настройки ctx->data_meta
. Исходя из обсуждения в комментариях, похоже, что происходит в вашем случае.
Если у вас нет поддержки метаданных XDP, вы можете попытаться закодировать метку времени в другом поле вашего пакета. BPF-карты также могут быть опцией, но вам потребуется одна запись для каждого пакета, поэтому вы не уверены в ее влиянии на память / производительность.