Skip to main content
RunBook Academy

VyOSXXV · BGP Route AdvertisementAdvertisement

BGP advertisement troubleshooting — prefix not advertised, route-map blocking, next-hop unreachable

Advanced⏱ ~26 minvyosvtyshshow ip bgpshow ip bgp neighborsshow ip routeshow route-mapshow bgp ipv4 unicast neighbors <ip> advertised-routesshow configuration commandstcpdump

What you'll learn

  • Run the canonical diagnostic for 'prefix not advertised'
  • Identify route-map and prefix-list blocks at the inbound, outbound, and redistribution boundaries
  • Diagnose next-hop unreachability on eBGP peers
  • Apply the production discipline that catches advertisement failures before the user notices

Prerequisites

Verified against VyOS 1.5.x LTS (circinus) · VyOS 1.4.x (sagitta) — legacy · FRRouting 10.x (VyOS 1.5) · Linux kernel 6.6 LTS (VyOS 1.5 base) · strongSwan 5.9.x (IPsec) · WireGuard 1.0.x (kernel module + userspace tooling)

Not yet marked complete on this device.

A BGP prefix that the operator expected to advertise but did not is one of the most common production failures. The failure has four boundaries, and a methodical operator walks each one in order:

  1. RIB — is the prefix in the routing table at all?
  2. Loc-RIB — is the prefix in the BGP table?
  3. Advertised — does the local router advertise the prefix to the peer?
  4. Peer uses — does the peer’s BGP table accept the prefix?

This lesson is the operator’s diagnostic discipline for BGP advertisement failures on VyOS 1.5 LTS / FRR 10.x. It is the cross-cutting lesson that ties together the prior lessons in this part.

The diagnostic decision tree

flowchart TB
  Q1{"Is the prefix in the RIB?\n(show ip route)"}
  Q2{"Is the prefix in the BGP table?\n(show ip bgp prefix)"}
  Q3{"Does advertised-routes include it?\n(show ip bgp neighbors advertised-routes)"}
  Q4{"Does the peer's BGP table accept it?\n(peer-side show ip bgp prefix)"}

  Q1 -- "no" --> A1["Fix the RIB\n(static route, interface, IGP)"]
  Q1 -- "yes" --> Q2
  Q2 -- "no" --> A2["Check origination:\nnetwork statement,\nredistribute filter,\naggregate components"]
  Q2 -- "yes" --> Q3
  Q3 -- "no" --> A3["Check outbound policy:\nroute-map, prefix-list,\ncommunity filter"]
  Q3 -- "yes" --> Q4
  Q4 -- "no" --> A4["Check inbound policy:\npeer-side filter,\nnext-hop reachable,\nAS-path loop"]
  Q4 -- "yes" --> A5["Done — the prefix is working"]

The four boundaries:

  • RIB — the local routing table. BGP can only originate what exists here.
  • Loc-RIB — the BGP table on the local router. The prefix must be installed here by a network statement, a redistribution, an aggregate, or a peer.
  • Advertised — the prefix that leaves the router for the peer. Outbound policy filters the Loc-RIB.
  • Peer uses — the prefix in the peer’s BGP table. Inbound policy on the peer filters it.

The operator who skips a boundary misses the failure. The operator who walks the tree in order finds the failure.

Boundary 1: the RIB

Read-only / Safe
vyos@r1:~$ show ip route 192.0.2.0/24
Routing entry for 192.0.2.0/24
Known via "static", distance 1, metric 0, best
* 10.0.0.1, via eth0

Illustrative output

Two things to be precise about here. show ip route 192.0.2.0/24 asks about that prefix at that length; if you want everything inside it, ask for it explicitly:

vyos@r1:~$ show ip route 192.0.2.0/24 longer-prefixes

And the default VRF is the only table this reads. If the interface carrying the address is in a VRF, the route is in that VRF’s table and the default table has never heard of it:

vyos@r1:~$ show ip route vrf all 192.0.2.0/24

If the prefix is absent, BGP has nothing to advertise.

Common causes:

  • Interface is downshow interfaces ethernet eth0.
  • Static route is misconfiguredshow configuration commands | grep static.
  • The IGP (OSPF, IS-IS) does not have the routeshow ip ospf database for OSPF, show isis database for IS-IS.
  • The prefix is in a different routing table — VRF or policy routing has moved it.

The fix is at the routing layer below BGP. BGP is downstream of all these sources.

Boundary 2: the BGP Loc-RIB

Read-only / Safe
vyos@r1:~$ show ip bgp 192.0.2.0/24
BGP routing table entry for 192.0.2.0/24
Paths: (1 available, best #1, table default)
Advertised to non peer-group peers:
  10.0.0.2
Local
  0.0.0.0 from 0.0.0.0 (192.0.2.1)
    Origin IGP, metric 0, weight 32768, valid, sourced, local, best

Illustrative output

The three things to read in that entry: sourced, local says this router originated the prefix rather than learning it, weight 32768 is the weight FRR gives locally sourced paths, and the Advertised to list names the peers that have actually been sent it.

If the prefix is absent:

  • The network statement does not match the RIB entry exactly (the exact-match rule from xxv-01).
  • The redistribution route-map rejects the prefix.
  • The aggregate has no components.
  • The peer session through which the prefix would arrive is down.

When you are not sure of the exact length, widen the question rather than guessing:

vyos@r1:~$ show bgp ipv4 unicast 192.0.2.0/24 longer-prefixes

Do not reach for show ip bgp regexp here. That command takes an AS-path regular expression, not a prefix — it is for questions like “what am I carrying that transits AS 64513”, and feeding it a dotted-quad quietly matches nothing useful.

The diagnostic for each:

SymptomDiagnosticFix
network does not matchshow ip route <prefix>; compare the maskAdjust the network mask or the RIB prefix
redistribute route-map blocksvtysh -c 'show route-map OSPF-TO-BGP'Widen the prefix-list the route-map matches on
aggregate-address has no componentsshow ip bgp <component prefix>Originate the components
Peer session downshow ip bgp summaryFix the session (TCP/179, ACL, AS)

Boundary 3: the outbound policy

The prefix is in the Loc-RIB but not in the peer’s advertised-routes. Cause: an outbound route-map, prefix-list, filter-list, or community-list is denying the prefix.

vyos@r1:~$ show ip bgp neighbors 10.0.0.2 advertised-routes

If the prefix is absent from that list, find out which policy is attached. Two sources, and they answer different questions:

# What the configuration says should be attached
vyos@r1:~$ show configuration commands | match 'neighbor 10.0.0.2'

# What FRR has actually loaded for this peer
vyos@r1:~$ vtysh -c 'show bgp neighbors 10.0.0.2'

The show bgp neighbors output is long. Under the For address family: IPv4 Unicast heading it reports the inbound and outbound policy in force — the route-map, prefix-list, filter-list and distribute-list names, if any. Read that section rather than the whole thing, and read it in preference to the VyOS tree: a name in the tree that is missing from FRR’s view is itself the finding.

Then walk the route-map’s rules. FRR knows what it compiled:

vyos@r1:~$ vtysh -c 'show route-map OUT-v4'

Read it against the configuration that produced it:

vyos@r1:~$ show configuration commands | match 'route-map OUT-v4'
set policy route-map OUT-v4 rule 10 action 'permit'
set policy route-map OUT-v4 rule 10 match ip address prefix-list 'ADVERTISE-EXTERNAL'

Now the arithmetic. Rule 10 permits a prefix that is in ADVERTISE-EXTERNAL. A prefix that is not in that list matches no rule in the route-map, and a route that matches no rule in a route-map is denied — the implicit deny at the end of the map is doing the work, with no deny rule anywhere in the configuration to point at. This is why 192.0.2.0/24 never reaches the peer.

The fix is to permit it where the match is made:

set policy prefix-list ADVERTISE-EXTERNAL rule 5 action permit
set policy prefix-list ADVERTISE-EXTERNAL rule 5 prefix 192.0.2.0/24

Do not try to add a trailing action deny rule to the prefix-list to “make the deny explicit”. Every prefix-list rule needs a prefix to match on, so a rule carrying only an action is rejected at commit — and the deny you are trying to write is already the behaviour.

Boundary 4: the peer’s inbound policy

The local router advertises the prefix, but the peer’s BGP table does not have it. Cause: the peer’s inbound policy is denying the prefix, or the peer cannot reach the next-hop.

The peer-side diagnostic:

# On the peer
vyos@r2:~$ show ip bgp 192.0.2.0/24

# The prefixes the peer received from R1, before its own inbound policy
vyos@r2:~$ show bgp ipv4 unicast neighbors 10.0.0.1 received-routes

received-routes is a pre-policy view, and FRR can only produce it if the session has soft-reconfiguration inbound enabled on that neighbour — otherwise it refuses the command rather than returning an empty list. Read the error before concluding nothing arrived:

set protocols bgp neighbor 10.0.0.1 address-family ipv4-unicast soft-reconfiguration inbound

Three outcomes, three different problems:

  • In received-routes, absent from show ip bgp — the peer’s inbound policy denied it.
  • Absent from received-routes — it never arrived. Look at the sending side’s outbound policy again, or at an address-family mismatch: a session that negotiated only IPv4 unicast carries nothing else, no matter what either side has configured.
  • Present in show ip bgp but not in show ip route — it arrived, it was accepted, and it still is not usable. That is the next-hop problem below, and it is the one operators misdiagnose most often, because the prefix is in the BGP table.

The next-hop check

# On the peer: what next-hop did the path arrive with?
vyos@r2:~$ show bgp ipv4 unicast 192.0.2.0/24

# Can this router reach that address?
vyos@r2:~$ show ip route 10.0.0.1

A path whose next-hop the receiving router cannot resolve fails BGP’s next-hop reachability check. It stays in the BGP table — FRR annotates the next-hop as inaccessible — but it is not valid, so it never becomes best and never reaches the RIB. The symptom is a prefix that is visibly present in show ip bgp and visibly absent from show ip route.

Common production failures — and the diagnostic

“I added a network statement but the prefix is not advertised”

Step 1: show ip route <prefix>. If absent, the RIB has nothing.

Step 2: show ip bgp <prefix>. If absent, the BGP table has nothing. The exact-match rule may be the issue (the RIB has a different mask than the network statement).

Step 3: show ip bgp neighbors <peer> advertised-routes. If the prefix is absent, the outbound policy is denying it.

Step 4: peer-side show ip bgp <prefix>. If absent on the peer, the inbound policy or next-hop is the issue.

“The peer was receiving the prefix, but stopped”

Step 1: Has the local configuration changed? show system commit lists the commit revisions with the user and time behind each one. compare saved diffs the candidate — which, with no pending edits, is the running configuration — against /config/config.boot, so it catches a change that was committed but never saved. The change may have added an outbound route-map or removed a network statement.

Step 2: Has the RIB changed? show ip route <prefix>. The underlying route may have been withdrawn.

Step 3: Has the peer session changed? show ip bgp summary. The session may have flapped, or the peer may have changed their inbound policy.

“The prefix is in advertised-routes but the peer does not have it in their BGP table”

Step 1: Has the peer received a route-refresh? If the peer’s policy changed since the last refresh, the local router’s view of the peer’s policy may be stale.

Step 2: Has the peer’s inbound policy changed? The peer may have added a prefix-list or community filter.

Step 3: Is the next-hop reachable on the peer? If the peer lost its route to the next-hop, the prefix is still in the peer’s BGP table — show ip bgp <prefix> finds it — but it is not valid and not in show ip route. Check the next-hop address itself rather than the prefix.

“The prefix is being advertised, but the AS-path is wrong”

Step 1: show ip bgp <prefix>. Check the AS-path column. Compare against what the operator expected.

Step 2: If the AS-path has prepended ASes unexpectedly, a route-map on the outbound policy may be adding them.

Step 3: If the AS-path is missing ASes (e.g. an aggregation should have preserved them but did not), the aggregate-address may not have as-set.

Validation discipline

The disciplined operator runs the validation sequence for every BGP change, before declaring the change successful.

# 1. The RIB has the prefix
show ip route 192.0.2.0/24

# 2. The BGP table has it, sourced locally
show ip bgp 192.0.2.0/24

# 3. The advertised routes to this peer include it
show ip bgp neighbors 10.0.0.2 advertised-routes

# 4. The peer's BGP table has it, and its next-hop resolves
#    (peer-side; needs access to the peer, or the peer's operator)

# 5. Forwarding actually works
traceroute 192.0.2.10

The data-plane validation (traceroute) is the proof. A prefix in BGP tables is not the same as traffic flowing. The discipline is to confirm both.

Rollback

The standard rollback sequence:

The cheapest rollback is the one you set up before the change: apply with commit-confirm 5 and simply do not confirm. The router reverts on the timer, including when the change is what cut you off from it.

After a commit has been confirmed, work outward from the smallest tool:

# 1. Undo the specific thing, if you know what it was
delete protocols bgp neighbor 10.0.0.2 address-family ipv4-unicast route-map export OUT-v4
commit

# 2. Or restore a known-good file into the candidate, and read
#    the diff before committing it
load /config/backup/bgp-known-good.conf
compare
commit

load replaces the candidate wholesale, so compare between the load and the commit is not optional — it is the only thing standing between “restore the BGP policy” and “restore last month’s interface addressing along with it”.

Two things that are not rollbacks. discard throws away an uncommitted candidate; it does nothing about a change you have already committed, and there is nothing to commit afterwards. And rollback restores an entire previous commit revision — every change committed since goes with it — so it is a deliberate, whole-configuration decision rather than a way to back out one policy.

Cross-course references

  • Part XXIII (XXIII-VyOS-BGPFund) covers the BGP FSM and the states that gate UPDATE sending.
  • Part XXIV (XXIV-VyOS-BGPSessions) covers the session establishment that is prerequisite for any advertisement.
  • Part XXV-01 through XXV-05 (XXV-VyOS-BGPAdvertise) cover the origination primitives that produce the prefix in the Loc-RIB.
  • Part XXVIII (XXVIII-VyOS-BGPPrefixFilter) covers the outbound policy that filters the advertisement.
  • Part XXXI (XXXI-VyOS-BGPTroubleshoot) is the troubleshooting counterpart for sessions and routes.

Quiz

Knowledge check · 4 questions

  1. Q1. An operator commits `set protocols bgp address-family ipv4-unicast network 192.0.2.0/24` but the prefix is not in the BGP table. What is the first thing the operator should check?

  2. Q2. A route that matches no rule in a route-map is denied, even though no `deny` rule appears anywhere in the configuration.

  3. Q3. R1 has a `network 192.0.2.0/24` statement in its default BGP instance and eth0 carries 192.0.2.1/24. The peer reports they are not receiving the prefix, and `show ip bgp 192.0.2.0/24` on R1 returns nothing. The BGP session is Established. Where does the diagnostic go next?

    R1: set interfaces ethernet eth0 address 192.0.2.1/24 set protocols bgp system-as 64512 set protocols bgp neighbor 10.0.0.2 remote-as 64513 set protocols bgp address-family ipv4-unicast network 192.0.2.0/24 The operator runs `show ip bgp 192.0.2.0/24` and gets no output. `show ip bgp summary` shows 10.0.0.2 as Established.

  4. Q4. R1 learns 198.51.100.0/24 from an eBGP peer and readvertises it to its iBGP peer R2. On R2 the prefix is present in `show ip bgp 198.51.100.0/24` but absent from `show ip route 198.51.100.0/24`, and no traffic follows it. What is happening, and what is the fix?

    R1 and R2 are iBGP peers inside AS 64512, peering on their loopbacks, which OSPF carries. R1 also has an eBGP session to 203.0.113.1 in AS 64513 and learns 198.51.100.0/24 over it. On R2, `show ip bgp 198.51.100.0/24` shows the path. `show ip route 198.51.100.0/24` shows nothing.

Passing score: 75%. Answers are checked in this browser.