Skip to content
Open
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
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
* @qdeslandes
*.nix @jordalgo
52 changes: 52 additions & 0 deletions .github/workflows/nix.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Nix Build

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
build_nix:
name: "Build: Nix (${{ matrix.runner }})"
strategy:
matrix:
runner: [ubuntu-latest, ubuntu-24.04-arm]
runs-on: ${{ matrix.runner }}

steps:
- name: Checkout bpfilter
uses: actions/checkout@v4
- uses: nixbuild/nix-quick-install-action@v34
with:
nix_conf: |
keep-env-derivations = true
keep-outputs = true
- name: Restore and save Nix store
uses: nix-community/cache-nix-action@v7
with:
# restore and save a cache using this key
primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }}
# if there's no cache hit, restore a cache by this prefix
restore-prefixes-first-match: nix-${{ runner.os }}-
# collect garbage until the Nix store size (in bytes) is at most this number
# before trying to save a new cache
# 1G = 1073741824
gc-max-store-size-linux: 1G
# do purge caches
purge: true
# purge all versions of the cache
purge-prefixes: nix-${{ runner.os }}-
# created more than this number of seconds ago
purge-created: 0
# or, last accessed more than this number of seconds ago
# relative to the start of the `Post Restore and save Nix store` phase
purge-last-accessed: 0
# except any version with the key that is the same as the `primary-key`
purge-primary-key: never
- name: Build & check
run: |
nix fmt -- --check .
nix build
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Usual build folder
/build/

# Nix
result*

# IDE configuration folder
.zed
.vscode
Expand All @@ -14,4 +17,3 @@ __pycache__

# Local Claude instructions
CLAUDE.local.md

7 changes: 5 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ project(bpfilter

list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/tools/cmake")

include(GitVersion)
get_version_from_git()
option(NO_GIT_VERSION "Disable git-based version detection" 0)
if (NOT NO_GIT_VERSION)
include(GitVersion)
get_version_from_git()
endif ()
message(NOTICE "bpfilter version ${PROJECT_VERSION}${PROJECT_VERSION_SUFFIX}")

include(GNUInstallDirs)
Expand Down
94 changes: 94 additions & 0 deletions derivation.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
{
stdenv,
lib,
cmake,
ninja,
pkg-config,
clang,
bison,
flex,
libbpf,
libnl,
elfutils,
openssl,
testers,
zlib,
zstd,
pcre2,
xxd,
version ? "0.0.1",
}:

let
fs = lib.fileset;

# zerocallusedregs is invalid with -target bpf
hardeningDisable = [ "zerocallusedregs" ];

in
{
inherit hardeningDisable;

package = stdenv.mkDerivation (finalAttrs: {
pname = "bpfilter";
inherit version;

src = fs.toSource {
root = ./.;
fileset = fs.unions [
./src
./CMakeLists.txt
./tools/cmake
];
};

inherit hardeningDisable;

nativeBuildInputs = [
cmake
ninja
pkg-config
clang # for building codegen BPF progs
bison
flex
];

buildInputs = [
libbpf
libnl
elfutils
openssl
zlib
zstd
pcre2
xxd
];

cmakeFlags = [
"-DNO_GIT_VERSION=1"
"-DDEFAULT_PROJECT_VERSION=${finalAttrs.version}"
"-DNO_DOCS=1"
"-DNO_TESTS=1"
"-DNO_CHECKS=1"
"-DNO_BENCHMARKS=1"
];

# We do not run the unit tests because the nix build sandbox doesn't
# have access to /sys/kernel/btf/vmlinux.
doCheck = false;

meta.pkgConfigModules = [ "bpfilter" ];

passthru = {
tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage;
};

preFixup = ''
substituteInPlace $out/lib/systemd/system/bpfilter.service \
--replace-fail /usr/sbin/bpfilter $out/bin/bpfilter

# workaround for https://github.com/NixOS/nixpkgs/issues/144170
substituteInPlace $out/lib/pkgconfig/bpfilter.pc --replace-fail ''${prefix}/ ""
'';
});
}
7 changes: 6 additions & 1 deletion 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+.
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 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 @@ -83,6 +83,11 @@ If you want to perform a full build of ``bpfilter`` (including all test tests, c
sed \
xxd

# Nix (this is experimental)
nix develop
# or
nix build

You can then use CMake to generate the build system:

.. code-block:: shell
Expand Down
27 changes: 27 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

110 changes: 110 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
{
description = "bpfilter - eBPF-based packet filtering framework";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
};

outputs =
{ self, nixpkgs }:
let
systems = [
"x86_64-linux"
"aarch64-linux"
];
forAllSystems = nixpkgs.lib.genAttrs systems;
nixpkgsFor = forAllSystems (system: import nixpkgs { inherit system; });

version = "0.0.1";

in
{
packages = forAllSystems (
system:
let
pkgs = nixpkgsFor.${system};
bpfilterLib = pkgs.callPackage ./derivation.nix { inherit version; };
in
{
default = bpfilterLib.package;
bpfilter = bpfilterLib.package;
}
);

formatter = forAllSystems (system: nixpkgsFor.${system}.nixfmt-rfc-style);

devShells = forAllSystems (
system:
let
pkgs = nixpkgsFor.${system};
bpfilterLib = pkgs.callPackage ./derivation.nix { inherit version; };
in
{
default = pkgs.mkShell {
name = "bpfilter-dev";

inherit (bpfilterLib) hardeningDisable;

inputsFrom = [ bpfilterLib.package ];

packages = with pkgs; [
gnumake
clang-tools # clang-tidy, clang-format
include-what-you-use
gcc
autoconf
automake
libtool

# Git (for GitVersion.cmake and benchmarks)
git
libgit2

# BPF tools
bpftools

# Networking tools (for e2e tests)
iproute2
iputils

# Testing
cmocka
gbenchmark

# Utilities
gawk
jq
gnused
procps
lcov

# Documentation
# TODO: this (`make doc`) is still broken but should be fixed when linuxdoc is added to nixpkgs
doxygen
python3
python3Packages.sphinx
# python3Packages.breathe
# python3Packages.furo
# python3Packages.linuxdoc
# python3Packages.gitpython
# python3Packages.scapy
# python3Packages.python-dateutil
# python3Packages.setuptools
# glibcLocales
];

shellHook = ''
# Set locale for sphinx-build
export LOCALE_ARCHIVE="${pkgs.glibcLocales}/lib/locale/locale-archive"
export LC_ALL=C.UTF-8

# Add libbpf headers to include path for clang-tidy
export CPATH="${pkgs.libbpf}/include''${CPATH:+:$CPATH}"

echo "bpfilter development environment"
'';
};
}
);
};
}