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