Make bgp_route hand-only for divergent IN/OUT CLI layouts.

Skip TextFSM for neighbor route tables (status vs plain, From, RD+VRF, heavy wraps); parse via callback and cover with live RR/VRF fixtures.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-09-23 15:36:25 +08:00
parent ac53af4a5d
commit c18c9afa2e
6 changed files with 354 additions and 194 deletions

View file

@ -13,7 +13,8 @@ zte/zte_zxros_show_bgp_summary.textfsm, .*, zte_zxros, sh[[ow]] bgp .+ sum[[mary
zte/zte_zxros_show_ospf_neighbor.textfsm, .*, zte_zxros, sh[[ow]] ip ospf nei[[ghbor]]
zte/zte_zxros_show_vrrp_brief.textfsm, .*, zte_zxros, sh[[ow]] vrrp .+ br[[ief]]
zte/zte_zxros_show_opticalinfo_brief.textfsm, .*, zte_zxros, sh[[ow]] opticalinfo br[[ief]]
zte/zte_zxros_show_bgp_neighbor_routes.textfsm, .*, zte_zxros, sh[[ow]] bgp .+ nei[[ghbor]] (in|out)
# bgp neighbor in/out routes: hand-only (parsers/zte/bgp_route.py); template kept as archive
# zte/zte_zxros_show_bgp_neighbor_routes.textfsm, .*, zte_zxros, sh[[ow]] bgp .+ nei[[ghbor]] (in|out)
zte/zte_zxros_show_ip_forwarding_route.textfsm, .*, zte_zxros, sh[[ow]] ip forw[[arding]] rou[[te]]
zte/zte_zxros_show_ipv6_forwarding_route.textfsm, .*, zte_zxros, sh[[ow]] ipv6 forw[[arding]] rou[[te]]
zte/zte_zxros_show_l2vpn_forwardinfo_detail.textfsm, .*, zte_zxros, sh[[ow]] l2vpn forw[[ardinfo]] det[[ail]]

View file

@ -1,7 +1,12 @@
# ARCHIVE — not registered in index. bgp_route uses hand-only normalize
# (IN/OUT / status / From / RD+VRF / wraps diverge too much for one template).
Value Filldown RD (\S+)
Value STATUS ((?:\*[<>isd]*(?:\s+[isd]+)?|[<>isd]+)?)
Value Filldown VRF (\S+)
Value STATUS (\*(?:\s*[<>isd]+)?|[<>isd]+)
Value NETWORK (\d{1,3}(?:\.\d{1,3}){3}/\d{1,2}|[0-9A-Fa-f:]+/\d{1,3})
Value NEXT_HOP (\d{1,3}(?:\.\d{1,3}){3}|[0-9A-Fa-f:]+)
# IPv4, IPv6, or IPv4-mapped (::FFFF:a.b.c.d)
Value NEXT_HOP (\d{1,3}(?:\.\d{1,3}){3}|::[Ff]{4}:\d{1,3}(?:\.\d{1,3}){3}|[0-9A-Fa-f:]+)
Value FROM (\d{1,3}(?:\.\d{1,3}){3}|::[Ff]{4}:\d{1,3}(?:\.\d{1,3}){3}|[0-9A-Fa-f:]+)
Value METRIC (\S*)
Value LOC_PRF (\S*)
Value TAG (\S*)
@ -12,13 +17,12 @@ Start
^\s*\*?\s*Network\s+Next -> Routes
^Network\s+Next -> Routes
^\s*Dest\s+Next -> Routes
# RD may appear before header on some snippets; keep Filldown ready
^Route\s+Distinguisher\s*:?\s*${RD}
^Route\s+Distinguisher\s*:?\s*${RD}(?:\s*\(\s*default\s+for\s+vrf\s+${VRF}\s*\))?
^\s*$$
^.* -> Start
Routes
^Route\s+Distinguisher\s*:?\s*${RD}
^Route\s+Distinguisher\s*:?\s*${RD}(?:\s*\(\s*default\s+for\s+vrf\s+${VRF}\s*\))?
^Status\s+codes
^Origin\s+codes
^Current\s+AS
@ -30,11 +34,28 @@ Routes
^\s*\*?\s*Network\s+Next
^Network\s+Next
^\s*Dest\s+Next
# One-line IPv4 / RR "* i prefix nh …"
# IN one-line with status: * i prefix nh metric loc tag path
^\s*${STATUS}\s+${NETWORK}\s+${NEXT_HOP}\s+${METRIC}\s+${LOC_PRF}\s+${TAG}\s+${PATH}\s*$$ -> Record
^\s*${STATUS}\s+${NETWORK}\s+${NEXT_HOP}\s+${METRIC}\s+${LOC_PRF}\s+${PATH}\s*$$ -> Record
^\s*${STATUS}\s+${NETWORK}\s+${NEXT_HOP}\s+${PATH}\s*$$ -> Record
# IPv6 wrap: network alone, then next-hop (+ optional metric/path) lines
# OUT one-line without status: net nh [from] metric locprf [tag] path
^\s*${NETWORK}\s+${NEXT_HOP}\s+${FROM}\s+${METRIC}\s+${LOC_PRF}\s+${TAG}\s+${PATH}\s*$$ -> Record
^\s*${NETWORK}\s+${NEXT_HOP}\s+${FROM}\s+${METRIC}\s+${LOC_PRF}\s+${PATH}\s*$$ -> Record
^\s*${NETWORK}\s+${NEXT_HOP}\s+${FROM}\s+${LOC_PRF}\s+${PATH}\s*$$ -> Record
^\s*${NETWORK}\s+${NEXT_HOP}\s+${LOC_PRF}\s+${PATH}\s*$$ -> Record
# IN wrap: status+net+nh then indented metrics
^\s*${STATUS}\s+${NETWORK}\s+${NEXT_HOP}\s*$$
^\s+${METRIC}\s+${LOC_PRF}\s+${TAG}\s+${PATH}\s*$$ -> Record
^\s+${METRIC}\s+${LOC_PRF}\s+${PATH}\s*$$ -> Record
^\s+${PATH}\s*$$ -> Record
# OUT wrap: net+nh+from then indented metrics (From may be long IPv6)
^\s*${NETWORK}\s+${NEXT_HOP}\s+${FROM}\s*$$
^\s+${METRIC}\s+${LOC_PRF}\s+${TAG}\s+${PATH}\s*$$ -> Record
^\s+${METRIC}\s+${LOC_PRF}\s+${PATH}\s*$$ -> Record
^\s+${PATH}\s*$$ -> Record
# Classic wrap: network alone, then next-hop (+ optional metric/path)
^\s*${STATUS}\s+${NETWORK}\s*$$
^\s*${NETWORK}\s*$$
^\s+${NEXT_HOP}\s+${METRIC}\s+${LOC_PRF}\s+${TAG}\s+${PATH}\s*$$ -> Record
^\s+${NEXT_HOP}\s+${METRIC}\s+${LOC_PRF}\s+${PATH}\s*$$ -> Record
^\s+${NEXT_HOP}\s+${PATH}\s*$$ -> Record