{ "annotations": { "list": [ { "builtIn": 1, "datasource": { "type": "datasource", "uid": "grafana" }, "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" } ] }, "description": "Generic Router Diff. Compares the BGP routing tables (BMP Adj-RIB-In) of up to 4 selectable routers. Generalized from the 2-router RR Loc-RIB Diff dashboard. Router 1 and Router 2 are always compared; Router 3 and Router 4 are optional - set them to '-- none --' to compare just two.", "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 1, "id": null, "links": [ { "asDropdown": true, "icon": "external link", "includeVars": true, "keepTime": true, "tags": [ "obmp-nav" ], "title": "OBMP Dashboards", "type": "dashboards" } ], "liveNow": false, "panels": [ { "datasource": { "type": "datasource", "uid": "grafana" }, "gridPos": { "h": 5, "w": 24, "x": 0, "y": 0 }, "id": 1, "options": { "content": "## Router Diff\n\nCompares the BGP routing tables of up to **4 routers** via BMP (Adj-RIB-In). Select routers with the **Router 1-4** dropdowns. **Router 1** and **Router 2** are always compared; set **Router 3** / **Router 4** to `-- none --` to compare just two or three.\n\n- **Presence Matrix** — one row per prefix, one column per selected router, cell = best-path next-hop. Blank cell = prefix absent on that router.\n- **Divergence** — prefixes that are missing on some routers or whose best-path next-hop / AS-path disagree.\n- **Summary stats** — prefix count per router and total divergent prefixes.\n- **All Paths** — per-prefix drill-down across the selected routers (pick a prefix with the **Prefix** dropdown).", "mode": "markdown" }, "title": "Router Diff — Overview", "type": "text" }, { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "description": "Active (non-withdrawn) prefixes on Router 1 for the selected AFI.", "fieldConfig": { "defaults": { "color": { "fixedColor": "blue", "mode": "fixed" }, "thresholds": { "mode": "absolute", "steps": [ { "color": "blue", "value": null } ] } }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 0, "y": 5 }, "id": 10, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "format": "table", "rawSql": "SELECT COUNT(DISTINCT r.prefix::text) AS \"prefixes\"\nFROM ip_rib r\nJOIN bgp_peers p ON p.hash_id = r.peer_hash_id\nJOIN routers rt ON rt.hash_id = p.router_hash_id\nWHERE rt.name = '$router1' AND r.iswithdrawn = false\n AND ('$afi' = 'All' OR ('$afi' = 'IPv4' AND r.isipv4) OR ('$afi' = 'IPv6' AND NOT r.isipv4))", "refId": "A" } ], "title": "$router1 Prefixes", "type": "stat" }, { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "description": "Active (non-withdrawn) prefixes on Router 2 for the selected AFI.", "fieldConfig": { "defaults": { "color": { "fixedColor": "green", "mode": "fixed" }, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] } }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 4, "y": 5 }, "id": 11, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "format": "table", "rawSql": "SELECT COUNT(DISTINCT r.prefix::text) AS \"prefixes\"\nFROM ip_rib r\nJOIN bgp_peers p ON p.hash_id = r.peer_hash_id\nJOIN routers rt ON rt.hash_id = p.router_hash_id\nWHERE rt.name = '$router2' AND r.iswithdrawn = false\n AND ('$afi' = 'All' OR ('$afi' = 'IPv4' AND r.isipv4) OR ('$afi' = 'IPv6' AND NOT r.isipv4))", "refId": "A" } ], "title": "$router2 Prefixes", "type": "stat" }, { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "description": "Active prefixes on Router 3 for the selected AFI. Shows 0 when Router 3 is set to '-- none --'.", "fieldConfig": { "defaults": { "color": { "fixedColor": "purple", "mode": "fixed" }, "thresholds": { "mode": "absolute", "steps": [ { "color": "purple", "value": null } ] } }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 8, "y": 5 }, "id": 12, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "format": "table", "rawSql": "SELECT COUNT(DISTINCT r.prefix::text) AS \"prefixes\"\nFROM ip_rib r\nJOIN bgp_peers p ON p.hash_id = r.peer_hash_id\nJOIN routers rt ON rt.hash_id = p.router_hash_id\nWHERE rt.name = '$router3' AND r.iswithdrawn = false\n AND ('$afi' = 'All' OR ('$afi' = 'IPv4' AND r.isipv4) OR ('$afi' = 'IPv6' AND NOT r.isipv4))", "refId": "A" } ], "title": "$router3 Prefixes", "type": "stat" }, { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "description": "Active prefixes on Router 4 for the selected AFI. Shows 0 when Router 4 is set to '-- none --'.", "fieldConfig": { "defaults": { "color": { "fixedColor": "orange", "mode": "fixed" }, "thresholds": { "mode": "absolute", "steps": [ { "color": "orange", "value": null } ] } }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 12, "y": 5 }, "id": 13, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "format": "table", "rawSql": "SELECT COUNT(DISTINCT r.prefix::text) AS \"prefixes\"\nFROM ip_rib r\nJOIN bgp_peers p ON p.hash_id = r.peer_hash_id\nJOIN routers rt ON rt.hash_id = p.router_hash_id\nWHERE rt.name = '$router4' AND r.iswithdrawn = false\n AND ('$afi' = 'All' OR ('$afi' = 'IPv4' AND r.isipv4) OR ('$afi' = 'IPv6' AND NOT r.isipv4))", "refId": "A" } ], "title": "$router4 Prefixes", "type": "stat" }, { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "description": "Distinct prefixes that diverge across the selected routers — either missing on some routers or with a different best-path next-hop / AS-path.", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null }, { "color": "yellow", "value": 1 }, { "color": "red", "value": 25 } ] } }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 16, "y": 5 }, "id": 14, "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": "table", "rawSql": "WITH params AS (\n SELECT '$router1'::text AS r1, '$router2'::text AS r2,\n '$router3'::text AS r3, '$router4'::text AS r4, '$afi'::text AS afi\n),\nbp AS (\n SELECT DISTINCT ON (rt.name, r.prefix, r.prefix_len)\n rt.name AS rname, r.prefix, r.prefix_len, ba.next_hop, ba.as_path\n FROM ip_rib r\n JOIN bgp_peers p ON p.hash_id = r.peer_hash_id\n JOIN routers rt ON rt.hash_id = p.router_hash_id\n JOIN base_attrs ba ON ba.hash_id = r.base_attr_hash_id\n CROSS JOIN params\n WHERE r.iswithdrawn = false\n AND rt.name IN (params.r1, params.r2, params.r3, params.r4)\n AND (params.afi = 'All' OR (params.afi = 'IPv4' AND r.isipv4) OR (params.afi = 'IPv6' AND NOT r.isipv4))\n ORDER BY rt.name, r.prefix, r.prefix_len, ba.local_pref DESC NULLS LAST\n),\nagg AS (\n SELECT bp.prefix, bp.prefix_len,\n COUNT(DISTINCT bp.rname) AS present_on,\n COUNT(DISTINCT host(bp.next_hop)) AS nh_variants,\n COUNT(DISTINCT bp.as_path) AS path_variants\n FROM bp GROUP BY bp.prefix, bp.prefix_len\n),\nsel AS (\n SELECT COUNT(*) AS n FROM (\n SELECT t.v FROM params, unnest(ARRAY[params.r1, params.r2, params.r3, params.r4]) AS t(v)\n WHERE t.v <> '-- none --'\n ) s\n)\nSELECT COUNT(*) AS \"divergent\"\nFROM agg\nWHERE agg.present_on < (SELECT n FROM sel) OR agg.nh_variants > 1 OR agg.path_variants > 1", "refId": "A" } ], "title": "Divergent Prefixes", "type": "stat" }, { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "description": "Number of routers currently selected (Router 1-4, excluding any set to '-- none --').", "fieldConfig": { "defaults": { "color": { "fixedColor": "text", "mode": "fixed" }, "thresholds": { "mode": "absolute", "steps": [ { "color": "text", "value": null } ] } }, "overrides": [] }, "gridPos": { "h": 4, "w": 4, "x": 20, "y": 5 }, "id": 15, "options": { "colorMode": "value", "graphMode": "none", "justifyMode": "auto", "orientation": "auto", "reduceOptions": { "calcs": [ "lastNotNull" ], "fields": "", "values": false }, "textMode": "auto" }, "targets": [ { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "format": "table", "rawSql": "SELECT COUNT(*) AS \"routers\"\nFROM (\n SELECT t.v\n FROM unnest(ARRAY['$router1','$router2','$router3','$router4']) AS t(v)\n WHERE t.v <> '-- none --'\n) s", "refId": "A" } ], "title": "Routers Selected", "type": "stat" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 9 }, "id": 20, "title": "Presence Matrix", "type": "row" }, { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "description": "One row per prefix, one column per selected router. Each cell shows the best-path next-hop on that router; a blank cell means the prefix is absent there. Columns for routers set to '-- none --' are headed '-- none --' and stay empty. Filter by AFI with the dropdown.", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "custom": { "align": "auto", "displayMode": "auto", "filterable": true }, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] } }, "overrides": [ { "matcher": { "id": "byName", "options": "Prefix" }, "properties": [ { "id": "custom.width", "value": 200 } ] }, { "matcher": { "id": "byName", "options": "AFI" }, "properties": [ { "id": "custom.width", "value": 70 } ] } ] }, "gridPos": { "h": 14, "w": 24, "x": 0, "y": 10 }, "id": 21, "options": { "footer": { "fields": "", "reducer": [ "count" ], "show": true }, "showHeader": true, "sortBy": [ { "desc": false, "displayName": "Prefix" } ] }, "targets": [ { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "format": "table", "rawSql": "WITH params AS (\n SELECT '$router1'::text AS r1, '$router2'::text AS r2,\n '$router3'::text AS r3, '$router4'::text AS r4, '$afi'::text AS afi\n),\nbp AS (\n SELECT DISTINCT ON (rt.name, r.prefix, r.prefix_len)\n rt.name AS rname, r.prefix, r.prefix_len, r.isipv4, ba.next_hop\n FROM ip_rib r\n JOIN bgp_peers p ON p.hash_id = r.peer_hash_id\n JOIN routers rt ON rt.hash_id = p.router_hash_id\n JOIN base_attrs ba ON ba.hash_id = r.base_attr_hash_id\n CROSS JOIN params\n WHERE r.iswithdrawn = false\n AND rt.name IN (params.r1, params.r2, params.r3, params.r4)\n AND (params.afi = 'All' OR (params.afi = 'IPv4' AND r.isipv4) OR (params.afi = 'IPv6' AND NOT r.isipv4))\n ORDER BY rt.name, r.prefix, r.prefix_len, ba.local_pref DESC NULLS LAST\n)\nSELECT\n bp.prefix::text AS \"Prefix\",\n CASE WHEN bp.isipv4 THEN 'IPv4' ELSE 'IPv6' END AS \"AFI\",\n MAX(CASE WHEN bp.rname = pr.r1 THEN host(bp.next_hop) END) AS \"$router1\",\n MAX(CASE WHEN bp.rname = pr.r2 THEN host(bp.next_hop) END) AS \"$router2\",\n MAX(CASE WHEN bp.rname = pr.r3 THEN host(bp.next_hop) END) AS \"$router3\",\n MAX(CASE WHEN bp.rname = pr.r4 THEN host(bp.next_hop) END) AS \"$router4\"\nFROM bp CROSS JOIN params pr\nGROUP BY bp.prefix, bp.prefix_len, bp.isipv4, pr.r1, pr.r2, pr.r3, pr.r4\nORDER BY \"Prefix\"", "refId": "A" } ], "title": "Prefix Presence Matrix (cell = best-path next-hop)", "type": "table" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 24 }, "id": 30, "title": "Divergence", "type": "row" }, { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "description": "Prefixes where the selected routers disagree: either the prefix is present on some routers but not all, or the best-path next-hop / AS-path differs between routers. 'Present On' counts how many selected routers carry the prefix; 'Selected' is the total selected router count.", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "custom": { "align": "auto", "displayMode": "auto", "filterable": true }, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] } }, "overrides": [ { "matcher": { "id": "byName", "options": "Divergence" }, "properties": [ { "id": "custom.displayMode", "value": "color-background" }, { "id": "mappings", "value": [ { "options": { "AS-Path differs": { "color": "orange", "index": 1 }, "Missing on some": { "color": "red", "index": 0 }, "NH + AS-Path differ": { "color": "red", "index": 3 }, "Next-Hop differs": { "color": "yellow", "index": 2 } }, "type": "value" } ] } ] }, { "matcher": { "id": "byName", "options": "Next-Hops" }, "properties": [ { "id": "custom.width", "value": 320 } ] } ] }, "gridPos": { "h": 14, "w": 24, "x": 0, "y": 25 }, "id": 31, "options": { "footer": { "fields": "", "reducer": [ "count" ], "show": true }, "showHeader": true, "sortBy": [ { "desc": false, "displayName": "Prefix" } ] }, "targets": [ { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "format": "table", "rawSql": "WITH params AS (\n SELECT '$router1'::text AS r1, '$router2'::text AS r2,\n '$router3'::text AS r3, '$router4'::text AS r4, '$afi'::text AS afi\n),\nbp AS (\n SELECT DISTINCT ON (rt.name, r.prefix, r.prefix_len)\n rt.name AS rname, r.prefix, r.prefix_len, r.isipv4, ba.next_hop, ba.as_path\n FROM ip_rib r\n JOIN bgp_peers p ON p.hash_id = r.peer_hash_id\n JOIN routers rt ON rt.hash_id = p.router_hash_id\n JOIN base_attrs ba ON ba.hash_id = r.base_attr_hash_id\n CROSS JOIN params\n WHERE r.iswithdrawn = false\n AND rt.name IN (params.r1, params.r2, params.r3, params.r4)\n AND (params.afi = 'All' OR (params.afi = 'IPv4' AND r.isipv4) OR (params.afi = 'IPv6' AND NOT r.isipv4))\n ORDER BY rt.name, r.prefix, r.prefix_len, ba.local_pref DESC NULLS LAST\n),\nagg AS (\n SELECT bp.prefix, bp.prefix_len, bool_and(bp.isipv4) AS isipv4,\n COUNT(DISTINCT bp.rname) AS present_on,\n COUNT(DISTINCT host(bp.next_hop)) AS nh_variants,\n COUNT(DISTINCT bp.as_path) AS path_variants,\n string_agg(DISTINCT bp.rname || '=' || host(bp.next_hop), ', ' ORDER BY bp.rname || '=' || host(bp.next_hop)) AS nh_detail\n FROM bp GROUP BY bp.prefix, bp.prefix_len\n),\nsel AS (\n SELECT COUNT(*) AS n FROM (\n SELECT t.v FROM params, unnest(ARRAY[params.r1, params.r2, params.r3, params.r4]) AS t(v)\n WHERE t.v <> '-- none --'\n ) s\n)\nSELECT\n agg.prefix::text AS \"Prefix\",\n CASE WHEN agg.isipv4 THEN 'IPv4' ELSE 'IPv6' END AS \"AFI\",\n agg.present_on AS \"Present On\",\n (SELECT n FROM sel) AS \"Selected\",\n CASE\n WHEN agg.present_on < (SELECT n FROM sel) THEN 'Missing on some'\n WHEN agg.nh_variants > 1 AND agg.path_variants > 1 THEN 'NH + AS-Path differ'\n WHEN agg.nh_variants > 1 THEN 'Next-Hop differs'\n WHEN agg.path_variants > 1 THEN 'AS-Path differs'\n ELSE 'Consistent'\n END AS \"Divergence\",\n agg.nh_detail AS \"Next-Hops\"\nFROM agg\nWHERE agg.present_on < (SELECT n FROM sel) OR agg.nh_variants > 1 OR agg.path_variants > 1\nORDER BY \"Prefix\"", "refId": "A" } ], "title": "Divergent Prefixes — Detail", "type": "table" }, { "collapsed": false, "gridPos": { "h": 1, "w": 24, "x": 0, "y": 39 }, "id": 40, "title": "Per-Prefix All Paths", "type": "row" }, { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "description": "Every path for the prefix chosen in the Prefix dropdown, across all selected routers. Use this to drill into a divergent prefix and see exactly which path each router holds and where it was learned from.", "fieldConfig": { "defaults": { "color": { "mode": "thresholds" }, "custom": { "align": "auto", "displayMode": "auto", "filterable": true }, "thresholds": { "mode": "absolute", "steps": [ { "color": "green", "value": null } ] } }, "overrides": [ { "matcher": { "id": "byName", "options": "Router" }, "properties": [ { "id": "custom.displayMode", "value": "color-text" }, { "id": "color", "value": { "fixedColor": "blue", "mode": "fixed" } } ] } ] }, "gridPos": { "h": 12, "w": 24, "x": 0, "y": 40 }, "id": 41, "options": { "footer": { "fields": "", "reducer": [ "count" ], "show": true }, "showHeader": true, "sortBy": [ { "desc": false, "displayName": "Router" } ] }, "targets": [ { "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "format": "table", "rawSql": "SELECT\n rt.name AS \"Router\",\n p.peer_addr::text AS \"Learned From\",\n host(ba.next_hop) AS \"Next Hop\",\n ba.as_path::text AS \"AS Path\",\n ba.origin_as AS \"Origin AS\",\n COALESCE(ba.local_pref, 0) AS \"Local Pref\",\n COALESCE(ba.med, 0) AS \"MED\",\n ba.community_list::text AS \"Communities\",\n ba.cluster_list::text AS \"Cluster List\",\n host(ba.originator_id) AS \"Originator ID\",\n r.labels AS \"Labels\",\n r.timestamp AS \"Last Update\"\nFROM ip_rib r\nJOIN bgp_peers p ON p.hash_id = r.peer_hash_id\nJOIN routers rt ON rt.hash_id = p.router_hash_id\nJOIN base_attrs ba ON ba.hash_id = r.base_attr_hash_id\nWHERE rt.name IN ('$router1', '$router2', '$router3', '$router4')\n AND r.iswithdrawn = false\n AND r.prefix::text = '$prefix'\nORDER BY rt.name, p.peer_addr", "refId": "A" } ], "title": "All Paths for $prefix", "type": "table" } ], "refresh": "30s", "schemaVersion": 36, "tags": [ "obmp", "obmp-nav", "bgp", "diff" ], "templating": { "list": [ { "current": {}, "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "definition": "SELECT name FROM routers WHERE state = 'up' ORDER BY name", "hide": 0, "includeAll": false, "label": "Router 1", "multi": false, "name": "router1", "options": [], "query": "SELECT name FROM routers WHERE state = 'up' ORDER BY name", "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" }, { "current": {}, "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "definition": "SELECT name FROM routers WHERE state = 'up' ORDER BY name", "hide": 0, "includeAll": false, "label": "Router 2", "multi": false, "name": "router2", "options": [], "query": "SELECT name FROM routers WHERE state = 'up' ORDER BY name", "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" }, { "current": {}, "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "definition": "SELECT '-- none --' AS name UNION ALL SELECT name FROM routers WHERE state = 'up' ORDER BY name", "description": "Optional third router. Select '-- none --' to compare only two routers.", "hide": 0, "includeAll": false, "label": "Router 3", "multi": false, "name": "router3", "options": [], "query": "SELECT '-- none --' AS name UNION ALL SELECT name FROM routers WHERE state = 'up' ORDER BY name", "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" }, { "current": {}, "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "definition": "SELECT '-- none --' AS name UNION ALL SELECT name FROM routers WHERE state = 'up' ORDER BY name", "description": "Optional fourth router. Select '-- none --' to compare fewer routers.", "hide": 0, "includeAll": false, "label": "Router 4", "multi": false, "name": "router4", "options": [], "query": "SELECT '-- none --' AS name UNION ALL SELECT name FROM routers WHERE state = 'up' ORDER BY name", "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" }, { "current": { "selected": true, "text": "All", "value": "All" }, "hide": 0, "includeAll": false, "label": "AFI", "multi": false, "name": "afi", "options": [ { "selected": true, "text": "All", "value": "All" }, { "selected": false, "text": "IPv4", "value": "IPv4" }, { "selected": false, "text": "IPv6", "value": "IPv6" } ], "query": "All,IPv4,IPv6", "skipUrlSync": false, "type": "custom" }, { "current": {}, "datasource": { "type": "postgres", "uid": "obmp_postgres" }, "definition": "SELECT DISTINCT r.prefix::text FROM ip_rib r JOIN bgp_peers p ON p.hash_id = r.peer_hash_id JOIN routers rt ON rt.hash_id = p.router_hash_id WHERE rt.name IN ('$router1', '$router2', '$router3', '$router4') AND r.iswithdrawn = false ORDER BY 1", "hide": 0, "includeAll": false, "label": "Prefix", "multi": false, "name": "prefix", "options": [], "query": "SELECT DISTINCT r.prefix::text FROM ip_rib r JOIN bgp_peers p ON p.hash_id = r.peer_hash_id JOIN routers rt ON rt.hash_id = p.router_hash_id WHERE rt.name IN ('$router1', '$router2', '$router3', '$router4') AND r.iswithdrawn = false ORDER BY 1", "refresh": 1, "regex": "", "skipUrlSync": false, "sort": 1, "type": "query" } ] }, "time": { "from": "now-6h", "to": "now" }, "timepicker": {}, "timezone": "", "title": "Router Diff", "uid": "router-diff", "version": 1 }