在 Docker 中编译 eBPF 程序因缺少 '__u64' 类型而失败

问题描述 投票:0回答:2

我正在尝试在基于 ARM64 Ubuntu 20.04 映像的 Docker 容器内编译 eBPF 程序。我遇到编译错误,其中

clang
编译器无法找到
__u64
类型的定义,该定义应由内核标头提供。这是我收到的错误:

/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;
                                                                                          ^

我已经安装了

linux-headers-${KERNEL_VERSION}
软件包并设置了 clang 的包含路径,如下所示:

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

我还创建了符号链接以确保正确引用

asm
asm-generic
目录:

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

clang
编译器仍然找不到
asm/types.h
文件。我已验证该文件存在并且可以在容器中访问。这是我通过 SSH 连接到容器时的输出:

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

这是我完整的 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"]

我陷入困境,不知道还能做什么来解决这个问题。有没有人遇到过类似的问题,或者您可以提供可能出现问题的指导吗?

c linux docker ubuntu clang
2个回答
0
投票

您是否曾经在 C 文件中包含 ,而不是直接访问 gernic 或 asm types.h ?

并且它应该放在 include bpf_helper_defs.h 之前


0
投票

__u64
类型是Linux内核头文件中定义的基本无符号64位整数类型,通常为
asm/types.h
linux/types.h
等类型。如果
clang
找不到,问题往往在于如何设置“包含路径”,或者如何安装和引用内核头。

在“内核数据类型 u8、u16、u32、u64 未解决”之后,问题出在编译与依赖这些数据类型的无线子系统 (mac80211) 相关的文件。建议的决议提到

<linux/types.h>
应自动包含
<asm/types.h>
,这使得显式包含
<asm-generic/types.h>
变得不必要,并且可能会带来可移植性问题。

因此请确保在

使用其中定义的类型之前
包含(直接或间接)linux/types.h

类似:

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

虽然您可能会想直接包含

<asm-generic/types.h>
来解决问题,但正如超级用户答案中提到的,通常不建议这样做。首选方法是依赖从
linux/types.h
开始的包含层次结构,这确保了不同内核版本和架构之间的可移植性和一致性。

此线程中所述,

clang
选项
-target bpf
可能会阻止找到
asm/types.h

在 Ubuntu 和 Debian 系统上,特定于体系结构的标头(如
asm/types.h
)位于以系统体系结构三元组命名的目录中(例如,对于 x86_64 系统为
/usr/include/x86_64-linux-gnu/
)。当使用
-target bpf
编译 BPF 时,
clang
不会自动包含这些特定于架构的路径,从而导致定义缺失。 确保安装
gcc-multilib
(
RUN apt-get install -y gcc-multilib
)

虽然这些解决方法的直接适用性可能会根据您的特定 Docker 环境和您的目标架构(ARM64,如 Dockerfile 中所述)而有所不同,但基本原则和方法应该有助于解决编译问题

__u64

© www.soinside.com 2019 - 2024. All rights reserved.