VyOSXXV · BGP Route AdvertisementAdvertisement
BGP conditional advertisement — advertise-map and non-exist-map
What you'll learn
- Configure a per-neighbour advertise-map with an exist-map or non-exist-map on VyOS 1.5
- Explain what the conditional is evaluated against, and on what timer
- Recognise the backup-path use case and its withdraw-on-failure inverse
- Diagnose why a conditional advertisement never fires, using the evidence VyOS and FRR actually give you
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) · 2026-08-19
BGP conditional advertisement is the operator’s tool for reactive advertisement: advertise this prefix to this peer only when some other prefix is — or is not — in the local BGP table.
Three facts shape everything else in this lesson, and getting them straight first saves a lot of confusion:
- It is per neighbour and outbound. There is no global “conditional advertisement” object. The configuration hangs off one neighbour’s address family and changes what that neighbour is sent.
- The condition is evaluated against the local BGP table, not against interface state, not against a peer’s session state.
- It runs on a periodic scanner, not on events. Failover is bounded by that timer, which is why this is a policy mechanism and not a fast-failover mechanism.
The two maps
The mechanism uses two route-maps with different jobs, and the naming does not make the difference obvious.
advertise-map— names the prefixes whose advertisement to this neighbour is placed under conditional control. Its permit rules select what is conditionally advertised.non-exist-map— names the prefixes whose absence from the BGP table makes the condition true. When they are gone, the advertise-map’s prefixes are advertised.exist-map— the inverse. When the named prefixes are in the BGP table, the advertise-map’s prefixes are advertised.
You use advertise-map with exactly one of the other two.
flowchart TB
T["Local BGP table"] --> C{"Condition route-map<br/>matches a prefix in the table?"}
C -->|"non-exist-map: no match"| ADV["Advertise the advertise-map<br/>prefixes to this neighbour"]
C -->|"non-exist-map: match found"| WD["Withdraw them from<br/>this neighbour"]
C -->|"exist-map: match found"| ADV
C -->|"exist-map: no match"| WD
ADV --> P["Neighbour"]
WD --> P
The backup-path use case
The canonical use is a second address block that should only appear when the first one is gone.
flowchart LR
AS["AS 64512"]
P1["Provider A<br/>(primary)"]
P2["Provider B<br/>(backup)"]
PR["Primary prefix<br/>192.0.2.0/24"]
BK["Backup prefix<br/>198.51.100.0/24"]
PR --> AS
BK --> AS
AS -- "always advertises 192.0.2.0/24" --> P1
AS -- "advertises 198.51.100.0/24 only<br/>when 192.0.2.0/24 has gone" --> P2
- While
192.0.2.0/24is in the local BGP table, the condition (non-exist) is false and198.51.100.0/24is not advertised to Provider B. - When
192.0.2.0/24leaves the BGP table, the condition becomes true on the next scanner run and198.51.100.0/24is advertised. - When it comes back, the backup is withdrawn again.
Note what the condition is watching: the BGP table, not the link and not the session. If the primary prefix is locally originated, it disappears only when the router stops originating it. That is the single most common reason this design does not behave the way its author expected, and the quiz returns to it.
The VyOS configuration
Route-maps and prefix-lists first, because the commit will reject a neighbour that names a route-map which does not exist:
set policy prefix-list PRIMARY-PFX rule 10 action 'permit'
set policy prefix-list PRIMARY-PFX rule 10 prefix '192.0.2.0/24'
set policy prefix-list BACKUP-PFX rule 10 action 'permit'
set policy prefix-list BACKUP-PFX rule 10 prefix '198.51.100.0/24'
set policy route-map ADVERTISE-BACKUP rule 10 action 'permit'
set policy route-map ADVERTISE-BACKUP rule 10 match ip address prefix-list 'BACKUP-PFX'
set policy route-map WATCH-PRIMARY rule 10 action 'permit'
set policy route-map WATCH-PRIMARY rule 10 match ip address prefix-list 'PRIMARY-PFX'
Then the origination and the conditional, on the neighbour that should receive the backup:
set protocols bgp system-as 64512
set protocols bgp address-family ipv4-unicast network '192.0.2.0/24'
set protocols bgp address-family ipv4-unicast network '198.51.100.0/24'
set protocols bgp neighbor 198.51.100.1 remote-as '65002'
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast conditionally-advertise advertise-map 'ADVERTISE-BACKUP'
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast conditionally-advertise non-exist-map 'WATCH-PRIMARY'
Three things to read off that:
- The conditional lives under one neighbour, inside one
address family. A second peer that needs the same behaviour
needs its own copy; an IPv6 session needs its own maps and its
own
address-family ipv6-unicastblock. ADVERTISE-BACKUPselects what is conditionally advertised.WATCH-PRIMARYis the condition, and it is matched against the local BGP table.
The scanner timer
FRR does not re-evaluate the condition on every UPDATE. It runs a conditional-advertisement scanner periodically, and 60 seconds is the default. The consequence is blunt: after the primary prefix leaves the table, the backup can take up to a minute to be advertised, plus propagation.
The period is adjustable within a range (FRR accepts 5 to 240 seconds):
set protocols bgp parameters conditional-advertisement timer '20'
Shortening it costs CPU — every run walks the table for every neighbour with a conditional — and buys you a smaller worst case, not a fast one.
exist-map versus non-exist-map
The two express opposite intents and are easy to swap by accident:
| Intent | Condition map | Behaviour |
|---|---|---|
| Advertise a backup when the primary is gone | non-exist-map | Advertise while the watched prefix is absent |
| Advertise only while an upstream is present | exist-map | Advertise while the watched prefix is present |
The exist-map form is the withdraw-on-failure pattern: keep
attracting traffic from this peer only while you have a working
path onward, so you stop being a blackhole when you do not.
set policy prefix-list UPSTREAM-A-PFX rule 10 action 'permit'
set policy prefix-list UPSTREAM-A-PFX rule 10 prefix '203.0.113.0/24'
set policy route-map WATCH-UPSTREAM-A rule 10 action 'permit'
set policy route-map WATCH-UPSTREAM-A rule 10 match ip address prefix-list 'UPSTREAM-A-PFX'
set policy route-map ADVERTISE-MINE rule 10 action 'permit'
set policy route-map ADVERTISE-MINE rule 10 match ip address prefix-list 'PRIMARY-PFX'
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast conditionally-advertise advertise-map 'ADVERTISE-MINE'
set protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast conditionally-advertise exist-map 'WATCH-UPSTREAM-A'
Pick the watched prefix carefully. A prefix that upstream A originates and nobody else does is a decent proxy for “A is reachable”; a prefix that arrives from three upstreams tells you nothing about A at all.
Validation
1. The configuration is where you think it is.
show configuration commands | match conditionally-advertise
2. The condition prefix’s presence in the table. This is the input to the decision:
show ip bgp 192.0.2.0/24
Present means a non-exist-map condition is false. Absent means
it is true.
3. What the neighbour is actually being sent. This is the output, and it is the real evidence:
vyos@r1:~$ show ip bgp neighbors 198.51.100.1 advertised-routes4. Exercise it. Remove the primary origination, wait past the scanner period, and look again:
configure
delete protocols bgp address-family ipv4-unicast network 192.0.2.0/24
commit
Then, after at least one scanner interval, repeat step 3. The backup prefix should now appear in the advertised list. Put the primary back and it should disappear again.
5. Confirm from the peer’s side if you can. The definitive
check is what the neighbour has in its table. Your
advertised-routes is what you sent; their show ip bgp is what
they kept, and an inbound filter on their side can make those
differ.
Failure modes
The condition never becomes true
Almost always because the watched prefix has not actually left the BGP table. Work through it in this order:
- Is the watched prefix still there?
show ip bgp 192.0.2.0/24. If the answer is yes, everything else is a distraction — the mechanism is behaving correctly and the input is wrong. - Why is it still there? The common cases: it is locally
originated by a
networkstatement or a redistribution that does not care about the failure; or it is being learned from a second peer as well as the one that failed; or the session you expected to drop is still Established because the hold timer has not expired. - Has a scanner interval elapsed? Up to 60 seconds by default. Do not diagnose inside the first minute.
- Does the condition route-map match the prefix? A prefix-list
entry of
192.0.2.0/24does not match192.0.2.0/25. If you need it to, useleandgedeliberately. - Is outbound policy dropping the backup anyway? If the
condition is true and the prefix still does not appear in
advertised-routes, the conditional has fired and something else is filtering. Read the neighbour’s outbound route-map.
The advertisement flaps
The watched prefix is itself unstable, so the condition alternates on successive scanner runs and the backup is advertised and withdrawn repeatedly. Every cycle is a real UPDATE to the peer and propagates outward.
The fix is upstream of the conditional: make the watched prefix a stable signal. Watch something you originate, or something with a single stable source, rather than a prefix that arrives over a flapping session. Lengthening the timer hides the flap rather than fixing it, and doubles the worst-case failover at the same time.
The intent and the map are inverted
The configuration works exactly as written, and what it does is
the opposite of what was wanted. exist-map advertises while the
watched prefix is present; non-exist-map advertises while it is
absent. The tell is that the behaviour is consistent and
deterministic — it always does the wrong thing, rather than
sometimes.
Audit against the intent in words before you audit the syntax:
“advertise the backup when the primary is gone” is non-exist-map;
“stop attracting traffic when my upstream is gone” is exist-map.
The conditional was applied to the wrong neighbour or family
It is per neighbour, per address family. Applied to the wrong
peer, the intended peer sees the prefix unconditionally and the
wrong one sees it appear and disappear. Applied under
address-family ipv6-unicast when the maps match IPv4 prefixes,
the condition can never be true. The rendered FRR block shows both
mistakes at a glance, which is why step 1 of validation is worth
the keystrokes.
Rollback
delete protocols bgp neighbor 198.51.100.1 address-family ipv4-unicast conditionally-advertise
commit
Removing the conditional does not make the prefix disappear — it returns it to unconditional advertisement, subject to normal outbound policy. That is usually the safe direction, but say it out loud before you do it in an incident: the backup block is about to be advertised permanently, and if the reason it was conditional was that advertising it always causes a problem, you have just caused that problem.
If the safer outcome is “advertise nothing extra”, remove the origination instead:
delete protocols bgp address-family ipv4-unicast network 198.51.100.0/24
commit
For a planned change, commit-confirm 10 protects the session
you are working over, compare shows what is about to change,
and rollback 1 then commit returns to the previous revision.
Production discipline
Cross-course references
vyos-xxv-01-bgp-network-statementcovers the origination the condition and the advertisement both depend on.vyos-xxv-03-bgp-redistribute-staticcovers the alternative origination path, and why a redistributed prefix may not vanish when you expect it to.XXXIII-VyOS-RoutePolicycovers the route-map and prefix-list primitives used here, includingleandgematching.- The BGP session parts cover hold timers, BFD and next-hop tracking — the mechanisms that decide when the watched prefix actually leaves the table.
Quiz
Knowledge check · 4 questions
Q1. A neighbour carries `advertise-map ADVERTISE-BACKUP non-exist-map WATCH-PRIMARY`. ADVERTISE-BACKUP matches 198.51.100.0/24; WATCH-PRIMARY matches 192.0.2.0/24. What does this neighbour receive?
Q2. BGP conditional advertisement is re-evaluated on every BGP UPDATE, so the backup path is advertised the instant the watched prefix leaves the table.
Q3. R1 has a non-exist-map watching 192.0.2.0/24. The operator shuts the link to Provider A and waits five minutes. The backup 198.51.100.0/24 is never advertised. Diagnose it.
R1 originates both blocks with `set protocols bgp address-family ipv4-unicast network 192.0.2.0/24` and `... network 198.51.100.0/24`, and both prefixes are in the local BGP table. The conditional is configured on the Provider B neighbour with `advertise-map ADVERTISE-BACKUP non-exist-map WATCH-PRIMARY`. After the link to Provider A is shut, `show ip bgp neighbors 198.51.100.1 advertised-routes` still lists only 192.0.2.0/24.
Q4. An operator wanted to advertise a backup block when the primary path failed, and configured `exist-map` instead of `non-exist-map`. Describe the behaviour they get, how they would recognise it, and the fix.
The neighbour carries `advertise-map ADVERTISE-BACKUP exist-map WATCH-PRIMARY`. ADVERTISE-BACKUP matches the backup block 198.51.100.0/24 and WATCH-PRIMARY matches the primary block 192.0.2.0/24. Both blocks are in the local BGP table under normal conditions, and the peer is receiving both.
Passing score: 75%. Answers are checked in this browser.