The first release since 0.2.7 (2026-05-20). It adds three modules (vpp-offload, neigh-snoop, and guard, which is experimental) and a persistent event log. No directive was removed and a 0.2.7 config parses unchanged, but read Upgrading from 0.2.7 before installing: the upgrade order matters, and one default changed.
Upgrading from 0.2.7
systemctl stop packetframepacketframe detach --all, run with the old 0.2.7 binary. fast-path refuses to start over the pins a previous daemon left.- Install the 0.5.0 package or tarball.
systemctl daemon-reload. The .deb runs no maintainer scripts, so it neither reloads systemd nor stops or restarts the daemon.systemctl start packetframe
- Behaviour change:
bridge-resolvenow defaults to on (auto). While the bridge short-circuit is installed,mss-clamp … via <bridge>no longer matches, because clamp matching keys on the resolved egress device. Scope the clampviathe underlying device, or setbridge-resolve offto keep 0.2.7's behaviour. The daemon logs a warning naming both when it sees this. - Installing the VPP package (vpp-offload only): follow the vpp-unifi README exactly. It ships a boot-time hugepage sysctl file that its skip flag does not remove. Delete the file and confirm it is gone before you reboot;
packetframe feasibilityflags it asvpp.sysctl-hugepages. - Downgrading: run 0.5.0's
packetframe detach --allbefore installing 0.2.7. 0.2.7'sdetachdoes not know guard's tc filters, VPP's MCAM rules, the IPv6 hand-back veth, tc-ingress attachments or the saved coalescing values, and leaves them in place. - Already on a main-branch build running vpp-offload: install,
systemctl daemon-reload, thensystemctl stop packetframe && packetframe detach --keep-vpp && systemctl start packetframe; VPP keeps forwarding throughout. Before that, renamev6-outboundtov6-diverton anyportline and drop anysteer-keep6 tcp 179 …or destination-portsteer-keep6 tcp|udp 53line (now built-in keeps); 0.5.0 refuses a config with either.
Highlights
- VPP offload, in production. vpp-offload steers IPv4 and IPv6, in both directions, into a VPP instance on NIC virtual functions, with the eBPF fast-path as the failover tier. On the reference deployment (four steered ports, full IPv4 and IPv6 tables), softirq is about 74% of CPU with no bypass and 31–62% with the eBPF fast-path alone. Steering IPv4 into VPP took it to 11–19%, and moving IPv6 in alongside it took it to about 1%. Every figure from the fast-path-only one on is an off-peak reading. Runbook · Measurements
- Restarts that stay steered.
packetframe detach --keep-vppleaves VPP forwarding, and the next daemon adopts it from the route ledger the clean stop preserved. Measured on the reference deployment: no unsteered window, and VPP is never restarted. Runbook - neigh-snoop learns neighbours on IX-facing bridges passively and feeds FRR's next-hop gate. In production on the reference deployment. Runbook
- Event log.
packetframe eventsshows steering, verify, restarts and health transitions from a persistent log, with or without the daemon running. Runbook
Changes
vpp-offload (new)
- Supervises a VPP process: startup config, core placement, IRQs moved off VPP's cores. Any VPP whose binary-API CRCs match is accepted at attach. (#105, #121, #238)
- Routes come from fast-path's resolved FIB,
fallback-defaultincluded, with readback verify and a drift scan. (#123, #266) - NIC MCAM steering per port:
port … steer on,direction src|dst|both, trunks withvlans all, bridged VLANs through a BVI.steer-capacityenlarges the NIC's rule table. The steering lever reloads without a restart. (#127, #128, #190, #249, #255, #258) steer-exemptkeeps chosen destinations on the kernel path; the exemption tripwire reports kernel routes VPP lacks, for IPv4 and IPv6. (#189, #192, #281)local-route/local-route6deliver traffic to hosts on attached VLANs. VPP resolves new neighbours itself (glean); glean and ARP-reply counters are exported. (#190, #282, #287)- IPv6:
v6 onloads the IPv6 table into VPP.v6-divert <vlans>|untaggedon aportline diverts TCP and UDP over IPv6 addressed to the router's MAC.steer-keep6keeps services that accept new sessions on the kernel path; DNS (destination port 53) and BGP (TCP 179, both directions) are built-in keeps. (#278, #279, #280) - Router-owned IPv6 that
v6-divertsends to VPP returns to the kernel over a hand-back veth, guarded by a stateless ACL in VPP that admits only replies. (#283) loopback-address6gives VPP a global source for its ICMPv6 errors;drift-accept6acknowledges an IPv6 drift finding. (#285, #288)packetframe detach --keep-vpprestarts the daemon while VPP forwards. Without a usable route ledger the next start reads VPP's FIB instead, on the eBPF tier meanwhile (about 3 minutes at 1.1M routes); theadoption_pathevent says which path ran. (#253, #277)- Per-port health rows in
packetframe status, gauges in the metrics textfile, and remedies that name commands the module accepts. (#114, #129)
neigh-snoop (new)
- Learns third-party ARP/ND pairs on IX-facing bridges from a receive-only socket, installs them as
NUD_STALE, and never overrides a confirmed entry. (#212, #218, #215) - Persists its table per bridge (
persist-dir,seed-max-age) and picks up a recreated bridge by name. (#217) bridge <iface> ix-modestops fast-path's resolver sending proactive probes on that bridge. (#213)frr-gatereconciles FRR's next-hop prefix-lists from what was learned and measures route-server coverage. (#216)
guard (new, experimental)
- A tc-egress frame policer for IX-facing interfaces: per-target ARP/NS rate limit, LLDP drop, foreign-source-MAC drop and a broadcast/multicast catch-all, each class
monitoror enforce. Not validated on the reference vendor kernel; run every class inmonitorfirst. (#204–#207, runbook)
fast-path
integrity-authority birdc [path] | frr upstream <ip> … | nonenames what attests the route mirror is complete. The default is the localbirdc, as in 0.2.7;frrreads FRR 10 throughvtyshon a configurableinterval. Restart-only. (#173, #232, #236)route-source bgp … anyiplistens on a phantom address, so FRR can feed routes over iBGP from a non-loopback address. (#196)bridge-resolve auto|on|off: bridge egress short-circuit, on by default (see Upgrading). (#78)fdb-pin on: FDB-pinned direct-to-port egress through a multi-member bridge. Opt-in, restart-only. (#85)fib-cache on: a destination cache in front of custom-FIB lookups. Default off. (#79)coalesce …: NIC interrupt coalescing at attach, restored bydetach. Restart-only. (#269)local-prefix6: the connected fast path for IPv6, with NDP kept off it. (#72)attach <iface> tc: a tc-ingress datapath (custom-fib only). It measured about 70% more CPU per packet than generic XDP on the reference hardware, so it is not recommended. (#75)- New counters: the softnet
time_squeezeexport, anderr_parse_tcsplit by bounds check. (#184, #138)
probe (packetframe feasibility)
vpp.sysctl-hugepagesdetects a boot-persistent hugepage sysctl, priced at the running kernel's page size. It is a rollout gate with its own verdict bucket. (#201, #225)- Flags per-packet IRQ coalescing. (#84)
CLI and operations
- The event log (
packetframe events) is on by default at<state-dir>/events.log;event-log <path>|offandevent-log-max <size>change it. (#289) - The systemd unit caps the restart loop (
StartLimitBurst=3in 300 s), setsKillMode=processso a stop does not kill a VPP kept for adoption, and addsLogsDirectory=packetframe. (#224, #242) - Restart-required refusals quote the full restart command. (#273)
- Release artifacts include
CHANGELOG.md,conf/example.confand the runbooks. (#294) - Built with Rust 1.98.1; building from source needs 1.98 or later. (#296)
Fixes
- fast-path routes only frames addressed to the router. (#271)
- fast-path re-probes lost nexthops and tracks redirect targets live, and
statusno longer hides traffic that takes the kernel path. (#220) - The anyip reconcile no longer dumps the whole FIB, and failed custom-FIB deletes are repaired. (#223, #154)
- A vpp-offload failure degrades that module and leaves fast-path running. (#237)
status,reconfigureanddetachrecognise a running daemon when run from a newly installed binary;detachno longer proceeds under a live daemon. (#164)log-leveltakes effect and reloads with SIGHUP; 0.2.7 parsed it and ignored it. (#169)
Known limitations
- A fast-path restart still bounces the link on drivers where XDP attach and detach reset the port (a few lost pings over about two minutes on the reference hardware), because fast-path does not adopt pins across a restart.
- IPv6 is steered by frame, not address: only TCP/UDP arriving on a VLAN listed in
v6-divertis offloaded, so list every upstream VLAN. The allowlist does not scope what is diverted, and diverted IPv6 bypasses the kernel's forward-path netfilter. (runbook) - VPP's own glean output (the ARP requests and neighbour solicitations it sends) bypasses guard, which polices kernel tc egress.
- Native XDP is refused on rvu-nicpf interfaces on kernels without upstream commit 04f647c8e456 (Linux 6.8), including the reference vendor kernel, where native attach panics. Use
genericorauto. - The .deb runs no maintainer scripts: run
systemctl daemon-reloadafter every install. - MCAM steering rules survived one vendor provisioning push on a lab box on one firmware release. Survival across firmware releases is untested. Nothing re-asserts stripped rules automatically; the 30 s readback reports them as
steering DEGRADED.
Install and verify
When upgrading, run steps 1 and 2 above first.
ARCH=$(dpkg --print-architecture) # amd64 or arm64
curl -LO "https://github.com/unredacted/packetframe/releases/download/v0.5.0/packetframe_0.5.0_${ARCH}.deb"
curl -LO https://github.com/unredacted/packetframe/releases/download/v0.5.0/SHA256SUMS
sha256sum -c SHA256SUMS --ignore-missing
dpkg -i "packetframe_0.5.0_${ARCH}.deb" && systemctl daemon-reloadTarballs for {aarch64,x86_64}-unknown-linux-{gnu,musl} are attached below.
Full changelog: v0.2.7...v0.5.0