Проблема с bpf_xdp_adjust_head

Работаем над небольшой программой с bpf для расширения пакета (т.е. добавляем mpls encap). Удалось расширить без проблем, но я пишу в заголовке, что s_mac и d_mac неверны. Я предполагаю, что из-за того, что новое пространство меньше, я перекрываю исходный заголовок eth и, таким образом, получаю неправильные значения.

    /* extend the packet for mpls header encapsulation */
    if (bpf_xdp_adjust_head(ctx, 0 - (int)sizeof(struct mpls_hdr)))
        return XDP_DROP;

    data = (void *)(long)ctx->data;
    data_end = (void *)(long)ctx->data_end;

    /* relocate ethernet header to start of packet and set MACs */
    new_eth = data;
    old_eth = data + (int)sizeof(struct mpls_hdr);
    //set new header while swaping src/dst mac
    set_ethhdr(new_eth, old_eth, bpf_htons(ETH_P_MPLS_UC));

Вот где я считаю, что проблема возникает, когда я memcpy в new_eth я вгрызаюсь в пространство old_eth. Есть ли способ решить эту проблему, скопировав значения old_eth в другую структуру, а затем используя ее для создания new_eth?

static __always_inline void set_ethhdr(struct ethhdr *new_eth,
                                       const struct ethhdr *old_eth,
                                       __be16 h_proto)
{
    memcpy(new_eth->h_source, old_eth->h_source, ETH_ALEN);
    memcpy(new_eth->h_dest, old_eth->h_dest, ETH_ALEN);
    new_eth->h_proto = h_proto;
}

Я очень новичок в BPF и C в целом, поэтому не уверен, действительно ли это проблема.

Спасибо.


person Cmarv    schedule 26.12.2020    source источник


Ответы (1)


Я изменил, как показано ниже. Не уверен, что это лучший способ решить эту проблему, но он работает для моего варианта использования ( poc ).

static __always_inline void set_ethhdr(struct ethhdr *new_eth,
                                       const struct ethhdr *old_eth,
                                       __be16 h_proto)
{
    __u8 h_tmp_src[ETH_ALEN];
    __u8 h_tmp_dst[ETH_ALEN];

    __builtin_memcpy(h_tmp_src, old_eth->h_source, ETH_ALEN);
    __builtin_memcpy(h_tmp_dst, old_eth->h_dest, ETH_ALEN);

    __builtin_memcpy(new_eth->h_dest, h_tmp_src, ETH_ALEN);
    __builtin_memcpy(new_eth->h_source, h_tmp_dst, ETH_ALEN);
    
    new_eth->h_proto = h_proto;
}
person Cmarv    schedule 26.12.2020