BGP Neighbor Flapping: Root Causes and Fixes - 夜莺博客

BGP Neighbor Flapping: Root Causes and Fixes

A flapping BGP session is never a local problem: every reset withdraws and re-advertises prefixes, triggering CPU spikes on every peer in the AS — and in iBGP route-reflector topologies, one unstable client can ripple across the whole network. This article breaks down the layered causes of BGP neighbor flapping (physical link issues, timer misconfiguration, hardware/software faults, authentication and policy problems), explains what each BGP state tells you, and provides a structured diagnosis and hardening checklist you can apply on any vendor.

The reason flapping deserves its own playbook is the damping behaviour it triggers. Policy-based route dampening, BGP's own update pacing, and conservative default timers all punish a peer that resets repeatedly: instead of a few seconds of instability you get minutes of suppression, and the peer that flaps is often the least important one in the topology. Getting to the root cause quickly is worth more than any amount of tuning.

Why BGP Sessions Flap

  • Network layer: intermittent interface flaps, packet loss on congested paths (three missed Keepalives expire the Hold Timer), route recursion breaking the next hop, MTU mismatches silently dropping large UPDATE packets, or WAN instability for eBGP peers.
  • Timer misconfiguration: mismatched Hold Timers, overly aggressive Keepalive intervals, short ConnectRetry timers that trigger remote route dampening, or sub-second BFD falsely declaring peers dead on high-latency links.
  • Hardware/software: saturated router CPU missing Keepalives, memory exhaustion on full-table feeds, BGP process bugs, marginal SFPs causing CRC errors, and stale sessions after NSF/NSR failovers.
  • Authentication & policy: MD5/TCP-AO password mismatch on one side, malformed outbound policies stripping mandatory attributes (AS_PATH, NEXT_HOP), exceeded maximum-prefix limits, and GTSM TTL mismatches.

Two of these deserve extra attention because they masquerade as something else. An MTU black hole looks exactly like a mid-session random reset: the session establishes fine with small OPEN and KEEPALIVE messages, then dies the first time a full routing table needs a large UPDATE carried in a single TCP segment. And a maximum-prefix limit that is set too low produces a perfectly healthy session that tears itself down at a predictable interval, roughly the time it takes the peer to send one prefix too many.

Reading the BGP State Machine

The state a neighbour is stuck in narrows the fault to a layer before you log into a single device:

State What it means
Idle Not connecting — often auth failure, policy error, or max-prefix exceeded
Connect TCP SYN sent — routing or firewall blocking port 179
Active Most common stuck state — IP unreachable, wrong peer IP, ACL blocking
OpenSent/OpenConfirm OPEN exchange failing — MTU, AS mismatch, auth mismatch
Established then drop Keepalive timing or link quality problem

The most useful distinction is between never-Established and Established-then-dropped. The first is a configuration or reachability problem that will reproduce every time; the second is a transport or resource problem that is intermittent by nature. If a neighbour reaches Established and then drops after roughly a fixed number of seconds, work out what that interval is - it is usually the Hold Timer expiring (roughly 3× the Keepalive interval), and that tells you the KEEPALIVE path is broken even though the session came up.

Observed interval Likely cause
Immediate, every attempt Auth mismatch, AS mismatch, ACL/firewall on 179, wrong peer address
~3 × Keepalive seconds, repeating One-way reachability, packet loss, MTU on large UPDATEs, CPU starvation
Random, correlated with traffic peaks Congestion, buffer drops, QoS policer, undersized link
After a specific number of prefixes maximum-prefix threshold exceeded
Correlated with a link error counter Physical layer - SFP, cable, patch panel, optic budget
After every config commit or reload NSF/NSR, GR, or policy ordering issue

Timers, Keepalives and Hold Time Maths

BGP's default timers are deliberately conservative and are the right starting point: a Hold Time of 180 seconds with a Keepalive interval of 60 seconds. The session is declared dead after the Hold Timer expires, which happens when three consecutive KEEPALIVE messages are missed at the default ratio. That means a single lost packet should never take a session down - loss has to be sustained for nearly a full minute.

If a session is dropping with default timers, the underlying problem is severe, and shortening the timers is not a fix; it is a way to make the outages more frequent. The correct direction is the opposite: fix the transport, or move liveness detection to BFD with proper multiplier tuning, and leave the BGP timers alone.

! Cisco IOS / IOS-XE - review current values before changing anything
router bgp 65001
 neighbor 10.0.0.1 remote-as 65002
 neighbor 10.0.0.1 timers 10 30
!
! The negotiation rule: the LOWER Hold Time wins on both sides,
! and the Keepalive interval must be <= one third of the Hold Time.

The negotiation rule catches people out. BGP negotiates the minimum Hold Time of the two peers, but each side sends Keepalives at its own configured interval. Configuring 10/30 on one side and leaving 60/180 on the other produces a session that dies on the 10/30 device's schedule while the other side never sees a problem. Always set timers symmetrically, and document them.

Diagnosis Checklist

show bgp neighbors <peer-IP>          # Last Reset reason
ping <peer-IP> repeat 1000 source <local-IP>   # extended ping, any loss?
show logging | include BGP           # correlate timestamps

Start with the "Last reset" line, because Cisco records the exact reason string. A few of the most informative values:

show bgp neighbors 10.0.0.1 | include "Last reset|BGP state|hold time|keepalive"
show bgp neighbors 10.0.0.1 | include "Notification|reason"

! Common reason strings and what they point at
! "Peer closed the session"        -> remote side tore it down (check the far end first)
! "Hold Timer Expired"             -> keepalives not arriving; transport or CPU
! "Notification received"          -> read the notification code below
! "Administratively Shutdown"      -> neighbor shutdown on the far end
! "Maximum Prefix Limit"           -> raise the limit or fix the advertisement
! "TCP Connection Failed"          -> port 179 unreachable, routing, ACL
! "BGP Notification sent"          -> WE sent the error; look at the code we sent

The notification code is the single most diagnostic value BGP produces. Code 2 (Open Message Error) with subcode 2 is a bad peer AS; subcode 7 is an unacceptable Hold Time; subcode 5 is an authentication failure. Code 4 (Hold Timer Expired) means the transport died. Code 6 (Cease) with subcode 2 is a maximum-prefix shutdown. Once you have the code, the fault is usually obvious.

Then work through the layers:

  • Verify Hold Timer and Keepalive match on both peers.
  • Inspect interface error counters for CRC and input errors - show interfaces twice, five minutes apart.
  • Test path MTU with large DF-bit pings, and check whether the UPDATE size correlates with the flap.
  • Confirm MD5/TCP-AO passphrases match exactly, including on both address families.
  • Check and raise maximum-prefix limits, and watch which prefix pushes it over.
  • Monitor CPU and memory during the flap - a router that misses Keepalives under load is a capacity problem, not a BGP problem.
  • On high-latency or jittery links, relax BFD timers or disable BFD while isolating the issue.

Two more commands that resolve most remaining cases:

! What exactly is being reset, and how often?
show bgp all summary
show bgp neighbor 10.0.0.1 | include "Connections established|dropped|Reset"

! Debugging - use with extreme care on a production router
debug bgp neighbor-events
debug bgp keepalives
debug ip bgp updates prefix-list FLAP_TEST

Vendor-Specific Diagnostics

The concepts are universal but the commands are not. Keep a short set per platform in your runbook:

# Cisco IOS-XE
show bgp neighbors 10.0.0.1
show bgp all summary
show logging | include %BGP

# Juniper Junos
show bgp neighbor 10.0.0.1
show bgp summary
show log messages | match bgp

# Arista EOS
show bgp neighbors 10.0.0.1
show bgp summary
show logging | grep BGP

# FRRouting on Linux
vtysh -c "show bgp neighbor 10.0.0.1"
vtysh -c "show bgp summary"
journalctl -u frr | grep bgp

BFD, GTSM and Route Dampening Interactions

Three mechanisms designed to protect you can also cause the flap you are chasing.

BFD is the fastest and the riskiest. A BFD interval of 50ms with a multiplier of 3 declares a peer dead after 150ms of loss, which is well below the jitter of a congested WAN or a software-forwarded platform under load. On any link you do not own end to end, start with 300ms × 3 and tighten only with evidence. Also confirm BFD is not running over a path with different fate than the BGP TCP session - if BFD traverses a different link than the session's next hop, you can declare dead a peer that is perfectly reachable.

GTSM (Generalized TTL Security Mechanism, RFC 5082) validates that inbound BGP packets carry a TTL of 254 or 255, meaning they were sent by a directly connected peer. It is a strong anti-spoofing measure, but a single hop of additional distance - a route reflector one hop away, an intermediate device, or a multi-hop session - drops the packet and the session fails instantly and repeatedly. State it explicitly: GTSM on eBGP single-hop sessions only.

Route dampening does not cause the flap, but it converts one into a long outage. A peer that resets a few times in quick succession gets its routes suppressed for a penalty half-life that starts at 15 minutes. If a prefix is flapping while you investigate, consider suspending inbound dampening on the affected peer so that recovery is immediate once the root cause is fixed.

Structural Fixes That Prevent Flaps

Some flapping is architecture, not tuning. These changes remove whole classes of instability:

  • Peer iBGP over loopbacks, never physical interfaces. A loopback survives link failures, card changes and RMA events; a session bound to a physical port has a hard dependency on that port.
  • Never let BGP depend on a single uplink's fate. Where a peer has two paths, make sure the BGP session is not pinned to one of them.
  • Give the control plane headroom. A device receiving a full table needs enough memory and CPU to process updates and answer Keepalives on time; a control-plane policer that drops BGP traffic under load is a self-inflicted outage.
  • Prefer route reflectors or confederations to a full mesh so that one flapping client cannot reset every session in the AS.
  • Separate the control plane from the data plane path in policy. Ensure BGP traffic is not caught by a QoS policer or ACL that was sized for data.

Prevention Best Practices

Peer iBGP over loopbacks, enable Graceful Restart (RFC 4724) and NSR where supported, apply route dampening judiciously (RFC 7196), use default timers on stable links, test route policies in the lab before production, keep software patched, and monitor bgpBackwardTransition traps with real-time alerting. For related routing-protocol troubleshooting, see our OSPF neighbor stuck in INIT article, the Nexus vPC failover checklist, and the multi-vendor CLI cheat sheet.

Finally, alert on the pattern rather than the event. A single bgpBackwardTransition at 04:00 during a planned maintenance window is noise; three within an hour is a trend, and five within an hour is an incident. Tune your trap handling to separate the two, and you will catch the next real flap long before it becomes a page.

FAQ

Can a BGP session flap without the underlying link flapping? Yes, and this is the common case. A session can die while the interface stays up: MTU black holes, control-plane CPU exhaustion, TCP retransmission timeouts, and authentication changes all do it.

Should I shorten BGP timers to detect failures faster? Generally no. Use BFD for fast failure detection and leave BGP timers at their defaults (or at least at symmetric, documented values). Short BGP timers convert transient loss into session resets.

Why does one side show "Peer closed the session" while the other shows a notification code? The side that sent the notification is the side that detected the fault; the side that received it logs "Peer closed the session". Always read both ends.

What does "Maximum Prefix Limit" in the reset reason mean? The peer advertised more prefixes than the configured maximum-prefix allows, and the local router tore down the session as protection. Either raise the limit deliberately or investigate why the peer is advertising more routes than expected.

Is route dampening still recommended? Sparingly. Modern practice (RFC 7196) leans toward less aggressive damping, or none, combined with good monitoring and a curated prefix list. Damping an unstable peer's legitimate prefixes is often worse than the instability itself.

Do the diagnosis in the order above - state, reset reason, notification code, interface counters, timers - and you will reach the root cause in minutes rather than hours. Nearly every "BGP is flapping" ticket ends up being a physical layer, an MTU value or a policy counter, not BGP itself.

原文链接:https://www.thenetworkdna.com/2026/03/bgp-neighbor-flapping-issues.html