BGP · · 4 min read

How BGP Works: Peers, Updates, and the Finite State Machine

BGP peering does not auto-discover. Every session is deliberately configured, runs over TCP port 179, and walks a strict finite state machine before a single route flows. The foundation you need before touching BGP config.

How BGP Works: Peers, Updates, and the Finite State Machine - PingLabz BGP article title card

BGP doesn't discover neighbors automatically like OSPF does with multicast hellos. Every BGP peering session is deliberately configured, runs over a TCP connection on port 179, and progresses through a strict finite state machine before a single route is exchanged. Understanding this process is the foundation for everything else in BGP - from configuration to troubleshooting.

New to BGP? Start with the full BGP guide, then come back here for the deep dive.

TCP - BGP's Transport

BGP is the only major routing protocol that runs over TCP. This gives it reliable, ordered delivery without needing to build that into the protocol itself. When two BGP speakers are configured to peer, one initiates a TCP connection to port 179 on the other. The three-way TCP handshake (SYN, SYN-ACK, ACK) must complete before any BGP messages flow.

This has practical implications: firewalls and ACLs must permit TCP/179 in both directions. If you're peering over a transit link, the source IP must match the configured neighbor address exactly. Mismatches here are the number one cause of peers stuck in Active state - more on that in Troubleshooting BGP Neighbor Adjacency Issues.

The BGP Finite State Machine

Once the TCP session is attempted, each BGP speaker tracks the peer's state through six stages:

1. Idle

The router has a neighbor configured but hasn't started connecting. BGP initializes resources and waits for a Start event (administrative enable or retry timer expiry). If something goes wrong at any later stage, the peer drops back to Idle and a ConnectRetry timer starts.

2. Connect

The router is actively attempting the TCP three-way handshake to port 179 on the peer. If TCP connects successfully, the router sends a BGP OPEN message and moves to OpenSent. If the TCP connection fails, the router moves to Active.

3. Active

The router is retrying the TCP connection. Despite the name, Active is actually a problem state - it means the TCP handshake keeps failing. Common causes: wrong neighbor IP, ACL blocking TCP/179, interface down, or a routing issue preventing reachability to the peer address.

4. OpenSent

TCP is established and the local router has sent its OPEN message. It's waiting for the peer's OPEN in return. If the peer's OPEN is acceptable (matching AS numbers, compatible capabilities), the router sends a KEEPALIVE and moves to OpenConfirm. If the OPEN is rejected (wrong AS, bad parameters), a NOTIFICATION is sent and the peer drops to Idle.

5. OpenConfirm

Both OPEN messages have been exchanged and accepted. The router is waiting for a KEEPALIVE from the peer to confirm the session. Once received, the state moves to Established.

6. Established

The session is up. UPDATE messages carrying NLRI (routes) begin flowing. KEEPALIVE messages maintain the session at regular intervals (default every 60 seconds). If the hold timer expires (default 180 seconds - three missed keepalives), the session tears down with a NOTIFICATION and returns to Idle.

BGP Message Types

BGP uses four message types (detailed in BGP Message Types: OPEN, UPDATE, KEEPALIVE, and NOTIFICATION):

OPEN
Purpose
Negotiate session parameters (ASN, hold time, router ID, capabilities)
When SentAfter TCP connects
UPDATE
Purpose
Advertise new prefixes or withdraw previously advertised ones
When Sent
After Established state
KEEPALIVE
Purpose
Confirm the peer is alive
When SentEvery 60s by default
NOTIFICATION
Purpose
Signal an error and tear down the session
When SentOn error condition

A prefix that keeps going away and coming back produces a stream of UPDATE and withdraw messages, and that churn is what route dampening was invented to suppress - a feature still sitting in the IOS XE CLI that most operators now deliberately leave switched off.

BGP Tables: Adj-RIB-In, Loc-RIB, Adj-RIB-Out

Each BGP speaker maintains three conceptual tables per address family:

  • Adj-RIB-In: All routes received from a specific peer, before any inbound policy is applied. View with show ip bgp neighbors [ip] received-routes.
  • Loc-RIB: The main BGP table after inbound policy and best path selection. This is what show ip bgp displays. Only the best path (marked with >) is installed in the routing table.
  • Adj-RIB-Out: Routes advertised to a specific peer after outbound policy. View with show ip bgp neighbors [ip] advertised-routes.

The flow is: Adj-RIB-In → inbound route-map/filter → best path selection → Loc-RIB → outbound route-map/filter → Adj-RIB-Out. Understanding this pipeline is essential for troubleshooting why a route isn't being advertised or received - a topic we cover extensively in Troubleshooting BGP Route Advertisement Problems.

The best path selection stage in the middle of that pipeline is where most of the surprises live, because it is a 13-step tiebreak that stops at the first step producing a winner and never consults anything below it. All 13 steps walked on real output shows which of them a normal topology ever actually reaches.

Get the BGP Field Reference - 9 pages, free

Everything you'd want to remember about BGP on nine printable pages. FSM diagram, all 13 best-path steps with gotchas, troubleshooting decision tree, copy-paste IOS XE templates, and real lab captures. Free for PingLabz members - just sign up with your email.

Get the BGP cheat-sheet

Verifying BGP on IOS XE

On our PingLabz BGP Lab, R1-HQ (AS 65001) peers with ISP-A-PE1 (AS 65010). Here's what a healthy session looks like:

R1-HQ# show ip bgp summary
BGP router identifier 1.1.1.1, local AS number 65001
BGP table version is 24, main routing table version 24
12 network entries using 2976 bytes of memory
14 path entries using 1792 bytes of memory
4/3 BGP path/bestpath attribute entries using 1088 bytes of memory
2 BGP AS-PATH entries using 64 bytes of memory

Neighbor        V   AS   MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
203.0.113.1     4   65010    1842    1756       24    0    0 1d02h          8
10.1.1.2        4   65001     945     948       24    0    0 1d02h          4

The State/PfxRcd column shows a number - that means the session is Established and the peer has sent that many prefixes. If you see a state name (Active, OpenSent, Idle) instead of a number, the session isn't up.

R1-HQ# show ip bgp neighbors 203.0.113.1 | include state
  BGP state = Established, up for 1d02h
  BGP table version 24, neighbor version 24/0

Key Takeaways

  • BGP runs over TCP port 179 - both sides must be reachable and firewalls must permit the traffic bidirectionally.
  • The six-state FSM (Idle → Connect → Active → OpenSent → OpenConfirm → Established) tells you exactly where a session is failing.
  • A peer stuck in Active means the TCP handshake is failing - check reachability, ACLs, and source IP matching.
  • BGP maintains three tables per peer: Adj-RIB-In (received), Loc-RIB (best paths), and Adj-RIB-Out (advertised).
  • In show ip bgp summary, a number in State/PfxRcd means the session is healthy; a state name means it's not.

Read next

Terminal card showing a repeating CDP native VLAN mismatch log naming Ethernet0/0 native VLAN 1 against SW2 Ethernet0/0 native VLAN 99
VLANs ·

Native VLAN Mismatch: Read the CDP Log, Fix the Trunk

%CDP-4-NATIVE_VLAN_MISMATCH hands you both interfaces and both native VLANs in one line. The real damage is underneath it: untagged frames get re-homed at the trunk boundary and two VLANs quietly become one. Captured live on IOS XE 17.18.2 in CML.