From 2da238e3aeef26dfe0a1b274536fc9d2e931c054 Mon Sep 17 00:00:00 2001 From: Damien Date: Sat, 18 Apr 2026 18:44:34 +0000 Subject: [PATCH] Update campus host attachment pattern to single-attached access --- README.md | 49 +++++++++++++++++++++++----------- assets/arista-evpn-fabric.svg | 16 +++++------ configs/campus-access1.cfg | 22 ++++----------- configs/campus-access2.cfg | 22 ++++----------- configs/campus-leaf1.cfg | 2 +- configs/campus-leaf2.cfg | 2 +- configs/campus-leaf3.cfg | 2 +- configs/campus-leaf4.cfg | 2 +- evpn-lab.clab.yml | 50 +++++++---------------------------- hosts/README.md | 45 ++++++++++++++++++++++++------- hosts/campus-host1_interfaces | 25 +++--------------- hosts/campus-host2_interfaces | 25 +++--------------- 12 files changed, 105 insertions(+), 157 deletions(-) diff --git a/README.md b/README.md index 5f94966..c775314 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,16 @@ 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). +- **MLAG** everywhere there is dual-homing at the fabric layers (leaf pairs, border-leaf pairs, access → leafs, and DC host → access). +- **Host attachment pattern**: + - **DC hosts** (servers) are **dual-homed via LACP** to an access switch — typical DC + server redundancy. + - **Campus hosts** (user endpoints: PC, phone, printer) are **single-attached** to a + Campus access switch via one plain Ethernet link. Redundancy lives at the access-switch + layer (the access switch itself is dual-homed via LACP to its leaf MLAG pair), not at + the host. - **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. +- **VLAN 50** remains defined as a campus-local L2 VXLAN stretched between the two Campus VTEPs (infrastructure-only, not wired to any host in the current topology). - **Convention**: L2 VNI = `110000 + vlan_id`, L3 VNI = `100001` for VRF `gold`, RT `1:100001` in both fabrics. ## 📐 Topology @@ -93,16 +100,23 @@ docker exec -it clab-arista-evpn-fabric-border-leaf-dc1 Cli ### Access Switches -| 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 | +| Access Switch | Uplink Pair | VLANs | Host | Host attachment | +| --------------- | ------------------------ | -------- | -------------- | ------------------------- | +| access1 | leaf1/2 (VTEP1) | 40 | host1 | LACP Po1 (dual-homed) | +| access2 | leaf3/4 (VTEP2) | 34 | host2 | LACP Po1 (dual-homed) | +| access3 | leaf5/6 (VTEP3) | 40 | host3 | LACP Po1 (dual-homed) | +| access4 | leaf7/8 (VTEP4) | 78 | host4 | LACP Po1 (dual-homed) | +| campus-access1 | campus-leaf1/2 (VTEP1) | 60 | campus-host1 | access port (single link) | +| campus-access2 | campus-leaf3/4 (VTEP2) | 70 | campus-host2 | access port (single link) | -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. +All access switches are L2-only, LACP-bonded to their leaf MLAG pair via `Port-Channel10`. MSTP + edge-port BPDU guard. + +Host-facing ports: + +- **DC access switches** run a `Port-Channel1` trunk (VLANs allowed per host) for a host + dual-homed in LACP (two physical links, one bond on the Linux side). +- **Campus access switches** use a plain `Ethernet3` in `switchport mode access` with + BPDU guard + portfast — the host connects with a single Ethernet link and no bonding. ## 🧭 IP Addressing Plan @@ -171,11 +185,12 @@ Gateway: `172.16.0.254`. | 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 | +> DC hosts are dual-homed in LACP over `bond0` with tagged VLAN sub-interfaces. +> Campus hosts are single-attached with one untagged `eth1` in a single access VLAN. + ## 🏷️ VXLAN Network Identifiers ### L2 VNI Mapping @@ -266,15 +281,17 @@ docker exec -it clab-arista-evpn-fabric-host2 ping -c 3 10.78.78.104 ### Intra-Campus connectivity -```bash -# L2 VLAN 50: campus-host1 ↔ campus-host2 -docker exec -it clab-arista-evpn-fabric-campus-host1 ping -c 3 10.50.50.102 +Campus hosts sit in VRF `gold` — use the L3 test to validate VTEP1↔VTEP2 via campus spines. +```bash # 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 ``` +> VLAN 50 (stretched L2 VXLAN) is still provisioned on the campus VTEPs as an +> infrastructure example but is not wired to any host in the current topology. + ### End-to-end Campus ↔ DC (VRF gold via Core) ```bash diff --git a/assets/arista-evpn-fabric.svg b/assets/arista-evpn-fabric.svg index bfa42d7..bd8210b 100644 --- a/assets/arista-evpn-fabric.svg +++ b/assets/arista-evpn-fabric.svg @@ -84,10 +84,10 @@ 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) + VLAN 60 (10.60.60.101, gold) + single-attached (access) + VLAN 70 (10.60.70.102, gold) + single-attached (access) @@ -116,11 +116,9 @@ - - - - - + + + diff --git a/configs/campus-access1.cfg b/configs/campus-access1.cfg index 1aae6b0..9518fff 100644 --- a/configs/campus-access1.cfg +++ b/configs/campus-access1.cfg @@ -15,9 +15,6 @@ management api gnmi username admin privilege 15 role network-admin secret sha512 $6$xQktFrbdeqEhVzLM$.1wOJB25nw2fqYaSXDu6y4mo6AP9hngMCFe2vGDl84hWoz00Q.4unoEBqspNI0HEoRz.OZhdBHqQv12KABf0B0 ! ! VLANs -vlan 50 - name test-l2-vxlan-campus -! vlan 60 name vrf-gold-campus-subnet1 ! @@ -41,25 +38,16 @@ interface Ethernet2 interface Port-Channel10 description uplink-to-campus-leaf-mlag switchport mode trunk - switchport trunk allowed vlan 50,60 + switchport trunk allowed vlan 60 no shutdown ! -! Host-facing downlink (Port-Channel 1) +! Host-facing access port (single-attached endpoint in VLAN 60) interface Ethernet3 description campus-host1 - channel-group 1 mode active -! -interface Ethernet4 - description campus-host1 - channel-group 1 mode active -! -interface Port-Channel1 - description campus-host1 - switchport mode trunk - switchport trunk allowed vlan 50,60 - port-channel lacp fallback timeout 5 - port-channel lacp fallback individual + switchport mode access + switchport access vlan 60 spanning-tree portfast + spanning-tree bpduguard enable no shutdown ! ! Default route for management diff --git a/configs/campus-access2.cfg b/configs/campus-access2.cfg index 700eb69..49f0996 100644 --- a/configs/campus-access2.cfg +++ b/configs/campus-access2.cfg @@ -15,9 +15,6 @@ management api gnmi username admin privilege 15 role network-admin secret sha512 $6$xQktFrbdeqEhVzLM$.1wOJB25nw2fqYaSXDu6y4mo6AP9hngMCFe2vGDl84hWoz00Q.4unoEBqspNI0HEoRz.OZhdBHqQv12KABf0B0 ! ! VLANs -vlan 50 - name test-l2-vxlan-campus -! vlan 70 name vrf-gold-campus-subnet2 ! @@ -41,25 +38,16 @@ interface Ethernet2 interface Port-Channel10 description uplink-to-campus-leaf-mlag switchport mode trunk - switchport trunk allowed vlan 50,70 + switchport trunk allowed vlan 70 no shutdown ! -! Host-facing downlink (Port-Channel 1) +! Host-facing access port (single-attached endpoint in VLAN 70) interface Ethernet3 description campus-host2 - channel-group 1 mode active -! -interface Ethernet4 - description campus-host2 - channel-group 1 mode active -! -interface Port-Channel1 - description campus-host2 - switchport mode trunk - switchport trunk allowed vlan 50,70 - port-channel lacp fallback timeout 5 - port-channel lacp fallback individual + switchport mode access + switchport access vlan 70 spanning-tree portfast + spanning-tree bpduguard enable no shutdown ! ! Default route for management diff --git a/configs/campus-leaf1.cfg b/configs/campus-leaf1.cfg index 29c5a10..a4ae61a 100644 --- a/configs/campus-leaf1.cfg +++ b/configs/campus-leaf1.cfg @@ -101,7 +101,7 @@ interface Ethernet1 interface Port-Channel1 description campus-access1 switchport mode trunk - switchport trunk allowed vlan 50,60 + switchport trunk allowed vlan 60 mlag 1 port-channel lacp fallback timeout 5 port-channel lacp fallback individual diff --git a/configs/campus-leaf2.cfg b/configs/campus-leaf2.cfg index 54ca2ec..dbf3683 100644 --- a/configs/campus-leaf2.cfg +++ b/configs/campus-leaf2.cfg @@ -101,7 +101,7 @@ interface Ethernet1 interface Port-Channel1 description campus-access1 switchport mode trunk - switchport trunk allowed vlan 50,60 + switchport trunk allowed vlan 60 mlag 1 port-channel lacp fallback timeout 5 port-channel lacp fallback individual diff --git a/configs/campus-leaf3.cfg b/configs/campus-leaf3.cfg index fbe98cd..1731d33 100644 --- a/configs/campus-leaf3.cfg +++ b/configs/campus-leaf3.cfg @@ -101,7 +101,7 @@ interface Ethernet1 interface Port-Channel1 description campus-access2 switchport mode trunk - switchport trunk allowed vlan 50,70 + switchport trunk allowed vlan 70 mlag 1 port-channel lacp fallback timeout 5 port-channel lacp fallback individual diff --git a/configs/campus-leaf4.cfg b/configs/campus-leaf4.cfg index 0a1a0da..59c6c27 100644 --- a/configs/campus-leaf4.cfg +++ b/configs/campus-leaf4.cfg @@ -101,7 +101,7 @@ interface Ethernet1 interface Port-Channel1 description campus-access2 switchport mode trunk - switchport trunk allowed vlan 50,70 + switchport trunk allowed vlan 70 mlag 1 port-channel lacp fallback timeout 5 port-channel lacp fallback individual diff --git a/evpn-lab.clab.yml b/evpn-lab.clab.yml index af88bec..91ce278 100644 --- a/evpn-lab.clab.yml +++ b/evpn-lab.clab.yml @@ -267,33 +267,19 @@ topology: mgmt-ipv4: 172.16.0.62 startup-config: configs/campus-access2.cfg - # Campus Hosts - dual-homed with LACP bonding + # Campus Hosts - single-attached to access switch (enterprise user endpoint pattern) campus-host1: kind: linux mgmt-ipv4: 172.16.0.105 image: ghcr.io/hellt/network-multitool cap-add: - NET_ADMIN + binds: + - hosts/campus-host1_interfaces:/etc/network/interfaces exec: - - ip link add bond0 type bond mode 802.3ad - - ip link set dev bond0 type bond xmit_hash_policy layer3+4 - - ip link set dev eth1 down - - ip link set dev eth2 down - - ip link set eth1 master bond0 - - ip link set eth2 master bond0 - ip link set dev eth1 up - - ip link set dev eth2 up - - ip link set dev bond0 type bond lacp_rate fast - - ip link set dev bond0 up - - ip link add link bond0 name bond0.50 type vlan id 50 - - ip link set bond0.50 up - - ip addr add 10.50.50.101/24 dev bond0.50 - - ip link add link bond0 name bond0.60 type vlan id 60 - - ip link set bond0.60 up - - ip addr add 10.60.60.101/24 dev bond0.60 - - ip route add 10.60.70.0/24 via 10.60.60.1 - - ip route add 10.34.34.0/24 via 10.60.60.1 - - ip route add 10.78.78.0/24 via 10.60.60.1 + - ip addr add 10.60.60.101/24 dev eth1 + - ip route add default via 10.60.60.1 campus-host2: kind: linux @@ -301,26 +287,12 @@ topology: image: ghcr.io/hellt/network-multitool cap-add: - NET_ADMIN + binds: + - hosts/campus-host2_interfaces:/etc/network/interfaces exec: - - ip link add bond0 type bond mode 802.3ad - - ip link set dev bond0 type bond xmit_hash_policy layer3+4 - - ip link set dev eth1 down - - ip link set dev eth2 down - - ip link set eth1 master bond0 - - ip link set eth2 master bond0 - ip link set dev eth1 up - - ip link set dev eth2 up - - ip link set dev bond0 type bond lacp_rate fast - - ip link set dev bond0 up - - ip link add link bond0 name bond0.50 type vlan id 50 - - ip link set bond0.50 up - - ip addr add 10.50.50.102/24 dev bond0.50 - - ip link add link bond0 name bond0.70 type vlan id 70 - - ip link set bond0.70 up - - ip addr add 10.60.70.102/24 dev bond0.70 - - ip route add 10.60.60.0/24 via 10.60.70.1 - - ip route add 10.34.34.0/24 via 10.60.70.1 - - ip route add 10.78.78.0/24 via 10.60.70.1 + - ip addr add 10.60.70.102/24 dev eth1 + - ip route add default via 10.60.70.1 links: # ===================================================== @@ -428,8 +400,6 @@ topology: - endpoints: ["campus-leaf3:eth1", "campus-access2:eth1"] - endpoints: ["campus-leaf4:eth1", "campus-access2:eth2"] - # Campus Host connections to access switches (dual-homed via LACP) + # Campus Host connections to access switches (single link, enterprise user endpoint) - endpoints: ["campus-access1:eth3", "campus-host1:eth1"] - - endpoints: ["campus-access1:eth4", "campus-host1:eth2"] - endpoints: ["campus-access2:eth3", "campus-host2:eth1"] - - endpoints: ["campus-access2:eth4", "campus-host2:eth2"] diff --git a/hosts/README.md b/hosts/README.md index 0c62902..1c8c7cb 100644 --- a/hosts/README.md +++ b/hosts/README.md @@ -13,8 +13,12 @@ This directory contains network interface configuration files for Alpine Linux h ### 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) +Campus hosts are **single-attached** to a Campus access switch (enterprise user endpoint +pattern — no LACP bond, no VLAN trunking on the host side). Each host sits in a single +access VLAN that maps to VRF `gold`. + +- `campus-host1_interfaces` - Configuration for campus-host1 (VLAN 60 VRF gold 10.60.60.101/24, GW 10.60.60.1) +- `campus-host2_interfaces` - Configuration for campus-host2 (VLAN 70 VRF gold 10.60.70.102/24, GW 10.60.70.1) ## Usage @@ -30,7 +34,9 @@ host1: ## Format -Files use Debian/Alpine ifupdown format with bonding and VLAN extensions: +Files use Debian/Alpine ifupdown format. + +### DC hosts (dual-homed via LACP to access switches) ``` auto lo @@ -50,20 +56,39 @@ iface bond0. inet static vlan-raw-device bond0 ``` +### Campus hosts (single-attached, no bonding, no VLAN tagging) + +``` +auto lo +iface lo inet loopback + +auto eth1 +iface eth1 inet static + address / + gateway +``` + ## Key Concepts -### LACP Bonding -- All hosts use **mode 4** (802.3ad LACP) bonding -- Dual-homed to MLAG leaf pairs for redundancy +### DC: LACP Bonding +- DC hosts use **mode 4** (802.3ad LACP) bonding +- Dual-homed to MLAG leaf pairs — typical for DC servers that need NIC-level redundancy - Requires matching LACP configuration on switches +### Campus: Single-attached user endpoints +- Campus hosts use a single `eth1` interface connected to an access port +- Redundancy is handled at the access-switch layer (the access switch is itself + dual-homed via LACP to the leaf MLAG pair), not at the host +- This matches the realistic enterprise pattern for PCs, phones, printers, etc. + ### VLAN Tagging -- Hosts handle VLAN tagging via sub-interfaces -- Format: `bond0.` (e.g., bond0.40, bond0.34, bond0.78) -- Switch ports are configured as trunks allowing specific VLANs +- DC hosts: VLAN tagging happens in the host via `bond0.` sub-interfaces + (e.g., bond0.40, bond0.34, bond0.78); switch ports are trunks +- Campus hosts: no tagging on the host; the access switch places untagged frames + into `switchport access vlan ` ### IP Addressing -- Static IP configuration on VLAN sub-interfaces +- Static IP configuration on the host interface (sub-interface for DC, `eth1` for Campus) - Subnet assignment based on VLAN ID pattern (e.g., VLAN 40 = 10.40.40.0/24) ## Modification diff --git a/hosts/campus-host1_interfaces b/hosts/campus-host1_interfaces index 9033698..984b20c 100644 --- a/hosts/campus-host1_interfaces +++ b/hosts/campus-host1_interfaces @@ -1,26 +1,7 @@ auto lo iface lo inet loopback -auto bond0 -iface bond0 inet manual - use bond - bond-slaves eth1 eth2 - bond-mode 802.3ad - bond-miimon 100 - bond-lacp-rate fast - up ip link set $IFACE up - -auto bond0.50 -iface bond0.50 inet static - address 10.50.50.101 - netmask 255.255.255.0 - vlan-raw-device bond0 - up ip link set $IFACE up - -auto bond0.60 -iface bond0.60 inet static - address 10.60.60.101 - netmask 255.255.255.0 +auto eth1 +iface eth1 inet static + address 10.60.60.101/24 gateway 10.60.60.1 - vlan-raw-device bond0 - up ip link set $IFACE up diff --git a/hosts/campus-host2_interfaces b/hosts/campus-host2_interfaces index baa420a..b837b64 100644 --- a/hosts/campus-host2_interfaces +++ b/hosts/campus-host2_interfaces @@ -1,26 +1,7 @@ auto lo iface lo inet loopback -auto bond0 -iface bond0 inet manual - use bond - bond-slaves eth1 eth2 - bond-mode 802.3ad - bond-miimon 100 - bond-lacp-rate fast - up ip link set $IFACE up - -auto bond0.50 -iface bond0.50 inet static - address 10.50.50.102 - netmask 255.255.255.0 - vlan-raw-device bond0 - up ip link set $IFACE up - -auto bond0.70 -iface bond0.70 inet static - address 10.60.70.102 - netmask 255.255.255.0 +auto eth1 +iface eth1 inet static + address 10.60.70.102/24 gateway 10.60.70.1 - vlan-raw-device bond0 - up ip link set $IFACE up