Established, but wrong
An Established session can still fail you in two ways: it can keep dropping, or it can stay up while carrying the wrong routes. The prefix counts in the summary are the first clue for the second kind, so know your normal numbers.
The hold timer expires
Every BGP session agrees a hold time: if nothing arrives from the peer for that long, the session is declared dead. Routers send KEEPALIVEs (by default every 60 seconds, with a 180-second hold time in FRR's traditional profile) to stop that happening when there are no updates.
To make it quick, both ends here use timers 5 15: keepalives every 5 seconds, hold time 15. Then a firewall on r2 drops everything to and from r1. Fourteen seconds later r1 gives up with NOTIFICATION 4/0, Hold Timer Expired, and goes back to trying to connect.
In production, a session that drops every few minutes with Hold Timer Expired means keepalives are being lost on a path that otherwise works: a congested or policed link, a control plane too busy to send them, or an MTU problem that drops large UPDATEs. Shorter timers detect failures sooner but make sessions more fragile; Bidirectional Forwarding Detection (BFD) is the better tool for fast failure detection.
No policy, no routes
The session is up and both sides agree on everything, but the summary shows (Policy) where the prefix counts should be. By default, FRR exchanges no routes at all on an eBGP session with no import or export policy, following RFC 8212, which made this the safe default after years of accidental route leaks. The neighbour detail says Inbound updates discarded due to missing policy, and r2's side shows it's sending 4 and receiving 0.
The fix is a route-map in each direction, even one that permits everything, if that's genuinely your policy.
Your own filter
r1's import prefix-list gains a line that denies 198.51.100.64/26. The summary now shows 3 prefixes received instead of 4, and nothing else looks wrong. This is where soft-reconfiguration inbound pays for itself:
received-routesis what the peer actually sent, before your policy: all 4, and it even says 1 filtered.routesis what survived your policy: 3.
A prefix in the first list but not the second was dropped by your own import policy. A prefix in neither list was never sent, so the conversation is with the peer's export policy. (clear bgp … soft in re-runs the import policy against the stored copy, without resetting the session.)
The next hop nobody can reach
r2 stops setting next-hop-self towards r3. r3 still receives 203.0.113.0/24 over iBGP, but with r1's address, 192.0.2.0, as the next hop, because iBGP passes the next hop on unchanged. r3 has no route to 192.0.2.0/31, so the path is marked inaccessible. It's in the BGP table, but it's not valid, not best, not installed and not passed on.
This is the classic iBGP mistake. Either set next-hop-self on the border router, or carry the external link addresses in the IGP. show bgp nexthop lists every next hop BGP is tracking and whether it resolves.
r1:~# vtysh -c "show bgp neighbors 192.0.2.1" | grep -E "BGP state|Hold time|keepalive interval|Last read"
BGP state = Established, up for 00:00:06
Last read 00:00:01, Last write 00:00:01
Hold time is 15 seconds, keepalive interval is 5 seconds
Configured hold time is 15 seconds, keepalive interval is 5 seconds
r2:~# date "+%H:%M:%S firewall now drops everything to and from r1"
03:46:16 firewall now drops everything to and from r1
r1:~# grep -E "ADJCHANGE|NOTIFICATION|Hold Timer|hold timer" /var/log/frr/frr.log | tail -3
2026/10/18 03:46:10 BGP: [N9HHH-F8H1M] %ADJCHANGE: neighbor 192.0.2.1(r2) in vrf default Up
2026/10/18 03:46:30 BGP: [HZN6M-XRM1G] %NOTIFICATION: sent to neighbor 192.0.2.1 4/0 (Hold Timer Expired) 0 bytes
2026/10/18 03:46:30 BGP: [PXVXG-TFNNT] %ADJCHANGE: neighbor 192.0.2.1(r2) in vrf default Down BGP Notification send
r1# show bgp summary
IPv4 Unicast Summary:
BGP router identifier 198.51.100.241, local AS number 64500 VRF default vrf-id 0
BGP table version 17
RIB entries 3, using 384 bytes of memory
Peers 1, using 17 KiB of memory
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc
192.0.2.1 4 64501 14 17 0 0 0 00:00:05 Connect 0 r2
Total number of neighbors 1
r1:~# vtysh -c "show bgp neighbors 192.0.2.1" | grep -E "BGP state|Last reset"
BGP state = Connect
Last reset 00:00:05, Notification sent (Hold Timer Expired)- Line 4: Agreed timers: a keepalive every 5 seconds, declared dead after 15 seconds of silence.
- Line 8: The moment the firewall starts dropping everything between r1 and r2.
- Lines 12–13: Fourteen seconds later: NOTIFICATION 4/0, Hold Timer Expired, and the session goes down. The NOTIFICATION can't get through the firewall either, so r2 has to wait for its own hold timer.
- Line 24: Back to Connect: r1 is trying to reconnect, and its SYNs are being dropped.
- Line 30: The reason is recorded for later.
r1# show bgp summary
IPv4 Unicast Summary:
BGP router identifier 198.51.100.241, local AS number 64500 VRF default vrf-id 0
BGP table version 9
RIB entries 9, using 1152 bytes of memory
Peers 1, using 17 KiB of memory
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc
192.0.2.1 4 64501 15 12 9 0 0 00:00:06 (Policy) (Policy) r2
Total number of neighbors 1
r1:~# vtysh -c "show bgp neighbors 192.0.2.1" | grep -iE "policy|accepted prefixes|BGP state"
BGP state = Established, up for 00:00:06
Inbound updates discarded due to missing policy
Outbound updates discarded due to missing policy
0 accepted prefixes
r1:~# grep -iE "policy" /var/log/frr/frr.log | tail -2
2026/10/18 03:46:58 BGP: [M8SSC-Q34TS] EBGP inbound/outbound policy not properly setup, please configure in order for your peering to work correctly
r2# show bgp summary
IPv4 Unicast Summary:
BGP router identifier 198.51.100.242, local AS number 64501 VRF default vrf-id 0
BGP table version 6
RIB entries 7, using 896 bytes of memory
Peers 2, using 33 KiB of memory
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc
192.0.2.0 4 64500 12 15 6 0 0 00:00:06 0 4 r1
192.0.2.3 4 64501 4 6 6 0 0 00:00:27 1 3 r3 (iBGP)
Total number of neighbors 2- Line 10: Up, but
(Policy)instead of prefix counts. - Lines 16–18: Both directions discarded; nothing accepted.
- Line 21: FRR also says so in the log, once.
- Line 32: From r2's side: it's sending 4 and receiving nothing.
r1# clear bgp 192.0.2.1 soft in
r1# show bgp summary
IPv4 Unicast Summary:
BGP router identifier 198.51.100.241, local AS number 64500 VRF default vrf-id 0
BGP table version 6
RIB entries 9, using 1152 bytes of memory
Peers 1, using 17 KiB of memory
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd PfxSnt Desc
192.0.2.1 4 64501 9 7 6 0 0 00:00:21 3 1 r2
Total number of neighbors 1
r1# show bgp ipv4 unicast neighbors 192.0.2.1 received-routes
BGP table version is 6, local router ID is 198.51.100.241, vrf id 0
Default local pref 100, local AS 64500
Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*> 198.51.100.0/26 192.0.2.1 0 0 64501 i
*> 198.51.100.64/26 192.0.2.1 0 0 64501 i
*> 198.51.100.128/26
192.0.2.1 0 0 64501 i
*> 198.51.100.192/27
192.0.2.1 0 64501 i
Total number of prefixes 4 (1 filtered)
r1# show bgp ipv4 unicast neighbors 192.0.2.1 routes
BGP table version is 6, local router ID is 198.51.100.241, vrf id 0
Default local pref 100, local AS 64500
Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*> 198.51.100.0/26 192.0.2.1 0 0 64501 i
*> 198.51.100.128/26
192.0.2.1 0 0 64501 i
*> 198.51.100.192/27
192.0.2.1 0 64501 i
Displayed 3 routes and 4 total paths
r1# show ip prefix-list FROM-R2
ZEBRA: ip prefix-list FROM-R2: 2 entries
seq 5 deny 198.51.100.64/26
seq 10 permit 198.51.100.0/24 le 27
BGP: ip prefix-list FROM-R2: 2 entries
seq 5 deny 198.51.100.64/26
seq 10 permit 198.51.100.0/24 le 27- Line 1: Re-run the import policy against the stored copy of r2's routes; the session stays up.
- Line 12: 3 received instead of the usual 4. Easy to miss if you don't know your normal number.
- Line 27:
received-routes: 198.51.100.64/26 was sent by r2. - Line 33: …and FRR counts it as filtered.
- Lines 44–49:
routes: what survived r1's import policy. The /26 is missing, so the filter is r1's own. - Line 55: There it is.
r3# show bgp ipv4 unicast
BGP table version is 6, local router ID is 198.51.100.243, vrf id 0
Default local pref 100, local AS 64501
Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
*>i 198.51.100.0/26 192.0.2.2 0 100 0 i
*>i 198.51.100.64/26 192.0.2.2 0 100 0 i
*>i 198.51.100.128/26
192.0.2.2 0 100 0 i
*> 198.51.100.192/27
0.0.0.0 0 32768 i
=i 203.0.113.0/24 192.0.2.0 0 100 0 64500 i
Displayed 5 routes and 5 total paths
r3# show bgp ipv4 unicast 203.0.113.0/24
BGP routing table entry for 203.0.113.0/24, version 6
Paths: (1 available, no best path)
Not advertised to any peer
64500
192.0.2.0 (inaccessible, import-check enabled) from 192.0.2.2 (198.51.100.242)
Origin IGP, metric 0, localpref 100, invalid, internal, multipath
Last update: Sun Oct 18 03:47:56 2026
r3# show ip route 203.0.113.0/24
% Network not in table
r3# show bgp nexthop
Current BGP nexthop cache:
192.0.2.0 invalid, #paths 1
Last update: Sun Oct 18 03:47:56 2026
192.0.2.2 valid [IGP metric 0], #paths 3, peer 192.0.2.2
Resolved prefix 192.0.2.2/31
if eth0
Last update: Sun Oct 18 03:47:34 2026- Line 17: No
*(valid) and no>(best): the route is present but unusable. Its next hop is r1's link address. - Line 23: No best path.
- Lines 26–27: inaccessible: r3 has no route to 192.0.2.0.
- Line 31: So it never reaches the routing table.
- Line 35: The next-hop cache agrees: 192.0.2.0 is invalid.
r3# show bgp ipv4 unicast 203.0.113.0/24
BGP routing table entry for 203.0.113.0/24, version 7
Paths: (1 available, best #1, table default)
Not advertised to any peer
64500
192.0.2.2 from 192.0.2.2 (198.51.100.242)
Origin IGP, metric 0, localpref 100, valid, internal, best (First path received)
Last update: Sun Oct 18 03:48:01 2026
r3# show ip route 203.0.113.0/24
Routing entry for 203.0.113.0/24
Known via "bgp", distance 200, metric 0, best
Last update 00:00:05 ago
* 192.0.2.2, via eth0, weight 1- Lines 6–7: Next hop r2 (192.0.2.2), which r3 can reach: valid and best.
- Lines 12–14: Installed, via r2.
Check your understanding
A route is in r3's BGP table from an iBGP peer, but it's not best and not in the routing table. show bgp marks its next hop inaccessible. What's the usual fix?
- Set next-hop-self on the border router that learned it over eBGP (or carry the external link in the IGP).
- Raise the hold timer.
- Add ebgp-multihop on r3.
- Clear the session.