diff --git a/labsim/ovs.sh b/labsim/ovs.sh index 3ea6964..d4067a9 100644 --- a/labsim/ovs.sh +++ b/labsim/ovs.sh @@ -49,7 +49,12 @@ ovs_up() { # Drop any address from a previous mask/octet so a changed vlans.conf does # not leave a stale second address on the port. sudo ip -4 addr flush dev "$port" 2>/dev/null || true - sudo ip addr replace "${V_PREFIX}.${V_HOST}/${V_MASK}" dev "$port" + # host_octet 0 means "no host leg": the WAN transport VLANs belong to the + # fake ISPs, and giving the host an address there would misrepresent the + # segment -- the whole point is that VyOS reaches an ISP, not the host. + if [ "$V_HOST" != "0" ]; then + sudo ip addr replace "${V_PREFIX}.${V_HOST}/${V_MASK}" dev "$port" + fi done ovs_define_libvirt_net @@ -117,9 +122,19 @@ ovs_bond_router() { local count; count="$(echo "$taps" | grep -c .)" [ "$count" -eq 2 ] || { warn "router $vm has $count tap(s), expected 2 — skipping bond"; return 1; } - # Already bonded? (idempotent re-runs) + # Already bonded? Re-runs must still reconcile the VLAN list: adding a VLAN to + # vlans.conf and finding the bond unchanged is exactly how a VLAN silently + # fails to reach a router -- interface present, tag missing, frames dropped by + # the switch. Returning early here once cost real debugging time. if ovs list-ports "$OVS_BR" 2>/dev/null | grep -qx "$LAG_NAME"; then - log "LACP bond $LAG_NAME already present" + local want; want="$(vlan_id_list | tr ',' '\n' | grep -vx 1 | paste -sd, -)" + local have; have="$(ovs get port "$LAG_NAME" trunks 2>/dev/null | tr -d '[] ')" + if [ "$want" != "$have" ]; then + log "bond $LAG_NAME trunk drift: [$have] -> [$want]; updating" + ovs set port "$LAG_NAME" trunks="$want" + else + log "LACP bond $LAG_NAME already present, trunk correct" + fi return 0 fi diff --git a/labsim/vlans.conf b/labsim/vlans.conf index 866f197..1d87b2f 100644 --- a/labsim/vlans.conf +++ b/labsim/vlans.conf @@ -30,3 +30,14 @@ 9:private:172.31.9:10.0.9.0/23 10:lot:172.31.10:10.0.0.0/23:23:3 200:roomates:172.31.200:192.168.2.0/24 + +# WAN transport VLANs, mirroring production. These exist so the sim can run a +# fake ISP on each and the switch script's WAN health checks actually execute +# instead of printing "this delta configures no WAN -- skipping". A cutover +# attempt failed on the WAN with nothing having tested it, because the sim +# modelled every LAN VLAN faithfully and omitted the WAN entirely. +# +# No host leg is wanted here (host_octet 0 means "skip"): the ISP VMs own these +# segments, and a host address on a WAN transport VLAN would be a lie. +51:wan1:172.31.51:vodafone-pppoe(VLAN 51):24:0 +53:wan3:172.31.53:10gig-dhcp(VLAN 53):24:0