Small Linux daemon in Go that plays with the same ideas as GLBP: a shared virtual IP, an elected primary gateway, and ARP replies that hand out different virtual MACs so clients spread themselves across routers. Handy on a bench with a few VMs or cheap switches where you want to see the mechanics without a vendor stack.
This is not Cisco GLBP on the wire. The hello packets are a tiny custom UDP layout (see internal/adapters/netio/codec.go), priorities and roles are simplified, and there is no interop story with real GLBP gear. Treat it as a teaching aid, not a drop-in replacement.
The process joins a multicast group, exchanges short UDP “hellos”, and keeps a local table of who is alive. Highest priority wins the AVG role (with optional preemption); that node is the one that answers ARP for the configured VIP. When it answers, it picks one of the known forwarder MACs in round-robin order, so successive ARP exchanges can point clients at different routers’ dummy/VMAC interfaces. ARP I/O is done with libpcap on the LAN-facing interface you name in config.
Everyone in the same logical group must agree on VIP, group id, and multicast address/port. The stock in-memory store indexes forwarders by id only, so give each router different forwarder ids if you want every node’s MAC in the pool (the example/ YAMLs use 1 on one box and 2 on the other for that reason). If two peers reuse the same id, the table will keep whichever update arrived last.
- Linux (tested in the “normal” amd64 server VM sense; other arches untested here)
- Go 1.22+
- libpcap headers for the build (
libpcap-devon Debian/Ubuntu) - Enough privilege to open the interface in pcap and inject frames (typically root)
sudo apt install libpcap-devgo mod tidy
go build -o glbpd ./cmd/glbpdSanity check:
go vet ./...
go test ./...(go test is a no-op if your tree has no _test.go files yet.)
Path is whatever you pass to --config (default glbp.yaml). Minimal shape:
| Field | Notes |
|---|---|
interface |
LAN interface where ARP for the VIP appears |
virtual_ip |
IPv4 VIP the group owns |
group_id |
0–255, same on all members |
priority |
Higher wins AVG when timers say everyone is healthy |
weight |
Sent on the wire for each forwarder; the AVG’s selector is still plain round-robin over the live set |
preempt |
If true, a higher-priority node can take AVG from a lower one |
hello_time_sec / hold_time_sec |
Timers; defaults 3 / 10 if omitted or zero |
multicast_group / multicast_port |
Default 224.0.0.102 / 3222 |
forwarders |
List of { id, iface, weight? } — each iface must exist and expose a 6-byte MAC |
Working pair of configs lives under example/ (glbp-router-1.yaml, glbp-router-2.yaml) with mismatched priorities so you can watch one node grab AVG and the other fall back.
Each router needs a dummy (or similar) interface acting as its forwarder: own MAC, VIP as /32, forwarding on. The repo ships shell snippets you can paste or adapt:
example/int-router-1.sh— first router’svmac0bring-up + sysctl for ARP behaviour oneth0example/int-router-2.sh— same idea for the second box (adjust MAC if you care about uniqueness on the wire)
On the physical LAN interface you almost always want the kernel out of the way of ARP for the VIP so your process sees the requests:
sudo sysctl -w net.ipv4.conf.<iface>.arp_ignore=1
sudo sysctl -w net.ipv4.conf.<iface>.arp_announce=2Replace <iface> with your uplink name. Exact topology (bridges, namespaces, where the VIP also lives) is up to you; the daemon assumes ARP who-has for the VIP hits the pcap filter on the configured interface.
sudo ./glbpd --config example/glbp-router-1.yamlLogs tick on the hello interval: current role, peer count, forwarder count. Second node with the other yaml should show standby/listen until you kill the AVG or change priorities.
- Custom protocol on the wire; do not point this at a production VLAN with real GLBP speakers.
- No auth, no signing, no fancy state machine—just enough to watch elections and ARP fan-out.
- You are responsible for sysctl, routing, and not black-holing traffic in your lab.
GLBP and Cisco are trademarks of Cisco Systems, Inc. This repository is an independent experiment and is not affiliated with or endorsed by Cisco.