Add RR next-hop sanity check to the RR Loc-RIB Diff dashboard

Adds a panel that flags the next-hop-self-on-an-RR anti-pattern: reflected
routes (those carrying ORIGINATOR_ID) whose NEXT_HOP is an RR loopback while
the route was originated by a different router — meaning the RR rewrote
next-hop to itself and has been pulled into the forwarding path. RR-originated
routes and legitimately-imported eBGP routes (originator == next-hop) are
excluded. An editable rr_loopbacks template variable keeps it environment-
agnostic — useful for validating RR behavior during an IOS-XR to Junos
migration.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
sam 2026-05-18 21:18:22 -07:00
parent a662496e53
commit 6d3387dfe5

View File

@ -1142,6 +1142,148 @@
],
"title": "All Paths for $prefix",
"type": "table"
},
{
"type": "row",
"id": 60,
"title": "RR Next-Hop Sanity",
"gridPos": {
"h": 1,
"w": 24,
"x": 0,
"y": 55
},
"collapsed": false,
"panels": []
},
{
"type": "stat",
"id": 61,
"title": "Reflected Routes on RR Next-Hop",
"datasource": {
"type": "postgres",
"uid": "obmp_postgres"
},
"description": "Reflected routes whose NEXT_HOP is an RR loopback while the route was originated by a different router \u2014 the next-hop-self-on-an-RR anti-pattern that pulls the RR into the data path. Should be 0.",
"gridPos": {
"h": 6,
"w": 6,
"x": 0,
"y": 56
},
"fieldConfig": {
"defaults": {
"color": {
"mode": "thresholds"
},
"thresholds": {
"mode": "absolute",
"steps": [
{
"color": "green",
"value": null
},
{
"color": "red",
"value": 1
}
]
},
"unit": "short"
},
"overrides": []
},
"options": {
"colorMode": "background",
"graphMode": "none",
"justifyMode": "auto",
"orientation": "auto",
"reduceOptions": {
"calcs": [
"lastNotNull"
],
"fields": "",
"values": false
},
"textMode": "auto"
},
"targets": [
{
"datasource": {
"type": "postgres",
"uid": "obmp_postgres"
},
"format": "time_series",
"refId": "A",
"rawSql": "SELECT NOW() AS time, count(*) AS \"Anti-pattern Routes\"\nFROM ip_rib r\nJOIN base_attrs ba ON ba.hash_id = r.base_attr_hash_id\nWHERE r.iswithdrawn = false\n AND host(ba.next_hop) IN (${rr_loopbacks:singlequote})\n AND ba.originator_id IS NOT NULL AND host(ba.originator_id) <> host(ba.next_hop)"
}
]
},
{
"type": "table",
"id": 62,
"title": "Reflected Routes Landing on an RR Next-Hop",
"datasource": {
"type": "postgres",
"uid": "obmp_postgres"
},
"description": "Each row is a reflected route whose NEXT_HOP points at an RR loopback instead of the true originator \u2014 the RR has been pulled into the forwarding path (next-hop-self mis-applied on the client-facing side). Empty is healthy. Use this to validate RR behavior, e.g. during an IOS-XR to Junos RR migration.",
"gridPos": {
"h": 6,
"w": 18,
"x": 6,
"y": 56
},
"fieldConfig": {
"defaults": {
"custom": {
"align": "auto",
"displayMode": "auto"
}
},
"overrides": [
{
"matcher": {
"id": "byName",
"options": "Next-Hop (RR!)"
},
"properties": [
{
"id": "custom.displayMode",
"value": "color-background"
},
{
"id": "color",
"value": {
"mode": "fixed",
"fixedColor": "red"
}
}
]
}
]
},
"options": {
"showHeader": true,
"footer": {
"show": false,
"reducer": [
"sum"
],
"fields": ""
}
},
"targets": [
{
"datasource": {
"type": "postgres",
"uid": "obmp_postgres"
},
"format": "table",
"refId": "A",
"rawSql": "SELECT\n r.prefix AS \"Prefix\",\n host(ba.next_hop) AS \"Next-Hop (RR!)\",\n host(ba.originator_id) AS \"True Originator\",\n COALESCE(rtr.name, p.peer_addr::text) AS \"Seen on Router\",\n COALESCE(NULLIF(p.name,''), p.peer_addr::text) AS \"Via Peer\",\n ba.origin_as AS \"Origin AS\"\nFROM ip_rib r\nJOIN base_attrs ba ON ba.hash_id = r.base_attr_hash_id\nJOIN bgp_peers p ON p.hash_id = r.peer_hash_id\nJOIN routers rtr ON rtr.hash_id = p.router_hash_id\nWHERE r.iswithdrawn = false\n AND host(ba.next_hop) IN (${rr_loopbacks:singlequote})\n AND ba.originator_id IS NOT NULL AND host(ba.originator_id) <> host(ba.next_hop)\nORDER BY r.prefix\nLIMIT 200"
}
]
}
],
"refresh": "30s",
@ -1267,6 +1409,51 @@
"skipUrlSync": false,
"sort": 1,
"type": "query"
},
{
"name": "rr_loopbacks",
"type": "custom",
"label": "RR Loopbacks",
"description": "Loopback / BGP router-id addresses of your route reflectors. Edit this list for your environment.",
"query": "10.10.255.0,10.10.255.20,10.11.255.0,10.11.255.20",
"multi": true,
"includeAll": true,
"current": {
"text": [
"All"
],
"value": [
"$__all"
]
},
"options": [
{
"text": "All",
"value": "$__all",
"selected": true
},
{
"text": "10.10.255.0",
"value": "10.10.255.0",
"selected": false
},
{
"text": "10.10.255.20",
"value": "10.10.255.20",
"selected": false
},
{
"text": "10.11.255.0",
"value": "10.11.255.0",
"selected": false
},
{
"text": "10.11.255.20",
"value": "10.11.255.20",
"selected": false
}
],
"hide": 0
}
]
},