devis switch : la partie B déclarait encore les VLAN tenants

Le filtre `routage_tenants` n'avait été posé que sur la partie A et les
trunks. La partie B a sa propre boucle et sortait toujours les douze VLAN
tenants : aucun trunk ne les portait, aucun SVI ne les utilisait, mais leur
présence suggérait que les switches d'accès devaient les connaître — ce qui
contredit la décision.

Vérifié dans les deux sens : zéro VLAN tenant en mode `sdn`, les vingt-quatre
déclarations de retour en mode `switch`.

Corrigé aussi l'en-tête, qui annonçait les VLAN tenants « uniques globalement
sur le trunk » — ils ne sont plus sur aucun trunk en SDN.

Preuves : 24 OK, 0 échec.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-08-03 08:35:44 -04:00
parent e5ce2b93b1
commit 87697597fb
2 changed files with 17 additions and 5 deletions

View file

@ -22,6 +22,15 @@ VXLAN ajoute 50 octets. `make underlay` **refuse** un réseau de transport sous
échouent — la panne la plus coûteuse à diagnostiquer. Les deux réseaux de la fabric principale
passent à 9000.
### Corrigé — la partie B déclarait encore les VLAN tenants
Le filtre `routage_tenants` n'avait été posé que sur la partie A et les trunks : la partie B a
sa propre boucle de déclaration, et sortait toujours les douze VLAN tenants. Aucun trunk ne
les portait, aucun SVI ne les utilisait — mais leur présence suggérait que les switches
d'accès devaient les connaître, ce qui contredit la décision.
Vérifié dans les deux sens : zéro VLAN tenant en mode `sdn`, les vingt-quatre déclarations
(douze par partie) de retour en mode `switch`.
### Le partage des responsabilités, écrit
Une table dans `docs/sdn-evpn.md` dit qui route et qui filtre pour chaque nature de trafic.
Deux conséquences y sont nommées : **l'inter-tenant ne peut plus être oublié** — il doit sortir

View file

@ -263,10 +263,13 @@ def partie_acces(underlay: dict | None, tenants: list, vlans: str,
if transit and r["vlan"] == transit["vlan"]:
continue
out += [f"vlan {r['vlan']}", f" name {r['nom']}"]
for nom, pfx, n in tenants:
for zone in sorted(n["categories"]):
out += [f"vlan {vlan_de(n['index'], zone)}",
f" name {pfx}{n['index']}-{n['categories'][zone]['libelle']}"]
if underlay_mod.routage_tenants(underlay) == "sdn":
out.append("! Aucun VLAN de tenant : ils vivent dans le SDN, pas sur le fil.")
else:
for nom, pfx, n in tenants:
for zone in sorted(n["categories"]):
out += [f"vlan {vlan_de(n['index'], zone)}",
f" name {pfx}{n['index']}-{n['categories'][zone]['libelle']}"]
bord = bool(underlay_mod.stp(underlay))
out += ["!", "! ----- B2. Configuration par switch -----",
"! /!\\ UN SEUL de ces blocs par machine : celui qui porte son nom. Adresse de",
@ -447,7 +450,7 @@ def generer(tenants: list[tuple[str, str, dict]], dialecte: str | None = None) -
"! ============================================================",
"! DEVIS SWITCH — reseau converge multi-tenant (Set-OPS)",
"! Genere par scripts/devis_reseau.py depuis les nomenclatures.",
"! VLAN = 1000 + index*10 + zone (unique globalement sur le trunk).",
"! VLAN = 1000 + index*10 + zone (unique globalement dans la federation).",
"! Underlay (VLAN < 1000) = fabric physique, cluster-global.",
]
if r_nom: