Skip to content

Route Reflection

Thomas Mangin edited this page Nov 15, 2025 · 1 revision

BGP Route Reflection

Route reflection is a BGP scaling technique that reduces the number of required IBGP (Internal BGP) peering sessions in large networks. This guide covers how to use ExaBGP as a route reflector or route reflector client.

Table of Contents

Overview

Important: ExaBGP does NOT manipulate the routing table (RIB/FIB). When using ExaBGP as a route reflector, it reflects routes between BGP peers but does not install routes into the system routing table.

Why Route Reflection?

In traditional IBGP, all routers must peer with each other (full mesh). For n routers, this requires n(n-1)/2 peering sessions:

  • 5 routers: 10 sessions
  • 10 routers: 45 sessions
  • 50 routers: 1,225 sessions
  • 100 routers: 4,950 sessions

Route reflection allows routers to peer with a route reflector instead of each other, dramatically reducing the number of sessions.

Route Reflection Architecture

Traditional IBGP (Full Mesh):          Route Reflection:

    R1 ─────── R2                          R1 ────┐
     β”‚ β•²     β•± β”‚                            R2 ────
     β”‚   β•² β•±   β”‚                            R3 ───┼─── RR (Route Reflector)
     β”‚   β•± β•²   β”‚                            R4 ────
     β”‚ β•±     β•² β”‚                            R5 β”€β”€β”€β”€β”˜
    R3 ─────── R4
     β”‚         β”‚                         5 sessions (vs 10 in full mesh)
     └────R5β”€β”€β”€β”˜

   10 sessions

Terminology

  • Route Reflector (RR) - Router that reflects routes to clients
  • Route Reflector Client - Router that peers with the RR
  • Non-Client - IBGP peer that is not a client (full mesh with RR)
  • Cluster - Route reflector and its clients
  • Cluster ID - Identifier for a cluster (prevents loops)
  • Originator ID - Original router that advertised the route

Route Reflection Concepts

Route Reflection Rules

A route reflector follows these rules when receiving routes from IBGP peers:

1. Routes from Clients:

  • Reflect to all other clients in the cluster
  • Reflect to all non-client IBGP peers
  • Advertise to all EBGP peers

2. Routes from Non-Clients:

  • Reflect to all clients in the cluster
  • Do NOT reflect to other non-clients
  • Advertise to all EBGP peers

3. Routes from EBGP peers:

  • Reflect to all clients
  • Advertise to all non-client IBGP peers
  • Advertise to all other EBGP peers

Route Reflector Attributes

Route reflectors add special BGP attributes to prevent loops:

  • ORIGINATOR_ID (Type Code 9) - Router ID of the route originator
  • CLUSTER_LIST (Type Code 10) - List of cluster IDs the route has traversed

Route Reflector Configuration

Configure ExaBGP as a route reflector.

Basic Route Reflector Configuration

# /etc/exabgp/exabgp.conf
# ExaBGP as Route Reflector

# Client 1
neighbor 192.0.2.11 {
    router-id 192.0.2.1;
    local-address 192.0.2.1;
    local-as 65001;
    peer-as 65001;

    # This peer is a route reflector client
    route-reflector-client;

    family {
        ipv4 unicast;
        ipv6 unicast;
    }
}

# Client 2
neighbor 192.0.2.12 {
    router-id 192.0.2.1;
    local-address 192.0.2.1;
    local-as 65001;
    peer-as 65001;

    # This peer is a route reflector client
    route-reflector-client;

    family {
        ipv4 unicast;
        ipv6 unicast;
    }
}

# Client 3
neighbor 192.0.2.13 {
    router-id 192.0.2.1;
    local-address 192.0.2.1;
    local-as 65001;
    peer-as 65001;

    # This peer is a route reflector client
    route-reflector-client;

    family {
        ipv4 unicast;
        ipv6 unicast;
    }
}

# Non-client IBGP peer (traditional full mesh with this peer)
neighbor 192.0.2.20 {
    router-id 192.0.2.1;
    local-address 192.0.2.1;
    local-as 65001;
    peer-as 65001;

    # No route-reflector-client directive = non-client

    family {
        ipv4 unicast;
        ipv6 unicast;
    }
}

Route Reflector with Multiple Address Families

neighbor 192.0.2.11 {
    router-id 192.0.2.1;
    local-address 192.0.2.1;
    local-as 65001;
    peer-as 65001;

    route-reflector-client;

    # Route reflection for multiple address families
    family {
        ipv4 unicast;
        ipv6 unicast;
        ipv4 mpls-vpn;
        ipv6 mpls-vpn;
        l2vpn evpn;
    }
}

Route Reflector Client Configuration

Configure ExaBGP as a route reflector client.

Basic Client Configuration

# /etc/exabgp/exabgp.conf
# ExaBGP as Route Reflector Client

# Peer with route reflector
neighbor 192.0.2.1 {
    router-id 192.0.2.11;
    local-address 192.0.2.11;
    local-as 65001;
    peer-as 65001;

    # No special directive needed on client side
    # Route reflector marks this as a client

    family {
        ipv4 unicast;
        ipv6 unicast;
    }
}

# API process to announce routes
process announce {
    run /etc/exabgp/announce.py;
    encoder text;
}

neighbor 192.0.2.1 {
    api {
        processes [ announce ];
    }
}

Client with Route Announcements

#!/usr/bin/env python3
# /etc/exabgp/announce.py
# Route reflector client announcing routes

import sys
import time

# Announce routes to route reflector
# Route reflector will reflect to other clients

routes = [
    "198.51.100.0/24",
    "203.0.113.0/24",
]

for route in routes:
    print(f"announce route {route} next-hop self", flush=True)
    sys.stderr.write(f"Announced {route} to route reflector\n")

# Keep process running
while True:
    time.sleep(60)

Cluster Configuration

A cluster consists of a route reflector and its clients. Cluster IDs prevent routing loops.

Single Cluster

# /etc/exabgp/exabgp.conf
# Route Reflector with Cluster ID

neighbor 192.0.2.11 {
    router-id 192.0.2.1;
    local-address 192.0.2.1;
    local-as 65001;
    peer-as 65001;

    route-reflector-client;

    # Cluster ID (typically the RR's router ID)
    cluster-id 192.0.2.1;

    family {
        ipv4 unicast;
    }
}

Multiple Route Reflectors (Same Cluster)

For redundancy, deploy multiple route reflectors in the same cluster:

        RR1 (192.0.2.1)
       /   \
      /     \
   Client1  Client2
      \     /
       \   /
        RR2 (192.0.2.2)

Both RRs must use the SAME cluster ID:

# RR1 Configuration
neighbor 192.0.2.11 {
    router-id 192.0.2.1;
    local-address 192.0.2.1;
    local-as 65001;
    peer-as 65001;

    route-reflector-client;
    cluster-id 192.0.2.254;  # Same cluster ID on both RRs

    family {
        ipv4 unicast;
    }
}

# RR2 Configuration
neighbor 192.0.2.11 {
    router-id 192.0.2.2;
    local-address 192.0.2.2;
    local-as 65001;
    peer-as 65001;

    route-reflector-client;
    cluster-id 192.0.2.254;  # Same cluster ID on both RRs

    family {
        ipv4 unicast;
    }
}

Hierarchical Route Reflection

In very large networks, use hierarchical route reflection:

             Top-Level RR
            /            \
    Regional RR1      Regional RR2
    /    |    \        /    |    \
  C1    C2    C3      C4    C5    C6

Different clusters use different cluster IDs:

# Top-Level RR Configuration
neighbor 192.0.2.10 {  # Regional RR1
    router-id 192.0.2.1;
    local-address 192.0.2.1;
    local-as 65001;
    peer-as 65001;

    route-reflector-client;
    cluster-id 192.0.2.1;  # Top-level cluster ID

    family {
        ipv4 unicast;
    }
}

# Regional RR1 Configuration
neighbor 192.0.2.11 {  # Client 1
    router-id 192.0.2.10;
    local-address 192.0.2.10;
    local-as 65001;
    peer-as 65001;

    route-reflector-client;
    cluster-id 192.0.2.10;  # Regional cluster ID

    family {
        ipv4 unicast;
    }
}

Loop Prevention

Route reflectors use two BGP attributes to prevent routing loops:

ORIGINATOR_ID

The ORIGINATOR_ID is the router ID of the router that originally advertised the route into IBGP.

Loop Prevention Rule: If a router receives a route with its own router ID in the ORIGINATOR_ID, it rejects the route.

CLUSTER_LIST

The CLUSTER_LIST is a list of cluster IDs the route has traversed.

Loop Prevention Rule: If a route reflector receives a route with its own cluster ID in the CLUSTER_LIST, it rejects the route.

Example: Loop Prevention in Action

   RR1 (Cluster 192.0.2.1)
    β”‚
    β”‚ reflects route with:
    β”‚ ORIGINATOR_ID = 192.0.2.11
    β”‚ CLUSTER_LIST = [192.0.2.1]
    β–Ό
   RR2 (Cluster 192.0.2.2)
    β”‚
    β”‚ reflects route with:
    β”‚ ORIGINATOR_ID = 192.0.2.11
    β”‚ CLUSTER_LIST = [192.0.2.1, 192.0.2.2]
    β–Ό
   RR1 (Cluster 192.0.2.1)
    β”‚
    └─ REJECTS route (own cluster ID in CLUSTER_LIST)

Verifying Loop Prevention

Check ExaBGP logs for rejected routes:

tail -f /var/log/exabgp/exabgp.log | grep -i "cluster\|originator"

Best Practices

1. Use Redundant Route Reflectors

Deploy at least 2 route reflectors per cluster for redundancy:

# Client peers with both RRs
neighbor 192.0.2.1 {  # RR1
    router-id 192.0.2.11;
    local-address 192.0.2.11;
    local-as 65001;
    peer-as 65001;

    family {
        ipv4 unicast;
    }
}

neighbor 192.0.2.2 {  # RR2
    router-id 192.0.2.11;
    local-address 192.0.2.11;
    local-as 65001;
    peer-as 65001;

    family {
        ipv4 unicast;
    }
}

2. Use Consistent Cluster IDs

All route reflectors in the same cluster MUST use the same cluster ID:

# GOOD: Same cluster ID
# RR1: cluster-id 192.0.2.254
# RR2: cluster-id 192.0.2.254

# BAD: Different cluster IDs
# RR1: cluster-id 192.0.2.1
# RR2: cluster-id 192.0.2.2

3. Plan Your Cluster Hierarchy

For large networks, design a hierarchical route reflection architecture:

  • Small networks (<50 routers): Single cluster, 2+ RRs
  • Medium networks (50-500 routers): 2-3 clusters, 2+ RRs per cluster
  • Large networks (>500 routers): Hierarchical, 3+ levels

4. Monitor Route Reflector Health

Route reflectors are critical infrastructure. Monitor them carefully:

#!/usr/bin/env python3
# /etc/exabgp/rr-monitor.py

import sys
import json

client_count = 0
routes_reflected = 0

while True:
    line = sys.stdin.readline()
    if not line:
        break

    try:
        data = json.loads(line)

        if data.get('type') == 'state':
            state = data['neighbor']['state']
            peer = data['neighbor']['address']['peer']

            if state == 'up':
                client_count += 1
                sys.stderr.write(f"Client {peer} connected (total: {client_count})\n")
            elif state == 'down':
                client_count -= 1
                sys.stderr.write(f"Client {peer} disconnected (total: {client_count})\n")

        elif data.get('type') == 'update':
            routes_reflected += 1
            sys.stderr.write(f"Routes reflected: {routes_reflected}\n")

    except Exception as e:
        sys.stderr.write(f"Error: {e}\n")

5. Document Your Topology

Maintain documentation of your route reflection topology:

# route-reflection-topology.yaml

clusters:
  - cluster_id: 192.0.2.1
    name: "Core Cluster"
    route_reflectors:
      - ip: 192.0.2.1
        hostname: rr1.example.com
      - ip: 192.0.2.2
        hostname: rr2.example.com
    clients:
      - 192.0.2.11
      - 192.0.2.12
      - 192.0.2.13
      - 192.0.2.14
      - 192.0.2.15

  - cluster_id: 192.0.2.10
    name: "Regional Cluster 1"
    route_reflectors:
      - ip: 192.0.2.10
        hostname: rr-regional1.example.com
    clients:
      - 192.0.2.21
      - 192.0.2.22
      - 192.0.2.23

6. Test Failover Scenarios

Regularly test route reflector failover:

# Shutdown RR1, verify clients fail over to RR2
sudo systemctl stop exabgp@rr1

# Check client connectivity
# Clients should maintain connectivity via RR2

# Restore RR1
sudo systemctl start exabgp@rr1

7. Use Route Refresh

Enable route refresh capability to request route updates:

neighbor 192.0.2.11 {
    router-id 192.0.2.1;
    local-address 192.0.2.1;
    local-as 65001;
    peer-as 65001;

    route-reflector-client;

    capability {
        route-refresh enable;
    }

    family {
        ipv4 unicast;
    }
}

Troubleshooting

Problem: Routes Not Being Reflected

Symptoms: Clients don't receive routes from other clients.

Debugging steps:

  1. Verify route reflector client configuration:
neighbor 192.0.2.11 {
    route-reflector-client;  # Must be present
}
  1. Check BGP sessions are established:
grep "Peer.*up" /var/log/exabgp/exabgp.log
  1. Verify address families match:
# RR and clients must have matching address families
family {
    ipv4 unicast;
}
  1. Check for loop prevention rejections:
tail -f /var/log/exabgp/exabgp.log | grep -i "loop\|cluster\|originator"

Problem: Routing Loops

Symptoms: Routes loop between route reflectors, consuming bandwidth.

Solutions:

  1. Verify cluster IDs are configured:
neighbor 192.0.2.11 {
    route-reflector-client;
    cluster-id 192.0.2.1;  # Must be present
}
  1. Check cluster IDs are identical within a cluster:
# All RRs in same cluster must have same cluster-id
  1. Review hierarchical design:
# Different clusters must have different cluster IDs
# Top-level: cluster-id 192.0.2.1
# Regional:  cluster-id 192.0.2.10

Problem: Inconsistent Routes

Symptoms: Different clients receive different routes.

Debugging steps:

  1. Check route policies are consistent across RRs:
# All RRs in a cluster should have identical policies
  1. Verify all RRs are receiving the same routes:
# Enable receive-routes on RRs
neighbor-changes;
receive-routes;
  1. Check for split-brain scenario:
# Verify RRs can communicate with each other

Problem: Route Reflector Overload

Symptoms: Route reflector CPU/memory usage is high.

Solutions:

  1. Add more route reflectors:
# Distribute clients across more RRs
  1. Use hierarchical route reflection:
# Create regional clusters
  1. Optimize address families:
# Only reflect required address families
family {
    ipv4 unicast;  # Don't enable unnecessary families
}

See Also


πŸ‘» Ghost written by Claude (Anthropic AI)

Clone this wiki locally