frontière : le devis rattrape la bascule SDN, et deux devis se contredisaient
Le prochain saut des routes tenants pointait le SVI du commutateur. En EVPN il ne route plus les tenants : la route arriverait sur un équipement sans chemin vers le tenant — configuration qui s'applique sans erreur et ne fonctionne pas. Le devis émet `<NOEUD-DE-SORTIE-EVPN>` et dit pourquoi. `underlay.passerelle_sortie` garde son sens : adresse du pare-feu sur le lien de transit, donc sortie de l'UNDERLAY. Deux choses distinctes. Corrigé aussi une contradiction antérieure au SDN : la section 0 demandait de router l'administration vers 10.0.4.6, le SVI du commutateur lui-même, alors que `devis-reseau` émet 10.0.4.1, l'adresse du pare-feu — tout en affirmant que l'autre devis « émet déjà ces routes ». Elles coïncident maintenant, vérifié ligne à ligne. Et deux commentaires qui affirmaient l'inverse de la décision se dérivent du mode de routage. Preuves : 24 OK, 0 échec. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
87697597fb
commit
58fdaa5540
3 changed files with 62 additions and 5 deletions
25
CHANGELOG.md
25
CHANGELOG.md
|
|
@ -1,5 +1,30 @@
|
|||
# CHANGELOG — Set-OPS
|
||||
|
||||
## 2026-08-03 (suite) — le devis frontière rattrape la bascule SDN
|
||||
|
||||
Trois affirmations du devis frontière étaient devenues fausses, dont une qui cassait le
|
||||
routage.
|
||||
|
||||
### Corrigé — le prochain saut des routes tenants
|
||||
Elles pointaient le SVI du commutateur (`10.0.4.6`). En EVPN, il ne route plus les tenants :
|
||||
une route pointée là arriverait sur un équipement **sans chemin vers le tenant**. Configuration
|
||||
qui s'applique sans erreur et ne fonctionne pas — la signature qu'on traque depuis deux jours.
|
||||
|
||||
Le devis émet désormais `<NOEUD-DE-SORTIE-EVPN>` et dit pourquoi, à figer après le spike.
|
||||
|
||||
`underlay.passerelle_sortie` **garde** son sens : c'est l'adresse du pare-feu sur le lien de
|
||||
transit, donc la sortie de l'**underlay**. Deux choses distinctes qu'il ne faut pas confondre.
|
||||
|
||||
### Corrigé — une contradiction entre les deux devis, antérieure au SDN
|
||||
La section 0 du devis frontière demandait de router les réseaux d'administration **vers
|
||||
`10.0.4.6`** — le SVI du commutateur lui-même. `make devis-reseau` émet `10.0.4.1`, l'adresse
|
||||
du pare-feu. Les deux devis se contredisaient, alors que l'un affirmait que l'autre « émet déjà
|
||||
ces routes ». Elles coïncident maintenant, vérifié ligne à ligne.
|
||||
|
||||
### Corrigé — deux commentaires qui affirmaient l'inverse de la décision
|
||||
L'en-tête (« les passerelles de zone restent sur les switches L3 ») et la description des
|
||||
routes (« routage inter-zone sur les switches L3 ») se dérivent maintenant du mode de routage.
|
||||
|
||||
## 2026-08-03 — le SDN prend le routage tenant, le devis switch se vide
|
||||
|
||||
Trois décisions, et le devis les applique déjà : **une zone EVPN par tenant** ; le routage
|
||||
|
|
|
|||
|
|
@ -80,8 +80,16 @@ tenants.
|
|||
|
||||
**Le nœud de sortie remplace le prochain saut.** En EVPN, le trafic quitte le VRF par un ou
|
||||
plusieurs *exit nodes* désignés. Ce sont eux, et non plus le commutateur, que l'OPNsense voit
|
||||
comme voisins. `underlay.passerelle_sortie` changera de nature : il désignera l'entrée du
|
||||
tenant vers la bordure, côté hyperviseur.
|
||||
comme voisins.
|
||||
|
||||
C'est **appliqué** : en mode `sdn`, le devis frontière n'émet plus le SVI du commutateur comme
|
||||
prochain saut des routes tenants — il émet le marqueur `<NOEUD-DE-SORTIE-EVPN>` et dit
|
||||
pourquoi. Une route pointée vers le SVI arriverait sur un équipement qui n'a aucun chemin vers
|
||||
le tenant : c'est le genre de configuration qui s'applique sans erreur et ne fonctionne pas.
|
||||
|
||||
À noter : `underlay.passerelle_sortie` **garde** son sens — c'est l'adresse du pare-feu sur le
|
||||
lien de transit, donc la sortie de l'**underlay**, indépendante du routage tenant. Ce sont
|
||||
deux choses distinctes qu'il ne faut pas confondre.
|
||||
|
||||
**Le MTU est un prérequis vérifié, pas un conseil.** VXLAN ajoute 50 octets ; `make underlay`
|
||||
**refuse** un réseau de transport sous 1550 dès que `routage_tenants: sdn`. C'est le premier
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ import underlay as underlay_mod # noqa: E402
|
|||
# (meme idiome que devis_reseau). Le panneau « Intrants de base » du GUI les ecrit
|
||||
# dans group_vars/opnsense.yml : le devis se complete tout seul ensuite.
|
||||
PROCHAIN_SAUT = "<PROCHAIN-SAUT-SWITCH>"
|
||||
NOEUD_SORTIE = "<NOEUD-DE-SORTIE-EVPN>"
|
||||
IF_TRANSIT = "<IF-TRANSIT>"
|
||||
IF_WAN = "<IF-WAN>"
|
||||
|
||||
|
|
@ -122,6 +123,11 @@ def prochain_saut(transit: dict | None) -> str:
|
|||
fois dans l'underlay) ouvrirait la porte a deux valeurs contradictoires — c'est
|
||||
exactement le mode de panne qu'on ferme. Marqueur tant qu'aucun transit n'existe.
|
||||
"""
|
||||
if underlay_mod.routage_tenants(underlay_mod.charger()) == "sdn":
|
||||
# En EVPN, le commutateur ne route plus les tenants : le voisin de la frontiere
|
||||
# est un NOEUD DE SORTIE (hyperviseur), pas le SVI. Emettre le SVI produirait
|
||||
# des routes vers un equipement qui n'a aucun chemin vers le tenant.
|
||||
return NOEUD_SORTIE
|
||||
return str((transit or {}).get("passerelle") or "").strip() or PROCHAIN_SAUT
|
||||
|
||||
# Le socle est porte par TOUS les hotes : sa destination n'est pas une poignee
|
||||
|
|
@ -286,7 +292,10 @@ def construire(tenants: list[tuple[str, str, dict]]) -> dict:
|
|||
{
|
||||
"reseau": supernet_de(n["index"]),
|
||||
"prochain_saut": saut,
|
||||
"description": f"{nom} (index {n['index']}) — routage inter-zone sur les switches L3",
|
||||
"description": f"{nom} (index {n['index']}) — routage inter-zone "
|
||||
+ ("dans la zone EVPN du tenant"
|
||||
if underlay_mod.routage_tenants(underlay_mod.charger()) == "sdn"
|
||||
else "sur les switches L3"),
|
||||
}
|
||||
for nom, _pfx, n in tenants
|
||||
]
|
||||
|
|
@ -314,8 +323,12 @@ def construire(tenants: list[tuple[str, str, dict]]) -> dict:
|
|||
"adresse_frontiere": (transit or {}).get("passerelle_sortie"),
|
||||
"nom_frontiere": nom_frontiere(transit),
|
||||
} if transit else None,
|
||||
# Le switch route vers l'ADRESSE DU PARE-FEU sur le lien de transit
|
||||
# (`passerelle_sortie`), pas vers son propre SVI ni vers un noeud de sortie :
|
||||
# c'est la sortie de l'underlay. `devis_reseau` emet exactement ces lignes.
|
||||
"reciproque_switch": [
|
||||
f"ip route {cidr} -> {saut} (retour vers l'administration)"
|
||||
f"ip route {cidr} -> {(transit or {}).get('passerelle_sortie') or PROCHAIN_SAUT}"
|
||||
f" (retour vers l'administration)"
|
||||
for cidr in admin
|
||||
],
|
||||
}
|
||||
|
|
@ -327,7 +340,9 @@ def rendre(devis: dict) -> str:
|
|||
"# DEVIS OPNSENSE — frontiere nord/sud (Set-OPS)",
|
||||
"# Genere par scripts/devis_opnsense.py. NE PAS EDITER A LA MAIN.",
|
||||
"# Derive du registre des flux (pair: externe) + des nomenclatures.",
|
||||
"# Les passerelles de zone restent sur les switches L3 : aucun SVI ici.",
|
||||
("# Les passerelles de zone sont anycast sur les hyperviseurs (SDN EVPN) : aucun SVI ici."
|
||||
if underlay_mod.routage_tenants(underlay_mod.charger()) == "sdn"
|
||||
else "# Les passerelles de zone restent sur les switches L3 : aucun SVI ici."),
|
||||
"# ============================================================",
|
||||
"",
|
||||
"## 0. Prerequis reciproques — COTE SWITCHES",
|
||||
|
|
@ -373,6 +388,15 @@ def rendre(devis: dict) -> str:
|
|||
out += [
|
||||
"## 2. Routes statiques (vers les supernets tenants)",
|
||||
]
|
||||
if devis["routes"] and devis["routes"][0]["prochain_saut"] == NOEUD_SORTIE:
|
||||
out += [
|
||||
"# /!\\ LE PROCHAIN SAUT N'EST PAS LE COMMUTATEUR. En SDN EVPN, il ne route plus",
|
||||
"# les tenants : une route pointee vers son SVI arriverait sur un equipement sans",
|
||||
"# chemin vers le tenant. Le voisin de la frontiere est un NOEUD DE SORTIE — un",
|
||||
"# hyperviseur qui porte la sortie du VRF. A figer apres le spike EVPN.",
|
||||
]
|
||||
out += [
|
||||
]
|
||||
for r in devis["routes"]:
|
||||
out.append(f"route add {r['reseau']} via {r['prochain_saut']} # {r['description']}")
|
||||
out += ["", "## 3. Alias"]
|
||||
|
|
|
|||
Loading…
Reference in a new issue