Skip to content
Thomas Mangin edited this page Jul 13, 2026 · 4 revisions

Pre-Alpha. This page describes behavior that may change.

Ze optionally integrates with VPP (the FD.io Vector Packet Processor) to forward packets at DPDK speed. When vpp.enabled is true, ze takes ownership of the whole VPP lifecycle: startup, DPDK NIC binding, GoVPP connection, crash recovery, and clean teardown.

How it fits together

BGP reactor -> protocol RIB -> sysRIB
                                 |
                          +------+------+
                          |             |
                     fib-kernel     fib-vpp
                     (netlink)      (GoVPP)
                          |             |
                          v             v
                    Linux FIB       VPP FIB
                     (local)        (transit)

Ze keeps two FIB backends side by side. fib-kernel programs the Linux route table for local services (SSH, web UI, BGP TCP sessions). fib-vpp pushes the same routes into VPP's FIB for DPDK-speed transit forwarding.

Configuration

Minimal example:

vpp {
    enabled true;
    dpdk {
        interface 0000:03:00.0 { name xe0; }
        interface 0000:03:00.1 { name xe1; }
    }
}

Full reference:

Path Type Default Description
vpp.enabled boolean false Master switch.
vpp.external boolean false Connect to an existing VPP (skip startup.conf, NIC bind, exec).
vpp.api-socket string /run/vpp/api.sock GoVPP Unix socket path.
vpp.cpu.main-core uint8 auto CPU core for VPP main thread.
vpp.cpu.workers uint8 auto Number of worker threads.
vpp.cpu.poll-sleep Nms (0-100ms) unset Fixed sleep between VPP main-loop polls (ms only, e.g. 10ms). Omit for lowest latency (workers busy-poll at 100% CPU); set it on shared or dev hosts to trade latency for idle CPU.
vpp.memory.main-heap size 1G VPP main heap. 1536M for full DFZ.
vpp.memory.hugepage-size 2M or 1G 2M Hugepage size.
vpp.memory.buffers uint32 128000 Buffers per NUMA node.
vpp.dpdk.interface[pci].name string required Short interface name (e.g. xe0).
vpp.stats.poll-interval uint16 30 Seconds between stats reads.
vpp.lcp.enabled boolean true Linux Control Plane plugin (linux_cp / linux_nl).
vpp.lcp.sync boolean true Mirror VPP link/MTU/IP changes into the Linux TAPs.
vpp.lcp.auto-subint boolean true Auto-create Linux TAPs for dot1q and QinQ sub-interfaces.
vpp.lcp.netns string dataplane Network namespace where LCP TAPs appear. For BGP to bind on an LCP-shadowed interface, set this to a root-reachable namespace (host / root); ze doctor warns (doctor-vpp-lcp-netns) otherwise.
vpp.plugins.wireguard boolean false Load wireguard_plugin.so so the VPP interface backend can program WireGuard tunnels. ze doctor warns (doctor-vpp-wireguard) if a wireguard interface is configured under vpp with this off.

FIB programming

fib {
    vpp {
        enabled true;
        table-id 0;
    }
}

External mode

When something else owns VPP (systemd, container sidecar):

vpp {
    enabled true;
    external true;
    api-socket /run/vpp/api.sock;
}

Ze connects to the API socket, runs telemetry, and programs the FIB, but does not start VPP or bind NICs.

What ze manages

When VPP is ze-owned (not external):

  1. Parses vpp { } YANG config.
  2. Renders startup.conf.
  3. Loads vfio, vfio_pci, vfio_iommu_type1 kernel modules.
  4. Unbinds NICs from current driver, binds to vfio-pci.
  5. Execs the VPP binary.
  6. Connects GoVPP to the API socket.
  7. Starts the stats poller.
  8. On crash: backoff (1s to 30s), restart, replay RIB.
  9. On shutdown: SIGTERM VPP, PCI rescan, restore original NIC drivers.

System prerequisites

Requirement How to provide it
Hugepages (~6 GB production, 2 GB lab) /sys/kernel/mm/hugepages/ or /etc/sysctl.d/
IOMMU enabled BIOS: VT-d / AMD-Vi. Kernel: intel_iommu=on iommu=pt
CPU isolation for workers isolcpus=<cores>
DPDK-compatible NIC Intel i210/i350, X520/X540, X710/XL710, E810, VirtIO

Observability

  • Prometheus metrics: per-interface rx/tx packets/bytes/drops/errors, per-node clocks, system vector rates.
  • fib-vpp show: JSON dump of routes fib-vpp believes it has installed.
  • vppctl: Direct VPP introspection via /run/vpp/cli.sock.

MPLS label programming

The fib-vpp plugin programs MPLS labels from BGP labeled unicast routes. When a best-path route carries MPLS labels, fib-vpp installs the corresponding label push operation in VPP's FIB. Labels flow from the BGP wire through the RIB to VPP without manual configuration.

Firewall VPP backend

The firewall plugin supports a VPP backend (backend vpp) that uses VPP's ACL classify pipeline for packet filtering and NAT44-ED for SNAT/DNAT/masquerade. See the firewall page for details.

VPP interface backend

When an interface selects backend vpp, ze manages it directly through the GoVPP binary API instead of the kernel. Alongside plain interfaces (create, delete, address, admin state, MTU, bridge ports, monitor), the backend supports:

  • Tunnels: GRE, GRETAP, IPIP, and VXLAN, under interface { tunnel <name> { encapsulation { <kind> { ... } } } } with a local { ip ... } source and remote { ip ... } destination. VXLAN adds a mandatory vni and an optional port (default 4789). VPP terminates tunnels on an address, so a local-interface source is not accepted on this backend, and the GRE key field is not carried (the VPP GRE API has none).
  • Port mirroring (SPAN): a mirror block copies a port's traffic to another. ingress <port> mirrors received traffic, egress <port> mirrors transmitted traffic; setting both gives RX+TX.
  • WireGuard: interface { wireguard <name> { private-key ...; listen-port ...; peer <name> { public-key ...; endpoint { ip; port } allowed-ips ...; } } }. Requires vpp.plugins.wireguard true. The VPP WireGuard API carries no per-peer preshared key or fwmark, so those netlink-only options are not programmed here.
  • LCP pairs: the Linux Control Plane shadows a VPP interface into a Linux TAP in the vpp.lcp.netns namespace, so kernel networking (for example the BGP TCP listener) can still bind() and connect(). Pairs are created through lcp_itf_pair_add_del; the host name is capped at the Linux 15-byte limit.
interface {
    backend vpp;
    tunnel gre0 {
        encapsulation { gre { local { ip 10.0.0.1; } remote { ip 10.0.0.2; } } }
    }
    tunnel vx0 {
        encapsulation { vxlan { local { ip 10.0.0.1; } remote { ip 10.0.0.2; } vni 100; } }
    }
}

GRE tunnels and WireGuard interfaces are proven against real VPP 25.10; LCP pairs are unit- and wiring-tested and need a VPP build shipping the linux-cp / linux-nl plugins for a full real-VPP proof.

Traffic control VPP backend

The traffic-control subsystem has a VPP backend, selected with traffic { control { backend vpp; } } (the default is Linux tc). It classifies and polices in VPP's classify + policer pipeline:

  • Policing by DSCP: a class with match { type dscp; value N; } steers DSCP-matched packets (IPv4 TOS or IPv6 traffic-class, values 0-63) to that class's policer.
  • Protocol filtering: a match { type protocol; value N; } steers by IP protocol / next-header (0-255) through a VPP classify table into the policer.
  • Multi-class steering: several filtered classes on one interface share chained classify tables and each get their own policer; an unfiltered class binds to the egress policer. Every class in a multi-class config must carry a steering filter.

The backend accepts the htb and tbf qdiscs and the dscp and protocol filter types. The mark filter and other qdiscs (prio, hfsc, sfq, and so on) have no faithful VPP equivalent and are rejected at commit. The classify offsets were validated against real VPP 25.10. See Traffic Control for the config surface shared with the tc backend.

Static routes in VPP

When the VPP data plane is active, the static-route plugin programs its routes into VPP's FIB (via ip_route_add_del) instead of the kernel, mapping forward, blackhole (drop), and reject next-hops and honouring the per-route table ID. With no VPP connector present it falls back to the kernel netlink backend. Interface-only next-hops are not yet programmed on the VPP backend. This is separate from fib-vpp, which programs BGP best routes from the system RIB.

Host tuning and doctor checks

Two knobs tune VPP's host footprint:

  • Poll-sleep (vpp.cpu.poll-sleep): a fixed sleep between main-loop polls, in whole milliseconds. Omit it for lowest latency (workers busy-poll at 100% CPU); set a value like 10ms on a shared or development host to trade latency for idle CPU.
  • Hugepages: on the gokrazy appliance ze owns the kernel cmdline, so image.hugepages (and optionally image.memory-bytes) in appliance.json bakes the reservation into the boot cmdline. On a general-purpose host you reserve hugepages yourself.

ze doctor guards the VPP prerequisites, and only fires when vpp.enabled is true:

Check Fires when
doctor-vpp-hugepages No hugepages reserved (error), or the reservation is smaller than requested or than the estimated need (warning).
doctor-vpp-lcp-netns BGP is configured but vpp.lcp.netns is not root-reachable, so the BGP listener cannot bind on an LCP-shadowed interface.
doctor-vpp-wireguard A wireguard interface uses backend vpp but vpp.plugins.wireguard is off.

Crash recovery and reconnect

If VPP exits unexpectedly, the component emits ("vpp", "disconnected"), backs off (1s doubling to a 30s cap), restarts VPP, and re-emits ("vpp", "reconnected"). On each (re)connect it tears down and recreates the stats poller and GoVPP connection so no stale connection state survives. The dependent plugins then reset: fib-vpp reinitializes its backend and broadcasts a full-table replay request, so the entire system RIB is reprogrammed into the fresh VPP, and the interface backend re-runs its monitor. This clears forwarding state left behind by the crashed process.

What is not yet wired

The MPLS label programming (vpp-3) and the native VPP interface backend (vpp-4: interfaces, tunnels, mirror, WireGuard, LCP pairs) described above are now in tree. The remaining phase:

Phase What it adds
vpp-5 L2 cross-connect, bridge domains, SRv6, sFlow.

See also

Adapted from main/docs/guide/vpp.md.

Home

About

First Steps

Configuration

Operation

Interfaces

Plugins

Plugin Development

Chaos Testing

Blueprints

Development

Reference

Clone this wiki locally