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
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
The
__u64
type is a basic unsigned 64-bit integer type defined in the Linux kernel headers, typically in types likeasm/types.h
orlinux/types.h
. Ifclang
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:
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 fromlinux/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 findasm/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
.