From 0190ef5fb8658a70ed77627b8b64f74822f233ba Mon Sep 17 00:00:00 2001 From: sam Date: Tue, 19 May 2026 01:42:31 -0700 Subject: [PATCH] Fix BGP Peer Map blank graph: connect disconnected lab components The node graph rendered blank because the two CML/PROX labs formed two disconnected components (iBGP-only meshes within each lab), and Grafana's nodeGraph layout renders nothing for a disconnected graph. Match BGP sessions to monitored routers by peer IP as well as peer BGP-ID, so the real cross-lab eBGP sessions become graph edges. The graph is now one connected component (30 iBGP + 4 eBGP edges) and lays out. The companion external-neighbours table uses the same peer-IP check so those sessions are no longer double-listed. Co-Authored-By: Claude Opus 4.7 (1M context) --- obmp-grafana/dashboards/obmp/Maps-1006/bgp_peer_map.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/obmp-grafana/dashboards/obmp/Maps-1006/bgp_peer_map.json b/obmp-grafana/dashboards/obmp/Maps-1006/bgp_peer_map.json index 87ff3cf..8d1d9df 100644 --- a/obmp-grafana/dashboards/obmp/Maps-1006/bgp_peer_map.json +++ b/obmp-grafana/dashboards/obmp/Maps-1006/bgp_peer_map.json @@ -31,7 +31,7 @@ { "datasource": {"type": "postgres","uid": "obmp_postgres"}, "format": "table", - "rawSql": "WITH rid AS (\n SELECT DISTINCT router_hash_id, host(localbgpid) AS bgpid\n FROM v_peers WHERE localbgpid IS NOT NULL\n),\nsess AS (\n SELECT\n LEAST(vp.router_hash_id, rid2.router_hash_id)::text AS a,\n GREATEST(vp.router_hash_id, rid2.router_hash_id)::text AS b,\n CASE WHEN vp.peerasn = vp.localasn THEN 'iBGP' ELSE 'eBGP' END AS kind,\n vp.peer_hash_id AS feed\n FROM v_peers vp\n JOIN rid rid2 ON rid2.bgpid = host(vp.peerbgpid)\n WHERE vp.peer_state = 'up' AND vp.router_hash_id <> rid2.router_hash_id\n)\nSELECT a || '-' || b AS id, a AS source, b AS target,\n COUNT(DISTINCT feed)::int AS mainstat,\n MAX(kind) AS secondarystat,\n MAX(kind) AS detail__session_type\nFROM sess GROUP BY a, b", + "rawSql": "WITH rid AS (\n SELECT DISTINCT router_hash_id, host(localbgpid) AS bgpid\n FROM v_peers WHERE localbgpid IS NOT NULL\n),\nsess AS (\n SELECT\n LEAST(vp.router_hash_id, rid2.router_hash_id)::text AS a,\n GREATEST(vp.router_hash_id, rid2.router_hash_id)::text AS b,\n CASE WHEN vp.peerasn = vp.localasn THEN 'iBGP' ELSE 'eBGP' END AS kind,\n vp.peer_hash_id AS feed\n FROM v_peers vp\n JOIN rid rid2 ON rid2.bgpid = host(vp.peerbgpid) OR rid2.bgpid = host(vp.peerip)\n WHERE vp.peer_state = 'up' AND vp.router_hash_id <> rid2.router_hash_id\n)\nSELECT a || '-' || b AS id, a AS source, b AS target,\n COUNT(DISTINCT feed)::int AS mainstat,\n MAX(kind) AS secondarystat,\n MAX(kind) AS detail__session_type\nFROM sess GROUP BY a, b", "refId": "edges" } ], @@ -52,7 +52,7 @@ { "datasource": {"type": "postgres","uid": "obmp_postgres"}, "format": "table", - "rawSql": "SELECT vp.routername AS \"Router\",\n host(vp.peerip) AS \"Peer\",\n vp.peerasn AS \"Peer AS\",\n CASE WHEN vp.peerasn = vp.localasn THEN 'iBGP' ELSE 'eBGP' END AS \"Type\",\n vp.peer_state AS \"State\"\nFROM v_peers vp\nWHERE vp.peer_state = 'up'\n AND NOT EXISTS (SELECT 1 FROM v_peers r WHERE host(r.localbgpid) = host(vp.peerbgpid))\nORDER BY vp.routername, vp.peerip", + "rawSql": "SELECT vp.routername AS \"Router\",\n host(vp.peerip) AS \"Peer\",\n vp.peerasn AS \"Peer AS\",\n CASE WHEN vp.peerasn = vp.localasn THEN 'iBGP' ELSE 'eBGP' END AS \"Type\",\n vp.peer_state AS \"State\"\nFROM v_peers vp\nWHERE vp.peer_state = 'up'\n AND NOT EXISTS (SELECT 1 FROM v_peers r WHERE host(r.localbgpid) = host(vp.peerbgpid) OR host(r.localbgpid) = host(vp.peerip))\nORDER BY vp.routername, vp.peerip", "refId": "A" } ],