diff --git a/README.md b/README.md index 57b107e..5f94966 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,23 @@ -# Arista EVPN-VXLAN ContainerLab +# Arista EVPN-VXLAN ContainerLab β€” DC + Core + Campus -A production-ready Arista BGP EVPN-VXLAN data center fabric topology using ContainerLab and cEOS. +An extended Arista BGP EVPN-VXLAN multi-fabric lab using ContainerLab and cEOS. The topology interconnects a **Data Center fabric** and a **Campus fabric** through a dedicated **Core L3 transit zone**, with a VRF (`gold`) stretched end-to-end across both fabrics. ## 🎯 Overview -This lab demonstrates a complete 3-tier EVPN-VXLAN data center fabric with: +| Zone | Devices | +| ------ | --------------------------------------------------------------------------------------- | +| DC | 2 spines, 8 leafs (4 MLAG VTEPs), 2 border leafs (MLAG), 4 access switches, 4 hosts | +| Core | 2 core routers (iBGP AS 65500, OSPF underlay with BLs, eBGP to DC & Campus BLs) | +| Campus | 2 spines, 4 leafs (2 MLAG VTEPs), 2 border leafs (MLAG), 2 access switches, 2 hosts | -- **2 Spine switches** (BGP Route Reflectors) -- **8 Leaf switches** forming 4 VTEPs (MLAG pairs) -- **4 Access switches** (L2-only, dual-homed to leaf MLAG pairs) -- **BGP EVPN overlay** with L2/L3 VXLAN -- **MLAG configuration** for high availability -- **Test hosts** for validation +Key design choices: + +- **eBGP** in both fabrics (underlay + EVPN overlay) between spines and leafs / border leafs. +- **OSPF area 0 + eBGP multi-hop** between each Border Leaf pair and both Core routers (over dot1q subinterfaces: `.100` = default VRF underlay, `.200` = VRF `gold`). +- **MLAG** everywhere there is dual-homing (leaf pairs, border-leaf pairs, access β†’ leafs, host β†’ access). +- **VRF `gold`** is stretched end-to-end: DC leafs (VLAN 34 / 78) ↔ DC-BL ↔ Core ↔ Campus-BL ↔ Campus leafs (VLAN 60 / 70), all sharing L3 VNI `100001`. +- **VLAN 50** is a campus-local L2 VXLAN stretched between the two Campus VTEPs. +- **Convention**: L2 VNI = `110000 + vlan_id`, L3 VNI = `100001` for VRF `gold`, RT `1:100001` in both fabrics. ## πŸ“ Topology @@ -21,284 +27,323 @@ This lab demonstrates a complete 3-tier EVPN-VXLAN data center fabric with: ### Prerequisites -- ContainerLab installed -- Docker installed +- ContainerLab +- Docker - Arista cEOS image: `ceos:4.35.0` ### Deploy the Lab ```bash -# Clone the repository git clone https://gitea.arnodo.fr/Damien/arista-evpn-vxlan-clab.git cd arista-evpn-vxlan-clab -# Deploy the topology sudo containerlab deploy -t evpn-lab.clab.yml - -# Check status sudo containerlab inspect -t evpn-lab.clab.yml ``` ### Access Devices ```bash -# SSH to any device (password: admin) +# SSH (password: admin) β€” works for every cEOS node ssh admin@clab-arista-evpn-fabric-leaf1 +ssh admin@clab-arista-evpn-fabric-core1 +ssh admin@clab-arista-evpn-fabric-campus-leaf1 -# Or use docker exec -docker exec -it clab-arista-evpn-fabric-leaf1 Cli +# Or via docker exec +docker exec -it clab-arista-evpn-fabric-border-leaf-dc1 Cli ``` -## πŸ“‹ Configuration Details +## πŸ“‹ Architecture -### AS Numbers +### Node Inventory -- **Spine**: AS 65000 -- **VTEP1 (Leaf1/2)**: AS 65001 -- **VTEP2 (Leaf3/4)**: AS 65002 -- **VTEP3 (Leaf5/6)**: AS 65003 -- **VTEP4 (Leaf7/8)**: AS 65004 +| Zone | Role | Nodes | AS | +| ------ | ----------------------- | ------------------------------------------------------ | ------ | +| DC | Spine | `spine1`, `spine2` | 65000 | +| DC | Leaf VTEP1 (MLAG) | `leaf1`, `leaf2` | 65001 | +| DC | Leaf VTEP2 (MLAG) | `leaf3`, `leaf4` | 65002 | +| DC | Leaf VTEP3 (MLAG) | `leaf5`, `leaf6` | 65003 | +| DC | Leaf VTEP4 (MLAG) | `leaf7`, `leaf8` | 65004 | +| DC | Border Leaf (MLAG) | `border-leaf-dc1`, `border-leaf-dc2` | 65005 | +| DC | Access (L2-only) | `access1`-`access4` | β€” | +| DC | Host | `host1`-`host4` | β€” | +| Core | Core router | `core1`, `core2` | 65500 | +| Campus | Spine | `campus-spine1`, `campus-spine2` | 66000 | +| Campus | Leaf VTEP1 (MLAG) | `campus-leaf1`, `campus-leaf2` | 66001 | +| Campus | Leaf VTEP2 (MLAG) | `campus-leaf3`, `campus-leaf4` | 66002 | +| Campus | Border Leaf (MLAG) | `border-leaf-campus1`, `border-leaf-campus2` | 66005 | +| Campus | Access (L2-only) | `campus-access1`, `campus-access2` | β€” | +| Campus | Host | `campus-host1`, `campus-host2` | β€” | + +### AS Numbering + +| AS | Role | +| ----- | ---------------------------------- | +| 65000 | DC Spine | +| 65001 | DC VTEP1 (leaf1/2) | +| 65002 | DC VTEP2 (leaf3/4) | +| 65003 | DC VTEP3 (leaf5/6) | +| 65004 | DC VTEP4 (leaf7/8) | +| 65005 | DC Border Leaf pair | +| 65500 | Core (iBGP between core1 & core2) | +| 66000 | Campus Spine | +| 66001 | Campus VTEP1 (campus-leaf1/2) | +| 66002 | Campus VTEP2 (campus-leaf3/4) | +| 66005 | Campus Border Leaf pair | ### Access Switches -| Access Switch | Uplink Leaf Pair | VLAN(s) | Connected Host | -| ------------- | ---------------- | ------- | -------------- | -| access1 | Leaf1/2 (VTEP1) | 40 | host1 | -| access2 | Leaf3/4 (VTEP2) | 34 | host2 | -| access3 | Leaf5/6 (VTEP3) | 40 | host3 | -| access4 | Leaf7/8 (VTEP4) | 78 | host4 | +| Access Switch | Uplink Pair | VLANs | Host | +| --------------- | ------------------------ | -------- | -------------- | +| access1 | leaf1/2 (VTEP1) | 40 | host1 | +| access2 | leaf3/4 (VTEP2) | 34 | host2 | +| access3 | leaf5/6 (VTEP3) | 40 | host3 | +| access4 | leaf7/8 (VTEP4) | 78 | host4 | +| campus-access1 | campus-leaf1/2 (VTEP1) | 50, 60 | campus-host1 | +| campus-access2 | campus-leaf3/4 (VTEP2) | 50, 70 | campus-host2 | -- L2-only switches with LACP uplinks (Port-Channel 10) to leaf MLAG pairs -- Host-facing downlinks via LACP (Port-Channel 1) -- STP mode MSTP with edge-port BPDU guard +All access switches are L2-only, LACP-bonded to their leaf MLAG pair via `Port-Channel10`, with host downlinks on `Port-Channel1`. MSTP + edge-port BPDU guard. -### IP Addressing +## 🧭 IP Addressing Plan -#### Management Network +### Management (`172.16.0.0/24`) -- Subnet: `172.16.0.0/24` -- Spine1: `172.16.0.1` -- Spine2: `172.16.0.2` -- Leaf1: `172.16.0.25`, Leaf2: `172.16.0.50`, Leaf3-8: `172.16.0.27-32` -- Access1-4: `172.16.0.41-44` +| Node | IP | Node | IP | +| ------------------------- | --------------- | ------------------------- | --------------- | +| spine1 | 172.16.0.1 | campus-spine1 | 172.16.0.20 | +| spine2 | 172.16.0.2 | campus-spine2 | 172.16.0.21 | +| border-leaf-dc1 | 172.16.0.3 | border-leaf-campus1 | 172.16.0.22 | +| border-leaf-dc2 | 172.16.0.4 | border-leaf-campus2 | 172.16.0.23 | +| core1 | 172.16.0.10 | campus-leaf1-4 | 172.16.0.51-54 | +| core2 | 172.16.0.11 | campus-access1 | 172.16.0.61 | +| leaf1 | 172.16.0.25 | campus-access2 | 172.16.0.62 | +| leaf2 | 172.16.0.50 | host1-4 | 172.16.0.101-104| +| leaf3-8 | 172.16.0.27-32 | campus-host1 | 172.16.0.105 | +| access1-4 | 172.16.0.41-44 | campus-host2 | 172.16.0.106 | -#### Loopback Interfaces +Gateway: `172.16.0.254`. -- **Router-ID Loopbacks (Lo0)**: `10.0.250.0/24` - - Spine1: `10.0.250.1/32` - - Spine2: `10.0.250.2/32` - - Leaf1-8: `10.0.250.11-18/32` +### Router-ID Loopback0 (`Lo0`) -- **VTEP Loopbacks (Lo1)**: `10.0.255.0/24` - - VTEP1: `10.0.255.11/32` - - VTEP2: `10.0.255.12/32` - - VTEP3: `10.0.255.13/32` - - VTEP4: `10.0.255.14/32` +| Zone | Range | Nodes | +| ------ | ------------------- | --------------------------------------------------------------------- | +| DC | `10.0.250.0/24` | spine1 .1, spine2 .2, leaf1-8 .11-.18, BL-dc1 .21, BL-dc2 .22 | +| Core | `10.0.200.0/24` | core1 `10.0.200.1`, core2 `10.0.200.2` | +| Campus | `10.1.250.0/24` | campus-spine1 .1, campus-spine2 .2, campus-leaf1-4 .11-.14, BL-campus1 .21, BL-campus2 .22 | -#### Underlay P2P Links +### VTEP Loopback1 (`Lo1`) β€” shared per MLAG pair -- Spine1 to Leafs: `10.0.1.0/31`, `10.0.1.2/31`, ... `10.0.1.14/31` -- Spine2 to Leafs: `10.0.2.0/31`, `10.0.2.2/31`, ... `10.0.2.14/31` -- MLAG iBGP peering: `10.0.3.0/31`, `10.0.3.2/31`, `10.0.3.4/31`, `10.0.3.6/31` +| Fabric | VTEP | Address | Leafs | +| ------ | ------ | --------------- | ---------------------- | +| DC | VTEP1 | `10.0.255.11` | leaf1, leaf2 | +| DC | VTEP2 | `10.0.255.12` | leaf3, leaf4 | +| DC | VTEP3 | `10.0.255.13` | leaf5, leaf6 | +| DC | VTEP4 | `10.0.255.14` | leaf7, leaf8 | +| DC | BL | `10.0.255.15` | border-leaf-dc1/2 | +| Campus | VTEP1 | `10.1.255.11` | campus-leaf1/2 | +| Campus | VTEP2 | `10.1.255.12` | campus-leaf3/4 | +| Campus | BL | `10.1.255.21` | border-leaf-campus1/2 | -#### Host Network Addressing +### Underlay P2P (`/31`) -| Host | VLAN | VRF | IP Address | Gateway | Type | -| ----- | ---- | ------- | --------------- | ---------- | -------- | -| host1 | 40 | default | 10.40.40.101/24 | - | L2 VXLAN | -| host2 | 34 | gold | 10.34.34.102/24 | 10.34.34.1 | L3 VXLAN | -| host3 | 40 | default | 10.40.40.103/24 | - | L2 VXLAN | -| host4 | 78 | gold | 10.78.78.104/24 | 10.78.78.1 | L3 VXLAN | +| Segment | Subnets | +| -------------------------------- | --------------------------------------- | +| DC spine1 ↔ leaf/BL | `10.0.1.0/31` … `10.0.1.18/31` | +| DC spine2 ↔ leaf/BL | `10.0.2.0/31` … `10.0.2.18/31` | +| DC MLAG iBGP SVIs (per pair) | `10.0.3.0/31`, `.2/31`, `.4/31`, `.6/31`, `.8/31` (BL) | +| DC MLAG peer-link SVIs | `10.0.199.240/31` … `10.0.199.246/31` | +| DC-BL ↔ Core (default, `.100`) | `10.0.4.0/31` .. `10.0.4.6/31` | +| DC-BL ↔ Core (VRF gold, `.200`) | `10.0.14.0/31` .. `10.0.14.6/31` | +| Campus-BL ↔ Core (default) | `10.0.5.0/31` .. `10.0.5.6/31` | +| Campus-BL ↔ Core (VRF gold) | `10.0.15.0/31` .. `10.0.15.6/31` | +| Core1 ↔ Core2 (default) | `10.0.200.128/31` | +| Core1 ↔ Core2 (VRF gold) | `10.0.200.130/31` | +| Campus spine1 ↔ leaf/BL | `10.1.1.0/31` … `10.1.1.10/31` | +| Campus spine2 ↔ leaf/BL | `10.1.2.0/31` … `10.1.2.10/31` | +| Campus MLAG iBGP SVIs | `10.1.3.0/31`, `.2/31`, `.4/31` | +| Campus MLAG peer-link SVIs | `10.1.199.250/31` … `10.1.199.254/31` | -**Notes:** +### Host Addressing -- Host1 and Host3 are in VLAN 40 (L2 VXLAN only) and can communicate at Layer 2 -- Host2 and Host4 are in VRF "gold" with different subnets, communicating via EVPN Type-5 routes (L3 VXLAN) -- All hosts use LACP bonding (802.3ad) with dual-homing to access switches -- Each access switch is dual-homed via LACP (Port-Channel) to a leaf MLAG pair +| Host | VLAN | VRF | IP / Mask | Gateway | Purpose | +| ------------- | ---- | -------- | ----------------- | ------------ | ------------------------------ | +| host1 | 40 | default | 10.40.40.101/24 | β€” | DC L2 stretched (VTEP1↔VTEP3) | +| host2 | 34 | gold | 10.34.34.102/24 | 10.34.34.1 | DC L3 VRF gold | +| host3 | 40 | default | 10.40.40.103/24 | β€” | DC L2 stretched | +| host4 | 78 | gold | 10.78.78.104/24 | 10.78.78.1 | DC L3 VRF gold | +| campus-host1 | 50 | default | 10.50.50.101/24 | β€” | Campus L2 stretched (VTEP1↔VTEP2) | +| campus-host1 | 60 | gold | 10.60.60.101/24 | 10.60.60.1 | Campus L3 VRF gold | +| campus-host2 | 50 | default | 10.50.50.102/24 | β€” | Campus L2 stretched | +| campus-host2 | 70 | gold | 10.60.70.102/24 | 10.60.70.1 | Campus L3 VRF gold | -### VXLAN Network Identifiers (VNI) +## 🏷️ VXLAN Network Identifiers -#### L2 VNI (VLAN to VNI Mapping) +### L2 VNI Mapping -| VLAN | Description | VNI | VTEPs | Route Target | Route Distinguisher | -| ---- | ------------- | ------ | ------------------------------- | ------------ | -------------------------- | -| 40 | test-l2-vxlan | 110040 | VTEP1, VTEP3 (Leaf1/2, Leaf5/6) | 40:110040 | 65001:110040, 65003:110040 | +| VLAN | Description | VNI | Scope | RT | +| ---- | ------------------------------ | ------ | ------------------------------------------------------ | ---------- | +| 40 | DC L2 VXLAN (stretched) | 110040 | DC VTEP1 (leaf1/2) + VTEP3 (leaf5/6) | 40:110040 | +| 50 | Campus L2 VXLAN (stretched) | 110050 | Campus VTEP1 (campus-leaf1/2) + VTEP2 (campus-leaf3/4) | 50:110050 | +| 34 | DC VRF gold subnet (local) | 110034 | DC VTEP2 only (anycast GW 10.34.34.1) | 34:110034 | +| 78 | DC VRF gold subnet (local) | 110078 | DC VTEP4 only (anycast GW 10.78.78.1) | 78:110078 | +| 60 | Campus VRF gold subnet (local) | 110060 | Campus VTEP1 only (anycast GW 10.60.60.1) | 60:110060 | +| 70 | Campus VRF gold subnet (local) | 110070 | Campus VTEP2 only (anycast GW 10.60.70.1) | 70:110070 | -**L2 VNI Details:** +### L3 VNI Mapping (end-to-end) -- VLAN 40 is stretched across VTEP1 (Leaf1/2) and VTEP3 (Leaf5/6) for pure Layer 2 connectivity -- Hosts in VLAN 40 (host1 and host3) communicate at Layer 2 across the EVPN fabric -- EVPN Type-2 (MAC/IP) routes are used for MAC address learning and distribution +| VRF | L3 VNI | RT | Scope | +| ---- | ------- | ---------- | ----------------------------------------------------- | +| gold | 100001 | 1:100001 | DC VTEP2/VTEP4/DC-BL + Campus VTEP1/VTEP2/Campus-BL | -#### L3 VNI (VRF to VNI Mapping) +VRF `gold` is announced over EVPN Type-5 (IP prefix) inside each fabric, and **stitched by the Core** via eBGP IPv4 unicast in VRF gold (over the `.200` dot1q subinterfaces). L3 VNI `100001` is re-used end-to-end for symmetry; RT `1:100001` is consistent across both fabrics. -| VRF | Description | VNI | VTEPs | Route Target | VLANs | -| ---- | ------------------------------- | ------ | ------------------------------- | ------------ | ------ | -| gold | L3 VRF for inter-subnet routing | 100001 | VTEP2, VTEP4 (Leaf3/4, Leaf7/8) | 1:100001 | 34, 78 | +### Route Distinguisher Convention -**L3 VNI Details:** +- Leafs / BLs: `rd :1` for VRF gold; `rd :` per L2 VLAN (e.g. `65001:110040`, `66002:110050`). +- Cores: `rd :100001` for VRF gold (transit only β€” no EVPN, IPv4 unicast with `redistribute connected`). -- VRF "gold" uses VNI 100001 for Layer 3 VXLAN routing between different subnets -- VLAN 34 (10.34.34.0/24) on VTEP2 and VLAN 78 (10.78.78.0/24) on VTEP4 are both in VRF gold -- EVPN Type-5 (IP Prefix) routes are used for inter-subnet routing -- Each VTEP advertises its local subnets via EVPN, enabling routed connectivity between host2 and host4 +## πŸ”€ Control Plane Summary -#### VNI Summary - -| VNI Type | VNI | Purpose | EVPN Route Type | -| -------- | ------ | ----------------------------- | ------------------ | -| L2 VNI | 110040 | Layer 2 extension for VLAN 40 | Type-2 (MAC/IP) | -| L3 VNI | 100001 | Layer 3 routing for VRF gold | Type-5 (IP Prefix) | - -### Features Implemented - -βœ… **Underlay** - -- BGP IPv4 Unicast -- ECMP with 4 paths -- eBGP between Spine-Leaf -- iBGP between MLAG pairs - -βœ… **Overlay** - -- BGP EVPN address family -- VXLAN data plane -- EVPN Type-2 (MAC/IP routes) -- EVPN Type-5 (IP Prefix routes) - -βœ… **High Availability** - -- MLAG dual-homing -- Dual-active detection -- Anycast VTEP gateway +| Segment | Protocol | Notes | +| ----------------------------------- | ------------------------------------ | ------------------------------------- | +| DC spine ↔ leaf/BL underlay | eBGP IPv4 (AS 65000 ↔ 650xx) | `maximum-paths 4 ecmp 64` | +| DC spine ↔ leaf/BL overlay | eBGP EVPN via Loopback0, multi-hop 3 | Spines reflect via `ebgp peer-group` | +| DC MLAG pair iBGP | iBGP over VLAN 4091 SVI | `next-hop-self` | +| DC-BL ↔ Core (default) | OSPF area 0 + eBGP AS 65005 ↔ 65500 | on `.100` dot1q subinterface | +| DC-BL ↔ Core (VRF gold) | eBGP AS 65005 ↔ 65500 | on `.200` dot1q subinterface | +| Core1 ↔ Core2 (default) | OSPF area 0 + iBGP AS 65500 | via Loopback0 | +| Core1 ↔ Core2 (VRF gold) | iBGP AS 65500 | VRF-aware over `.200` subinterface | +| Campus-BL ↔ Core (default / gold) | OSPF + eBGP AS 66005 ↔ 65500 | same pattern as DC-BL | +| Campus spine ↔ leaf/BL underlay | eBGP IPv4 (AS 66000 ↔ 660xx) | | +| Campus spine ↔ leaf/BL overlay | eBGP EVPN via Loopback0, multi-hop 3 | | +| Campus MLAG pair iBGP | iBGP over VLAN 4091 SVI | | ## πŸ§ͺ Testing & Validation -### Verify BGP EVPN Neighbors +### Fabric health ```bash -# On any spine -show bgp evpn summary +# DC +ssh admin@clab-arista-evpn-fabric-spine1 "show bgp evpn summary" +ssh admin@clab-arista-evpn-fabric-leaf3 "show bgp evpn summary" +ssh admin@clab-arista-evpn-fabric-border-leaf-dc1 "show bgp evpn summary" -# On any leaf -show bgp evpn summary +# Campus +ssh admin@clab-arista-evpn-fabric-campus-spine1 "show bgp evpn summary" +ssh admin@clab-arista-evpn-fabric-campus-leaf1 "show bgp evpn summary" + +# Core transit (no EVPN β€” IPv4 only) +ssh admin@clab-arista-evpn-fabric-core1 "show ip bgp summary" +ssh admin@clab-arista-evpn-fabric-core1 "show ip bgp summary vrf gold" +ssh admin@clab-arista-evpn-fabric-core1 "show ip ospf neighbor" ``` -### Verify VXLAN +### VXLAN ```bash -# Check VXLAN interface +# On any leaf/BL show interface vxlan1 - -# Check remote VTEPs show vxlan vtep - -# Check VXLAN address table show vxlan address-table ``` -### Verify MLAG +### MLAG ```bash -# Check MLAG status show mlag - -# Check MLAG interfaces -show mlag interfaces +show mlag interfaces detail ``` -### Test Connectivity - -#### L2 VXLAN Testing (VLAN 40) - -Test Layer 2 connectivity between host1 and host3 across the EVPN fabric: +### Intra-DC connectivity (existing tests) ```bash -# From host1 to host3 (same VLAN 40, different VTEPs) -docker exec -it clab-arista-evpn-fabric-host1 ping -c 4 10.40.40.103 +# L2 VLAN 40: host1 ↔ host3 +docker exec -it clab-arista-evpn-fabric-host1 ping -c 3 10.40.40.103 -# Check host1 interface -docker exec -it clab-arista-evpn-fabric-host1 ip addr show bond0 - -# From host3 to host1 -docker exec -it clab-arista-evpn-fabric-host3 ping -c 4 10.40.40.101 +# L3 VRF gold (DC only): host2 ↔ host4 +docker exec -it clab-arista-evpn-fabric-host2 ping -c 3 10.78.78.104 ``` -#### L3 VXLAN Testing (VRF gold) - -Test Layer 3 connectivity between host2 and host4 in VRF "gold": +### Intra-Campus connectivity ```bash -# From host2 to host4 (different subnets via EVPN Type-5) -docker exec -it clab-arista-evpn-fabric-host2 ping -c 4 10.78.78.104 +# L2 VLAN 50: campus-host1 ↔ campus-host2 +docker exec -it clab-arista-evpn-fabric-campus-host1 ping -c 3 10.50.50.102 -# From host4 to host2 -docker exec -it clab-arista-evpn-fabric-host4 ping -c 4 10.34.34.102 - -# Check routing table on hosts -docker exec -it clab-arista-evpn-fabric-host2 ip route -docker exec -it clab-arista-evpn-fabric-host4 ip route +# L3 VRF gold (Campus only): campus-host1 ↔ campus-host2 +docker exec -it clab-arista-evpn-fabric-campus-host1 ping -c 3 10.60.70.102 +docker exec -it clab-arista-evpn-fabric-campus-host2 ping -c 3 10.60.60.101 ``` -#### Verify EVPN Routes on Switches +### End-to-end Campus ↔ DC (VRF gold via Core) ```bash -# Check EVPN Type-2 routes (MAC/IP) - for VLAN 40 -ssh admin@clab-arista-evpn-fabric-leaf1 -show bgp evpn route-type mac-ip +# campus-host1 (10.60.60.101, VRF gold Campus) β†’ host2 (10.34.34.102, VRF gold DC) +docker exec -it clab-arista-evpn-fabric-campus-host1 ping -c 3 10.34.34.102 -# Check EVPN Type-5 routes (IP Prefix) - for VRF gold -ssh admin@clab-arista-evpn-fabric-leaf3 -show bgp evpn route-type ip-prefix ipv4 +# campus-host2 (10.60.70.102) β†’ host4 (10.78.78.104) +docker exec -it clab-arista-evpn-fabric-campus-host2 ping -c 3 10.78.78.104 -# Verify VXLAN learned MACs -show vxlan address-table +# Reverse direction +docker exec -it clab-arista-evpn-fabric-host2 ping -c 3 10.60.60.101 +docker exec -it clab-arista-evpn-fabric-host4 ping -c 3 10.60.70.102 -# Check MAC addresses learned via EVPN -show mac address-table +# Traceroute: expected path campus-leaf β†’ campus-BL β†’ core β†’ DC-BL β†’ DC-leaf +docker exec -it clab-arista-evpn-fabric-campus-host1 traceroute 10.34.34.102 +``` + +### Inspect the Core transit path + +```bash +# Check VRF gold routes on core1 β€” both DC and Campus prefixes should be present +ssh admin@clab-arista-evpn-fabric-core1 "show ip route vrf gold" +ssh admin@clab-arista-evpn-fabric-core1 "show ip bgp vrf gold" + +# EVPN Type-5 on DC-BL (imported from DC fabric, redistributed from Core into EVPN) +ssh admin@clab-arista-evpn-fabric-border-leaf-dc1 "show bgp evpn route-type ip-prefix ipv4" + +# EVPN Type-5 on Campus-BL +ssh admin@clab-arista-evpn-fabric-border-leaf-campus1 "show bgp evpn route-type ip-prefix ipv4" ``` ## πŸ“ Repository Structure ``` arista-evpn-vxlan-clab/ -β”œβ”€β”€ README.md # This file -β”œβ”€β”€ TROUBLESHOOTING.md # Troubleshooting guide -β”œβ”€β”€ END_TO_END_TESTING.md # Testing procedures -β”œβ”€β”€ evpn-lab.clab.yml # ContainerLab topology +β”œβ”€β”€ README.md +β”œβ”€β”€ TROUBLESHOOTING.md +β”œβ”€β”€ END_TO_END_TESTING.md +β”œβ”€β”€ evpn-lab.clab.yml +β”œβ”€β”€ evpn-lab.clab.yml.annotations.json β”œβ”€β”€ assets/ -β”‚ └── arista-evpn-fabric.svg # Topology diagram -β”œβ”€β”€ configs/ # Device configurations -β”‚ β”œβ”€β”€ spine1.cfg -β”‚ β”œβ”€β”€ spine2.cfg -β”‚ β”œβ”€β”€ leaf1.cfg through leaf8.cfg -β”‚ β”œβ”€β”€ access1.cfg -β”‚ β”œβ”€β”€ access2.cfg -β”‚ β”œβ”€β”€ access3.cfg -β”‚ └── access4.cfg -└── hosts/ # Host interface configurations +β”‚ └── arista-evpn-fabric.svg +β”œβ”€β”€ configs/ +β”‚ β”œβ”€β”€ spine1.cfg, spine2.cfg +β”‚ β”œβ”€β”€ leaf1.cfg … leaf8.cfg +β”‚ β”œβ”€β”€ border-leaf-dc1.cfg, border-leaf-dc2.cfg +β”‚ β”œβ”€β”€ access1.cfg … access4.cfg +β”‚ β”œβ”€β”€ core1.cfg, core2.cfg +β”‚ β”œβ”€β”€ campus-spine1.cfg, campus-spine2.cfg +β”‚ β”œβ”€β”€ campus-leaf1.cfg … campus-leaf4.cfg +β”‚ β”œβ”€β”€ border-leaf-campus1.cfg, border-leaf-campus2.cfg +β”‚ └── campus-access1.cfg, campus-access2.cfg +└── hosts/ β”œβ”€β”€ README.md - β”œβ”€β”€ host1_interfaces - β”œβ”€β”€ host2_interfaces - β”œβ”€β”€ host3_interfaces - └── host4_interfaces + β”œβ”€β”€ host1_interfaces … host4_interfaces + β”œβ”€β”€ campus-host1_interfaces + └── campus-host2_interfaces ``` ## πŸ—‘οΈ Cleanup ```bash -# Destroy the lab -sudo containerlab destroy -t evpn-lab.clab.yml - -# Remove all related containers and networks sudo containerlab destroy -t evpn-lab.clab.yml --cleanup ``` ## πŸ“š References -- [Original Configuration Guide](https://overlaid.net/2019/01/27/arista-bgp-evpn-configuration-example/) - [Arista EOS Documentation](https://www.arista.com/en/support/product-documentation) - [ContainerLab Documentation](https://containerlab.dev/) -- [RFC 7432 - BGP MPLS-Based Ethernet VPN](https://tools.ietf.org/html/rfc7432) -- [RFC 8365 - A Network Virtualization Overlay Solution Using EVPN](https://tools.ietf.org/html/rfc8365) +- [RFC 7432 β€” BGP MPLS-Based Ethernet VPN](https://tools.ietf.org/html/rfc7432) +- [RFC 8365 β€” A Network Virtualization Overlay Solution Using EVPN](https://tools.ietf.org/html/rfc8365) +- [RFC 9135 β€” Integrated Routing and Bridging in EVPN](https://tools.ietf.org/html/rfc9135) diff --git a/assets/arista-evpn-fabric.svg b/assets/arista-evpn-fabric.svg index bf68ced..bfa42d7 100644 --- a/assets/arista-evpn-fabric.svg +++ b/assets/arista-evpn-fabric.svg @@ -1,389 +1,301 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - spine1 - - - - - - - - - - - - - - - - - - - - - spine2 - - - - - - - - - - - - - - - - - - - - - leaf1 - - - - - - - - - - - - - - - - - - - - - leaf2 - - - - - - - - - - - - - - - - - - - - - leaf3 - - - - - - - - - - - - - - - - - - - - - leaf4 - - - - - - - - - - - - - - - - - - - - - leaf5 - - - - - - - - - - - - - - - - - - - - - leaf6 - - - - - - - - - - - - - - - - - - - - - leaf7 - - - - - - - - - - - - - - - - - - - - - leaf8 - - - - - - - - - - - - - - - - - - - - - access1 - - - - - - - - - - - - - - - - - - - - - access2 - - - - - - - - - - - - - - - - - - - - - access3 - - - - - - - - - - - - - - - - - - - - - access4 - - - - - - - - - - - - - - - - - - - - - host1 - - - - - - - - - - - - - - - - - - - - - host2 - - - - - - - - - - - - - - - - - - - - - host3 - - - - - - - - - - - - - - - - - - - - - host4 \ No newline at end of file + + + + + + + Arista EVPN-VXLAN Campus + DC Fabric + Campus EVPN-VXLAN ↔ Core L3 (OSPF + BGP) ↔ DC EVPN-VXLAN + + + + CAMPUS FABRIC (AS 66000/66001/66002/66005) + + + + CORE L3 (AS 65500) + OSPF area 0 + iBGP + VRF gold transit + + + + DATACENTER FABRIC (AS 65000/65001-65004/65005) + + + + + + campus-spine1 + + campus-spine2 + + + + + + campus-leaf1 + + campus-leaf2 + + campus-leaf3 + + campus-leaf4 + + + + + + border-leaf-campus1 + + border-leaf-campus2 + + + + + + campus-access1 + + campus-access2 + + + + + + campus-host1 + + campus-host2 + + + + Route Reflectors (AS 66000) + VTEP1 (AS 66001) + VTEP2 (AS 66002) + Campus Border Leafs MLAG (AS 66005) + VLAN 50 (10.50.50.101) + VLAN 60 (10.60.60.101, gold) + VLAN 50 (10.50.50.102) + VLAN 70 (10.60.70.102, gold) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + core1 + + core2 + + + iBGP + OSPF + + + + + + + + + + + + + + + + + + spine1 + + spine2 + + + + + + leaf1 + + leaf2 + + leaf3 + + leaf4 + + leaf5 + + leaf6 + + leaf7 + + leaf8 + + + + + + border-leaf-dc1 + + border-leaf-dc2 + + + + + + access1 + + access2 + + access3 + + access4 + + + + + + host1 + + host2 + + host3 + + host4 + + + + Route Reflectors (AS 65000) + VTEP1 (65001) + VTEP2 (65002) + VTEP3 (65003) + VTEP4 (65004) + DC Border Leafs MLAG (AS 65005) + VLAN 40 + VLAN 34 (gold) + VLAN 40 + VLAN 78 (gold) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Legend + + Spine (RR) + + Leaf (VTEP) + + Border Leaf + + Core router + + Access L2 + + Host + + Fabric (underlay + EVPN) + + Core (OSPF+BGP / VRF gold) + + MLAG peer-link + L2 VNI 110040 (DC VLAN 40), 110050 (Campus VLAN 50); L3 VNI 100001 (VRF gold, shared) + + diff --git a/evpn-lab.clab.yml.annotations.json b/evpn-lab.clab.yml.annotations.json index 8984cba..ea51282 100644 --- a/evpn-lab.clab.yml.annotations.json +++ b/evpn-lab.clab.yml.annotations.json @@ -1,138 +1,79 @@ { - "freeTextAnnotations": [], + "freeTextAnnotations": [ + { + "id": "label-campus", + "position": { "x": -100, "y": 60 }, + "text": "CAMPUS FABRIC (AS 66000 / 66001 / 66002 / 66005)", + "fontSize": 16, + "color": "#2563eb" + }, + { + "id": "label-core", + "position": { "x": 1100, "y": 60 }, + "text": "CORE (AS 65500)", + "fontSize": 16, + "color": "#ea580c" + }, + { + "id": "label-dc", + "position": { "x": 1600, "y": 60 }, + "text": "DATA CENTER FABRIC (AS 65000 / 65001-4 / 65005)", + "fontSize": 16, + "color": "#16a34a" + } + ], "freeShapeAnnotations": [], "trafficRateAnnotations": [], "groupStyleAnnotations": [], "networkNodeAnnotations": [], "nodeAnnotations": [ - { - "id": "spine1", - "position": { - "x": 260, - "y": 160 - } - }, - { - "id": "spine2", - "position": { - "x": 740, - "y": 160 - } - }, - { - "id": "leaf1", - "position": { - "x": -60, - "y": 420 - } - }, - { - "id": "leaf2", - "position": { - "x": 100, - "y": 420 - } - }, - { - "id": "leaf3", - "position": { - "x": 260, - "y": 420 - } - }, - { - "id": "leaf4", - "position": { - "x": 420, - "y": 420 - } - }, - { - "id": "leaf5", - "position": { - "x": 580, - "y": 420 - } - }, - { - "id": "leaf6", - "position": { - "x": 740, - "y": 420 - } - }, - { - "id": "leaf7", - "position": { - "x": 920, - "y": 420 - } - }, - { - "id": "leaf8", - "position": { - "x": 1080, - "y": 420 - } - }, - { - "id": "host1", - "position": { - "x": 20, - "y": 680 - } - }, - { - "id": "host2", - "position": { - "x": 340, - "y": 680 - } - }, - { - "id": "host3", - "position": { - "x": 660, - "y": 680 - } - }, - { - "id": "host4", - "position": { - "x": 1000, - "y": 680 - } - }, - { - "id": "access4", - "position": { - "x": 1000, - "y": 540 - } - }, - { - "id": "access3", - "position": { - "x": 660, - "y": 520 - } - }, - { - "id": "access2", - "position": { - "x": 340, - "y": 520 - } - }, - { - "id": "access1", - "position": { - "x": 20, - "y": 520 - } - } + + { "id": "campus-spine1", "position": { "x": 120, "y": 160 } }, + { "id": "campus-spine2", "position": { "x": 420, "y": 160 } }, + + { "id": "campus-leaf1", "position": { "x": -60, "y": 400 } }, + { "id": "campus-leaf2", "position": { "x": 80, "y": 400 } }, + { "id": "campus-leaf3", "position": { "x": 240, "y": 400 } }, + { "id": "campus-leaf4", "position": { "x": 380, "y": 400 } }, + + { "id": "border-leaf-campus1", "position": { "x": 540, "y": 400 } }, + { "id": "border-leaf-campus2", "position": { "x": 680, "y": 400 } }, + + { "id": "campus-access1", "position": { "x": 40, "y": 540 } }, + { "id": "campus-access2", "position": { "x": 320, "y": 540 } }, + + { "id": "campus-host1", "position": { "x": 40, "y": 680 } }, + { "id": "campus-host2", "position": { "x": 320, "y": 680 } }, + + { "id": "core1", "position": { "x": 960, "y": 300 } }, + { "id": "core2", "position": { "x": 1180, "y": 300 } }, + + { "id": "border-leaf-dc1", "position": { "x": 1380, "y": 400 } }, + { "id": "border-leaf-dc2", "position": { "x": 1520, "y": 400 } }, + + { "id": "spine1", "position": { "x": 1800, "y": 160 } }, + { "id": "spine2", "position": { "x": 2280, "y": 160 } }, + + { "id": "leaf1", "position": { "x": 1660, "y": 400 } }, + { "id": "leaf2", "position": { "x": 1800, "y": 400 } }, + { "id": "leaf3", "position": { "x": 1940, "y": 400 } }, + { "id": "leaf4", "position": { "x": 2080, "y": 400 } }, + { "id": "leaf5", "position": { "x": 2220, "y": 400 } }, + { "id": "leaf6", "position": { "x": 2360, "y": 400 } }, + { "id": "leaf7", "position": { "x": 2500, "y": 400 } }, + { "id": "leaf8", "position": { "x": 2640, "y": 400 } }, + + { "id": "access1", "position": { "x": 1720, "y": 540 } }, + { "id": "access2", "position": { "x": 2000, "y": 540 } }, + { "id": "access3", "position": { "x": 2280, "y": 540 } }, + { "id": "access4", "position": { "x": 2560, "y": 540 } }, + + { "id": "host1", "position": { "x": 1720, "y": 680 } }, + { "id": "host2", "position": { "x": 2000, "y": 680 } }, + { "id": "host3", "position": { "x": 2280, "y": 680 } }, + { "id": "host4", "position": { "x": 2560, "y": 680 } } ], "edgeAnnotations": [], "aliasEndpointAnnotations": [], "viewerSettings": {} -} \ No newline at end of file +} diff --git a/hosts/README.md b/hosts/README.md index 44bdaac..0c62902 100644 --- a/hosts/README.md +++ b/hosts/README.md @@ -4,11 +4,18 @@ This directory contains network interface configuration files for Alpine Linux h ## Files +### DC hosts + - `host1_interfaces` - Configuration for host1 (VLAN 40, IP 10.40.40.101) - `host2_interfaces` - Configuration for host2 (VLAN 34, IP 10.34.34.102) - `host3_interfaces` - Configuration for host3 (VLAN 40, IP 10.40.40.103) - `host4_interfaces` - Configuration for host4 (VLAN 78, IP 10.78.78.104) +### Campus hosts + +- `campus-host1_interfaces` - Configuration for campus-host1 (VLAN 50 stretched L2 10.50.50.101, VLAN 60 VRF gold 10.60.60.101) +- `campus-host2_interfaces` - Configuration for campus-host2 (VLAN 50 stretched L2 10.50.50.102, VLAN 70 VRF gold 10.60.70.102) + ## Usage Each file is mounted to `/etc/network/interfaces` in its respective host container via ContainerLab's `binds` feature: