Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
{
"annotations" : {
"list" : [
{
"builtIn" : 1 ,
"datasource" : {
"type" : "datasource" ,
"uid" : "grafana"
} ,
"enable" : true ,
"hide" : true ,
"iconColor" : "rgba(0, 211, 255, 1)" ,
"name" : "Annotations & Alerts" ,
"target" : {
"limit" : 100 ,
"matchAny" : false ,
"tags" : [ ] ,
"type" : "dashboard"
} ,
"type" : "dashboard"
}
]
} ,
"editable" : true ,
"fiscalYearStartMonth" : 0 ,
"graphTooltip" : 0 ,
2026-05-18 20:55:03 -07:00
"id" : null ,
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
"iteration" : 1654876929746 ,
2026-05-18 20:55:03 -07:00
"links" : [
2026-05-18 22:22:21 -07:00
{
"asDropdown" : true ,
"icon" : "external link" ,
"includeVars" : true ,
"keepTime" : true ,
"tags" : [
"obmp-nav"
] ,
"title" : "OBMP Dashboards" ,
"type" : "dashboards"
}
2026-05-18 20:55:03 -07:00
] ,
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
"liveNow" : false ,
"panels" : [
{
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
2026-05-18 20:55:03 -07:00
"description" : "IPv4 vs IPv6 prefix count advertised by this ASN." ,
"fieldConfig" : {
"defaults" : {
2026-05-18 22:22:21 -07:00
"color" : {
"mode" : "palette-classic"
} ,
"custom" : {
"hideFrom" : {
"legend" : false ,
"tooltip" : false ,
"viz" : false
}
} ,
2026-05-18 20:55:03 -07:00
"decimals" : 0 ,
"mappings" : [ ] ,
"unit" : "none"
} ,
"overrides" : [ ]
} ,
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
"gridPos" : {
"h" : 8 ,
"w" : 5 ,
"x" : 0 ,
"y" : 0
} ,
"id" : 6 ,
"links" : [ ] ,
2026-05-18 20:55:03 -07:00
"options" : {
2026-05-18 22:22:21 -07:00
"displayLabels" : [
"value"
] ,
"legend" : {
"calcs" : [ ] ,
"displayMode" : "table" ,
"placement" : "bottom" ,
"values" : [
"value" ,
"percent"
]
} ,
2026-05-18 20:55:03 -07:00
"pieType" : "pie" ,
2026-05-18 22:22:21 -07:00
"reduceOptions" : {
"calcs" : [
"lastNotNull"
] ,
"fields" : "" ,
"values" : false
} ,
"tooltip" : {
"mode" : "single" ,
"sort" : "none"
}
2026-05-18 20:55:03 -07:00
} ,
"pluginVersion" : "9.1.7" ,
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
"targets" : [
{
2026-05-18 22:22:21 -07:00
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
"alias" : "" ,
"format" : "time_series" ,
"rawSql" : "SELECT\n max(timestamp) as time,\n count(*) as \"ipv4\"\nFROM\n global_ip_rib\nWHERE\n recv_origin_as = [[asn_num]]\n and family(prefix) = 4\nGROUP BY prefix\n" ,
"refId" : "A"
} ,
{
2026-05-18 22:22:21 -07:00
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
"alias" : "" ,
"format" : "time_series" ,
"rawSql" : "SELECT\n max(timestamp) as time,\n count(*) as \"ipv6\"\nFROM\n global_ip_rib\nWHERE\n recv_origin_as = [[asn_num]]\n and family(prefix) = 6\nGROUP BY prefix\n" ,
"refId" : "B"
}
] ,
"title" : "Advertised IP Addresses" ,
2026-05-18 20:55:03 -07:00
"type" : "piechart"
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
} ,
{
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
"fieldConfig" : {
"defaults" : {
"color" : {
"mode" : "thresholds"
} ,
"mappings" : [
{
"options" : {
"match" : "null" ,
"result" : {
"text" : "N/A"
}
} ,
"type" : "special"
}
] ,
"thresholds" : {
"mode" : "absolute" ,
"steps" : [
{
"color" : "green" ,
"value" : null
} ,
{
"color" : "red" ,
"value" : 80
}
]
} ,
"unit" : "none"
} ,
"overrides" : [ ]
} ,
"gridPos" : {
"h" : 4 ,
"w" : 4 ,
"x" : 5 ,
"y" : 0
} ,
"id" : 11 ,
"links" : [ ] ,
"maxDataPoints" : 100 ,
"options" : {
"colorMode" : "background" ,
"graphMode" : "none" ,
"justifyMode" : "auto" ,
"orientation" : "horizontal" ,
"reduceOptions" : {
"calcs" : [
"mean"
] ,
"fields" : "" ,
"values" : false
} ,
"text" : { } ,
"textMode" : "auto"
} ,
"pluginVersion" : "8.5.4" ,
"targets" : [
{
"alias" : "" ,
"format" : "table" ,
"group" : [ ] ,
"hide" : false ,
"metricColumn" : "none" ,
"rawQuery" : true ,
"rawSql" : "SELECT count(distinct asn) as count\nFROM (\n\tSELECT\n\t\t\tas_path[array_position(as_path, ${asn_num}::bigint) - 1] as asn\n\t\tFROM base_attrs a\n\t\tWHERE as_path && '{${asn_num}}'\n) d\nWHERE asn is not null and asn != ${asn_num}\n" ,
"refId" : "A" ,
"select" : [
[
{
"params" : [
"value"
] ,
"type" : "column"
}
]
] ,
"timeColumn" : "time" ,
"where" : [
{
"name" : "$__timeFilter" ,
"params" : [ ] ,
"type" : "macro"
}
]
}
] ,
"title" : "Upstream ASNs" ,
"type" : "stat"
} ,
{
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
2026-05-18 20:55:03 -07:00
"description" : "IPv4/IPv6 prefixes originated by this ASN over time, with RPKI/IRR coverage (from stats_ip_origins)." ,
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
"fieldConfig" : {
"defaults" : {
2026-05-18 22:22:21 -07:00
"color" : {
"mode" : "palette-classic"
} ,
"custom" : {
"axisCenteredZero" : false ,
"axisColorMode" : "text" ,
"axisLabel" : "" ,
"axisPlacement" : "auto" ,
"barAlignment" : 0 ,
"drawStyle" : "line" ,
"fillOpacity" : 10 ,
"gradientMode" : "none" ,
"hideFrom" : {
"legend" : false ,
"tooltip" : false ,
"viz" : false
} ,
"lineInterpolation" : "linear" ,
"lineWidth" : 1 ,
"pointSize" : 5 ,
"scaleDistribution" : {
"type" : "linear"
} ,
"showPoints" : "auto" ,
"spanNulls" : false ,
"stacking" : {
"group" : "A" ,
"mode" : "none"
} ,
"thresholdsStyle" : {
"mode" : "off"
}
} ,
2026-05-18 20:55:03 -07:00
"decimals" : 0 ,
"mappings" : [ ] ,
"unit" : "none"
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
} ,
"overrides" : [ ]
} ,
"gridPos" : {
"h" : 8 ,
"w" : 15 ,
"x" : 9 ,
"y" : 0
} ,
"id" : 14 ,
"links" : [ ] ,
"options" : {
2026-05-18 22:22:21 -07:00
"legend" : {
"calcs" : [
"min" ,
"max" ,
"mean"
] ,
"displayMode" : "table" ,
"placement" : "right" ,
"showLegend" : true
} ,
"tooltip" : {
"mode" : "multi" ,
"sort" : "none"
}
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
} ,
2026-05-18 20:55:03 -07:00
"pluginVersion" : "9.1.7" ,
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
"targets" : [
{
2026-05-18 22:22:21 -07:00
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
"alias" : "" ,
"format" : "time_series" ,
"rawSql" : "SELECT\n $__time(interval_time),\n v4_prefixes,v6_prefixes,v4_with_rpki,v6_with_rpki,v4_with_irr,v6_with_irr\nFROM\n stats_ip_origins\nWHERE\n $__timeFilter(interval_time) and asn = [[asn_num]]\nORDER BY interval_time asc\n" ,
"refId" : "A"
}
] ,
"title" : "Originating Prefix Trend" ,
2026-05-18 20:55:03 -07:00
"type" : "timeseries"
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
} ,
{
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
"fieldConfig" : {
"defaults" : {
"color" : {
"mode" : "thresholds"
} ,
"mappings" : [
{
"options" : {
"match" : "null" ,
"result" : {
"text" : "N/A"
}
} ,
"type" : "special"
}
] ,
"thresholds" : {
"mode" : "absolute" ,
"steps" : [
{
"color" : "green" ,
"value" : null
} ,
{
"color" : "red" ,
"value" : 80
}
]
} ,
"unit" : "none"
} ,
"overrides" : [ ]
} ,
"gridPos" : {
"h" : 4 ,
"w" : 4 ,
"x" : 5 ,
"y" : 4
} ,
"id" : 12 ,
"links" : [ ] ,
"maxDataPoints" : 100 ,
"options" : {
"colorMode" : "background" ,
"graphMode" : "none" ,
"justifyMode" : "auto" ,
"orientation" : "horizontal" ,
"reduceOptions" : {
"calcs" : [
"mean"
] ,
"fields" : "" ,
"values" : false
} ,
"text" : { } ,
"textMode" : "auto"
} ,
"pluginVersion" : "8.5.4" ,
"targets" : [
{
"alias" : "" ,
"format" : "table" ,
"group" : [ ] ,
"hide" : false ,
"metricColumn" : "none" ,
"rawQuery" : true ,
"rawSql" : "SELECT count(distinct asn) as count\nFROM (\n\tSELECT\n\t\t\tas_path[(array_positions(as_path, ${asn_num}::bigint))[cardinality(array_positions(as_path, ${asn_num}::bigint)) ] + 1] as asn\n\t\tFROM base_attrs a\n\t\tWHERE as_path && '{${asn_num}}'\n) d\nWHERE asn is not null" ,
"refId" : "A" ,
"select" : [
[
{
"params" : [
"value"
] ,
"type" : "column"
}
]
] ,
"timeColumn" : "time" ,
"where" : [
{
"name" : "$__timeFilter" ,
"params" : [ ] ,
"type" : "macro"
}
]
}
] ,
"title" : "Downstream ASNs" ,
"type" : "stat"
} ,
{
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
"fieldConfig" : {
"defaults" : {
"color" : {
"mode" : "thresholds"
} ,
"custom" : {
"align" : "auto" ,
"displayMode" : "auto" ,
"inspect" : false
} ,
"decimals" : 2 ,
"displayName" : "" ,
"mappings" : [ ] ,
"thresholds" : {
"mode" : "absolute" ,
"steps" : [
{
"color" : "green" ,
"value" : null
} ,
{
"color" : "red" ,
"value" : 80
}
]
} ,
"unit" : "none"
} ,
"overrides" : [
{
"matcher" : {
"id" : "byName" ,
"options" : "as_name"
} ,
"properties" : [
{
"id" : "unit" ,
"value" : "none"
} ,
{
"id" : "links" ,
"value" : [
{
"targetBlank" : true ,
"title" : "Click to see ASN history" ,
"url" : "/grafana/d/prefix-hist-asn/prefix-history-by-asn?var-origin_as=$asn_num"
}
]
} ,
{
"id" : "custom.align"
}
]
}
]
} ,
"gridPos" : {
"h" : 7 ,
"w" : 24 ,
"x" : 0 ,
"y" : 8
} ,
"id" : 2 ,
"links" : [ ] ,
"options" : {
"footer" : {
"fields" : "" ,
"reducer" : [
"sum"
] ,
"show" : false
} ,
"showHeader" : true
} ,
"pluginVersion" : "8.5.4" ,
"targets" : [
{
"alias" : "" ,
"format" : "table" ,
"group" : [ ] ,
"hide" : false ,
"metricColumn" : "none" ,
"rawQuery" : true ,
"rawSql" : "select as_name,org_id,org_name,address,city,state_prov,country,remarks,raw_output,source\n from info_asn i \n where asn = [[asn_num]]" ,
"refId" : "A" ,
"select" : [
[
{
"params" : [
"value"
] ,
"type" : "column"
}
]
] ,
"timeColumn" : "time" ,
"where" : [
{
"name" : "$__timeFilter" ,
"params" : [ ] ,
"type" : "macro"
}
]
}
] ,
"title" : "ASN Info" ,
"transformations" : [
{
"id" : "merge" ,
"options" : {
"reducers" : [ ]
}
}
] ,
"type" : "table"
} ,
{
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
"fieldConfig" : {
"defaults" : {
"color" : {
"mode" : "thresholds"
} ,
"custom" : {
"align" : "auto" ,
"displayMode" : "auto" ,
"filterable" : true ,
"inspect" : false
} ,
"decimals" : 2 ,
"displayName" : "" ,
"mappings" : [ ] ,
"thresholds" : {
"mode" : "absolute" ,
"steps" : [
{
"color" : "green" ,
"value" : null
} ,
{
"color" : "red" ,
"value" : 80
}
]
} ,
"unit" : "none"
} ,
"overrides" : [
{
"matcher" : {
"id" : "byName" ,
"options" : "ASN"
} ,
"properties" : [
{
"id" : "unit" ,
"value" : "none"
} ,
{
"id" : "custom.align"
} ,
{
"id" : "decimals" ,
"value" : 0
}
]
}
]
} ,
"gridPos" : {
"h" : 9 ,
"w" : 12 ,
"x" : 0 ,
"y" : 15
} ,
"id" : 8 ,
"links" : [ ] ,
"options" : {
"footer" : {
"fields" : "" ,
"reducer" : [
"sum"
] ,
"show" : false
} ,
"showHeader" : true
} ,
"pluginVersion" : "8.5.4" ,
"targets" : [
{
"alias" : "" ,
"format" : "table" ,
"group" : [ ] ,
"metricColumn" : "none" ,
"rawQuery" : true ,
"rawSql" : "SELECT d.asn as \"ASN\",\n\tmax(as_name) as \"Name\",\n\tmax(org_name) as \"Org Name\",\n\tmax(org_id) as \"Org ID\",\n\tmax(country) as \"Country\",\n\tmax(city) AS \"City\",\n\tmax(state_prov) as \"State Prov\",\n\tmax(source) as \"Source\"\nFROM (\n\tSELECT\n\t\t\tas_path[array_position(as_path, ${asn_num}::bigint) - 1] as asn\n\t\tFROM base_attrs a\n\t\tWHERE as_path && '{${asn_num}}'\n) d\nLEFT JOIN info_asn i ON (i.asn = d.asn)\nWHERE d.asn is not null\nGROUP BY d.asn" ,
"refId" : "A" ,
"select" : [
[
{
"params" : [
"value"
] ,
"type" : "column"
}
]
] ,
"timeColumn" : "time" ,
"where" : [
{
"name" : "$__timeFilter" ,
"params" : [ ] ,
"type" : "macro"
}
]
}
] ,
"title" : "Upstream ASNs" ,
"transformations" : [
{
"id" : "merge" ,
"options" : {
"reducers" : [ ]
}
}
] ,
"type" : "table"
} ,
{
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
"fieldConfig" : {
"defaults" : {
"color" : {
"mode" : "thresholds"
} ,
"custom" : {
"align" : "auto" ,
"displayMode" : "auto" ,
"inspect" : false
} ,
"decimals" : 0 ,
"displayName" : "" ,
"mappings" : [ ] ,
"thresholds" : {
"mode" : "absolute" ,
"steps" : [
{
"color" : "green" ,
"value" : null
} ,
{
"color" : "red" ,
"value" : 80
}
]
} ,
"unit" : "none"
} ,
"overrides" : [
{
"matcher" : {
"id" : "byName" ,
"options" : "Time"
} ,
"properties" : [
{
"id" : "displayName" ,
"value" : "Time"
} ,
{
"id" : "unit" ,
"value" : "time: YYYY-MM-DD HH:mm:ss"
} ,
{
"id" : "custom.align"
}
]
} ,
{
"matcher" : {
"id" : "byName" ,
"options" : "ASN"
} ,
"properties" : [
{
"id" : "unit" ,
"value" : "none"
} ,
{
"id" : "custom.align"
}
]
}
]
} ,
"gridPos" : {
"h" : 9 ,
"w" : 12 ,
"x" : 12 ,
"y" : 15
} ,
"id" : 9 ,
"links" : [ ] ,
"options" : {
"footer" : {
"fields" : "" ,
"reducer" : [
"sum"
] ,
"show" : false
} ,
"showHeader" : true
} ,
"pluginVersion" : "8.5.4" ,
"targets" : [
{
"alias" : "" ,
"format" : "table" ,
"group" : [ ] ,
"metricColumn" : "none" ,
"rawQuery" : true ,
"rawSql" : "SELECT d.asn as \"ASN\",\n\tmax(as_name) as \"Name\",\n\tmax(org_name) as \"Org Name\",\n\tmax(org_id) as \"Org ID\",\n\tmax(country) as \"Country\",\n\tmax(city) AS \"City\",\n\tmax(state_prov) as \"State Prov\",\n\tmax(source) as \"Source\"\nFROM (\n\tSELECT\n\t\t\tas_path[(array_positions(as_path, ${asn_num}::bigint))[cardinality(array_positions(as_path, ${asn_num}::bigint)) ] + 1] as asn\n\t\tFROM base_attrs a\n\t\tWHERE as_path && '{${asn_num}}'\n) d\nLEFT JOIN info_asn i ON (i.asn = d.asn)\nWHERE d.asn is not null\nGROUP BY d.asn" ,
"refId" : "A" ,
"select" : [
[
{
"params" : [
"value"
] ,
"type" : "column"
}
]
] ,
"timeColumn" : "time" ,
"where" : [
{
"name" : "$__timeFilter" ,
"params" : [ ] ,
"type" : "macro"
}
]
}
] ,
"title" : "Downstream ASNs" ,
"transformations" : [
{
"id" : "merge" ,
"options" : {
"reducers" : [ ]
}
}
] ,
"type" : "table"
} ,
{
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
"description" : "" ,
"fieldConfig" : {
"defaults" : {
"color" : {
"mode" : "thresholds"
} ,
"custom" : {
"align" : "auto" ,
"displayMode" : "auto" ,
"inspect" : false
} ,
"decimals" : 2 ,
"displayName" : "" ,
"mappings" : [ ] ,
"thresholds" : {
"mode" : "absolute" ,
"steps" : [
{
"color" : "green" ,
"value" : null
} ,
{
"color" : "red" ,
"value" : 80
}
]
} ,
"unit" : "string"
} ,
"overrides" : [
{
"matcher" : {
"id" : "byName" ,
"options" : "Prefix"
} ,
"properties" : [
{
"id" : "unit" ,
"value" : "short"
} ,
{
"id" : "decimals" ,
"value" : 2
} ,
{
"id" : "links" ,
"value" : [
{
"targetBlank" : true ,
"title" : "Click for Prefix History" ,
"url" : "/grafana/d/vCRvHSFiz/prefix-history-by-prefix?orgId=1&var-prefix=${__cell}"
}
]
} ,
{
"id" : "custom.align"
}
]
}
]
} ,
"gridPos" : {
"h" : 13 ,
"w" : 5 ,
"x" : 0 ,
"y" : 24
} ,
"id" : 15 ,
"links" : [ ] ,
"options" : {
"footer" : {
"fields" : "" ,
"reducer" : [
"sum"
] ,
"show" : false
} ,
"showHeader" : true
} ,
"pluginVersion" : "8.5.4" ,
"targets" : [
{
"alias" : "" ,
"format" : "table" ,
"group" : [ ] ,
"metricColumn" : "none" ,
"rawQuery" : true ,
"rawSql" : "SELECT r.aggregate\n\tFROM (\n\t\tSELECT distinct w.prefix,\n\t\t\t\t FIRST_VALUE(a.prefix) OVER (\n\t\t\t\t\t\tPARTITION BY w.prefix ORDER BY a.prefix ASC) as aggregate\n\t\t\t\tFROM (\n\t\t\t\t\tSELECT prefix\n\t\t\t\t\t\tFROM global_ip_rib\n\t\t\t\t\t\tWHERE iswithdrawn = false\n\t\t\t\t\t\t\tAND recv_origin_as = $asn_num\n\t\t\t\t\t\t\tAND prefix_len > 0 and prefix_len <= 25\n\t\t\t\t\t\tGROUP BY prefix\n\t\t\t\t\t) w\n\t\t\t\t\tJOIN (\n\t\t\t\t\tSELECT distinct prefix\n\t\t\t\t\t\tFROM global_ip_rib\n\t\t\t\t\t\tWHERE iswithdrawn = false \n\t\t\t\t\t\t\tAND recv_origin_as = $asn_num\n\t\t\t\t\t\t\tAND prefix_len > 0 and prefix_len <= 25\n\t\t\t\t\t) a ON (w.prefix <<= a.prefix)\n\t\t) r\n\tGROUP BY r.aggregate\n\tORDER BY aggregate;" ,
"refId" : "A" ,
"select" : [
[
{
"params" : [
"value"
] ,
"type" : "column"
}
]
] ,
"timeColumn" : "time" ,
"where" : [
{
"name" : "$__timeFilter" ,
"params" : [ ] ,
"type" : "macro"
}
]
}
] ,
"title" : "Aggregates" ,
"transformations" : [
{
"id" : "merge" ,
"options" : {
"reducers" : [ ]
}
}
] ,
"type" : "table"
} ,
{
"datasource" : {
"type" : "postgres" ,
"uid" : "obmp_postgres"
} ,
"description" : "" ,
"fieldConfig" : {
"defaults" : {
"color" : {
"mode" : "thresholds"
} ,
"custom" : {
"align" : "auto" ,
"displayMode" : "auto" ,
"inspect" : false
} ,
"decimals" : 0 ,
"displayName" : "" ,
"mappings" : [ ] ,
"thresholds" : {
"mode" : "absolute" ,
"steps" : [
{
"color" : "green" ,
"value" : null
} ,
{
"color" : "red" ,
"value" : 80
}
]
} ,
"unit" : "none"
} ,
"overrides" : [
{
"matcher" : {
"id" : "byName" ,
"options" : "Prefix"
} ,
"properties" : [
{
"id" : "unit" ,
"value" : "none"
} ,
{
"id" : "decimals" ,
"value" : 0
} ,
{
"id" : "links" ,
"value" : [
{
"targetBlank" : true ,
"title" : "Click for Looking Glass" ,
"url" : "d/lookingglass/looking-glass?orgId=1&var-input=${__value.text}&var-prefix=${__value.text}"
}
]
} ,
{
"id" : "custom.align"
}
]
}
]
} ,
"gridPos" : {
"h" : 13 ,
"w" : 19 ,
"x" : 5 ,
"y" : 24
} ,
"id" : 4 ,
"links" : [ ] ,
"options" : {
"footer" : {
"fields" : "" ,
"reducer" : [
"sum"
] ,
"show" : false
} ,
"showHeader" : true
} ,
"pluginVersion" : "8.5.4" ,
"targets" : [
{
"alias" : "" ,
"format" : "table" ,
"group" : [ ] ,
"metricColumn" : "none" ,
"rawQuery" : true ,
"rawSql" : "SELECT r.prefix as \"Prefix\",r.rpki_origin_as AS \"RPKI Origin AS\",i.origin_as as \"IRR Origin AS\",\"Last Change\", i.descr as \"IRR Description\", i.source as \"IRR Source\"\n\nFROM (\n select\n prefix,rpki_origin_as,\n max(timestamp) as \"Last Change\"\n FROM global_ip_rib\n WHERE recv_origin_as = [[asn_num]]\n GROUP BY prefix,rpki_origin_as\n ) r\n LEFT JOIN info_route i ON (i.prefix = r.prefix)\n\n\n" ,
"refId" : "A" ,
"select" : [
[
{
"params" : [
"value"
] ,
"type" : "column"
}
]
] ,
"timeColumn" : "time" ,
"where" : [
{
"name" : "$__timeFilter" ,
"params" : [ ] ,
"type" : "macro"
}
]
}
] ,
"title" : "Advertised Prefixes (multiple shown for all IRR entries)" ,
"transformations" : [
{
"id" : "merge" ,
"options" : {
"reducers" : [ ]
}
}
] ,
"type" : "table"
}
] ,
"schemaVersion" : 36 ,
"style" : "dark" ,
"tags" : [
2026-05-18 20:55:03 -07:00
"obmp" ,
"obmp-nav" ,
"operations"
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
] ,
"templating" : {
"list" : [
{
2026-05-18 22:22:21 -07:00
"name" : "asn_num" ,
"type" : "textbox" ,
"label" : "Origin AS" ,
"description" : "Enter an origin AS number \u2014 every panel shows that AS's prefixes, upstreams, and downstreams from the BMP RIB." ,
"query" : "13335" ,
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
"current" : {
2026-05-18 22:22:21 -07:00
"text" : "13335" ,
"value" : "13335"
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
} ,
"options" : [
{
2026-05-18 22:22:21 -07:00
"text" : "13335" ,
"value" : "13335" ,
"selected" : true
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
}
] ,
2026-05-18 22:22:21 -07:00
"hide" : 0 ,
"skipUrlSync" : false
Add ExaBGP route injector, Grafana dashboards, and full documentation
- Add exabgp/ container: ExaBGP 5.x + Flask REST API for on-demand BGP
route injection into CML IOS-XR lab (AS 65020 via eBGP from AS 65100)
- Add 6 injection scenarios: internet_sample, churn, blackhole, anycast,
full_table, lab_prefixes
- Add inject.py CLI wrapper for the ExaBGP API
- Add iosxr_bgp_config.md with IOS-XR neighbor config and NETCONF script
- Add obmp-grafana/ dashboards and provisioning (17 dashboards)
- Update docker-compose.yml: add exabgp service, fix Kafka external
listener IP, extend log retention from 90min to 720min
- Add DOCS.md: full project documentation including architecture, setup,
user guide, sanity checks, troubleshooting, and command reference
- Update .gitignore: exclude .env and .claude/
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:46:37 -07:00
}
]
} ,
"time" : {
"from" : "now-3h" ,
"to" : "now"
} ,
"timepicker" : {
"refresh_intervals" : [
"5s" ,
"10s" ,
"30s" ,
"1m" ,
"5m" ,
"15m" ,
"30m" ,
"1h" ,
"2h" ,
"1d"
] ,
"time_options" : [
"5m" ,
"15m" ,
"1h" ,
"6h" ,
"12h" ,
"24h" ,
"2d" ,
"7d" ,
"30d"
]
} ,
"timezone" : "" ,
"title" : "ASN View" ,
"uid" : "asnview-agg" ,
"version" : 5 ,
"weekStart" : ""
}