netx/netx_api/biz_state/parsers/zte/arp.py
2026-09-17 21:40:51 +08:00

63 lines
1.9 KiB
Python

"""ZTE: show arp [| one-line]."""
from __future__ import annotations
import re
from typing import Any
_ARP_AGE_TIME_RE = re.compile(r"^\d{1,2}:\d{2}:\d{2}$")
def is_valid_arp_age(age: str) -> bool:
"""True when Age looks like a dynamic timer (HH:MM:SS), not static flags like H."""
return bool(_ARP_AGE_TIME_RE.match(str(age or "").strip()))
def normalize_arp(
*,
raw_text: str,
vendor: str = "",
device_type: str = "",
command: str = "",
params: dict[str, str] | None = None,
) -> list[dict[str, Any]]:
_ = (vendor, device_type, command, params)
out: list[dict[str, Any]] = []
seen: set[tuple[str, str]] = set()
ip_re = re.compile(r"^\d{1,3}(?:\.\d{1,3}){3}$")
for raw in str(raw_text or "").splitlines():
line = raw.strip()
if not line or line.startswith("---") or line.lower().startswith("arp protect"):
continue
if line.lower().startswith("the count"):
continue
if "hardware" in line.lower() and "address" in line.lower():
continue
parts = line.split()
if len(parts) < 4 or not ip_re.match(parts[0]):
continue
ip = parts[0]
age = parts[1]
mac = parts[2]
iface = parts[3]
exter = parts[4] if len(parts) > 4 else ""
inter = parts[5] if len(parts) > 5 else ""
sub = parts[6] if len(parts) > 6 else ""
key = (ip, iface)
if key in seen:
continue
seen.add(key)
dynamic = is_valid_arp_age(age)
out.append(
{
"ip": ip[:64],
"age": age[:32],
"mac": mac[:64],
"interface": iface[:128],
"exter_vlan": exter[:32],
"inter_vlan": inter[:32],
"sub_interface": sub[:128],
"entry_type": "dynamic" if dynamic else "static",
}
)
return out