mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 02:00:46 +08:00
Split ZTE L2VPN MAC outgoing into pw/AC/SID fields and skip separator rows.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
4b38427679
commit
0dc63bb96a
4 changed files with 173 additions and 22 deletions
|
|
@ -16,6 +16,84 @@ _MAC_RE = re.compile(
|
|||
r"(?P<vpn>\S+)\s+(?P<vlan>\S+)\s+(?P<out>.+?)\s+(?P<attr>\S+)\s*$"
|
||||
)
|
||||
|
||||
_SID_OUT_RE = re.compile(
|
||||
r"(?i)^SID\s+(?P<vpn_sid>\S+)\s*,\s*(?P<neighbor_sid>\S+)\s*$"
|
||||
)
|
||||
_AC_OUT_RE = re.compile(
|
||||
r"^(?P<ac_port>\S+)\s*,\s*[EeIi]:(?P<exter_vlan>\S+)\s*$"
|
||||
)
|
||||
_PW_OUT_RE = re.compile(r"^(?P<pw>\S+)\s*,\s*(?P<neighbor>\S+)\s*$")
|
||||
|
||||
|
||||
def _empty_outgoing(raw: str = "") -> dict[str, str]:
|
||||
text = str(raw or "").strip()
|
||||
return {
|
||||
"outgoing": text[:256],
|
||||
"pw": "",
|
||||
"neighbor": "",
|
||||
"ac_port": "",
|
||||
"exter_vlan": "",
|
||||
"vpn_sid": "",
|
||||
"neighbor_sid": "",
|
||||
}
|
||||
|
||||
|
||||
def _parse_outgoing(raw: str) -> dict[str, str]:
|
||||
"""Split Outgoing Information into typed fields; keep raw in outgoing."""
|
||||
out = _empty_outgoing(raw)
|
||||
text = out["outgoing"]
|
||||
if not text:
|
||||
return out
|
||||
|
||||
m = _SID_OUT_RE.match(text)
|
||||
if m:
|
||||
out["vpn_sid"] = m.group("vpn_sid")[:128]
|
||||
out["neighbor_sid"] = m.group("neighbor_sid")[:128]
|
||||
return out
|
||||
|
||||
m = _AC_OUT_RE.match(text)
|
||||
if m:
|
||||
out["ac_port"] = m.group("ac_port")[:128]
|
||||
out["exter_vlan"] = m.group("exter_vlan")[:32]
|
||||
return out
|
||||
|
||||
# ESI / other opaque forms stay in outgoing only.
|
||||
if text.upper().startswith("ESI:"):
|
||||
return out
|
||||
|
||||
m = _PW_OUT_RE.match(text)
|
||||
if m:
|
||||
out["pw"] = m.group("pw")[:128]
|
||||
out["neighbor"] = m.group("neighbor")[:128]
|
||||
return out
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def _is_mac(token: str) -> bool:
|
||||
t = str(token or "").strip()
|
||||
return bool(re.fullmatch(r"[0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4}", t))
|
||||
|
||||
|
||||
def _row(
|
||||
*,
|
||||
mac: str,
|
||||
vpn: str,
|
||||
vlan: str,
|
||||
outgoing: str,
|
||||
attribute: str,
|
||||
) -> dict[str, Any] | None:
|
||||
if not _is_mac(mac) or not vpn or vpn.lower() == "vpn":
|
||||
return None
|
||||
row = {
|
||||
"mac": mac[:64],
|
||||
"vpn": vpn[:128],
|
||||
"vlan": str(vlan or "").strip()[:32],
|
||||
"attribute": str(attribute or "").strip()[:64],
|
||||
}
|
||||
row.update(_parse_outgoing(outgoing))
|
||||
return row
|
||||
|
||||
|
||||
def _map_fsm_rows(rows: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
||||
out: list[dict[str, Any]] = []
|
||||
|
|
@ -23,21 +101,20 @@ def _map_fsm_rows(rows: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|||
for r in rows:
|
||||
mac = row_get(r, "MAC", "mac")
|
||||
vpn = row_get(r, "VPN", "vpn")
|
||||
if not mac or mac.lower() == "mac":
|
||||
continue
|
||||
key = (mac, vpn)
|
||||
if key in seen:
|
||||
continue
|
||||
seen.add(key)
|
||||
out.append(
|
||||
{
|
||||
"mac": mac[:64],
|
||||
"vpn": vpn[:128],
|
||||
"vlan": row_get(r, "VLAN", "vlan")[:32],
|
||||
"outgoing": row_get(r, "OUTGOING", "outgoing")[:256],
|
||||
"attribute": row_get(r, "ATTRIBUTE", "attribute")[:64],
|
||||
}
|
||||
mapped = _row(
|
||||
mac=mac,
|
||||
vpn=vpn,
|
||||
vlan=row_get(r, "VLAN", "vlan"),
|
||||
outgoing=row_get(r, "OUTGOING", "outgoing"),
|
||||
attribute=row_get(r, "ATTRIBUTE", "attribute"),
|
||||
)
|
||||
if not mapped:
|
||||
continue
|
||||
seen.add(key)
|
||||
out.append(mapped)
|
||||
return out
|
||||
|
||||
|
||||
|
|
@ -54,16 +131,17 @@ def _hand_parse(*, raw_text: str, **_kw: Any) -> list[dict[str, Any]]:
|
|||
key = (m.group("mac"), m.group("vpn"))
|
||||
if key in seen:
|
||||
continue
|
||||
seen.add(key)
|
||||
out.append(
|
||||
{
|
||||
"mac": m.group("mac")[:64],
|
||||
"vpn": m.group("vpn")[:128],
|
||||
"vlan": m.group("vlan")[:32],
|
||||
"outgoing": m.group("out").strip()[:256],
|
||||
"attribute": m.group("attr")[:64],
|
||||
}
|
||||
mapped = _row(
|
||||
mac=m.group("mac"),
|
||||
vpn=m.group("vpn"),
|
||||
vlan=m.group("vlan"),
|
||||
outgoing=m.group("out").strip(),
|
||||
attribute=m.group("attr"),
|
||||
)
|
||||
if not mapped:
|
||||
continue
|
||||
seen.add(key)
|
||||
out.append(mapped)
|
||||
return out
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -404,7 +404,13 @@ _L2VPN_MAC_FIELDS: list[FieldDef] = [
|
|||
FieldDef("mac", length=64, indexed=True, is_key=True, display_name="MAC"),
|
||||
FieldDef("vpn", length=128, indexed=True, is_key=True, display_name="VPN"),
|
||||
FieldDef("vlan", length=32, role="meta", display_name="VLAN"),
|
||||
FieldDef("outgoing", length=256, role="state", display_name="Outgoing"),
|
||||
FieldDef("pw", length=128, role="state", display_name="PW"),
|
||||
FieldDef("neighbor", length=128, role="state", display_name="Neighbor"),
|
||||
FieldDef("ac_port", length=128, role="state", display_name="AC Port"),
|
||||
FieldDef("exter_vlan", length=32, role="state", display_name="Exter VLAN"),
|
||||
FieldDef("vpn_sid", length=128, role="state", display_name="VPN SID"),
|
||||
FieldDef("neighbor_sid", length=128, role="state", display_name="Neighbor SID"),
|
||||
FieldDef("outgoing", length=256, role="meta", display_name="Outgoing"),
|
||||
FieldDef("attribute", length=64, role="meta", display_name="Attribute"),
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
Value MAC (\S+)
|
||||
Value MAC ([0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4}\.[0-9A-Fa-f]{4})
|
||||
Value VPN (\S+)
|
||||
Value VLAN (\S+)
|
||||
Value OUTGOING (.*)
|
||||
|
|
@ -13,6 +13,7 @@ Start
|
|||
|
||||
Entries
|
||||
^${MAC}\s+${VPN}\s+${VLAN}\s+${OUTGOING}\s+${ATTRIBUTE}\s*$$ -> Record
|
||||
^-+(\s+-+)*\s*$$
|
||||
^\s*$$
|
||||
^\S+\s*#\s*$$ -> End
|
||||
^.*#\s*$$ -> End
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue