IP Conflict Diagnostics
Get IP Conflicts
GET /api/v1/diagnostics/ip-conflicts?area_id=<uuid>
GET /api/v1/diagnostics/ip-conflicts?pi_id=<uuid>
GET /api/v1/diagnostics/ip-conflicts?rd_id=<uuid>
GET /api/v1/diagnostics/ip-conflicts?network_id=<uuid>
Detects IP address conflicts and misconfigurations within the selected scope. Runs 4 SQL queries:
- Duplicate Router IDs — devices sharing the same router ID
- Duplicate IPs — interfaces on different devices sharing the same IP address
- Duplicate Prefixes — same network advertised by multiple devices within the same source type (stub or inter-area)
- Conflicting Externals — same prefix advertised by multiple ASBRs with different attributes (metric type, metric, or tag)
Auth: Any authenticated user.
Response: 200 OK
{
"summary": {
"duplicate_router_ids": 1,
"duplicate_ips": 2,
"duplicate_prefixes": 3,
"conflicting_externals": 1,
"total": 7
},
"duplicate_router_ids": [
{
"router_id": "10.0.0.1",
"devices": [
{ "device_id": "uuid-1", "hostname": "router-a" },
{ "device_id": "uuid-2", "hostname": "router-b" }
]
}
],
"duplicate_ips": [
{
"ip_address": "192.168.1.1",
"devices": [
{ "device_id": "uuid-1", "hostname": "router-a", "if_name": "GigabitEthernet0/0", "router_id": "10.0.0.1" },
{ "device_id": "uuid-3", "hostname": "router-c", "if_name": "GigabitEthernet0/1", "router_id": "10.0.0.3" }
]
}
],
"duplicate_prefixes": [
{
"network": "10.0.1.0/24",
"source": "stub",
"devices": [
{ "device_id": "10.0.0.1", "hostname": "router-a" },
{ "device_id": "10.0.0.2", "hostname": "router-b" }
]
}
],
"conflicting_externals": [
{
"network": "192.0.2.0/24",
"entries": [
{ "adv_router": "10.0.0.5", "hostname": "asbr-1", "metric_type": 2, "metric": 100, "tag": 0, "is_nssa": false },
{ "adv_router": "10.0.0.6", "hostname": "asbr-2", "metric_type": 1, "metric": 200, "tag": 0, "is_nssa": false }
]
}
]
}
Error responses:
400 Bad Request -- Missing scope parameter
Get Single Points of Failure
GET /api/v1/diagnostics/spof?area_id=<uuid>
GET /api/v1/diagnostics/spof?pi_id=<uuid>
GET /api/v1/diagnostics/spof?rd_id=<uuid>
GET /api/v1/diagnostics/spof?network_id=<uuid>
Identifies articulation points (cut vertices) and bridge links in the topology graph using Tarjan's algorithm. These are devices/links whose failure would partition the network into disconnected components. Only considers links with state "up".
Auth: Any authenticated user.
Response: 200 OK
{
"summary": {
"total_devices": 12,
"total_links": 15,
"articulation_points": 2,
"bridge_links": 3
},
"articulation_points": [
{
"device_id": "uuid-1",
"router_id": "10.0.0.1",
"hostname": "core-rtr-1",
"affected_components": 3
}
],
"bridge_links": [
{
"link_id": "uuid-link-1",
"source_device_id": "uuid-1",
"source_router_id": "10.0.0.1",
"source_hostname": "core-rtr-1",
"target_device_id": "uuid-2",
"target_router_id": "10.0.0.2",
"target_hostname": "edge-rtr-1",
"affected_components": 2
}
]
}
Fields:
affected_components — Number of connected components that would result from removing this device/link. Higher = more critical (3+ is critical severity, 2 is warning).
Error responses:
400 Bad Request -- Missing scope parameter
Get Routing Stability Report
GET /api/v1/diagnostics/stability?area_id=<uuid>&period=24h
GET /api/v1/diagnostics/stability?pi_id=<uuid>&period=7d
GET /api/v1/diagnostics/stability?rd_id=<uuid>&period=6h
GET /api/v1/diagnostics/stability?network_id=<uuid>&period=1h
Identifies flapping links (frequent state changes) and unstable devices (high event rate) by aggregating topology_event data over the specified period. Uses SQL GROUP BY aggregation for efficiency.
Query parameters:
- Scope:
area_id, area_ids, pi_id, rd_id, or network_id (same as other diagnostics endpoints)
period — Time window: 1h, 6h, 24h (default), 7d, 30d
Response: 200 OK
{
"flapping_links": [
{
"entity_id": "uuid",
"source_router_id": "10.0.0.1",
"source_hostname": "router-a",
"target_router_id": "10.0.0.2",
"target_hostname": "router-b",
"state_changes": 7,
"period_hours": 24,
"first_event": "2026-02-23T10:15:00Z",
"last_event": "2026-02-24T08:30:00Z"
}
],
"unstable_devices": [
{
"router_id": "10.0.0.3",
"hostname": "router-c",
"event_count": 25,
"period_hours": 24,
"breakdown": {
"link_state_changed": 12,
"link_added": 8,
"link_removed": 5
},
"first_event": "2026-02-23T06:00:00Z",
"last_event": "2026-02-24T09:45:00Z"
}
],
"summary": {
"flapping_links": 1,
"unstable_devices": 1,
"total_events": 150,
"period_hours": 24
}
}
Thresholds:
- Flapping links: 3+ state-change events (link_state_changed, link_added, link_removed)
- Unstable devices: 10+ total events of any type
Error responses:
400 Bad Request -- Missing scope parameter
Get Timer Consistency Report
GET /api/v1/diagnostics/timer-consistency?area_id=<uuid>
GET /api/v1/diagnostics/timer-consistency?pi_id=<uuid>
GET /api/v1/diagnostics/timer-consistency?rd_id=<uuid>
GET /api/v1/diagnostics/timer-consistency?network_id=<uuid>
Compares OSPF hello/dead timers, authentication type, network type, and MTU across interfaces that share a link within each area. Returns mismatches where two connected interfaces have different timer, configuration, or MTU values. Data is populated by the SNMP poller from OSPF-MIB (ospfIfHelloInterval, ospfIfRtrDeadInterval, ospfIfAuthType, ospfIfType) and IF-MIB (ifMtu).
Auth: Any authenticated user.
Query parameters:
- Scope (mutually exclusive, one required):
area_id, area_ids, pi_id, rd_id, or network_id
Response: 200 OK
{
"mismatches": [
{
"area_id": "uuid",
"interface_a": {
"device_id": "uuid",
"router_id": "10.0.0.1",
"hostname": "core-rtr-1",
"ip_address": "192.168.1.1",
"if_name": "Gi0/0/0",
"hello_interval": 10,
"dead_interval": 40,
"auth_type": "md5",
"network_type": "p2p",
"if_mtu": 9000
},
"interface_b": {
"device_id": "uuid",
"router_id": "10.0.0.2",
"hostname": "edge-rtr-1",
"ip_address": "192.168.1.2",
"if_name": "Gi0/1/0",
"hello_interval": 30,
"dead_interval": 120,
"auth_type": "none",
"network_type": "broadcast",
"if_mtu": 1500
},
"mismatch_type": "hello_interval"
}
],
"summary": {
"interfaces_checked": 42,
"mismatches": 3
}
}
Fields:
mismatch_type — The type of mismatch detected: hello_interval, dead_interval, auth_type, network_type, mtu, or nondefault_timers. A single interface pair may produce multiple mismatch entries (one per mismatched field). nondefault_timers is the inverted case: both endpoints agree on hello/dead but on values other than the RFC 2328 defaults (10/40) — a healthy adjacency the pairwise checks can never flag (OSPF requires matching timers, so a link-wide template mistake always agrees with itself). Only reported for network types the 10/40 default applies to (broadcast, p2p); NBMA/point-to-multipoint default to 30/120 and are skipped rather than guessed.
interface_a / interface_b — The two endpoints of the link with their OSPF timer/config values.
summary.interfaces_checked — Total interfaces with OSPF timer data in scope.
summary.mismatches — Total number of mismatch entries.
Error responses:
400 Bad Request -- Missing scope parameter
Get Best Practices Report
GET /api/v1/diagnostics/best-practices?area_id=<uuid>
GET /api/v1/diagnostics/best-practices?pi_id=<uuid>
GET /api/v1/diagnostics/best-practices?rd_id=<uuid>
GET /api/v1/diagnostics/best-practices?network_id=<uuid>
Best practices compliance report. Runs 5 automated OSPF checks (IS-IS areas are filtered out automatically):
- Reference Bandwidth Consistency (warning) — detects routers in same PI with different implied reference bandwidths
- Area 0 Contiguity (critical) — non-backbone areas with no ABR connected to backbone
- Stub Area Compliance (warning) — ASBRs in stub/totally_stub areas (Type 5 leakage risk)
- Router ID Uniqueness (critical) — duplicate router IDs across devices
- Passive Interface Suggestions (info) — interfaces with no peer that aren't loopback/stub/virtual
Auth: Any authenticated user.
Query parameters:
- Scope (mutually exclusive, one required):
area_id, area_ids, pi_id, rd_id, or network_id
Response: 200 OK
{
"findings": [{
"category": "backbone_design",
"severity": "critical",
"title": "Area 0.0.1.20 has no backbone connectivity",
"description": "No ABR in area 0.0.1.20 connects to area 0.0.0.0. 3 device(s) in this area are isolated from the backbone.",
"devices": [{"id": "uuid", "name": "r1", "router_id": "10.0.0.1"}],
"area_id": "uuid"
}],
"summary": {"total": 5, "critical": 1, "warning": 2, "info": 2, "devices_checked": 42, "areas_checked": 6}
}
Fields:
findings[].category — Check category: reference_bandwidth, backbone_design, stub_compliance, router_id_uniqueness, passive_interface
findings[].severity — critical, warning, or info
findings[].title — Human-readable summary of the finding
findings[].description — Detailed explanation with device/area counts
findings[].devices — Affected devices (id, name, router_id)
findings[].area_id — Area UUID (when finding is area-scoped)
summary.total — Total number of findings
summary.critical / summary.warning / summary.info — Count by severity
summary.devices_checked — Total devices in scope
summary.areas_checked — Total areas in scope
Error responses:
400 Bad Request -- Missing scope parameter
Get Asymmetric Costs
GET /api/v1/diagnostics/asymmetric-costs?area_id=<uuid>
GET /api/v1/diagnostics/asymmetric-costs?pi_id=<uuid>
GET /api/v1/diagnostics/asymmetric-costs?rd_id=<uuid>
GET /api/v1/diagnostics/asymmetric-costs?network_id=<uuid>
Returns all links where forward cost differs from reverse cost — a common OSPF misconfiguration that causes asymmetric routing. Only up links with both costs set (> 0) are checked.
Response: 200 OK
{
"summary": {
"total_links_checked": 87,
"asymmetric_count": 3
},
"asymmetric_links": [
{
"link_id": "uuid",
"area_id": "uuid",
"area_label": "0.0.0.0",
"link_type": "point-to-point",
"source": {
"device_id": "uuid",
"router_id": "10.0.0.1",
"name": "core-rtr-01",
"cost": 10
},
"destination": {
"device_id": "uuid",
"router_id": "10.0.0.2",
"name": "core-rtr-02",
"cost": 20
}
}
]
}
Fields:
summary.total_links_checked — Total up links with both costs set in scope
summary.asymmetric_count — Number of links with cost mismatch
asymmetric_links[].source / .destination — Link endpoints with display names (respects system device name mode) and per-direction costs
Error responses:
400 Bad Request -- Missing scope parameter