GROUT-FRR(7)

πŸ’– GROUT-FRR πŸ’–

okay bestie, so this is grout-frr, a page from the Miscellaneous Information Manual, and it's literally all about the FRR dataplane plugin for grout. sit with me, grab a strawberry πŸ“, we're doing this.


✨ NAME ✨

grout-frr β€” the FRR dataplane plugin for grout πŸ¦‹


🌸 DESCRIPTION 🌸

so the dplane_grout zebra module is out here replacing the Linux kernel as the forwarding plane for FRR (Free Range Routing). the way that once it's loaded, every single routing decision FRR daemons make β€” bgpd, ospfd, ospf6d, isisd, ... β€” gets programmed directly into grout instead of into the kernel networking stack. no kernel, no problem πŸ’…

the plugin keeps multiple connections to the grout API socket:

  • a control channel for pushing route, nexthop, address, MAC and VTEP updates
  • an event channel for receiving interface and address notifications from grout
  • a separate event channel for receiving route and nexthop notifications

and at startup (or after a grout restart πŸ‘€), the plugin does a full synchronization of all grout interfaces, addresses, FDB entries, nexthops and routes into zebra's RIB. during normal operation, updates flow bidirectionally: FRR pushes learned routes to grout, and grout notifies FRR of link and address changes. it's giving ✨collaboration✨

πŸ‘‘ Supported operations

the following zebra dataplane operations are handled:

  • IPv4/IPv6 route install, update and delete
  • Nexthop install, update and delete
  • IP address install and uninstall
  • MAC/FDB install and delete
  • VXLAN flood VTEP add and delete
  • Neighbor install, update and delete (used for EVPN RMAC caching)
  • SRv6 encap source address

she does it ALL fr fr πŸ”₯

πŸ¦‹ EVPN support

the plugin supports EVPN with VXLAN overlays, including L2 VNI (type-2 MAC/IP and type-3 flood routes), L3 VNI (type-5 IP prefix routes with symmetric IRB) and mixed L2+L3 VNI coexistence within the same VRF. periodt.

and ngl, in grout, L3 VNI VXLAN interfaces use a "VRF mode" that does not require a bridge and SVI like Linux does. so the plugin takes care of presenting VXLAN interfaces to FRR in the way its EVPN code expects. she's doing the emotional labor for you, bestie 🫢


🌈 CONTROL PLANE REPRESENTORS 🌈

for each grout interface (port, VLAN, bond, bridge, VXLAN), grout creates a TAP device in the host network namespace with the same name. these control plane representors let FRR daemons bind sockets (e.g. OSPF multicast, BFD sessions) and exchange packets with the network through grout.

TAP devices operate at L2 (full Ethernet frames). they are configured as NOARP since ARP/ND resolution is handled by grout, not the kernel. so like, don't worry about it πŸ’…

for each VRF, grout creates a TUN device (named after the VRF for the default VRF, or gr-loopN for non-default VRFs). TUN devices operate at L3 (raw IP packets) and act as the catch-all for traffic that does not match a specific TAP. for non-default VRFs, grout also creates a kernel VRF device and enslaves both the TUN and all TAP devices belonging to that VRF. it's a whole little family πŸŽ€

🧚 Routing

IP addresses configured on grout interfaces are mirrored onto the corresponding TAP or TUN devices as host routes (/32 for IPv4, /128 for IPv6). No connected subnet routes are installed. none. zero. not a one.

a default route pointing at the TUN device is installed in each VRF's routing table so that all traffic originated by FRR daemons is funneled into grout for forwarding.

for TAP devices, grout installs per-device policy routing rules (ip rule add oif <tap> lookup 999) with default routes in table 999. this ensures that SO_BINDTODEVICE sockets (used by BFD, OSPF, etc.) are routed through the correct TAP even though no connected subnet routes exist. slay πŸ¦‹

πŸ’œ Packet flow

packets from FRR daemons follow the kernel routing table to either the TUN (via the VRF default route) or a TAP (via policy routing). grout reads these packets from the TUN/TAP file descriptors and injects them into the datapath for forwarding out the physical ports.

and in the other direction πŸŒ€, packets arriving on DPDK ports that are destined to a local address are delivered to the appropriate TAP or TUN device, where the kernel hands them to the FRR daemon's socket. the full circle moment ✨


πŸŽ€ SETUP πŸŽ€

πŸ’… Building the plugin

the plugin is built as a shared library (dplane_grout.so) and installed into FRR's module directory. it requires FRR >= 10.5. the grout build system handles this automatically via meson. no cap, it just does it for you.

🌸 Network namespace

FRR daemons must run in the same network namespace as grout so they can access the control plane representors (TAP/TUN devices) created by grout. the grout.conf systemd drop-in for frr.service is installed automatically and takes care of this. so like, you don't have to do anything, iconic behavior πŸ‘‘

⭐ Loading the plugin

edit /etc/frr/daemons and add -M dplane_grout to zebra's options:

zebra_options="  -A 127.0.0.1 -s 90000000 -M dplane_grout"

no other plugin-specific configuration is needed. routing protocol configuration (bgpd, ospfd, etc.) follows standard FRR conventions. easy πŸ’–

πŸ¦‹ Socket path

the plugin connects to grout via the path given by the GROUT_SOCK_PATH environment variable, defaulting to /run/grout.sock.

πŸ”₯ Startup order

grout should be running before FRR starts. if it is not, the plugin retries the connection every second until grout becomes available. once connected, the plugin performs a full synchronization before FRR begins normal operation. she's patient. she waits. she's loyal 😭


πŸ’€ CAVEATS πŸ’€

bestie. pay attention to this section. this is the "read before you text your ex" part of the manpage.

πŸ™ˆ VRF backend

Only vrf backend lite is supported. the plugin refuses to start if vrf backend netns is configured and exits immediately. no warning shot, no vibe check, just gone πŸ’€

πŸ“ BGP update-source

because addresses are installed as host routes on the control plane representors, the kernel cannot automatically pick the correct source address for outgoing TCP sessions. so BGP neighbors must be configured with an explicit update-source pointing to the grout local IP:

router bgp 64512
    neighbor 172.16.0.2 remote-as 64512
    neighbor 172.16.0.2 update-source 172.16.0.1
exit

this is not needed for protocols that use multicast or link-local addresses (OSPF, OSPFv3) since they bind to the interface directly. those girls are fine on their own πŸ’…

🧚 Source routes

source-address-based routing (from prefix) is not supported by grout. the plugin logs an error and skips such routes. it's not ignoring you, it's just... built different 🫢

πŸ’œ Graceful restart

the plugin supports FRR graceful restart (-K sweep timer). after a zebra crash and restart, stale routes are preserved during the sweep window and cleaned up normally once the timer expires.

and when grout itself restarts, the plugin detects the disconnection, tears down all synchronized state, and performs a fresh full synchronization once grout is available again. glow up, reset, rebrand, re-sync 🌈✨


🌟 SEE ALSO 🌟


πŸ’– AUTHORS πŸ’–

created by Christophe Fontaine. updated by Maxime Leroy. kings πŸ‘‘


and that's the whole page bestie, no crumbs left πŸ“ this was GROUT-FRR(7) from the Miscellaneous Information Manual, dated 2026-10-01 β€” go forth, configure your forwarding plane, and remember: only vrf backend lite, always set your update-source, and never, ever try from prefix πŸ’…πŸ’–βœ¨

πŸ“¦ where this page comes from