Skip to content
LinkState
Go back

Rolling next-hop-self without creating hidden blackholes

Introduction

Next‑hop‑self (NHS) and reflection policies are BGP control‑plane knobs that change the next‑hop attribute for routes a router originates or reflects. In IP‑Clos, EVPN‑VXLAN, or segment‑routing fabrics, altering NHS can switch the dataplane path for traffic that traverses the fabric. A mis‑configured NHS/reflection rule can create a control‑plane‑correct but dataplane‑broken state: the RIB looks valid, yet the FIB fails to install the expected next‑hop, causing black‑holes or loops.

Before exposing the entire fabric to a new NHS/reflection setting, each change must be validated at two independent layers:

  1. Recursive reachability – the route’s next‑hop resolves via IGP/SR‑TE to an actual outgoing interface.
  2. FIB install success – the resolved next‑hop is programmed into the forwarding ASIC or software dataplane.

If either check fails, the change must be halted before it propagates further, limiting blast‑radius to a controlled segment.


Designing the Staged Rollout Process

1. Identify Gateways and Fabric Segments

2. Rollout Schedule and Sequence

PhaseActionScopePre‑checkCommit BoundaryVerification GateRollback TriggerOperator Intervention
0Baseline captureAll devicesVerify current NHS/reflection, recursive reachability, FIB install–––Review baseline docs
1Gateway‑ASingle gatewayIGP/SR‑TE stability, no flapsApply NHS/reflection via config‑replaceRecursive reachability + FIB install on gateway‑ALoss of reachability or FIB miss > 5 sManual abort if verification fails
2Gateway‑B (peer)Second gateway in same podSame pre‑checkApply changeSame verificationSame triggerManual abort
3Pod‑wideAll leaf/spine in podVerify no new flaps from previous gatesPush change via orchestrator (Ansible, Nornir, etc.)Recursive reachability + FIB install on 10 % sample>2 % sample failsPause, investigate
4Fabric‑wideRemaining pods sequentiallySame pre‑check per podPush changeSame verification on each podSame trigger per podPause per pod
5Cut‑overAll devicesFinal global sanity check–Global verification (see Monitoring)N/ASign‑off

Commit boundary – point where configuration is written to running‑config (commit in Junos, write memory in IOS‑XR, etc.).
Verification gate – occurs after the commit but before the change is advertised to peers.

3. Implementing Rollback Mechanisms for Failed Gates


Verifying Recursive Reachability

Understanding Recursive Reachability

Recursive reachability means a route’s next‑hop address is itself reachable via the underlying IGP (or SR‑TE) topology. For BGP, the next‑hop is often a loopback; the IGP must have a valid path to that loopback. If the IGP path disappears, the BGP route becomes unusable even though the BGP table shows it.

Tools and Techniques

Tool/TechniqueWhat it ShowsGate Usage
show ip route <next-hop> (IOS‑XR)Recursive resolution of a specific next‑hopVerify IGP‑derived path with valid outgoing interface.
show route <next-hop> detail (Junos)Recursive path, metric, outgoing interfaceLook for * indicating active route.
show fib route <next-hop> (EOS)FIB entry for the next‑hop (if installed)Confirms IGP path is programmed.
Telemetry (gNMI/YANG) – ietf-routing:routing-state/ribProgrammatic retrieval of recursive routesPull via script; evaluate source-protocol and next-hop.
Ping/Traceroute from device to next‑hopEnd‑to‑end L3 reachabilityUse ping <next-hop> repeat 3 and traceroute <next-hop>.

Example CLI Commands

Cisco IOS‑XR

# Pre‑check: ensure IGP stability
show ospf neighbor | include Full
show isis neighbor | include Up

# Verify recursive reachability for candidate next-hop (e.g., 10.0.0.1)
show ip route 10.0.0.1

Expected snippet:

Routing entry for 10.0.0.1/32
  Known via "ospf 1", distance 110, metric 20, type intra area
  Last update from 10.0.0.2 via GigabitEthernet0/0/0/1, 00:00:12 ago
  Routing Descriptor Blocks:
  * 10.0.0.2, from 10.0.0.2, via GigabitEthernet0/0/0/1, route-metric 20, traffic share count 1

Juniper Junos

# Pre‑check: IS‑IS adjacency
show isis adjacency | match Up

# Recursive reachability check
show route 10.0.0.1 detail

Look for:

10.0.0.1/32      *[IS-IS/18] 00:00:10, metric 20
                 > to 10.0.0.2 via ge-0/0/1.0

Arista EOS

# Pre‑check: OSPF/EIGRP status
show ip ospf neighbor
show ip eigrp neighbors

# Recursive reachability
show ip route 10.0.0.1

Expected:

O        10.0.0.1/32 [110/20] via 10.0.0.2, Ethernet1

Verifying FIB Install Success

Understanding FIB Installation

The Forwarding Information Base (FIB) is the hardware‑accelerated table used for packet forwarding. A route may reside in the RIB but be absent from the FIB due to TCAM exhaustion, incorrect next‑hop type, or ASIC‑specific programming errors (e.g., missing encapsulation for SR‑TE). Verifying FIB install ensures the control‑plane decision is actually enforced in the dataplane.

Methods for Verification

MethodDescriptionTypical Output
show fib route <prefix> (IOS‑XR/Junos/EOS)Direct FIB lookup* if installed, or Not present if missing.
show platform software fed switch <num> fwd-table (Cisco Catalyst)ASIC‑level viewHardware entry count.
gNMI get on ietf-interfaces:interfaces/state/statistics + ietf-routing:routing-state/ribTelemetry‑based verificationJSON with fib-entry flag.
Packet‑in counters (show monitor session)Detects packets punted to CPU due to missing FIBNon‑zero punt counters indicate FIB miss.
BGP show bgp neighbors <ip> advertised-routes + show ip cefCorrelates RIB vs FIBEnsure advertised route appears in CEF/FIB.

Automation Examples

Python (Nornir + Netmiko) – IOS‑XR

from nornir import InitNornir
from nornir_netmiko.tasks import netmiko_send_command
from nornir_utils.plugins.functions import print_result

nr = InitNornir(config_file="config.yaml")

def check_fib(task, prefix):
    cmd = f"show fib route {prefix}"
    result = task.run(task=netmiko_send_command, command_string=cmd)
    fib_output = result.result
    if prefix in fib_output and "via" in fib_output:
        task.host["fib_ok"] = True
    else:
        task.host["fib_ok"] = False

gateways = nr.filter(F=F(groups__contains="gateway"))
result = gateways.run(task=check_fib, prefix="10.0.0.0/24")
print_result(result)

if any(not h["fib_ok"] for h in gateways.inventory.hosts.values()):
    raise SystemExit("FIB install failed on one or more gateways")

Ansible Playbook – Junos

- name: Verify FIB install for NHS change
  hosts: gateway
  gather_facts: false
  vars:
    prefix: 10.0.0.0/24
  tasks:
    - name: Retrieve FIB entry
      juniper.junos.junos_command:
        commands:
          - "show route {{ prefix }} detail"
      register: fib_out

    - name: Parse output for active route
      set_fact:
        fib_ok: "{{ fib_out.stdout[0] | regex_search('\\* ' + prefix) }}"

    - name: Fail if FIB missing
      fail:
        msg: "FIB install failed for {{ prefix }} on {{ inventory_hostname }}"
      when: not fib_ok

Troubleshooting Common Issues

Recursive Reachability Problems

SymptomLikely CauseDiagnostic StepsFix
show ip route <next-hop> returns % Network not in tableIGP missing route to next‑hop (loopback)Verify IGP adjacency (show ospf neighbor, show isis adjacency). Look for area mismatches or auth failures.Restore IGP adjacency (fix timers, auth, duplicate addresses).
Next‑hop resolves via a blackhole or discard routeMis‑configured static route or aggregateshow ip route <next-hop> shows * with discard.Remove or correct the offending static/aggregate.
Recursive path flaps every few secondsLink instability or BGP‑induced IGP feedbackMonitor interface counters (show interfaces) and IGP logs.Stabilize physical layer, adjust BGP hold‑timers, enable IGP‑BGP isolation (bgp bestpath med missing-as-worst).
Ping to next‑hop succeeds but route still shows unresolvedAsymmetric routing or VRF leakageCheck VRF context (show ip vrf) and ensure next‑hop lookup is in correct VRF.Place NHS configuration under correct VRF or adjust route‑targets.

FIB Install Failures

SymptomLikely CauseDiagnostic StepsFix
show fib route <prefix> returns Not present while RIB shows entryTCAM exhaustionCheck show platform hardware fed switch <num> fwd-table usage or show resources.Summarize/aggregate prefixes, enable FIB compression, or upgrade line card.
FIB entry shows incorrect next‑hop (e.g., 0.0.0.0)Next‑hop unresolved due to recursive failureCross‑check with recursive reachability output.Fix recursive reachability first; FIB will update automatically.
Packets punted to CPU increase after change (show monitor session)ASIC cannot encapsulate SR‑TE or MPLS labelVerify platform capabilities (show capabilities).Disable offending feature (e.g., SR‑TE) or use compatible line card.
FIB entry present but traffic black‑holedIncorrect egress interface (e.g., mis‑programmed ASIC)Verify egress interface in FIB entry; compare with expected interface.Re‑apply NHS/reflection after correcting ASIC programming or reload line card.

End of document.


Share this post on:

Previous Post
Finding a one-segment outage in green dashboards
Next Post
Git as audit trail, SoT as live model