Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
bpfilter is an eBPF-based packet filtering framework that translates filtering rules into optimized BPF programs. Licensed under GPLv2, maintained by Meta.

**Components:**
- `libbpfilter` - Core library with public API for filtering logic
- `bpfilter` - Daemon that generates and manages BPF programs
- `bfcli` - CLI for defining filtering rules
- `libbpfilter` - Core library containing all filtering logic, BPF code generation, and program lifecycle management
- `bfcli` - CLI for defining and managing filtering rules via `libbpfilter`

**Requirements:** Linux 6.6+, libbpf 1.2+

Expand All @@ -17,13 +16,12 @@ bpfilter is an eBPF-based packet filtering framework that translates filtering r
src/
├── libbpfilter/ # Core library (shared object)
│ ├── include/bpfilter/ # Public API headers
│ └── *.c # Implementation (chain, matcher, rule, hook, set, bpf, btf...)
├── bpfilter/ # Daemon
│ ├── cgen/ # BPF code generation engine
│ │ ├── matcher/ # Packet matcher codegen (ip4, ip6, tcp, udp, icmp, meta, set)
│ │ └── prog/ # Program linking (link, map)
│ ├── xlate.c # Rule translation
│ └── bpf/ # eBPF stub programs
│ └── *.c # Implementation (chain, matcher, rule, hook, set, bpf, btf, ctx...)
Comment on lines 22 to +24
Copy link

Choose a reason for hiding this comment

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

🟡 CLAUDE.md directory tree has two issues: xlate.c on line 22 no longer exists (it was part of the deleted src/bpfilter/ daemon code) and should be removed, and line 23 (bpf/) uses └── but should use ├── since *.c follows at the same level. Both are minor documentation inaccuracies introduced by this PR.

Extended reasoning...

Bug Description

The CLAUDE.md directory tree listing for src/libbpfilter/ contains two documentation errors introduced by this PR's changes.

Issue 1: Stale xlate.c reference (line 22)

Line 22 of CLAUDE.md lists xlate.c under src/libbpfilter/:

│   ├── xlate.c           # Rule translation

However, xlate.c was part of src/bpfilter/ (the daemon directory that this PR removes). The rule translation functionality was rewritten into src/libbpfilter/cli.c as part of this PR. Since xlate.c does not exist under src/libbpfilter/, this line should be removed entirely.

Issue 2: Duplicate last-child tree markers (lines 23-24)

Lines 23-24 both use the └── (last-child) marker at the same indentation level:

│   └── bpf/              # eBPF stub programs
│   └── *.c               # Implementation...

In standard ASCII tree notation, └── means "last child at this level." Since bpf/ is not the last entry (it is followed by *.c), line 23 should use ├── instead. The correct tree after removing xlate.c would be:

│   ├── bpf/              # eBPF stub programs
│   └── *.c               # Implementation...

Step-by-step proof

  1. The PR diff shows CLAUDE.md was modified to update the directory tree after removing the daemon.
  2. Reading CLAUDE.md line 22: │ ├── xlate.c # Rule translation — this file does not exist under src/libbpfilter/. It was in src/bpfilter/ which was deleted.
  3. Reading line 23: │ └── bpf/ — uses └── but *.c follows on line 24 at the same level, so ├── is correct.
  4. Reading line 24: │ └── *.c — correctly uses └── as the actual last child.

Impact

These are documentation-only issues with no functional impact. The directory tree in CLAUDE.md will be slightly misleading to developers trying to understand the project structure, but it does not affect builds, tests, or runtime behavior.

Fix

Remove line 22 (xlate.c) and change line 23 from └── to ├── for the bpf/ entry.

├── bfcli/ # CLI (parser.y, lexer.l, opts, print, chain, ruleset)
└── external/ # External deps (mpack)

Expand All @@ -35,7 +33,7 @@ tests/
└── harness/ # Test utilities (test.h, mock.h, fake.h)

doc/
├── usage/ # User guides (bfcli, daemon)
├── usage/ # User guides (bfcli)
└── developers/ # Dev docs (build, style, tests, modules/)
```

Expand Down Expand Up @@ -114,15 +112,15 @@ Use `#pragma once` for header guards. Prefer forward declarations over includes

### Commit messages
Format: `component: subcomponent: short description`
- Components: `lib`, `daemon`, `cli`, `tests`, `build`, `tools`, `doc`
- Components: `lib`, `cli`, `tests`, `build`, `tools`, `doc`
- Lowercase, imperative mood, no period, under 72 chars
- Description explains "why", code shows "what"
- No reference to Claude or Claude as co-author

Examples:
```
lib: matcher: add meta.flow_hash matcher
daemon: cgen: link: add support for dual-stack Netfilter chains
lib: cgen: link: add support for dual-stack Netfilter chains
tests: e2e: fix end-to-end tests leaving files behind
```

Expand Down
3 changes: 1 addition & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,13 @@ target_link_options(bf_global_flags_cxx

add_subdirectory(src/libbpfilter)
add_subdirectory(src/bfcli)
add_subdirectory(src/bpfilter)

if (NOT ${NO_DOCS})
add_subdirectory(doc)
endif ()

if (NOT ${NO_TESTS})
set(CMAKE_CTEST_ARGUMENTS "--output-on-failure")
set(CMAKE_CTEST_ARGUMENTS "--output-on-failure;--label-exclude;fuzzing")
enable_testing()
add_subdirectory(tests)
endif ()
Expand Down
5 changes: 1 addition & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
- **Low overhead**: minimal resource consumption with maximized efficiency
- **Developer-friendly**: clean architecture with clear separation of components

**bpfilter** combines three components: a CLI that allows users to define filtering rules in human-readable text, a daemon that converts these rules into efficient BPF programs, and a library that facilitates seamless communication between applications and the filtering subsystem.
**bpfilter** combines two components: a core library that translates filtering rules into efficient BPF programs and manages their lifecycle, and a CLI that allows users to define and manage filtering rules in human-readable text.

Want to know more about **bpfilter**? Check the [user's guide](https://bpfilter.io/usage/index.html), the [developer documentation](https://bpfilter.io/developers/build.html), our [contributing guide](https://bpfilter.io/developers/contributing.html), or watch our latest [public talk](https://www.youtube.com/watch?v=fzaPEm4PXn0)!

Expand Down Expand Up @@ -61,9 +61,6 @@ make -C $BUILD_DIR
### Usage

```shell
# Start the daemon
sudo $BUILD_DIR/output/sbin/bpfilter

# Count the number of ping coming to interface #2
sudo $BUILD_DIR/output/sbin/bfcli ruleset set --from-str "chain my_chain BF_HOOK_XDP{ifindex=2} ACCEPT rule ip4.proto icmp counter ACCEPT"
```
Expand Down
2 changes: 0 additions & 2 deletions doc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ list(FILTER bf_srcs EXCLUDE REGEX "${CMAKE_SOURCE_DIR}/src/external/.*")
set(doc_srcs
${CMAKE_CURRENT_SOURCE_DIR}/index.rst
${CMAKE_CURRENT_SOURCE_DIR}/usage/bfcli.rst
${CMAKE_CURRENT_SOURCE_DIR}/usage/daemon.rst
${CMAKE_CURRENT_SOURCE_DIR}/usage/index.rst
${CMAKE_CURRENT_SOURCE_DIR}/developers/build.rst
${CMAKE_CURRENT_SOURCE_DIR}/developers/contributing.rst
Expand All @@ -89,7 +88,6 @@ set(doc_srcs
${CMAKE_CURRENT_SOURCE_DIR}/developers/style.rst
${CMAKE_CURRENT_SOURCE_DIR}/developers/tests.rst
${CMAKE_CURRENT_SOURCE_DIR}/developers/modules/index.rst
${CMAKE_CURRENT_SOURCE_DIR}/developers/modules/bpfilter/bpfilter.rst
${CMAKE_CURRENT_SOURCE_DIR}/developers/modules/libbpfilter/libbpfilter.rst
${CMAKE_CURRENT_SOURCE_DIR}/external/benchmarks/index.rst
${CMAKE_CURRENT_SOURCE_DIR}/external/coverage/index.rst
Expand Down
7 changes: 4 additions & 3 deletions doc/developers/build.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Build from sources
==================

This document describes the process to build ``bpfilter`` from sources. While ``bpfilter`` can be built on most systems, a recent (6.6+) Linux kernel is required with ``libbpf`` 1.2+ to run the ``bpfilter`` daemon. ``bpfilter`` officially supports Fedora 40+, CentOS Stream 9+, and Ubuntu 24.04+. There is also a nix flake which supports all the make targets.
This document describes the process to build ``bpfilter`` from sources. While ``bpfilter`` can be built on most systems, a recent (6.6+) Linux kernel is required with ``libbpf`` 1.2+ to run ``bpfilter``. ``bpfilter`` officially supports Fedora 40+, CentOS Stream 9+, and Ubuntu 24.04+. There is also a nix flake which supports all the make targets except for ``doc``.

If you want to perform a full build of ``bpfilter`` (including all test tests, code check, benchmarks, and documentation), the following dependencies are required:

Expand Down Expand Up @@ -101,9 +101,10 @@ The usual CMake options are allowed (e.g. ``CMAKE_BUILD_TYPE``, ``CMAKE_INSTALL_

A full configuration (without any part disabled) will provide the following targets:

- ``core``, ``bpfilter``, ``libbpfilter``, ``bfcli``: the ``bpfilter`` binaries.
- ``core``, ``libbpfilter``, ``bfcli``: the ``bpfilter`` binaries.
- ``test_bin``: build the binaries needed to run the tests (below).
- ``test``: run all the tests. This command will run ``unit``, ``check``, ``e2e``, ``fuzzing``, and ``integration`` targets. See :doc:`tests` for more information.
- ``test``: run all the tests. This command will run ``unit``, ``check``, ``e2e``, and ``integration`` targets. See :doc:`tests` for more information.
- ``fuzzing``: fuzz the CLI parser for 60 seconds.
- ``check``: run ``clang-tidy`` and ``clang-format`` against the source files.
- ``benchmarks``: run the benchmarks on ``bpfilter``.

Expand Down
4 changes: 0 additions & 4 deletions doc/developers/modules/bpfilter/bpfilter.rst

This file was deleted.

10 changes: 4 additions & 6 deletions doc/developers/modules/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ Modules
:caption: Modules

libbpfilter/libbpfilter
bpfilter/bpfilter

``bpfilter`` is composed of multiple modules depending on each other. Splitting the project in different modules allows for the source code to be efficiently reused, be it for ``bfcli``, ``bpfilter``'s daemon, or ``libbpfilter``:
``bpfilter`` is composed of multiple modules depending on each other. Splitting the project in different modules allows for the source code to be efficiently reused:

- ``core``: core definitions used by the daemon, ``bfcli``, and ``libbpfilter``.
- ``bpfilter``: daemon logic, including deserializing data sent by the client into ``bpfilter``'s internal format, and the BPF bytecode generation logic.
- ``bfcli``: generic client to communicate with the daemon.
- ``libbpfilter``: static and shared library to communicate with the daemon.
- ``core``: core definitions used by ``bfcli`` and ``libbpfilter``.
- ``libbpfilter``: core library containing all filtering logic, BPF code generation, and program lifecycle management.
- ``bfcli``: CLI tool for defining and managing filtering rules via ``libbpfilter``.
- ``external``: non-``bpfilter`` code, imported into the project to provide consistent external definitions.
7 changes: 0 additions & 7 deletions doc/developers/modules/libbpfilter/libbpfilter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@ libbpfilter
.. doxygenfile:: bpfilter/bpfilter.h


Namespaces
----------

.. doxygenfile:: ns.h
:sections: briefdescription detaileddescription typedef struct innerclass enum var define func


Pack
----

Expand Down
2 changes: 1 addition & 1 deletion doc/developers/style.rst
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ Commit messages should be formatted as ``component: subcomponent: short descript
- No period at the end
- Keep under 72 characters

Components are ``lib``, ``daemon``, ``cli``, ``tests``, ``build``, ``tools``, ``doc``. Subcomponents reflect the directory structure (e.g., ``tests: e2e:``, ``daemon: cgen: link:``). If you're unsure, check the commit history for a hint.
Components are ``lib``, ``cli``, ``tests``, ``build``, ``tools``, ``doc``. Subcomponents reflect the directory structure (e.g., ``tests: e2e:``, ``lib: cgen: link:``). If you're unsure, check the commit history for a hint.

Examples:

Expand Down
3 changes: 1 addition & 2 deletions doc/developers/tests.rst
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ End-to-end tests are designed to validate bpfilter's behaviour as seen by the us

**Example**

``e2e_test_util.sh`` provides functions to create a sandboxed environment and start the ``bpfilter`` daemon. Here is an example of a simple end-to-end test that creates a sandbox and starts ``bpfilter``:
``e2e_test_util.sh`` provides functions to create a sandboxed environment. Here is an example of a simple end-to-end test that creates a sandbox:

.. code-block:: shell

Expand All @@ -96,7 +96,6 @@ End-to-end tests are designed to validate bpfilter's behaviour as seen by the us
. "$(dirname "$0")"/../e2e_test_util.sh

make_sandbox
start_bpfilter

# Ping the sandbox's IPv4 address from the sandboxed namespace
${FROM_NS} ping -c 1 -W 0.1 ${NS_IP_ADDR}
Expand Down
2 changes: 1 addition & 1 deletion doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,6 @@
- **Low overhead**: minimal resource consumption with maximized efficiency
- **Developer-friendly**: clean architecture with clear separation of components

**bpfilter** combines three components: a CLI that allows users to define filtering rules in human-readable text, a daemon that converts these rules into efficient BPF programs, and a library that facilitates seamless communication between applications and the filtering subsystem.
**bpfilter** combines two components: ``bfcli``, a CLI that allows users to define filtering rules in human-readable text, and ``libbpfilter``, a library that converts these rules into efficient BPF programs and manages their lifecycle.

Want to know more about **bpfilter**? Check the :doc:`user's guide <usage/index>`, the :doc:`developer documentation <developers/build>`, or watch our talk at `Scale <https://www.youtube.com/watch?v=fzaPEm4PXn0>`_!
27 changes: 20 additions & 7 deletions doc/usage/bfcli.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
``bfcli``
=========

``bfcli`` is a command line tool to communicate with the bpfilter daemon.
``bfcli`` is the command line tool for defining and managing bpfilter filtering rules. It calls ``libbpfilter`` directly to generate, load, and manage BPF programs.

Environment variables
---------------------

``bfcli`` reads the following environment variables to configure the library before processing commands. These variables are ignored when ``--dry-run`` is used.

- ``BF_BPFFS_PATH``: path to the BPF filesystem directory. Defaults to ``/sys/fs/bpf``. bpfilter pins BPF objects under a ``bpfilter`` subdirectory at this path.
- ``BF_WITH_BPF_TOKEN``: if set (any value), associate a BPF token to every ``bpf()`` system call. Required when running in user namespaces. The token is created from the bpffs at ``BF_BPFFS_PATH``. Only supported for kernel v6.9+.
- ``BF_VERBOSE``: comma-separated list of verbose flags. Supported values:

Comment on lines +7 to +14
Copy link

Choose a reason for hiding this comment

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

🔴 The documentation at lines 7-14 claims bfcli reads BF_BPFFS_PATH, BF_WITH_BPF_TOKEN, and BF_VERBOSE environment variables, but no getenv() calls exist anywhere in bfcli or libbpfilter. Users following this documentation would set environment variables that are silently ignored, with bfcli using default values instead. Either implement getenv() support or remove the environment variables section from the docs.

Extended reasoning...

Bug Description

The newly added "Environment variables" section in doc/usage/bfcli.rst (lines 7-14) documents three environment variables that bfcli supposedly reads:

  • BF_BPFFS_PATH: path to the BPF filesystem directory
  • BF_WITH_BPF_TOKEN: whether to associate a BPF token
  • BF_VERBOSE: comma-separated list of verbose flags

However, there are zero getenv() calls anywhere in src/bfcli/ or src/libbpfilter/. The only getenv calls in the entire project are in tools/perfrec and tools/benchmarks (for SUDO_UID/SUDO_GID), which are unrelated.

Code Path Analysis

bfcli parses its configuration exclusively via command-line flags using argp. In src/bfcli/opts.c, the flags --bpffs-path (key b), --with-bpf-token (key t), and --verbose (key v) are defined and parsed in _bfc_opts_parser(). The parsed values are stored in struct bfc_opts fields (bpffs_path, with_bpf_token, verbose). In src/bfcli/main.c, these opts are passed directly to bf_ctx_setup(opts.with_bpf_token, opts.bpffs_path, opts.verbose). At no point does any code call getenv() to read environment variables.

Why Tests Don’t Catch This

The e2e test helper (tests/e2e/e2e_test_util.sh) both exports the environment variable AND passes the CLI flag:

export BF_BPFFS_PATH=${WORKDIR}/bpf
BFCLI="bfcli --bpffs-path ${BF_BPFFS_PATH}"

Since ${BFCLI} always includes --bpffs-path, the CLI flag provides the correct value. The export is a no-op from bfcli’s perspective. This masks the fact that environment variable support is missing.

Step-by-Step Proof

  1. A user reads the documentation and runs: export BF_BPFFS_PATH=/my/custom/bpffs && bfcli ruleset get
  2. bfcli enters main() in src/bfcli/main.c, calls bfc_opts_parse() which initializes opts.bpffs_path = "/sys/fs/bpf" (the default from src/bfcli/opts.h line 107).
  3. Since no --bpffs-path flag was passed on the command line, opts.bpffs_path remains at the default /sys/fs/bpf.
  4. bf_ctx_setup() is called with bpffs_path = "/sys/fs/bpf", completely ignoring the user’s exported BF_BPFFS_PATH=/my/custom/bpffs.
  5. The user’s intended configuration is silently discarded.

Impact

Users following the official documentation will believe they can configure bfcli via environment variables. When they do, their settings are silently ignored, leading to misconfiguration. This is particularly dangerous for BF_BPFFS_PATH since using the wrong bpffs path could cause BPF programs to be pinned in the wrong location, and for BF_WITH_BPF_TOKEN which is required in user namespace scenarios.

Fix

Either:

  1. Add getenv() calls in bfcli (e.g., in bfc_opts_parse or main) to read these environment variables as fallback defaults when the corresponding CLI flags are not provided, or
  2. Remove the "Environment variables" section from doc/usage/bfcli.rst entirely until the feature is actually implemented.

- ``debug``: enable debug logs.
- ``bpf``: insert log messages into BPF programs to log failed kernel function calls. View with ``bpftool prog tracelog`` or ``cat /sys/kernel/debug/tracing/trace_pipe``.
- ``bytecode``: dump a program's bytecode before loading it.

Commands
--------
Expand Down Expand Up @@ -32,7 +45,7 @@ Chains with valid hook options defined are attached to their hook. Chains withou
``ruleset get``
~~~~~~~~~~~~~~~

Print the ruleset: request all the chains and rules from the daemon with counters values.
Print the ruleset: request all the chains and rules with counters values.

**Example**

Expand All @@ -49,7 +62,7 @@ Print the ruleset: request all the chains and rules from the daemon with counter
``ruleset flush``
~~~~~~~~~~~~~~~~~

Remove all the chains and rules defined by the daemon. Once this command completes, the daemon doesn't contain any filtering rules, as if it was freshly started.
Remove all the chains and rules. Once this command completes, bpfilter doesn't contain any filtering rules.

**Examples**

Expand All @@ -69,14 +82,14 @@ Remove all the chains and rules defined by the daemon. Once this command complet
``chain set``
~~~~~~~~~~~~~

Generate and load a chain into the kernel. If the chain definition contains hook options, the daemon will attach it to its hook. Any existing chain with the same name (attached or not) will be discarded and replaced with the new one.
Generate and load a chain into the kernel. If the chain definition contains hook options, bpfilter will attach it to its hook. Any existing chain with the same name (attached or not) will be discarded and replaced with the new one.

If you want to update an existing chain without downtime, use ``bfcli chain update`` instead.

**Options**
- ``--from-str CHAIN``: read the chain to set from the command line arguments.
- ``--from-file FILEPATH``: read the chain from a file.
- ``--name NAME``: if ``--from-str`` or ``--from-file`` provide multiple chains, ``NAME`` specify which one to send to the daemon.
- ``--name NAME``: if ``--from-str`` or ``--from-file`` provide multiple chains, ``NAME`` specifies which one to use.
- ``--dry-run``: parse and validate the chain, but do not apply it.

**Examples**
Expand Down Expand Up @@ -158,7 +171,7 @@ If a chain with the same name already exist, it won't be replaced. See ``bfcli c
**Options**
- ``--from-str CHAIN``: read the chain to set from the command line arguments.
- ``--from-file FILEPATH``: read the chain from a file.
- ``--name NAME``: if ``--from-str`` or ``--from-file`` provide multiple chains, ``NAME`` specify which one to send to the daemon.
- ``--name NAME``: if ``--from-str`` or ``--from-file`` provide multiple chains, ``NAME`` specifies which one to use.
- ``--dry-run``: parse and validate the chain, but do not apply it.

**Examples**
Expand Down Expand Up @@ -213,7 +226,7 @@ If you want to modify the hook options, use ``bfcli chain set`` instead.
**Options**
- ``--from-str CHAIN``: read the chain to set from the command line arguments.
- ``--from-file FILEPATH``: read the chain from a file.
- ``--name NAME``: if ``--from-str`` or ``--from-file`` provide multiple chains, ``NAME`` specify which one to send to the daemon.
- ``--name NAME``: if ``--from-str`` or ``--from-file`` provide multiple chains, ``NAME`` specifies which one to use.
- ``--dry-run``: parse and validate the chain, but do not apply it.

**Examples**
Expand Down
27 changes: 0 additions & 27 deletions doc/usage/daemon.rst

This file was deleted.

21 changes: 4 additions & 17 deletions doc/usage/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,12 @@ Usage
:maxdepth: 2
:caption: Usage

daemon
bfcli


``bpfilter`` is composed of two main parts that work together: the client used by the users to define the filtering rules and send them to the **daemon** that performs the heavy lifting of generating the BPF bytecode.
``bpfilter`` is composed of two main parts: ``libbpfilter``, the core library that generates and manages BPF programs, and ``bfcli``, the CLI used to define filtering rules. ``bfcli`` calls ``libbpfilter`` directly to translate rules into BPF programs and load them into the kernel.

Before anything, you will have to run the daemon on your system, see :doc:`daemon` for more details.

Then, use ``bfcli`` to create, update, or read chains.
See :doc:`bfcli` for the full command reference and filter syntax.

Install
-------
Expand All @@ -31,7 +28,7 @@ If you use a different distribution, you can still build and use **bpfilter** if
Example usage
Copy link

Choose a reason for hiding this comment

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

🟡 Documentation bug: doc/usage/index.rst line 31 incorrectly lists the local build path as $BUILD_DIR/output/bin/bfcli when it should be $BUILD_DIR/output/sbin/bfcli. The bfcli binary is installed to CMAKE_INSTALL_SBINDIR (i.e., sbin/) per src/bfcli/CMakeLists.txt, and README.md already correctly uses sbin. This is a minor doc inconsistency introduced in this PR.

Extended reasoning...

What the bug is

In doc/usage/index.rst, the PR changed the local-build path instruction from the old $BUILD_DIR/output/sbin/bpfilter (which was correct for the daemon) to $BUILD_DIR/output/bin/bfcli. The directory component was changed from sbin to bin, but bfcli is still installed to sbin/, not bin/.

The specific code path

The install destination for bfcli is defined in src/bfcli/CMakeLists.txt at line 81, which uses DESTINATION ${CMAKE_INSTALL_SBINDIR}. The CMake GNUInstallDirs module sets CMAKE_INSTALL_SBINDIR to sbin by default. This means the actual install path is $BUILD_DIR/output/sbin/bfcli, not $BUILD_DIR/output/bin/bfcli.

Step-by-step proof

  1. src/bfcli/CMakeLists.txt installs bfcli with DESTINATION ${CMAKE_INSTALL_SBINDIR}, which resolves to sbin/.
  2. README.md (line 65, also modified in this PR) correctly references $BUILD_DIR/output/sbin/bfcli.
  3. doc/usage/index.rst (line 31, new in this PR) incorrectly references $BUILD_DIR/output/bin/bfcli.
  4. The two documentation files are inconsistent, and the CMakeLists.txt confirms sbin is correct.

Why existing code does not prevent this

This is a documentation-only issue. There is no automated check that verifies documentation paths match actual CMake install destinations.

Impact

Users who follow the usage guide to run a locally-built bfcli will get a "command not found" error because they will look in bin/ instead of sbin/. The impact is low since README.md has the correct path, and users can easily discover the right location.

Fix

Change $BUILD_DIR/output/bin/bfcli to $BUILD_DIR/output/sbin/bfcli on line 31 of doc/usage/index.rst.

-------------

From here on, we assume **bpfilter** has been installed on your system. If you build it locally, you will need to substitute the ``bpfilter`` command with ``$BUILD_DIR/output/sbin/bpfilter``, same for ``bfcli``. The example below is meant to familiarize you with **bpfilter**, more in-depth information can be found throughout the documentation.
From here on, we assume **bpfilter** has been installed on your system. If you build it locally, you will need to substitute the ``bfcli`` command with ``$BUILD_DIR/output/bin/bfcli``. The example below is meant to familiarize you with **bpfilter**, more in-depth information can be found throughout the documentation.

This example will block ``ping`` requests sent going out of the local host to a remote server.

Expand All @@ -53,19 +50,9 @@ Let's check if we can ping ``facebook.com`` before we do anything:
rtt min/avg/max/mdev = 23.596/25.493/28.622/1.880 ms


**Start the daemon**

The daemon is responsible for receiving the user-defined filtering rules, and translating them into BPF programs. We will start it in ``--transient`` mode, so all the filtering programs defined will be discarded when we stop it, preventing any mistake on our side!

.. code-block:: bash

$ sudo bpfilter --transient
info : waiting for requests...


**Create a new filtering rule**

Now that the daemon is up and running, we will use ``bfcli`` to send a filtering chain. A chain is a set of rules to filter packets on:
Use ``bfcli`` to create a filtering chain. A chain is a set of rules to filter packets on:

.. code-block:: bash

Expand Down
Loading
Loading