Skip to content

infra: add pdump support for live packet capture with tcpdump#561

Closed
vjardin wants to merge 1 commit into
DPDK:mainfrom
vjardin:vj_tcpdump
Closed

infra: add pdump support for live packet capture with tcpdump#561
vjardin wants to merge 1 commit into
DPDK:mainfrom
vjardin:vj_tcpdump

Conversation

@vjardin

@vjardin vjardin commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

Add a --pdump flag that enables DPDK secondary process attachment for packet capture. When set, grout starts without --in-memory (shared hugepages) and calls rte_pdump_init() to register the IPC handler.

Stock system tcpdump can then attach as a secondary process and capture live traffic using the grout:N device syntax. A wrapper script (subprojects/packagefiles/libpcap/grout-tcpdump.sh) handles the LD_LIBRARY_PATH setup while libpcap upstream support is pending (the-tcpdump-group/libpcap#1656).

The libpcap subproject is built as a shared library with DPDK pdump support via cmake. It produces libpcap.so with both PCAP_SUPPORT_DPDK (standalone dpdk:N devices) and PCAP_SUPPORT_DPDK_PDUMP (secondary grout:N devices) enabled.

The DPDK subproject requires a patch to lib/eal/common/eal_common_thread.c that removes an overly conservative rte_mp_disable() call from rte_thread_register(), which blocked secondary process attachment when non-EAL worker threads are registered.

Packet dump support for tcpdump secondary process attachment

Adds --pdump flag to enable DPDK secondary process mode, allowing system tcpdump with DPDK support to attach and capture traffic on grout:N devices.

Application changes

main/dpdk.c:

  • Includes rte_pdump.h
  • Modified EAL arguments: skips --in-memory flag when pdump is enabled (line: else if (!gr_config.pdump))
  • Calls rte_pdump_init() after rte_eal_init() if pdump is active, logs errors and NOTICE level message on success

main/gr_config.h:

  • Added bool pdump field to struct gr_config

main/main.c:

  • Added -P/--pdump command-line option with documentation
  • Sets gr_config.pdump = true when flag is provided

Build system changes

meson.build:

  • Updated DPDK dependency: enabled pdump and bpf libraries in enable_libs option
  • Added custom_target for libpcap build that:
    • Creates dedicated build directory (libpcap-build)
    • Configures libpcap via CMake with DPDK support enabled
    • Sets PKG_CONFIG_PATH to DPDK pkg-config directories
    • Exports DPDK_LIBDIR and DPDK_DRVDIR environment variables for CMake
    • Links against DPDK libraries with rpath
    • Creates symlink libpcap.so.0.8 → libpcap.so.1

subprojects/libpcap.wrap:

Packet capture wrapper

subprojects/packagefiles/libpcap/grout-tcpdump.sh:

  • New bash script wrapping system tcpdump to use locally-built libpcap with DPDK pdump support
  • Computes paths relative to build directory, validates libpcap.so existence
  • Sets LD_LIBRARY_PATH to prioritize local libpcap.so.0.8 and DPDK libraries
  • Exports DPDK_CFG with secondary process configuration and driver path for secondary process PMD discovery
  • Intended as temporary workaround pending upstream libpcap merge (references libpcap PR #1656)

Add a --pdump flag that enables DPDK secondary process attachment for
packet capture. When set, grout starts without --in-memory (shared
hugepages) and calls rte_pdump_init() to register the IPC handler.

Stock system tcpdump can then attach as a secondary process and
capture live traffic using the grout:N device syntax. A wrapper script
(subprojects/packagefiles/libpcap/grout-tcpdump.sh) handles the
LD_LIBRARY_PATH setup while libpcap upstream support is pending
(the-tcpdump-group/libpcap#1656).

The libpcap subproject is built as a shared library with DPDK pdump
support via cmake. It produces libpcap.so with both PCAP_SUPPORT_DPDK
(standalone dpdk:N devices) and PCAP_SUPPORT_DPDK_PDUMP (secondary
grout:N devices) enabled.

The DPDK subproject requires a patch to lib/eal/common/eal_common_thread.c
that removes an overly conservative rte_mp_disable() call from
rte_thread_register(), which blocked secondary process attachment
when non-EAL worker threads are registered.

Signed-off-by: Vincent Jardin <vjardin@free.fr>
@vjardin

vjardin commented Mar 17, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai

coderabbitai Bot commented Mar 17, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

The pull request adds packet dump (pdump) functionality using DPDK's pdump library. Changes include adding a pdump configuration flag to the gr_config structure, introducing a -P/--pdump command-line option, implementing pdump initialization in dpdk_init after rte_eal_init, updating DPDK build configuration to enable pdump and bpf libraries, building a custom libpcap with DPDK pdump support, and adding a tcpdump wrapper script that uses the custom libpcap for packet capture.

📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can generate a title for your PR based on the changes with custom instructions.

Set the reviews.auto_title_instructions setting to generate a title for your PR based on the changes in the PR with custom instructions.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@main/dpdk.c`:
- Around line 190-198: The check for rte_pdump_init() incorrectly negates its
return value (which is -1) and loses the real error in rte_errno; change the
failure branch so that when rte_pdump_init() < 0 you read the actual error code
from rte_errno (e.g. int err = rte_errno), log rte_strerror(err) via LOG(...),
and set ret to -err (to preserve the negative return convention) before jumping
to end; update the block around gr_config.pdump / rte_pdump_init to use
rte_errno for both logging and the returned error value.

In `@meson.build`:
- Around line 168-193: The custom_target libpcap_build runs cmake/make against
libpcap but doesn't declare a build dependency on the DPDK build, causing races
in parallel builds; update the libpcap_build target to add a depends entry
referencing the DPDK build target (for example the dpdk library target from the
dpdk subproject or an existing executable like grout that already depends on
DPDK) so the DPDK artifacts and pkg-config files are guaranteed to exist before
running the cmake command; keep the dependency as the dpdk build target name
already present in your meson project (or grout) so cmake runs only after DPDK
is built.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b3aa95ca-b07d-4663-9c45-d05796c969ad

📥 Commits

Reviewing files that changed from the base of the PR and between 0f7b91c and 2475485.

📒 Files selected for processing (6)
  • main/dpdk.c
  • main/gr_config.h
  • main/main.c
  • meson.build
  • subprojects/libpcap.wrap
  • subprojects/packagefiles/libpcap/grout-tcpdump.sh

Comment thread main/dpdk.c
Comment on lines +190 to +198
if (gr_config.pdump) {
ret = rte_pdump_init();
if (ret < 0) {
ret = -ret;
LOG(ERR, "rte_pdump_init: %s", rte_strerror(ret));
goto end;
}
LOG(NOTICE, "pdump enabled, secondary processes can attach for packet capture");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

DPDK rte_pdump_init return value and rte_errno

💡 Result:

The DPDK function rte_pdump_init returns an int value: 0 on success. It returns -1 on failure, in which case rte_errno is set accordingly to indicate the specific error condition. This follows the standard DPDK API convention for functions returning int, as seen in related APIs like rte_pdump_enable and older documentation explicitly stating "Returns: 0 on success, -1 on error, rte_errno is set accordingly." (e.g., DPDK 17.11 docs). No specific error codes unique to rte_pdump_init are documented; rte_errno provides DPDK-specific or system error details (e.g., E_RTE_SECONDARY if called from secondary process). Official DPDK documentation and manpages confirm the signature int rte_pdump_init(void) and usage in primary processes like testpmd for initializing the packet capture framework.

Citations:


Incorrect error code extraction from rte_pdump_init().

rte_pdump_init() returns -1 on failure with the actual error code stored in rte_errno. The current code negates the return value (yielding 1), which loses the real error information.

Proposed fix
 	if (gr_config.pdump) {
 		ret = rte_pdump_init();
 		if (ret < 0) {
-			ret = -ret;
+			ret = rte_errno;
 			LOG(ERR, "rte_pdump_init: %s", rte_strerror(ret));
 			goto end;
 		}
 		LOG(NOTICE, "pdump enabled, secondary processes can attach for packet capture");
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@main/dpdk.c` around lines 190 - 198, The check for rte_pdump_init()
incorrectly negates its return value (which is -1) and loses the real error in
rte_errno; change the failure branch so that when rte_pdump_init() < 0 you read
the actual error code from rte_errno (e.g. int err = rte_errno), log
rte_strerror(err) via LOG(...), and set ret to -err (to preserve the negative
return convention) before jumping to end; update the block around
gr_config.pdump / rte_pdump_init to use rte_errno for both logging and the
returned error value.

Comment thread meson.build
Comment on lines +168 to +193
libpcap_build = custom_target(
'libpcap',
output: '.libpcap-stamp',
command: [
'sh', '-c',
'mkdir -p "' + libpcap_builddir + '" && ' +
'cd "' + libpcap_builddir + '" && ' +
'export PKG_CONFIG_PATH="' + dpdk_pkgconfig_path + ':' + dpdk_pc_path + ':$PKG_CONFIG_PATH" && ' +
'DPDK_LIBDIR="' + meson.global_build_root() + '/subprojects/dpdk/lib" && ' +
'DPDK_DRVDIR="' + meson.global_build_root() + '/subprojects/dpdk/drivers" && ' +
'cmake "' + libpcap_srcdir + '" ' +
'-DDISABLE_DPDK:BOOL=OFF ' +
'-DHAVE_RTE_ETH_DEV_COUNT_AVAIL:BOOL=ON ' +
'-DHAVE_STRUCT_RTE_ETHER_ADDR:BOOL=ON ' +
'-DDISABLE_DBUS:BOOL=ON ' +
'-DDISABLE_RDMA:BOOL=ON ' +
'-DDISABLE_BLUETOOTH:BOOL=ON ' +
'-DDISABLE_NETMAP:BOOL=ON ' +
'-DBUILD_SHARED_LIBS:BOOL=ON ' +
'"-DCMAKE_SHARED_LINKER_FLAGS=-L$DPDK_LIBDIR -L$DPDK_DRVDIR -Wl,-rpath,$DPDK_LIBDIR:$DPDK_DRVDIR" ' +
'&& make -j pcap && ' +
'ln -sf libpcap.so.1 libpcap.so.0.8 && ' +
'touch "@OUTPUT@"',
],
build_by_default: true,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Missing build dependency on DPDK could cause parallel build failures.

The custom_target for libpcap relies on DPDK libraries and pkg-config files existing at configure/build time, but doesn't declare a dependency on the DPDK build. In a parallel build (ninja -j$(nproc)), cmake may run before DPDK artifacts are available.

Proposed fix
 libpcap_build = custom_target(
   'libpcap',
   output: '.libpcap-stamp',
+  depends: dpdk_dep.type_name() == 'internal' ? subproject('dpdk').get_variable('dpdk_lib') : [],
   command: [

Alternatively, if dpdk_lib isn't exposed, you could depend on the grout executable or another target that already depends on DPDK:

 libpcap_build = custom_target(
   'libpcap',
   output: '.libpcap-stamp',
+  depends: [grout_exe],
   command: [
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@meson.build` around lines 168 - 193, The custom_target libpcap_build runs
cmake/make against libpcap but doesn't declare a build dependency on the DPDK
build, causing races in parallel builds; update the libpcap_build target to add
a depends entry referencing the DPDK build target (for example the dpdk library
target from the dpdk subproject or an existing executable like grout that
already depends on DPDK) so the DPDK artifacts and pkg-config files are
guaranteed to exist before running the cmake command; keep the dependency as the
dpdk build target name already present in your meson project (or grout) so cmake
runs only after DPDK is built.

@vjardin

vjardin commented Mar 20, 2026

Copy link
Copy Markdown
Contributor Author

close, let's have a different approach. I'll open a new serie.

@vjardin vjardin closed this Mar 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant