From ed6b350b06346d1e2c60f3022ea1d44398826461 Mon Sep 17 00:00:00 2001 From: skullcmd Date: Tue, 28 Apr 2026 22:07:21 +0000 Subject: [PATCH] fix(install): apt install librte-net-ena25 + librte-net-mlx5-25 with DPDK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Debian DPDK 24.11.x ships every Poll-Mode Driver as its own package (librte-net-) instead of bundling them into libdpdk-dev. Without the relevant PMD installed, rte_eal_init() succeeds but no eth ports are probed and the scanner refuses to start. anygpt-52 hit this on c6in.metal: ENA NICs were silently absent from rte_eth_dev_count_avail() until librte-net-ena25 was apt-installed manually. Reported in PR #65 issuecomment-4339242358. Fix: install_dpdk_build_deps now pulls librte-net-ena25 (AWS ENA PMD — every c6in/c5n/m5n/m6in instance) AND librte-net-mlx5-25 (Mellanox ConnectX-5/6 PMD for non-AWS bare-metal hosts at Equinix/OVH/Hetzner) alongside libdpdk-dev. The 25 ABI suffix matches Debian trixie's DPDK 24.11.x. Stock Intel ixgbe/i40e drivers are still in libdpdk-dev's auto-pull set so we don't need to name them. Falls back to libdpdk-dev alone if PMDs are unavailable in the archive — better to ship a partial DPDK build than fail the install. The runtime warning makes it explicit so operators know to check rte_eth_dev_count_avail() if it returns 0 later. Test: new Case 5 in test-install-external-deps-dpdk.sh runs the install script with ANYSCAN_INSTALL_DPDK_DEPS=true (default) + stubs id and apt-get on PATH, then asserts apt-get install was called with libdpdk-dev, librte-net-ena25, and librte-net-mlx5-25. Co-Authored-By: Claude Opus 4.7 (1M context) --- install-external-deps.sh | 40 +++++++++-- tools/test-install-external-deps-dpdk.sh | 85 ++++++++++++++++++++++++ 2 files changed, 118 insertions(+), 7 deletions(-) diff --git a/install-external-deps.sh b/install-external-deps.sh index a974ca4..bd19d3a 100755 --- a/install-external-deps.sh +++ b/install-external-deps.sh @@ -483,6 +483,21 @@ install_pfring_zc_build_deps() { # # Set ANYSCAN_INSTALL_DPDK_DEPS=false to suppress this block (e.g. on # AMIs where the operator pre-pinned a different libdpdk version). +# Per-NIC DPDK PMD packages. Debian DPDK 24.11.x ships every Poll-Mode +# Driver as its own package (librte-net-) instead of shoving +# them all into libdpdk-dev. Without the relevant PMD installed, +# rte_eal_init() succeeds but no eth ports are probed and the scanner +# refuses to start (anygpt-52 hit this on c6in.metal: ENA NICs silently +# absent from rte_eth_dev_count_avail() until librte-net-ena25 was +# apt-installed manually). +# +# We pull both the AWS PMD (ENA — every c6in/c5n/m5n/m6in instance) and +# the Mellanox PMD (mlx5 — bare-metal hosts at Equinix/OVH/Hetzner with +# CX-5/CX-6 NICs). Stock Intel ixgbe/i40e drivers are still in +# libdpdk-dev's auto-pull set so we don't need to name them. The 25 ABI +# suffix matches Debian trixie's DPDK 24.11.x (libdpdk-dev → librte-*-25). +DPDK_PMD_PACKAGES=(librte-net-ena25 librte-net-mlx5-25) + install_dpdk_build_deps() { if [ "${ANYSCAN_INSTALL_DPDK_DEPS:-true}" != "true" ]; then return 0 @@ -499,21 +514,32 @@ install_dpdk_build_deps() { else printf '[*] Skipping DPDK build deps: not root and sudo is not available.\n' printf ' Install manually if you plan to build the scanner with USE_DPDK=1:\n' - printf ' sudo apt-get install -y libdpdk-dev dpdk\n' + printf ' sudo apt-get install -y libdpdk-dev dpdk %s\n' "${DPDK_PMD_PACKAGES[*]}" return 0 fi if [ "${apt_cmd[0]}" = "sudo" ] && ! sudo -n true >/dev/null 2>&1; then printf '[*] Skipping DPDK build deps: sudo would prompt for a password.\n' printf ' Install manually if you plan to build the scanner with USE_DPDK=1:\n' - printf ' sudo apt-get install -y libdpdk-dev dpdk\n' + printf ' sudo apt-get install -y libdpdk-dev dpdk %s\n' "${DPDK_PMD_PACKAGES[*]}" return 0 fi - printf '[*] Installing DPDK build deps (libdpdk-dev dpdk)...\n' + printf '[*] Installing DPDK build deps (libdpdk-dev dpdk %s)...\n' "${DPDK_PMD_PACKAGES[*]}" if ! "${apt_cmd[@]}" install -y --no-install-recommends \ - libdpdk-dev dpdk >/dev/null 2>&1; then - printf '[!] apt-get install of DPDK build deps failed; the scanner will still build with default `make`.\n' >&2 - printf ' Re-run with USE_DPDK=1 only after libdpdk-dev is present.\n' >&2 - return 0 + libdpdk-dev dpdk "${DPDK_PMD_PACKAGES[@]}" >/dev/null 2>&1; then + # Fall back to libdpdk-dev alone if PMD packages are unavailable + # in the current archive — better to ship a partial DPDK build + # than fail the whole install. The scanner will still link + # against librte_eal but rte_eth_dev_count_avail() will return + # 0 on hosts whose NIC PMD is missing. + printf '[!] apt-get install of DPDK build deps incl. PMDs failed; retrying without PMDs.\n' >&2 + if ! "${apt_cmd[@]}" install -y --no-install-recommends \ + libdpdk-dev dpdk >/dev/null 2>&1; then + printf '[!] apt-get install of DPDK build deps failed; the scanner will still build with default `make`.\n' >&2 + printf ' Re-run with USE_DPDK=1 only after libdpdk-dev is present.\n' >&2 + return 0 + fi + printf '[!] DPDK PMD packages (%s) not installed; rte_eth_dev_count_avail() may return 0 at runtime on ENA/mlx5 hosts.\n' "${DPDK_PMD_PACKAGES[*]}" >&2 + printf ' Install manually once available: sudo apt-get install -y %s\n' "${DPDK_PMD_PACKAGES[*]}" >&2 fi } diff --git a/tools/test-install-external-deps-dpdk.sh b/tools/test-install-external-deps-dpdk.sh index a26b400..9b979aa 100755 --- a/tools/test-install-external-deps-dpdk.sh +++ b/tools/test-install-external-deps-dpdk.sh @@ -298,6 +298,91 @@ else note_fail "dpdk cached-binary path" "install-external-deps.sh exited non-zero (see $case_dir/stderr.log)" fi +# --------------------------------------------------------------------------- +# Case 5: ANYSCAN_INSTALL_DPDK_DEPS=true → apt-get install includes the +# per-NIC PMD packages (librte-net-ena25 + librte-net-mlx5-25). +# +# Without these, rte_eal_init() succeeds but rte_eth_dev_count_avail() +# returns 0 on ENA hosts (anygpt-52 hit this on c6in.metal: librte-net- +# ena25 had to be apt-installed manually before the scanner could see +# any eth ports). PR #65 issuecomment-4339242358. +# --------------------------------------------------------------------------- +case_dir="$WORK_ROOT/case-dpdk-pmd-install" +mkdir -p "$case_dir" + +repo_dir="$case_dir/engine" +runtime_env="$case_dir/runtime.env" +artifact_dir="$case_dir/artifacts" +make_log="$case_dir/make.log" +git_log="$case_dir/git.log" +apt_log="$case_dir/apt.log" +stub_dir="$case_dir/stubs" +linkage_marker="$case_dir/linkage-marker" + +mkdir -p "$repo_dir" "$artifact_dir" +: >"$linkage_marker" # advertise DPDK linkage so make stub produces a librte-linked scanner +: >"$repo_dir/Makefile" + +prepare_stubs "$stub_dir" "$make_log" "$git_log" "$linkage_marker" + +# Stub `id` so install_dpdk_build_deps takes the root branch (apt-get +# directly, not sudo). The script captures id's output via $(id -u …), +# so the stub must echo "0" not "1". +cat >"$stub_dir/id" <<'EOF' +#!/usr/bin/env bash +case "$1" in + -u) printf '0\n' ;; + *) printf '0\n' ;; +esac +EOF +chmod +x "$stub_dir/id" + +# Stub `apt-get` to record argv and succeed. +cat >"$stub_dir/apt-get" <>"$apt_log" +exit 0 +EOF +chmod +x "$stub_dir/apt-get" + +( + export PATH="$stub_dir:$PATH" + export ANYSCAN_USE_DPDK=1 + export ANYSCAN_VULNSCANNER_REPO_DIR="$repo_dir" + # Leave ANYSCAN_INSTALL_DPDK_DEPS unset (defaults to true) so + # install_dpdk_build_deps actually runs the apt-get path. + export ANYSCAN_INSTALL_AFXDP_DEPS=false + export ANYSCAN_INSTALL_PFRING_ZC_DEPS=false + export ANYSCAN_RUNTIME_ENV_FILE="$runtime_env" + export ANYSCAN_LOCAL_BOOTSTRAP_ARTIFACT_DIR="$artifact_dir" + unset SUDO_USER + "$TARGET_SCRIPT" >"$case_dir/stdout.log" 2>"$case_dir/stderr.log" +) || note_fail "dpdk pmd install path" \ + "install-external-deps.sh exited non-zero (see $case_dir/stderr.log)" + +if [ -s "$apt_log" ]; then + note_pass "dpdk pmd install path invokes apt-get" + assert_contains_substring \ + "dpdk pmd install passes libdpdk-dev to apt-get" \ + "libdpdk-dev" \ + "$apt_log" + assert_contains_substring \ + "dpdk pmd install passes librte-net-ena25 to apt-get (ENA PMD for AWS c6in/c5n/m6in)" \ + "librte-net-ena25" \ + "$apt_log" + assert_contains_substring \ + "dpdk pmd install passes librte-net-mlx5-25 to apt-get (mlx5 PMD for non-AWS bare metal)" \ + "librte-net-mlx5-25" \ + "$apt_log" +else + note_fail "dpdk pmd install path invokes apt-get" \ + "expected apt-get to be invoked but $apt_log is empty" + if [ -f "$case_dir/stderr.log" ]; then + printf ' stderr:\n' >&2 + sed 's/^/ /' "$case_dir/stderr.log" >&2 + fi +fi + printf '\n' printf 'PASS: %d\n' "$PASS" printf 'FAIL: %d\n' "$FAIL"