diff --git a/.gitignore b/.gitignore index a44f2bc..67101b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .idea *.log +.env +.claude/ diff --git a/DOCS.md b/DOCS.md new file mode 100644 index 0000000..a60f07d --- /dev/null +++ b/DOCS.md @@ -0,0 +1,746 @@ +# OpenBMP + ExaBGP Route Injector — Full Documentation + +## Table of Contents + +1. [What Is This Project?](#1-what-is-this-project) +2. [Architecture](#2-architecture) +3. [Prerequisites](#3-prerequisites) +4. [Initial Setup (First Time)](#4-initial-setup-first-time) +5. [IOS-XR Router Configuration](#5-ios-xr-router-configuration) +6. [Starting and Stopping](#6-starting-and-stopping) +7. [Route Injection User Guide](#7-route-injection-user-guide) +8. [Grafana Dashboards](#8-grafana-dashboards) +9. [Sanity Checks](#9-sanity-checks) +10. [Relevant Commands Reference](#10-relevant-commands-reference) +11. [Troubleshooting](#11-troubleshooting) +12. [Data Retention](#12-data-retention) +13. [Environment Variables Reference](#13-environment-variables-reference) + +--- + +## 1. What Is This Project? + +This is a **BGP Monitoring Platform (BMP) lab stack** deployed via Docker Compose. It collects, stores, and visualizes BGP routing data from a Cisco IOS-XR lab network (running in Cisco Modeling Labs / CML). + +**What it does:** + +- Receives BMP (BGP Monitoring Protocol, RFC 7854) telemetry from routers on TCP port 5000 +- Streams BMP data through Kafka into a TimescaleDB/PostgreSQL database +- Provides 17 Grafana dashboards for real-time and historical BGP analysis +- Includes an **ExaBGP route injector** that peers with the two CORE routers and injects synthetic BGP routes, enabling testing of BGP policy, route propagation, and Grafana dashboards without needing internet connectivity + +**The lab network:** + +- AS 65020 — 9 Cisco IOS-XR routers in CML (iBGP full mesh via route-reflectors) +- AS 65100 — ExaBGP container (eBGP peer to both CORE routers) +- CORE-01: `10.100.0.100` (CML-R9K-CORE-01) +- CORE-02: `10.100.0.200` (CML-R9K-CORE-02) +- Host IP: `10.40.40.202` (ExaBGP binds here; reachable from CML management network) + +--- + +## 2. Architecture + +``` +IOS-XR Routers (9x, AS 65020) + BMP telemetry on TCP 5000 + | + v + obmp-collector (openbmp/collector:2.2.3) + | + v + obmp-kafka (confluentinc/cp-kafka:7.1.1) + + obmp-zookeeper (confluentinc/cp-zookeeper:7.1.1) + | + v + obmp-psql-app (openbmp/psql-app:2.2.2) + Java consumer — writes parsed BGP data to PostgreSQL + | + v + obmp-psql (openbmp/postgres:2.2.1) + PostgreSQL 14 + TimescaleDB + | + +---------> obmp-grafana (grafana/grafana:9.1.7) :3000 + | 17 dashboards, PostgreSQL datasource + +---------> obmp-whois (openbmp/whois:2.2.0) :4300 + WHOIS query server backed by the DB + +ExaBGP (obmp-exabgp, built locally) + python:3.11-slim + exabgp 5.x + Flask API + Peers eBGP to CORE-01 and CORE-02 (AS 65100 -> AS 65020) + HTTP API on :5050 — inject/withdraw routes on demand + Routes propagate via iBGP mesh to all 9 routers -> BMP -> DB -> Grafana +``` + +### Container Summary + +| Container | Image | Port(s) | Role | +|-----------|-------|---------|------| +| obmp-zookeeper | confluentinc/cp-zookeeper:7.1.1 | 2181 (internal) | Kafka coordination | +| obmp-kafka | confluentinc/cp-kafka:7.1.1 | 9092 | Message broker | +| obmp-collector | openbmp/collector:2.2.3 | 5000 | BMP receiver | +| obmp-psql-app | openbmp/psql-app:2.2.2 | 9005 | Kafka→PostgreSQL consumer | +| obmp-psql | openbmp/postgres:2.2.1 | 5432 | TimescaleDB storage | +| obmp-grafana | grafana/grafana:9.1.7 | 3000 | Visualization | +| obmp-whois | openbmp/whois:2.2.0 | 4300 | WHOIS query server | +| obmp-exabgp | local build | 5050 (host net) | BGP route injector | + +--- + +## 3. Prerequisites + +- Docker Engine (20.10+) and Docker Compose v2 +- Host IP `10.40.40.202` reachable from the CML management network +- CML routers with BMP configured pointing to `10.40.40.202:5000` +- CML CORE routers configured with ExaBGP as eBGP neighbor (see Section 5) +- `OBMP_DATA_ROOT` directory created (default: `/var/openbmp`) + +--- + +## 4. Initial Setup (First Time) + +### 4.1 Clone the repository + +```bash +git clone +cd obmp-docker +``` + +### 4.2 Create persistent data directories + +```bash +export OBMP_DATA_ROOT=/var/openbmp +sudo mkdir -p $OBMP_DATA_ROOT +mkdir -p ${OBMP_DATA_ROOT}/config +mkdir -p ${OBMP_DATA_ROOT}/kafka-data +mkdir -p ${OBMP_DATA_ROOT}/zk-data +mkdir -p ${OBMP_DATA_ROOT}/zk-log +mkdir -p ${OBMP_DATA_ROOT}/postgres/data +mkdir -p ${OBMP_DATA_ROOT}/postgres/ts +mkdir -p ${OBMP_DATA_ROOT}/grafana +mkdir -p ${OBMP_DATA_ROOT}/grafana/dashboards +sudo chmod -R 777 $OBMP_DATA_ROOT +``` + +### 4.3 Initialise the database (first run only) + +Create the init trigger file — this causes psql-app to create all tables on startup: + +```bash +touch ${OBMP_DATA_ROOT}/config/init_db +``` + +> **Warning:** Do not create this file on subsequent runs unless you want to wipe and recreate the entire database. + +### 4.4 Copy Grafana provisioning files + +```bash +cp -r obmp-grafana/provisioning ${OBMP_DATA_ROOT}/grafana/ +cp -r obmp-grafana/dashboards ${OBMP_DATA_ROOT}/grafana/ +``` + +### 4.5 Start the stack + +```bash +OBMP_DATA_ROOT=/var/openbmp docker compose -p obmp up -d +``` + +Wait ~2 minutes for all services to initialise (especially PostgreSQL and psql-app which run schema migrations). + +### 4.6 Verify everything is running + +```bash +docker compose -p obmp ps +docker compose -p obmp logs --tail=20 psql-app +``` + +--- + +## 5. IOS-XR Router Configuration + +The ExaBGP container peers eBGP with both CORE routers. Each CORE router must be configured with: + +### 5.1 Route policies (apply once per router) + +``` +route-policy EXABGP_IN + pass +end-policy + +route-policy EXABGP_OUT + drop +end-policy +``` + +### 5.2 BGP neighbor block + +``` +router bgp 65020 + neighbor 10.40.40.202 + remote-as 65100 + description ExaBGP-Route-Injector + ebgp-multihop 5 + update-source MgmtEth0/RP0/CPU0/0 + ! + address-family ipv4 unicast + route-policy EXABGP_IN in + route-policy EXABGP_OUT out + next-hop-self + ! + ! +! +``` + +### 5.3 Static route for next-hop resolution + +IOS-XR BGP does not use the default route (0.0.0.0/0) to resolve BGP next-hops. A more-specific static route for the ExaBGP host subnet is required in the default VRF: + +``` +router static + address-family ipv4 unicast + 10.40.40.0/24 10.100.0.254 + ! +! +``` + +### 5.4 Config notes + +| Knob | Why | +|------|-----| +| `remote-as 65100` | ExaBGP presents as AS 65100 (eBGP to your AS 65020 mesh) | +| `ebgp-multihop 5` | Host and router are on different subnets | +| `update-source MgmtEth0/RP0/CPU0/0` | ExaBGP is reachable via the management interface | +| `next-hop-self` | Replace ExaBGP's next-hop (10.40.40.202) with the CORE router's address when reflecting into iBGP — ensures all routers can resolve the next-hop | +| `EXABGP_OUT` drops | Prevents the lab from advertising its own prefixes back to ExaBGP | +| Static route | Required: IOS-XR BGP will not install injected routes as bestpaths without a specific route to the next-hop | + +### 5.5 NETCONF alternative + +See `exabgp/iosxr_bgp_config.md` for a Python/ncclient script that pushes all of the above config programmatically. + +Credentials: `username=webui`, `password=cisco`, port 830. + +--- + +## 6. Starting and Stopping + +### Start all services + +```bash +OBMP_DATA_ROOT=/var/openbmp docker compose -p obmp up -d +``` + +### Stop all services (preserve data) + +```bash +docker compose -p obmp down +``` + +### Stop and remove all data (full reset) + +```bash +docker compose -p obmp down -v +sudo rm -rf /var/openbmp +``` + +### Rebuild the ExaBGP container (after code changes) + +```bash +docker compose -p obmp build exabgp +docker compose -p obmp up -d exabgp +``` + +### Restart a single service + +```bash +docker compose -p obmp restart +# e.g.: +docker compose -p obmp restart exabgp +docker compose -p obmp restart psql-app +``` + +--- + +## 7. Route Injection User Guide + +The ExaBGP container exposes a Flask REST API on port 5050 (host network). The `inject.py` CLI wraps this API. + +### 7.1 Setup + +```bash +cd exabgp +pip install requests # only needed if running inject.py from the host +``` + +### 7.2 Check status + +```bash +python3 inject.py status +``` + +Output shows API health, active route count, and peer states: + +```json +{ + "status": "ok", + "active_routes": 77, + "peers": { + "10.100.0.100": {"state": "up", "updated": "2026-03-05T10:00:00Z"}, + "10.100.0.200": {"state": "up", "updated": "2026-03-05T10:00:00Z"} + } +} +``` + +### 7.3 List available scenarios + +```bash +python3 inject.py scenarios +``` + +| Scenario | Routes | Description | +|----------|--------|-------------| +| `internet_sample` | ~94 | Partial internet table — real public prefixes, realistic AS paths (Cloudflare, Google, AWS, Azure, etc.) | +| `churn` | 30 | RFC documentation prefixes for announce/withdraw churn testing | +| `blackhole` | 5 | /32 prefixes with RTBH community (65100:666 + 65535:666) | +| `anycast` | 3 | Same prefixes with varying AS paths and MEDs (best-path testing) | +| `full_table` | 500+ | Large partial internet table with synthetic /24s | +| `lab_prefixes` | 8 | Enterprise/SP-style routes with communities and local-pref | + +### 7.4 Load a scenario + +```bash +python3 inject.py scenario internet_sample +``` + +Routes propagate: ExaBGP → CORE-01/CORE-02 (eBGP) → all 9 routers (iBGP) → BMP → Kafka → PostgreSQL → Grafana. + +### 7.5 Withdraw a scenario + +```bash +python3 inject.py withdraw-scenario internet_sample +``` + +### 7.6 Announce individual prefixes + +```bash +python3 inject.py announce 10.0.0.0/8 \ + --as-path 65100 3356 15169 \ + --community 65100:100 \ + --med 100 +``` + +### 7.7 Withdraw individual prefixes + +```bash +python3 inject.py withdraw 10.0.0.0/8 +``` + +### 7.8 Withdraw everything + +```bash +python3 inject.py withdraw-all +``` + +### 7.9 Generate route churn (populate history tables) + +The `churn` command cycles the churn scenario repeatedly, generating `ip_rib_log` and `stats_chg_*` entries that power Grafana's history dashboards. + +```bash +# 5 cycles, 30 seconds apart +python3 inject.py churn --count 5 --interval 30 + +# Run indefinitely until Ctrl+C +python3 inject.py churn +``` + +### 7.10 REST API directly (curl) + +```bash +BASE=http://localhost:5050 + +# Health +curl $BASE/healthz + +# List scenarios +curl $BASE/scenarios + +# Load scenario +curl -X POST $BASE/scenario/internet_sample + +# Announce custom prefix +curl -X POST $BASE/announce \ + -H 'Content-Type: application/json' \ + -d '{"prefixes":["10.0.0.0/8"],"as_path":[65100,3356,15169],"communities":["65100:100"]}' + +# Withdraw all +curl -X POST $BASE/withdraw/all + +# Peer state +curl $BASE/peers +``` + +### 7.11 Adding custom scenarios + +Edit `exabgp/scenarios/__init__.py`. Add an entry to `SCENARIOS` following the existing pattern: + +```python +SCENARIOS['my_scenario'] = { + 'description': 'My custom routes', + 'routes': [ + _r('192.0.2.0/24', [65100, 65200], communities=['65100:100']), + ], +} +``` + +The `scenarios/` directory is volume-mounted into the container, so changes are live without rebuilding. However, the Python module is imported at container start — **restart the container** after editing: + +```bash +docker compose -p obmp restart exabgp +``` + +--- + +## 8. Grafana Dashboards + +Access: `http://10.40.40.202:3000` +Default credentials: `admin` / `openbmp` (anonymous access also enabled) + +### Dashboard Categories + +| Category | Dashboard | Description | +|----------|-----------|-------------| +| General | OBMP Home | Overview / landing page | +| Base | Inventory | Router and peer inventory | +| Base | Looking Glass | Real-time RIB lookup by prefix | +| Base | ASN View | ASN-level routing view | +| History | Prefix History | Route change history for a prefix | +| History | Prefix History by ASN | Filtered by origin AS | +| History | Prefix History by Community | Filtered by BGP community | +| Tops | Top Prefixes | Most-updated prefixes | +| Tops | Top L3VPN Prefixes | L3VPN equivalent | +| Link State | LS Nodes | IS-IS link-state node database | +| Link State | LS Links | IS-IS link-state link database | +| Link State | LS Topology | Network topology map | +| Link State | LS Prefixes | Link-state prefix database | +| Link State | LS History | Link-state change history | +| L3VPN | L3VPN Looking Glass | VPN RIB lookup | +| L3VPN | L3VPN Prefix History | VPN route change history | +| L3VPN | L3VPN RIB Browser | Full VPN RIB browser | + +> History dashboards require `ip_rib_log` and `stats_chg_*` table data. Run `inject.py churn` to populate these. + +--- + +## 9. Sanity Checks + +### 9.1 All containers running + +```bash +docker compose -p obmp ps +``` + +All containers should show `running`. If any are restarting, check logs: + +```bash +docker compose -p obmp logs --tail=50 +``` + +### 9.2 ExaBGP peers up + +```bash +python3 exabgp/inject.py status +``` + +Both `10.100.0.100` and `10.100.0.200` should show `"state": "up"`. + +Or check from the router side: + +``` +show bgp neighbors 10.40.40.202 +show bgp summary | inc 10.40.40.202 +``` + +### 9.3 Routes accepted by CORE routers + +After loading `internet_sample`: + +```bash +# On CORE-01 or CORE-02: +show bgp summary +# Expect: 77 accepted prefixes, 77 are bestpaths from 10.40.40.202 + +show bgp 8.8.8.0/24 +# Expect: best path via 10.40.40.202 (eBGP), also iBGP copies from other routers +``` + +### 9.4 Routes in OpenBMP database + +```bash +docker exec -it obmp-psql psql -U openbmp -c " + SELECT count(DISTINCT prefix) AS unique_prefixes, + count(DISTINCT peer_hash_id) AS peers_reporting + FROM ip_rib + WHERE isIPv4 = true AND isWithdrawn = false; +" +``` + +Expect `~129 unique prefixes` and `56 peers_reporting` (9 routers × ~6 peers each) after loading `internet_sample`. + +### 9.5 Kafka is healthy + +```bash +docker exec -it obmp-kafka kafka-topics --bootstrap-server localhost:29092 --list +``` + +Should show topics like `openbmp.parsed.unicast_prefix`, `openbmp.parsed.peer`, etc. + +### 9.6 Grafana datasource + +Open `http://10.40.40.202:3000` → Configuration → Data Sources → OpenBMP → Test. +Should return "Database Connection OK". + +### 9.7 BMP collector receiving data + +```bash +docker compose -p obmp logs --tail=30 collector +``` + +Should show connections from router management IPs. + +### 9.8 psql-app consumer is caught up + +```bash +docker compose -p obmp logs --tail=30 psql-app +``` + +Should show periodic cron job outputs (RPKI sync, IRR sync, global_ip_rib updates). + +--- + +## 10. Relevant Commands Reference + +### Docker Compose + +```bash +# Start stack +OBMP_DATA_ROOT=/var/openbmp docker compose -p obmp up -d + +# Stop stack +docker compose -p obmp down + +# Show status +docker compose -p obmp ps + +# Follow logs (all services) +docker compose -p obmp logs -f + +# Follow logs (specific service) +docker compose -p obmp logs -f exabgp +docker compose -p obmp logs -f psql-app +docker compose -p obmp logs -f collector + +# Rebuild and restart ExaBGP +docker compose -p obmp build exabgp && docker compose -p obmp up -d exabgp + +# Restart a service +docker compose -p obmp restart psql-app +``` + +### Route Injection (from `exabgp/` directory) + +```bash +# API health and peer states +python3 inject.py status + +# List active routes +python3 inject.py routes + +# List scenarios +python3 inject.py scenarios + +# Load a scenario +python3 inject.py scenario internet_sample +python3 inject.py scenario churn +python3 inject.py scenario blackhole +python3 inject.py scenario full_table +python3 inject.py scenario lab_prefixes + +# Withdraw a scenario +python3 inject.py withdraw-scenario internet_sample + +# Withdraw all active routes +python3 inject.py withdraw-all + +# Announce a specific prefix +python3 inject.py announce 10.0.0.0/8 --as-path 65100 3356 15169 --community 65100:100 + +# Withdraw a specific prefix +python3 inject.py withdraw 10.0.0.0/8 + +# Run churn (populate history tables) +python3 inject.py churn --count 5 --interval 30 +``` + +### Database Queries + +```bash +# Connect to database +docker exec -it obmp-psql psql -U openbmp -d openbmp + +# Count unique prefixes in RIB +SELECT count(DISTINCT prefix) FROM ip_rib WHERE isIPv4=true AND isWithdrawn=false; + +# Show recent route changes +SELECT prefix, origin_as, iswithdrawn, timestamp +FROM ip_rib_log +ORDER BY timestamp DESC LIMIT 20; + +# Show peer summary +SELECT name, state, timestamp_last_updated +FROM bgp_peers +ORDER BY state, name; + +# Show routes from ExaBGP peer +SELECT prefix, origin_as, as_path +FROM ip_rib +WHERE peer_hash_id IN ( + SELECT hash_id FROM bgp_peers WHERE peer_addr = '10.40.40.202' +) +AND isWithdrawn = false; +``` + +### IOS-XR Verification (on router CLI) + +``` +show bgp neighbors 10.40.40.202 +show bgp neighbors 10.40.40.202 received routes +show bgp summary +show bgp 8.8.8.0/24 +show bgp 1.1.1.0/24 +show route 8.8.8.0/24 +``` + +--- + +## 11. Troubleshooting + +### ExaBGP container keeps restarting + +Check logs: + +```bash +docker compose -p obmp logs --tail=50 exabgp +``` + +Common causes and fixes: + +| Symptom | Cause | Fix | +|---------|-------|-----| +| Exits after "welcome" banner | Missing or wrong env file path | `startup.sh` generates `/usr/local/etc/exabgp/exabgp.env` — verify this path exists in container | +| Process `api` killed 5 times | Wrong Python path in conf | Conf uses `/usr/local/bin/python3` — correct for python:3.11-slim | +| `drop = true` in env | ExaBGP drops privileges to nobody, can't bind 179 | `startup.sh` patches `drop = false` — check the sed lines ran | +| `__pycache__ Permission denied` during build | Root-owned cache from previous container run | `.dockerignore` excludes `**/__pycache__` — confirm file exists | + +### BGP sessions not establishing + +1. Verify host IP `10.40.40.202` is reachable from CML management network: `ping 10.40.40.202` from router +2. Check ExaBGP peer state: `python3 exabgp/inject.py status` +3. On router: `show bgp neighbors 10.40.40.202` — look for error codes +4. Common IOS-XR errors: + - `no-update-source-config` — add `update-source MgmtEth0/RP0/CPU0/0` + - `no-ipv6-address` — ensure only IPv4 unicast AF is configured (no IPv6) + - TCP refused — check port 179 is reachable (ExaBGP uses `network_mode: host`) + +### Routes received but not bestpath + +IOS-XR BGP requires a specific route to resolve the BGP next-hop (10.40.40.202). The default route (0.0.0.0/0) is insufficient. + +``` +router static + address-family ipv4 unicast + 10.40.40.0/24 10.100.0.254 +``` + +Verify: `show bgp 1.1.1.0/24` — should show `Status: s (active), bestpath`. + +### Grafana shows no data + +1. Check datasource: Configuration → Data Sources → OpenBMP → Test +2. Verify psql-app is writing: `docker compose -p obmp logs psql-app` +3. Check the database directly (see database queries above) +4. History dashboards need route churn — run `python3 inject.py churn` + +### Kafka not starting + +Zookeeper must be healthy first. Check: + +```bash +docker compose -p obmp logs zookeeper +docker compose -p obmp restart kafka +``` + +### psql-app fails to start + +Usually a PostgreSQL connection issue or schema mismatch. Check: + +```bash +docker compose -p obmp logs psql-app +# If "relation does not exist" errors: re-trigger DB init +touch /var/openbmp/config/init_db +docker compose -p obmp restart psql-app +``` + +--- + +## 12. Data Retention + +Configured in `docker-compose.yml` via `POSTGRES_DROP_*` environment variables: + +| Table | Default Retention | +|-------|-------------------| +| peer_event_log | 1 year | +| stat_reports | 4 weeks | +| ip_rib_log | 4 weeks | +| alerts | 4 weeks | +| ls_nodes_log | 4 months | +| ls_links_log | 4 months | +| ls_prefixes_log | 4 months | +| stats_chg_byprefix | 4 weeks | +| stats_chg_byasn | 4 weeks | +| stats_chg_bypeer | 4 weeks | +| stats_ip_origins | 4 weeks | +| stats_peer_rib | 4 weeks | +| stats_peer_update_counts | 4 weeks | + +Adjust in `docker-compose.yml` under the `psql-app` service environment block. + +--- + +## 13. Environment Variables Reference + +### ExaBGP container + +| Variable | Default | Description | +|----------|---------|-------------| +| `EXABGP_LOCAL_IP` | `10.40.40.202` | Host IP ExaBGP binds to and uses as router-id | +| `EXABGP_LOCAL_AS` | `65100` | ExaBGP's AS number | +| `EXABGP_PEER_AS` | `65020` | AS of the IOS-XR lab | +| `EXABGP_PEER_1` | `10.100.0.100` | First CORE router to peer with | +| `EXABGP_PEER_2` | `10.100.0.200` | Second CORE router to peer with | +| `EXABGP_API_PORT` | `5050` | Flask API port | + +### psql-app container (key variables) + +| Variable | Default | Description | +|----------|---------|-------------| +| `MEM` | `3` | JVM heap in GB | +| `ENABLE_RPKI` | `1` | Enable RPKI sync from Cloudflare | +| `ENABLE_IRR` | `1` | Enable IRR sync | +| `ENABLE_DBIP` | `1` | Enable DB-IP geolocation import | +| `POSTGRES_REPORT_WINDOW` | `8 minute` | Aggregation window for summary tables | + +### inject.py (CLI) + +| Variable | Default | Description | +|----------|---------|-------------| +| `EXABGP_API` | `http://localhost:5050` | ExaBGP API base URL | diff --git a/docker-compose.yml b/docker-compose.yml index 69d44a4..28acc94 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -45,13 +45,12 @@ services: # Change/add listeners based on your FQDN that the host and other containers can access. You can use # an IP address as well. By default, only within the compose/containers can Kafka be accesssed # using port 29092. Outside access can be enabled, but you should use an FQDN listener. - #KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://:9092 - KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://obmp-kafka:29092 + KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://obmp-kafka:29092,PLAINTEXT_HOST://10.40.40.202:9092 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 KAFKA_NUM_PARTITIONS: 8 - KAFKA_LOG_RETENTION_MINUTES: 90 + KAFKA_LOG_RETENTION_MINUTES: 720 KAFKA_LOG_ROLL_MS: 3600000 KAFKA_LOG_SEGMENT_BYTES: 1073741824 KAFKA_MESSAGE_MAX_BYTES: 100000000 @@ -198,6 +197,30 @@ services: - POSTGRES_DROP_stats_peer_rib='4 weeks' - POSTGRES_DROP_stats_peer_update_counts='4 weeks' + exabgp: + restart: unless-stopped + container_name: obmp-exabgp + build: + context: ./exabgp + dockerfile: Dockerfile + # Host networking so ExaBGP can reach CML routers directly on port 179 + network_mode: host + environment: + # IP on the host that CML routers can reach (matches Kafka external listener) + - EXABGP_LOCAL_IP=10.40.40.202 + # ExaBGP presents as AS 65100 (eBGP peer to your AS 65020 lab) + - EXABGP_LOCAL_AS=65100 + - EXABGP_PEER_AS=65020 + # CORE routers to peer with — these propagate routes into the iBGP mesh + - EXABGP_PEER_1=10.100.0.100 + - EXABGP_PEER_2=10.100.0.200 + # Flask API port (also on host network) + - EXABGP_API_PORT=5050 + volumes: + # Mount scenarios dir so you can edit/add scenarios without rebuilding + - ./exabgp/scenarios:/exabgp/scenarios + # No ports: block needed — network_mode: host exposes directly + whois: restart: unless-stopped container_name: obmp-whois @@ -215,4 +238,4 @@ services: - POSTGRES_USER=openbmp - POSTGRES_DB=openbmp - POSTGRES_HOST=obmp-psql - - POSTGRES_PORT=5432 \ No newline at end of file + - POSTGRES_PORT=5432 diff --git a/exabgp/.dockerignore b/exabgp/.dockerignore new file mode 100644 index 0000000..7668361 --- /dev/null +++ b/exabgp/.dockerignore @@ -0,0 +1,2 @@ +**/__pycache__ +**/*.pyc diff --git a/exabgp/Dockerfile b/exabgp/Dockerfile new file mode 100644 index 0000000..bb98101 --- /dev/null +++ b/exabgp/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.11-slim + +RUN apt-get update && apt-get install -y --no-install-recommends \ + procps \ + && rm -rf /var/lib/apt/lists/* + +# Install ExaBGP and Flask API dependencies +RUN pip install --no-cache-dir exabgp flask requests + +# ExaBGP writes its own config at startup; we just need the source tree +COPY . /exabgp/ +WORKDIR /exabgp + +RUN chmod +x /exabgp/startup.sh /exabgp/inject.py + +# Flask API port +EXPOSE 5050 + +CMD ["/bin/bash", "/exabgp/startup.sh"] diff --git a/exabgp/api/requirements.txt b/exabgp/api/requirements.txt new file mode 100644 index 0000000..36b02be --- /dev/null +++ b/exabgp/api/requirements.txt @@ -0,0 +1,3 @@ +exabgp +flask +requests diff --git a/exabgp/api/server.py b/exabgp/api/server.py new file mode 100644 index 0000000..de56802 --- /dev/null +++ b/exabgp/api/server.py @@ -0,0 +1,273 @@ +#!/usr/bin/env python3 +""" +ExaBGP Route Injection API Server + +Runs as an ExaBGP process — reads BGP events from stdin, writes BGP +commands to stdout. Flask API runs in a background thread so HTTP +requests trigger live route announcements/withdrawals. + +API endpoints: + GET /healthz - health + active route count + GET /routes - list all active routes + POST /announce - announce prefixes + POST /withdraw - withdraw prefixes + POST /withdraw/all - withdraw everything + GET /scenarios - list available scenarios + POST /scenario/ - load a scenario + DELETE /scenario/ - withdraw a scenario + GET /peers - BGP peer state +""" + +import sys +import os +import json +import threading +import time +import logging +from flask import Flask, request, jsonify + +# --- logging to stderr so it doesn't pollute ExaBGP's stdout pipe --- +logging.basicConfig( + stream=sys.stderr, + level=logging.INFO, + format='%(asctime)s [API] %(levelname)s %(message)s', +) +log = logging.getLogger(__name__) + +app = Flask(__name__) + +# Thread-safe stdout for ExaBGP commands +_stdout_lock = threading.Lock() +# Active routes: prefix -> metadata dict +active_routes = {} +# Peer state received from ExaBGP events +peer_states = {} + + +# --------------------------------------------------------------------------- +# ExaBGP command helpers +# --------------------------------------------------------------------------- + +def _send(cmd: str): + """Write a command to ExaBGP via stdout.""" + with _stdout_lock: + sys.stdout.write(cmd + '\n') + sys.stdout.flush() + log.info('→ ExaBGP: %s', cmd) + + +def _build_announce(prefix, next_hop='self', as_path=None, communities=None, med=None, local_pref=None): + parts = [f'announce route {prefix} next-hop {next_hop}'] + if as_path: + parts.append(f'as-path [ {" ".join(str(a) for a in as_path)} ]') + if communities: + parts.append(f'community [ {" ".join(communities)} ]') + if med is not None: + parts.append(f'med {med}') + if local_pref is not None: + parts.append(f'local-preference {local_pref}') + return ' '.join(parts) + + +def _build_withdraw(prefix, next_hop='self'): + return f'withdraw route {prefix} next-hop {next_hop}' + + +def announce_route(prefix, next_hop='self', as_path=None, communities=None, med=None, local_pref=None): + cmd = _build_announce(prefix, next_hop, as_path, communities, med, local_pref) + _send(cmd) + active_routes[prefix] = { + 'prefix': prefix, + 'next_hop': next_hop, + 'as_path': as_path or [], + 'communities': communities or [], + 'med': med, + 'local_pref': local_pref, + 'announced_at': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime()), + } + + +def withdraw_route(prefix, next_hop='self'): + _send(_build_withdraw(prefix, next_hop)) + active_routes.pop(prefix, None) + + +# --------------------------------------------------------------------------- +# Flask API routes +# --------------------------------------------------------------------------- + +@app.route('/healthz') +def health(): + return jsonify({ + 'status': 'ok', + 'active_routes': len(active_routes), + 'peers': peer_states, + }) + + +@app.route('/routes', methods=['GET']) +def list_routes(): + return jsonify({ + 'count': len(active_routes), + 'routes': list(active_routes.values()), + }) + + +@app.route('/announce', methods=['POST']) +def api_announce(): + data = request.get_json(force=True) + prefixes = data.get('prefixes', []) + if not prefixes: + return jsonify({'error': 'prefixes list required'}), 400 + + next_hop = data.get('next_hop', 'self') + as_path = data.get('as_path', []) + communities = data.get('communities', []) + med = data.get('med') + local_pref = data.get('local_pref') + + announced = [] + for prefix in prefixes: + announce_route(prefix, next_hop, as_path, communities, med, local_pref) + announced.append(prefix) + + return jsonify({'announced': announced, 'count': len(announced)}) + + +@app.route('/withdraw', methods=['POST']) +def api_withdraw(): + data = request.get_json(force=True) + prefixes = data.get('prefixes', []) + if not prefixes: + return jsonify({'error': 'prefixes list required'}), 400 + + withdrawn = [] + for prefix in prefixes: + withdraw_route(prefix) + withdrawn.append(prefix) + + return jsonify({'withdrawn': withdrawn, 'count': len(withdrawn)}) + + +@app.route('/withdraw/all', methods=['POST']) +def api_withdraw_all(): + prefixes = list(active_routes.keys()) + for prefix in prefixes: + withdraw_route(prefix) + return jsonify({'withdrawn': prefixes, 'count': len(prefixes)}) + + +# --------------------------------------------------------------------------- +# Scenario management +# --------------------------------------------------------------------------- + +sys.path.insert(0, '/exabgp') +from scenarios import SCENARIOS + + +@app.route('/scenarios', methods=['GET']) +def list_scenarios(): + return jsonify({ + 'scenarios': { + name: { + 'description': s.get('description', ''), + 'route_count': len(s.get('routes', [])), + } + for name, s in SCENARIOS.items() + } + }) + + +@app.route('/scenario/', methods=['POST']) +def load_scenario(name): + if name not in SCENARIOS: + return jsonify({'error': f'Unknown scenario: {name}. Available: {list(SCENARIOS)}'}), 404 + + scenario = SCENARIOS[name] + announced = [] + for route in scenario['routes']: + prefix = route['prefix'] + announce_route( + prefix, + next_hop=route.get('next_hop', 'self'), + as_path=route.get('as_path', []), + communities=route.get('communities', []), + med=route.get('med'), + local_pref=route.get('local_pref'), + ) + announced.append(prefix) + + log.info('Loaded scenario %s: %d routes', name, len(announced)) + return jsonify({'scenario': name, 'announced': announced, 'count': len(announced)}) + + +@app.route('/scenario/', methods=['DELETE']) +def unload_scenario(name): + if name not in SCENARIOS: + return jsonify({'error': f'Unknown scenario: {name}'}), 404 + + scenario = SCENARIOS[name] + withdrawn = [] + for route in scenario['routes']: + prefix = route['prefix'] + if prefix in active_routes: + withdraw_route(prefix) + withdrawn.append(prefix) + + log.info('Unloaded scenario %s: %d routes', name, len(withdrawn)) + return jsonify({'scenario': name, 'withdrawn': withdrawn, 'count': len(withdrawn)}) + + +@app.route('/peers', methods=['GET']) +def get_peers(): + return jsonify({'peers': peer_states}) + + +# --------------------------------------------------------------------------- +# ExaBGP event loop (main thread) +# --------------------------------------------------------------------------- + +def parse_exabgp_event(line: str): + """Parse ExaBGP neighbor state events from stdin.""" + # ExaBGP text events look like: + # neighbor 10.100.0.100 up + # neighbor 10.100.0.100 down + parts = line.strip().split() + if len(parts) >= 3 and parts[0] == 'neighbor': + peer_ip = parts[1] + state = parts[2] + peer_states[peer_ip] = {'state': state, 'updated': time.strftime('%Y-%m-%dT%H:%M:%SZ', time.gmtime())} + log.info('Peer %s → %s', peer_ip, state) + + +def main(): + api_port = int(os.environ.get('EXABGP_API_PORT', 5050)) + + # Start Flask in background thread + flask_thread = threading.Thread( + target=lambda: app.run(host='0.0.0.0', port=api_port, threaded=True), + daemon=True, + ) + flask_thread.start() + log.info('Flask API listening on port %d', api_port) + + # Main thread: read ExaBGP events from stdin + log.info('Waiting for ExaBGP events on stdin...') + while True: + try: + line = sys.stdin.readline() + if not line: + log.warning('ExaBGP stdin closed, exiting') + break + line = line.strip() + if line: + log.debug('← ExaBGP: %s', line) + parse_exabgp_event(line) + except KeyboardInterrupt: + break + except Exception as e: + log.error('Event loop error: %s', e) + + +if __name__ == '__main__': + main() diff --git a/exabgp/inject.py b/exabgp/inject.py new file mode 100644 index 0000000..f1fc7fd --- /dev/null +++ b/exabgp/inject.py @@ -0,0 +1,213 @@ +#!/usr/bin/env python3 +""" +inject.py — CLI wrapper for the ExaBGP Route Injection API + +Usage: + inject.py status + inject.py routes + inject.py scenarios + inject.py announce [...] [--as-path ASN...] [--community STR...] [--med N] [--next-hop IP] + inject.py withdraw [...] + inject.py withdraw-all + inject.py scenario + inject.py withdraw-scenario + inject.py churn [--count N] [--interval SEC] # cycle announce/withdraw for ip_rib_log population + +Environment: + EXABGP_API=http://localhost:5050 API base URL +""" + +import sys +import os +import json +import time +import argparse +import requests + +API = os.environ.get('EXABGP_API', 'http://localhost:5050') + + +def _post(path, data=None): + r = requests.post(f'{API}{path}', json=data or {}, timeout=10) + r.raise_for_status() + return r.json() + + +def _delete(path): + r = requests.delete(f'{API}{path}', timeout=10) + r.raise_for_status() + return r.json() + + +def _get(path): + r = requests.get(f'{API}{path}', timeout=10) + r.raise_for_status() + return r.json() + + +def _pp(data): + print(json.dumps(data, indent=2)) + + +def cmd_status(args): + _pp(_get('/healthz')) + + +def cmd_routes(args): + data = _get('/routes') + print(f"Active routes: {data['count']}") + for r in data['routes']: + path = ' '.join(str(a) for a in r.get('as_path', [])) + comms = ' '.join(r.get('communities', [])) + parts = [r['prefix'], f'nh={r["next_hop"]}'] + if path: + parts.append(f'as-path=[{path}]') + if comms: + parts.append(f'community=[{comms}]') + if r.get('med') is not None: + parts.append(f'med={r["med"]}') + print(' ' + ' '.join(parts)) + + +def cmd_scenarios(args): + data = _get('/scenarios') + print(f"{'Name':<20} {'Routes':>6} Description") + print('-' * 70) + for name, info in data['scenarios'].items(): + print(f"{name:<20} {info['route_count']:>6} {info['description']}") + + +def cmd_announce(args): + payload = { + 'prefixes': args.prefixes, + 'next_hop': args.next_hop, + 'as_path': [int(a) for a in args.as_path] if args.as_path else [], + 'communities': args.community or [], + } + if args.med is not None: + payload['med'] = args.med + data = _post('/announce', payload) + print(f"Announced {data['count']} route(s):") + for p in data['announced']: + print(f" + {p}") + + +def cmd_withdraw(args): + data = _post('/withdraw', {'prefixes': args.prefixes}) + print(f"Withdrew {data['count']} route(s):") + for p in data['withdrawn']: + print(f" - {p}") + + +def cmd_withdraw_all(args): + data = _post('/withdraw/all') + print(f"Withdrew all {data['count']} route(s)") + + +def cmd_scenario(args): + data = _post(f'/scenario/{args.name}') + print(f"Loaded scenario '{args.name}': {data['count']} routes announced") + + +def cmd_withdraw_scenario(args): + data = _delete(f'/scenario/{args.name}') + print(f"Withdrew scenario '{args.name}': {data['count']} routes withdrawn") + + +def cmd_churn(args): + """ + Cycle announce/withdraw on the 'churn' scenario to generate ip_rib_log + entries and populate stats_chg_* tables in OpenBMP. + """ + count = args.count + interval = args.interval + print(f"Starting churn: {count} cycles, {interval}s interval") + print("This will populate ip_rib_log and stats_chg_* tables in OpenBMP.") + print("Press Ctrl+C to stop.\n") + + cycle = 0 + try: + while count == 0 or cycle < count: + cycle += 1 + print(f"Cycle {cycle}: announcing churn scenario...") + r = _post('/scenario/churn') + print(f" + {r['count']} routes announced") + time.sleep(interval) + + print(f"Cycle {cycle}: withdrawing churn scenario...") + r = _delete('/scenario/churn') + print(f" - {r['count']} routes withdrawn") + time.sleep(interval) + + print() + except KeyboardInterrupt: + print("\nChurn stopped. Withdrawing any active routes...") + _post('/withdraw/all') + print("Done.") + + +def main(): + parser = argparse.ArgumentParser( + description='ExaBGP Route Injection CLI', + formatter_class=argparse.RawDescriptionHelpFormatter, + ) + sub = parser.add_subparsers(dest='command') + + sub.add_parser('status', help='Show API health and peer states') + sub.add_parser('routes', help='List active announced routes') + sub.add_parser('scenarios', help='List available scenarios') + sub.add_parser('withdraw-all', help='Withdraw all active routes') + + p = sub.add_parser('announce', help='Announce one or more prefixes') + p.add_argument('prefixes', nargs='+') + p.add_argument('--as-path', nargs='+', default=[], metavar='ASN') + p.add_argument('--community', nargs='+', default=[], metavar='COMM') + p.add_argument('--med', type=int, default=None) + p.add_argument('--next-hop', default='self', metavar='IP') + + p = sub.add_parser('withdraw', help='Withdraw one or more prefixes') + p.add_argument('prefixes', nargs='+') + + p = sub.add_parser('scenario', help='Load a named scenario') + p.add_argument('name') + + p = sub.add_parser('withdraw-scenario', help='Withdraw a named scenario') + p.add_argument('name') + + p = sub.add_parser('churn', help='Cycle announce/withdraw to populate ip_rib_log') + p.add_argument('--count', type=int, default=0, metavar='N', + help='Number of cycles (0 = infinite)') + p.add_argument('--interval', type=float, default=30.0, metavar='SEC', + help='Seconds between announce and withdraw (default: 30)') + + args = parser.parse_args() + + cmds = { + 'status': cmd_status, + 'routes': cmd_routes, + 'scenarios': cmd_scenarios, + 'announce': cmd_announce, + 'withdraw': cmd_withdraw, + 'withdraw-all': cmd_withdraw_all, + 'scenario': cmd_scenario, + 'withdraw-scenario': cmd_withdraw_scenario, + 'churn': cmd_churn, + } + + if not args.command: + parser.print_help() + sys.exit(1) + + try: + cmds[args.command](args) + except requests.exceptions.ConnectionError: + print(f"ERROR: Cannot connect to ExaBGP API at {API}") + print("Is the exabgp container running? docker compose logs exabgp") + sys.exit(1) + except requests.exceptions.HTTPError as e: + print(f"ERROR: {e}") + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/exabgp/iosxr_bgp_config.md b/exabgp/iosxr_bgp_config.md new file mode 100644 index 0000000..5b4ae4e --- /dev/null +++ b/exabgp/iosxr_bgp_config.md @@ -0,0 +1,172 @@ +# IOS-XR BGP Config for ExaBGP Peering + +Apply to **both CORE routers** (`CML-R9K-CORE-01` @ 10.100.0.100 and +`CML-R9K-CORE-02` @ 10.100.0.200). + +Credentials: `ssh user@` password `cisco` + +--- + +## Route Policy (apply once per router) + +``` +route-policy EXABGP_IN + pass +end-policy + +route-policy EXABGP_OUT + drop +end-policy +``` + +--- + +## BGP Neighbor Block + +``` +router bgp 65020 + neighbor 10.40.40.202 + remote-as 65100 + description ExaBGP-Route-Injector + ebgp-multihop 5 + update-source MgmtEth0/RP0/CPU0/0 + ! + address-family ipv4 unicast + route-policy EXABGP_IN in + route-policy EXABGP_OUT out + next-hop-self + ! + address-family ipv6 unicast + route-policy EXABGP_IN in + route-policy EXABGP_OUT out + next-hop-self + ! + ! +! +``` + +### Key config notes + +| Knob | Why | +|------|-----| +| `remote-as 65100` | ExaBGP presents as AS 65100 (eBGP to your AS 65020 mesh) | +| `ebgp-multihop 5` | Host (10.40.40.202) and router (10.100.0.x) are different subnets | +| `update-source MgmtEth0/RP0/CPU0/0` | Use management interface for the TCP session | +| `next-hop-self` | Replace ExaBGP's next-hop (10.40.40.202) with the CORE router's loopback when reflecting into iBGP — ensures other routers can resolve the next-hop via ISIS | +| `EXABGP_OUT` drops | Prevent the lab from advertising its own prefixes back to ExaBGP | + +--- + +## Verification Commands + +``` +show bgp neighbors 10.40.40.202 +show bgp neighbors 10.40.40.202 received routes +show bgp summary +show route 1.1.1.0/24 +show bgp 1.1.1.0/24 +``` + +After loading the `internet_sample` scenario you should see ~94 new +prefixes in the BGP table and they should propagate to all 9 routers +via the iBGP mesh. + +--- + +## NETCONF push (alternative to CLI) + +With NETCONF already enabled, you can push this config programmatically: + +```bash +pip install ncclient + +python3 - <<'EOF' +from ncclient import manager + +ROUTERS = [ + {'host': '10.100.0.100', 'description': 'CML-R9K-CORE-01'}, + {'host': '10.100.0.200', 'description': 'CML-R9K-CORE-02'}, +] + +POLICY_XML = """ + + + + + EXABGP_IN + route-policy EXABGP_IN pass end-policy + + + EXABGP_OUT + route-policy EXABGP_OUT drop end-policy + + + + + + default + + 0 + + 65020 + + + + + + 10.40.40.202 + + 0 + 65100 + + ExaBGP-Route-Injector + + 5 + + + + + + + ipv4-unicast + + EXABGP_IN + EXABGP_OUT + true + + + ipv6-unicast + + EXABGP_IN + EXABGP_OUT + true + + + + + + + + + + + +""" + +for router in ROUTERS: + print(f"Configuring {router['description']} ({router['host']})...") + with manager.connect( + host=router['host'], + port=830, + username='user', + password='cisco', + hostkey_verify=False, + device_params={'name': 'iosxr'}, + ) as m: + m.edit_config(target='candidate', config=POLICY_XML) + m.commit() + print(f" Done.") + +print("All routers configured.") +EOF +``` diff --git a/exabgp/scenarios/__init__.py b/exabgp/scenarios/__init__.py new file mode 100644 index 0000000..bde9ca8 --- /dev/null +++ b/exabgp/scenarios/__init__.py @@ -0,0 +1,315 @@ +""" +BGP Route Injection Scenarios + +Each scenario is a dict with: + description: str + routes: list of route dicts + +Route dict keys: + prefix (required) e.g. "1.1.1.0/24" + next_hop default "self" + as_path list of ASNs, e.g. [65100, 1299, 15169] + communities list of strings, e.g. ["65100:100"] + med int, optional + local_pref int, optional + +Well-known transit ASNs used in AS paths: + 174 Cogent + 701 Verizon / MCI + 1299 Telia + 2914 NTT + 3257 GTT + 3356 Lumen / Level3 + 6461 Zayo + 6762 Sparkle / Telecom Italia + 7018 AT&T +""" + +# --------------------------------------------------------------------------- +# Helper to build route dicts quickly +# --------------------------------------------------------------------------- + +def _r(prefix, as_path, communities=None, med=None, local_pref=None): + return { + 'prefix': prefix, + 'next_hop': 'self', + 'as_path': as_path, + 'communities': communities or [], + 'med': med, + 'local_pref': local_pref, + } + + +# --------------------------------------------------------------------------- +# Scenario: internet_sample +# Partial internet table — realistic mix of prefix lengths and AS paths. +# Prefixes are real public ranges with synthetic (but plausible) AS paths. +# --------------------------------------------------------------------------- + +_INTERNET_V4 = [ + # Cloudflare + _r('1.1.1.0/24', [65100, 174, 13335]), + _r('1.0.0.1/32', [65100, 3356, 13335]), + _r('104.16.0.0/13', [65100, 1299, 13335]), + _r('104.24.0.0/14', [65100, 6461, 13335]), + _r('162.158.0.0/15', [65100, 7018, 13335]), + _r('172.64.0.0/13', [65100, 2914, 13335]), + _r('198.41.128.0/17', [65100, 3257, 13335]), + # Google / Alphabet + _r('8.8.8.0/24', [65100, 3356, 15169]), + _r('8.8.4.0/24', [65100, 1299, 15169]), + _r('8.34.208.0/20', [65100, 6762, 15169]), + _r('34.0.0.0/15', [65100, 701, 15169]), + _r('35.190.0.0/17', [65100, 2914, 15169]), + _r('64.233.160.0/19', [65100, 3356, 15169]), + _r('66.102.0.0/20', [65100, 7018, 15169]), + _r('74.125.0.0/16', [65100, 174, 15169]), + _r('142.250.0.0/15', [65100, 3257, 15169]), + _r('172.217.0.0/16', [65100, 6461, 15169]), + _r('216.58.192.0/19', [65100, 1299, 15169]), + # Amazon AWS + _r('3.0.0.0/15', [65100, 3356, 16509]), + _r('13.32.0.0/15', [65100, 1299, 16509]), + _r('52.0.0.0/14', [65100, 6461, 16509]), + _r('52.84.0.0/15', [65100, 2914, 16509]), + _r('54.64.0.0/13', [65100, 701, 16509]), + _r('54.144.0.0/12', [65100, 174, 16509]), + _r('54.160.0.0/13', [65100, 3257, 16509]), + _r('99.77.128.0/18', [65100, 7018, 16509]), + _r('205.251.192.0/18',[65100, 3356, 16509]), + # Microsoft Azure + _r('13.64.0.0/11', [65100, 1299, 8075]), + _r('20.0.0.0/14', [65100, 6762, 8075]), + _r('20.33.0.0/16', [65100, 3356, 8075]), + _r('40.64.0.0/10', [65100, 2914, 8075]), + _r('52.224.0.0/11', [65100, 701, 8075]), + _r('104.40.0.0/13', [65100, 174, 8075]), + _r('168.61.0.0/16', [65100, 7018, 8075]), + # Akamai + _r('23.0.0.0/12', [65100, 3356, 20940]), + _r('23.32.0.0/11', [65100, 1299, 20940]), + _r('23.192.0.0/11', [65100, 6461, 20940]), + _r('92.122.0.0/15', [65100, 2914, 20940]), + _r('95.100.0.0/15', [65100, 3257, 20940]), + _r('184.24.0.0/13', [65100, 7018, 20940]), + # Fastly CDN + _r('23.235.32.0/20', [65100, 174, 54113]), + _r('103.244.50.0/24', [65100, 3356, 54113]), + _r('151.101.0.0/16', [65100, 1299, 54113]), + _r('157.52.192.0/18', [65100, 6461, 54113]), + _r('185.31.16.0/22', [65100, 2914, 54113]), + _r('199.27.72.0/21', [65100, 701, 54113]), + # Twitter / X + _r('104.244.42.0/24', [65100, 3356, 13414]), + _r('192.133.76.0/22', [65100, 1299, 13414]), + # Meta / Facebook + _r('31.13.24.0/21', [65100, 174, 32934]), + _r('31.13.64.0/18', [65100, 6762, 32934]), + _r('66.220.144.0/20', [65100, 7018, 32934]), + _r('69.63.176.0/20', [65100, 2914, 32934]), + _r('69.171.224.0/19', [65100, 3257, 32934]), + _r('157.240.0.0/17', [65100, 3356, 32934]), + _r('185.89.218.0/23', [65100, 701, 32934]), + _r('204.15.20.0/22', [65100, 1299, 32934]), + # Apple + _r('17.0.0.0/8', [65100, 1299, 714]), + _r('17.172.224.0/19', [65100, 6461, 714]), + _r('17.178.96.0/19', [65100, 2914, 714]), + _r('192.35.50.0/24', [65100, 3356, 714]), + # Comcast + _r('50.18.0.0/16', [65100, 7018, 7922]), + _r('73.0.0.0/8', [65100, 174, 7922]), + _r('96.0.0.0/11', [65100, 3257, 7922]), + # Verizon + _r('70.0.0.0/11', [65100, 3356, 701]), + _r('98.0.0.0/10', [65100, 1299, 701]), + _r('174.0.0.0/12', [65100, 6461, 701]), + # Generic transit destinations for AS path variety + _r('5.0.0.0/16', [65100, 1299, 6762, 34984]), + _r('45.86.0.0/16', [65100, 3257, 9002, 51847]), + _r('80.64.0.0/18', [65100, 174, 1239, 34224]), + _r('82.112.0.0/15', [65100, 6461, 5400, 12322]), + _r('89.0.0.0/17', [65100, 2914, 3491, 8551]), + _r('91.108.4.0/22', [65100, 701, 9002, 42831]), + _r('141.0.0.0/16', [65100, 7018, 1239, 6830]), + _r('185.0.0.0/22', [65100, 3356, 5400, 44946]), + _r('195.0.0.0/21', [65100, 1299, 3491, 30781]), + _r('212.0.0.0/16', [65100, 6762, 9002, 3301]), + _r('217.0.0.0/20', [65100, 174, 1239, 25160]), +] + +_INTERNET_V6 = [ + _r('2001:4860::/32', [65100, 3356, 15169]), # Google + _r('2001:4860:4860::/48', [65100, 1299, 15169]), + _r('2606:4700::/32', [65100, 174, 13335]), # Cloudflare + _r('2606:4700:4700::/48', [65100, 3356, 13335]), + _r('2400:cb00::/32', [65100, 2914, 13335]), + _r('2620:0:2d0::/48', [65100, 701, 2906]), # Netflix + _r('2600::/23', [65100, 6461, 16509]), # Amazon + _r('2a00:1450::/32', [65100, 1299, 15169]), # Google EU + _r('2001:8d8::/32', [65100, 3257, 20940]), # Akamai + _r('2620:1ec::/36', [65100, 7018, 8075]), # Microsoft + _r('2a03:2880::/32', [65100, 3356, 32934]), # Meta + _r('2001:df0::/32', [65100, 2914, 4837]), # China Unicom + _r('2001:500::/30', [65100, 174, 3356]), # ARIN + _r('2001:db8::/32', [65100, 1299, 65001]), # Documentation (RFC 3849) +] + + +# --------------------------------------------------------------------------- +# Scenario: churn +# 30 prefixes designed to be announced then withdrawn repeatedly. +# Load with /scenario/churn, withdraw with DELETE /scenario/churn. +# Run announce→withdraw→announce cycles to populate ip_rib_log. +# --------------------------------------------------------------------------- + +_CHURN_PREFIXES = [ + '198.51.100.0/24', # RFC 5737 documentation space + '198.51.101.0/24', + '198.51.102.0/24', + '198.51.103.0/24', + '198.51.104.0/24', + '198.51.105.0/24', + '198.51.106.0/24', + '198.51.107.0/24', + '198.51.108.0/24', + '198.51.109.0/24', + '203.0.113.0/24', # RFC 5737 documentation space + '203.0.113.1/32', + '203.0.113.2/32', + '203.0.113.3/32', + '203.0.113.4/32', + '100.64.0.0/24', # RFC 6598 shared address space + '100.64.1.0/24', + '100.64.2.0/24', + '100.64.3.0/24', + '100.64.4.0/24', + '192.0.2.0/24', # RFC 5737 + '192.0.2.128/25', + '192.0.2.0/25', + '192.0.3.0/24', + '192.0.4.0/24', + '192.0.5.0/24', + '192.0.6.0/24', + '192.0.7.0/24', + '192.0.8.0/24', + '192.0.9.0/24', +] + +_CHURN_ROUTES = [ + _r(p, [65100, 65200], communities=['65100:200']) + for p in _CHURN_PREFIXES +] + + +# --------------------------------------------------------------------------- +# Scenario: blackhole +# Prefixes with RTBH (Remotely Triggered Black Hole) community. +# Community 65100:666 signals black-hole intent. +# Also includes the well-known BLACKHOLE community (65535:666). +# --------------------------------------------------------------------------- + +_BLACKHOLE_ROUTES = [ + _r('192.0.2.1/32', [65100], communities=['65100:666', '65535:666']), + _r('192.0.2.2/32', [65100], communities=['65100:666', '65535:666']), + _r('192.0.2.3/32', [65100], communities=['65100:666', '65535:666']), + _r('198.51.100.1/32',[65100], communities=['65100:666', '65535:666']), + _r('198.51.100.2/32',[65100], communities=['65100:666', '65535:666']), +] + + +# --------------------------------------------------------------------------- +# Scenario: anycast +# Same three prefixes announced with different AS paths and MEDs — +# simulates anycast competition (best-path selection testing). +# --------------------------------------------------------------------------- + +_ANYCAST_ROUTES = [ + # Anycast prefix 1 — two paths, different MED + _r('192.0.2.0/24', [65100, 65300], med=100), + # Anycast prefix 2 — longer AS path + _r('198.51.100.0/24', [65100, 65300, 65400], med=200), + # Anycast prefix 3 — shorter AS path, preferred + _r('203.0.113.0/24', [65100, 65200], med=50), +] + + +# --------------------------------------------------------------------------- +# Scenario: full_table +# 500+ prefixes simulating a large partial internet table. +# Built by expanding internet_sample with synthetic /24s. +# --------------------------------------------------------------------------- + +def _gen_full_table(): + routes = list(_INTERNET_V4) + list(_INTERNET_V6) + # Add synthetic /24 blocks from 100.x.x.0/24 space (RFC 6598) + transit_paths = [ + [65100, 1299, 7922], + [65100, 3356, 16509], + [65100, 174, 15169], + [65100, 6461, 32934], + [65100, 2914, 8075], + [65100, 7018, 20940], + [65100, 1299, 54113], + [65100, 3356, 13335], + ] + for i in range(100, 200): + for j in range(0, 256, 8): + path = transit_paths[((i - 100) + (j // 8)) % len(transit_paths)] + origin = 64512 + ((i * 32 + j // 8) % 1023) + routes.append(_r(f'100.{i}.{j}.0/24', path + [origin])) + return routes + + +# --------------------------------------------------------------------------- +# Scenario: lab_prefixes +# Mimics realistic enterprise/SP routes your lab routers would see. +# Useful for testing policy: communities, local-pref, AS path filtering. +# --------------------------------------------------------------------------- + +_LAB_ROUTES = [ + # Customer routes (shorter AS path, higher local-pref via community) + _r('10.200.0.0/24', [65100, 65500], communities=['65100:100'], local_pref=200), + _r('10.200.1.0/24', [65100, 65500], communities=['65100:100'], local_pref=200), + _r('10.200.2.0/24', [65100, 65500], communities=['65100:100'], local_pref=200), + # Peer routes (medium preference) + _r('10.201.0.0/22', [65100, 65600], communities=['65100:200'], local_pref=150), + _r('10.201.4.0/22', [65100, 65600], communities=['65100:200'], local_pref=150), + # Transit routes (longer path, lower preference) + _r('10.202.0.0/20', [65100, 1299, 65700], communities=['65100:300'], local_pref=100), + _r('10.202.16.0/20', [65100, 3356, 65700], communities=['65100:300'], local_pref=100), + # Default route + _r('0.0.0.0/0', [65100, 3356], communities=['65100:400']), +] + + +# --------------------------------------------------------------------------- +# Registry +# --------------------------------------------------------------------------- + +SCENARIOS = { + 'internet_sample': { + 'description': 'Partial internet table (~80 IPv4 + 14 IPv6 prefixes with realistic AS paths)', + 'routes': _INTERNET_V4 + _INTERNET_V6, + }, + 'churn': { + 'description': '30 RFC documentation prefixes for announce/withdraw churn testing', + 'routes': _CHURN_ROUTES, + }, + 'blackhole': { + 'description': '5 /32 prefixes with RTBH community (65100:666 + 65535:666)', + 'routes': _BLACKHOLE_ROUTES, + }, + 'anycast': { + 'description': '3 prefixes with varying AS paths and MEDs for best-path testing', + 'routes': _ANYCAST_ROUTES, + }, + 'full_table': { + 'description': '500+ prefixes simulating a large partial internet table', + 'routes': _gen_full_table(), + }, + 'lab_prefixes': { + 'description': 'Enterprise/SP-style routes with communities and local-pref for policy testing', + 'routes': _LAB_ROUTES, + }, +} diff --git a/exabgp/startup.sh b/exabgp/startup.sh new file mode 100644 index 0000000..0dba2e6 --- /dev/null +++ b/exabgp/startup.sh @@ -0,0 +1,67 @@ +#!/bin/bash +set -e + +LOCAL_IP=${EXABGP_LOCAL_IP:-10.40.40.202} +LOCAL_AS=${EXABGP_LOCAL_AS:-65100} +PEER_AS=${EXABGP_PEER_AS:-65020} +PEER_1=${EXABGP_PEER_1:-10.100.0.100} +PEER_2=${EXABGP_PEER_2:-10.100.0.200} +API_PORT=${EXABGP_API_PORT:-5050} + +echo "================================================================" +echo " ExaBGP Route Injector" +echo " Local: ${LOCAL_IP} AS${LOCAL_AS}" +echo " Peers: ${PEER_1}, ${PEER_2} (AS${PEER_AS})" +echo " API: http://0.0.0.0:${API_PORT}" +echo "================================================================" + +# Generate ExaBGP 5.x env file — ExaBGP looks here based on pip install prefix +mkdir -p /usr/local/etc/exabgp +exabgp env > /usr/local/etc/exabgp/exabgp.env +sed -i 's/drop = true/drop = false/' /usr/local/etc/exabgp/exabgp.env +sed -i 's/cli = true/cli = false/' /usr/local/etc/exabgp/exabgp.env +sed -i "s/destination = 'stdout'/destination = 'stderr'/" /usr/local/etc/exabgp/exabgp.env + +# Generate exabgp.conf from environment +cat > /tmp/exabgp.conf << EOF +process api { + run /usr/local/bin/python3 /exabgp/api/server.py; + encoder text; +} + +neighbor ${PEER_1} { + router-id ${LOCAL_IP}; + local-address ${LOCAL_IP}; + local-as ${LOCAL_AS}; + peer-as ${PEER_AS}; + description "CML-R9K-CORE-01"; + hold-time 90; + + family { + ipv4 unicast; + } + + api { + processes [ api ]; + } +} + +neighbor ${PEER_2} { + router-id ${LOCAL_IP}; + local-address ${LOCAL_IP}; + local-as ${LOCAL_AS}; + peer-as ${PEER_AS}; + description "CML-R9K-CORE-02"; + hold-time 90; + + family { + ipv4 unicast; + } + + api { + processes [ api ]; + } +} +EOF + +exec exabgp server /tmp/exabgp.conf diff --git a/obmp-grafana/.gitignore b/obmp-grafana/.gitignore new file mode 100644 index 0000000..c23b802 --- /dev/null +++ b/obmp-grafana/.gitignore @@ -0,0 +1,6 @@ +.DS_Store +.idea +*.log +*.pyc +*.tgz +*.gz diff --git a/obmp-grafana/LICENSE b/obmp-grafana/LICENSE new file mode 100644 index 0000000..0be3d0b --- /dev/null +++ b/obmp-grafana/LICENSE @@ -0,0 +1,26 @@ +Copyright 2021 Cisco Systems, Inc. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/obmp-grafana/README.md b/obmp-grafana/README.md new file mode 100644 index 0000000..b340dd2 --- /dev/null +++ b/obmp-grafana/README.md @@ -0,0 +1,12 @@ +# OpenBMP Grafana Integration +Grafana can be used with the OpenBMP PostgreSQL backend to visualize BGP data and statistics. + +## Install/Run Grafana +Install/run grafana. See [grafana in openbmp compose](https://github.com/OpenBMP/obmp-docker/blob/main/docker-compose.yml) for +details on how you can run the Grafana container. + +## Grafana Provisioning +This repo is structured to support [Grafana Provisioning](https://grafana.com/docs/grafana/latest/administration/provisioning/). +For the most part, this repo can be cloned directly in to the ```/etc/grafana/provisioning``` directory. + + diff --git a/obmp-grafana/dashboards/General/OBMP-Home.json b/obmp-grafana/dashboards/General/OBMP-Home.json new file mode 100644 index 0000000..b6a0392 --- /dev/null +++ b/obmp-grafana/dashboards/General/OBMP-Home.json @@ -0,0 +1,237 @@ +{ + "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, + "id": 1, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "gridPos": { + "h": 3, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 6, + "links": [], + "options": { + "content": "# OpenBMP\n\n*Select a dashboard*", + "mode": "markdown" + }, + "pluginVersion": "8.5.4", + "type": "text" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "gridPos": { + "h": 18, + "w": 4, + "x": 0, + "y": 3 + }, + "id": 7, + "links": [], + "options": { + "maxItems": 41, + "query": "", + "showHeadings": true, + "showRecentlyViewed": false, + "showSearch": true, + "showStarred": false, + "tags": [ + "obmp-tops" + ] + }, + "pluginVersion": "8.5.4", + "tags": [], + "title": "Tops", + "type": "dashlist" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "gridPos": { + "h": 18, + "w": 5, + "x": 4, + "y": 3 + }, + "id": 8, + "links": [], + "options": { + "maxItems": 41, + "query": "", + "showHeadings": true, + "showRecentlyViewed": false, + "showSearch": true, + "showStarred": false, + "tags": [ + "obmp-base" + ] + }, + "pluginVersion": "8.5.4", + "tags": [], + "title": "Base", + "type": "dashlist" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "gridPos": { + "h": 18, + "w": 5, + "x": 9, + "y": 3 + }, + "id": 4, + "links": [], + "options": { + "maxItems": 41, + "query": "", + "showHeadings": true, + "showRecentlyViewed": false, + "showSearch": true, + "showStarred": false, + "tags": [ + "obmp-history" + ] + }, + "pluginVersion": "8.5.4", + "tags": [], + "title": "Prefix History", + "type": "dashlist" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "gridPos": { + "h": 18, + "w": 5, + "x": 14, + "y": 3 + }, + "id": 9, + "links": [], + "options": { + "maxItems": 41, + "query": "", + "showHeadings": true, + "showRecentlyViewed": false, + "showSearch": true, + "showStarred": false, + "tags": [ + "obmp-l3vpn" + ] + }, + "pluginVersion": "8.5.4", + "tags": [], + "title": "L3VPN", + "type": "dashlist" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "gridPos": { + "h": 18, + "w": 5, + "x": 19, + "y": 3 + }, + "id": 3, + "links": [], + "options": { + "maxItems": 41, + "query": "", + "showHeadings": true, + "showRecentlyViewed": false, + "showSearch": true, + "showStarred": false, + "tags": [ + "obmp-linkstate" + ] + }, + "pluginVersion": "8.5.4", + "tags": [], + "title": "Link State", + "type": "dashlist" + } + ], + "schemaVersion": 36, + "style": "dark", + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "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": "OBMP-Home", + "uid": "obmp-home", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/Base-1001/asn_view.json b/obmp-grafana/dashboards/obmp/Base-1001/asn_view.json new file mode 100644 index 0000000..b255af9 --- /dev/null +++ b/obmp-grafana/dashboards/obmp/Base-1001/asn_view.json @@ -0,0 +1,1050 @@ +{ + "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, + "id": 3, + "iteration": 1654876929746, + "links": [], + "liveNow": false, + "panels": [ + { + "aliasColors": {}, + "breakPoint": "50%", + "combine": { + "label": "Others", + "threshold": 0 + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "decimals": 0, + "fontSize": "80%", + "format": "none", + "gridPos": { + "h": 8, + "w": 5, + "x": 0, + "y": 0 + }, + "id": 6, + "legend": { + "show": true, + "values": true + }, + "legendType": "Under graph", + "links": [], + "maxDataPoints": 3, + "nullPointMode": "connected", + "pieType": "pie", + "strokeWidth": 1, + "targets": [ + { + "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" + }, + { + "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", + "type": "grafana-piechart-panel", + "valueName": "total" + }, + { + "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" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "decimals": 0, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 15, + "x": 9, + "y": 0 + }, + "hiddenSeries": false, + "id": 14, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "hideEmpty": false, + "hideZero": false, + "max": true, + "min": true, + "rightSide": true, + "show": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "8.5.4", + "pointradius": 5, + "points": true, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "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" + } + ], + "thresholds": [], + "timeFrom": "24h", + "timeRegions": [], + "title": "Originating Prefix Trend", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "decimals": 0, + "format": "none", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "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": [ + "obmp-base" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "714", + "value": "714" + }, + "hide": 0, + "includeAll": false, + "label": "ASN", + "multi": false, + "name": "asn_num", + "options": [ + { + "selected": true, + "text": "109", + "value": "109" + } + ], + "query": "109", + "queryValue": "714", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "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": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/Base-1001/inventory.json b/obmp-grafana/dashboards/obmp/Base-1001/inventory.json new file mode 100644 index 0000000..a696345 --- /dev/null +++ b/obmp-grafana/dashboards/obmp/Base-1001/inventory.json @@ -0,0 +1,506 @@ +{ + "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, + "id": 4, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "up" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "light-green", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "down" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "light-red", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 11, + "w": 4, + "x": 0, + "y": 0 + }, + "id": 3, + "links": [], + "maxDataPoints": 3, + "options": { + "displayLabels": [], + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "bottom", + "values": [ + "value", + "percent" + ] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n count(distinct router_hash_id) as value,\n r.state as metric\nFROM routers r\n JOIN bgp_peers p on (r.hash_id = p.router_hash_id)\n group by r.state\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Router Status", + "type": "piechart" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 20, + "x": 4, + "y": 0 + }, + "id": 1, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select max(r.timestamp) as timestamp,r.name,max(ip_address) as ip_address,max(r.state) as state,\n count(*) as peers,max(description) as description, CASE WHEN max(r.state) = 'up' THEN 1 ELSE 0 END as stateBool\n from routers r\n JOIN bgp_peers p on (r.hash_id = p.router_hash_id)\n GROUP BY r.name;", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Routers", + "type": "table" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "up" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "light-green", + "mode": "fixed" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "down" + }, + "properties": [ + { + "id": "color", + "value": { + "fixedColor": "light-red", + "mode": "fixed" + } + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 4, + "x": 0, + "y": 11 + }, + "id": 4, + "links": [], + "maxDataPoints": 3, + "options": { + "displayLabels": [], + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "bottom", + "sortBy": "Value", + "sortDesc": true, + "values": [ + "value", + "percent" + ] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "last" + ], + "fields": "", + "values": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n state as metric,\n count(*) value\nFROM bgp_peers\ngroup by metric", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Peer Status", + "type": "piechart" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 14, + "w": 20, + "x": 4, + "y": 11 + }, + "id": 2, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "IPv4 Prefixes" + } + ] + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": " SELECT\n max(RouterName) as \"RouterName\",\n max(PeerName) as \"PeerName\",\n max(PeerIP) as \"PeerIP\",\n max(PeerASN) as \"PeerASN\",\n max(peer_state) as \"State\",\n max(LastModified) as \"LastModified\",\n max(v4_prefixes) as \"IPv4 Prefixes\",\n max(v6_prefixes) as \"IPv6 Prefixes\",\n CASE WHEN max(peer_state) = 'up' THEN 1 ELSE 0 END as stateBool\nFROM v_peers p\n LEFT JOIN stats_peer_rib s ON (p.peer_hash_id = s.peer_hash_id\n AND s.interval_time >= now() - interval '20 minutes')\nGROUP BY p.peer_hash_id;\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Peers", + "type": "table" + } + ], + "schemaVersion": 36, + "style": "dark", + "tags": [ + "obmp-base" + ], + "templating": { + "list": [] + }, + "time": { + "from": "now-1h", + "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": "utc", + "title": "Inventory", + "uid": "inventory", + "version": 3, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/Base-1001/looking_glass.json b/obmp-grafana/dashboards/obmp/Base-1001/looking_glass.json new file mode 100644 index 0000000..55b0eb3 --- /dev/null +++ b/obmp-grafana/dashboards/obmp/Base-1001/looking_glass.json @@ -0,0 +1,910 @@ +{ + "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, + "id": 5, + "iteration": 1654877090626, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "uid": "obmp-postgres" + }, + "gridPos": { + "h": 3, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 15, + "links": [], + "options": { + "content": "# Looking Glass\n\n> Enter an IP address with or without bit length. The longest matched prefix will be used. Specify the length to find exact match or best aggregate.", + "mode": "markdown" + }, + "pluginVersion": "8.5.4", + "type": "text" + }, + { + "circleMaxSize": "15", + "circleMinSize": 2, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "decimals": 0, + "esMetric": "Count", + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "hideEmpty": false, + "hideZero": false, + "id": 17, + "initialZoom": "1", + "locationData": "table", + "mapCenter": "(0°, 0°)", + "mapCenterLatitude": 0, + "mapCenterLongitude": 0, + "maxDataPoints": 1, + "mouseWheelZoom": false, + "showLegend": false, + "stickyLabels": false, + "tableQueryOptions": { + "geohashField": "geohash", + "labelField": "name", + "latitudeField": "latitude", + "longitudeField": "longitude", + "metricField": "value", + "queryType": "coordinates" + }, + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n 10 as value, latitude, longitude, stateprov as name\nFROM geo_ip\nWHERE\n ip && '$input'\nORDER BY ip desc limit 1", + "refId": "A", + "select": [ + [ + { + "params": [ + "latitude" + ], + "type": "column" + } + ] + ], + "table": "v_ip_routes_geo", + "timeColumn": "lastmodified", + "timeColumnType": "timestamp", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "thresholds": "0,10", + "title": "Prefix Location", + "type": "grafana-worldmap-panel", + "unitPlural": "", + "unitSingle": "", + "valueName": "current" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "description": "Prefix found in router's RIB.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 0, + "y": 3 + }, + "id": 9, + "links": [], + "maxDataPoints": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "values": [ + "value", + "percent" + ] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n floor(extract(epoch from max(r.timestamp))) as time,\n CASE WHEN v.router_hash_id is null THEN 'Not in Router RIB' ELSE 'In Router Rib' END as metric,\n 1 as value\nFROM routers r\n left join (select distinct router_hash_id\n from v_ip_routes \n where prefix = '$prefix'\n and iswithdrawn = false group by router_hash_id) v \n on (r.hash_id = v.router_hash_id)\nWHERE r.state = 'up'\nGROUP BY r.hash_id,v.router_hash_id\norder by time\n\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Router Visibility", + "type": "piechart" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "description": "Prefix found in peer RIB's", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 6, + "y": 3 + }, + "id": 10, + "links": [], + "maxDataPoints": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "values": [ + "value", + "percent" + ] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n floor(extract(epoch from max(p.timestamp))) as time,\n CASE WHEN v.peer_hash_id is null THEN 'Not in Peers RIB' ELSE 'In Peer RIB' END as metric,\n 1 as value\nFROM bgp_peers p\n left join (select peer_hash_id,isipv4\n from v_ip_routes \n where prefix = '$prefix' and prefix != '0.0.0.0/0'\n and iswithdrawn = false group by peer_hash_id,isipv4) v \n on (p.hash_id = v.peer_hash_id)\nWHERE p.isipv4 = CASE WHEN family('$prefix') = 4 THEN true ELSE false END\n AND p.state = 'up'\nGROUP BY p.hash_id,v.peer_hash_id,p.isipv4\norder by time\n\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Peer Visibility", + "type": "piechart" + }, + { + "columns": [], + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fontSize": "100%", + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 12, + "links": [], + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "raw_output", + "preserveFormat": true, + "sanitize": false, + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select distinct origin_as,i.as_name,org_id,org_name,remarks,address,city,state_prov,country,raw_output,source\n from ip_rib r LEFT JOIN info_asn i ON (i.asn = r.origin_as)\n where r.prefix = '$prefix' \n and origin_as > 0\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "ASN Info", + "transform": "table", + "type": "table-old" + }, + { + "columns": [], + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fontSize": "100%", + "gridPos": { + "h": 4, + "w": 24, + "x": 0, + "y": 14 + }, + "id": 13, + "links": [], + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colorMode": "cell", + "colors": [ + "#cca300", + "#e24d42", + "#9ac48a" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "irr_origin_as", + "thresholds": [ + "0", + "1" + ], + "type": "number", + "unit": "none" + }, + { + "alias": "", + "align": "auto", + "colorMode": "cell", + "colors": [ + "#cca300", + "#e24d42", + "#9ac48a" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 0, + "mappingType": 1, + "pattern": "rpki_origin_as", + "thresholds": [ + "0", + "1" + ], + "type": "number", + "unit": "none" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select distinct r.origin_as as recv_origin_as,\n CASE WHEN g.rpki_origin_as is null THEN 0 ELSE g.rpki_origin_as END as rpki_origin_as,\n CASE WHEN i.origin_as is null THEN 0 ELSE i.origin_as END as irr_origin_as,\n i.descr,i.source\n from ip_rib r \n LEFT JOIN info_route i ON (i.prefix = r.prefix)\n LEFT JOIN global_ip_rib g ON (g.prefix = r.prefix)\n where r.prefix = '$prefix'\n and r.origin_as > 0\n AND r.peer_hash_id in ($peer_hash)\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Prefix Info", + "transform": "table", + "type": "table-old" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "filterable": true, + "inspect": false + }, + "decimals": 0, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "lastmodified" + }, + "properties": [ + { + "id": "displayName", + "value": "Time" + }, + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss.SSS" + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "prefix" + }, + "properties": [ + { + "id": "displayName", + "value": "Prefix" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Prefix History ", + "url": "/d/prefix-hist/prefix-history-by-prefix?orgId=1&var-prefix=${__value.text}&var-input=${__value.text}" + } + ] + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "origin_as" + }, + "properties": [ + { + "id": "displayName", + "value": "Origin" + }, + { + "id": "unit", + "value": "none" + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "ASN View", + "url": "d/asnview-agg/asn-view?orgId=1&var-asn_num=${__value.text}" + } + ] + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "iswithdrawn" + }, + "properties": [ + { + "id": "displayName", + "value": "Withdrawn" + }, + { + "id": "unit", + "value": "bool" + }, + { + "id": "custom.displayMode", + "value": "color-background-solid" + }, + { + "id": "custom.align", + "value": "auto" + }, + { + "id": "color", + "value": { + "mode": "continuous-GrYlRd" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.width", + "value": 194 + } + ] + } + ] + }, + "gridPos": { + "h": 23, + "w": 24, + "x": 0, + "y": 18 + }, + "id": 3, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select distinct ip.*, \n \tFIRST_VALUE(geo_ip.city) OVER (PARTITION BY ip.prefix ORDER BY geo_ip.ip DESC) as city,\n \tFIRST_VALUE(geo_ip.stateprov) OVER (PARTITION BY ip.prefix ORDER BY geo_ip.ip DESC) as stateprov,\n \tFIRST_VALUE(geo_ip.country) OVER (PARTITION BY ip.prefix ORDER BY geo_ip.ip DESC) as country,\n ls.local_router_name\n\tFROM (SELECT lastmodified,peername,prefix,\n \tiswithdrawn,origin_as,med,localpref,nh,as_path,communities\n from v_ip_routes\n \t\twhere prefix && '$input' and prefixlen <= 32 AND prefixlen > 0\n \t\t AND peer_hash_id in ($peer_hash)\n \t\tlimit 2000\n \t) ip\n\t\tLEFT JOIN geo_ip on (geo_ip.ip >>= ip.prefix AND geo_ip.ip != '0.0.0.0/0')\n LEFT JOIN v_ls_prefixes ls ON (ls.prefix >>= ip.nh and length(ls.local_router_name) > 0)", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Looking Glass", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + } + ], + "type": "table" + } + ], + "schemaVersion": 36, + "style": "dark", + "tags": [ + "obmp-base" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "17.44.224.0/22", + "value": "17.44.224.0/22" + }, + "hide": 0, + "label": "Prefix/IP", + "name": "input", + "options": [ + { + "selected": false, + "text": "3.235.73.1", + "value": "3.235.73.1" + } + ], + "query": "17.44.224.0/22", + "queryValue": "50.227.215.188", + "skipUrlSync": false, + "type": "textbox" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select name as __text, hash_id as __value from routers where state = 'up'", + "hide": 0, + "includeAll": true, + "label": "Router", + "multi": true, + "name": "router_hash", + "options": [], + "query": "select name as __text, hash_id as __value from routers where state = 'up'", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash)", + "hide": 0, + "includeAll": true, + "label": "Peer", + "multi": true, + "name": "peer_hash", + "options": [], + "query": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "17.44.224.0/22", + "value": "17.44.224.0/22" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select prefix from ip_rib \nwhere prefix >>= '$input' and peer_hash_id in ($peer_hash) \norder by prefix desc limit 1", + "hide": 2, + "includeAll": false, + "multi": false, + "name": "prefix", + "options": [], + "query": "select prefix from ip_rib \nwhere prefix >>= '$input' and peer_hash_id in ($peer_hash) \norder by prefix desc limit 1", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "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": "Looking Glass", + "uid": "lookingglass", + "version": 4, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/History-1002/prefix_hist_asn.json b/obmp-grafana/dashboards/obmp/History-1002/prefix_hist_asn.json new file mode 100644 index 0000000..56cf19a --- /dev/null +++ b/obmp-grafana/dashboards/obmp/History-1002/prefix_hist_asn.json @@ -0,0 +1,644 @@ +{ + "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, + "id": 7, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "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": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 11, + "x": 0, + "y": 0 + }, + "id": 1, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "sum" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.0.5", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "time_series", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n $__timeGroup(interval_time, $__interval) as time,\n sum(updates) as updates, sum(withdraws) as withdraws\nFROM stats_chg_byasn s\nWHERE $__timeFilter(interval_time)\n AND s.origin_as = [[origin_as]]\n AND s.peer_hash_id in ($peer_hash)\n\ngroup by time\nORDER BY time ASC\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Prefix Advertisements & Withdrawals", + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "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": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 13, + "x": 11, + "y": 0 + }, + "id": 2, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "max", + "sum" + ], + "displayMode": "table", + "placement": "right", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.0.5", + "targets": [ + { + "alias": "", + "format": "time_series", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n $__timeGroup(interval_time, $__interval) as time,\n sum(updates) as updates, sum(withdraws) as withdraws,\n left(PeerName,32) as metric\nFROM stats_chg_byasn l\n JOIN v_peers p ON (l.peer_hash_id = p.peer_hash_id)\nWHERE $__timeFilter(interval_time)\n AND l.origin_as = [[origin_as]]\n AND l.peer_hash_id in ($peer_hash)\n\nGROUP BY peername,time\nORDER BY time ASC\n\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Changes by Peer", + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "filterable": true, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "lastmodified" + }, + "properties": [ + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss.SSS" + }, + { + "id": "custom.width", + "value": 201 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "origin_as" + }, + "properties": [ + { + "id": "custom.width", + "value": 118 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "localpref" + }, + "properties": [ + { + "id": "custom.width", + "value": 76 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "communities" + }, + "properties": [ + { + "id": "custom.width", + "value": 525 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "as_path" + }, + "properties": [ + { + "id": "custom.width", + "value": 252 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "med" + }, + "properties": [ + { + "id": "custom.width", + "value": 87 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "nh" + }, + "properties": [ + { + "id": "custom.width", + "value": 136 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "prefix" + }, + "properties": [ + { + "id": "custom.width", + "value": 206 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "event" + }, + "properties": [ + { + "id": "custom.width", + "value": 113 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "routername" + }, + "properties": [ + { + "id": "custom.width", + "value": 142 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "peername" + }, + "properties": [ + { + "id": "custom.width", + "value": 283 + } + ] + } + ] + }, + "gridPos": { + "h": 20, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 3, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "9.1.7", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": " select lastmodified,event,routername,peername,prefix,nh,\n origin_as,localpref,med,as_path,communities\n from v_ip_routes_history \n where $__timeFilter(lastmodified)\n AND origin_as = [[origin_as]]\n AND peer_hash_id in ($peer_hash)\n\n order by lastmodified desc,id desc\n limit $limit;", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Prefix History", + "type": "table" + } + ], + "refresh": "", + "schemaVersion": 37, + "style": "dark", + "tags": [ + "obmp-history" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "16509", + "value": "16509" + }, + "hide": 0, + "label": "Origin ASN", + "name": "origin_as", + "options": [ + { + "selected": true, + "text": "0", + "value": "0" + } + ], + "query": "0", + "skipUrlSync": false, + "type": "textbox" + }, + { + "current": { + "selected": false, + "text": "1000", + "value": "1000" + }, + "hide": 0, + "includeAll": false, + "label": "Limit", + "multi": false, + "name": "limit", + "options": [ + { + "selected": true, + "text": "1000", + "value": "1000" + }, + { + "selected": false, + "text": "5000", + "value": "5000" + }, + { + "selected": false, + "text": "10000", + "value": "10000" + } + ], + "query": "1000,5000,10000", + "skipUrlSync": false, + "type": "custom" + }, + { + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select name as __text, hash_id as __value from routers", + "hide": 0, + "includeAll": true, + "label": "Router", + "multi": true, + "name": "router_hash", + "options": [], + "query": "select name as __text, hash_id as __value from routers", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash) ", + "hide": 0, + "includeAll": true, + "label": "Peer", + "multi": true, + "name": "peer_hash", + "options": [], + "query": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash) ", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-24h", + "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": "Prefix History (by ASN)", + "uid": "prefix-hist-asn", + "version": 2, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/History-1002/prefix_hist_community.json b/obmp-grafana/dashboards/obmp/History-1002/prefix_hist_community.json new file mode 100644 index 0000000..eb62618 --- /dev/null +++ b/obmp-grafana/dashboards/obmp/History-1002/prefix_hist_community.json @@ -0,0 +1,376 @@ +{ + "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, + "id": 8, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "filterable": true, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "lastmodified" + }, + "properties": [ + { + "id": "custom.width", + "value": 214 + }, + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss.SSS" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "localpref" + }, + "properties": [ + { + "id": "custom.width", + "value": 107 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "med" + }, + "properties": [ + { + "id": "custom.width", + "value": 79 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "nh" + }, + "properties": [ + { + "id": "custom.width", + "value": 122 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "origin_as" + }, + "properties": [ + { + "id": "custom.width", + "value": 112 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "prefix" + }, + "properties": [ + { + "id": "custom.width", + "value": 148 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "routername" + }, + "properties": [ + { + "id": "custom.width", + "value": 216 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "event" + }, + "properties": [ + { + "id": "custom.width", + "value": 112 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "peername" + }, + "properties": [ + { + "id": "custom.width", + "value": 310 + } + ] + } + ] + }, + "gridPos": { + "h": 23, + "w": 23, + "x": 0, + "y": 0 + }, + "id": 3, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "9.1.7", + "targets": [ + { + "alias": "", + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": " select lastmodified,event,routername,peername,prefix,\n origin_as,nh,localpref,med,as_path,communities \n from v_ip_routes_history \n where $__timeFilter(lastmodified)\n AND peer_hash_id in ($peer_hash)\n AND communities && '{$community}'\n order by lastmodified desc,id desc\n limit $limit;", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Prefix History", + "type": "table" + } + ], + "schemaVersion": 37, + "style": "dark", + "tags": [ + "obmp-history" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "13445:1000", + "value": "13445:1000" + }, + "hide": 0, + "includeAll": false, + "label": "Community", + "multi": false, + "name": "community", + "options": [ + { + "selected": true, + "text": "13445:1000", + "value": "13445:1000" + } + ], + "query": "13445:1000", + "skipUrlSync": false, + "type": "custom" + }, + { + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select name as __text, hash_id as __value from routers", + "hide": 0, + "includeAll": true, + "label": "Router", + "multi": true, + "name": "router_hash", + "options": [], + "query": "select name as __text, hash_id as __value from routers", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash)", + "hide": 0, + "includeAll": true, + "label": "Peer", + "multi": true, + "name": "peer_hash", + "options": [], + "query": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "1000", + "value": "1000" + }, + "hide": 0, + "includeAll": false, + "label": "Limit", + "multi": false, + "name": "limit", + "options": [ + { + "selected": true, + "text": "1000", + "value": "1000" + }, + { + "selected": false, + "text": "5000", + "value": "5000" + }, + { + "selected": false, + "text": "10000", + "value": "10000" + } + ], + "query": "1000, 5000, 10000", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-1h", + "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": "Prefix History (by Community)", + "uid": "prefix-hist-comm", + "version": 2, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/History-1002/prefix_history.json b/obmp-grafana/dashboards/obmp/History-1002/prefix_history.json new file mode 100644 index 0000000..2906b53 --- /dev/null +++ b/obmp-grafana/dashboards/obmp/History-1002/prefix_history.json @@ -0,0 +1,677 @@ +{ + "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" + } + ] + }, + "description": "", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 9, + "links": [], + "liveNow": false, + "panels": [ + { + "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": "lastmodified" + }, + "properties": [ + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss.SSS" + }, + { + "id": "custom.width", + "value": 224 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 5, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "9.1.7", + "targets": [ + { + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select lastmodified,CASE WHEN iswithdrawn THEN 'Withdrawn' ELSE 'Active' END as state,routername,peername,prefix,prefixlen,\n origin_as,med,localpref,nh,as_path,communities \n from v_ip_routes \n where peer_hash_id in ($peer_hash) \n ${prefix_clause:raw}\n limit $limit\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Current RIB State", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "decimals": 0, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 11, + "x": 0, + "y": 6 + }, + "hiddenSeries": false, + "id": 1, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "show": true, + "total": true, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.1.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "", + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n interval_time as time,\n sum(updates) as updates, sum(withdraws) as withdraws\nFROM stats_chg_byprefix s\nWHERE $__timeFilter(interval_time)\n AND peer_hash_id in ($peer_hash)\n ${prefix_clause:raw}\n\ngroup by interval_time\nORDER BY interval_time ASC\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Prefix Advertisements & Withdrawals", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:289", + "format": "none", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:290", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "decimals": 0, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 13, + "x": 11, + "y": 6 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sort": "total", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.1.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "", + "format": "time_series", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n interval_time as time,\n sum(updates) + sum(withdraws) as value,\n left(PeerName,32) as metric\nFROM stats_chg_byprefix s\n JOIN v_peers p ON (s.peer_hash_id = p.peer_hash_id)\nWHERE $__timeFilter(interval_time)\n AND s.peer_hash_id in ($peer_hash)\n ${prefix_clause:raw}\n\nGROUP BY s.interval_time,peername\nORDER BY interval_time ASC\n\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Changes by Peer", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:346", + "decimals": 0, + "format": "none", + "label": "", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:347", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "filterable": true, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "lastmodified" + }, + "properties": [ + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss.SSS" + }, + { + "id": "displayName", + "value": "Last Modified" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Last Modified" + }, + "properties": [ + { + "id": "custom.width", + "value": 208 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "communities" + }, + "properties": [ + { + "id": "custom.width", + "value": 402 + } + ] + } + ] + }, + "gridPos": { + "h": 20, + "w": 24, + "x": 0, + "y": 13 + }, + "id": 3, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Last Modified" + } + ] + }, + "pluginVersion": "9.1.7", + "targets": [ + { + "alias": "", + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": " select lastmodified,event,routername,peername,prefix,nh,\n origin_as,as_path,communities,localpref,med\n from v_ip_routes_history \n where $__timeFilter(lastmodified)\n AND peer_hash_id in ($peer_hash)\n ${prefix_clause:raw}\n \n order by lastmodified desc,id desc\n limit $limit;", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Prefix History", + "type": "table" + } + ], + "refresh": "", + "schemaVersion": 37, + "style": "dark", + "tags": [ + "obmp-history" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select name as __text, hash_id as __value from routers\n", + "hide": 0, + "includeAll": true, + "label": "Router", + "multi": true, + "name": "router_hash", + "options": [], + "query": "select name as __text, hash_id as __value from routers\n", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash) ", + "hide": 0, + "includeAll": true, + "label": "Peer", + "multi": true, + "name": "peer_hash", + "options": [], + "query": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash) ", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "1000", + "value": "1000" + }, + "hide": 0, + "includeAll": false, + "label": "Limit", + "multi": false, + "name": "limit", + "options": [ + { + "selected": true, + "text": "1000", + "value": "1000" + }, + { + "selected": false, + "text": "5000", + "value": "5000" + }, + { + "selected": false, + "text": "10000", + "value": "10000" + } + ], + "query": "1000,5000,10000", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + }, + { + "current": { + "selected": false, + "text": "187.249.2.0/24", + "value": "187.249.2.0/24" + }, + "hide": 0, + "label": "Prefix", + "name": "input", + "options": [ + { + "selected": true, + "text": "187.249.2.0/24", + "value": "187.249.2.0/24" + } + ], + "query": "187.249.2.0/24", + "queryValue": "67.211.53.0/24", + "skipUrlSync": false, + "type": "textbox" + }, + { + "current": { + "selected": false, + "text": "AND prefix = '187.249.2.0/24'", + "value": "AND prefix = '187.249.2.0/24'" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select CASE WHEN '$input' != '-' THEN 'AND prefix = ''' || (select prefix from global_ip_rib where prefix >>= (CASE WHEN '$input' != '-' THEN '$input' ELSE '0/0' END)::inet order by prefix desc limit 1)::text || '''' ELSE '' END;", + "hide": 2, + "includeAll": false, + "multi": false, + "name": "prefix_clause", + "options": [], + "query": "select CASE WHEN '$input' != '-' THEN 'AND prefix = ''' || (select prefix from global_ip_rib where prefix >>= (CASE WHEN '$input' != '-' THEN '$input' ELSE '0/0' END)::inet order by prefix desc limit 1)::text || '''' ELSE '' END;", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "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": "Prefix History (by Prefix)", + "uid": "prefix-hist", + "version": 2, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/L3VPN-1005/l3vpn_looking_glass.json b/obmp-grafana/dashboards/obmp/L3VPN-1005/l3vpn_looking_glass.json new file mode 100644 index 0000000..9caa2a7 --- /dev/null +++ b/obmp-grafana/dashboards/obmp/L3VPN-1005/l3vpn_looking_glass.json @@ -0,0 +1,780 @@ +{ + "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, + "id": 19, + "iteration": 1654877653557, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "description": "Prefix found in router's RIB.", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 0, + "y": 0 + }, + "id": 9, + "links": [], + "maxDataPoints": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "values": [ + "value", + "percent" + ] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n floor(extract(epoch from max(r.timestamp))) as time,\n CASE WHEN v.router_hash_id is null THEN 'Not in Router RIB' ELSE 'In Router Rib' END as metric,\n 1 as value\nFROM routers r\n left join (select distinct router_hash_id\n from v_l3vpn_routes\n where prefix = '$prefix'\n and ('$rd' = '-' OR rd = '$rd')\n and iswithdrawn = false group by router_hash_id) v \n on (r.hash_id = v.router_hash_id)\nWHERE r.state = 'up'\nGROUP BY r.hash_id,v.router_hash_id\norder by time\n\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Router Visibility", + "type": "piechart" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "description": "Prefix found in peer RIB's", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 6, + "x": 6, + "y": 0 + }, + "id": 10, + "links": [], + "maxDataPoints": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "values": [ + "value", + "percent" + ] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n floor(extract(epoch from max(p.timestamp))) as time,\n CASE WHEN v.peer_hash_id is null THEN 'Not in Peers RIB' ELSE 'In Peer RIB' END as metric,\n 1 as value\nFROM bgp_peers p\n left join (select peer_hash_id,isipv4\n from l3vpn_rib \n where prefix = '$prefix' and prefix != '0.0.0.0/0'\n AND ('$rd' = '-' OR rd = '$rd')\n and iswithdrawn = false group by peer_hash_id,isipv4) v \n on (p.hash_id = v.peer_hash_id)\nWHERE p.isipv4 = CASE WHEN family('$prefix') = 4 THEN true ELSE false END\n AND p.state = 'up'\nGROUP BY p.hash_id,v.peer_hash_id,p.isipv4\norder by time\n\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Peer Visibility", + "type": "piechart" + }, + { + "circleMaxSize": "15", + "circleMinSize": 2, + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "decimals": 0, + "esMetric": "Count", + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "hideEmpty": false, + "hideZero": false, + "id": 17, + "initialZoom": "1", + "locationData": "table", + "mapCenter": "(0°, 0°)", + "mapCenterLatitude": 0, + "mapCenterLongitude": 0, + "maxDataPoints": 1, + "mouseWheelZoom": false, + "showLegend": false, + "stickyLabels": false, + "tableQueryOptions": { + "geohashField": "geohash", + "labelField": "name", + "latitudeField": "latitude", + "longitudeField": "longitude", + "metricField": "value", + "queryType": "coordinates" + }, + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n 10 as value, latitude, longitude, stateprov as name\nFROM geo_ip\nWHERE\n ip && '$input'\nORDER BY ip desc limit 1", + "refId": "A", + "select": [ + [ + { + "params": [ + "latitude" + ], + "type": "column" + } + ] + ], + "table": "v_ip_routes_geo", + "timeColumn": "lastmodified", + "timeColumnType": "timestamp", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "thresholds": "0,10", + "title": "Prefix Location", + "type": "grafana-worldmap-panel", + "unitPlural": "", + "unitSingle": "", + "valueName": "current" + }, + { + "columns": [], + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fontSize": "100%", + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 12, + "links": [], + "scroll": true, + "showHeader": true, + "sort": { + "col": 0, + "desc": true + }, + "styles": [ + { + "alias": "Time", + "align": "auto", + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "pattern": "Time", + "type": "date" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "dateFormat": "YYYY-MM-DD HH:mm:ss", + "decimals": 2, + "mappingType": 1, + "pattern": "raw_output", + "preserveFormat": true, + "sanitize": false, + "thresholds": [], + "type": "string", + "unit": "short" + }, + { + "alias": "", + "align": "auto", + "colors": [ + "rgba(245, 54, 54, 0.9)", + "rgba(237, 129, 40, 0.89)", + "rgba(50, 172, 45, 0.97)" + ], + "decimals": 2, + "pattern": "/.*/", + "thresholds": [], + "type": "string", + "unit": "short" + } + ], + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select distinct origin_as,i.as_name,org_id,org_name,remarks,address,city,state_prov,country,raw_output,source\n from l3vpn_rib r LEFT JOIN info_asn i ON (i.asn = r.origin_as)\n where r.prefix = '$prefix'\n and ('$rd' = '-' OR rd = '$rd')\n and origin_as > 0\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "ASN Info", + "transform": "table", + "type": "table-old" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "filterable": true, + "inspect": false + }, + "decimals": 0, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "lastmodified" + }, + "properties": [ + { + "id": "displayName", + "value": "Time" + }, + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss.SSS" + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "prefix" + }, + "properties": [ + { + "id": "displayName", + "value": "Prefix" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Prefix History ", + "url": "/d/l3vpn-prefix-hist/prefix-history-by-prefix-l3vpn?orgId=1&var-input=${__value.text}&var-rd=$rd" + } + ] + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "origin_as" + }, + "properties": [ + { + "id": "displayName", + "value": "Origin" + }, + { + "id": "unit", + "value": "none" + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "ASN View", + "url": "/grafana/d/asnview/asn-view?orgId=1&var-asn_num=${__value.text}" + } + ] + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "iswithdrawn" + }, + "properties": [ + { + "id": "displayName", + "value": "Withdrawn" + }, + { + "id": "unit", + "value": "bool" + }, + { + "id": "custom.displayMode", + "value": "color-background-solid" + }, + { + "id": "custom.align", + "value": "auto" + }, + { + "id": "color", + "value": { + "mode": "continuous-GrYlRd" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.width", + "value": 194 + } + ] + } + ] + }, + "gridPos": { + "h": 23, + "w": 24, + "x": 0, + "y": 14 + }, + "id": 3, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select distinct ip.*, \n \tFIRST_VALUE(geo_ip.city) OVER (PARTITION BY ip.prefix ORDER BY geo_ip.ip DESC) as city,\n \tFIRST_VALUE(geo_ip.stateprov) OVER (PARTITION BY ip.prefix ORDER BY geo_ip.ip DESC) as stateprov,\n \tFIRST_VALUE(geo_ip.country) OVER (PARTITION BY ip.prefix ORDER BY geo_ip.ip DESC) as country,\n ls.local_router_name\n\tFROM (SELECT lastmodified,peername,rd,prefix,\n \tiswithdrawn,origin_as,med,localpref,nh,as_path,extcommunities,communities,largecommunities\n from v_l3vpn_routes\n \t\twhere prefix && '$input' \n \t\t AND peer_hash_id in ($peer_hash)\n \t\t AND ('$rd' = '-' OR rd = '$rd')\n \t\tlimit 2000\n \t) ip\n\t\tLEFT JOIN geo_ip on (geo_ip.ip >>= ip.prefix AND geo_ip.ip != '0.0.0.0/0')\n LEFT JOIN v_ls_prefixes ls ON (ls.prefix >>= ip.nh and length(ls.local_router_name) > 0)", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Looking Glass", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + } + ], + "type": "table" + } + ], + "schemaVersion": 36, + "style": "dark", + "tags": [ + "obmp-l3vpn" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "80.0.0.2", + "value": "80.0.0.2" + }, + "hide": 0, + "label": "Prefix/IP", + "name": "input", + "options": [ + { + "selected": true, + "text": "80.0.0.2", + "value": "80.0.0.2" + } + ], + "query": "80.0.0.2", + "queryValue": "50.227.215.188", + "skipUrlSync": false, + "type": "textbox" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select name as __text, hash_id as __value from routers where state = 'up'", + "hide": 0, + "includeAll": true, + "label": "Router", + "multi": true, + "name": "router_hash", + "options": [], + "query": "select name as __text, hash_id as __value from routers where state = 'up'", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash) and recvcapabilities like '% afi=1 safi=128 %';", + "hide": 0, + "includeAll": true, + "label": "Peer", + "multi": true, + "name": "peer_hash", + "options": [], + "query": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash) and recvcapabilities like '% afi=1 safi=128 %';", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "isNone": true, + "selected": false, + "text": "None", + "value": "" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select prefix from l3vpn_rib \nwhere prefix >>= '$input' and peer_hash_id in ($peer_hash) and ('$rd' = '-' OR rd = '$rd')\norder by prefix desc limit 1", + "hide": 2, + "includeAll": false, + "multi": false, + "name": "prefix", + "options": [], + "query": "select prefix from l3vpn_rib \nwhere prefix >>= '$input' and peer_hash_id in ($peer_hash) and ('$rd' = '-' OR rd = '$rd')\norder by prefix desc limit 1", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "description": "RD in the format of N:N. Set to - for all.", + "hide": 2, + "label": "RD", + "name": "rd", + "query": "-", + "skipUrlSync": false, + "type": "constant" + } + ] + }, + "time": { + "from": "now-1h", + "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": "Looking Glass - L3VPN", + "uid": "jiQW6VB7k", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/L3VPN-1005/l3vpn_prefix_hist.json b/obmp-grafana/dashboards/obmp/L3VPN-1005/l3vpn_prefix_hist.json new file mode 100644 index 0000000..62f1d24 --- /dev/null +++ b/obmp-grafana/dashboards/obmp/L3VPN-1005/l3vpn_prefix_hist.json @@ -0,0 +1,745 @@ +{ + "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" + } + ] + }, + "description": "", + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 20, + "links": [], + "liveNow": false, + "panels": [ + { + "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": "lastmodified" + }, + "properties": [ + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss.SSS" + }, + { + "id": "custom.width", + "value": 224 + } + ] + } + ] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 5, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "9.1.7", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select lastmodified,CASE WHEN iswithdrawn THEN 'Withdrawn' ELSE 'Active' END as state,routername,peername,prefix,prefixlen,\n origin_as,med,localpref,nh,as_path,communities \n from v_l3vpn_routes \n where peer_hash_id in ($peer_hash) \n ${prefix_clause:raw}\n limit $limit\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Current RIB State", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + } + ], + "type": "table" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "decimals": 0, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 6 + }, + "hiddenSeries": false, + "id": 1, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "total": true, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.1.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n interval_time as time,\n sum(updates) as updates, sum(withdraws) as withdraws\nFROM stats_l3vpn_chg_byprefix s\nWHERE $__timeFilter(interval_time)\n AND peer_hash_id in ($peer_hash)\n ${prefix_clause:raw}\n\ngroup by interval_time\nORDER BY interval_time ASC\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Prefix Advertisements & Withdrawals", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:289", + "format": "none", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:290", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "decimals": 0, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 6 + }, + "hiddenSeries": false, + "id": 2, + "legend": { + "alignAsTable": true, + "avg": true, + "current": false, + "max": true, + "min": false, + "rightSide": true, + "show": true, + "sort": "total", + "sortDesc": true, + "total": true, + "values": true + }, + "lines": true, + "linewidth": 1, + "links": [], + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.1.7", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "time_series", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n interval_time as time,\n sum(updates) + sum(withdraws) as value,\n left(PeerName,32) as metric\nFROM stats_l3vpn_chg_byprefix s\n JOIN v_peers p ON (s.peer_hash_id = p.peer_hash_id)\nWHERE $__timeFilter(interval_time)\n AND s.peer_hash_id in ($peer_hash)\n ${prefix_clause:raw}\n\nGROUP BY s.interval_time,peername\nORDER BY interval_time ASC\n\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Changes by Peer", + "tooltip": { + "shared": true, + "sort": 0, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:346", + "decimals": 0, + "format": "none", + "label": "", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:347", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "filterable": true, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "lastmodified" + }, + "properties": [ + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss.SSS" + }, + { + "id": "displayName", + "value": "Last Modified" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Last Modified" + }, + "properties": [ + { + "id": "custom.width", + "value": 208 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "event" + }, + "properties": [ + { + "id": "mappings", + "value": [ + { + "options": { + "Advertised": { + "color": "semi-dark-green", + "index": 0 + }, + "Withdrawn": { + "color": "semi-dark-red", + "index": 1 + } + }, + "type": "value" + } + ] + }, + { + "id": "custom.displayMode", + "value": "color-background-solid" + } + ] + } + ] + }, + "gridPos": { + "h": 20, + "w": 24, + "x": 0, + "y": 13 + }, + "id": 3, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [ + { + "desc": true, + "displayName": "Last Modified" + } + ] + }, + "pluginVersion": "9.1.7", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": " select lastmodified,event,routername,peername,prefix,nh,\n origin_as,localpref,med,as_path,extcommunities,communities,largecommunities\n from v_l3vpn_routes_history \n where $__timeFilter(lastmodified)\n AND peer_hash_id in ($peer_hash)\n ${prefix_clause:raw}\n \n order by lastmodified desc,id desc\n limit $limit;", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Prefix History", + "type": "table" + } + ], + "refresh": "", + "schemaVersion": 37, + "style": "dark", + "tags": [ + "obmp-l3vpn" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select routername as __text, router_hash_id as __value from v_peers where recvcapabilities like '% afi=1 safi=128 %';\n", + "hide": 0, + "includeAll": true, + "label": "Router", + "multi": true, + "name": "router_hash", + "options": [], + "query": "select routername as __text, router_hash_id as __value from v_peers where recvcapabilities like '% afi=1 safi=128 %';\n", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash) and recvcapabilities like '% afi=1 safi=128 %';", + "hide": 0, + "includeAll": true, + "label": "Peer", + "multi": true, + "name": "peer_hash", + "options": [], + "query": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash) and recvcapabilities like '% afi=1 safi=128 %';", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "1000", + "value": "1000" + }, + "hide": 0, + "includeAll": false, + "label": "Limit", + "multi": false, + "name": "limit", + "options": [ + { + "selected": true, + "text": "1000", + "value": "1000" + }, + { + "selected": false, + "text": "3000", + "value": "3000" + }, + { + "selected": false, + "text": "5000", + "value": "5000" + }, + { + "selected": false, + "text": "8000", + "value": "8000" + }, + { + "selected": false, + "text": "10000", + "value": "10000" + } + ], + "query": "1000,3000,5000,8000,10000", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + }, + { + "current": { + "selected": false, + "text": "100.100.100.100", + "value": "100.100.100.100" + }, + "hide": 0, + "label": "Prefix", + "name": "input", + "options": [ + { + "selected": true, + "text": "100.100.100.100", + "value": "100.100.100.100" + } + ], + "query": "100.100.100.100", + "queryValue": "67.211.53.0/24", + "skipUrlSync": false, + "type": "textbox" + }, + { + "current": { + "selected": false, + "text": "", + "value": "" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select CASE WHEN '$input' != '-' THEN 'AND prefix = ''' || (\n select prefix from l3vpn_rib \n where peer_hash_id in ($peer_hash) \n AND ('$rd' = '-' OR rd = '$rd')\n AND prefix >>= (CASE WHEN '$input' != '-' THEN '$input' ELSE '0/0' END)::inet order by prefix desc limit 1)::text || ''''\n ELSE '' END;", + "hide": 2, + "includeAll": false, + "multi": false, + "name": "prefix_clause", + "options": [], + "query": "select CASE WHEN '$input' != '-' THEN 'AND prefix = ''' || (\n select prefix from l3vpn_rib \n where peer_hash_id in ($peer_hash) \n AND ('$rd' = '-' OR rd = '$rd')\n AND prefix >>= (CASE WHEN '$input' != '-' THEN '$input' ELSE '0/0' END)::inet order by prefix desc limit 1)::text || ''''\n ELSE '' END;", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": false, + "text": "-", + "value": "-" + }, + "description": "RD in the format of N:N. Set to - for all.", + "hide": 0, + "includeAll": false, + "label": "RD", + "multi": false, + "name": "rd", + "options": [ + { + "selected": true, + "text": "-", + "value": "-" + } + ], + "query": "-", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "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": "Prefix History (by Prefix) L3VPN", + "uid": "l3vpn-prefix-hist", + "version": 2, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/L3VPN-1005/l3vpn_rib_browser.json b/obmp-grafana/dashboards/obmp/L3VPN-1005/l3vpn_rib_browser.json new file mode 100644 index 0000000..30a676a --- /dev/null +++ b/obmp-grafana/dashboards/obmp/L3VPN-1005/l3vpn_rib_browser.json @@ -0,0 +1,702 @@ +{ + "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, + "id": 21, + "iteration": 1654877634754, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMin": 0, + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + } + }, + "decimals": 0, + "displayName": "Routes", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 11, + "x": 0, + "y": 0 + }, + "id": 5, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "groupWidth": 0.7, + "legend": { + "calcs": [ + "sum" + ], + "displayMode": "table", + "placement": "bottom" + }, + "orientation": "auto", + "showValue": "always", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select\n count(*) as count,\n rd\n from l3vpn_rib\n where\n peer_hash_id in ($peer_hash)\n and ('$rd' = '-' or rd = '$rd')\n and iswithdrawn = false\n group by rd\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "latitude" + ], + "type": "column" + } + ] + ], + "table": "v_ip_routes_geo", + "timeColumn": "lastmodified", + "timeColumnType": "timestamp", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Routes Advertised/Active", + "type": "barchart" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "axisSoftMin": 0, + "fillOpacity": 80, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineWidth": 1, + "scaleDistribution": { + "type": "linear" + } + }, + "decimals": 0, + "displayName": "Routes", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "semi-dark-orange", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "count" + ], + "prefix": "All except:", + "readOnly": true + } + }, + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] + } + ] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 11, + "y": 0 + }, + "id": 6, + "options": { + "barRadius": 0, + "barWidth": 0.97, + "groupWidth": 0.7, + "legend": { + "calcs": [ + "sum" + ], + "displayMode": "table", + "placement": "bottom" + }, + "orientation": "auto", + "showValue": "always", + "stacking": "none", + "tooltip": { + "mode": "single", + "sort": "none" + }, + "xTickLabelRotation": 0, + "xTickLabelSpacing": 0 + }, + "pluginVersion": "8.3.4", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select\n count(*) as count,\n rd\n from l3vpn_rib\n where\n peer_hash_id in ($peer_hash)\n and ('$rd' = '-' OR rd = '$rd')\n and iswithdrawn = true\n group by rd\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "latitude" + ], + "type": "column" + } + ] + ], + "table": "v_ip_routes_geo", + "timeColumn": "lastmodified", + "timeColumnType": "timestamp", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Routes Withdrawn/Inactive", + "type": "barchart" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "filterable": true, + "inspect": false + }, + "decimals": 0, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "lastmodified" + }, + "properties": [ + { + "id": "displayName", + "value": "Time" + }, + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss.SSS" + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "prefix" + }, + "properties": [ + { + "id": "displayName", + "value": "Prefix" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Prefix History ", + "url": "/d/l3vpn-prefix-hist/prefix-history-by-prefix-l3vpn?orgId=1&var-limit=$limit&var-input=${__value.text}&var-rd=$rd" + } + ] + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "origin_as" + }, + "properties": [ + { + "id": "displayName", + "value": "Origin" + }, + { + "id": "unit", + "value": "none" + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "ASN View", + "url": "/grafana/d/asnview/asn-view?orgId=1&var-asn_num=${__value.text}" + } + ] + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "iswithdrawn" + }, + "properties": [ + { + "id": "displayName", + "value": "Withdrawn" + }, + { + "id": "unit", + "value": "bool" + }, + { + "id": "custom.displayMode", + "value": "color-background-solid" + }, + { + "id": "custom.align", + "value": "auto" + }, + { + "id": "color", + "value": { + "mode": "continuous-GrYlRd" + } + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Time" + }, + "properties": [ + { + "id": "custom.width", + "value": 194 + } + ] + } + ] + }, + "gridPos": { + "h": 23, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 3, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select distinct ip.*, \n \tFIRST_VALUE(geo_ip.city) OVER (PARTITION BY ip.prefix ORDER BY geo_ip.ip DESC) as city,\n \tFIRST_VALUE(geo_ip.stateprov) OVER (PARTITION BY ip.prefix ORDER BY geo_ip.ip DESC) as stateprov,\n \tFIRST_VALUE(geo_ip.country) OVER (PARTITION BY ip.prefix ORDER BY geo_ip.ip DESC) as country,\n ls.local_router_name\n\tFROM (SELECT lastmodified,peername,rd,prefix,\n \tiswithdrawn,origin_as,med,localpref,nh,as_path,communities,extcommunities\n from v_l3vpn_routes\n \t\twhere \n \t\t peer_hash_id in ($peer_hash)\n \t\t AND ('$rd' = '-' OR rd = '$rd')\n \t\t AND (iswithdrawn in ($state))\n \t\tlimit $limit\n \t) ip\n\t\tLEFT JOIN geo_ip on (geo_ip.ip >>= ip.prefix AND geo_ip.ip != '0.0.0.0/0')\n LEFT JOIN v_ls_prefixes ls ON (ls.prefix >>= ip.nh and length(ls.local_router_name) > 0)", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Looking Glass (RD = $rd)", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + } + ], + "type": "table" + } + ], + "schemaVersion": 36, + "style": "dark", + "tags": [ + "obmp-l3vpn" + ], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select routername as __text, router_hash_id as __value from v_peers where router_state = 'up' and recvcapabilities like '% afi=1 safi=128 %';", + "hide": 0, + "includeAll": true, + "label": "Router", + "multi": true, + "name": "router_hash", + "options": [], + "query": "select routername as __text, router_hash_id as __value from v_peers where router_state = 'up' and recvcapabilities like '% afi=1 safi=128 %';", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "isNone": true, + "selected": false, + "text": "None", + "value": "" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash) and recvcapabilities like '% afi=1 safi=128 %';", + "hide": 0, + "includeAll": false, + "label": "Peer", + "multi": true, + "name": "peer_hash", + "options": [], + "query": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash) and recvcapabilities like '% afi=1 safi=128 %';", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": true, + "text": "-", + "value": "-" + }, + "description": "RD in the format of N:N. Set to - for all.", + "hide": 0, + "includeAll": false, + "label": "RD", + "multi": false, + "name": "rd", + "options": [ + { + "selected": true, + "text": "-", + "value": "-" + } + ], + "query": "-", + "queryValue": "203:20", + "skipUrlSync": false, + "type": "custom" + }, + { + "current": { + "selected": true, + "text": "1000", + "value": "1000" + }, + "hide": 0, + "includeAll": false, + "label": "Limit", + "multi": false, + "name": "limit", + "options": [ + { + "selected": true, + "text": "1000", + "value": "1000" + }, + { + "selected": false, + "text": "3000", + "value": "3000" + }, + { + "selected": false, + "text": "5000", + "value": "5000" + }, + { + "selected": false, + "text": "8000", + "value": "8000" + }, + { + "selected": false, + "text": "10000", + "value": "10000" + } + ], + "query": "1000,3000,5000,8000,10000", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + }, + { + "current": { + "selected": true, + "text": [ + "Advertised" + ], + "value": [ + "False" + ] + }, + "hide": 0, + "includeAll": true, + "multi": true, + "name": "state", + "options": [ + { + "selected": false, + "text": "All", + "value": "$__all" + }, + { + "selected": true, + "text": "Advertised", + "value": "False" + }, + { + "selected": false, + "text": "Withdrawn", + "value": "True" + } + ], + "query": "Advertised : False, Withdrawn : True", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + } + ] + }, + "time": { + "from": "now-1h", + "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": "L3VPN RIB Browser", + "uid": "v-cdzIBnz", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/LinkState-1004/ls_history.json b/obmp-grafana/dashboards/obmp/LinkState-1004/ls_history.json new file mode 100644 index 0000000..721ba47 --- /dev/null +++ b/obmp-grafana/dashboards/obmp/LinkState-1004/ls_history.json @@ -0,0 +1,324 @@ +{ + "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, + "id": 14, + "iteration": 1654877691622, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 10, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 6, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "always", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ + "sum" + ], + "displayMode": "table", + "placement": "right" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.0.5", + "targets": [ + { + "format": "time_series", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n $__timeGroup(timestamp, $__interval) as time,\n count(*) as count,\n CASE WHEN iswithdrawn THEN 'WITHDRAWN' ELSE 'ACTIVE' END as metric\nFROM\n ls_links_log\nWHERE\n $__timeFilter(timestamp)\n AND peer_hash_id = '$peer_hash'\nGROUP BY time,metric\nORDER BY time\n\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Link Changes", + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "filterable": true, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "seq" + }, + "properties": [ + { + "id": "unit", + "value": "locale" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss.SSS" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "state" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background-solid" + }, + { + "id": "mappings", + "value": [ + { + "options": { + "ACTIVE": { + "color": "semi-dark-green", + "index": 0 + }, + "WITHDRAWN": { + "color": "semi-dark-red", + "index": 1 + } + }, + "type": "value" + } + ] + } + ] + } + ] + }, + "gridPos": { + "h": 14, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "format": "table", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n l.timestamp,\n l.seq,ln.name as LocalNode, rn.name as RemoteNode, l.mt_id,l.igp_metric,CASE WHEN l.iswithdrawn THEN 'WITHDRAWN' ELSE 'ACTIVE' END as state\nFROM\n ls_links_log l JOIN ls_nodes ln ON (l.local_node_hash_id = ln.hash_id and l.peer_hash_id = ln.peer_hash_id) \n JOIN ls_nodes rn ON (l.remote_node_hash_id = rn.hash_id and rn.peer_hash_id = l.peer_hash_id)\nWHERE\n $__timeFilter(l.timestamp)\n AND l.peer_hash_id = '$peer_hash'\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Link History", + "type": "table" + } + ], + "refresh": false, + "schemaVersion": 36, + "style": "dark", + "tags": [ + "obmp-linkstate" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "yyz01-wxbb-crt01-lo0.webex.com", + "value": "367c22e4-57d9-2328-654b-96ea750e0267" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "SELECT __text,__value FROM (\n select peername as __text, peer_hash_id as __value, count(*) as count\n from v_ls_nodes\n group by peername,peer_hash_id) d\nwhere count > 0", + "hide": 0, + "includeAll": false, + "label": "BGP Peer", + "multi": false, + "name": "peer_hash", + "options": [], + "query": "SELECT __text,__value FROM (\n select peername as __text, peer_hash_id as __value, count(*) as count\n from v_ls_nodes\n group by peername,peer_hash_id) d\nwhere count > 0", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "LS Link History", + "uid": "-r7gAlyZk", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/LinkState-1004/ls_links.json b/obmp-grafana/dashboards/obmp/LinkState-1004/ls_links.json new file mode 100644 index 0000000..6084bda --- /dev/null +++ b/obmp-grafana/dashboards/obmp/LinkState-1004/ls_links.json @@ -0,0 +1,479 @@ +{ + "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, + "id": 15, + "iteration": 1654877712696, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 7, + "x": 0, + "y": 0 + }, + "id": 4, + "links": [], + "maxDataPoints": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "values": [ + "value", + "percent" + ] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "format": "time_series", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select floor(extract(epoch from max(timestamp))) as time,\n count(*) as value, CASE WHEN iswithdrawn THEN 'WITHDRAWN' ELSE 'ACTIVE' END as metric\nfrom ls_links\nwhere local_node_hash_id = '$local_node_hash_id'\n AND peer_hash_id = '$peer_hash'\ngroup by iswithdrawn\norder by time\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Link States", + "type": "piechart" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 6, + "x": 7, + "y": 0 + }, + "id": 6, + "links": [], + "maxDataPoints": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "values": [ + "value" + ] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "format": "time_series", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select floor(extract(epoch from max(timestamp))) as time,\n count(*) as value, CASE WHEN mt_id = 2 THEN 'IPv6' ELSE 'IPv4' END as metric\nfrom ls_links\nwhere local_node_hash_id = '$local_node_hash_id'\n AND peer_hash_id = '$peer_hash'\ngroup by mt_id\norder by time\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Links by Type", + "type": "piechart" + }, + { + "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": "timestamp" + }, + "properties": [ + { + "id": "displayName", + "value": "Time" + }, + { + "id": "unit", + "value": "short" + }, + { + "id": "decimals", + "value": 2 + }, + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss.SSS" + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "seq" + }, + "properties": [ + { + "id": "unit", + "value": "locale" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "state" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background-solid" + }, + { + "id": "mappings", + "value": [ + { + "options": { + "ACTIVE": { + "color": "semi-dark-green", + "index": 0 + }, + "WITHDRAWN": { + "color": "semi-dark-red", + "index": 1 + } + }, + "type": "value" + } + ] + } + ] + } + ] + }, + "gridPos": { + "h": 14, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 2, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "format": "table", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT state,local_router_name,local_igp_routerid,remote_router_name,remote_igp_routerid,mt_id,igp_metric,protocol, timestamp, seq\n FROM v_ls_links\n WHERE local_node_hash_id = '$local_node_hash_id'\n AND peer_hash_id = '$peer_hash'", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "$local_node_name Links", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + } + ], + "transparent": true, + "type": "table" + } + ], + "schemaVersion": 36, + "style": "dark", + "tags": [ + "obmp-linkstate" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "yyz01-wxbb-crt01-lo0.webex.com", + "value": "367c22e4-57d9-2328-654b-96ea750e0267" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "SELECT __text,__value FROM (\n select peername as __text, peer_hash_id as __value, count(*) as count\n from v_ls_nodes\n group by peername,peer_hash_id) d\nwhere count > 0\n ", + "hide": 0, + "includeAll": false, + "label": "BGP Peer", + "multi": false, + "name": "peer_hash", + "options": [], + "query": "SELECT __text,__value FROM (\n select peername as __text, peer_hash_id as __value, count(*) as count\n from v_ls_nodes\n group by peername,peer_hash_id) d\nwhere count > 0\n ", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "AMS10-WXBB-CRT02", + "value": "1ed1da6b-6f57-57aa-92f5-edda59049e9a" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select name as __text, hash_id as __value from ls_nodes where peer_hash_id = '$peer_hash' and not igp_router_id ~ '\\..[1-9A-F]00$'", + "hide": 0, + "includeAll": false, + "label": "ISIS Node", + "multi": false, + "name": "local_node_hash_id", + "options": [], + "query": "select name as __text, hash_id as __value from ls_nodes where peer_hash_id = '$peer_hash' and not igp_router_id ~ '\\..[1-9A-F]00$'", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 5, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "AMS10-WXBB-CRT02", + "value": "AMS10-WXBB-CRT02" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select name from ls_nodes where hash_id = '$local_node_hash_id' and peer_hash_id = '$peer_hash'", + "hide": 2, + "includeAll": false, + "multi": false, + "name": "local_node_name", + "options": [], + "query": "select name from ls_nodes where hash_id = '$local_node_hash_id' and peer_hash_id = '$peer_hash'", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "LS Links", + "uid": "MPqNG_sWz", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/LinkState-1004/ls_nodes.json b/obmp-grafana/dashboards/obmp/LinkState-1004/ls_nodes.json new file mode 100644 index 0000000..5901bbe --- /dev/null +++ b/obmp-grafana/dashboards/obmp/LinkState-1004/ls_nodes.json @@ -0,0 +1,511 @@ +{ + "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, + "id": 16, + "iteration": 1654877745288, + "links": [], + "liveNow": false, + "panels": [ + { + "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 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 0, + "y": 0 + }, + "id": 6, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "background", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "text": {}, + "textMode": "auto" + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "format": "table", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT count(*)\n FROM ls_nodes where peer_hash_id = '$peer_hash';", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Total Nodes", + "type": "stat" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 7, + "x": 3, + "y": 0 + }, + "id": 8, + "links": [], + "maxDataPoints": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "values": [ + "value" + ] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select floor(extract(epoch from max(timestamp))) as time,\n count(*) as count, \n CASE WHEN iswithdrawn THEN 'WITHDRAWN' ELSE 'ACTIVE' END as metric\nfrom ls_links\nwhere peer_hash_id = '$peer_hash'\ngroup by iswithdrawn\norder by time\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Link States", + "type": "piechart" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 7, + "x": 10, + "y": 0 + }, + "id": 9, + "links": [], + "maxDataPoints": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "right", + "values": [ + "value" + ] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "sum" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "format": "time_series", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select floor(extract(epoch from max(timestamp))) as time,\n count(*) as count, \n CASE WHEN mt_id = 2 THEN 'IPv6' ELSE 'IPv4' END as metric\nfrom ls_links \nwhere peer_hash_id = '$peer_hash'\ngroup by metric\norder by time\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Links by Type", + "type": "piechart" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "filterable": true, + "inspect": false + }, + "decimals": 0, + "displayName": "", + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + } + ] + }, + "unit": "none" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "timestamp" + }, + "properties": [ + { + "id": "displayName", + "value": "Time" + }, + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss.SSS" + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "state" + }, + "properties": [ + { + "id": "mappings", + "value": [ + { + "options": { + "ACTIVE": { + "color": "semi-dark-green", + "index": 0 + }, + "WITHDRAWN": { + "color": "semi-dark-red", + "index": 1 + } + }, + "type": "value" + } + ] + }, + { + "id": "custom.displayMode", + "value": "color-background-solid" + } + ] + } + ] + }, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 6 + }, + "id": 4, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "format": "table", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT state, nodename, routerid, protocol, timestamp, seq\n FROM v_ls_nodes\n where peer_hash_id = '$peer_hash'\n\n ", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Backbone ISIS Nodes", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + } + ], + "type": "table" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "gridPos": { + "h": 2, + "w": 24, + "x": 0, + "y": 19 + }, + "id": 2, + "options": { + "content": "\n\n", + "mode": "markdown" + }, + "pluginVersion": "8.5.4", + "type": "text" + } + ], + "schemaVersion": 36, + "style": "dark", + "tags": [ + "obmp-linkstate" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "yyz01-wxbb-crt01-lo0.webex.com", + "value": "367c22e4-57d9-2328-654b-96ea750e0267" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "SELECT __text,__value FROM (\n select peername as __text, peer_hash_id as __value, count(*) as count\n from v_ls_nodes\n group by peername,peer_hash_id) d\nwhere count > 0\n", + "hide": 0, + "includeAll": false, + "label": "BGP Peer", + "multi": false, + "name": "peer_hash", + "options": [], + "query": "SELECT __text,__value FROM (\n select peername as __text, peer_hash_id as __value, count(*) as count\n from v_ls_nodes\n group by peername,peer_hash_id) d\nwhere count > 0\n", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "LS Nodes", + "uid": "dzdSWlyWz", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/LinkState-1004/ls_prefixes.json b/obmp-grafana/dashboards/obmp/LinkState-1004/ls_prefixes.json new file mode 100644 index 0000000..d17a807 --- /dev/null +++ b/obmp-grafana/dashboards/obmp/LinkState-1004/ls_prefixes.json @@ -0,0 +1,377 @@ +{ + "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, + "id": 17, + "iteration": 1654877763755, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "decimals": 0, + "mappings": [], + "unit": "short" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 7, + "x": 0, + "y": 0 + }, + "id": 4, + "links": [], + "maxDataPoints": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "bottom", + "values": [ + "value" + ] + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "format": "time_series", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select floor(extract(epoch from max(timestamp))) as time,\n count(*) as value, CASE WHEN mt_id = 2 THEN 'IPv6' ELSE 'IPv4' END as metric\nfrom v_ls_prefixes\nwhere local_node_hash_id = '$local_node_hash_id'\n and peer_hash_id = '$peer_hash'\ngroup by mt_id\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Prefixes Total by Type", + "type": "piechart" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "filterable": true, + "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": "timestamp" + }, + "properties": [ + { + "id": "displayName", + "value": "Time" + }, + { + "id": "unit", + "value": "time: YYYY-MM-DD HH:mm:ss.SSS" + }, + { + "id": "custom.align" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "state" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "color-background-solid" + }, + { + "id": "mappings", + "value": [ + { + "options": { + "ACTIVE": { + "color": "semi-dark-green", + "index": 0 + }, + "WITHDRAWN": { + "color": "semi-dark-red", + "index": 1 + } + }, + "type": "value" + } + ] + } + ] + } + ] + }, + "gridPos": { + "h": 22, + "w": 23, + "x": 0, + "y": 7 + }, + "id": 2, + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT state, mt_id, prefix, metric, protocol, timestamp\n FROM v_ls_prefixes\n WHERE local_node_hash_id = '$local_node_hash_id'\n AND peer_hash_id = '$peer_hash'", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "$local_node_name Prefixes", + "transformations": [ + { + "id": "merge", + "options": { + "reducers": [] + } + } + ], + "type": "table" + } + ], + "schemaVersion": 36, + "style": "dark", + "tags": [ + "obmp-linkstate" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "yyz01-wxbb-crt01-lo0.webex.com", + "value": "367c22e4-57d9-2328-654b-96ea750e0267" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "SELECT __text,__value FROM (\n select peername as __text, peer_hash_id as __value, count(*) as count\n from v_ls_nodes\n group by peername,peer_hash_id) d\nwhere count > 0", + "hide": 0, + "includeAll": false, + "label": "BGP Peer", + "multi": false, + "name": "peer_hash", + "options": [], + "query": "SELECT __text,__value FROM (\n select peername as __text, peer_hash_id as __value, count(*) as count\n from v_ls_nodes\n group by peername,peer_hash_id) d\nwhere count > 0", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "BLR03-WXBB-CRT01", + "value": "4275c83a-8d03-5361-d890-0b2bf4ad1b91" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select name as __text, hash_id as __value from ls_nodes where peer_hash_id = '$peer_hash' AND not igp_router_id ~ '\\..[1-9A-F]00$'", + "hide": 0, + "includeAll": false, + "label": "ISIS Node", + "multi": false, + "name": "local_node_hash_id", + "options": [], + "query": "select name as __text, hash_id as __value from ls_nodes where peer_hash_id = '$peer_hash' AND not igp_router_id ~ '\\..[1-9A-F]00$'", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 5, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "BLR03-WXBB-CRT01", + "value": "BLR03-WXBB-CRT01" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select name from ls_nodes where hash_id = '$local_node_hash_id' and peer_hash_id = '$peer_hash'", + "hide": 2, + "includeAll": false, + "multi": false, + "name": "local_node_name", + "options": [], + "query": "select name from ls_nodes where hash_id = '$local_node_hash_id' and peer_hash_id = '$peer_hash'", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "LS Prefixes", + "uid": "iEcqtlyWk", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/LinkState-1004/ls_topo.json b/obmp-grafana/dashboards/obmp/LinkState-1004/ls_topo.json new file mode 100644 index 0000000..e3d9975 --- /dev/null +++ b/obmp-grafana/dashboards/obmp/LinkState-1004/ls_topo.json @@ -0,0 +1,216 @@ +{ + "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, + "id": 23, + "iteration": 1654877522167, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "gridPos": { + "h": 28, + "w": 23, + "x": 0, + "y": 0 + }, + "id": 2, + "targets": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select local_node_hash_id as id,\n CASE WHEN max(local_router_name) = '' THEN max(local_igp_routerid) ELSE max(local_router_name) END as title,\n max(local_igp_routerid) as detail__routerid\n from v_ls_links\n where peer_hash_id = '$peer_hash'\n and local_igp_routerid like '%.0000' and remote_igp_routerid like '%.0000'\n and igp_metric < 16000000\n and state in ($state)\n and (local_node_hash_id = '$local_node_hash' or remote_node_hash_id = '$local_node_hash')\n group by local_node_hash_id\n order by title;", + "refId": " nodes", + "select": [ + [ + { + "params": [ + "amr_rx_hbhloss_pct" + ], + "type": "column" + } + ] + ], + "table": "as_path_metrics", + "timeColumn": "start_timestamp", + "timeColumnType": "timestamp", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "select local_node_hash_id || '->' || remote_node_hash_id as id,\n local_node_hash_id as source,\n remote_node_hash_id as target,\n max(igp_metric)::int as mainstat,\n max(state) as secondarystat,\n max(remote_router_name) as detail__remote\n from v_ls_links\n where peer_hash_id = '$peer_hash'\n and local_igp_routerid like '%.0000' and remote_igp_routerid like '%.0000'\n and igp_metric < 16000000\n and state in ($state)\n and (local_node_hash_id = '$local_node_hash' or remote_node_hash_id = '$local_node_hash')\ngroup by local_node_hash_id,remote_node_hash_id;\n ", + "refId": "edges", + "select": [ + [ + { + "params": [ + "amr_rx_hbhloss_pct" + ], + "type": "column" + } + ] + ], + "table": "as_path_metrics", + "timeColumn": "start_timestamp", + "timeColumnType": "timestamp", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Topology", + "type": "nodeGraph" + } + ], + "schemaVersion": 36, + "style": "dark", + "tags": [ + "obmp-linkstate" + ], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "yyz01-wxbb-crt01-lo0.webex.com", + "value": "367c22e4-57d9-2328-654b-96ea750e0267" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "SELECT __text,__value FROM (\n select peername as __text, peer_hash_id as __value, count(*) as count\n from v_ls_nodes\n group by peername,peer_hash_id) d\nwhere count > 0", + "hide": 0, + "includeAll": false, + "label": "BGP Peer", + "multi": false, + "name": "peer_hash", + "options": [], + "query": "SELECT __text,__value FROM (\n select peername as __text, peer_hash_id as __value, count(*) as count\n from v_ls_nodes\n group by peername,peer_hash_id) d\nwhere count > 0", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + }, + { + "current": { + "selected": true, + "text": "Active", + "value": "ACTIVE" + }, + "hide": 0, + "includeAll": true, + "label": "State", + "multi": false, + "name": "state", + "options": [ + { + "selected": false, + "text": "All", + "value": "$__all" + }, + { + "selected": false, + "text": "Inactive", + "value": "WITHDRAWN" + }, + { + "selected": true, + "text": "Active", + "value": "ACTIVE" + } + ], + "query": "Inactive : WITHDRAWN, Active : ACTIVE", + "queryValue": "", + "skipUrlSync": false, + "type": "custom" + }, + { + "current": { + "selected": false, + "text": "NRT02-WXBB-CRT01", + "value": "3e96d517-e4b8-7264-1479-2814e9691f10" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select local_router_name as __text, local_node_hash_id as __value \nfrom v_ls_links\nwhere peer_hash_id = '$peer_hash'\n and local_igp_routerid like '%.0000'\n and igp_metric < 16000000\n and state in ($state)\ngroup by local_router_name,local_node_hash_id", + "hide": 0, + "includeAll": false, + "label": "Node", + "multi": false, + "name": "local_node_hash", + "options": [], + "query": "select local_router_name as __text, local_node_hash_id as __value \nfrom v_ls_links\nwhere peer_hash_id = '$peer_hash'\n and local_igp_routerid like '%.0000'\n and igp_metric < 16000000\n and state in ($state)\ngroup by local_router_name,local_node_hash_id", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "LinkState Topology", + "uid": "SNOLrQlnz", + "version": 3, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/Tops-1003/top_l3vpn_prefixes.json b/obmp-grafana/dashboards/obmp/Tops-1003/top_l3vpn_prefixes.json new file mode 100644 index 0000000..f5f008a --- /dev/null +++ b/obmp-grafana/dashboards/obmp/Tops-1003/top_l3vpn_prefixes.json @@ -0,0 +1,1048 @@ +{ + "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, + "id": 11, + "iteration": 1654876675775, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "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": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 8, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "right" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.0.5", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n $__timeGroup(interval_time, $__interval) as time,\n sum(updates) as updates,sum(withdraws) as withdraws\nFROM stats_l3vpn_chg_bypeer s\n JOIN v_peers p ON (s.peer_hash_id = p.peer_hash_id)\nWHERE $__timeFilter(interval_time)\n AND s.peer_hash_id in ($peer_hash)\nGROUP BY time\nORDER BY time ASC\n\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Advertisements & Withdrawals", + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "Count of Updates", + "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": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 4, + "interval": "15m", + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "right" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.0.5", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n $__timeGroup(interval_time, $__interval) as time,\n sum(updates),\n p.PeerName as metric\n FROM stats_l3vpn_chg_bypeer l\n JOIN v_peers p ON (p.peer_hash_id = l.peer_hash_id)\n WHERE $__timeFilter(interval_time)\n AND l.peer_hash_id in ($peer_hash)\n GROUP BY peername,time\n order by time asc\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Updates by Peer", + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "Count of Updates", + "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": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 5, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "right" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.0.5", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n $__timeGroup(interval_time, $__interval) as time,\n sum(withdraws),\n p.PeerName as metric\n FROM stats_l3vpn_chg_bypeer l\n JOIN v_peers p ON (p.peer_hash_id = l.peer_hash_id)\n WHERE $__timeFilter(interval_time)\n AND l.peer_hash_id in ($peer_hash)\n group by peername,time\n order by time", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Withdraws by Peer", + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 20 + }, + { + "color": "red", + "value": 60 + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Updates" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "gradient-gauge" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "asn" + }, + "properties": [ + { + "id": "custom.align", + "value": "center" + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Prefix History", + "url": "/grafana/d/score-by-origin/clients-score-by-origin-asn?orgId=1&var-input=${__value.text}&${__url_time_range}" + } + ] + }, + { + "id": "unit", + "value": "none" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "asn" + }, + "properties": [ + { + "id": "custom.width", + "value": 119 + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 13 + }, + "id": 10, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": " SELECT\n rd,\n sum(updates) as \"Updates\"\n FROM stats_l3vpn_chg_byrd l\n WHERE $__timeFilter(interval_time)\n AND peer_hash_id in ($peer_hash)\n GROUP BY rd\n order by \"Updates\" desc\n LIMIT 20", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Top Updates by RD", + "type": "table" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 20 + }, + { + "color": "red", + "value": 60 + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Withdraws" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "gradient-gauge" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "rd" + }, + "properties": [ + { + "id": "custom.align", + "value": "left" + }, + { + "id": "unit", + "value": "none" + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 13 + }, + "id": 11, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": " SELECT\n rd,\n sum(withdraws) as \"Withdraws\"\n FROM stats_l3vpn_chg_byrd l\n WHERE $__timeFilter(interval_time)\n AND peer_hash_id in ($peer_hash)\n GROUP BY rd\n order by \"Withdraws\" desc\n LIMIT 20", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Top Withdraws by RD", + "type": "table" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 20 + }, + { + "color": "red", + "value": 60 + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Updates" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "gradient-gauge" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "prefix" + }, + "properties": [ + { + "id": "custom.align", + "value": "left" + }, + { + "id": "custom.width", + "value": 202 + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Prefix History", + "url": "/d/l3vpn-prefix-hist/prefix-history-by-prefix-l3vpn?orgId=1&var-input=${__value.text}&${__url_time_range}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "rd" + }, + "properties": [ + { + "id": "custom.width", + "value": 139 + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 2, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n rd,prefix,\n sum(updates) as \"Updates\"\n FROM stats_l3vpn_chg_byprefix l\n WHERE $__timeFilter(interval_time)\n AND peer_hash_id in ($peer_hash)\n GROUP BY rd,prefix\n order by \"Updates\" desc\nLIMIT 60\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Top Prefix Updates", + "type": "table" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 20 + }, + { + "color": "red", + "value": 60 + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Withdraws" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "gradient-gauge" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "prefix" + }, + "properties": [ + { + "id": "custom.align", + "value": "left" + }, + { + "id": "custom.width", + "value": 202 + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Prefix History", + "url": "/d/l3vpn-prefix-hist/prefix-history-by-prefix-l3vpn?orgId=1&var-input=${__value.text}&${__url_time_range}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "rd" + }, + "properties": [ + { + "id": "custom.width", + "value": 139 + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 12, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n rd,prefix,\n sum(withdraws) as \"Withdraws\"\n FROM stats_l3vpn_chg_byprefix l\n WHERE $__timeFilter(interval_time)\n AND peer_hash_id in ($peer_hash)\n GROUP BY rd,prefix\n order by \"Withdraws\" desc\nLIMIT 60\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Top Prefix Withdraws", + "type": "table" + } + ], + "refresh": false, + "schemaVersion": 36, + "style": "dark", + "tags": [ + "obmp-tops" + ], + "templating": { + "list": [ + { + "allValue": "", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select routername as __text, router_hash_id as __value from v_peers where router_state = 'up' and recvcapabilities like '% afi=1 safi=128 %';", + "hide": 0, + "includeAll": true, + "label": "Filter by Router", + "multi": true, + "name": "router_hash", + "options": [], + "query": "select routername as __text, router_hash_id as __value from v_peers where router_state = 'up' and recvcapabilities like '% afi=1 safi=128 %';", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash) and recvcapabilities like '% afi=1 safi=128 %';", + "hide": 0, + "includeAll": true, + "label": "Peer", + "multi": true, + "name": "peer_hash", + "options": [], + "query": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash) and recvcapabilities like '% afi=1 safi=128 %';", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-24h", + "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": "utc", + "title": "Top L3VPN by Prefixes", + "uid": "0nEe0IBnk", + "version": 1, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/dashboards/obmp/Tops-1003/top_prefixes.json b/obmp-grafana/dashboards/obmp/Tops-1003/top_prefixes.json new file mode 100644 index 0000000..b267d2b --- /dev/null +++ b/obmp-grafana/dashboards/obmp/Tops-1003/top_prefixes.json @@ -0,0 +1,1367 @@ +{ + "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, + "id": 12, + "iteration": 1654876366831, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "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": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "decimals": 0, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 8, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "right" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.0.5", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n $__timeGroup(interval_time, $__interval) as time,\n sum(updates) as updates,sum(withdraws) as withdraws\nFROM stats_chg_bypeer s\n JOIN v_peers p ON (s.peer_hash_id = p.peer_hash_id)\nWHERE $__timeFilter(interval_time)\n AND s.peer_hash_id in ($peer_hash)\nGROUP BY time\nORDER BY time ASC\n\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Advertisements & Withdrawals", + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "Count of Updates", + "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": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 6 + }, + "id": 13, + "interval": "15m", + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "right" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.0.5", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n $__timeGroup(interval_time, $__interval) as time,\n sum(updates),\n p.routername as metric\n FROM stats_chg_bypeer l\n JOIN v_peers p ON (p.peer_hash_id = l.peer_hash_id)\n WHERE $__timeFilter(interval_time)\n AND l.peer_hash_id in ($peer_hash)\n GROUP BY routername,time\n order by time asc\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Updates by Router", + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "Count of Updates", + "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": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 6 + }, + "id": 5, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "right" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.0.5", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n $__timeGroup(interval_time, $__interval) as time,\n sum(withdraws),\n p.routername as metric\n FROM stats_chg_bypeer l\n JOIN v_peers p ON (p.peer_hash_id = l.peer_hash_id)\n WHERE $__timeFilter(interval_time)\n AND l.peer_hash_id in ($peer_hash)\n group by routername,time\n order by time", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Withdraws by Router", + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "Count of Updates", + "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": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 13 + }, + "id": 4, + "interval": "15m", + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "right" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.0.5", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n $__timeGroup(interval_time, $__interval) as time,\n sum(updates),\n p.PeerName as metric\n FROM stats_chg_bypeer l\n JOIN v_peers p ON (p.peer_hash_id = l.peer_hash_id)\n WHERE $__timeFilter(interval_time)\n AND l.peer_hash_id in ($peer_hash)\n GROUP BY peername,time\n order by time asc\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Updates by Peer", + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisLabel": "Count of Updates", + "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": "never", + "spanNulls": true, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "locale" + }, + "overrides": [] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 13 + }, + "id": 14, + "links": [], + "options": { + "legend": { + "calcs": [ + "mean", + "max" + ], + "displayMode": "table", + "placement": "right" + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "8.0.5", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "time_series", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT\n $__timeGroup(interval_time, $__interval) as time,\n sum(withdraws),\n p.PeerName as metric\n FROM stats_chg_bypeer l\n JOIN v_peers p ON (p.peer_hash_id = l.peer_hash_id)\n WHERE $__timeFilter(interval_time)\n AND l.peer_hash_id in ($peer_hash)\n group by peername,time\n order by time", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Withdraws by Peer", + "type": "timeseries" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 20 + }, + { + "color": "red", + "value": 60 + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Updates" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "gradient-gauge" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "asn" + }, + "properties": [ + { + "id": "custom.align", + "value": "center" + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "ASN Info", + "url": "/d/asnview-agg/asn-view?orgId=1&var-asn_num=${__value.text}&${__url_time_range}" + } + ] + }, + { + "id": "unit", + "value": "none" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "asn" + }, + "properties": [ + { + "id": "custom.width", + "value": 119 + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 20 + }, + "id": 10, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT as_name as \"AS Name\",d.* from (\n SELECT\n origin_as as asn,\n sum(updates) as \"Updates\"\n FROM stats_chg_byasn l\n WHERE $__timeFilter(interval_time)\n AND peer_hash_id in ($peer_hash)\n GROUP BY asn\n order by \"Updates\" desc\n LIMIT 20\n) d\nLEFT JOIN info_asn i ON (i.asn = d.asn)\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Top Updates by ASN", + "type": "table" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "#EAB839", + "value": 20 + }, + { + "color": "red", + "value": 60 + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Withdraws" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "gradient-gauge" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "asn" + }, + "properties": [ + { + "id": "custom.align", + "value": "center" + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "ASN Info", + "url": "/d/asnview-agg/asn-view?orgId=1&var-asn_num=${__value.text}&${__url_time_range}" + } + ] + }, + { + "id": "unit", + "value": "none" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "asn" + }, + "properties": [ + { + "id": "custom.width", + "value": 119 + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 20 + }, + "id": 11, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.4", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT as_name,d.* from (\n SELECT\n origin_as as asn,\n sum(withdraws) as \"Withdraws\"\n FROM stats_chg_byasn l\n WHERE $__timeFilter(interval_time)\n AND peer_hash_id in ($peer_hash)\n GROUP BY asn\n order by \"Withdraws\" desc\n LIMIT 20\n) d\nLEFT JOIN info_asn i ON (i.asn = d.asn)\n", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Top Withdraws by ASN", + "type": "table" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green" + }, + { + "color": "#EAB839", + "value": 20 + }, + { + "color": "red", + "value": 60 + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Updates" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "gradient-gauge" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "prefix" + }, + "properties": [ + { + "id": "custom.align", + "value": "center" + }, + { + "id": "custom.width", + "value": 258 + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Prefix History", + "url": "/d/prefix-hist/prefix-history-by-prefix?orgId=1&var-router_hash=All&var-peer_hash=All&var-limit=1000&var-input=${__value.text}&${__url_time_range}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "origin_as" + }, + "properties": [ + { + "id": "unit", + "value": "none" + }, + { + "id": "custom.align", + "value": "center" + }, + { + "id": "custom.width", + "value": 136 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "AS Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 136 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Desc" + }, + "properties": [ + { + "id": "custom.width", + "value": 178 + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 0, + "y": 27 + }, + "id": 2, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.2", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT as_name as \"AS Name\", irr_descr as \"Desc\",r.recv_origin_as as origin_as,d.* FROM (\nSELECT\n prefix,\n sum(updates) as \"Updates\"\n FROM stats_chg_byprefix l\n WHERE $__timeFilter(interval_time)\n AND peer_hash_id in ($peer_hash)\n GROUP BY prefix\n order by \"Updates\" desc\nLIMIT 60\n) d\nJOIN global_ip_rib r ON (r.prefix = d.prefix)\nLEFT JOIN info_asn i ON (i.asn = r.recv_origin_as)", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Top Prefix Updates", + "type": "table" + }, + { + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "displayMode": "auto", + "inspect": false + }, + "links": [], + "mappings": [], + "thresholds": { + "mode": "percentage", + "steps": [ + { + "color": "green" + }, + { + "color": "#EAB839", + "value": 20 + }, + { + "color": "red", + "value": 60 + } + ] + }, + "unit": "locale" + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "Withdraws" + }, + "properties": [ + { + "id": "custom.displayMode", + "value": "gradient-gauge" + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "prefix" + }, + "properties": [ + { + "id": "custom.align", + "value": "center" + }, + { + "id": "custom.width", + "value": 258 + }, + { + "id": "links", + "value": [ + { + "targetBlank": true, + "title": "Prefix History", + "url": "/d/prefix-hist/prefix-history-by-prefix?orgId=1&var-router_hash=All&var-peer_hash=All&var-limit=1000&var-input=${__value.text}&${__url_time_range}" + } + ] + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "origin_as" + }, + "properties": [ + { + "id": "unit", + "value": "none" + }, + { + "id": "custom.align", + "value": "center" + }, + { + "id": "custom.width", + "value": 136 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "AS Name" + }, + "properties": [ + { + "id": "custom.width", + "value": 136 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "Desc" + }, + "properties": [ + { + "id": "custom.width", + "value": 178 + } + ] + } + ] + }, + "gridPos": { + "h": 7, + "w": 12, + "x": 12, + "y": 27 + }, + "id": 12, + "links": [], + "options": { + "footer": { + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "8.5.2", + "targets": [ + { + "alias": "", + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "format": "table", + "group": [], + "hide": false, + "metricColumn": "none", + "rawQuery": true, + "rawSql": "SELECT as_name as \"AS Name\", irr_descr as \"Desc\",r.recv_origin_as as origin_as,d.* FROM (\nSELECT\n prefix,\n sum(withdraws) as \"Withdraws\"\n FROM stats_chg_byprefix l\n WHERE $__timeFilter(interval_time)\n AND peer_hash_id in ($peer_hash)\n GROUP BY prefix\n order by \"Withdraws\" desc\nLIMIT 60\n) d\nJOIN global_ip_rib r ON (r.prefix = d.prefix)\n--LEFT JOIN info_route ir ON (ir.prefix = d.prefix)\nLEFT JOIN info_asn i ON (i.asn = r.recv_origin_as)", + "refId": "A", + "select": [ + [ + { + "params": [ + "value" + ], + "type": "column" + } + ] + ], + "timeColumn": "time", + "where": [ + { + "name": "$__timeFilter", + "params": [], + "type": "macro" + } + ] + } + ], + "title": "Top Prefix Withdraws", + "type": "table" + } + ], + "refresh": false, + "schemaVersion": 36, + "style": "dark", + "tags": [ + "obmp-tops" + ], + "templating": { + "list": [ + { + "allValue": "", + "current": { + "selected": true, + "text": [ + "All" + ], + "value": [ + "$__all" + ] + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select name as __text, hash_id as __value from routers where length(name) > 0", + "hide": 0, + "includeAll": true, + "label": "Filter by Router", + "multi": true, + "name": "router_hash", + "options": [], + "query": "select name as __text, hash_id as __value from routers where length(name) > 0", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "postgres", + "uid": "obmp_postgres" + }, + "definition": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash)", + "hide": 0, + "includeAll": true, + "label": "Peer", + "multi": true, + "name": "peer_hash", + "options": [], + "query": "select peername as __text, peer_hash_id as __value from v_peers where router_hash_id in ($router_hash)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 1, + "type": "query" + } + ] + }, + "time": { + "from": "now-24h", + "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": "utc", + "title": "Top by Prefixes", + "uid": "e_cJJzxnk", + "version": 4, + "weekStart": "" +} \ No newline at end of file diff --git a/obmp-grafana/provisioning/dashboards/openbmp-dashboards.yml b/obmp-grafana/provisioning/dashboards/openbmp-dashboards.yml new file mode 100644 index 0000000..5a58345 --- /dev/null +++ b/obmp-grafana/provisioning/dashboards/openbmp-dashboards.yml @@ -0,0 +1,125 @@ +apiVersion: 1 + +providers: + # an unique provider name. Required + - name: 'OpenBMP' + # Org id. Default to 1 + orgId: 1 + # name of the dashboard folder. + folder: '' + # folder UID. will be automatically generated if not specified + folderUid: '' + # provider type. Default to 'file' + type: file + # disable dashboard deletion + disableDeletion: false + # how often Grafana will scan for changed dashboards + updateIntervalSeconds: 30 + # allow updating provisioned dashboards from the UI + allowUiUpdates: true + options: + # path to dashboard files on disk. Required when using the 'file' type + path: /var/lib/grafana/dashboards/General + # use folder names from filesystem to create folders in Grafana + foldersFromFilesStructure: false + # an unique provider name. Required + - name: 'OpenBMP-Base' + # Org id. Default to 1 + orgId: 1 + # name of the dashboard folder. + folder: 'OBMP-Base' + # folder UID. will be automatically generated if not specified + folderUid: '1001' + # provider type. Default to 'file' + type: file + # disable dashboard deletion + disableDeletion: false + # how often Grafana will scan for changed dashboards + updateIntervalSeconds: 30 + # allow updating provisioned dashboards from the UI + allowUiUpdates: true + options: + # path to dashboard files on disk. Required when using the 'file' type + path: /var/lib/grafana/dashboards/obmp/Base-1001 + # use folder names from filesystem to create folders in Grafana + foldersFromFilesStructure: false + - name: 'OpenBMP-History' + # Org id. Default to 1 + orgId: 1 + # name of the dashboard folder. + folder: 'OBMP-History' + # folder UID. will be automatically generated if not specified + folderUid: '1002' + # provider type. Default to 'file' + type: file + # disable dashboard deletion + disableDeletion: false + # how often Grafana will scan for changed dashboards + updateIntervalSeconds: 30 + # allow updating provisioned dashboards from the UI + allowUiUpdates: true + options: + # path to dashboard files on disk. Required when using the 'file' type + path: /var/lib/grafana/dashboards/obmp/History-1002 + # use folder names from filesystem to create folders in Grafana + foldersFromFilesStructure: false + - name: 'OpenBMP-Tops' + # Org id. Default to 1 + orgId: 1 + # name of the dashboard folder. + folder: 'OBMP-Tops' + # folder UID. will be automatically generated if not specified + folderUid: '1003' + # provider type. Default to 'file' + type: file + # disable dashboard deletion + disableDeletion: false + # how often Grafana will scan for changed dashboards + updateIntervalSeconds: 30 + # allow updating provisioned dashboards from the UI + allowUiUpdates: true + options: + # path to dashboard files on disk. Required when using the 'file' type + path: /var/lib/grafana/dashboards/obmp/Tops-1003 + # use folder names from filesystem to create folders in Grafana + foldersFromFilesStructure: false + - name: 'OpenBMP-LinkState' + # Org id. Default to 1 + orgId: 1 + # name of the dashboard folder. + folder: 'OBMP-LinkState' + # folder UID. will be automatically generated if not specified + folderUid: '1004' + # provider type. Default to 'file' + type: file + # disable dashboard deletion + disableDeletion: false + # how often Grafana will scan for changed dashboards + updateIntervalSeconds: 30 + # allow updating provisioned dashboards from the UI + allowUiUpdates: true + options: + # path to dashboard files on disk. Required when using the 'file' type + path: /var/lib/grafana/dashboards/obmp/LinkState-1004 + # use folder names from filesystem to create folders in Grafana + foldersFromFilesStructure: false + - name: 'OpenBMP-L3VPN' + # Org id. Default to 1 + orgId: 1 + # name of the dashboard folder. + folder: 'OBMP-L3VPN' + # folder UID. will be automatically generated if not specified + folderUid: '1005' + # provider type. Default to 'file' + type: file + # disable dashboard deletion + disableDeletion: false + # how often Grafana will scan for changed dashboards + updateIntervalSeconds: 30 + # allow updating provisioned dashboards from the UI + allowUiUpdates: true + options: + # path to dashboard files on disk. Required when using the 'file' type + path: /var/lib/grafana/dashboards/obmp/L3VPN-1005 + # use folder names from filesystem to create folders in Grafana + foldersFromFilesStructure: false \ No newline at end of file diff --git a/obmp-grafana/provisioning/datasources/openbmp-ds.yml b/obmp-grafana/provisioning/datasources/openbmp-ds.yml new file mode 100644 index 0000000..be37a7b --- /dev/null +++ b/obmp-grafana/provisioning/datasources/openbmp-ds.yml @@ -0,0 +1,48 @@ +# config file version +apiVersion: 1 + +# list of datasources that should be deleted from the database +#deleteDatasources: +# - name: PostgreSQL +# orgId: 1 + +# list of datasources to insert/update depending +# whats available in the database +datasources: + # name of the datasource. Required + - name: PostgreSQL + uid: obmp_postgres + # datasource type. Required + type: postgres + # access mode. direct or proxy. Required + access: direct + # org id. will default to orgId 1 if not specified + orgId: 1 + # url + url: obmp-psql:5432 + # database user, if used + user: openbmp + # database name, if used + database: openbmp + # mark as default datasource. Max one per org + isDefault: true + + secureJsonData: + password: openbmp + + # fields that will be converted to json and stored in json_data + jsonData: + tlsAuth: false + tlsAuthWithCACert: false + postgresVersion: 1200 + sslmode: "require" + timescaledb: true + maxOpenConns: 6 + maxIdleConns: 1 + connMaxLifetime: 3600 + + # json object of data that will be encrypted. + #secureJsonData: + version: 1 + # allow users to edit datasources from the UI. + editable: true \ No newline at end of file