Feature
Ze Features
Ze is an open-source configuration and protocol engine written in Go. The network operating system built on it runs on any Linux or as a gokrazy appliance.
Status values: Supported means implemented and covered in the normal release evidence for this pre-release; Experimental means implemented but still needs deployment evidence or hardening before production claims; Partial means a named subset is not implemented or not proven; Stub-backed means external dependency evidence currently comes from a stub harness; Rejected means unsupported by design; Future means planned but not shipped.
| Feature | Status | Description |
|---|---|---|
| BGP Protocol | Supported | 23 address families, 14 capabilities, 15 path attributes. The whole BGP subsystem is compile-out-able with the ze_bgp build tag: make ze and ze-appliance include it (default-on in ZE_FEATURES), while ze-stripped and bare ze_core builds drop internal/component/bgp entirely -- engine, wire codec, RIB, and every BGP plugin -- plus flowspec-firewall, which translates BGP-delivered flowspec routes and is meaningless without it. Both composition roots are gated (the generated all_ze_bgp.go and the CLI root), and a bgp {} config block is rejected as an unknown field rather than silently ignored. A BGP-less daemon still runs OSPF, IS-IS, static routes, the FIB, MRT recording, and flow export: the route-action vocabulary, the BGP message-type codes, and the best-path-change event contract those consumers share live in always-on internal/core/bgp/* leaves, and the three places always-on code used to call into the engine (ze config dump/diff/validate resolution, the graceful-restart marker, the RIB dump provider) are inversion-of-control seams the engine fills from its own init. ze-chaos and ze-perf drive an in-process reactor and force ze_bgp on. Within a ze_bgp build the BMP monitoring plugin (RFC 7854/8671/9069) is independently compile-out-able with the ze_bmp build tag: it is a dependent gate -- BMP imports the engine, so all_ze_bmp.go is generated //go:build ze_bgp && ze_bmp and a ze_bmp-without-ze_bgp build links neither BMP nor the engine -- letting a BGP daemon ship without the BMP receiver/sender. . cmd/ze/dispatch_bgp.go |
| Configuration | ∿ | YANG-modeled config with prefix limits, update groups, session resilience, duplicate list-key rejection, side-effect-free in-process plugin verifiers for static/API/CLI validation, and transactional commits using active/candidate/rollback pointers. Live external plugin OnConfigVerify callbacks run only in daemon reload/commit transactions. |
| Deactivate / Activate | Supported | Junos-style inactive: prefix on any node (leaf, container, list entry, leaf-list value); kept in file, skipped at apply. CLI: ze config deactivate/activate <file> <path>. TUI: deactivate <path> / activate <path>. Engine-level, no schema annotation required. |
| Environment Variables | Supported | Ze-native env surface: ze.user, ze.pid.file, ze.pprof, ze.bgp.openwait, ze.bgp.announce.delay, ze.cli.format; ExaBGP-compat env keys retired 2026-04 |
| Outbound source-address | Supported | Optional source-address local-IP binding for outbound service connections: BMP collector, RPKI/RTR cache, flow-export (UDP), IRR whois, and the managed hub TLS client; LDP binds its transport-address as the session source (RFC 5036). Unset = OS-selected source (unchanged). Shared network.RealDialer applies the bind for TCP/TLS; flow-export binds the UDP socket. See Outbound Source Address. |
| CLI Default Output Format | Supported | Configurable default output format via environment { cli { format { default text; } } }. Supported values: text (default), table, json, yaml, ndjson. Session override via set cli format <value> in operational mode. Explicit pipe operators (\| json, \| table, etc.) always win over the configured default. |
| Interfaces | Experimental | Linux interface management via netlink: ethernet, dummy, veth, bridge, loopback, VLAN (with 802.1p ingress/egress QoS maps translating PCP to internal priority and back, and named class-of-service profiles via the cos plugin with interface-level inheritance and per-unit override/opt-out; dynamic per-subscriber CoS via RADIUS Filter-Id "cos:\<name>" or vendor-specific attributes (Cisco-AVPair, Juniper ERX, Nokia, Huawei) applied on session-up with mid-session CoA changes and session-down revert; MikroTik Mikrotik-Rate-Limit VSA for shaper rate extraction ), 8 tunnel kinds (GRE, GRETAP, IP6GRE, IP6GRETAP, IPIP, SIT, IP6TNL, IPIP6), and WireGuard (declarative peers with $9$-encoded keys); DHCP (config-driven, routes, DNS, NTP discovery), NTP client (clock sync, RTC, time persistence, max-step safety cap), monitoring, migration, mirroring, per-interface offload and steering (GRO, GSO, SG, TSO, LRO, hw-tc-offload via kernel ethtool ioctl; RPS, RFS via sysfs; boolean three-state: true/false/absent), per-family reverse path filtering (rpf-check strict|loose|disable in ipv4/ipv6 containers, backed by rp_filter sysctl on Linux; IPv6 enforcement requires VPP), per-interface rate tracking (1s sampler with show interface rate, monitor interface rate, 12 ze_interface_* Prometheus gauges, web rate columns). Local privileged integration covers first-apply non-adoption, reload deletion scoped to previously managed links, and rollback of created kernel links after partial apply failure; target-runner evidence is still required before production deployment claims. The NTP client is compile-out-able with ze_ntp (the show system NTP block reads it through the nil-safe registry seam) and the class-of-service profiles with ze_cos; the dynamic per-subscriber CoS handler additionally requires ze_l2tp (a BNG feature: no sessions, no dynamic CoS). |
| IPv6 Router Advertisements | Experimental | Ze sends IPv6 Router Advertisements on a LAN interface unit (RFC 4861). This is the job radvd does on other systems. Hosts build addresses by stateless address autoconfiguration (SLAAC), learn a default router, and learn DNS resolvers (RFC 8106 RDNSS, up to 8 servers). The router-advertisement container sits in the per-unit ipv6 container. It carries the M and O flags, the per-prefix L and A flags, four timers, a prefix list, and the resolver block. The container is Linux only and netlink only. A backend vpp tree rejects it at config verify. Config verify applies the cross-leaf rules a YANG range cannot express. minimum-interval is at most 0.75 x maximum-interval, and preferred-lifetime is at most valid-lifetime. A prefix with host bits is rejected rather than masked, and so is the link-local prefix. Two zero values are legal input. router-lifetime 0 advertises prefixes and resolvers while Ze is not a default router. rdnss lifetime 0 tells hosts to stop using the resolvers. The iface-ra plugin owns the socket and the timers. Every advertisement leaves with Hop Limit 255. The sender joins for Router Solicitations and sends to. Each unsolicited interval is random between the two configured bounds, and a solicited answer is rate limited. A sender that stops sends up to three advertisements with a Router Lifetime of 0. Counters are ze_iface_ra_sent_total{interface} and ze_iface_ra_solicited_total{interface}. ze doctor reports doctor-iface-ra-forwarding when an advertising interface has IPv6 forwarding off. . ff02::2ff02::1 |
| Plugins | ∿ | RIB, route server (with reactor-native RS fast path, dynamic peers, RS-client, community filtering), graceful restart, RPKI (ASPA policy enforcement), healthcheck, community filters, prefix-list filters, AS-path filters, AS-path length filters, community-match filters, per-address-family filters (remove an AFI/SAFI from an UPDATE on import or export -- e.g. a FlowSpec route reflector that never advertises ipv4/flow back to edge peers via export remove ipv4/flow -- or tear down the session on a received family; applies to forwarded and originated/injected routes), route attribute modifiers (set/increment/decrement for local-preference/med/aigp, community add/remove for standard/large/extended), remove-private-AS policy action, AIGP (RFC 7311), BMP (RFC 7854), interface monitoring, cross-protocol redistribute (egress; routes injected by a redistribute source replay to a BGP peer that establishes after the injection, via a re-emit-on-peer-up request), FlowSpec-to-firewall bridge. BMP Loc-RIB and some redistribution claims remain explicitly scoped by readiness review. |
| BFD Liveness Detection | ∿ | RFC 5880 Bidirectional Forwarding Detection plugin: pinned single-hop (UDP 3784) and multi-hop (UDP 4784) sessions, profile-driven timer bundles, GTSM enforcement (IP_TTL=255 outbound / IP_RECVTTL ingress gate), multi-hop min-TTL floor, RFC 5880 §6.8.7 TX jitter (0-25%, clamped to [10%, 25%) when detect-multiplier=1), SO_BINDTODEVICE for single-hop interface and multi-VRF binding, BGP peer opt-in with RFC 9384 Cease subcode 10 teardown, show bfd sessions/session/profile commands, ze_bfd_* Prometheus metrics, RFC 5880 §6.7 Keyed SHA1/MD5 (meticulous variants included) authentication with file-backed sequence-number persistence, and RFC 5880 §6.4 Echo mode config/wire advertisement (transport half tracked as spec-bfd-6b-echo-transport). Compile-out-able with the ze_bfd build tag (default-on in ZE_FEATURES): a stripped build drops the engine, session, transport, auth, and command surface and rejects a bfd {} block, while the nil-able client seam (bfd/api, with the bfd/packet State/Diag types) stays always-on so BGP, OSPF, and static route monitors run without BFD by their existing warn-and-degrade path. |
| Kernel Tunable Management | Experimental | Sysctl plugin centralizes kernel parameter management with three-layer precedence (config > transient > default). Plugins declare required defaults (e.g., fib-kernel enables forwarding), users override via config or CLI. Original values restored on clean stop. Named profiles group co-dependent tunables (dsr, router, hardened, multihomed, proxy) applied per interface unit. User-defined profiles supported. CLI: show sysctl, ze sysctl list, ze sysctl describe, set sysctl, ze sysctl list-profiles, ze sysctl describe-profile. <!-- source: internal/core/sysctl/profiles.go -- ProfileDef, MustRegisterProfile, builtinProfiles… |
| Connection Tracking Management | Experimental | Declarative conntrack configuration under system { conntrack {} }. Helper module loading (ftp, sip, h323, pptp, tftp, sane, irc, amanda, netbios-ns, snmp, nfs, sqlnet) via modprobe on Linux (load-only, never unload). User-friendly config for table sizing (table-size, hash-size, expect-max), per-protocol timeouts (TCP, UDP, ICMP, ICMPv6, GRE, SCTP, DCCP), TCP behavior flags (be-liberal, loose, max-retrans, ignore-invalid-rst), and global flags (accounting, timestamp, checksum, log-invalid). All sysctl values routed through the sysctl plugin for three-layer precedence. Dual-setting prevention rejects keys in sysctl {} that conntrack manages. On gokrazy (modules built-in), module loading is skipped gracefully. CLI: show system conntrack. Telemetry: configured-max gauge alongside existing per-CPU counters. |
| Installation | Experimental | ze install local copies the binary to a standard FHS prefix (/usr/local, /usr, /opt/ze) and scaffolds the config directory if no database.zefs exists. ze install systemd manages the systemd service: requires an existing database.zefs, creates the ze user/group, writes, grants the needed network capabilities, enables the unit, and can start it with --start. ze uninstall systemd stops, disables, and removes only the service unit. ze install remote provides PXE-based bare-metal provisioning: generates ze config from CLI flags, forks ze - to start DHCP+PXE (dhcpserver plugin with options 43/60/66/67/77/93, BIOS/UEFI bootfile selection, iPXE chainloading via boot-script-url for automatic kernel cmdline), TFTP (RFC 1350 read-only tftpserver plugin with RFC 2347 option negotiation for UEFI PXE), and HTTP image server (imageserver plugin with Range support, dynamic boot.ipxe generation with ze.server/ze.image/ze.port). --kernel and --initrd flags auto-stage installer artifacts; stock iPXE binaries bundled in are copied to the TFTP directory if not present. ze appliance iso builds bootable amd64 or arm64 UEFI installer media around an existing appliance image, verifies the image checksum before ISO creation, and boots an initrd path that decompresses and writes the gzip-compressed embedded image while skipping PXE-style ZeFS download. ze uninstall local removes the binary (optionally config with --purge). Bootstrap mode: when ze starts with zefs but no config and no template, it discovers all interfaces, enables DHCP client on every ethernet NIC, and starts SSH for operator access. Non-ethernet interfaces are skipped. SSH credentials come from zefs (pre-provisioned by the installer). The installer initrd is a single statically-linked Go binary (cmd/ze-installer, packed into a pure-Go cpio with zero external binaries) running as PID 1 that either downloads the gokrazy disk image via HTTP or mounts appliance ISO media read-only, writes the selected image to a safe target disk, injects the zefs database only in HTTP mode, reboots in HTTP mode, and powers off in ISO mode so removable media can be removed before the next boot. Appliance and gokrazy images compile the in-image ze binary with the ze_core build tag (the base personality). Positive build tags (ze_distro, ze_appliance, ze_setup) add feature sets on top. Finer per-feature compile-out tags (ze_<feature>, e.g. ze_lg for the looking glass, ze_ssh for the ssh server) include or exclude individual optional services: make ze/ze-appliance enable the default-on set (ZE_FEATURES in the Makefile), while ze-stripped omits them for a smaller, hardened binary; an omitted service is not linked and its config block is rejected as unknown. Alternate binaries (ze-test, ze-chaos, ze-perf, ze-analyze) each have their own tag and exclude core. Build the initrd with ze appliance initrd. The netboot pair behind ze install remote (tftpserver + imageserver) is compile-out-able with the shared ze_pxe build tag, and the DHCP server with ze_dhcpserver: default-on in ZE_FEATURES, dropped from ze-stripped / bare ze_core builds. . /etc/systemd/system/ze.servicetools/ipxe-binaries/ |
| Modular Deployment | ∿ | Config-driven plugin loading: BGP, interfaces, and FIB load only when their config section is present. Add or remove subsystems at runtime via config reload (SIGHUP). Required config-root autoload failures fail closed, reload diffs restart same-name plugins when their definition changes, and changed external plugin replacements are pre-started before the old handler is removed. |
| Static Routes | Supported | Config-driven static route plugin with named routing tables (policy-based routing), interface-only next-hops (PPPoE/GRE tunnels), mixed ECMP (gateway + interface-only in same group), ECMP (multiple active next-hops), per-next-hop weighted load balancing, BFD-tracked failover (next-hop removed from ECMP group on session DOWN, re-added on UP), blackhole/reject, IPv4/IPv6, config reload reconciliation, and redistribute integration (redistribute { import static }). Named tables resolved via routing-table registry; non-default table routes are PBR-only (not redistributed into BGP). Programs kernel via netlink multipath or VPP via GoVPP. |
| Connected Routes | Supported | Redistribute directly connected interface prefixes into BGP via redistribute { import connected }. Subscribes to interface address events; emits RouteChangeBatch on address add/remove. Reference-counted: multiple addresses on the same prefix emit one announcement, withdrawn only when the last address is removed. IPv4 and IPv6. No kernel programming (kernel already has connected routes). |
| Kernel Routes | Experimental | Redistribute externally-installed kernel routes into BGP via redistribute { import kernel }. Consumes parsed route events from a shared netlink route watcher, filtering Ze-owned routes (rtproto 250-252), RTPROT_KERNEL (2), and RTPROT_REDIRECT (1). Emits RouteChangeBatch for DHCP (16), PPP/manual (BOOT=3), admin static (STATIC=4) routes. Tracks announced prefixes; withdraws all on shutdown. IPv4 and IPv6. Shares a single netlink subscription with fib-kernel (route re-assertion). . internal/core/routewatch/ |
| Policy Routing | Experimental | Policy-based routing via nftables packet marking and kernel ip rules. Steers traffic to alternate routing tables or next-hops based on L3/L4 match criteria (address, port, protocol, TCP flags, set references). Actions: accept (bypass), drop, table N (fwmark + ip rule), next-hop (auto-managed table from 2000-2999), tcp-mss clamping. Interface wildcard binding (e.g., l2tp*). Config reload reconciles nftables tables, ip rules, and auto-managed routes. Compile-out-able with the ze_policyroute build tag: default-on in ZE_FEATURES, dropped from ze-stripped / bare ze_core builds, with its config block rejected as unknown. |
| RPF Lookup | Supported | Reverse Path Forwarding query: longest-prefix-match against Loc-RIB for any CIDR family (IPv4/IPv6 unicast/multicast). Exposes show bgp rib rpf <family> <source-addr> command returning matched prefix, next-hop, admin distance, and metric as JSON. Generic LPM on the sharded Loc-RIB (queries all shards, picks most specific). |
| Route Installation | Experimental | FIB pipeline: protocol RIB best-path tracking, system RIB selection by admin distance, recursive next-hop resolution (max depth 8, IGP metric accumulation, cascade on NH change), ECMP grouping (equal-cost paths collected into nexthop groups, max 128 members), rich route programming (route type blackhole/unreachable/prohibit, metric, VRF table ID, MPLS labels, SRv6 SID), kernel backend via netlink multipath with route type/metric/table/MPLS-lwtunnel/SRv6-seg6 support, VPP backend via GoVPP with multi-path/route-type/metric/table support, per-producer netlink protocol ownership, crash recovery via stale-mark-sweep, external change monitoring. CLI: show nexthop-table, show ecmp-groups. Local privileged integration covers FIB restart sweep and flush-on-stop preserving static and policyroute-owned routes; target-runner evidence is still required before production deployment claims. |
| IS-IS | Experimental | Native IS-IS link-state IGP (ISO/IEC 10589, RFC 1195/5305/5301/5303/5308) running directly over Layer 2: L1+L2 levels, broadcast + point-to-point circuits with DIS election and pseudo-nodes, adjacency FSM, link-state database with flooding (CSNP/PSNP sync), SPF, and FIB install via the shared Loc-RIB. Authentication (RFC 5304 HMAC-MD5, RFC 5310 generic crypto / HMAC-SHA, and cleartext) is configured as named key-chains with $9$-encoded secrets: per-interface chains authenticate Hellos (IIH), per-level chains (area key L1 / domain key L2) authenticate LSPs and CSNP/PSNP; the Authentication TLV is emitted first, LSP digests zero the Authentication Value + Checksum + Remaining Lifetime before signing (Fletcher checksum computed after), purges are authenticated, key rotation is hitless via send/accept lifetimes, and every digest compare is constant-time. Auth-failure rejections increment ze_isis_auth_failures_total{level,interface}. Redistribution meshes IS-IS with BGP in both directions through the protocol-agnostic redistribute framework: a single source isis exports SPF routes (redistribute { destination bgp { import isis } }), and an isis consumer imports connected/static/BGP prefixes into IS-IS LSPs as Extended IP Reachability (TLV 135, redistribute { destination isis { import connected/static/bgp } }); enabled and passive interface prefixes are also advertised. TLV 135 carries no external bit (RFC 5305 sec 4); the up/down bit is set only on a down-level leak (RFC 2966). Redistribution counters are ze_isis_redist_injected_total{source,afi}, ze_isis_redist_withdrawn_total{source,afi}, ze_isis_redist_inject_failures_total{source}, and ze_isis_lsp_reoriginations_total{level}. Dual-stack IPv6 (RFC 5308) runs over the same instance under single-topology: per-interface address-family ipv6-unicast advertises NLPID 0x8E (TLV 129), carries the link-local address in the Hello (TLV 232) and non-link-local addresses in the LSP, originates IPv6 prefixes as IPv6 Reachability (TLV 236, link-local prefixes excluded per RFC 5308 sec 2), runs IPv6 route extraction over the shared SPF tree (a TLV 236 metric above MAX_V6_PATH_METRIC 0xFE000000 is ignored), and installs IPv6 routes via the same Loc-RIB path (show isis route ipv6); IPv6 redistribution works both ways under the single isis source with an afi=ipv6 counter label. Non-congruent IPv4/IPv6 topologies are out of scope (RFC 5120 Multi-Topology not implemented). Live adjacency, flooding, SPF, dual-stack, and FRR interop run as QEMU integration / interop tests. The IS-IS plugin is compile-out-able with the ze_isis build tag: make ze and ze-appliance include it (default-on in ZE_FEATURES), while ze-stripped and bare ze_core builds drop internal/plugins/isis (engine, codec, transport, cli, schema) from both composition roots and reject the isis {} config block as unknown. |
| OSPF | Experimental | Native OSPF engine with one ospf config root for OSPFv2 IPv4 and OSPFv3 IPv6 (address-family ipv6): raw protocol 89 transports, interface and neighbor state machines, LSDB flooding/aging, intra-area SPF, ABR summary origination, inter-area route calculation with area ranges, ASBR external origination and redistribution, OSPFv3 Link-LSAs and Intra-Area-Prefix-LSAs, stub / totally-stubby / NSSA areas (RFC 3101: Type 7/NSSA origination, translator election, Type 7 to Type 5 translation, §2.5 preference), virtual links through a transit area (RFC 2328 §15 / RFC 5340 §4.2: config-validated transit-area/ABR/self rules, transit-area-SPF-computed cost, backbone Router-LSA virtual record + transit-area V-bit, §16.3 transit pass, routed transport), the RFC 5250 opaque-LSA carrier with RFC 3630/5392 Traffic Engineering and the RFC 7770 Router Information LSA (OSPFv2 Opaque type 4, OSPFv3 function code 12, informational capability bits, a consumer-neutral TLV hook), the RFC 7684 Extended Prefix/Link Opaque LSAs (Opaque type 7/8, prefix/link attribute containers with a generic sub-TLV registration hook for Segment Routing), Graceful Restart (RFC 3623 IPv4 + RFC 5187 IPv6, one shared restarter + helper control plane: the IPv4 Grace-LSA rides the opaque carrier as Opaque type 3, the IPv6 Grace-LSA is a native link-scope LS type 0x000B, non-stop forwarding via the RTPROT_ZE FIB retention, an NVS restart fact, and a family-neutral graceful-restart config), Segment Routing over the MPLS data plane (RFC 8665 IPv4 + RFC 8666 IPv6, one shared control plane: SRGB/SRLB label ranges, the multi-range index-to-label arithmetic, the NP/E/M push/swap/PHP truth table, node Prefix-SIDs and SRLB-allocated Adjacency-SIDs, install through the shared mpls-fib bus as the third producer alongside LDP and RSVP-TE; the IPv4 family rides RFC 7770/7684 opaque LSAs and the IPv6 family the RFC 8362 Extended LSAs), LFA / TI-LFA fast reroute (RFC 5286: per-neighbour SPFs and the strict loop-free / node-protecting / downstream inequalities select a pre-computed backup next-hop per primary, with a TI-LFA post-convergence Segment-Routing repair list where no directly-connected LFA exists, the §6.3 multi-area suppression rules, and install as a link-down/backup FIB next-hop through a generic carry-through field on locrib.Path; IPv4 carries SR repair labels, OSPFv3 gets base-LFA next-hop selection through the address-family seam), per-interface OSPFv2 authentication with key chains and replay protection, ECMP, and FIB install through the shared Loc-RIB -> sysrib -> fibkernel path. show ospf exposes process, neighbor, interface, database (including opaque, te-database, and router-information views), route, SPF, and border-router views. The OSPF plugin is compile-out-able with the ze_ospf build tag: make ze and ze-appliance include it (default-on in ZE_FEATURES), while ze-stripped and bare ze_core builds drop internal/plugins/ospf (engine, codec, transport, v3, cli, schema) from both composition roots and reject the ospf {} config block as unknown. |
| MPLS / LDP / RSVP-TE | Experimental | Kernel MPLS forwarding: BGP labeled-unicast routes programmed into the Linux MPLS FIB (label push via netlink lwtunnel), 20-bit label / 16-deep stack validation, net.mpls.platform_labels + per-interface mpls { enable } (net.mpls.conf.<iface>.input) sysctls, ze doctor kernel-module check, ze_fibkernel_mpls_* metrics, show mpls forwarding (reads the kernel AF_MPLS table). LDP (RFC 5036): UDP multicast discovery, TCP session FSM, label information base. RSVP-TE (RFC 3209/2205): control plane over raw IP (protocol 46) -- PATH/RESV signaling for ingress/transit/egress, ERO-based explicit routing, per-interface bandwidth admission control with PathErr on oversubscription, soft-state refresh, PathTear teardown, and make-before-break reroute (SE style). Fast Reroute (RFC 4090): facility backup -- a tunnel fast-reroute request adds FAST_REROUTE/SESSION_ATTRIBUTE protection flags to PATH; a transit Point of Local Repair arms a configured bypass, and on a link failure redirects the LSP onto it with a 2-label stack (the bypass label over the protected label), sends a PathErr Notify (code 25/3) toward the head-end without tearing the LSP down, and the head-end re-optimizes make-before-break; node protection merges at the next-next hop using RRO label recording. Dataplane: RSVP-TE/LDP emit push/swap/pop forwarding entries on the mpls-fib event bus and fib-kernel programs them (IP route + label for push, AF_MPLS routes for swap/pop, including the 2-label facility-backup stack), keeping fib-kernel the single kernel-FIB owner. ze-to-ze FRR is covered by the in-memory fabric interop; cross-vendor interop needs a proprietary RSVP-TE peer (no open-source one exists). LDP and RSVP-TE are independently compile-out-able with the ze_ldp and ze_rsvpte build tags (default-on in ZE_FEATURES; dropped from ze-stripped / bare ze_core, with their ldp {} / rsvp-te {} config blocks rejected as unknown); the MPLS operational surface (show mpls forwarding and the show mpls command schema, internal/component/mpls + internal/plugins/mpls-cmd) is compile-out-able with ze_mpls, while kernel MPLS forwarding itself (fib/kernel) stays always-on. |
| VRRP | Experimental | First-hop redundancy on interface units: RFC 9568 VRRPv3 for IPv4 and IPv6 (the default) with RFC 3768 VRRPv2 available per group via version 2 (IPv4 only). Groups are named by the operator and carry a mandatory vrid, configured under the unit's family container so the group sits next to the addresses it backs: interface { ethernet eth0 { unit 0 { ipv4 { vrrp { group uplink { vrid 10; virtual-address [ 192.0.2.1 ]; } } } } } }. Each group gets its own macvlan device carrying the RFC virtual MAC (for IPv4, for IPv6), so failover moves the L2 address and not just the L3 one, and hosts need no ARP re-resolution. Adverts run over IP protocol 112 to 224.0.0.18 / ff02::12 with GTSM TTL/hop-limit 255 enforced on transmit and receive; a Master transition emits gratuitous ARP (IPv4) and unsolicited Neighbor Advertisements (IPv6). The address owner is detected from the unit's configured addresses and runs at priority 255 per RFC 9568 Section 5.2.4; accept-mode, preempt, preempt-delay-seconds, and priority are per group. accept-mode is a known partial: it is parsed, validated (rejected under version 2), and reported by show vrrp, but is not enforced on the dataplane this pass, so the virtual address answers traffic while the router is Active regardless of the leaf (RFC 9568 Section 6.4.3 filtering is not installed). Cross-leaf rules the YANG grammar cannot express are enforced by an in-process verifier shared with ze doctor (doctor-vrrp-config-invalid, doctor-vrrp-backend-unusable, doctor-vrrp-raw-socket), so a commit and a doctor run can never disagree. Operational surface: show vrrp, show vrrp interface name <iface>, show vrrp statistics, clear vrrp statistics, plus ze_vrrp_state{device,group,vrid,family} and ze_vrrp_transitions_total for Prometheus. Netlink backend only: VRRP needs macvlan devices and raw sockets, so a VPP-backed tree is rejected rather than silently degraded. RFC 3768 authentication is not implemented by design (RFC 9568 Section 9 removed it as providing no real security). Virtual-MAC ownership of the virtual IP is enforced on the dataplane: the macvlan is created in private mode and the virtual IP carries the parent's subnet prefix, with arp_ignore/arp_filter/rp_filter sysctls (applied and later restored by the plugin) making the macvlan the sole ARP responder, so a host resolving the virtual IP gets the virtual MAC (mirrors keepalived's use_vmac). Experimental: the wire format is asserted against golden frames in QEMU and interoperability is proven against keepalived 2.3.1 (election, node-death failover, graceful stop, virtual-MAC ownership), but it has not been hardened in production. The VRRP plugin is compile-out-able with the ze_vrrp build tag: make ze and ze-appliance include it (default-on in ZE_FEATURES), while ze-stripped and bare ze_core builds drop internal/plugins/vrrp (engine, FSM, packet codec, transport, schema) and reject the vrrp {} block under an interface unit as an unknown field; VRRP registers its CLI through the plugin registry, so it needs no dispatch-root companion. . 00:00:5e:00:01:{vrid}00:00:5e:00:02:{vrid} |
| Interactive Launcher | Supported | Running ze with no arguments in a terminal shows a BubbleTea menu of all commands grouped by section, with type-ahead filtering, scrolling, and drill-down into YANG verb sub-commands. Non-TTY invocations fall back to static help text. |
| CLI Commands | Supported | Protocol tools, config management, schema discovery, daemon control, AS topology graph, policy dry-run testing (show policy test) |
| CLI Session Transcript | Supported | Local transcript recording of ze cli and ze config edit sessions to. Preserves command input and output for post-disconnect recovery. Enabled via environment { cli { transcript enabled } } config or ze.cli.transcript env var. Best-effort writes never block CLI operation. . $XDG_DATA_HOME/ze/transcripts/ |
| API Commands | Supported | Peer management, route updates, RIB operations, event subscription |
| Configuration Reload | ∿ | Live reload via SIGHUP with automatic reconciliation. Reload stages edited config as a candidate version and promotes it to active only after runtime reload succeeds. Plugin-server transactions, config-provider roots, subsystem reload, and changed external plugin replacement roll back on failure; remaining reload safety depends on component-specific journals and privileged dataplane evidence. |
| Fleet Management | Experimental | Centralized config distribution over TLS |
| Performance Benchmarking | Supported | Cross-implementation latency benchmarking with ze-perf |
| Web Interface | Supported | HTTPS config editor with YANG-driven UI, CLI bar, and L2TP session management (CQM graph, event timeline, disconnect). The service is default-on but compile-out-able with the ze_web build tag: make ze and ze-appliance include it, while minimal ze_core and ze-stripped builds drop internal/component/web. Self-signed HTTPS certificates are generated by the shared internal/core/selfcert helper and persisted through caller-owned storage. |
| Looking Glass | Supported | Public BGP looking glass with birdwatcher API, AS path graphs, and BMP-monitored route display |
| AI-First Design | Supported | Self-describing CLI-as-API with MCP transport for AI assistants |
| Self-Documenting System | Supported | Runtime introspection of plugins, env vars, RPCs, schemas, commands |
| Host Inventory | Supported | Structured hardware inventory for ISP fleet monitoring: CPU (vendor, topology, hybrid P/E layout, scaling driver, frequencies, throttle counts), physical NICs (driver, PCI IDs, link speed, queue counts, firmware, rings), DMI board identity, memory with ECC counters, hwmon thermal sensors + per-CPU throttle, block devices with NVMe firmware, kernel release/cmdline/microcode/arch flags. Read-only sysfs/procfs, no daemon required. Single show host cpu/nic/... command served by the daemon when reachable, falling back to the same in-process detection when no daemon is running; JSON by default for pipeline consumption. |
| Self-Update | Supported | Platform-aware update backend. Normal Linux uses Ze self-update or passive version checking with SHA-256 verified download, atomic binary replacement via rename, .prev hard-link rollback, deterministic spread scheduling (FNV-1a per device+version), maintenance windows, server-side pause, and persisted update history. Gokrazy appliances report backend: gokrazy-ab through the gokrazy backend and keep the manual update system firmware {check,download,apply,restart,rollback} command family wired; unsupported operations report that system image updates are managed by gokrazy. Minimal (no-tag) builds return an explicit self-update unavailable in minimal build response. ze update serve standalone server remains available on Ze-managed platforms to distribute artifacts. Config: system { update-check { auto-apply true; spread 1800; maintenance-window { start 02:00; end 06:00 }; restart { time 03:00 } } }. |
| Operational Report Bus | Supported | Cross-subsystem ze show warnings and ze show errors commands with source <name> filtering: single place to surface prefix-threshold crossings, stale route data, BGP NOTIFICATIONs sent/received, unexpected session drops, session-stuck/flap/EOR-timeout, route-count-anomaly (>50% drop), FIB sync failures/orphans/programming-lag, firewall stale-table/drift, plugin crashes, interface error counters. State-based warnings + event-based error ring, login banner reads the same source. |
| Local Audit Trail | Supported | Structured local audit log for config commit/discard, daemon reload, and failed authentication across SSH, web, REST, gRPC, MCP, CLI, and system surfaces. show audit filters by action, actor, surface, time range, and count. Disk-backed JSON-lines storage is used when Ze starts from a config file; stdin configs use memory-only storage. |
| Health Registry | Supported | Aggregated component health via show health and /health HTTP endpoint (503 when any component is down). Registered components: l2tp, report-bus, ipsec, pki, bgp (session-stuck/flap/EOR), fib (sync-failure/orphan/lag), firewall (stale-table/drift audit), iface (error counters), plugins (crash/disabled), vpp (API socket probe). Each check is expected to return within 1 second by contract; the registry recovers panics but does not enforce a timeout. |
| Storage SMART Management | Supported | YANG-modeled SMART disk health: auto-enable on detected ATA/NVMe devices, periodic health polling with three-tier temperature alerting (informational warning, rate-of-change warning, critical error) via report bus, scheduled self-tests (short daily, extended weekly with day-of-week constraint), in-progress detection (skips duplicate tests), live status via show storage smart (per-device health, temperature, power-on hours, error count, NVMe percent-used/available-spare, self-test schedule). Pure ioctl (no smartctl binary, gokrazy-safe). Config reload updates intervals live. ze doctor verifies SMART accessibility when enabled. First NOS with YANG-modeled SMART management. |
Tech-Support Bundle (ze support) |
Supported | Offline archive generator with 20 pure-Go modules (no shell-outs, gokrazy-safe): version, doctor, host, platform, config (sanitized), crashes, disk, interfaces (netlink), routes (netlink), neighbors (netlink), env, sysctl, runtime, dmesg, sockets, kernel modules, conntrack, file descriptors, DNS, firewall (nftables via netlink). Module selection (--module/--exclude), time scoping (--since), privacy-by-default (--sensitive to include secrets), reason metadata (--reason), JSON manifest (--json). Archive: ze-support-<hostname>-<timestamp>.tar.gz with one JSON file per module. No NOS vendor produces structured JSON-per-module output. SMART disk health via direct ATA/NVMe ioctls (no smartctl binary). |
System Readiness (ze doctor) |
Supported | Offline pre-start checks: runtime platform detection (gokrazy, systemd, container, plain-linux, darwin) with capability probing (read-only root, /perm, systemd, gokrazy socket, reboot, persistent storage), config syntax, YANG validation, TLS certs (missing/expired/invalid), VPP socket, kernel modules, interface existence/state, SSH host key, listener conflicts, plugin binaries, storage integrity, dangling config references, disk space (<5% free), DNS resolver reachability, clock skew (>5 min vs NTP), VPP version (Linux), VPP hugepage reservation (Linux). Platform-aware checks: gokrazy /perm writability, container read-only root, missing Ze-managed clock synchronization, platform-mismatched persistence/DNS paths, and Linux machine-id presence. --json output with stable diagnostic codes and ze explain <code> for remediation. |
| Granular Debug | Supported | Verb-first debug (set/delete/show/clear, matching VyOS syslog-level config) with per-module flag/direction/scope filtering and named profiles. CLI: ze set debug module <name> (enable), ze delete debug module <name> (disable), ze set debug module <name> flag <flag>, ze set debug module <name> scope direction <dir>, ze set debug module <name> level <level>. Hierarchical prefixes work (ze set debug module bgp covers all bgp.* subsystems). Named profiles: ze set/delete debug profile name <name>, ze show debug profile [name <name>], ze set debug active name <name> (apply). Stored in debug.zefs (separate from config). Each plugin declares its valid flags via the debug YANG registry. Not auto-applied on reboot (safety). show debug (YANG-dispatched) queries live daemon state. |
| Runtime Diagnostics | Supported | Production debugging via CLI and MCP: show l2tp observer (per-session event ring), show l2tp cqm (per-login echo RTT/loss buckets), show l2tp echo (current echo state), show l2tp reliable (reliable transport Ns/Nr/cwnd), show traffic control (TC qdisc/class state), show metrics pool (BGP attribute pool occupancy and dedup rates), enhanced subsystem-list (real plugin state). All auto-exposed as MCP tools for AI-assisted troubleshooting. |
| Core Diagnostics | Supported | 11 built-in diagnostic commands replacing ss, dmesg, lsof, dig, nc, traceroute, mtr, ping, tcpdump, and pprof on gokrazy appliances: show system sockets (TCP/UDP state), show system kernel-log (dmesg), show system goroutines (dump with singleflight dedup), show tcp-check (port probe), show traceroute (ICMP path trace with per-hop RTT, IPv4/IPv6), monitor traceroute (live mtr-style continuous trace with | log | resolve and | log | origin enrichment), monitor ping (continuous ICMP ping with live stats), show capture interface (AF_PACKET live capture with BPF filters, pcap or text output), show system file-descriptors (FD counts and limits), show dns lookup/cache (DNS resolution, cache listing, selective delete, flush, stats reset), show system profile (cpu/heap pprof), show system memory (/proc/self/status OS view). monitor system netlink streams kernel route/link/address change events as JSON (replaces ip monitor). BFD raw capture ring. Root privilege enforcement at startup. See Production Diagnostics Guide. |
| Protocol Event Capture and Replay | Supported | Per-peer, opt-in JSONL capture of a BGP session's inbound protocol events, and a replay harness that feeds a capture back through the same read path. Capture tees the COMPLETE wire message at both read paths (standard and coalesced) before RFC 7606 enforcement and before coalescing, so a malformed UPDATE is recorded exactly as the peer sent it and a coalesced batch is recorded as the separate messages it arrived as. Config operations applied while a capture runs are recorded with their transaction id, with secret-bearing values redacted. Off by default: the tee costs one nil comparison and no allocation per received message. Each file is capped at capture { maximum-size } megabytes exactly (1-1024, default 100); at the cap it rotates once to <file>.1 or stops, per capture { on-limit }, so a peer uses at most twice the cap on disk. Writer backpressure sheds events rather than blocking the read loop, counts them in ze_bgp_capture_dropped_events_total, and writes the gap into the stream. ze doctor reports a capture directory the daemon cannot write. Replay: ze-test replay <file> drives Session.ReadAndProcess over a stub connection and an injected clock and reports the FSM transitions, the prefixes announced and withdrawn, and any NOTIFICATION the session sent. |
| Crash Capture | Supported | Automatic stderr redirect captures panic stack traces from any goroutine. Forwarded to syslog (via ze.log.destination) in real time and persisted to crash files on disk. Crash reports include ring buffer context (last 64 log entries before the panic), version, build date, uptime. Crash dir autodetected (on gokrazy, fallback chain for other platforms). CLI: show crashes, show crashes latest. Env vars: ze.crash.dir, ze.crash.keep. . /perm/ze/crash/ |
| Interoperability Testing | Supported | 100+ Docker-based interop scenarios against FRR, BIRD, and GoBGP; OpenBGPD, FreeRtr, and Rust implementations are exercised as performance-benchmark DUTs, not interop scenarios |
| Testing Health | Supported | Generated report on whether a regression would actually be caught, as opposed to how many tests exist: RFC MUST requirements proven by a positive+negative test pair (as distinct from those annotated away), tests with no reachable failure call, test files no go test target can build, mutation kill rate, negative-test ratio per subsystem, and technique adoption bucketed by package age. Ratios always carry numerator and denominator, an unmeasured metric renders unknown rather than green, and the assert-nothing and tag-orphan counts are ratcheted by make ze-verify so they can only fall. KPI history is committed to, so evolution is visible across releases. . test/health/history.ndjson |
| gNMI | Supported | Industry-standard gRPC Network Management Interface for YANG-modeled config. Capabilities, Get, Set (via segment-based paths preserving IP list keys), Subscribe ONCE and STREAM modes. Bearer token auth with constant-time comparison, optional TLS. YANG config schema under environment { gnmi {} }, show gnmi CLI command, Prometheus counters (ze_gnmi_requests_total, ze_gnmi_subscribe_active, ze_gnmi_errors_total). External config commits (web, CLI, managed) notify STREAM subscribers. Env-var gated (ze.gnmi.enabled), default port 9339. The service is default-on but compile-out-able with the ze_gnmi build tag: make ze and ze-appliance include it, while ze-stripped and bare ze_core builds drop internal/component/gnmi, its schema, and its show gnmi RPC. |
| REST/gRPC API | ∿ | Programmatic API with OpenAPI 3.1 spec, config sessions. Both transports accept multiple named listen endpoints via environment.api-server.rest.server <name> / .grpc.server <name>. REST is plaintext and therefore loopback-only; expose it remotely only behind a TLS terminator. Non-loopback authenticated gRPC listeners require TLS. Bearer token auth, per-user auth, CORS support. Both transports share one engine for identical command output. SSE and gRPC streaming are wired to registered streaming commands such as monitor event, using the same authorization and accounting path as SSH monitor commands. Completion remains future work. Each transport is independently compile-out-able: ze_rest gates internal/component/api/rest and ze_grpc gates internal/component/api/grpc, so a build can ship gRPC-without-REST or vice-versa. make ze/ze-appliance include both; ze-stripped and bare ze_core drop both. With a transport compiled out its server code and its config container (rest{}/grpc{}) are absent, so that block is rejected as unknown; the shared api-server { token } base and the parent internal/component/api engine stay always-on (gNMI uses the parent). |
| Named Service Listeners | Supported | Every service that accepts inbound connections (web, ssh, mcp, looking-glass, telemetry, REST, gRPC, plugin hub) models its listen endpoints as a named YANG list. Each entry binds its own listener on the same subsystem; bind is all-or-nothing with rollback on failure. CollectListeners detects overlapping ip:port pairs at config parse time across every service. |
| MCP Integration | Supported | AI-assisted BGP operations through Model Context Protocol. The transport is stateless Streamable HTTP, revision 2026-07-28: per-request _meta, standard request headers, per-request authentication, and server/discover. Ze is an OAuth 2.1 resource server. Background tasks are server-directed through the extension: the daemon reads each command's ze:task-support annotation and decides whether to return a task handle. The client polls a task, and the server never pushes one. MCP Apps UI resources carry embedded panels, and Ze gates them on the extension. Cacheable results carry ttlMs and a private cacheScope on server/discover, tools/list, resources/list and resources/read. Elicitation runs as a Multi Round-Trip Request. The server RETURNS resultType: "input_required" with an inputRequests map, in form mode. Ze sends this result only when the client declares form-mode support. The client then retries the original call with inputResponses, because the revision forbids a server to send an independent request on any stream. Ze mints no requestState, so Ze holds nothing between the two requests. The service is default-on and compile-out-able with the ze_mcp build tag. make ze and ze-appliance include it, and ze-stripped and bare ze_core builds drop internal/component/mcp and its schema. An omitted MCP exposes no endpoint, and Ze rejects its environment { mcp {} } config block as unknown. . io.modelcontextprotocol/tasksio.modelcontextprotocol/ui |
| Chaos MCP | Supported | AI-queryable chaos test state via MCP: 6 tools (status, problems, peers, scenario, control, execute), Watchdog anomaly detector with structured PROBLEM lines, per-family convergence tracking |
| Chaos MRT Recording | Supported | --mrt-file flag produces standard BGP4MP_MESSAGE_AS4 and BGP4MP_STATE_CHANGE_AS4 MRT records from chaos peer events, readable by bgpdump/bgpkit-parser/ze-analyze. Strftime filename patterns for rotation. |
| MRT Dump | Supported | RFC 6396 daemon-side MRT recording with three independent streams (updates, all messages, periodic TABLE_DUMP_V2 RIB snapshots). YANG config, per-peer and direction filtering, extended timestamps, add-path aware, on-demand CLI dump, async non-blocking writes, strftime file rotation. Analysis tools: show, routes, inject, replay, convert (pcap/json), statistics, filter. The daemon MRT plugin is compile-out-able with the ze_mrt build tag (default-on in ZE_FEATURES): ze-stripped and bare ze_core builds drop internal/plugins/mrt and its config schema, and the internal/mrt format library plus the shared internal/core/bgp/msgtype leaf drop by dead-code elimination once neither MRT nor the BGP engine references them. MRT loads inert without a BGP source, so it is independent of ze_bgp; its reactor bridges reach the engine through a plugin-registry seam so the always-on hub never imports the plugin. |
| PKI Certificate Store | Supported | YANG pki {} config for CA certificates and device certificates with private keys. Base64-DER certificate parsing, PKCS8/SEC1/PKCS1 private key detection, $9$ sensitive encoding for keys, chain validation, expiry checking, atomic reload. PEM export for IPsec and TLS consumers. ServerTLSMaterial gives a TLS listener the leaf plus every stored intermediate, so the web/API HTTPS listener (environment.web.certificate) and the as112/geodns DoT/DoH listeners (tls { certificate }) can serve an operator certificate with its full chain; a configured name that does not resolve stops the listener rather than falling back to self-signed. Health check (degraded at 30 days, down when expired). Report bus warnings for approaching expiry. show pki certificates, show pki certificate <name>. Shared infrastructure for IPsec, TLS, and future mutual-auth features. |
| IPsec Data Model | Supported | YANG vpn { ipsec {} } config for site-to-site VPN: ESP groups (proposals, lifetime, PFS), IKE groups (proposals, DPD, key-exchange, close-action), site-to-site peers (X.509 and PSK auth, VTI bind, group references). Algorithm enums match strongSwan naming. Cross-reference validation (group names, PKI certificates, interface binding, local-id/CN match). Config diff detection for reload. |
| IKEv2 Wire Format | Supported | RFC 7296 wire codec: all payload types (SA, KE, Nonce, ID, AUTH, CERT, CERTREQ, Notify, Delete, Vendor, TSi/TSr, EAP, Configuration). Header encode/decode, payload chaining, encryption envelope. |
| IKEv2 Cryptographic Primitives | Supported | DH groups (MODP 2048/3072/4096/8192, ECP 256/384/521), PRF (SHA-256/384/512), integrity (HMAC-SHA-256/384/512), encryption (AES-CBC, AES-GCM-16 128/256, ChaCha20-Poly1305), SKEYSEED derivation, key expansion (RFC 7296 Section 2.14). |
| IKEv2 Engine | Supported | Full IKE FSM for both initiator and responder roles (connection-type initiate/respond): IKE_SA_INIT, IKE_AUTH, CREATE_CHILD_SA, INFORMATIONAL exchanges. PSK and X.509 certificate authentication; as responder Ze also acts as the EAP authenticator (EAP-MSCHAPv2/EAP-TLS server). Child SA creation with traffic selectors and ESP proposals. IKE SA and Child SA rekeying (initiate and respond) with collision handling. DPD (Dead Peer Detection) via INFORMATIONAL exchange with configurable interval and timeout. XFRM policy and state programming via netlink. Reconciliation on config reload. SK crypto, key derivation, AUTH octets, and ESP key roles are parameterized by SA role. Compile-out-able with the ze_ike build tag (default-on in ZE_FEATURES): a stripped build drops the engine, IPsec config plumbing, crypto, EAP, wire codec, and command surface and rejects a vpn { ipsec {} } block; ike/dataplane (the XFRM programming seam OSPF's RFC 4552 authentication also uses) stays always-on. |
| IPsec EAP Authentication | Supported | EAP-MSCHAPv2 (type 26) and EAP-TLS (type 13) authentication for road warrior VPN clients inside IKEv2 IKE_AUTH exchange. MS-CHAPv2 crypto (NtPasswordHash, ChallengeResponse, MPPE key derivation), TLS handshake in EAP with fragmentation, MSK derivation feeding IKEv2 AUTH payload. Virtual IP pool with dual-stack allocation (IPv4 + IPv6), DNS push via Configuration Payload. |
| IPsec NAT Traversal | Supported | NAT detection via SHA-1 hash notify payloads in IKE_SA_INIT (RFC 7296 Section 2.23). Port 4500 with non-ESP marker for IKE, UDP encapsulation for ESP (RFC 3948). NAT keepalive (0xFF byte, 20s interval). XFRM SA UDP encap attribute set when NAT detected. |
| IPsec MOBIKE | Rejected | RFC 4555 MOBIKE notifications and XFRM endpoint migration are not implemented. |
| XFRM Interfaces | Supported | Route-based IPsec via XFRM interfaces (interface { xfrm <name> { if-id <N> } }). Traffic routed through the interface is encrypted; traffic arriving is decrypted. Created and deleted via netlink. |
| IPsec Interop Testing | Supported | Docker-based interop test infrastructure against strongSwan as the remote IKE peer, covering Ze as initiator (PSK, EAP-MSCHAPv2, EAP-TLS, BGP redistribute, child rekey) and as responder (PSK, EAP-MSCHAPv2, IKE-SA rekey) via. On hosts without XFRM (macOS Docker) the dataplane checks gate on availability and control-plane establishment is verified from strongSwan's logs. . test/ipsec-interop/scenarios/ |
| IPsec CLI and Diagnostics | Supported | show vpn ipsec sa/status/peer, clear vpn ipsec sa [peer <name>], monitor vpn ipsec (live SA event stream). Web page at with SA table. Health check (healthy/degraded/down from SA state). Prometheus metrics ze_ipsec_sa_count, ze_ipsec_tunnel_up and ze_ipsec_tunnel_degraded (per-peer gauges). Up requires an installed Child SA. Degraded names an established SA that carries no ESP. All show commands produce JSON and support full pipe operators. . /show/vpn/ipsec/ |
| DNS Resolver | Supported | Built-in cached DNS resolver for all components. Uses configured system.name-server or resolv.conf, and fails closed with no DNS server configured when neither is available. It does not silently fall back to public recursive resolvers. Cache management: show dns cache list/record, clear dns cache (flush/selective delete/stats reset). |
| Resolution CLI and Pipes | Supported | Offline ze resolve tool for DNS, Team Cymru ASN names, PeeringDB prefix counts, and IRR AS-SET expansion. The | resolve (reverse DNS) and | origin (ASN/network lookup via Team Cymru) pipe operators enrich any command's JSON output with DNS-based annotations. ze pipe brings these pipe operators to offline commands: ze show debug profile \| ze pipe match reactor, ze show debug profile \| ze pipe count, ze show debug profile \| ze pipe resolve. |
| Pipe Output Limiting | Supported | | first N and | last N pipe operators bound output to the first or last N items. Works on any command's JSON output (client-side truncation). Commands that register them as pipe filters (e.g. RIB) get server-side early termination: | first N stops the iterator at N, saving both iteration and serialization cost. | last N keeps a trailing window. JSON output includes a "pipe" metadata dict recording which data-shaping modifiers were applied. |
Stdin/stdout - on filename arguments |
Supported | Every filename-accepting command treats - as stdin when reading and stdout when writing, so configs and data stream through pipes without temp files: generate \| ze config show -, ssh host cat rib.mrt \| ze analyze show -, ze config show - \| ze config set - bgp session asn local 65001 \| ze config validate -, ze config migrate -o - old.conf. Resolution goes through one leaf helper so - behaves identically everywhere; MRT stdin auto-detects gzip/bzip2 by magic bytes. stdin is consumable once: a second - in one command fails closed. ze config edit/rollback/history - are rejected (no TTY / no revision history for a pipe). A build gate (make ze-dash-stdio-check) fails any command that reads/writes a user path without the helper. |
| Netdata-compatible OS Telemetry | Supported | 138 Prometheus metrics from /proc and /sys (CPU, memory, network, disk, IPv4/IPv6 protocols, conntrack, PSI, cpuidle, cpufreq, ZFS, btrfs, mdstat, SCTP, IPVS, wireless, etc) matching Netdata's naming and labels exactly. Drop-in replacement for Netdata's Prometheus exporter, existing Grafana dashboards keep working. Per-collector enable/disable, interval override, and prefix are scoped under telemetry.prometheus.netdata so Ze-native metrics keep their ze_* names. The Prometheus HTTP service defaults to loopback and can require HTTP Basic Auth. The Prometheus HTTP exporter (the /metrics + /health listener, telemetry config extraction, basic-auth, and the Netdata OS collectors) is compile-out-able with the ze_telemetry build tag: make ze and ze-appliance include it, while ze-stripped and bare ze_core builds drop internal/component/telemetry/exporter and internal/component/telemetry/collector and reject the telemetry {} config block as unknown. Metric COLLECTION (the always-on internal/core/metrics registry used by ~60 packages, plus its no-op dummy) stays linked in every build, so a no-telemetry binary still records every ze_* counter; it just cannot expose them over HTTP. |
| Flow Export | Experimental | Interface counter and per-flow record export over UDP via sFlow v5, NetFlow v9 (RFC 3954), and IPFIX (RFC 7011). Per-collector polling interval and template refresh. Packet sampling (tc sample + psample) exported as sFlow flow samples with configurable 1-in-N rate, header truncation, and psample group. Conntrack-based per-flow records (periodic table dumps) for NetFlow v9 and IPFIX. Optional BGP next-hop enrichment from the RIB best-change event. show flow export [<collector>] reports per-collector datagrams-sent, bytes-sent, errors, sequence, and last-export-time. show flow recent [dst <prefix>] returns recent conntrack flow records (5-tuple + TCP state) from a bounded drop-oldest ring (recent-flow-ring, default 4096 records, allocated only when conntrack export is on) that feeds on-box DDoS characterization. Prometheus metrics: ze_flowexport_datagrams_total, ze_flowexport_bytes_total, ze_flowexport_errors_total, ze_flowexport_samples_total, ze_flowexport_flows_total, ze_flowexport_flows_active, ze_flowexport_recent_ring_drops. Per-flow records cover IPv4 and IPv6 (separate templates); BGP enrichment currently fills next-hop only; sampling needs Linux with CAP_NET_ADMIN and kernel psample. Compile-out-able with the ze_flowexport build tag: default-on in ZE_FEATURES, dropped from ze-stripped / bare ze_core builds, with its config block rejected as unknown. |
| Traffic Monitor | Experimental | Lazy consumer-refcounted aggregation service (internal/component/trafficstat) that subscribes to the observation feed and maintains a time-windowed ranked usage view (per-interface rates, top-N source/dest IPs, top ports with service names, protocol mix, 60s history). The aggregator is rebuilt on the shared internal/core/stats rolling-window primitive; severity is now a display-only CLI computation from the history facts (the neutral layer holds no verdict). Runs only while consumers are attached. Consumed by show traffic stat (one-shot JSON snapshot), monitor traffic stat (full-screen alt-screen TUI via the generic MonitorProvider registry), and ddos/detect (Depth-1: pre-computed per-interface rates instead of raw counter diffing). Includes internal/core/portname hardcoded port-to-service-name table with amplification-vector overlay for 7 known reflection ports. |
| Traffic Feature Signals | Experimental | Neutral per-source detection SIGNALS (facts, never verdicts) derived from the observation feed by a second consumer alongside the traffic monitor: fan-out (distinct destinations), out/in byte ratio (exfiltration), destination-port entropy, new-peer, rare-port/proto, and coarse beaconing (interval regularity, bounded to periods of a few seconds by the 1s sampling tick). Computed via the shared internal/core/stats primitives (rolling window, Shannon entropy, interval regularity). Viewed via show traffic feature; bounded per-source state with idle eviction. The judgment layer (the anomaly detection family) consumes these facts. |
| Behavioral Anomaly Detection | Experimental | Darktrace-style SECURITY anomaly detector (report-only), a domain separate from volumetric DDoS. Consumes the neutral trafficfeature signals and learns each source entity's own pattern-of-life via a per-(entity,feature) EWMA baseline (internal/core/stats), scores self-deviation plus peer-group rarity (source-prefix cohorts), and correlates multiple weak feature deviations on one entity into a single incident (capped/discounted combine, not naive sum). A confirm/clear state machine debounces; confirmed incidents emit on the anomaly-detect event bus and land in a bounded recent-incident ring viewed via show anomaly detect. It takes NO action (the anomaly/shape responder acts); scoring is bounded per-entity with idle eviction. A ze doctor check (doctor-anomaly-detect-no-feature-source) warns when enabled without a flow source. Prometheus: ze_anomaly_incidents_total, ze_anomaly_active, ze_anomaly_tracked_entities. Both the detector and the shape responder are compile-out-able with the ze_anomaly build tag: default-on in ZE_FEATURES, dropped from ze-stripped / bare ze_core builds, with an anomaly {} block rejected as unknown. |
| Autonomous Anomaly Response | Experimental | Shadow-first responder (anomaly/shape) that subscribes to anomaly-detect incidents and installs a surgical per-SOURCE firewall action (rate-limit via firewall.MatchSourceAddress+Limit, drop fallback). SHADOW is the default: it logs the would-be action and installs nothing. In armed mode each anomalous source gets its own live nft rule with a mandatory timed AUTO-REVERT (withdraws after a TTL regardless of any clear event), a global BLAST-RADIUS cap (refuses to arm beyond N), a KILL-SWITCH (reverts all + forces shadow), and an ALLOWLIST (protected sources are never armed). One mutex guards the armed map; a per-timer generation guard makes a superseded timer a no-op. Status via show anomaly shape. Separate firewall owner key isolates it from ddos/local. A ze doctor check (doctor-anomaly-shape-armed-no-firewall) warns when armed without a firewall. Prometheus: ze_anomaly_shape_armed, ze_anomaly_shape_reverted_total, ze_anomaly_shape_arm_refused_total, ze_anomaly_shape_killswitch_total. |
| Traffic Usage | Experimental | eBPF TCX per-(port, protocol) and opt-in per-IP byte accounting on operator-selected interfaces, exported as Prometheus metrics and viewed via show traffic usage [name <interface>]. IPv4 only, monitoring only (never drops or modifies traffic), Linux >= 6.6 (no-op elsewhere; needs CAP_BPF + CAP_NET_ADMIN). The eBPF programs are assembled in pure Go (cilium/ebpf asm.Instructions) and loaded from memory: no C source, no committed .o, no clang/LLVM; hand-written assembly validated by BPF_PROG_TEST_RUN tests. Per-port accounting (ingress by dst_port, egress by src_port) is always on; track-ip adds per source/destination IPv4 (off by default to bound cardinality). Configurable poll interval, stale-timeout (delete unseen series to bound /metrics cardinality), and per-map LRU max-entries (top-talker eviction). Prometheus metrics: ze_traffic_usage_ingress_port_bytes_total, ze_traffic_usage_egress_port_bytes_total, ze_traffic_usage_ingress_bytes_total and ze_traffic_usage_egress_bytes_total (track-ip only), ze_traffic_usage_map_entries. A ze doctor check (doctor-traffic-usage-ebpf) warns when enabled but eBPF/TCX is unavailable. Compile-out-able with the ze_trafficusage build tag: default-on in ZE_FEATURES, dropped from ze-stripped / bare ze_core builds, with its config block rejected as unknown. |
| VPP Data Plane | Experimental | Manages VPP lifecycle (startup, crash recovery, DPDK NIC binding), programs FIB routes via GoVPP binary API, and polls VPP's stats segment for per-interface, per-node, and system-wide Prometheus metrics. Configurable poll interval. MPLS label operations (push, swap, pop) driven directly from BGP labeled unicast (RFC 8277): labels are stripped at NLRI parse, stored as RIB side-data, propagated through best-change events, and programmed into VPP via GoVPP IPRouteAddDel with LabelStack (push) or MplsRouteAddDel (swap/pop). vpp.external=true switches ze into connect-only mode for systemd-managed / container-sidecar deployments and the ze-test vpp stub harness. Local Docker evidence via make ze-deployment-vpp-test covers real VPP FIB add/withdraw, traffic policer apply/bind, same-config Ze restart preservation, startup cleanup of stale Ze traffic policers, and the IKE IPsec dataplane: two SAs and two policies programmed over the VPP binary API and read back through vppctl (SPIs, the inbound flag, the AEAD key and salt in their own fields, the ECN copy flags RFC 7296 Section 2.24 requires, the SPD bound to the interface, and both policies in priority order), plus proof that closing the backend removes the SAs and the SPD it installed so a restart leaves no orphan state. The IKE IPsec backend is TEST-ONLY and cannot yet be driven by IKE: it REFUSES every policy the IKE engine produces, because a VPP policy lives in an SPD bound to named interfaces and nothing supplies that interface; no config leaf selects the backend (only the private ze.test.ike.dataplane override does); ListSAs, ListPolicies and RemovePolicy all refuse, so an operator cannot read back or surgically remove what it programmed; and no test has sent ESP through it, so the evidence above is what VPP accepted and holds rather than traffic it carried. Same-process VPP traffic reapply now replays policer output binding so VPP-side unbinds converge back to desired state. Host tuning: vpp.cpu.poll-sleep (Nms) exposes VPP's idle main-loop sleep (unix { poll-sleep-usec }, unset = busy-poll for lowest latency); on the gokrazy appliance image.hugepages { size, page-size } reserves hugepages at boot by baking hugepages= kernel arguments, and ze doctor reports doctor-vpp-hugepages when the reservation is missing/insufficient/clamped. Compile-out-able with the ze_vpp build tag (default-on in ZE_FEATURES): a netlink-only build drops the GoVPP connector component, every per-plugin VPP backend (fib, firewall, iface, traffic, static, IKE IPsec), and the vendored GoVPP library; a vpp {} block is rejected as unknown and selecting a vpp backend fails closed with an unknown-backend error naming the registered set. |
| L2TPv2 BNG | ∿ | RFC 2661 L2TPv2 LNS/LAC with full BNG stack: tunnel lifecycle (SCCRQ/SCCRP/SCCCN, CHAP-MD5 challenge, HELLO keepalive, StopCCN teardown, tie-breaker), configurable dead-peer detection (hello-retries x hello-interval ACK-driven keepalive timeout, separate from the ~31s reliable-transport retransmit exhaustion, so a peer that dies without StopCCN is torn down fast while an idle-but-alive peer that only ZLB-ACKs HELLOs is not falsely dropped) , reliable delivery with sliding window and congestion avoidance, PPP negotiation (LCP 10-state FSM, PAP/CHAP-MD5/MS-CHAPv2 auth, IPCP/IPv6CP address assignment, proxy LCP), kernel data plane via l2tp_ppp netlink and PPPoL2TP sockets. Four plugins: auth-local (static users), auth-radius (RADIUS auth/acct/CoA/DM with failover, real per-subscriber traffic counters in Interim/Stop including RFC 2869 Gigawords), pool (bitmap-backed IPv4 ranges from Ze config), shaper (TC TBF/HTB on pppN interfaces with configured defaults and CoA rate updates). Subscriber route redistribution via redistribute { import l2tp }: the real RouteObserver emits add/remove route-change batches, and BGP announce/withdraw plumbing is covered with a synthetic producer. CQM monitoring (100s echo RTT/loss buckets, per-login sample rings, 24h retention). Web UI at /l2tp with session list, detail page, uPlot CQM graph with SSE live updates, event timeline, and disconnect with audit trail. ze_l2tp_* Prometheus metrics (session/tunnel gauges, per-session byte/packet counters, CQM echo RTT histogram, loss ratio, bucket state). ze_radius_* metrics (auth/acct/interim counters, server reachability). RADIUS Access-Accept subscriber profile attributes are consumed: Framed-IP-Address bypasses pool (direct IP assignment), Framed-Pool selects a named pool, Session-Timeout/Idle-Timeout enforce session lifetime, Filter-Id sets initial shaping rate at session establishment, Vendor-Specific attributes (RFC 2865 S5.26) extract CoS profiles from Cisco-AVPair/Juniper ERX/Nokia/Huawei VSAs and shaper rates from MikroTik Mikrotik-Rate-Limit (Ze "cos:" Filter-Id takes priority; unknown vendors silently ignored), Acct-Interim-Interval overrides the per-session accounting interval, and Framed-Route/Framed-IPv6-Route (RFC 2865 Section 5.22, RFC 6911 Section 3.2) inject per-subscriber static routes into BGP alongside the subscriber /32 or /128. Named pools are configured via YANG named-pool list under l2tp > pool. PPP auth now defaults to mandatory CHAP-MD5 with finite tunnel/session caps; no-auth requires explicit opt-in, hidden mandatory AVPs are rejected fail-closed. Docker-backed xl2tpd evidence covers external LAC control tunnel and incoming-call session setup. A peer-isolated Docker lab (make ze-deployment-l2tp-ppp-docker-test) proves full PPP LCP/IPCP, kernel pppN creation, dataplane ping, and BGP route redistribution from a live PPP session with Ze LNS, real xl2tpd/pppd LAC, and FRR in separate containers; requires host kernel PPPoL2TP support. Compile-out-able with the ze_l2tp build tag (default-on in ZE_FEATURES): a stripped build drops the whole BNG subtree (L2TP, PPPoE, subscriber management, local-auth/pool/shaper plugins) and rejects l2tp {} and pppoe {} blocks; the hub builds the subsystems through the gated bngRegister seam, the web session pages and diag l2tp captures answer not-in-this-build, and the cos dynamic RADIUS-CoS handler drops with it. |
| TACACS+ AAA | ∿ | RFC 8907 TACACS+ client for SSH login: PAP authentication, ordered server failover with per-server timeout, MD5 pseudo-pad body encryption, priv-lvl-to-profile mapping, command accounting (START/STOP records on every dispatched CLI command), and explicit-reject vs unreachable distinction so wrong-password TACACS+ replies do NOT silently fall through to local bcrypt. Runs as a pluggable aaa.Authenticator so local bcrypt remains the fallback when every TACACS+ server is unreachable (default). Configurable strict-fallback mode denies authorization when TACACS+ infrastructure is unavailable instead of falling back to local RBAC. Compile-out-able with the ze_tacacs build tag: default-on in ZE_FEATURES, dropped from ze-stripped / bare ze_core builds, with its config block rejected as unknown. |
| RADIUS admin AAA | ∿ | RFC 2865 RADIUS authentication for operator/admin login (SSH, web, MCP), distinct from the L2TP subscriber RADIUS path. PAP (User-Password hidden per §5.2), ordered server failover with per-server timeout and retries, Access-Accept reply-attribute-to-profile mapping (configurable, default Filter-Id §5.11, or Class §5.25) with a default-profile fallback, an Accept resolving to no profile rejected rather than authorized (an authenticated login always names at least one profile), and explicit-reject vs unreachable distinction so a wrong-password Access-Reject does NOT fall through to local bcrypt while an unreachable server does. Runs as a pluggable aaa.Authenticator at chain priority 50 (ahead of TACACS+ 100 and local 200); local bcrypt remains the fallback. ze doctor probes reachability (doctor-radius-admin-unreachable). Reuses the L2TP RADIUS client, so retransmit, failover, and Response-Authenticator verification behave identically. CHAP/EAP admin auth and admin-session accounting are not implemented. Compile-out-able with the ze_radius build tag (default-on in ZE_FEATURES); the l2tp RADIUS auth plugin is the dependent piece, generated behind ze_l2tp && ze_radius, so a radius-less BNG build links zero RADIUS symbols and a bng-less build keeps RADIUS system authentication. |
| PPPoE Access | ∿ | RFC 2516 PPPoE access concentrator: discovery state machine (PADI/PADO/PADR/PADS/PADT), HMAC-SHA256 AC-Cookie for DoS protection, per-interface session tables with bitmap SID allocation (1-65535), per-source-MAC PADI rate limiting, Service-Name filtering, kernel PPPoE sessions via AF_PPPOX + PX_PROTO_OE, and integration with the transport-agnostic PPP Driver (same auth/pool/shaper plugins as L2TP). YANG config (pppoe {}) with per-interface settings. CLI commands: show pppoe, show pppoe sessions, show pppoe statistics, show pppoe interfaces. Runs concurrently with L2TP on the same daemon. Functional tests (make ze-qemu-pppoe-test) drive a real client over a veth pair inside a per-test network namespace on ze's runtime kernel: PADI to PADO carrying AC-Name and AC-Cookie, PADR to PADS with a kernel AF_PPPOX session and a non-zero session id, a forged AC-Cookie earning no PADS, the same exchange on an 802.1Q sub-interface, and an L2TP SCCRP answered while the AC is bound. Partial because what follows PADS is not proven there: PPP negotiation, the session data plane, PADT teardown, PADI rate limiting and Service-Name filtering have unit coverage only, and the accel-ppp labs (ze-qemu-pppoe-accel-test) exercise ze as a PPPoE client rather than as the concentrator. PPPoE ships inside the ze_l2tp build tag (the BNG gate); a stripped build rejects a pppoe {} block as unknown. . test/pppoe/test/pppoe-interop/ |
| Firewall | Experimental | Packet filter and NAT via the nftables backend on Linux. Abstract model supports 15 match types (source/destination address, port ranges, protocol, input/output interface with wildcard prefix, connection state, marks, DSCP, ICMP type, ICMPv6 type, TCP flags, named sets) and 19 action/modifier types (accept, drop, reject, jump/goto/return, SNAT/DNAT with address ranges, masquerade, redirect, notrack, flow offload, set mark/connmark/DSCP/TCP-MSS, counter, log, rate limit). NAT exclude rules emit a Return verdict to skip translation. Global-options container maps keyword toggles (all-ping, broadcast-ping, syn-cookies, source-validation, etc.) to kernel sysctls via the sysctl plugin's default layer; explicit sysctl settings always override. IRR-based prefix-list filtering: source-asn, source-as-set, destination-asn, destination-as-set leaves in from-block resolve ASN/AS-SET references to nftables interval sets via the shared IRR PrefixStore (firewall-irr plugin). Per-interface source validation: bind an AS-SET to a customer-facing interface via irr { interface <name> { source-as-set <AS-SET>; } } to drop ingress traffic with source addresses not in the IRR-resolved prefix set (BCP 38). Component reactor wires into ze's engine lifecycle: Apply on boot and reload, rollback on failure. ze_ prefix on all kernel tables. |
| Control-Plane Policing (CoPP) | Experimental | Rate-limit new TCP connections to the BGP listen port (TCP/179) to protect against connection-flood DDoS. Generates an nft input-hook chain via the firewall registry: established/related sessions pass at full rate, operator-supplied trusted-source prefixes bypass the limit, new connections are rate-limited. Configurable rate, burst, protected-port (default 179), trusted-source prefix list, and over-limit policy (accept/drop, default accept for lock-out safety). Doctor check verifies the CoPP input chain is active when configured. Compile-out-able with the ze_copp build tag: default-on in ZE_FEATURES, dropped from ze-stripped / bare ze_core builds, with its config block rejected as unknown. |
| VPP Firewall Backend | Stub-backed | Registered as firewall { backend vpp }. Filter chains translate ze Match/Action types to VPP ACL rules via GoVPP binapi (source/destination prefix, port range, protocol, ICMP type/code, TCP flags, permit/deny/reflect). Connection-state established,related maps to ACL_ACTION_API_PERMIT_REFLECT (VPP reflexive ACL). NAT chains configure VPP NAT44-ED: masquerade via output-interface mode, SNAT via address pool + inside interface feature, DNAT via static mappings with tagged cleanup. SetMark and Limit actions use VPP's classify pipeline: classify tables match traffic by packet header fields, SetMark sets opaque metadata via CLASSIFY_API_ACTION_SET_METADATA, Limit creates a policer bound to the classify table via PolicerClassifySetInterface. Expression types without a faithful VPP representation are rejected at commit via firewall.RegisterVerifier("vpp", Verify): interface matches, connection marks, DSCP, sets, packet modification (connmark/dscp/tcp-mss), counters, log, chain traversal. |
| Commit-Time Backend Capability Check | Supported | YANG nodes that correspond to backend-specific features carry a ze:backend "<names>" annotation. On commit (daemon reload, first-apply, and ze config validate), the walker rejects the config with the YANG path and the list of supporting backends whenever the active backend does not implement the feature -- instead of letting an Apply-time "not supported" error fire inside the backend. The gate covers interface (netlink-only bridge, tunnel, wireguard, veth, mirror under the vpp backend), traffic/control (the backend-leaf CALL wired into OnConfigure/OnConfigVerify; tc-only feature annotations ship with spec-fw-7-traffic-vpp), and firewall (seven ze:backend "nft" annotations on conntrack-driven matches and nft-only action/modifier leaves). |
| Backend-Aware CLI Completion | Supported | CLI auto-completion filters options based on the active backend. Config editor mode (set/delete/edit/show) and operational command mode (show/clear/monitor) hide nodes annotated with ze:backend when the active backend is not in the annotation's list. Backend names are derived from the config tree at each tree change. Same ze:backend annotations used by commit-time validation, applied earlier at completion time. |
| Traffic Control Lifecycle | Experimental | The traffic/control section of the config is now programmed at boot and on SIGHUP reload. The traffic component's reactor calls the selected backend's Apply(map[string]InterfaceQoS) in OnConfigure and OnConfigApply, with sdk.Journal rollback on apply failure. Linux default backend is tc (netlink); future backends plug in via traffic.RegisterBackend. Local privileged integration covers netlink qdisc snapshot/restore after backend restart; target-runner and reactor-level boot/reload kernel-state evidence remain open. |
| VPP Traffic Control Backend | Stub-backed | Registered as traffic { control { backend vpp } }. Scope is per-class policing: HTB and TBF qdiscs translate each class to a VPP policer (CIR = Rate, EIR = Ceil, kbps with round-up). An unfiltered single class binds to interface egress via PolicerOutput. A class carrying a steering filter -- filter protocol <n> or filter dscp <v> -- is instead bound to the ingress policer-classify feature: the backend builds per-family (IPv4 + IPv6) classify tables whose mask/match vectors match the packet at absolute frame offsets and steers matching packets to the class policer via HitNextIndex (byte-for-byte VPP's own policer-hit-next, verified on VPP v25.10). Offsets: IPv4 protocol byte 23 / IPv6 next-header byte 20 for filter protocol; IPv4 TOS byte 15 (mask 0xFC) / IPv6 traffic-class bytes 14-15 (masks 0x0F/0xC0) for filter dscp -- filter dscp polices the DSCP-matched traffic (police-by-dscp), it is NOT a QoS remark. Multi-class HTB/TBF is accepted when EVERY class carries a steering filter: per-interface, per-family the sessions are grouped by field mask into one table per distinct mask (a session per class -> its own policer), and distinct-mask tables are chained via ClassifyAddDelTable.NextTableIndex (real VPP v25.10 validated the multi-session steering and chain fall-through). A multi-class config with any unfiltered class, the prio qdisc (a scheduler VPP does not expose), mark filters (Linux SKB fwmark has no faithful VPP equivalent), and every other qdisc type are rejected at OnConfigVerify via traffic.RegisterVerifier("vpp", Verify). Per, shipping silent-no-op features (classify sessions in a detached table, or N unfiltered policers stacked on the output feature arc producing min(rates) instead of per-class shaping) is banned. Apply waits up to 5s for VPP to be reachable and returns vpp not connected after 5s on timeout. On partial-apply error the backend undoes what this call programmed in VPP before returning. Reconcile-time deletions are tolerant of stale indexes (post-VPP-restart): failures log a warning and continue instead of failing the commit. A fresh backend instance scans VPP policers with the ze/ prefix, removes undesired startup orphans, and rebinds desired policers from config. Same-process reapply also replays PolicerOutput(apply=true) for existing desired policers, repairing VPP-side output unbinds without requiring a Ze restart. Protocol-filter classify tables are reclaimed by in-process reconcile (unbind + delete by tracked index); because VPP classify tables are anonymous they cannot be reclaimed by name at startup like policers, so a table left by a previous process is inert (unbound) memory reclaimed only by a VPP restart. Real-daemon traffic-control evidence covers policer apply/bind, restart preservation, startup orphan cleanup, protocol-filter and dscp-filter classify-table attachment + reconcile removal, and multi-class per-class steering (two policers bound via one table per family). . rules/exact-or-reject.md |
| AIGP (RFC 7311) | Supported | Accumulated IGP Metric path attribute. Capability negotiation, wire encoding/decoding, structured JSON exposure with RFC 4271 attribute flags. Not consumed in best-path selection. |
| PATHS-LIMIT (draft-abraitis-idr-addpath-paths-limit) | Supported | Per-family path count limit for ADD-PATH. Receiver advertises max paths per prefix; sender enforces. Unified config under capability { add-path { limit N; } } with per-family overrides. RS fast-path peers suppress the capability. |
| RPKI ASPA Policy Enforcement | Supported | ASPA path verification (draft-ietf-sidrops-aspa-verification) with configurable policy enforcement: rpki/aspa/action/invalid supports reject, log-only, accept. ASPA records distributed via RTR v2 (RFC 9582). |
| RPKI Per-Peer Action | Supported | Origin (invalid/not-found) and ASPA (invalid/unknown) validation actions are settable globally and per-peer/per-group (peer > group > global, resolved per leaf), while cache servers and ASPA enable stay global. show bgp rpki status reports effective global and per-peer resolved actions. |
| IRR BGP Import Filtering | Supported | bgp-filter-irr builds per-ASN import prefix-lists from explicit or PeeringDB-discovered IRR AS-SETs, refreshes and persists the lists, and rejects received prefixes outside the selected list. Includes status, prefix inspection, dry-run checks, and manual refresh commands. |
| FlowSpec-to-Firewall Bridge | Supported | flowspec-firewall plugin converts BGP FlowSpec rules into nftables entries in a dedicated ze_flowspec table. |
| IXP Route Server Dynamic Peers | Supported | Route server (bgp-rs) supports dynamic peers for IXP deployments. Peers connect dynamically and inherit configuration from a peer group template. RS-client role and per-peer community filtering. |
| Subscriber Session Model | Supported | Unified subscriber session model for L2TP/PPPoE subscribers with shared session lifecycle, auth, pool, and shaper infrastructure. Show enricher registry lets plugins contribute data to show commands: in-process plugins register via show.MustRegister in init; external plugins declare enrichers at registration (Stage 1) and handle ze-plugin-callback:enrich-show callbacks at runtime with a 2s timeout. Web service-locator pages call show.Enrich explicitly. show subscriber detail and show subscriber gain CoS profile data when the cos plugin is loaded. . internal/core/show/ |
| Config Schema Stamp | Supported | Config files carry a schema version stamp. Downgrade recovery prunes incompatible fields when loading a config from a newer version. |
| Config Dependency Graph | Supported | ze config graph visualizes config dependency relationships. |
| Graceful Listener Migration | Supported | Hot reload of listener endpoints (web, LG, REST, gRPC, MCP). New listener starts before old one stops; in-flight connections are drained. |
| Docker Support | Supported | Static binary on scratch base (~89 MB). make ze-docker with optional build tags. Compose support via. docker/compose.yaml |
| Archive Pruning | Supported | commit-revisions config field limits the number of retained committed revisions. Older revisions pruned after each commit. |
| DHCP Server Named Ranges | Supported | Multiple named address ranges per subnet for segmented allocation. Each range has an independent bitmap pool. Compile-out-able with the ze_dhcpserver build tag: default-on in ZE_FEATURES, dropped from ze-stripped / bare ze_core builds, with its config block rejected as unknown. |
| AS112 Anycast DNS | Supported | Authoritative sink for misdirected RFC 1918 / link-local reverse-DNS queries (RFC 7534) and the EMPTY.AS112.ARPA DNAME-redirection zone (RFC 7535). Four fixed anycast host addresses (never operator-typed), registered against the iface address-ownership registry and bound via IP_FREEBIND. Optional allow-from client-source access list (loopback always permitted). BGP integration composes existing healthcheck/watchdog/update-block mechanisms: the anycast route announces only once a probe against a real anycast service address confirms the DNS service is healthy, with an operator-chosen community and optional AS112-origin AS_PATH override. show as112, as112 health [target <ip>], ze_as112_* metrics. The four covering prefixes can also be BGP-originated directly through the redistribute path (redistribute { destination bgp { import as112 } }) with a configurable origin ASN (asn, default 112) and community, health-gated by the watchdog serving-state check (RFC 7534 Section 3.3). Compile-out-able with the ze_as112 build tag: default-on in ZE_FEATURES, dropped from ze-stripped / bare ze_core builds, with its config block rejected as unknown. |
| ExaBGP Compatibility | Supported | Automatic config migration and plugin bridge The bridge plugin and the ze exabgp command are compile-out-able with the ze_exabgp build tag (default-on in ZE_FEATURES); ze config migrate stays in every build (the migration library is always-on, only the runtime bridge gates). |