Classroom Glossary Public page

Lab 11: VXLAN-EVPN Multi-Tenant Fabric in Containerlab

561 words

Chapter: 11 (Cloud Networking)
Duration: 90 minutes
Tools: Containerlab, FRRouting (EVPN), tcpdump, Wireshark
Points: 10


Objectives

  1. Deploy a 2-spine, 3-leaf Containerlab fabric with eBGP underlay
  2. Configure VXLAN VNI 100 overlay on leaf1 and leaf2
  3. Enable EVPN address-family to advertise MAC/IP routes
  4. Verify MAC learning without flooding via BGP EVPN Type 2 routes
  5. Capture VXLAN-encapsulated traffic on spine links

Topology

        spine1 (AS 65100)    spine2 (AS 65100)
        /    \               /    \
      leaf1   leaf2        leaf1   leaf2
     (65001) (65002)      (65001) (65002)
       |                    |
      host1                host2

leaf1 and leaf2 are in the overlay; leaf3 is connected to spines but not configured for EVPN in this lab.


Setup

# topo-evpn.clab.yml
name: evpn
topology:
  nodes:
    spine1:
      kind: linux
      image: frrouting/frr:latest
    spine2:
      kind: linux
      image: frrouting/frr:latest
    leaf1:
      kind: linux
      image: frrouting/frr:latest
    leaf2:
      kind: linux
      image: frrouting/frr:latest
    leaf3:
      kind: linux
      image: frrouting/frr:latest
    host1:
      kind: linux
      image: alpine:latest
    host2:
      kind: linux
      image: alpine:latest
  links:
    - endpoints: ["leaf1:eth1", "spine1:eth1"]
    - endpoints: ["leaf1:eth2", "spine2:eth1"]
    - endpoints: ["leaf2:eth1", "spine1:eth2"]
    - endpoints: ["leaf2:eth2", "spine2:eth2"]
    - endpoints: ["leaf3:eth1", "spine1:eth3"]
    - endpoints: ["leaf3:eth2", "spine2:eth3"]
    - endpoints: ["host1:eth1", "leaf1:eth3"]
    - endpoints: ["host2:eth1", "leaf2:eth3"]
containerlab deploy -t topo-evpn.clab.yml

Part 1: eBGP Underlay Configuration (25 min)

Configure eBGP underlay on all leaf-spine links (each leaf has its own AS; spines share AS 65100):

# Spine1 (AS 65100)
docker exec -it clab-evpn-spine1 vtysh <<'EOF'
configure terminal
interface eth1
 ip address 10.0.11.0/31
interface eth2
 ip address 10.0.21.0/31
interface eth3
 ip address 10.0.31.0/31
interface lo
 ip address 10.255.255.100/32
router bgp 65100
 bgp router-id 10.255.255.100
 no bgp ebgp-requires-policy
 neighbor LEAVES peer-group
 neighbor LEAVES send-community both
 neighbor 10.0.11.1 peer-group LEAVES
 neighbor 10.0.11.1 remote-as 65001
 neighbor 10.0.21.1 peer-group LEAVES
 neighbor 10.0.21.1 remote-as 65002
 neighbor 10.0.31.1 peer-group LEAVES
 neighbor 10.0.31.1 remote-as 65003
 address-family ipv4 unicast
  redistribute connected
 exit-address-family
EOF

Configure spine2 analogously (AS 65100, different IP block: 10.0.12.0/31, 10.0.22.0/31, 10.0.32.0/31).

# Leaf1 (AS 65001)
docker exec -it clab-evpn-leaf1 vtysh <<'EOF'
configure terminal
interface eth1
 ip address 10.0.11.1/31
interface eth2
 ip address 10.0.12.1/31
interface lo
 ip address 10.255.255.1/32
router bgp 65001
 bgp router-id 10.255.255.1
 no bgp ebgp-requires-policy
 neighbor SPINES peer-group
 neighbor SPINES remote-as 65100
 neighbor SPINES send-community both
 neighbor 10.0.11.0 peer-group SPINES
 neighbor 10.0.12.0 peer-group SPINES
 address-family ipv4 unicast
  redistribute connected
  maximum-paths 2
 exit-address-family
EOF

Verify underlay routing:

docker exec clab-evpn-leaf1 vtysh -c "show ip bgp summary"
docker exec clab-evpn-leaf1 vtysh -c "show ip route"
# Should see routes to leaf2 loopback via both spines (ECMP)

Record:

  1. Are all BGP sessions in leaf1's show ip bgp summary Established?
  2. How many paths does leaf1 have to leaf2's loopback (10.255.255.2/32)?

Part 2: VXLAN Overlay and EVPN Configuration (25 min)

# Leaf1: configure VXLAN and EVPN
docker exec -it clab-evpn-leaf1 vtysh <<'EOF'
configure terminal
interface vxlan100
 vxlan id 100
 vxlan local-tunnelip 10.255.255.1
 vxlan remoteip 10.255.255.2
 vxlan dstport 4789
router bgp 65001
 address-family l2vpn evpn
  neighbor SPINES activate
  advertise-all-vni
 exit-address-family
EOF

Create the VXLAN interface in the kernel and add it to a bridge with the host-facing port:

docker exec clab-evpn-leaf1 bash -c "
  ip link add vxlan100 type vxlan id 100 dstport 4789 local 10.255.255.1
  ip link set vxlan100 up
  ip link add br100 type bridge
  ip link set vxlan100 master br100
  ip link set eth3 master br100
  ip link set br100 up"

Repeat on leaf2 (local tunnelip 10.255.255.2; remoteip 10.255.255.1).

Configure hosts:

docker exec clab-evpn-host1 ip addr add 10.100.0.1/24 dev eth1
docker exec clab-evpn-host2 ip addr add 10.100.0.2/24 dev eth1

Part 3: EVPN Route Verification (15 min)

# Check EVPN routes on leaf1 after host1 has sent some traffic
docker exec clab-evpn-host1 arping -c 3 10.100.0.2

# On leaf1: check EVPN MAC/IP routes (Type 2)
docker exec clab-evpn-leaf1 vtysh -c "show bgp l2vpn evpn"
docker exec clab-evpn-leaf1 vtysh -c "show bgp l2vpn evpn route type 2"
docker exec clab-evpn-leaf1 vtysh -c "show evpn vni"
docker exec clab-evpn-leaf1 vtysh -c "show evpn mac vni 100"

Record:

  1. What BGP EVPN route type(s) appear after the arping?
  2. Does leaf1 see host2's MAC address via a Type 2 EVPN route from leaf2?
  3. What is the next-hop for the EVPN routes? (Should be leaf2's VTEP IP: 10.255.255.2)

Part 4: VXLAN Capture and Encapsulation Analysis (15 min)

# Capture on spine1's eth1 (leaf1 uplink) during host-to-host ping
docker exec clab-evpn-spine1 tcpdump -i eth1 -n \
  "udp port 4789" -w /tmp/vxlan_capture.pcap &

docker exec clab-evpn-host1 ping -c 5 10.100.0.2

docker exec clab-evpn-spine1 killall tcpdump 2>/dev/null
docker cp clab-evpn-spine1:/tmp/vxlan_capture.pcap /tmp/

Open in Wireshark. Display filter: vxlan

Examine the VXLAN frame structure:

  1. Outer Ethernet frame: src/dst MAC (should be leaf1 and spine1 MACs)
  2. Outer IP header: src 10.255.255.1 (leaf1 VTEP), dst 10.255.255.2 (leaf2 VTEP)
  3. UDP header: src port (random), dst port 4789
  4. VXLAN header: VNI field should show 100
  5. Inner Ethernet frame: src/dst MAC of host1 and host2

Record:

  1. What is the VNI value in the VXLAN header?
  2. What are the outer IP source and destination addresses?
  3. What are the inner Ethernet source and destination MAC addresses?
  4. How many bytes of overhead does VXLAN encapsulation add to the original Ethernet frame?

Part 5: ECMP Verification (10 min)

# Generate traffic and observe both spines are used
# (ECMP hash will distribute flows across spine1 and spine2)
docker exec clab-evpn-spine1 tcpdump -i eth1 -n -c 20 "udp port 4789" &
docker exec clab-evpn-spine2 tcpdump -i eth1 -n -c 20 "udp port 4789" &

for i in $(seq 1 50); do
  docker exec clab-evpn-host1 ping -c 1 -s $((i * 10)) 10.100.0.2 &
done
wait

docker exec clab-evpn-spine1 killall tcpdump 2>/dev/null
docker exec clab-evpn-spine2 killall tcpdump 2>/dev/null

Record:

  1. Did both spine1 and spine2 capture VXLAN traffic?
  2. What determines which flows go via spine1 vs. spine2? (Hint: ECMP hash inputs)
  3. What happens to existing VXLAN sessions if spine1 goes down?
# Simulate spine1 failure
docker exec clab-evpn-leaf1 ip link set eth1 down
docker exec clab-evpn-host1 ping -c 10 10.100.0.2
docker exec clab-evpn-leaf1 ip link set eth1 up

Lab Report

  1. Explain how EVPN eliminates the need for BUM (Broadcast/Unknown unicast/Multicast) flooding in a VXLAN fabric. What BGP EVPN route type is responsible?
  2. In the VXLAN capture, the inner Ethernet frame (host1's original packet) is completely unchanged by the encapsulation process. What property of VXLAN makes it transparent to the hosts?
  3. The leaf-spine fabric uses eBGP with a separate AS per leaf. Why is this preferred over running iBGP or OSPF as the underlay? (Hint: think about failure isolation and ECMP.)

Cleanup

containerlab destroy -t topo-evpn.clab.yml

Grading (10 points)

Item Points
eBGP underlay: all sessions Established; ECMP routes to leaf2 verified 2
EVPN: Type 2 MAC/IP routes propagated between leaf1 and leaf2 3
VXLAN capture: VNI, outer/inner headers correctly identified 3
Lab report: BUM elimination; transparency; eBGP underlay rationale 2