First-Hop Redundancy

Updated

September 4, 2026

First-Hop Redundancy

Hosts rarely run a routing protocol. They send traffic to a default gateway. If that gateway dies, the LAN dies with it—unless you give the LAN a virtual first hop that can move between routers. This chapter builds the model and a free-stack lab: Linux + FRR + Containerlab (mid-2026 open path).

Learning goals

By the end of this chapter you can:

  • Explain why a single gateway IP is a single point of failure
  • Contrast VRRP-class first-hop redundancy with floating statics and ECMP
  • Deploy a dual-router VRRP pair on FRR for a shared virtual IP (VIP)
  • Predict host behavior when the master fails and when it recovers
  • Verify with ip neigh, pings, and FRR VRRP state—not hope

Concepts

The problem

   h1 ---- [LAN] ---- gw 10.0.0.1  (one box)
              |
           Internet-ish

Host config: default via 10.0.0.1. When that box reboots, ARP still points at a MAC that is gone until the host relearns—or traffic blackholes forever if nothing answers.

First-hop redundancy idea

Two (or more) routers share:

Object Role
Virtual IP (VIP) Address hosts use as gateway
Virtual MAC (often) Stable L2 identity for the VIP
Master / backup roles Who owns the VIP right now
Hello / advertise “I am alive and I claim priority”

Hosts keep one gateway IP. The active forwarder changes under them.

Protocol family (vendor-agnostic)

Name Notes
VRRP Open standard idea; FRR supports VRRP
HSRP / GLBP Proprietary dialects of the same problem class
CARP OpenBSD-family cousin

This book uses VRRP on FRR because it is free, documented, and works in Containerlab without licenses. Optional: Nokia SR Linux community images have their own FHRP configuration surface—same model, different CLI.

Priority, preempt, timers

  • Priority: higher wins master election (within rules).
  • Preempt: when a higher-priority router returns, does it take the VIP back?
  • Advertisement interval: how fast backups notice silence.
  • Skew / master-down interval: how long before backup promotes.

What FHRP is not

Not this Because
Full routing protocol Hosts do not learn remote prefixes via VRRP
Load balancing of arbitrary flows (unless designed) Classic VRRP is active/standby for a VIP
Multihoming policy That is BGP/statics + dual default; separate chapter lab

FHRP protects the LAN’s first hop. Dual-homing the site edge is complementary (see dual-home lab later in this part).

ARP and the VIP

When master changes, hosts may still have the old MAC in the neighbor cache briefly. Good implementations use a shared virtual MAC or gratuitous ARP so clients rebind quickly. In labs, clear neighbor cache deliberately when debugging:

# Linux host
ip neigh flush dev eth1
# or
ip neigh del 10.0.0.254 dev eth1

Addressing plan

Node Role Interface Address
r1 VRRP priority high eth1 (LAN) 10.10.10.2/24
r2 VRRP priority low eth1 (LAN) 10.10.10.3/24
VIP gateway for hosts 10.10.10.254
h1 client eth1 10.10.10.10/24 via VIP
r1 eth2 uplink eth2 172.16.1.1/30
r2 eth2 uplink eth2 172.16.2.1/30
pe “upstream” eth1/eth2 172.16.1.2, 172.16.2.2

Upstream pe can be a simple FRR or Linux box that advertises a sink for drills (203.0.113.1 loopback).

Topology YAML

name: vrrp-edge

topology:
  nodes:
    r1:
      kind: linux
      image: quay.io/frrouting/frr:10.2.1
      binds:
        - ./config/r1:/etc/frr
    r2:
      kind: linux
      image: quay.io/frrouting/frr:10.2.1
      binds:
        - ./config/r2:/etc/frr
    pe:
      kind: linux
      image: quay.io/frrouting/frr:10.2.1
      binds:
        - ./config/pe:/etc/frr
    h1:
      kind: linux
      image: alpine:3.20
      exec:
        - apk add --no-cache iproute2 iputils
        - ip addr add 10.10.10.10/24 dev eth1
        - ip link set eth1 up
        - ip route add default via 10.10.10.254

  links:
    - endpoints: ["h1:eth1", "r1:eth1"]
    - endpoints: ["r1:eth1", "r2:eth1"]   # same LAN: use bridge or multipoint
    - endpoints: ["r1:eth2", "pe:eth1"]
    - endpoints: ["r2:eth2", "pe:eth2"]

LAN wiring note: two point-to-point links do not make a shared segment. Prefer a Linux bridge node as “LAN switch,” or Containerlab multipoint / bridge patterns from your lab-craft notes:

    lan:
      kind: linux
      image: alpine:3.20
      exec:
        - apk add --no-cache iproute2 bridge-utils
        - ip link add name br0 type bridge
        - ip link set br0 up
  # links: h1, r1, r2 all into lan with bridge enslavement in exec

Simpler teaching pattern: one host + two routers on a bridge so ARP and VRRP multicast behave like a campus LAN.

FRR daemons

zebra=yes
vrrpd=yes
# staticd or bgpd if you route beyond the VIP
staticd=yes

Check mid-2026 FRR image docs for exact daemon names (vrrpd may be integrated differently by version—vtysh show vrrp is the operator check).

FRR VRRP sketch (r1)

frr version 10.2.1
frr defaults traditional
hostname r1
!
interface eth1
 ip address 10.10.10.2/24
!
interface eth2
 ip address 172.16.1.1/30
!
interface eth1
 vrrp 1 ip 10.10.10.254
 vrrp 1 priority 200
 vrrp 1 advertisement-interval 1000
!
ip route 0.0.0.0/0 172.16.1.2
!
line vty

r2: real IP 10.10.10.3/24, priority 100, same VIP and VRID 1, default via its own uplink.

Syntax varies slightly by FRR minor version—always validate with:

docker exec clab-vrrp-edge-r1 vtysh -c 'show vrrp'
docker exec clab-vrrp-edge-r1 vtysh -c 'show interface eth1'

Linux alternative (keepalived)

Some operators run keepalived on Linux instead of NOS VRRP. Same objects: VIP, priority, advert. In pure Alpine labs you may:

# illustrative — package availability varies
# apk add keepalived
# configure vrrp_instance with virtual_ipaddress

For this book’s default path, FRR VRRP keeps one control-plane stack with your OSPF/BGP labs.

Deploy and baseline

sudo containerlab deploy -t vrrp-edge.clab.yml

docker exec clab-vrrp-edge-r1 vtysh -c 'show vrrp'
docker exec clab-vrrp-edge-r2 vtysh -c 'show vrrp'
docker exec clab-vrrp-edge-h1 ip route
docker exec clab-vrrp-edge-h1 ip neigh
docker exec clab-vrrp-edge-h1 ping -c 3 10.10.10.254
docker exec clab-vrrp-edge-h1 ping -c 3 172.16.1.2

Predict (baseline)

  • r1 is Master, r2 is Backup (priority 200 > 100)
  • h1 ARP for VIP resolves to master’s virtual/real MAC pattern for your stack
  • Ping VIP succeeds; traffic to upstream uses r1’s uplink

Observe

Record: VRRP state, VIP owner interface counters, ip neigh on h1, traceroute if upstream is reachable.

Drill 1 — Master failure

# Simulate master death (stop data plane or whole node)
docker exec clab-vrrp-edge-r1 ip link set eth1 down
# or: docker stop clab-vrrp-edge-r1

sleep 3
docker exec clab-vrrp-edge-r2 vtysh -c 'show vrrp'
docker exec clab-vrrp-edge-h1 ip neigh show 10.10.10.254
docker exec clab-vrrp-edge-h1 ping -c 10 10.10.10.254
docker exec clab-vrrp-edge-h1 ping -c 5 203.0.113.1   # if pe has this

Predict → observe → fix

Predict Observe Fix if wrong
r2 becomes Master after down-timer show vrrp timers, VRID mismatch, not same LAN
Short ping loss then recovery count drops ARP stuck—flush neigh; check VIP MAC
Upstream still works via r2 traceroute r2 default / pe return routes

Restore:

docker exec clab-vrrp-edge-r1 ip link set eth1 up
# or docker start + wait FRR ready
sleep 5
docker exec clab-vrrp-edge-r1 vtysh -c 'show vrrp'
docker exec clab-vrrp-edge-r2 vtysh -c 'show vrrp'

Preempt on: r1 reclaims Master. Preempt off: r2 may stay Master—document which you configured.

Drill 2 — Split brain / LAN partition (concept)

If both routers believe they are alone (broken LAN bridge), two masters can both answer the VIP → intermittent ARP thrash.

Predict

Duplicate VIP answers; flapping neighbor cache; odd packet loss.

Observe

docker exec clab-vrrp-edge-r1 vtysh -c 'show vrrp'
docker exec clab-vrrp-edge-r2 vtysh -c 'show vrrp'
# tcpdump for VRRP (IP protocol 112) on the LAN
docker exec clab-vrrp-edge-h1 sh -c 'apk add --no-cache tcpdump; tcpdump -ni eth1 proto 112 -c 10'

Fix / harden

  • Ensure single L2 domain for the VRID
  • BFD or link tracking to uplinks (advanced) so a “master” without upstream demotes
  • Monitoring on “two masters seen” is an ops smell

Drill 3 — Priority change live

docker exec -it clab-vrrp-edge-r2 vtysh
configure terminal
interface eth1
 vrrp 1 priority 250
end
write

Predict

If preempt allowed, r2 becomes Master; h1 may re-ARP; path to upstream shifts to r2’s uplink.

Observe

docker exec clab-vrrp-edge-r1 vtysh -c 'show vrrp'
docker exec clab-vrrp-edge-r2 vtysh -c 'show vrrp'
docker exec clab-vrrp-edge-h1 traceroute -n 172.16.2.2

Revert priorities in git-mounted configs after the experiment.

Return path and asymmetric edges

VIP failover only moves the outbound first hop. If upstream routing always returns via r1 while r2 is master, you get asymmetric paths or blackholes. Pair FHRP with:

  • Shared upstream design, or
  • Dynamic routing so return traffic follows the active edge, or
  • State-aware NAT only on the active path (harder—prefer avoid state at edge in labs first)

Verification checklist

Check Intent
show vrrp One Master per VRID on the LAN
Host default route Points at VIP only
ping VIP L2/L3 ownership of first hop
Kill master Backup promotes; host recovers
Capture proto 112 Hellos present on LAN
Upstream ping during fail Data plane + return path

verify.sh sketch

#!/usr/bin/env bash
set -euo pipefail
fail() { echo "FAIL: $*" >&2; exit 1; }

docker exec clab-vrrp-edge-h1 ping -c 2 -W 1 10.10.10.254 || fail "VIP"
# Exactly one master is harder in shell—parse show vrrp or accept soft check:
docker exec clab-vrrp-edge-r1 vtysh -c 'show vrrp' | grep -qi master \
  || docker exec clab-vrrp-edge-r2 vtysh -c 'show vrrp' | grep -qi master \
  || fail "no master"
echo OK

Common mistakes

Mistake Symptom
Routers not same L2 domain Never form master/backup correctly
Different VRID or VIP Two independent groups
Host points at real IP not VIP No redundancy
No return routes via backup Failover pings die mid-path
Priority tie without tie-break awareness Unstable election
Forgetting to enable vrrp daemon Empty show vrrp

Optional SR Linux note (community)

SR Linux community Containerlab kinds expose interface and IRP/FHRP-related configuration in a different tree (YANG/CLI). Do not memorize CLI here—map objects: VIP, group id, priority, interface, preempt. Same predict→observe drills.

Summary

  • Hosts need a stable first hop; VRRP-class protocols move a VIP between routers
  • FRR + Containerlab is enough to learn Master/Backup, preempt, and failure timers
  • Always verify host ARP, VRRP state, and end-to-end path after failover
  • FHRP is not multihoming policy—combine later with dual-home BGP/statics
  • Keep configs in binds; promote live priority experiments back to git

Next: DHCP relay and NAT—how edge services attach to this LAN model without becoming mysterious middleboxes.