mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 02:00:46 +08:00
Fix ZTE BGP vpnv4/vpnv6 RD VRF filldown and map VRF-scoped AFI to ipv4/ipv6.
Stop inheriting `(default for vrf)` onto RD-only blocks, and normalize CE vrf commands so `(afi,vrf)` sheet splits no longer collide with global VPNx tables. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
d701e4a35e
commit
c6a98e2526
3 changed files with 90 additions and 6 deletions
|
|
@ -33,9 +33,32 @@ _LOCAL_AS_IN_CMD_RE = re.compile(r"(?i)(?:^|\s)as\s+(\S+)(?:\s*\||\s*$)")
|
|||
|
||||
|
||||
def _detect_bgp_afi(command: str, params: dict[str, str] | None) -> str:
|
||||
"""Detect BGP AFI for peer/route rows.
|
||||
|
||||
VRF-scoped CLI (``… vrf <name> …``) is the CE/ipv4|ipv6 VRF AF even when
|
||||
ZTE spells the command as ``vpnv4|vpnv6 unicast vrf``. Map those to
|
||||
``ipv4``/``ipv6`` so split-by-(afi,vrf) does not collide with global
|
||||
VPNv4/VPNv6 tables that may carry RD ``(default for vrf X)`` into ``vrf``.
|
||||
"""
|
||||
low = str(command or "").lower()
|
||||
has_vrf = bool(_detect_vrf(command, params))
|
||||
if has_vrf:
|
||||
# Prefer command tokens over stale params.afi=vpnv*
|
||||
if "vpnv6" in low or "ipv6" in low:
|
||||
return "ipv6"
|
||||
if "vpnv4" in low or "ipv4" in low:
|
||||
return "ipv4"
|
||||
# Bare ``vrf`` with params.afi hint
|
||||
if params and params.get("afi"):
|
||||
af = str(params.get("afi") or "").strip().lower()
|
||||
if af in ("vpnv6", "ipv6"):
|
||||
return "ipv6"
|
||||
if af in ("vpnv4", "ipv4"):
|
||||
return "ipv4"
|
||||
return "ipv4"
|
||||
|
||||
if params and params.get("afi"):
|
||||
return str(params.get("afi") or "").strip().lower()
|
||||
low = str(command or "").lower()
|
||||
if "l2vpn" in low and "evpn" in low:
|
||||
return "evpn"
|
||||
if "l2vpn" in low and "vpls" in low:
|
||||
|
|
|
|||
|
|
@ -269,7 +269,10 @@ def _hand_parse(
|
|||
pending_nh = ""
|
||||
pending_rest = ""
|
||||
current_rd = ""
|
||||
current_vrf = vrf
|
||||
# Command-scoped VRF (CE view); RD blocks may temporarily override via
|
||||
# ``(default for vrf X)`` but must not fill-down onto RD-only segments.
|
||||
cmd_vrf = vrf
|
||||
current_vrf = cmd_vrf
|
||||
|
||||
def _flush_pending(*, rest: str = "", path_continuation: bool = False) -> dict[str, Any] | None:
|
||||
nonlocal pending_net, pending_flags, pending_nh, pending_rest
|
||||
|
|
@ -313,9 +316,8 @@ def _hand_parse(
|
|||
if row:
|
||||
yield row
|
||||
current_rd = (rd_m.group("rd") or "").strip()
|
||||
vrf_from_rd = (rd_m.group("vrf") or "").strip()
|
||||
if vrf_from_rd:
|
||||
current_vrf = vrf_from_rd
|
||||
# Reset every RD header: annotation wins; else fall back to cmd VRF.
|
||||
current_vrf = (rd_m.group("vrf") or "").strip() or cmd_vrf
|
||||
continue
|
||||
if _skip_noise_line(line):
|
||||
continue
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue