BGP Route Reflector Design for Enterprise Campuses
iBGP's full-mesh rule means 20 routers need 190 peering sessions — unmanageable long before that. Route reflectors break the mesh safely: how they work, where to place them in a campus, the IOS config, and the five design mistakes behind real outages.
The group-chat problem
Picture a group chat with 30 people where everyone hits "reply all" to everything. Every new member doesn't add one conversation — they add 29, one with each existing member. That is a full mesh: every router peers directly with every other router, and the session count is n(n-1)/2.
A route reflector is the teacher's aide. Instead of 30 kids shouting at each other, every kid tells the aide, and the aide relays the message to the kids who need it. Thirty shouting conversations collapse into 30 quiet ones with the aide — and in networking, the math is even better than that, as you'll see below.
The full-mesh tax
iBGP (internal BGP — the BGP routers use inside one company's network) has one annoying rule: a route learned from one iBGP peer is never re-advertised to another iBGP peer. This split-horizon behavior is what keeps iBGP loop-free — but it forces every router to peer directly with every other router. The session count is n(n-1)/2: 5 routers need 10 sessions, 10 routers need 45, and 20 routers need 190. Long before you hit 20 routers, the mesh is unmanageable.
If BGP fundamentals are rusty, start with BGP: How the Internet Actually Finds a Path — the split-horizon rule and the BGP decision process it protects are covered there.
What a route reflector actually does
A route reflector (RR) is simply an iBGP speaker allowed to break the split-horizon rule in a controlled way. Routers that peer with it are its clients; together they form a cluster (a group of clients plus their reflector, identified by a cluster-id). The reflector follows three reflection rules, and only these three:
- Route from a client → reflected to all other clients and to non-client iBGP peers.
- Route from a non-client iBGP peer → reflected to clients only.
- Route from an eBGP peer → reflected to everyone (clients and non-clients).
With one reflector, those 20 routers need 19 sessions instead of 190. With two reflectors for redundancy, each router peers with both — still a linear, sane number.
How loops stay impossible
Relaxing split-horizon sounds dangerous, and it would be, without two extra BGP attributes the reflector attaches to every reflected route. ORIGINATOR_ID records the router-id of the router that first injected the route into iBGP — if a router sees its own router-id in ORIGINATOR_ID, it ignores the route. CLUSTER_LIST records every cluster the route has passed through — if a reflector sees its own cluster-id in the list, it ignores the route. Between the two, a reflected route can never circle back to where it started.
On the wire: a BGP UPDATE carrying both attributes
Here is what the loop prevention actually looks like in a packet capture — a BGP UPDATE (message type 2) for 10.20.0.0/16, as the reflector sends it. The two reflection attributes are highlighted: ORIGINATOR_ID in teal, CLUSTER_LIST in amber.
ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
00 3a 02 00 00 00 20 40 01 01 00 40 02 04 02 01
fd e9 40 03 04 0a 00 00 fe 80 09 04 0a 00 01 02
80 0a 04 00 00 00 64 10 0a 14
Bytes 0–18 — BGP header. 16-byte marker (all ff), 2-byte length 00 3a (58 bytes total), 1-byte type 02 = UPDATE.
Every BGP message starts this way. Length covers the whole message including the 19-byte header, so the UPDATE body here is 39 bytes.
Withdrawn routes + attribute length. 00 00 (no withdrawals), 00 20 (32 bytes of path attributes follow).
An UPDATE can withdraw and announce in one message; this one only announces.
40 01 01 00 — ORIGIN. Flags 40 (well-known, transitive), type 1, length 1, value 0 = IGP.
The route was born inside the AS. Nothing reflector-specific here.
40 02 04 02 01 fd e9 — AS_PATH. One AS in sequence: fd e9 = 65001.
Inside iBGP the AS_PATH doesn't grow, but it's still carried so everyone agrees on the path's origin AS.
40 03 04 0a 00 00 fe — NEXT_HOP. Next hop 10.0.0.254.
Note the reflector does not rewrite the next hop — clients forward toward the original next hop, not toward the reflector.
80 09 04 0a 00 01 02 — ORIGINATOR_ID. Flags 80 (optional, non-transitive), type 9, length 4, value 10.0.1.2.
This is the router-id of the client (A, 10.0.1.2) that first injected the route. If this UPDATE ever circles back to 10.0.1.2, that router sees its own id and drops it.
80 0a 04 00 00 00 64 — CLUSTER_LIST. Flags 80 (optional, non-transitive), type 10, length 4, one cluster-id: 00 00 00 64 = 100.
The reflector appended its own cluster-id (100) before reflecting. Any reflector whose cluster-id is 100 will refuse this UPDATE — that's the drop you watched in the animation above.
10 0a 14 — NLRI. Prefix length 16, then 10.20 → 10.20.0.0/16.
NLRI is length-prefixed and packed: a /16 needs only the first 2 bytes of the address.
Want to see these attributes on your own prefixes from the outside? The BGP Toolkit's prefix lookup shows the AS path the world sees for your announcements.
Enterprise design: two reflectors, placed at the core
For a campus or multi-site enterprise, the design that survives contact with reality looks like this:
- Two reflectors per cluster. Never one. A single RR is a single point of failure for your entire iBGP control plane. Every client peers with both.
- Place them at the core or distribution layer — on routers that already see the whole topology. Do not put reflectors on WAN edge routers that flap with every provider hiccup.
- One cluster per site or building. Distinct cluster-ids per cluster are what make CLUSTER_LIST loop prevention work across sites.
- Think about the forwarding path. A reflector does not have to forward traffic — it only needs to speak BGP. But in practice the core routers do forward, and clients will happily install next-hops that trombone through the core. Verify the data path with traceroutes after any RR change.
- Hierarchy for large campuses. If clusters themselves need to exchange routes without a full mesh of RRs, make top-level reflectors whose clients are the lower-level reflectors. Two levels is plenty for any enterprise.
The config: a handful of lines on IOS
On the reflector, designate the clients and give the cluster an identity:
router bgp 65001
bgp router-id 10.0.0.1
bgp cluster-id 10.0.0.1
neighbor 10.0.1.2 remote-as 65001
neighbor 10.0.1.2 route-reflector-client
neighbor 10.0.1.3 remote-as 65001
neighbor 10.0.1.3 route-reflector-client
Clients need no special configuration at all — a plain iBGP neighbor statement toward the reflector is enough. That asymmetry is a feature: you can convert an existing full mesh to reflection by touching only the two reflectors, then pruning the old mesh sessions router by router. Before you prune, paste the candidate reflector config through the Network config verifier — it catches the duplicate-IP and ASN mistakes that turn a migration window into an outage window.
Five mistakes that cause real outages
- One reflector. The most common RR outage is the one where there was only ever one RR. Budget for two from day one.
- Duplicate or missing cluster-id. Two clusters with the same cluster-id, and CLUSTER_LIST starts discarding legitimate routes — the symptom is routes that exist on the reflector but never reach clients. Set it explicitly.
- Forgetting the reflector hides alternate paths. A reflector advertises only its single best path for each prefix. If the reflector's best path differs from a client's, the client never learns its own better option.
- Reflector placement that warps the forwarding path. iBGP does not change next-hop, so clients forward toward the original next-hop — but route selection is influenced by which paths the reflector chose to advertise.
- Mixing clusters without hierarchy. Reflectors in different clusters must peer with each other (as non-clients) or sit under a higher-level reflector.
Verify before you trust
Reflection is easy to configure and easy to mis-verify. On each reflector, confirm the client sessions are established:
show ip bgp summary ! clients should read Established
show ip bgp neighbors 10.0.1.2 advertised-routes
show ip bgp 10.20.0.0 ! check Originator and Cluster List lines
Then verify from the outside: the BGP Toolkit's looking glass and prefix lookup show you what the rest of the world sees for your prefixes. And when the design is done, walk it once end-to-end in the Enterprise Network Engineer track order — this article sits right after the BGP fundamentals piece for a reason.
- BGP: How the Internet Actually Finds a Path — split-horizon, the decision process, and the attributes reflectors manipulate.
- BGP Toolkit — one-click hijack verdict, looking glass, RPKI and bogon checks for the prefixes your reflectors carry.
- Network config verifier — sanity-check reflector configs for duplicate IPs, ASN mismatches, and unreachable subnets before maintenance windows.
- Enterprise Network Engineer: The Career Path Guide — where campus routing design sits in the hiring bar.
- iBGP requires a full mesh by default: n routers need n(n-1)/2 sessions, so the session count grows quadratically — 20 routers means 190 sessions.
- A route reflector relaxes the iBGP split-horizon rule and re-advertises client routes; ORIGINATOR_ID and CLUSTER_LIST attributes keep loops impossible.
- Design rule: two reflectors per cluster, never one. Place them at the core or distribution layer, and keep one cluster per site or building.
- A reflector advertises only its single best path, which can hide backup paths from clients — know when BGP add-paths is warranted.
- Validate with show commands and the BGP Toolkit; a mismatched cluster-id silently splits your cluster, so keep reflector configs identical where it counts.