We have been using a Perl based BGP script to announce some prefixes — for black hole routing, or to ban IP addresses as a result of law enforcement requests — from a database to the network.
This project was the result of searching for a new BGP daemon that can be hooked into any need and that supports the L3 MPLS VPN Unicast address family.
We have used osrg/gobgp (GoBGP) as a native library for the iBGP connection into our network. GoBGP can be embedded directly as a Go library, so instead of talking to a separate daemon over gRPC we drive the BGP server in-process and feed it routes straight from our database.
The repository for the testing tool is here: github.com/denizaydin/bgpRouteServer
The convergence problem with VPNv4 updates
The current release of osrg/gobgp sends each VPNv4 prefix in a single UPDATE message. If you have a large number of routes, this increases the convergence time considerably.
I changed table/message.go to pack a single UPDATE for VPNv4 routes that share the same route distinguisher (RD) and next-hop. That fork lives at denizaydin/gobgp. Grouping prefixes that share an RD and next-hop into one UPDATE drastically cuts the number of messages on the wire and speeds up convergence when announcing many routes at once.
How the route server works
The tool (bgpRouteServer) is intentionally small — a single main.go that ties together the GoBGP library and a MySQL backend:
- It opens a BGP session using the osrg/gobgp library.
- It reads the prefixes to advertise from a MySQL database.
- On a fixed interval it diffs the database against what is currently advertised, then adds new paths and withdraws removed ones.
The database connection and query are configurable through command-line flags. By default it runs:
| |
and re-scans the table every 30 seconds. New rows are advertised with AddPath(); rows that disappear are withdrawn with DeletePath() using the IPv4 VPN route family.
BGP configuration
The BGP server is started in-process with the following settings:
| Setting | Value |
|---|---|
| Local AS | 65000 |
| Router ID | 10.2.8.12 |
| Neighbor | 10.2.51.7 (peer AS 65000, iBGP) |
| Address families | ipv4-unicast, l3vpn-ipv4-unicast |
| Listen port | -1 (do not listen on TCP/179) |
Setting the listen port to -1 keeps GoBGP from binding to TCP/179, so the process only initiates the session to the configured neighbor — handy when running it next to other BGP software on the same host.
Route encoding
Each advertised route is built as a labeled VPNv4 path:
| Field | Value |
|---|---|
| Prefix length | /32 |
| MPLS label | 100 |
| Route Distinguisher | 1:1 |
| Route Target | extended community 1:1 (two-octet AS format) |
| Next hop | 10.2.8.12 |
This script is just for testing purposes. In the production setup each prefix in the database carries its own next-hop, route-target and RD, so the route server pulls those values per row instead of using the fixed 1:1 / 10.2.8.12 defaults shown above. The end result: routes are read from the database and advertised straight into the backbone over a single iBGP session.
The content of this post was created by the author; AI was used for editing and restructuring.