VyOSXXX · BGP Route ReflectorsRoute reflectors
Route reflector troubleshooting — missing client flag, loop-guard rejections, and the attributes an RR must not touch
What you'll learn
- Diagnose the case where clients learn nothing because the route-reflector-client flag is absent
- Diagnose a flag that was set in one address family and not the other
- Read a CLUSTER_LIST rejection as designed behaviour rather than a fault
- Diagnose an ORIGINATOR_ID rejection caused by a duplicate router-id
- Recognise an export policy on an RR that rewrites the attributes RFC 4456 forbids it to touch
- Explain why reflected paths do not give the client two forwarding paths through the RRs
- Use the seven-step audit to walk a reflection failure from symptom to cause
Prerequisites
- iBGP full-mesh problem — why IBGP requires a full mesh, what the route reflector solves, and the loop-prevention trio (originator-id, cluster-list, cluster-id)
- Route reflector configuration — `route-reflector-client`, the two-RR cluster, and the canonical client/server mesh
- Cluster-id — the deduplication key, and why it decides how your clients must peer
- BGP session states — Idle, Connect, Active, OpenSent, OpenConfirm, Established, and the Notification codes that knock a peer out of each
- BGP routes missing — not received, not advertised, not installed
Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling)
Route reflection is one flag on one neighbour, and the blast radius of getting it wrong is the whole iBGP table. That asymmetry is what makes RR failures worth a playbook: the symptom is almost always “routes are missing somewhere”, and the causes look nothing alike.
This lesson is the diagnostic half of the route reflector part. vyos-xxx-01-rr-concept explains why reflection is needed and what ORIGINATOR_ID and CLUSTER_LIST do; vyos-xxx-02-rr-config builds the configuration. Here we start from the symptom.
The seven-step audit
- Is the neighbour flagged as a client, in the address family in question?
show configuration commands | match route-reflectoron the reflector. - Is the session Established, and in that address family?
show ip bgp summaryandshow bgp ipv6 summary. - Does the reflector have the route at all?
show ip bgp 198.51.100.0/24on the RR. A reflector cannot reflect what it never selected as best. - Is the route being advertised to the client?
show ip bgp neighbors 10.255.0.1 advertised-routeson the RR. - Is the client discarding it?
show ip bgp neighbors 10.255.0.5 received-routeson the client, withsoft-reconfiguration inboundenabled, shows what arrived before policy and before the loop guards. - What are ORIGINATOR_ID and CLUSTER_LIST on the path?
show ip bgp 198.51.100.0/24prints both. Compare them with the receiving router’s own router-id and cluster-id. - Is any policy on the reflector modifying the path?
show configuration commands | match 'route-map export'on the RR. An RR is not supposed to be rewriting attributes.
Steps 3, 4 and 5 are the ones that localise the fault, because between them they answer “does the RR have it”, “did the RR send it”, and “did the client keep it”. Everything else refines the answer.
Symptom 1: the clients learn nothing from each other
By far the most common. Sessions are up, the reflector has every route, and every client’s table contains only what it originated.
vyos@RR-1:~$ show ip bgp summary
vyos@RR-1:~$ show ip bgp 198.51.100.0/24
vyos@RR-1:~$ show ip bgp neighbors 10.255.0.2 advertised-routes
The first two look healthy. The third is empty, or contains only routes the RR learned from eBGP.
The cause is that the reflector is not a reflector. Without route-reflector-client on a neighbour, that neighbour is an ordinary iBGP peer, and the ordinary iBGP rule applies in full: a route learned from one iBGP peer is never re-advertised to another iBGP peer. Nothing is broken — the router is doing exactly what plain iBGP requires, which is why the session state and the RR’s own table both look fine.
The fix sets the flag on every client, inside the address family:
configure
set protocols bgp neighbor 10.255.0.1 address-family ipv4-unicast route-reflector-client
set protocols bgp neighbor 10.255.0.2 address-family ipv4-unicast route-reflector-client
commit
save
Confirm on the reflector, not on the client — the flag is configuration on the RR and the client has no way to know it exists:
show configuration commands | match route-reflector
Symptom 2: IPv4 reflects and IPv6 does not
The dual-stack version of symptom 1, and it is easy to miss because half the estate works.
show configuration commands | match route-reflector
If that prints address-family ipv4-unicast route-reflector-client for each client and nothing under ipv6-unicast, the diagnosis is complete. route-reflector-client is a per-address-family property in FRR, and VyOS puts it where FRR does. A neighbour can be a client for IPv4 and an ordinary iBGP peer for IPv6 at the same time, on the same session, and the session state gives no hint.
set protocols bgp neighbor 10.255.0.1 address-family ipv6-unicast route-reflector-client
The same trap applies to every other per-family setting on the neighbour: soft-reconfiguration inbound, route-map export, nexthop-self. When an address family behaves differently from its sibling, compare the two subtrees before anything else.
Symptom 3: a route the reflector holds never reaches the other reflector
Two RRs, both configured, both with clients, and RR-2’s table does not contain a route RR-1 clearly reflected. show ip bgp on RR-1 shows the path with a CLUSTER_LIST containing RR-1’s cluster-id, and RR-2 has nothing.
This is not a fault. CLUSTER_LIST is the loop guard between reflectors: a router discards any path whose CLUSTER_LIST already contains its own cluster-id. Two RRs deliberately configured into the same cluster share a cluster-id, so each one rejects the other’s reflections by design. That is what “the same cluster” means.
set protocols bgp parameters cluster-id '1.2.3.4'
The decision the operator actually has to make is which model they want:
- Shared cluster-id. Both RRs are one logical cluster. They ignore each other’s reflections, each client gets one reflected copy per RR it peers with, and the table stays small. This is the RFC 4456 arrangement for redundant reflectors.
- Distinct cluster-ids (the default, since an unconfigured cluster-id is the RR’s router-id). The RRs accept each other’s reflections, clients see more paths, and path diversity improves at the cost of extra state and extra churn.
Neither loops: the guard holds in both models, because a path always carries the cluster-id of every reflector that touched it and no reflector accepts its own. What changes is how many copies exist. Diagnose this symptom by deciding which model was intended, then confirming the cluster-ids agree with that intent — not by assuming the missing path is a bug.
Symptom 4: a client rejects a route that is legitimately its own to learn
The client is up, the RR advertised the prefix, and the client’s table does not have it. received-routes on the client shows it arriving.
vyos@client-A:~$ show ip bgp neighbors 10.255.0.5 received-routes
vyos@client-A:~$ show ip bgp 198.51.100.0/24
Look at ORIGINATOR_ID on the path and at the client’s own router-id:
vyos@client-A:~$ show ip bgp 198.51.100.0/24
vyos@client-A:~$ show configuration commands | match router-id
A router discards any path whose ORIGINATOR_ID equals its own BGP router-id. That is the inner loop guard, and when the client really did originate the route, the rejection is correct and invisible — the client already has the route locally, so nothing looks wrong.
The failure case is a duplicate router-id. If two routers in the AS were built from the same template and both ended up with router-id 10.255.0.1, then a route originated by the first is rejected by the second, because the second sees its own router-id in ORIGINATOR_ID. The two routers exchange nothing through the reflector while every session stays Established and every other prefix flows normally.
set protocols bgp parameters router-id '10.255.0.2'
Changing a router-id resets the router’s BGP sessions. Do it in a window, and audit for a third duplicate while you are there:
show ip bgp summary
Symptom 5: the RR-client session never reaches Established
The generic session failure, with two RR-specific twists.
vyos@client-A:~$ show ip bgp summary
A peer sitting in Active is trying and failing to complete TCP; a peer sitting in Idle is not trying. The RR-specific causes:
- Loopback peering with no update-source. RR designs peer loopback to loopback. Without
set protocols bgp neighbor 10.255.0.5 update-source lo, the router sources the session from the egress interface, the reflector sees a source address it has no neighbour statement for, and the connection is refused. The route to the loopback existing in the IGP is a separate requirement, and both must hold. route-reflector-clienton an eBGP neighbour. Reflection is an iBGP mechanism. A neighbour whoseremote-asdiffers fromsystem-ascannot be a client, and the attempt is rejected rather than silently ignored.
show ip bgp neighbors 10.255.0.5
show ip route 10.255.0.5
The first shows the local and remote addresses the session is actually using; the second confirms the IGP can reach the reflector’s loopback at all. A session that will not come up is almost never an RR problem — work it as a session problem first, and only return to reflection once it is Established.
Symptom 6: clients receive the route and blackhole the traffic
The most damaging failure on this page, because everything looks correct. The clients have the prefix, the path is valid and best, and packets sent to it are dropped.
Look at the NEXT_HOP the client received, and at what the reflector is doing on export:
vyos@client-A:~$ show ip bgp 198.51.100.0/24
vyos@RR-1:~$ show configuration commands | match 'route-map export'
If the client’s NEXT_HOP is the reflector’s address rather than the originating router’s, the reflector is rewriting it — usually because somebody applied nexthop-self or an export route-map carried over from an eBGP-facing template.
RFC 4456 is explicit that a reflector should not modify NEXT_HOP, AS_PATH, LOCAL_PREF or MED on the routes it reflects. The reason is structural: a route reflector is a control-plane device. It is chosen for CPU and memory, it is often a virtual machine, and in many designs it is not in the forwarding path between any two clients at all. Rewriting NEXT_HOP tells every client to send traffic to a box that has no route to the destination and no capacity to carry it.
delete protocols bgp neighbor 10.255.0.1 address-family ipv4-unicast nexthop-self
The general rule for reflectors: policy that filters is a design decision to be made carefully, since it applies to every client at once. Policy that modifies the four protected attributes is a bug.
Symptom 7: the client does not load-balance across the two reflectors
Two RRs, both peered with the client, both reflecting the same prefix, and the client installs one path.
vyos@client-A:~$ show ip bgp 198.51.100.0/24
Two paths, one marked best, and adding maximum-paths ibgp does not change the forwarding behaviour in the way the operator expected:
set protocols bgp address-family ipv4-unicast maximum-paths ibgp '2'
The expectation is the error. Because a reflector does not modify NEXT_HOP (symptom 6), both reflected copies of the prefix carry the same next-hop — the originating router’s. There are two BGP paths and one forwarding destination. Installing both changes nothing about where the packets go, and no traffic flows through either reflector as a result of reflection.
What the two RRs give the client is control-plane redundancy: if RR-1 dies, RR-2 is already advertising the same prefix and the client keeps the route. That is the entire benefit, and it is a large one.
Real iBGP multipath needs genuinely different next-hops — two originating routers advertising the same prefix, or an anycast service. Then maximum-paths ibgp does what its name says, subject to the paths being equal through the earlier best-path steps. Configure it because the topology has two exits, not because the topology has two reflectors.
How it fails in production
- The client flag is absent. Plain iBGP split-horizon applies, and clients learn nothing from each other. The RR’s own table looks perfect.
- The flag is present in one address family only. IPv4 works, IPv6 does not, and the session state hides it.
- Client-to-client reflection was disabled by an inherited configuration. Same symptom as a missing flag, different cause, and only the configuration shows it.
- CLUSTER_LIST rejection. Correct behaviour between reflectors sharing a cluster-id. The bug, if there is one, is a mismatch between the cluster-id layout and the design.
- Duplicate router-id. ORIGINATOR_ID rejection discards legitimate routes between two routers while everything else works.
- The reflector rewrites NEXT_HOP. Clients hold a valid-looking route pointing at a control-plane device. Traffic is blackholed.
- Multipath expected across reflectors. Two paths, one next-hop, no change in forwarding. Redundancy here is control-plane only.
Rollback
Most of this lesson is a read activity: the operator is inspecting state, not changing it. The rollback path is for the eventual fix:
compareto see the diff beforecommit.commit-confirm 5for any change made across the sessions being altered — adding a client flag re-advertises a large part of the table, and getting it wrong on the RR affects every client at once.rollback 1thencommitandsaveto return to the previous revision.load /config/archive/config.boot.<timestamp>thencommitandsaveto return to an archived snapshot.
Two of these fixes are disruptive in a way the configuration diff does not show. Changing a router-id resets that router’s BGP sessions. Adding route-reflector-client to a neighbour causes the RR to re-advertise its table to that peer. Neither is a reason not to do it; both are reasons to do it in a window.
Production discipline
Cross-course references
The Linux course’s XIX-Linux-NetFoundations covers the kernel FIB the client eventually installs into. The OPNsense course’s XXX-OPNsense-DynamicRouting covers the same FRR machinery on the firewall side. Within this course, vyos-xxxi-01-session-states and vyos-xxxi-02-routes-missing carry the general session and route-loss workflows this lesson defers to; vyos-xxx-01-rr-concept covers why reflection exists and what the attributes do, vyos-xxx-02-rr-config builds the configuration, and vyos-xxx-03-cluster-id covers cluster design and redundancy.
Quiz
Knowledge check · 4 questions
Q1. Every iBGP session to the reflector is Established and the reflector's own BGP table is complete, but no client has learned a route from any other client. What is the most likely cause?
Q2. An unconfigured cluster-id defaults to the reflector's router-id, so two reflectors intended to form one cluster must be given a matching cluster-id explicitly.
Q3. Clients hold 198.51.100.0/24, the path is valid and best, and traffic to it is dropped. The NEXT_HOP the clients show is the reflector's loopback rather than the originating router's. What happened, and why is it worse than a filtering mistake?
RR-1 peers with four clients. A template that was written for an eBGP border router was reused for the reflector's neighbour stanzas, and it carries `set protocols bgp neighbor 10.255.0.1 address-family ipv4-unicast nexthop-self`. RR-1 is a virtual machine with a single interface, sized for control plane work; it is not in the forwarding path between any two clients.
Q4. Two routers in the same AS exchange no routes through the reflector, while every other pair works and all sessions are Established. The reflector advertises each router's prefixes to the other. What single misconfiguration explains it?
Client-A and client-D were built from the same golden image. `show ip bgp neighbors 10.255.0.5 received-routes` on client-D shows client-A's prefixes arriving from the reflector, but `show ip bgp` on client-D does not contain them. The reverse is also true. Every other client learns both routers' prefixes normally.
Passing score: 75%. Answers are checked in this browser.