Compiling eBPF program in Docker fails due to missing '__u64' type

27 Views Asked by At

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?

0

There are 0 best solutions below