Download Decipher/validator.py from sae8d/topo: direct link, hf CLI and curl.
- Browser
- Download file 3.19 kB
-
https://huggingface.co/spaces/sae8d/topo/resolve/main/Decipher/validator.py
- Command line
-
hf download hf://spaces/sae8d/topo/Decipher/validator.py
-
curl -L -o validator.py https://huggingface.co/spaces/sae8d/topo/resolve/main/Decipher/validator.py
3.19 kB
| import ipaddress | |
| from typing import List, Dict, Set | |
| from Decipher.models import NetworkTopology | |
| def validate_topology(topology: NetworkTopology) -> List[str]: | |
| """ | |
| Performs logical validation on the network topology and returns a list of warnings/errors. | |
| """ | |
| issues = [] | |
| device_names = {d.name for d in topology.devices} | |
| ip_to_interface = {} # ip -> (device, interface) | |
| # 1. Check for IP Conflicts and basic interface sanity | |
| for device in topology.devices: | |
| for intf in device.interfaces: | |
| if intf.ip: | |
| # Check for duplicate IPs | |
| if intf.ip in ip_to_interface: | |
| other_dev, other_intf = ip_to_interface[intf.ip] | |
| issues.append(f"IP Conflict: {intf.ip} is assigned to both {device.name} ({intf.name}) and {other_dev} ({other_intf})") | |
| else: | |
| ip_to_interface[intf.ip] = (device.name, intf.name) | |
| # Basic IP format validation | |
| try: | |
| if "/" in intf.ip: | |
| ipaddress.ip_interface(intf.ip) | |
| else: | |
| ipaddress.ip_address(intf.ip) | |
| except ValueError: | |
| issues.append(f"Invalid IP Format: '{intf.ip}' on {device.name} ({intf.name})") | |
| # 2. Ensure Link Endpoints Exist | |
| for link in topology.physical_links: | |
| if link.from_device not in device_names: | |
| issues.append(f"Broken Link: Source device '{link.from_device}' does not exist.") | |
| if link.to_device not in device_names: | |
| issues.append(f"Broken Link: Destination device '{link.to_device}' does not exist.") | |
| # 3. Verify Routing Protocols (Basic Sanity) | |
| for device in topology.devices: | |
| if device.routing and device.routing.ospf: | |
| device_ips = [intf.ip for intf in device.interfaces if intf.ip] | |
| for ospf in device.routing.ospf: | |
| for net_statement in ospf.networks: | |
| # Check if the OSPF network statement matches at least one interface IP segment | |
| try: | |
| # network statement is usually "network 10.0.0.0 0.0.0.255 area 0" | |
| # we extract the network and wildcard mask | |
| parts = net_statement.split() | |
| if "network" in parts: | |
| net_addr = parts[parts.index("network") + 1] | |
| # Simple check: does any device IP start with the same prefix? | |
| # This is a heuristic check | |
| found_match = False | |
| for ip in device_ips: | |
| if ip.split('.')[0:2] == net_addr.split('.')[0:2]: | |
| found_match = True | |
| break | |
| if not found_match: | |
| issues.append(f"OSPF Warning: Network statement '{net_statement}' on {device.name} doesn't seem to match any local interface IPs.") | |
| except Exception: | |
| pass | |
| return issues | |