BMP port 1790 everywhere: parameterize the published collector port (finding 12)
Decision landed: routers target 1790 (IANA BMP port); the collector keeps
listening on 5000 in-container. One .env variable now drives every hop:
- compose publishes ${ROUTER_FACING_PORT:-1790}:5000 (was hardcoded 5000:5000)
- gobgpd.conf.tmpl (+ evpn) gains __BMP_PORT__; setup.sh renders it from
ROUTER_FACING_PORT -- gobgp is host-networked, so it must chase the
published port or the full-table feeder silently breaks
- deploy.sh + scripts/wsl-portproxy.ps1: the WSL side now publishes the
router-facing port itself, so the portproxy forwards the same port
end-to-end instead of down-mapping to 5000
- cml/proxmox_bmp_config.py reads ROUTER_FACING_IP/PORT from .env (HOST_IP
fallback for pre-key .envs); xrd-node-definition.yaml baked port -> 1790
- .env.example documents ROUTER_FACING_IP/PORT; docs updated, finding 12
closed on the repo side (routers still on 5000 need a config re-apply)
Verified live: collector republished 0.0.0.0:1790->5000, gobgp BMP session
Up to HOST_IP:1790 with the RIB dump flowing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
0c91cad55f
commit
b480615ca2
@ -12,6 +12,15 @@ OBMP_DATA_ROOT=/var/openbmp
|
|||||||
# (Kafka external listener, BMP source, ExaBGP peering).
|
# (Kafka external listener, BMP source, ExaBGP peering).
|
||||||
HOST_IP=changeme
|
HOST_IP=changeme
|
||||||
|
|
||||||
|
# Router-facing BMP target -- what routers' `bmp server` config points at.
|
||||||
|
# On WSL this is the WINDOWS LAN IP (portproxy forwards into WSL); on native
|
||||||
|
# Linux it is normally the host IP. Port 1790 is the IANA BMP port; it maps
|
||||||
|
# to the collector's in-container 5000 (compose publishes
|
||||||
|
# ROUTER_FACING_PORT:5000, and gobgp/setup.sh render the same port).
|
||||||
|
# deploy.sh reconciles both values per host.
|
||||||
|
ROUTER_FACING_IP=changeme
|
||||||
|
ROUTER_FACING_PORT=1790
|
||||||
|
|
||||||
# Auth mode:
|
# Auth mode:
|
||||||
# local — Grafana built-in login (admin / openbmp). Lab default.
|
# local — Grafana built-in login (admin / openbmp). Lab default.
|
||||||
# OBMP_DOMAIN / OBMP_COOKIE_DOMAIN below can stay blank.
|
# OBMP_DOMAIN / OBMP_COOKIE_DOMAIN below can stay blank.
|
||||||
|
|||||||
@ -41,9 +41,13 @@ def _env_default(key, default, dotenv=".env"):
|
|||||||
|
|
||||||
|
|
||||||
# --- BMP collector ---------------------------------------------------------
|
# --- BMP collector ---------------------------------------------------------
|
||||||
# Resolved from $HOST_IP or the HOST_IP= line in repo-root .env.
|
# Routers must target the ROUTER-FACING address, not HOST_IP: on a WSL
|
||||||
COLLECTOR_HOST = _env_default("HOST_IP", "10.40.40.202")
|
# deployment HOST_IP is the unreachable WSL NAT address (portability finding
|
||||||
COLLECTOR_PORT = "5000"
|
# 4/12). ROUTER_FACING_* are written to .env by deploy.sh; HOST_IP remains
|
||||||
|
# the fallback for old native-lab .envs that predate those keys.
|
||||||
|
COLLECTOR_HOST = _env_default("ROUTER_FACING_IP",
|
||||||
|
_env_default("HOST_IP", "10.40.40.202"))
|
||||||
|
COLLECTOR_PORT = _env_default("ROUTER_FACING_PORT", "1790")
|
||||||
|
|
||||||
# `bmp server 1` block — flat formal form, identical to the ESXi lab.
|
# `bmp server 1` block — flat formal form, identical to the ESXi lab.
|
||||||
# Each line is self-contained and applied at the (config)# prompt; a bare
|
# Each line is self-contained and applied at the (config)# prompt; a bare
|
||||||
|
|||||||
@ -129,7 +129,7 @@ configuration:
|
|||||||
!
|
!
|
||||||
!
|
!
|
||||||
bmp server 1
|
bmp server 1
|
||||||
host 10.40.40.202 port 5000
|
host 10.40.40.202 port 1790
|
||||||
description OpenBMP
|
description OpenBMP
|
||||||
update-source Gi0/0/0/0
|
update-source Gi0/0/0/0
|
||||||
flapping-delay 60
|
flapping-delay 60
|
||||||
|
|||||||
@ -455,8 +455,8 @@ fi
|
|||||||
# The router-facing/external BMP port defaults to 1790 (the IANA-registered BMP
|
# The router-facing/external BMP port defaults to 1790 (the IANA-registered BMP
|
||||||
# port) rather than the collector's internal 5000 - avoids the crowded 5000 and
|
# port) rather than the collector's internal 5000 - avoids the crowded 5000 and
|
||||||
# is self-documenting. The collector still listens on 5000 INSIDE the container;
|
# is self-documenting. The collector still listens on 5000 INSIDE the container;
|
||||||
# the external 1790 maps down to it (compose 1790:5000 on native, portproxy
|
# compose publishes ${ROUTER_FACING_PORT:-1790}:5000 everywhere, so on WSL the
|
||||||
# listenport=1790 connectport=5000 on WSL).
|
# portproxy forwards listenport=ROUTER_PORT to the SAME port on the WSL side.
|
||||||
BMP_STD_PORT=1790
|
BMP_STD_PORT=1790
|
||||||
default_router_port="${ARG_ROUTER_PORT:-$BMP_STD_PORT}"
|
default_router_port="${ARG_ROUTER_PORT:-$BMP_STD_PORT}"
|
||||||
if [ -n "$ARG_ROUTER_IP" ]; then ROUTER_IP="$ARG_ROUTER_IP"; else
|
if [ -n "$ARG_ROUTER_IP" ]; then ROUTER_IP="$ARG_ROUTER_IP"; else
|
||||||
@ -738,7 +738,7 @@ if [ "$HOSTTYPE" = "wsl" ] && [ "$DTYPE" != "central-store" ]; then
|
|||||||
|
|
||||||
or add the rules by hand:
|
or add the rules by hand:
|
||||||
|
|
||||||
netsh interface portproxy add v4tov4 listenport=${ROUTER_PORT} listenaddress=0.0.0.0 connectport=${COLLECTOR_PORT} connectaddress=${HOST_IP}
|
netsh interface portproxy add v4tov4 listenport=${ROUTER_PORT} listenaddress=0.0.0.0 connectport=${ROUTER_PORT} connectaddress=${HOST_IP}
|
||||||
netsh interface portproxy add v4tov4 listenport=9092 listenaddress=0.0.0.0 connectport=9092 connectaddress=${HOST_IP}
|
netsh interface portproxy add v4tov4 listenport=9092 listenaddress=0.0.0.0 connectport=9092 connectaddress=${HOST_IP}
|
||||||
New-NetFirewallRule -DisplayName "OpenBMP ${ROUTER_PORT}" -Direction Inbound -LocalPort ${ROUTER_PORT} -Protocol TCP -Action Allow
|
New-NetFirewallRule -DisplayName "OpenBMP ${ROUTER_PORT}" -Direction Inbound -LocalPort ${ROUTER_PORT} -Protocol TCP -Action Allow
|
||||||
|
|
||||||
|
|||||||
@ -194,7 +194,11 @@ services:
|
|||||||
- net.ipv4.tcp_keepalive_probes=5
|
- net.ipv4.tcp_keepalive_probes=5
|
||||||
- net.ipv4.tcp_keepalive_time=180
|
- net.ipv4.tcp_keepalive_time=180
|
||||||
ports:
|
ports:
|
||||||
- "5000:5000"
|
# Router-facing BMP port (default 1790, the IANA BMP port) maps down to
|
||||||
|
# the collector's fixed in-container 5000. Kept in sync with .env
|
||||||
|
# ROUTER_FACING_PORT by deploy.sh; gobgp's BMP export targets the same
|
||||||
|
# published port (setup.sh renders it into gobgpd.conf).
|
||||||
|
- "${ROUTER_FACING_PORT:-1790}:5000"
|
||||||
volumes:
|
volumes:
|
||||||
- ${OBMP_DATA_ROOT}/config:/config
|
- ${OBMP_DATA_ROOT}/config:/config
|
||||||
environment:
|
environment:
|
||||||
@ -480,7 +484,7 @@ services:
|
|||||||
# Host networking: the daemon uses the host's real IPv4 + IPv6 stack, so
|
# Host networking: the daemon uses the host's real IPv4 + IPv6 stack, so
|
||||||
# both the v4 and v6 eBGP sessions to AS57355 source from the host's
|
# both the v4 and v6 eBGP sessions to AS57355 source from the host's
|
||||||
# public addresses (no Docker IPv6/NAT plumbing). BMP still reaches the
|
# public addresses (no Docker IPv6/NAT plumbing). BMP still reaches the
|
||||||
# collector on $HOST_IP:5000 (its published port).
|
# collector on $HOST_IP:$ROUTER_FACING_PORT (its published port).
|
||||||
network_mode: host
|
network_mode: host
|
||||||
depends_on:
|
depends_on:
|
||||||
- collector
|
- collector
|
||||||
|
|||||||
@ -28,7 +28,7 @@ This is a **BGP Monitoring Platform (BMP) lab stack** deployed via Docker Compos
|
|||||||
|
|
||||||
**What it does:**
|
**What it does:**
|
||||||
|
|
||||||
- Receives BMP (BGP Monitoring Protocol, RFC 7854) telemetry from routers on TCP port 5000
|
- Receives BMP (BGP Monitoring Protocol, RFC 7854) telemetry from routers on the router-facing port (default 1790, mapped to the collector's internal 5000)
|
||||||
- Streams BMP data through Kafka into a TimescaleDB/PostgreSQL database
|
- Streams BMP data through Kafka into a TimescaleDB/PostgreSQL database
|
||||||
- Provides **30 Grafana dashboards** (17 operational + 6 learning + 4 advanced analytics + 3 streaming telemetry) for real-time and historical BGP analysis
|
- Provides **30 Grafana dashboards** (17 operational + 6 learning + 4 advanced analytics + 3 streaming telemetry) 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
|
- 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
|
||||||
@ -119,7 +119,7 @@ Traffic Generator (Phase 4):
|
|||||||
|
|
||||||
- Docker Engine (20.10+) and Docker Compose v2
|
- Docker Engine (20.10+) and Docker Compose v2
|
||||||
- Host IP `10.40.40.202` reachable from the CML management network
|
- 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 routers with BMP configured pointing to the collector's router-facing address (see docs/router-bmp-config.md)
|
||||||
- CML CORE routers configured with ExaBGP as eBGP neighbor (see Section 5)
|
- CML CORE routers configured with ExaBGP as eBGP neighbor (see Section 5)
|
||||||
- `OBMP_DATA_ROOT` directory created (default: `/var/openbmp`)
|
- `OBMP_DATA_ROOT` directory created (default: `/var/openbmp`)
|
||||||
|
|
||||||
|
|||||||
@ -90,10 +90,14 @@ telegraf >= 1.30, which negotiates the API version (telegraf/Dockerfile now
|
|||||||
pins 1.33). Watch for the same failure in any other tooling that talks to the
|
pins 1.33). Watch for the same failure in any other tooling that talks to the
|
||||||
daemon with an old vendored client.
|
daemon with an old vendored client.
|
||||||
|
|
||||||
## 12. OPEN: router-side automation still targets the old lab's values
|
## 12. Router-side automation targeted the old lab's values
|
||||||
`cml/proxmox_bmp_config.py` sends routers at `HOST_IP` port `5000`, and
|
`cml/proxmox_bmp_config.py` sent routers at `HOST_IP` port `5000`, and
|
||||||
`cml/xrd-node-definition.yaml` bakes in `10.40.40.202:5000` — both correct on
|
`cml/xrd-node-definition.yaml` baked in `10.40.40.202:5000` — both correct on
|
||||||
the old native-Linux dev lab, wrong on a WSL host (finding 4: routers must
|
the old native-Linux dev lab, wrong on a WSL host (finding 4: routers must
|
||||||
target the router-facing address, and the port default is now 1790). Fold
|
target the router-facing address). Resolved 2026-07: the router-facing port
|
||||||
`ROUTER_FACING_IP`/`ROUTER_FACING_PORT` from `.env` into that tooling when
|
is **1790** everywhere; compose publishes `${ROUTER_FACING_PORT:-1790}:5000`,
|
||||||
the 5000-vs-1790 decision lands. See docs/router-bmp-config.md.
|
setup.sh renders the same port into gobgp's BMP export (gobgp is
|
||||||
|
host-networked and must hit the *published* port), and the cml tooling reads
|
||||||
|
`ROUTER_FACING_IP`/`ROUTER_FACING_PORT` from `.env`. Remaining hands-on step:
|
||||||
|
re-apply the config to routers still pointed at 5000. See
|
||||||
|
docs/router-bmp-config.md.
|
||||||
|
|||||||
@ -14,18 +14,19 @@ deploy.sh records the correct target in `.env` as
|
|||||||
|
|
||||||
| Stack host | Routers target | Path to the collector |
|
| Stack host | Routers target | Path to the collector |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| Native Linux | `ROUTER_FACING_IP` (= host IP) : `ROUTER_FACING_PORT` | compose port map -> collector :5000 |
|
| Native Linux | `ROUTER_FACING_IP` (= host IP) : `ROUTER_FACING_PORT` | compose publishes `ROUTER_FACING_PORT:5000` |
|
||||||
| WSL2 | Windows LAN IP : `ROUTER_FACING_PORT` | `netsh portproxy` (Windows) -> WSL `HOST_IP` -> collector :5000 |
|
| WSL2 | Windows LAN IP : `ROUTER_FACING_PORT` | `netsh portproxy` (Windows, same port) -> WSL -> compose `ROUTER_FACING_PORT:5000` |
|
||||||
|
|
||||||
On WSL the Windows-side forwarding must exist first — run
|
On WSL the Windows-side forwarding must exist first — run
|
||||||
`scripts/wsl-portproxy.ps1` in an **elevated** PowerShell, and re-run it after
|
`scripts/wsl-portproxy.ps1` in an **elevated** PowerShell, and re-run it after
|
||||||
every WSL restart (the WSL address changes).
|
every WSL restart (the WSL address changes).
|
||||||
|
|
||||||
The router-facing port defaults to **1790** (the IANA-registered BMP port);
|
The router-facing port is **1790** (the IANA-registered BMP port; decided
|
||||||
the collector always listens on **5000 inside the container**. The lab
|
2026-07 — the lab's historical 5000 is being retired). The collector always
|
||||||
routers were historically configured for 5000 — until they are reconfigured,
|
listens on **5000 inside the container**; compose maps
|
||||||
deploy with `--router-port 5000` (see the open decision in
|
`${ROUTER_FACING_PORT:-1790}` down to it, and setup.sh renders the same port
|
||||||
docs/PORTABILITY-FINDINGS.md, finding 12).
|
into gobgp's BMP export. Routers still configured for 5000 must be updated
|
||||||
|
(`cml/proxmox_bmp_config.py` applies the current values from `.env`).
|
||||||
|
|
||||||
## `bmp server` block
|
## `bmp server` block
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
[[bmp-servers]]
|
[[bmp-servers]]
|
||||||
[bmp-servers.config]
|
[bmp-servers.config]
|
||||||
address = "__HOST_IP__"
|
address = "__HOST_IP__"
|
||||||
port = 5000
|
port = __BMP_PORT__
|
||||||
# local-rib: the injected EVPN routes live in the loc-rib (there are no
|
# local-rib: the injected EVPN routes live in the loc-rib (there are no
|
||||||
# BGP peers / no adj-rib-in), so export the local RIB.
|
# BGP peers / no adj-rib-in), so export the local RIB.
|
||||||
route-monitoring-policy = "local-rib"
|
route-monitoring-policy = "local-rib"
|
||||||
|
|||||||
@ -158,13 +158,13 @@
|
|||||||
# --- BMP export to the OpenBMP collector ------------------------------------
|
# --- BMP export to the OpenBMP collector ------------------------------------
|
||||||
# GoBGP connects OUT to the collector. GoBGP's BMP config requires a literal
|
# GoBGP connects OUT to the collector. GoBGP's BMP config requires a literal
|
||||||
# IP (it cannot resolve a hostname), so we target the docker host IP where the
|
# IP (it cannot resolve a hostname), so we target the docker host IP where the
|
||||||
# collector publishes port 5000 -- stable across container recreation, unlike
|
# collector publishes the router-facing BMP port (default 1790) -- stable
|
||||||
# the collector's internal docker IP. Matches HOST_IP in .env.
|
# the collector's internal docker IP. Matches HOST_IP in .env.
|
||||||
# route-monitoring-policy = "pre-policy" exports the Adj-RIB-In (received
|
# route-monitoring-policy = "pre-policy" exports the Adj-RIB-In (received
|
||||||
# routes, pre import-policy) -- consistent with the rest of the OpenBMP fleet.
|
# routes, pre import-policy) -- consistent with the rest of the OpenBMP fleet.
|
||||||
[[bmp-servers]]
|
[[bmp-servers]]
|
||||||
[bmp-servers.config]
|
[bmp-servers.config]
|
||||||
address = "__HOST_IP__"
|
address = "__HOST_IP__"
|
||||||
port = 5000
|
port = __BMP_PORT__
|
||||||
route-monitoring-policy = "pre-policy"
|
route-monitoring-policy = "pre-policy"
|
||||||
statistics-timeout = 3600
|
statistics-timeout = 3600
|
||||||
|
|||||||
@ -13,8 +13,9 @@
|
|||||||
Must run in an ELEVATED PowerShell.
|
Must run in an ELEVATED PowerShell.
|
||||||
|
|
||||||
.PARAMETER RouterPort
|
.PARAMETER RouterPort
|
||||||
Router-facing BMP listen port on Windows (default 1790, the IANA BMP port).
|
Router-facing BMP port (default 1790, the IANA BMP port). Compose publishes
|
||||||
Forwards to the collector's in-container port 5000.
|
the same port on the WSL side (ROUTER_FACING_PORT:5000), so the proxy
|
||||||
|
forwards Windows:RouterPort -> WSL:RouterPort.
|
||||||
|
|
||||||
.PARAMETER WslIp
|
.PARAMETER WslIp
|
||||||
WSL address to forward to. Default: auto-detected via 'wsl hostname -I'.
|
WSL address to forward to. Default: auto-detected via 'wsl hostname -I'.
|
||||||
@ -25,7 +26,6 @@
|
|||||||
#>
|
#>
|
||||||
param(
|
param(
|
||||||
[int]$RouterPort = 1790,
|
[int]$RouterPort = 1790,
|
||||||
[int]$CollectorPort = 5000,
|
|
||||||
[int]$KafkaPort = 9092,
|
[int]$KafkaPort = 9092,
|
||||||
[string]$WslIp = ""
|
[string]$WslIp = ""
|
||||||
)
|
)
|
||||||
@ -45,8 +45,9 @@ if (-not $WslIp) {
|
|||||||
}
|
}
|
||||||
Write-Host "WSL address: $WslIp"
|
Write-Host "WSL address: $WslIp"
|
||||||
|
|
||||||
# listenport => connectport ($RouterPort maps DOWN to the collector's 5000)
|
# listenport => connectport (same port both sides; compose maps RouterPort
|
||||||
$maps = @{ $RouterPort = $CollectorPort; $KafkaPort = $KafkaPort }
|
# down to the collector's in-container 5000 on the WSL side)
|
||||||
|
$maps = @{ $RouterPort = $RouterPort; $KafkaPort = $KafkaPort }
|
||||||
foreach ($listen in $maps.Keys) {
|
foreach ($listen in $maps.Keys) {
|
||||||
netsh interface portproxy delete v4tov4 listenport=$listen listenaddress=0.0.0.0 2>$null | Out-Null
|
netsh interface portproxy delete v4tov4 listenport=$listen listenaddress=0.0.0.0 2>$null | Out-Null
|
||||||
netsh interface portproxy add v4tov4 listenport=$listen listenaddress=0.0.0.0 `
|
netsh interface portproxy add v4tov4 listenport=$listen listenaddress=0.0.0.0 `
|
||||||
|
|||||||
11
setup.sh
11
setup.sh
@ -194,11 +194,16 @@ fi
|
|||||||
|
|
||||||
# --- gobgpd.conf rendering (host-side -- gobgp image is distroless) ---------
|
# --- gobgpd.conf rendering (host-side -- gobgp image is distroless) ---------
|
||||||
# Render gobgp{,-evpn}/gobgpd.conf from gobgpd.conf.tmpl, substituting
|
# Render gobgp{,-evpn}/gobgpd.conf from gobgpd.conf.tmpl, substituting
|
||||||
# __HOST_IP__ with $HOST_IP. The rendered .conf is gitignored.
|
# __HOST_IP__ with $HOST_IP and __BMP_PORT__ with the collector's published
|
||||||
|
# port (ROUTER_FACING_PORT, default 1790 -- gobgp is host-networked, so it
|
||||||
|
# must target the published port, not the in-container 5000). The rendered
|
||||||
|
# .conf is gitignored.
|
||||||
|
BMP_PORT="$(get_env ROUTER_FACING_PORT)"; BMP_PORT="${BMP_PORT:-1790}"
|
||||||
for d in gobgp gobgp-evpn; do
|
for d in gobgp gobgp-evpn; do
|
||||||
if [ -f "$d/gobgpd.conf.tmpl" ]; then
|
if [ -f "$d/gobgpd.conf.tmpl" ]; then
|
||||||
sed -e "s/__HOST_IP__/$HOST_IP/g" "$d/gobgpd.conf.tmpl" > "$d/gobgpd.conf"
|
sed -e "s/__HOST_IP__/$HOST_IP/g" -e "s/__BMP_PORT__/$BMP_PORT/g" \
|
||||||
echo "Rendered $d/gobgpd.conf (HOST_IP=$HOST_IP)"
|
"$d/gobgpd.conf.tmpl" > "$d/gobgpd.conf"
|
||||||
|
echo "Rendered $d/gobgpd.conf (HOST_IP=$HOST_IP, BMP port=$BMP_PORT)"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user