TTR Networks

Advanced · EVPN and VXLAN: layer 2 over a routed fabric · section 6 of 6

Build the lab yourself

✓ Lab-tested 18 October 2026 on FRR 10.2.1

Three FRR containers (with tcpdump added). The hosts are network namespaces inside each leaf container, plugged into the leaf's bridge with a veth pair, so no Docker network is ever part of a bridge (that combination causes broadcast storms in Docker). Put FRR's daemons file (bgpd=yes) next to these files, then follow the compose file's comments. The root@host1 prompts are ip netns exec host1 … inside leaf1.

lab-compose.yaml
# Needs ./daemons (copy /etc/frr/daemons out of the FRR image, set bgpd=yes). Then:
#   docker compose up -d --build
#   docker compose exec leaf1 vxlan-setup.sh 10.0.0.11 host1 10.100.0.1/24 02:00:00:00:01:01
#   docker compose exec leaf2 vxlan-setup.sh 10.0.0.12 host2 10.100.0.2/24 02:00:00:00:02:02
# leaf2.conf is leaf1.conf with "1" -> "2" in the addresses and AS65002.
name: evpn-lab
x-frr: &frr
  build:
    dockerfile_inline: |
      FROM quay.io/frrouting/frr:10.2.1
      RUN apk add --no-cache tcpdump
  privileged: true
services:
  spine:
    <<: *frr
    volumes: ["./daemons:/etc/frr/daemons:ro", "./spine.conf:/etc/frr/frr.conf"]
    networks: { s-l1: { interface_name: eth0 }, s-l2: { interface_name: eth1 } }
  leaf1:
    <<: *frr
    volumes: ["./daemons:/etc/frr/daemons:ro", "./leaf1.conf:/etc/frr/frr.conf", "./vxlan-setup.sh:/usr/local/bin/vxlan-setup.sh:ro"]
    networks: { s-l1: { interface_name: eth0 } }
  leaf2:
    <<: *frr
    volumes: ["./daemons:/etc/frr/daemons:ro", "./leaf2.conf:/etc/frr/frr.conf", "./vxlan-setup.sh:/usr/local/bin/vxlan-setup.sh:ro"]
    networks: { s-l2: { interface_name: eth0 } }
networks:
  s-l1: { enable_ipv4: false, enable_ipv6: true, ipam: { config: [{ subnet: "fd00:80::/64" }] } }
  s-l2: { enable_ipv4: false, enable_ipv6: true, ipam: { config: [{ subnet: "fd00:81::/64" }] } }
  • Lines 1–5: Start, then create the VNI and a host on each leaf.
  • Lines 14–17: The spine, linked to both leaves.
  • Lines 18–25: The leaves.
leaf2.conf (FRR)
frr defaults traditional
hostname leaf2
!
interface eth0
 ip address 10.1.2.1/31
!
interface lo
 ip address 10.0.0.12/32
!
router bgp 65002
 bgp router-id 10.0.0.12
 no bgp ebgp-requires-policy
 neighbor 10.1.2.0 remote-as 65000
 neighbor 10.1.2.0 description spine
 !
 address-family ipv4 unicast
  network 10.0.0.12/32
 exit-address-family
 !
 address-family l2vpn evpn
  neighbor 10.1.2.0 activate
  advertise-all-vni
 exit-address-family
exit
!
  • Lines 10–11: leaf2: AS65002, loopback 10.0.0.12.

Where next

  • BGP on loopbacks vs interface addressesPrerequisite · Intermediate · 45 min

    Why BGP sessions between loopbacks survive link failures and use parallel links, and what they need to work: an IGP or static routes, update-source, the eBGP connected check, and BFD. Every failure is reproduced on two real VyOS routers.

  • Switching basics: layer 2, VLANs and IP addressingPrerequisite · Beginner · 40 min

    How a switch learns MAC addresses and floods broadcasts, how IP subnets and default gateways decide where packets go, how VLANs split a switch into separate networks, and how trunks and a router connect them. Built on a real switch, three PCs and a VyOS router.

  • BGP FundamentalsAlso covers BGP · Intermediate · 75 min

    How the Border Gateway Protocol glues the internet together: autonomous systems, sessions, path attributes, best-path selection, iBGP scaling and a hands-on eBGP lab with real FRR configuration.

  • Debugging BGP: every session state, reproducedAlso covers BGP · Intermediate · 60 min

    Break a working BGP lab a dozen ways and learn to read each failure: Idle, Connect, Active and OpenSent, max-prefix, firewalls, wrong AS, TTL, hold timers, missing policy and unreachable next hops, all with real FRR output and packet captures.