skip to Main Content

I’m trying to compile an eBPF program inside a Docker container based on an ARM64 Ubuntu 20.04 image. I’m encountering a compilation error where the clang compiler cannot find the definition for the __u64 type, which should be provided by the kernel headers. Here’s the error I’m getting:

/usr/include/bpf/bpf_helper_defs.h:78:90: error: unknown type name '__u64'
static long (* const bpf_map_update_elem)(void *map, const void *key, const void *value, __u64 flags) = (void *) 2;
                                                                                          ^

I’ve installed the linux-headers-${KERNEL_VERSION} package and set up the include paths for clang as follows:

RUN clang -O2 -target bpf 
    -I/usr/src/linux-headers-${KERNEL_VERSION}/include 
    -I/usr/src/linux-headers-${KERNEL_VERSION}/include/uapi 
    -I/usr/src/linux-headers-${KERNEL_VERSION}/arch/arm64/include 
    -I/usr/include/aarch64-linux-gnu 
    -I/usr/include/aarch64-linux-gnu/asm 
    -I/usr/include/aarch64-linux-gnu/asm-generic 
    -I/usr/include/bpf 
    -c ebpf_program.c -o ebpf_program.o

I’ve also created symbolic links to ensure that the asm and asm-generic directories are correctly referenced:

RUN ln -s /usr/include/aarch64-linux-gnu/asm /usr/include/asm
RUN ln -s /usr/include/aarch64-linux-gnu/asm-generic /usr/include/asm-generic

The clang compiler still cannot find the asm/types.h file. I’ve verified that the file exists and is accessible in the container. Here’s the output when I SSH into the container:

root@container:/usr/include/aarch64-linux-gnu/asm# cat types.h 
#include <asm-generic/types.h>

Here is my full Dockerfile:

# Use a base image that supports ARM64 architecture for Apple Silicon (local machines)
FROM --platform=linux/arm64 ubuntu:20.04

# Use ARG to specify the kernel version, allowing for flexibility
ARG KERNEL_VERSION=5.4.0-174-generic
ARG DEBIAN_FRONTEND=noninteractive

# Install dependencies
RUN apt-get update && apt-get install -y 
    bpfcc-tools 
    clang 
    llvm 
    libelf-dev 
    zlib1g-dev 
    gcc 
    iproute2 
    git 
    curl 
    ca-certificates 
    linux-libc-dev 
    make 
    pkg-config 
    && apt-get clean

# Install a specific version of the Linux kernel headers
RUN apt-get install -y linux-headers-${KERNEL_VERSION}

# Install Go for ARM64
RUN curl -OL https://golang.org/dl/go1.21.0.linux-arm64.tar.gz 
    && tar -C /usr/local -xzf go1.21.0.linux-arm64.tar.gz 
    && rm go1.21.0.linux-arm64.tar.gz

# Set environment variables for Go
ENV PATH=$PATH:/usr/local/go/bin
ENV GOPATH=/go
ENV PATH=$PATH:$GOPATH/bin

# Copy your Go application source code and module files into the container
COPY src /go/src/go_user_agent

# Set the working directory to the Go user agent script's location
WORKDIR /go/src/go_user_agent/

# Clone the libbpf repository and build it
RUN git clone https://github.com/libbpf/libbpf.git /usr/src/libbpf && 
    cd /usr/src/libbpf/src && 
    make && 
    make install

# Create a symbolic link from /usr/include/aarch64-linux-gnu/asm to /usr/include/asm
RUN ln -s /usr/include/aarch64-linux-gnu/asm /usr/include/asm

# Create a symbolic link from /usr/include/aarch64-linux-gnu/asm-generic to /usr/include/asm-generic
RUN ln -s /usr/include/aarch64-linux-gnu/asm-generic /usr/include/asm-generic

# Set the KERNEL_HEADERS_DIR environment variable to the path of the installed kernel headers
ENV KERNEL_HEADERS_DIR=/usr/src/linux-headers-${KERNEL_VERSION}

# Compile the eBPF program using the correct include paths
RUN clang -O2 -target bpf 
    -I$KERNEL_HEADERS_DIR/include 
    -I$KERNEL_HEADERS_DIR/include/linux 
    -I$KERNEL_HEADERS_DIR/include/uapi 
    -I$KERNEL_HEADERS_DIR/arch/arm64/include 
    -I/usr/include/aarch64-linux-gnu 
    -I/usr/include/asm-generic 
    -I/usr/include/bpf 
    -c ebpf_program.c -o ebpf_program.o

# Download dependencies
RUN go get -d -v

# Run tests and benchmarks
RUN go test -v ./... # Run all tests

# Run benchmarks and capture CPU profiles
RUN go test -bench . -benchmem -cpuprofile cpu.prof -o bench.test

# Build the Go user agent script
RUN go build -o go_user_agent

# Command to run the user agent script
CMD ["./go_user_agent"]

I’m stuck and not sure what else I can do to resolve this issue. Has anyone encountered a similar problem, or can you provide guidance on what might be going wrong?

2

Answers


  1. Have you ever do include <linux/types.h> or <vmlinux.h> in you C file instead of accessing the gerneic or asm types.h directly ?

    and it should be put ahead of include bpf_helper_defs.h

    Login or Signup to reply.
  2. The __u64 type is a basic unsigned 64-bit integer type defined in the Linux kernel headers, typically in types like asm/types.h or linux/types.h. If clang cannot find it, the problem often lies in how the "include paths" are set up, or how the kernel headers are installed and referenced.

    Following "Kernel data types u8, u16, u32, u64 not resolved", the problem was with compiling files related to the wireless subsystem (mac80211) which rely on these data types. The suggested resolution mentioned that <linux/types.h> should automatically include <asm/types.h>, making the explicit inclusion of <asm-generic/types.h> unnecessary and potentially problematic for portability.

    So make sure linux/types.h is included (either directly or indirectly) before any use of the types defined therein.

    Something like:

    RUN clang -O2 -target bpf 
        -I/usr/src/linux-headers-${KERNEL_VERSION}/include 
        -I/usr/src/linux-headers-${KERNEL_VERSION}/arch/arm64/include 
        -I/usr/src/linux-headers-${KERNEL_VERSION}/include/uapi 
        -I/usr/src/linux-headers-${KERNEL_VERSION}/include/generated/uapi 
        -I/usr/include/aarch64-linux-gnu  # Adjust based on your architecture
        -c ebpf_program.c -o ebpf_program.o
    

    While you might be tempted to directly include <asm-generic/types.h> to solve the problem, as mentioned in the Super User answer, this is generally not recommended. The preferred approach is to rely on the hierarchy of includes starting from linux/types.h, which ensures portability and consistency across different kernel versions and architectures.

    As mentioned in this thread, the clang option -target bpf might prevent to find asm/types.h.
    On Ubuntu and Debian systems, architecture-specific headers (like asm/types.h) are located in directories named after the system’s architecture triplet (e.g., /usr/include/x86_64-linux-gnu/ for x86_64 systems). When compiling for BPF with -target bpf, clang does not automatically include these architecture-specific paths, leading to missing definitions.
    Make sure to install gcc-multilib (RUN apt-get install -y gcc-multilib)

    While the direct applicability of these workarounds may vary based on your specific Docker environment and the architecture you’re targeting (ARM64, as mentioned in your Dockerfile), the underlying principles and approaches should help address the compilation issue with __u64.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search