DEV Community

Cover image for Make BGP Visible: A Live Topology Dashboard with Containerlab
Gergo Vadasz
Gergo Vadasz

Posted on • Originally published at gergovadasz.hu

Make BGP Visible: A Live Topology Dashboard with Containerlab

I wanted to refresh my BGP knowledge, but on terms that fit how I actually work. Running a home lab with physical routers wasn't an option, and the "heavyweight" network simulators—GNS3, EVE-NG, or Cisco VIRL—felt like overkill. I didn't want to sacrifice gigabytes of RAM to spin up vendor images I'd barely use, nor did I want a steep learning curve for the simulator itself before I could even touch a BGP configuration.

Packet Tracer was light enough, but it lives entirely in a GUI. I wanted my lab to be Infrastructure-as-Code: every router defined in a flat config file I could version, diff, and rebuild from scratch in seconds.

Once it was running, I wanted a "single pane of glass" focused on what BGP was actually doing: live routing tables, communities, and best-path changes—all updating the moment a link shifted. Together with Claude Code, I built my own BGP Dashboard.

The Tech Stack: Docker, Containerlab, Python

The lab is built on three open-source pillars, topped with a custom dashboard.

  • FRRouting (FRR): These are our routers. FRR is production-grade, open-source routing software used in massive scale-out networks. Because it's open-source, there are no licensing hurdles or proprietary image requirements. Furthermore, running each router as a lightweight Docker container—rather than a full virtual machine—means minimal RAM overhead and lightning-fast boot times.
  • Containerlab: This is the glue. It reads a single YAML file describing the topology—which routers exist, how they connect, and which configs to load—and wires them up as if you were plugging in physical cables. Bringing up a four-router lab takes one command and roughly 350 MB of RAM. It's the pure IaC experience: the whole lab lives in Git.
  • Python Dashboard: A custom backend polls each FRR instance every two seconds via the vtysh shell. It pulls BGP summaries and routing tables, then pushes that state to the browser over a WebSocket connection. The result? A dashboard that updates live without a manual refresh.

What the Dashboard Shows

image

This GIF captures a critical moment in BGP troubleshooting: forcing a full session reset on ISP1 and watching the aftermath. Notice a few key details:

  1. Live Topology: The diagram shows BGP sessions as colored links. All three links from ISP1 turn red the instant the sessions drop, then flip back to green as they re-establish. You can watch reconvergence happen in real-time without typing a single show command.
  2. Events Pane: This logs BGP Finite State Machine (FSM) transitions. With precise timestamps, it's easy to track exactly what happened and when.
  3. The Routing Table: The pane on the right shows ISP1's BGP RIB (Routing Information Base) depopulating as sessions drop, then repopulating as peers re-advertise their prefixes.

The goal was to make BGP state changes visible rather than something you have to infer from scrolling CLI output.

The Topology: Two Companies, Four Routers

I kept the topology simple and realistic to keep the focus on the protocol. The lab simulates two companies, each with dual-homed internet connectivity:

  • ISP1 and ISP2: Two separate Internet Service Providers in their own Autonomous Systems.
  • Customer-A and Customer-B: Each peers with both ISPs, providing redundant upstream paths.

This setup is small enough to understand at a glance, but rich enough to demonstrate the BGP concepts that actually matter in production:

Concept What it demonstrates
AS_PATH prepending Influencing inbound traffic by artificially lengthening the AS path
LOCAL_PREF Influencing outbound path selection within an AS
BGP communities Tagging prefixes to signal routing policy across AS boundaries
Multi-homing & failover What happens to traffic when one upstream session drops
Best-path selection Watching the decision process play out when multiple paths exist

Each of these can be triggered by changing a line in the FRR config (vtysh) and watching the dashboard update — no reloading the whole lab, no waiting.

BGP lab topology

How It Works Under the Hood

The architecture is intentionally simple so it stays readable and easy to modify. A quick heads-up: I haven't implemented authentication yet, and the Docker socket is exposed, so run this only in a trusted lab environment!

Data collection happens through FRR's vtysh shell, which provides a unified CLI across all FRR daemons. The Python backend connects to each container and runs commands like show bgp summary json and show bgp ipv4 unicast json. FRR supports JSON output on most show commands, which makes parsing straightforward without any screen-scraping.

State is diffed on every poll cycle. Rather than streaming raw data, the backend compares each new snapshot against the previous one and emits only what changed — a session that transitioned state, a prefix that appeared or was withdrawn. This keeps the WebSocket traffic minimal and makes the Events pane accurate.

The frontend is a single-page app that maintains a live WebSocket connection to the backend. The topology diagram is rendered as an SVG, with link colors driven by the current session state. The routing table and events log update incrementally as new data arrives.

Everything runs locally. There's no cloud dependency, no external API, no account required.

Try It Yourself

The full project is available on GitHub — topology definition, FRR configs, Python backend, and frontend all included.

Prerequisites: Docker and Containerlab installed on a Linux host. The lab has been tested on Ubuntu 22.04.

git clone https://github.com/vadaszgergo/bgp-lab-with-dashboard
cd bgp-lab-with-dashboard
sudo containerlab deploy -t simple.clab.yaml
Enter fullscreen mode Exit fullscreen mode

Then open http://localhost:8088 in your browser. The dashboard should come up within a few seconds.

From there, you can try anything with BGP — modify an FRR config, run a clear bgp *, advertise a new prefix — and watch how the network responds. The repository readme contains some example scenarios, like AS-path prepend, LOCAL_PREF change, and more.

If you find a bug, comments and pull requests are welcome. I'm posting a short walkthrough video as well, if you want to see in action (change resolution to 1080p in order to avoid the blur in the first few seconds).

Repository: GitHub - vadaszgergo/bgp-lab-with-dashboard

Walkthrough video: https://www.youtube.com/watch?v=N1RKT6id1UI

Originally published at gergovadasz.hu

Top comments (0)