VyOSXXVI · BGP AttributesAttributes
AS path — prepend, aggregation loss, and the loop prevention
What you'll learn
- Explain why AS_PATH is well-known mandatory and what it carries
- Configure AS path prepend on an outbound route-map for outbound traffic engineering
- Recognise the attribute loss during aggregation and how `as-set` preserves it
- Diagnose loop detection, prepend being ignored, and unexpected path selection
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)
AS_PATH is the path-vector mechanism that makes BGP a
path-vector protocol. Every BGP UPDATE carries the AS_PATH:
the sequence of ASes the route has transited. On VyOS 1.5 LTS
/ FRR 10.x, the configuration is set policy route-map ... set as-path prepend for outbound engineering, plus the
aggregation behaviour covered in xxv-02.
This lesson is the operator’s reference for AS_PATH: the well-known mandatory classification, prepend configuration, attribute loss on aggregation, loop prevention, and how it fails in production.
What AS_PATH does
AS_PATH is the canonical BGP attribute. Every BGP UPDATE must include it (it is well-known mandatory in RFC 4271’s classification). The attribute carries:
- The sequence of ASes the route has transited (AS_SEQUENCE).
- Optional AS_SETs (unordered sets of ASes) when summarising.
- An AS_CONFED_SEQUENCE for confederations.
flowchart LR
R15["R15 · AS 64515 · originator"]
R14["R14 · AS 64514"]
R13["R13 · AS 64513"]
R12["R12 · AS 64512"]
R15 -- "AS_PATH: 64515" --> R14
R14 -- "AS_PATH: 64514 64515" --> R13
R13 -- "AS_PATH: 64513 64514 64515" --> R12
In R15’s own BGP table the locally-originated route has an
empty AS_PATH. The AS is added at the moment of eBGP
advertisement: the sending router prepends its own AS to the
front of the path, so R14 receives 64515. Each subsequent
eBGP hop prepends again, leftmost-is-newest, so the path R12
holds reads back as “originated in 64515, reached me via
64514 then 64513”.
The receiving router can read the AS_PATH and:
- Choose a path — shorter AS_PATH is preferred in the best-path algorithm (shorter = fewer AS hops).
- Detect loops — if the local AS is already in the AS_PATH, the router refuses to install the route (it would be a loop).
- Apply policy — filter based on AS_PATH content (regex match, AS_PATH length, neighbour-AS).
The VyOS configuration for prepend
AS path prepend is the operator’s tool for outbound traffic engineering — making the local AS look longer to a peer, so the peer prefers a different path for traffic destined to the local AS.
VyOS 1.4 restructured the BGP tree: the local AS moved from
set protocols bgp <asn> to set protocols bgp system-as <asn>, neighbours moved to set protocols bgp neighbor ...,
and per-neighbour route-maps moved under an explicit
address-family node.
# Define the route-map
set policy route-map PREPEND-TO-PROVIDER-A rule 10 action 'permit'
set policy route-map PREPEND-TO-PROVIDER-A rule 10 set as-path prepend '64512 64512 64512'
# Apply outbound to the peer
set protocols bgp system-as '64512'
set protocols bgp neighbor 10.0.0.1 remote-as '64998'
set protocols bgp neighbor 10.0.0.1 address-family ipv4-unicast route-map export 'PREPEND-TO-PROVIDER-A'
commit
save
The set as-path prepend '64512 64512 64512' adds three
copies of the local AS to the AS_PATH of every route
advertised to Provider A. When Provider A’s peer (and
downstream peers) see the AS_PATH, they see the route as
having transited AS 64512 three extra times — making the path
look longer than it actually is.
The effect: traffic destined to AS 64512’s prefixes prefers Provider B over Provider A, because Provider A’s path is longer.
Verifying the prepend needs care, because there are two prepends in play: the explicit one from the route-map, and the implicit one the sender adds at eBGP transmit.
$ show bgp ipv4 neighbors 10.0.0.1 advertised-routes Network Next Hop Metric LocPrf Weight Path
*> 192.0.2.0/24 0.0.0.0 32768 64512 64512 64512 iIllustrative output
Read the Path column, not the row count. The three 64512
entries are the explicit prepend from the route-map. Whether
the implicit eBGP prepend also appears in this local view is
an implementation detail of how the sender renders its
outbound table, so do not use this command to count total path
length. The authoritative answer is on the other side: ask
Provider A, or look the prefix up in a public looking glass,
and count the ASNs there.
Aggregation and AS_PATH loss
When the operator aggregates multiple prefixes into a summary, the aggregate is a locally-originated route: its AS_PATH is empty in the local BGP table, and an eBGP peer receives it carrying only the aggregator’s AS. The AS_PATHs of the contributing more-specifics are lost.
flowchart LR
A["192.0.2.0/24 from AS 64513"]
B["192.0.3.0/24 from AS 64514"]
C["192.0.4.0/24 from AS 64515"]
AGG["AS 64512 aggregates 192.0.2.0/22"]
D1["default: peer sees AS_PATH 64512"]
D2["as-set: peer sees 64512 {64513,64514,64515}"]
A --> AGG
B --> AGG
C --> AGG
AGG --> D1
AGG --> D2
The default aggregate carries no trace of where the more-specifics came from. The receiving peer cannot tell which ASes originated them.
The fix is as-set:
set protocols bgp address-family ipv4-unicast aggregate-address 192.0.2.0/22 as-set
set protocols bgp address-family ipv4-unicast aggregate-address 192.0.2.0/22 summary-only
With as-set, the AS_PATH gains an AS_SET segment listing the
ASes from the contributing paths: {64513,64514,64515}. The
set is unordered — it records membership, not sequence.
The set format has consequences:
- The whole set counts as one hop — an AS_SET contributes 1 to AS_PATH length no matter how many ASes are inside it. A three-AS set and a one-AS set look the same length to the best-path algorithm.
- Loop detection is by membership — if the local AS is in the set, the receiving router refuses the route, exactly as if it had appeared in a sequence.
- Downstream path-length-based filtering is weakened — a peer that uses AS_PATH length as a tie-breaker sees the aggregate as barely longer than a single-AS advertisement, whatever it is really summarising.
iBGP handling of AS_PATH
When a route is advertised between iBGP peers (within the same AS), the AS_PATH is not modified. The advertising router does not prepend its AS to the path on iBGP.
flowchart LR
EXT["eBGP peer in AS 64513"]
R1["R1 · AS 64512"]
R3["R3 · AS 64512 · iBGP"]
R4["R4 · AS 64512 · iBGP"]
EXT -- "AS_PATH: 64513" --> R1
R1 -- "AS_PATH: 64513 · unchanged" --> R3
R1 -- "AS_PATH: 64513 · unchanged" --> R4
R3 and R4 see the AS_PATH as 64513 (the upstream AS).
They do not see 64512 64513, which is what they would see
if the AS_PATH were modified on iBGP.
This is the loop-prevention mechanism for iBGP: if the local AS were prepended to the path on iBGP, every iBGP peer would see its own AS in the path and reject the route.
Loop detection and the local AS in the path
When the local AS appears in a received AS_PATH, the route
is discarded at input. It does not become a “valid but not
best” entry — it never enters the BGP table at all, so
show bgp ipv4 unicast 192.0.2.0/24 reports that the network
is not in the table.
That silence is the diagnostic problem: the absence of a route looks the same whether the peer never sent it, a prefix-list filtered it, or loop detection ate it. To tell them apart, turn on inbound soft reconfiguration so the router keeps the unmodified received UPDATEs:
set protocols bgp neighbor 10.0.0.2 address-family ipv4-unicast soft-reconfiguration inbound
Now compare the two views:
show bgp ipv4 neighbors 10.0.0.2 received-routes
show bgp ipv4 unicast 192.0.2.0/24
If the prefix is in the first output and missing from the
second, the router received it and threw it away. Read the
Path column in the first output: if your own ASN is in
there, you are looking at loop detection, and the fault is in
the topology or in someone’s redistribution — not in your BGP
configuration.
The deliberate override exists, for the case where two sites genuinely share one ASN and are joined through a provider:
set protocols bgp neighbor 10.0.0.2 address-family ipv4-unicast allowas-in number '2'
allowas-in number accepts a path containing the local AS up
to that many times (1-10), on eBGP peers only. It switches
off the protocol’s only loop protection for that neighbour, so
use it where the topology makes a loop impossible, and nowhere
else.
A subtle case: as-set loop detection. With as-set, the
local AS appearing in the set is a loop just as much as in a
sequence. Membership is what is checked, not order.
Validation
# 1. The AS_PATH the local router holds
show bgp ipv4 unicast 192.0.2.0/24
# 2. The prepend as it leaves this router
show bgp ipv4 neighbors 10.0.0.1 advertised-routes
# 3. The aggregate's AS_PATH
show bgp ipv4 unicast 192.0.2.0/22
# 4. What the iBGP peers hold, run on the iBGP peer itself
show bgp ipv4 unicast 192.0.2.0/24
For AS_PATH regex matching:
show bgp ipv4 regexp _64513_
The underscore matches an AS_PATH separator — a space, the
start of the path, or the end — so _64513_ finds AS 64513
anywhere in the path without also matching 645130 or 164513.
There is no “does not traverse” form of this command. To
express the negative you build it as policy, where a deny
rule is available:
set policy as-path-list NOT-VIA-64513 rule 10 action 'deny'
set policy as-path-list NOT-VIA-64513 rule 10 regex '_64513_'
set policy as-path-list NOT-VIA-64513 rule 20 action 'permit'
set policy as-path-list NOT-VIA-64513 rule 20 regex '.*'
set policy route-map AVOID-64513 rule 10 action 'permit'
set policy route-map AVOID-64513 rule 10 match as-path 'NOT-VIA-64513'
Failure modes
Prepend is ignored
The operator configured set as-path prepend '64512 64512 64512' on the outbound route-map, but the peer does not see
the prepend.
Diagnostic:
- Is the route-map applied, and in which direction?
show bgp neighbor 10.0.0.1reports the policy attached to the session;show configuration commands | match "neighbor 10.0.0.1"shows whether the node saysroute-map exportorroute-map import. Prepend belongs onexport. - Is the rule matching?
show configuration commands | match "route-map PREPEND-TO-PROVIDER-A". Walk the rules and confirm theset as-path prependclause sits on apermitrule that the prefix actually reaches — adenyrule earlier in the list stops it dead. - Is the session eBGP? Compare the neighbour’s
remote-aswithsystem-as. Prepend is only meaningful across an eBGP boundary: prepend your own AS towards an iBGP peer in the same AS and that peer’s loop detection is entitled to drop the route. - Did the route-map take effect on the existing session?
A new outbound policy applies to subsequent advertisements.
reset bgp ipv4 10.0.0.1 soft outre-sends the table without tearing the session down.
Prepend is applied but the path is still preferred
The operator prepended to Provider A; Provider B’s path is still preferred by the operator’s downstream peers.
Possible causes:
- The prepend is too short — three prepended ASes may not be enough; the operator may need five or ten.
- AS_PATH length is not the tie-breaker — the downstream peer uses LOCAL_PREF or weight to make the decision; AS_PATH is only consulted when those are equal.
- The downstream peer has its own policy — the downstream peer may be preferring Provider B for reasons outside the operator’s control.
The fix is more prepend, or a different attribute (LOCAL_PREF on the downstream peer, if the operator can influence it).
Aggregation lost the AS_PATH
The operator aggregated prefixes from multiple ASes; the peer sees only the aggregator’s AS.
The fix:
set protocols bgp address-family ipv4-unicast aggregate-address 192.0.2.0/22 as-set
The aggregate’s AS_PATH gains an AS_SET segment.
Loop detected
The local AS appears in the AS_PATH of a received route. The route is discarded.
Diagnostic:
- The topology has a routing loop. The fix is at the topology level.
- The aggregate’s
as-setincludes the local AS. The fix is to removeas-setand accept the information loss. - A redistribution is causing the route to be advertised
back into a path that already contains the local AS. The
fix is a filter on the redistribution, not
allowas-in.
Rollback
# Remove the prepend from the route-map
delete policy route-map PREPEND-TO-PROVIDER-A rule 10 set as-path prepend
commit
# Remove the route-map from the neighbour
delete protocols bgp neighbor 10.0.0.1 address-family ipv4-unicast route-map export
commit
# Remove the as-set from the aggregate
delete protocols bgp address-family ipv4-unicast aggregate-address 192.0.2.0/22 as-set
commit
The rollback for a prepend that caused a routing problem:
- Capture the before state (
show bgp ipv4 neighbors 10.0.0.1 advertised-routes). - Remove the prepend and commit.
- Push the change out with
reset bgp ipv4 10.0.0.1 soft outrather than waiting for the next update. - Confirm the downstream peers have re-converged — which means asking them or checking a looking glass, not reading your own table.
Production discipline
Cross-course references
- Part XXV-02 (
XXV-VyOS-BGPAdvertise/ aggregate) covers the aggregation that loses AS_PATH withoutas-set. - Part XXVI-01 (
XXVI-VyOS-BGPAttributes/ local-preference) is the higher-precedence attribute in the best-path algorithm. - Part XXVII (
XXVII-VyOS-BGPBestPath) covers the best-path algorithm in full. - Part XXXIII (
XXXIII-VyOS-RoutePolicy) covers the route-map primitives used here.
Quiz
Knowledge check · 4 questions
Q1. An operator wants to influence outbound traffic engineering. Where should the AS path prepend be configured?
Q2. When a route is advertised between iBGP peers (within the same AS), the AS_PATH is not modified by the advertising router.
Q3. R1 defines a route-map with `set as-path prepend '64512 64512 64512'` and attaches it with `set protocols bgp neighbor 10.0.0.1 address-family ipv4-unicast route-map import 'PREPEND'`. The peer does not see the prepend. What is wrong?
R1's configuration: set policy route-map PREPEND rule 10 action 'permit' set policy route-map PREPEND rule 10 set as-path prepend '64512 64512 64512' set protocols bgp system-as '64512' set protocols bgp neighbor 10.0.0.1 remote-as '64998' set protocols bgp neighbor 10.0.0.1 address-family ipv4-unicast route-map import 'PREPEND' The operator expects the peer at 10.0.0.1 to see a prepended AS_PATH. `show bgp ipv4 neighbors 10.0.0.1 advertised-routes` shows the original path, and the peer confirms the same.
Q4. R1 (AS 64512) aggregates 192.0.2.0/22 from three different ASes (64513, 64514, 64515) and advertises to Provider Z. Provider Z's engineer asks 'where did these prefixes originate?'. What is the fix?
R1: set protocols bgp system-as '64512' set protocols bgp address-family ipv4-unicast aggregate-address 192.0.2.0/22 summary-only set protocols bgp neighbor 10.0.0.99 remote-as '64999' The aggregate is advertised to Provider Z (AS 64999). Provider Z's engineer sees the aggregate with AS_PATH `64512` and nothing else — no indication of which ASes originated the contributing prefixes.
Passing score: 75%. Answers are checked in this browser.