VyOSXXVI · BGP AttributesAttributes
Local preference — the iBGP outbound path selector
What you'll learn
- Configure `set policy route-map ... set local-preference` to influence outbound path
- Explain why local preference is well-known discretionary and iBGP-only
- Set local preference per-peer via neighbour route-map
- Diagnose why a higher local preference is being ignored (outbound path still wrong)
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)
BGP local preference is the operator’s tool for outbound
path selection within an AS. It tells every iBGP router in the
local AS: “use this path to reach the destination”. On VyOS
1.5 LTS / FRR 10.x, the configuration is set policy route-map ... set local-preference <0-4294967295>, applied via a
neighbour’s inbound route-map.
This lesson is the operator’s reference for local preference: the well-known discretionary classification, the iBGP-only propagation rule, the route-map configuration, and how it fails in production.
What local preference does
LOCAL_PREF is a BGP attribute carried in UPDATE messages between iBGP peers. It is one of the four “well-known” attributes defined by RFC 4271, and one of the two “discretionary” ones (the BGP speaker is not required to recognise it, but every BGP implementation does).
The attribute’s value is a 32-bit unsigned integer. Higher values are preferred. The default is 100 (every BGP speaker assumes a default if the attribute is absent).
flowchart LR
subgraph "AS 64512"
R1["R1\n(inbound from eBGP)"]
R2["R2\n(inbound from eBGP)"]
R3["R3\n(iBGP)"]
R4["R4\n(iBGP)"]
end
subgraph "AS 64513"
P1["Provider A"]
end
subgraph "AS 64514"
P2["Provider B"]
end
R1 -- "eBGP\nLOCAL_PREF: 200" --> P1
R2 -- "eBGP\nLOCAL_PREF: 100" --> P2
R1 -- "iBGP\ncarries LOCAL_PREF" --> R3
R1 -- "iBGP\ncarries LOCAL_PREF" --> R4
R2 -- "iBGP\ncarries LOCAL_PREF" --> R3
R2 -- "iBGP\ncarries LOCAL_PREF" --> R4
R3 -- "best path: R1 (LOCAL_PREF 200)" --> R3
R4 -- "best path: R1 (LOCAL_PREF 200)" --> R4
When R3 and R4 have two paths to a destination (one via R1, one via R2), the path with the higher LOCAL_PREF wins. R3 and R4 both send their outbound traffic via R1.
The attribute is iBGP-only: it is carried in UPDATE messages between iBGP peers (routers in the same AS), but stripped when sending to eBGP peers (routers in different ASes). This is a protocol invariant — receiving routers in the remote AS cannot be told what the local AS’s preference is. The receiving eBGP peer cannot “see” the local AS’s LOCAL_PREF.
The VyOS configuration
The local preference is set via a route-map applied to the neighbour’s inbound direction (the path entering the local AS from the eBGP peer).
# Define the route-map
set policy route-map FROM-PROVIDER-A rule 10 action permit
set policy route-map FROM-PROVIDER-A rule 10 set local-preference 200
set policy route-map FROM-PROVIDER-B rule 10 action permit
set policy route-map FROM-PROVIDER-B rule 10 set local-preference 100
# Apply to the eBGP neighbours
set protocols bgp system-as 64512
set protocols bgp neighbor 10.0.0.1 remote-as 64513
set protocols bgp neighbor 10.0.0.1 address-family ipv4-unicast route-map import FROM-PROVIDER-A
set protocols bgp neighbor 10.0.0.2 remote-as 64514
set protocols bgp neighbor 10.0.0.2 address-family ipv4-unicast route-map import FROM-PROVIDER-B
commit
save
Three things about the neighbour lines are worth stating
plainly, because they are where a configuration written for
VyOS 1.3 stops working on 1.5. The local ASN is now the
system-as leaf rather than a level of the tree. Peers hang
off set protocols bgp neighbor <address> with no ASN in the
path. And the policy is attached under the address family
as route-map import <name> — the peer-level route-map NAME import spelling is gone, which matters because a peer
can carry different policy for IPv4 and IPv6 and the old
spelling had nowhere to say which.
The import direction is the route-map applied to routes
received from the peer. The set local-preference 200 rewrites
the LOCAL_PREF attribute on every route that matches the
route-map’s permit rule.
After commit, every iBGP peer in AS 64512 sees:
- Routes from Provider A with LOCAL_PREF 200
- Routes from Provider B with LOCAL_PREF 100
When an iBGP router (R3 or R4) runs the best-path algorithm, it picks the path with LOCAL_PREF 200 (Provider A) as the best path.
vyos@r3:~$ show ip bgp 8.8.8.0/24
BGP routing table entry for 8.8.8.0/24
Paths: (2 available, best #1, table default)
Advertised to non peer-group peers:
...
64513 15169
10.0.0.1 from 10.0.0.1 (10.0.0.1)
Origin IGP, localpref 200, valid, external, best
...
64514 15169
10.0.0.2 from 10.0.0.2 (10.0.0.2)
Origin IGP, localpref 100, valid, external
...
The localpref 200 and localpref 100 columns show the
LOCAL_PREF values. The best flag is on the path with the
higher LOCAL_PREF.
The default of 100
If a route enters the AS without an explicit LOCAL_PREF configuration, the default is 100. This applies:
- When a route enters via an eBGP peer with no inbound route-map setting local preference.
- When a route is locally originated (via
networkor redistribution) — the default is 100.
The default of 100 is the reason most operators set LOCAL_PREF explicitly. Setting one peer’s LOCAL_PREF to 200 (preferred) and leaving the other at 100 (default) creates an asymmetry: the 200 peer is always preferred. Setting the less preferred peer to a value lower than 100 (e.g. 50) makes the asymmetry explicit but the result is the same.
Local preference vs weight
BGP has two “preference” attributes: LOCAL_PREF (interior) and weight (per-router). The order in the best-path algorithm:
- Weight (Cisco-proprietary, also in FRR) — higher wins. Local to the router. Not propagated.
- LOCAL_PREF — higher wins. Propagated through iBGP.
- Locally originated — preferred over learned.
- AS-path length — shorter wins.
- Origin — IGP < EGP < incomplete.
- MED — lower wins.
- eBGP over iBGP.
- IGP cost to next-hop — lower wins.
- Router-id — lower wins.
- Cluster-list length, neighbour address.
The two attributes solve different problems:
- Weight is for “this specific router should prefer X”. It does not propagate; it does not influence other routers in the AS.
- LOCAL_PREF is for “the entire AS should prefer X”. It propagates through iBGP; every iBGP router sees the same value.
flowchart TB
subgraph "AS 64512"
R1["R1\nweight: 0 (default)\nLOCAL_PREF: 200\n(preferred outbound)"]
R2["R2\nweight: 0 (default)\nLOCAL_PREF: 200\n(preferred outbound)"]
R3["R3\nweight: 5000 (override)\nLOCAL_PREF: 200\n(R3 prefers differently)"]
end
R1 -- "iBGP\nLOCAL_PREF: 200" --> R3
R2 -- "iBGP\nLOCAL_PREF: 200" --> R3
R3 -- "weight: 5000 overrides LOCAL_PREF 200" --> R3
Weight is checked before LOCAL_PREF. If R3 has weight 5000 on a route, R3 prefers that route regardless of LOCAL_PREF. The other iBGP peers (R1, R2) still use LOCAL_PREF 200.
Filtering by prefix or community
The route-map that sets LOCAL_PREF can also filter which prefixes receive the LOCAL_PREF:
set policy prefix-list PREFER-A-ROUTES rule 10 action permit
set policy prefix-list PREFER-A-ROUTES rule 10 prefix 198.51.100.0/24
set policy prefix-list PREFER-A-ROUTES rule 20 action deny
set policy route-map FROM-PROVIDER-A rule 10 action permit
set policy route-map FROM-PROVIDER-A rule 10 match ip address prefix-list PREFER-A-ROUTES
set policy route-map FROM-PROVIDER-A rule 10 set local-preference 200
set policy route-map FROM-PROVIDER-A rule 20 action permit
This configuration sets LOCAL_PREF 200 only for the prefix
198.51.100.0/24 from Provider A. Other prefixes from
Provider A are passed through with the default LOCAL_PREF
100.
The rule 20 with action permit and no set is a no-op —
it permits the route but does not change LOCAL_PREF. The
route keeps its default.
A common production pattern: prefer Provider A for traffic destined to one set of prefixes (e.g. North America), Provider B for another set (e.g. Europe):
set policy route-map FROM-PROVIDER-A rule 10 action permit
set policy route-map FROM-PROVIDER-A rule 10 match ip address prefix-list NA-ROUTES
set policy route-map FROM-PROVIDER-A rule 10 set local-preference 200
set policy route-map FROM-PROVIDER-A rule 20 action permit
set policy route-map FROM-PROVIDER-A rule 20 match ip address prefix-list EU-ROUTES
set policy route-map FROM-PROVIDER-A rule 20 set local-preference 50
The EU-ROUTES rule explicitly sets LOCAL_PREF to 50 (less
than the default 100), so Provider B is preferred for
European destinations.
Validation
# 1. The route-map exists and says what you think it says
show configuration commands | match FROM-PROVIDER-A
vtysh -c 'show route-map FROM-PROVIDER-A'
# 2. The peer has it bound inbound
show ip bgp neighbors 10.0.0.1
# Read the policy lines: "Route map for incoming advertisements is *FROM-PROVIDER-A*"
# 3. The LOCAL_PREF is set on the received routes
show ip bgp 8.8.8.0/24
# Expected: localpref 200 on the path from 10.0.0.1
# 4. The best path is the one with the higher LOCAL_PREF
show ip bgp 8.8.8.0/24 bestpath
Step 2 is the one to be careful about. There is no
show ip bgp neighbors <ip> route-map command — the binding
is reported inside the ordinary show ip bgp neighbors <ip>
output, in the block that names the inbound and outbound
policy. Reading that block is how you tell “the route-map is
not applied” from “the route-map is applied and does not
match”, which are the two halves of nearly every
local-preference incident.
For a comprehensive view of LOCAL_PREF across the paths from one origin AS:
vyos@r3:~$ show ip bgp regexp _15169$BGP table version is 12345, local router ID is 10.255.0.3, vrf id 0
Default local pref 100, local AS 64512
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete
Network Next Hop Metric LocPrf Weight Path
*>i8.8.8.0/24 10.0.0.1 0 200 0 64513 15169 i
* i 10.0.0.2 0 100 0 64514 15169 iIllustrative output
Read three things here. The LocPrf column carries the values
the route-maps set. The leading i on both rows says these
paths reached R3 over iBGP, which is the whole point — the
attribute survived the internal hop. And *> marks the best
path, on the row with 200.
Note also that show ip bgp regexp filters on the AS path,
not on the prefix: _15169$ means “paths originated by AS
15169”. A regex written as though it were a prefix filter
matches nothing and looks like an empty table.
Failure modes
Local preference is set but the path is not preferred
The route-map sets LOCAL_PREF 200 on Provider A’s routes, but the best-path algorithm picks Provider B’s path with LOCAL_PREF 100.
Diagnostic:
- Is the route-map applied?
show ip bgp neighbors 10.0.0.1and read the policy block, which names the inbound and outbound route-maps. A peer with no inbound policy simply does not print one. - Is the LOCAL_PREF set on the received routes? Run
show ip bgp 8.8.8.0/24and look forlocalpref 200on the path from Provider A. - Is the route-map’s match clause matching?
vtysh -c 'show route-map FROM-PROVIDER-A'prints the rendered rules and a per-rule match counter. A rule with a zero counter is not matching, which is a different problem from a rule that is missing. - Is the prefix being filtered out by the route-map?
The route-map may have a
denyrule that matches the prefix before thepermitrule withset local-preference.
Local preference is set but iBGP peers do not honour it
The iBGP peer sees LOCAL_PREF 200 in the UPDATE but picks a different path.
Diagnostic:
- The iBGP peer has its own weight setting that overrides
LOCAL_PREF.
show ip bgp <prefix>on the iBGP peer; look for non-zero weight. - The iBGP peer has its own inbound route-map that rewrites
LOCAL_PREF.
show ip bgp neighbors 10.255.0.1on that peer and read its policy block. - The iBGP peer does not have a route to the next-hop
(
RIB-failure).
Inbound route-map is not in place
The operator set up the route-map but forgot to apply it to the neighbour. The route-map exists in the policy configuration but is not bound to a neighbour.
Diagnostic:
show configuration commands | match FROM-PROVIDER-A— the policy exists, and the output shows noprotocols bgpline referencing it.show ip bgp neighbors 10.0.0.1— no inbound policy named.
The fix:
set protocols bgp neighbor 10.0.0.1 address-family ipv4-unicast route-map import FROM-PROVIDER-A
A route-map that is defined but bound to nothing is one of the quietest faults in BGP: it commits cleanly, it shows up in the configuration, and it does nothing at all.
The route-map is applied in the wrong direction
The operator applied the route-map outbound instead of inbound. The outbound route-map is for advertising, not for receiving. LOCAL_PREF is set on receipt, not on sending.
Diagnostic: show ip bgp neighbors 10.0.0.1 names the
route-map as the policy for outgoing advertisements rather
than incoming ones.
The fix:
delete protocols bgp neighbor 10.0.0.1 address-family ipv4-unicast route-map export
set protocols bgp neighbor 10.0.0.1 address-family ipv4-unicast route-map import FROM-PROVIDER-A
Rollback
# Remove the route-map from the neighbour
delete protocols bgp neighbor 10.0.0.1 address-family ipv4-unicast route-map import
commit
# Or remove the local-preference setting from the route-map
delete policy route-map FROM-PROVIDER-A rule 10 set local-preference
commit
The rollback for a misconfigured LOCAL_PREF is straightforward: remove the route-map from the neighbour, and the routes return to the default LOCAL_PREF 100. The iBGP peers will see the change and re-run the best-path algorithm.
For a planned rollback:
- Capture the before state (
show ip bgp <prefix>). - Remove the route-map.
- Verify the after state (LOCAL_PREF back to 100, best path may change).
Production discipline
Cross-course references
- Part XXV (
XXV-VyOS-BGPAdvertise) covers the origination primitives that produce routes in the BGP table; LOCAL_PREF acts on these routes after they arrive. - Part XXVI-02 (
XXVI-VyOS-BGPAttributes/ AS path) covers the next attribute in the best-path algorithm. - Part XXVII (
XXVII-VyOS-BGPBestPath) covers the best-path algorithm in full, including the tie-breakers after LOCAL_PREF. - Part XXXIII (
XXXIII-VyOS-RoutePolicy) covers the route-map primitives used here. - Part XXXIX (
XXXIX-VyOS-MultiWAN) covers the multi-WAN use case where LOCAL_PREF is the primary tool.
Quiz
Knowledge check · 4 questions
Q1. A route enters AS 64512 from an eBGP peer with no inbound route-map. What is the LOCAL_PREF of the route?
Q2. BGP LOCAL_PREF is sent on eBGP sessions and stripped on iBGP sessions.
Q3. R3 (an iBGP router in AS 64512) receives a route from R1 with LOCAL_PREF 200 (preferred). R3 has weight 5000 on the same route from R2 (which has LOCAL_PREF 100). Which path does R3 select as best?
R3 has: - iBGP session to R1 (carrying LOCAL_PREF 200 on the route) - iBGP session to R2 (carrying LOCAL_PREF 100 on the route) R3 also has a forgotten weight configuration: set protocols bgp neighbor 10.0.0.2 address-family ipv4-unicast route-map import WEIGHT-OVERRIDE set policy route-map WEIGHT-OVERRIDE rule 10 action permit set policy route-map WEIGHT-OVERRIDE rule 10 set weight 5000
Q4. R1 configures `set protocols bgp neighbor 10.0.0.1 address-family ipv4-unicast route-map export FROM-PROVIDER-A` and expects the LOCAL_PREF 200 setting on that route-map to influence outbound path selection within AS 64512. Why does this not work?
R1's route-map: set policy route-map FROM-PROVIDER-A rule 10 action permit set policy route-map FROM-PROVIDER-A rule 10 set local-preference 200 R1's neighbour: set protocols bgp neighbor 10.0.0.1 address-family ipv4-unicast route-map export FROM-PROVIDER-A 10.0.0.1 is the eBGP peer (Provider A).
Passing score: 75%. Answers are checked in this browser.