Installation & bring-up on FreeBSD
First-time install on FreeBSD 14.3: contiguous memory, DPDK 25.11 from source, NIC binding, build, interface naming, then start and confirm the plan. Order matters — a NIC must be handed to DPDK before the BNG can open it, and contiguous memory must be reserved at boot.
Prerequisites
libsodium provides Ed25519 for licensing; protobuf-c and libnghttp2 enable the gNMI / gRPC northbound (without them the tree still builds and gNMI runs in stub mode). openssl and libedit ship in the FreeBSD 14.3 base. Do not run pkg autoremove afterwards — DPDK here is a source install, not a package, and autoremove has previously swept it away.
pkg update
pkg install -y git meson ninja pkgconf python3 py311-elftools src \
libsodium protobuf-c libnghttp2
Contiguous memory
DPDK uses contigmem, not normal pages. For a two-port BNG, 2 GB is ample. Add the reservation and the DPDK kernel drivers to /boot/loader.conf, plus the PCI bus:dev:func of the NICs to bind at boot — those take decimal, not hex.
# /boot/loader.conf hw.contigmem.num_buffers=2 hw.contigmem.buffer_size=1073741824 contigmem_load="YES" nic_uio_load="YES" hw.nic_uio.bdfs="2:4:0,2:5:0"
DPDK 25.11 from source
Source-build so the kernel modules match the running kernel exactly. Point pkg-config at the install and verify the version reads 25.11.0 before building the BNG; keep the export in your shell profile.
cd /usr/src
fetch https://fast.dpdk.org/rel/dpdk-25.11.tar.xz
tar -xf dpdk-25.11.tar.xz && cd dpdk-25.11
meson setup build -Dtests=false
ninja -C build && ninja -C build install
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:/usr/local/libdata/pkgconfig
pkg-config --modversion libdpdk # MUST print 25.11.0
NIC binding
The loader.conf line binds ports at boot; a slot can also be handed over live. Always cross-check bus:dev:func against pciconf — mixing decimal and hex binds the wrong slot.
pciconf -lv | grep -B3 -A1 'Ethernet' devctl detach <kernel-if> devctl set driver pci0:2:5:0 nic_uio pciconf -lv | grep -B1 -A3 nic_uio
Start and confirm the plan
A clean start, then read the planner output. If the daemon exits immediately with a zero-workers or no-ports message, the NICs are not bound to nic_uio. -l is the EAL coremask, -n the memory-channel count.
pkill -9 bng; sleep 1; rm -f /var/run/dpdk/rte/mp_socket daemon -f -p /tmp/bng.pid -o /tmp/d.log ./build/bng -l 0-5 -n 4 -- sleep 12; tail -n 60 /tmp/d.log ./build/bng-cli # interactive ./build/bng-cli --selftest # offline command-tree selftest