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:
Sam 2026-07-20 16:19:53 -07:00
parent 0c91cad55f
commit b480615ca2
12 changed files with 63 additions and 35 deletions

View File

@ -12,6 +12,15 @@ OBMP_DATA_ROOT=/var/openbmp
# (Kafka external listener, BMP source, ExaBGP peering).
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:
# local — Grafana built-in login (admin / openbmp). Lab default.
# OBMP_DOMAIN / OBMP_COOKIE_DOMAIN below can stay blank.

View File

@ -41,9 +41,13 @@ def _env_default(key, default, dotenv=".env"):
# --- BMP collector ---------------------------------------------------------
# Resolved from $HOST_IP or the HOST_IP= line in repo-root .env.
COLLECTOR_HOST = _env_default("HOST_IP", "10.40.40.202")
COLLECTOR_PORT = "5000"
# Routers must target the ROUTER-FACING address, not HOST_IP: on a WSL
# deployment HOST_IP is the unreachable WSL NAT address (portability finding
# 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.
# Each line is self-contained and applied at the (config)# prompt; a bare

View File

@ -129,7 +129,7 @@ configuration:
!
!
bmp server 1
host 10.40.40.202 port 5000
host 10.40.40.202 port 1790
description OpenBMP
update-source Gi0/0/0/0
flapping-delay 60

View File

@ -455,8 +455,8 @@ fi
# 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
# 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
# listenport=1790 connectport=5000 on WSL).
# compose publishes ${ROUTER_FACING_PORT:-1790}:5000 everywhere, so on WSL the
# portproxy forwards listenport=ROUTER_PORT to the SAME port on the WSL side.
BMP_STD_PORT=1790
default_router_port="${ARG_ROUTER_PORT:-$BMP_STD_PORT}"
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:
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}
New-NetFirewallRule -DisplayName "OpenBMP ${ROUTER_PORT}" -Direction Inbound -LocalPort ${ROUTER_PORT} -Protocol TCP -Action Allow

View File

@ -194,7 +194,11 @@ services:
- net.ipv4.tcp_keepalive_probes=5
- net.ipv4.tcp_keepalive_time=180
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:
- ${OBMP_DATA_ROOT}/config:/config
environment:
@ -480,7 +484,7 @@ services:
# 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
# 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
depends_on:
- collector

View File

@ -28,7 +28,7 @@ This is a **BGP Monitoring Platform (BMP) lab stack** deployed via Docker Compos
**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
- 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
@ -119,7 +119,7 @@ Traffic Generator (Phase 4):
- 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 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)
- `OBMP_DATA_ROOT` directory created (default: `/var/openbmp`)

View File

@ -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
daemon with an old vendored client.
## 12. OPEN: router-side automation still targets the old lab's values
`cml/proxmox_bmp_config.py` sends routers at `HOST_IP` port `5000`, and
`cml/xrd-node-definition.yaml` bakes in `10.40.40.202:5000` — both correct on
## 12. Router-side automation targeted the old lab's values
`cml/proxmox_bmp_config.py` sent routers at `HOST_IP` port `5000`, and
`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
target the router-facing address, and the port default is now 1790). Fold
`ROUTER_FACING_IP`/`ROUTER_FACING_PORT` from `.env` into that tooling when
the 5000-vs-1790 decision lands. See docs/router-bmp-config.md.
target the router-facing address). Resolved 2026-07: the router-facing port
is **1790** everywhere; compose publishes `${ROUTER_FACING_PORT:-1790}:5000`,
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.

View File

@ -14,18 +14,19 @@ deploy.sh records the correct target in `.env` as
| Stack host | Routers target | Path to the collector |
|---|---|---|
| Native Linux | `ROUTER_FACING_IP` (= host IP) : `ROUTER_FACING_PORT` | compose port map -> collector :5000 |
| WSL2 | Windows LAN IP : `ROUTER_FACING_PORT` | `netsh portproxy` (Windows) -> WSL `HOST_IP` -> 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, same port) -> WSL -> compose `ROUTER_FACING_PORT:5000` |
On WSL the Windows-side forwarding must exist first — run
`scripts/wsl-portproxy.ps1` in an **elevated** PowerShell, and re-run it after
every WSL restart (the WSL address changes).
The router-facing port defaults to **1790** (the IANA-registered BMP port);
the collector always listens on **5000 inside the container**. The lab
routers were historically configured for 5000 — until they are reconfigured,
deploy with `--router-port 5000` (see the open decision in
docs/PORTABILITY-FINDINGS.md, finding 12).
The router-facing port is **1790** (the IANA-registered BMP port; decided
2026-07 — the lab's historical 5000 is being retired). The collector always
listens on **5000 inside the container**; compose maps
`${ROUTER_FACING_PORT:-1790}` down to it, and setup.sh renders the same port
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

View File

@ -22,7 +22,7 @@
[[bmp-servers]]
[bmp-servers.config]
address = "__HOST_IP__"
port = 5000
port = __BMP_PORT__
# 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.
route-monitoring-policy = "local-rib"

View File

@ -158,13 +158,13 @@
# --- BMP export to the OpenBMP collector ------------------------------------
# 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
# 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.
# route-monitoring-policy = "pre-policy" exports the Adj-RIB-In (received
# routes, pre import-policy) -- consistent with the rest of the OpenBMP fleet.
[[bmp-servers]]
[bmp-servers.config]
address = "__HOST_IP__"
port = 5000
port = __BMP_PORT__
route-monitoring-policy = "pre-policy"
statistics-timeout = 3600

View File

@ -13,8 +13,9 @@
Must run in an ELEVATED PowerShell.
.PARAMETER RouterPort
Router-facing BMP listen port on Windows (default 1790, the IANA BMP port).
Forwards to the collector's in-container port 5000.
Router-facing BMP port (default 1790, the IANA BMP port). Compose publishes
the same port on the WSL side (ROUTER_FACING_PORT:5000), so the proxy
forwards Windows:RouterPort -> WSL:RouterPort.
.PARAMETER WslIp
WSL address to forward to. Default: auto-detected via 'wsl hostname -I'.
@ -25,7 +26,6 @@
#>
param(
[int]$RouterPort = 1790,
[int]$CollectorPort = 5000,
[int]$KafkaPort = 9092,
[string]$WslIp = ""
)
@ -45,8 +45,9 @@ if (-not $WslIp) {
}
Write-Host "WSL address: $WslIp"
# listenport => connectport ($RouterPort maps DOWN to the collector's 5000)
$maps = @{ $RouterPort = $CollectorPort; $KafkaPort = $KafkaPort }
# listenport => connectport (same port both sides; compose maps RouterPort
# down to the collector's in-container 5000 on the WSL side)
$maps = @{ $RouterPort = $RouterPort; $KafkaPort = $KafkaPort }
foreach ($listen in $maps.Keys) {
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 `

View File

@ -194,11 +194,16 @@ fi
# --- gobgpd.conf rendering (host-side -- gobgp image is distroless) ---------
# 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
if [ -f "$d/gobgpd.conf.tmpl" ]; then
sed -e "s/__HOST_IP__/$HOST_IP/g" "$d/gobgpd.conf.tmpl" > "$d/gobgpd.conf"
echo "Rendered $d/gobgpd.conf (HOST_IP=$HOST_IP)"
sed -e "s/__HOST_IP__/$HOST_IP/g" -e "s/__BMP_PORT__/$BMP_PORT/g" \
"$d/gobgpd.conf.tmpl" > "$d/gobgpd.conf"
echo "Rendered $d/gobgpd.conf (HOST_IP=$HOST_IP, BMP port=$BMP_PORT)"
fi
done