简体   繁体   中英

eBPF implicit declaration of BPF Helper

I'm having an issue with compiling an eBPF program that I'm installing with TC. At the moment, it is only performing some basic mangling, which requires recalculating the IP checksum.

I noticed in the BPF helpers, there is a function bpf_l3_csum_replace which seems to be what I want. However, when I try to use any of the built-in functions that are mapped using the BPF_FUNC macro, I get an implicit declaration error:

... warning: implicit declaration of 'bpf_l3_csum_replace' is invalid in C99.

This is subsequently followed by an error from the verifier:

... A call to global function 'bpf_l3_csum_replace' is not supported. Only calls to predefined BPF helpers are allowed.

My compile line:

clang -target bpf -nostdinc -I/usr/include -I/usr/lib64/clang/5.0.2/include -O2 -emit-llvm -c <file> -o - | llc -march=bpf -filetype=obj -o <output>

I should note that I am able to compile and install a BPF object (using TC), as long as I don't use any of the "predefined" bpf helpers. The issue arises once I do.

I'm doing this outside of the kernel tree, FWIW. Not sure if that is an issue. I'm including the bpf header (linux/bpf.h), and I'm using the bpf_api.h header from the iproute2 package (didn't have much luck with the bpf_helpers.h header).

I'm still relatively new to eBPF, so I would not be surprised if I'm missing something. Any help would be appreciated.

Edit: Code

#define KBUILD_NAME "testbpf"
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/in.h>
#include <linux/tcp.h>
#include <linux/filter.h>
#include <linux/pkt_cls.h>
#include "bpf_api.h"


#define _htonl __builtin_bswap32

struct eth_hdr {
    unsigned char h_dest[ETH_ALEN];
    unsigned char h_source[ETH_ALEN];
    unsigned short h_proto;
};

#define IP_CSUM_OFFSET (ETH_HLEN + offsetof(struct iphdr, check))
#define TOS_OFF (ETH_HLEN + offsetof(struct iphdr, tos))
#define PROTO_OFF (ETH_HLEN + offsetof(struct iphdr, protocol))

__section("ingress") int bpf_prog(struct __sk_buff *skb)
{
    void *data = (void *) (long)skb->data;
    struct eth_hdr *eth = data;
    void *data_end = (void*) (long) skb->data_end;

    if (data+sizeof(*eth) > data_end)
        return BPF_H_DEFAULT;

    if (eth->h_proto == htons(ETH_P_ARP))
        return BPF_H_DEFAULT;

    // ipv4
    if (eth->h_proto == htons(ETH_P_IP))
    {
        struct iphdr *ip = data+sizeof(*eth);
        if (data+sizeof(*ip)+sizeof(*eth) > data_end)
            return BPF_H_DEFAULT;

        __u8 proto = ip->protocol;
        __u8 old_tos = ip->tos;
        // mangle our tos; not meant to achieve anything
        ip->tos = 0x04;
        if (proto == IPPROTO_ICMP)
            ip->tos = 0x00;
        if (proto == IPPROTO_TCP)
            ip->tos = 0x04;
        if (proto == IPPROTO_UDP)
            ip->tos = 0x08;
        // update our csum and return
        bpf_l3_csum_replace(skb, IP_CSUM_OFFSET, old_tos, ip->tos, 2); // ISSUE here
        return BPF_H_DEFAULT;
    }

    return BPF_H_DEFAULT;
}

char __license[] __section("license") = "GPL";

The compiler is throwing that error because bpf_api.h defines this helper as:

static int l3_csum_replace(struct __sk_buff *skb, uint32_t off, uint32_t from, uint32_t to, uint32_t flags);

instead of bpf_l3_csum_replace . If you remove the bpf_ prefix from the helper's name in your code it compiles as expected without manually adding a prototype.


Detail & Debugging

If you follow the prototype definition in bpf_api.h , you'll see that it uses BPF_FUNC which itself uses __BPF_FUNC :

#ifndef __BPF_FUNC
# define __BPF_FUNC(NAME, ...)                      \
    (* NAME)(__VA_ARGS__) __maybe_unused
#endif

#ifndef BPF_FUNC
# define BPF_FUNC(NAME, ...)                        \
    __BPF_FUNC(NAME, __VA_ARGS__) = (void *) BPF_FUNC_##NAME
#else
#endif

According to this snippet of code, any helper definition of the form:

static return_type BPF_FUNC(name, ... args ...);

will be expanded into:

static return_type name(... args ...);

So no bpf_ prefix is ever appended.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM