Skip to content
LinkState
Go back

Client-to-client reflection and IX loop risk

Introduction to Route Server Reflection

Overview of Route Server Architecture

A route server (RS) is a BGP speaker that peers with multiple autonomous systems (ASes) at an Internet Exchange Point (IXP) or a private fabric but does not forward traffic itself. Its sole purpose is to distribute reachability information between its clients. The RS maintains a separate BGP session with each client, typically using the same AS number as the client (or a dedicated RS‑AS) and advertises routes received from one client to all other clients, subject to any configured import/export policies.

Key control‑plane components:

The RS does not modify the AS_PATH unless explicitly configured to prepend or strip; it simply reflects the received NLRI with the original attributes (except for those altered by policy).

Client-to-Client Reflection Mechanism

In a traditional route‑reflector (RR) scenario, the RR reflects routes between its clients only if the client is configured as a route‑reflector client and the RR does not modify the ORIGINATOR_ID or CLUSTER_LIST attributes. A route server at an IXP can be configured to behave similarly: it receives a route from Client A, runs its BGP decision process, and if the route is selected for export to Client B, it sends the route to Client B unchanged (aside from policy). This is termed client‑to‑client reflection.

The mechanism works as follows:

  1. Receipt – RS receives UPDATE from Client A, stores it in Adj‑RIB‑in[A].
  2. Import policy – RS applies any inbound route‑policy (e.g., filtering, community manipulation) to Adj‑RIB‑in[A]; the result contributes to the Loc‑RIB.
  3. Best‑path selection – RS runs the BGP decision process on the Loc‑RIB. If the route from Client A wins, it is installed in the Loc‑RIB as the best path.
  4. Export policy – RS applies outbound policy for each client (Client B, Client C, …). If the policy permits advertisement, the RS places a copy of the Loc‑RIB entry into Adj‑RIB‑out[B].
  5. Transmission – RS sends UPDATE to Client B containing the NLRI and the original path attributes (AS_PATH, NEXT_HOP, etc.) as they appeared in the Loc‑RIB, subject to any attribute changes made by export policy (e.g., MED adjustment, community addition).

If the RS is configured to reflect all routes (no restrictive import/export policy), every route learned from any client is potentially advertised to every other client, creating a full‑mesh of reachability without the need for each peer to peer with every other peer directly.

Route Server Reflection and Circulation Paths

How Client-to-Client Reflection Creates Circulation Paths

A circulation path (sometimes called a “routing loop” or “persistent oscillation”) occurs when a route is advertised back to its originator after traversing one or more intermediate ASes, causing the originator to see its own prefix with an altered AS_PATH. In a pure client‑to‑client reflection scenario, the RS itself does not forward traffic, but the reflected routes can cause forwarding loops in the data plane if the following conditions hold:

  1. AS_PATH preservation – The RS does not modify the AS_PATH when reflecting. If Client A originates prefix P with AS_PATH = [65001], the RS advertises P to Client B with the same AS_PATH.
  2. Lack of loop‑prevention attributes – BGP’s loop detection relies on seeing the local AS number in the AS_PATH. If Client B is in AS 65002 and receives P with AS_PATH [65001], it will install the route and may forward traffic toward AS 65001. If AS 65001 (Client A) also receives a reflected route from the RS that now shows AS_PATH [65002 65001] (because the RS reflected a route that Client B had previously re‑advertised with its own AS prepended), a loop can form.
  3. Multihop redistribution – If any client redistributes the reflected route into another protocol (e.g., OSPF, IS‑IS) and later redistributes it back into BGP with a different AS_PATH, the RS may see a route with an AS_PATH that does not contain its own AS, causing it to reflect again.

The control‑plane trace for a simple two‑client loop:

Thus, circulation paths arise when reflected routes are allowed to travel back toward their originator and the originator’s loop‑prevention logic is bypassed or weakened by policy.

Exchange Fabric Topology and Reflection

At an IXP, the physical topology is typically a full‑mesh of layer‑2 connections (or a switched fabric) where each member connects to a common switch fabric. The route server sits outside the data plane, connected via a dedicated link or VLAN to each member’s router. Logically, the RS sees a star topology: each client is a leaf, the RS is the hub.

When reflection is enabled, the logical routing topology becomes a full‑mesh among clients via the RS:

Potential circulation paths manifest when:

Identifying Unexpected Circulation Paths

Operators should look for symptoms that indicate a route is being seen with an abnormal AS_PATH or that flapping is occurring:

A systematic approach:

  1. Capture BGP updates at the RS (monitor traffic or log updates) for the suspect prefix.
  2. Correlate timestamps with updates seen at each client.
  3. Trace the AS_PATH evolution: original AS_PATH → after RS reflection → after client re‑advertisement → after second RS reflection.
  4. Check policy logs: verify whether any import/export policy accepted or modified the route unexpectedly.

Debugging Route Server Reflection

Debugging steps vary by vendor but share a common core:

# Juniper
set protocols bgp traceoptions file bgp-reflect size 10m files 3
set protocols bgp traceoptions flag update
set protocols bgp traceoptions flag state
# Cisco IOS-XR
debug bgp updates
debug bgp neighbor <ip> updates
# Juniper
show route receive-protocol bgp <client-ip> <prefix>
show route advertising-protocol bgp <client-ip> <prefix>
# Cisco IOS-XR
show bgp <prefix>
show bgp neighbors <ip> advertised-routes
# Juniper
show configuration policy-options | display detail
show policy <policy-name> statistics
# Cisco IOS-XR
show route-policy <name> statistics
# Juniper
show bgp neighbor <ip> received-routes | match <prefix>
# Look for "Loop detected" in the output
# Nokia SR OS
show router bgp routes <prefix> detail

Policy Boundaries for Controlling Reflection

Route Server Configuration Options

Most RS implementations provide granular knobs to limit what gets reflected:

Implementing Policy Boundaries to Prevent Loop Amplification

To keep reflection from becoming a loop amplifier, apply the following policy layers:

  1. Strict inbound filtering at the RS
    • Drop any route that does not originate from a legitimate member (verify via IRR or RPKI).
    • Drop routes with AS_PATH lengths exceeding a reasonable threshold (e.g., >10) to prevent pathological prepending.
  2. Enforce AS_PATH loop check on export
    • Configure the RS to not advertise a route to a client if the client’s AS number appears anywhere in the AS_PATH.
    • Example (Juniper):
    policy-options {
        statement rs-export {
            term prevent-loop {
                from {
                    as-path [ ".*" ]; # match any
                }
                then {
                    if (as-path-contains $routing-instance.autonomous-system) {
                        reject;
                    }
                }
            }
            term accept {
                then accept;
            }
        }
    }
    protocols bgp group route-server {
        export rs-export;
    }
    • Similar constructs exist in Cisco IOS-XR (route-policy) and Nokia SR OS (policy-statement).
  3. Limit reflection to best‑path only
    • Many RS platforms have a reflect-only-best flag. Enabling this ensures that if a client receives a better path via another medium (e.g., private peering), the RS will not re‑advertise a worse path that could cause flapping.
  4. Use communities to signal non‑reflectability
    • Members can attach a well‑known community (e.g., NO_EXPORT, NO_ADVERTISE) or a private community (65000:999) to indicate that a route must not be reflected.
    • RS export policy checks for the community and drops the route:
    # Juniper
    term no-reflect {
        from {
            community [ NO_REFLECT ];
        }
        then reject;
    }
  5. Separate RS instances for different customer classes
    • If an IXP hosts both transit and content networks, run separate RS clusters (or separate RS processes) with distinct export policies to prevent transit routes from being reflected to content networks where they might be re‑advertised with different AS_PATHs.
  6. Monitor and enforce RS‑to‑RS peering policies
    • If multiple RS instances are used for redundancy, ensure they do not reflect routes between each other unless explicitly desired. Use a distinct AS number for the RS‑to‑RS peering and apply strict import/export filters (often just a default‑drop).

By combining these boundaries, the RS acts as a controlled mirror: it only forwards routes that have passed origin validation, loop checks, and intent‑based filters, preventing the amplification of malformed or looping updates.


Share this post on:

Previous Post
Aging out zombie inventory with last-seen signals
Next Post
Rollback plans need their own gates