BGP · · 13 min read

BGP Best Path Selection Algorithm: All 13 Steps on Real Output

BGP evaluates 13 steps in order and stops at the first one that produces a winner. Here is the full order, with steps 1 and 2 proven on real show ip bgp output from a three-AS CML lab where the best marker moves between two paths as one attribute changes.

Terminal showing show ip bgp with two paths and the best marker moving between them

When a BGP router has multiple paths to the same prefix, it needs a deterministic way to pick one as the best. Cisco's BGP implementation uses a 13-step algorithm, evaluated top to bottom. The first step that produces a clear winner ends the evaluation, and everything below it is never consulted. That single sentence explains most of the confusion around this topic: engineers spend an afternoon tuning MED and wonder why nothing moved, because a weight set two years ago is still deciding the outcome at step 1.

This page is the reference version of that order. The first two steps are shown on real output captured from a live lab, where the same prefix arrives from two different autonomous systems and the best marker moves from one path to the other because exactly one attribute changed. The remaining steps are documented from Cisco's published algorithm and RFC 4271, and this article says plainly which is which. For where path selection sits inside the wider protocol, start at the complete BGP configuration and troubleshooting guide.

Everything below was captured on CML using iol-xe nodes running IOS XE 17.18.2, on 2026-07-20.

The lab behind these captures

Three routers, three autonomous systems, one prefix advertised twice. R1 in AS 65001 and R2 in AS 65002 each originate 100.100.100.0/24 from a loopback and advertise it to R3 in AS 65003. R3 makes the decision, and R3 is where every capture below was taken.

R1 (AS 65001)Lo1 100.100.100.1, Et0/0 10.0.13.1
R2 (AS 65002)Lo1 100.100.100.2, Et0/0 10.0.23.2
R3 (AS 65003)Et0/0 10.0.13.2, Et0/1 10.0.23.1
PlatformCML iol-xe, IOS XE 17.18.2
Contested prefix100.100.100.0/24, two eBGP paths

The symmetry is deliberate. Both paths are eBGP, both AS paths are one hop, both origins are IGP, both MEDs are 0. That strips away every tiebreaker below step 2, so the only thing that can decide the winner is the attribute being changed. Production networks rarely give you a signal that clean, which is exactly why the algorithm feels mysterious there.

Prerequisites for Path Consideration

Before a path even enters the best path algorithm, it must pass two checks:

  • Valid next-hop: The next-hop address must be reachable in the routing table. If it is not resolvable, the path is marked as "not valid" and excluded before any attribute is compared. This is the most common reason iBGP routes do not get installed - see BGP next-hop-self for the fix, and why a BGP route you can see in the table never reaches the RIB for the full diagnostic path.
  • Synchronized (if synchronization is enabled): The prefix must also exist in the IGP. Synchronization is disabled by default on modern IOS XE (no synchronization), so this check rarely applies.

In the captures below, both paths print valid, external. That word valid is the algorithm confirming both candidates cleared the gate and the comparison actually happened. A path that never prints valid did not lose the algorithm, it never entered it, and no amount of attribute tuning will change that.

The 13 Steps

Step 1: Highest Weight (Cisco-proprietary)

Weight is a Cisco-only attribute, local to the router, and it is never advertised to any peer. Default is 0 for learned routes and 32768 for locally originated routes. Higher weight wins.

R3(config)# router bgp 65003
R3(config-router)#  neighbor 10.0.13.1 weight 200

That sets weight 200 on every route from R1. Here is what R3 printed afterwards, verbatim:

R3# show ip bgp 100.100.100.0/24
BGP routing table entry for 100.100.100.0/24, version 3
Paths: (2 available, best #1, table default)
  65001
    10.0.13.1 from 10.0.13.1 (100.100.100.1)
      Origin IGP, metric 0, localpref 100, weight 200, valid, external, best     <== WEIGHT 200 wins
  65002
    10.0.23.2 from 10.0.23.2 (100.100.100.2)
      Origin IGP, metric 0, localpref 100, valid, external                       <== weight 0, not best

Read the two descriptor blocks side by side and the decision is obvious. localpref 100 on both, metric 0 on both, Origin IGP on both, one AS in each AS path. The only difference in the entire output is weight 200 on the first block, and that is enough to end the evaluation at step 1. Note also that the loser is not marked bad or invalid. It is still valid, external, ready to take over the instant the winner disappears.

Use weight to influence one router without affecting any other in your AS. That locality is a feature when you are steering a single border router, and a trap when someone sets it and forgets it, because no other device has any way to see it. Covered in depth in how to set BGP weight per neighbour.

Step 2: Highest Local Preference

LOCAL_PREF is an iBGP attribute (it is not sent to eBGP peers). Default is 100. Higher wins. Unlike weight, local-pref propagates to every iBGP peer in your AS, so it influences path selection network-wide rather than on one box.

To prove that step 2 only gets a vote once step 1 is a tie, the lab removed the weight and applied local-pref 200 to the other neighbour in the same change window:

R3(config)# router bgp 65003
R3(config-router)#  no neighbor 10.0.13.1 weight 200
R3(config)# route-map LP permit 10
R3(config-route-map)#  set local-preference 200
R3(config-router)#  neighbor 10.0.23.2 route-map LP in
R3# clear ip bgp * soft

The clear ip bgp * soft matters. An inbound route-map does not retroactively rewrite paths already in the table, so without it you stare at unchanged output and conclude the policy failed. After the refresh, R3 printed this:

R3# show ip bgp 100.100.100.0/24
BGP routing table entry for 100.100.100.0/24, version 5
Paths: (2 available, best #2, table default)
  65001
    10.0.13.1 from 10.0.13.1 (100.100.100.1)
      Origin IGP, metric 0, localpref 100, valid, external                        <== localpref 100, not best
  65002
    10.0.23.2 from 10.0.23.2 (100.100.100.2)
      Origin IGP, metric 0, localpref 200, valid, external, best                  <== LOCAL_PREF 200 wins

The best marker moved to the second block. Two other details changed. The table version incremented from 3 to 5, which is how you confirm BGP actually reprocessed the prefix rather than ignoring your change. And the header now says best #2 instead of best #1, naming the winning descriptor block by number so you do not have to scan for the best keyword. On a prefix with six paths, that number is the fastest thing on the screen.

Local preference is the right tool when the whole AS should agree on an exit point, and applying it is almost always an inbound route-map job as above. The mechanics and the common failure modes are in setting local preference to steer outbound traffic.

Step 3: Locally Originated

Prefer routes originated locally via the network command, redistribution, or aggregation over routes learned from a peer. Locally originated routes carry a weight of 32768, which usually wins at step 1 anyway, so this step exists to catch cases where weight was manually equalised across candidates.

Step 4: Shortest AS-Path

Count the ASes in the AS_PATH attribute, fewer is preferred. A route through AS 65010 (one hop) beats a route through AS 65020 then AS 65010 (two hops). Confederation sub-AS entries do not count, and an AS_SET counts as one regardless of how many ASes it contains.

This is the step that AS-path prepending targets, artificially lengthening the path to make a route less preferred downstream. It is the only widely portable way to influence how traffic comes back to you, and the trade-offs are in making a path less attractive to upstream providers. Note that bgp bestpath as-path ignore disables this step entirely, which some large networks do deliberately to rely purely on local-pref and MED.

Step 5: Lowest Origin Type

IGP (i) beats EGP (e) beats Incomplete (?). Routes injected via the network command get IGP origin, redistributed routes get Incomplete, and EGP origin is a historic artefact you will effectively never see. Both lab paths print Origin IGP because both were advertised with a network statement, so this step was a tie throughout.

Step 6: Lowest MED

The Multi-Exit Discriminator is a suggestion to your eBGP neighbour about which of your entry points to prefer. Lower wins, and a missing MED is treated as 0 on IOS by default. Critically, MED is only compared between paths learned from the same neighbouring AS, which is why it so often appears to do nothing.

bgp always-compare-med compares MED across all paths regardless of advertising AS, at the cost of making your outcome depend on numbers set by other people's networks. Scope rules are in influencing which link your provider sends traffic back on. In the lab both paths show metric 0 and come from different ASes, so MED was doubly irrelevant.

Step 7: eBGP over iBGP

Prefer eBGP-learned routes over iBGP-learned ones. The usual shorthand is the administrative distance difference, 20 for eBGP against 200 for iBGP, though the selection happens inside BGP before AD is ever consulted. Both lab paths print external, so this was another tie. For how BGP's two distances interact with every other protocol on the box, see how Cisco ranks routes from different protocols.

Step 8: Lowest IGP Metric to Next-Hop

If multiple paths are still equal, prefer the one whose BGP next-hop is closest in IGP cost. This is hot potato routing: hand the traffic to the nearest exit and let someone else carry it.

It becomes decisive in large networks with several border routers, where every path has identical policy and the only differentiator left is where traffic physically leaves. It also means an OSPF cost change on an unrelated link can silently move BGP traffic to a different border router, which is nasty to debug if you did not know this step existed. See how OSPF cost is calculated and changed.

Step 9: Multipath (if enabled)

If maximum-paths is configured and multiple paths are equal through step 8, install them all for ECMP load balancing. The algorithm still continues below this point to select a single best path, because BGP must nominate one path for advertisement even when forwarding across several. Configuration and equality rules are in load sharing across two upstream links.

Step 10: Oldest eBGP Path

Prefer the path that has been in the BGP table the longest. This is a stability rule, not a quality rule: do not flap between two equally good paths just because a new one appeared. It applies only between eBGP paths, and it is why a lab that looks deterministic on paper can produce different winners depending on boot order.

Step 11: Lowest Router ID

Compare the BGP router IDs of the advertising peers, lower wins. If the route came through a route reflector, the ORIGINATOR_ID is used instead. The router ID is the value in parentheses in the capture above, (100.100.100.1) and (100.100.100.2), so had the lab reached this step, R1 would have won on the lower value.

Step 12: Shortest Cluster List

In route reflector environments, prefer the path with the fewest cluster IDs in the CLUSTER_LIST, meaning the fewest reflection hops. If this step is deciding your traffic, your reflector hierarchy is doing more work than intended - see scaling iBGP without a full mesh.

Step 13: Lowest Neighbor Address

The final tiebreaker: prefer the path from the peer with the lowest IP address. It exists purely to guarantee determinism when everything above it is identical, and reaching it means you have no policy in play at all.

Get the BGP Field Reference - 9 pages, free

Everything you'd want to remember about BGP on nine printable pages. FSM diagram, all 13 best-path steps with gotchas, troubleshooting decision tree, copy-paste IOS XE templates, and real lab captures. Free for PingLabz members - just sign up with your email.

Get the BGP cheat-sheet

Which steps this lab actually proved

Here is the split. Two steps were exercised as deciders. Five more can be read as ties directly off the capture, because the output prints the attribute each one compares. The rest were never reached, and nothing on this page claims to have observed them.

Step 1, weightDecided phase 1 (200 vs 0)
Step 2, local preferenceDecided phase 2 (200 vs 100)
Step 3, locally originatedTie, neither path local to R3
Step 4, AS-path lengthTie, one AS each (65001 / 65002)
Step 5, originTie, Origin IGP on both
Step 6, MEDTie, metric 0 on both
Step 7, eBGP over iBGPTie, external on both
Steps 8 to 13Not reached, documented from the standard

Steps 8 through 13 as described above come from Cisco's published best path algorithm (document 13753) and the decision process in RFC 4271 section 9.1. They are the order your router uses, and this lab simply never had to invoke them because the contest was settled at the top. If you see a page claiming to show all thirteen steps firing on one prefix, be suspicious - by definition only one of them can be the decider.

Verifying the Decision

Three commands cover almost every real investigation, and the order you run them in matters.

show ip bgp                    ! table view, the ">" column marks best paths
show ip bgp 100.100.100.0/24   ! per-path descriptors, the "best" keyword and why
show ip bgp 100.100.100.0/24 bestpath   ! where supported, the winning path only

Start wide with show ip bgp to confirm the prefix is present and how many paths exist. Then go to the per-prefix view, the output shown twice above, because that is the only view printing every attribute the algorithm compares. Work down the descriptor blocks in algorithm order and stop at the first line where they differ. That difference is your answer, and any attribute below it is decoration.

Reading a descriptor block, line by line

The per-path output is dense, so it is worth decomposing one block from the phase 2 capture:

  65002
    10.0.23.2 from 10.0.23.2 (100.100.100.2)
      Origin IGP, metric 0, localpref 200, valid, external, best
  • 65002 is the AS_PATH. One entry means one AS to traverse, which is what step 4 counts.
  • 10.0.23.2 from 10.0.23.2 is next-hop from peer. When those differ you have a third-party next-hop or a route reflector, and the first value is the one that must be reachable.
  • (100.100.100.2) is the advertising router's BGP router ID, the value step 11 would compare.
  • Origin IGP, metric 0 and localpref 200 feed steps 5, 6 and 2 respectively.
  • valid means the next-hop resolved and the path entered the algorithm.
  • external means eBGP-learned, which is step 7's input.
  • best is the verdict. Cross-reference it with best #2 in the header line to be sure which block you are looking at.

Notice what is absent: there is no weight field at all. IOS omits weight when it is 0, so "no weight shown" and "weight 0" mean the same thing. In phase 1 the winner printed weight 200 and the loser printed nothing. If you are diffing two paths and one has a field the other does not, that asymmetry is usually the story.

For a structured walkthrough against a box that is misbehaving right now, rather than a lab built to demonstrate one attribute, go to how to diagnose BGP picking an unexpected exit on a live router.

Common Gotchas

  • The soft clear is not optional. An inbound route-map applies to updates as they arrive, and existing paths keep their old attributes until you run clear ip bgp * soft. In the lab the table version only moved from 3 to 5 after the refresh. If your output has not changed, check the version number before you change the policy again.
  • Weight is invisible from everywhere else. No neighbour can see it in any show command. Two engineers can look at the same prefix on two routers, reach opposite conclusions about the best path, and both be right.
  • MED comparison scope catches people constantly. MED is only compared between paths from the same AS by default. With paths from AS 65001 and AS 65002, as in this lab, MED is ignored no matter what values you set, unless bgp always-compare-med is configured.
  • The loser stays in the table. Both paths kept printing valid, external across both phases. A path without best is a healthy standby, not a broken route.
  • Next-hop unreachable skips the algorithm entirely. The path never competes, so tuning attributes on it does nothing. Verify next-hop reachability before you touch any policy.
  • Prepending loses to local-pref every time. Prepending adds AS-path length at step 4, but a competing path with higher local-pref wins at step 2 and step 4 is never evaluated. Three prepends will not beat one local-pref statement.
  • Trust best #N over your own scanning. The header line names the winning descriptor block by number, best #1 in phase 1 and best #2 in phase 2, which is faster and safer than reading six blocks looking for a keyword.

Setting this policy at scale

Everything above manipulates one neighbour at a time, which is fine for three routers and unmanageable for thirty. In production the attributes at steps 1, 2, 4 and 6 are rarely set per-neighbour by hand. They are set by matching a tag that travelled with the route, so a customer or upstream can signal intent and your edge policy translates it into local-pref or prepends automatically. That mechanism is covered in tagging routes so downstream policy can act on them.

Key Takeaways

  • BGP best path selection is a 13-step sequential algorithm. The first step to produce a winner ends the evaluation, and every step below it is irrelevant for that prefix.
  • The lab proved steps 1 and 2 directly: two eBGP paths for one prefix, with the best marker moving from R1 to R2 when weight was removed and local-pref 200 applied. Steps 3 to 7 read as ties in the same output. Steps 8 to 13 are documented from Cisco's algorithm and RFC 4271, not observed here.
  • Weight is Cisco-proprietary and local to one router. Local-pref propagates AS-wide. MED is a suggestion to your neighbour and is only compared within the same source AS by default.
  • A path must have a valid, reachable next-hop to enter the algorithm at all. valid in the output is the confirmation that it did.
  • Read the per-path descriptors in algorithm order and stop at the first attribute that differs. best #N in the header names the winning block for you.
  • Policy changes need clear ip bgp * soft before the table reflects them. Watch the version increment to confirm reprocessing happened.

Where to go next

This page is the reference for the order itself. These companions do jobs it deliberately does not, and belong alongside it rather than instead of it.

Diagnose it on a live box
The hands-on companion: a repeatable procedure for working out why a production router is using an exit you did not expect, right now.
Go deep on the attribute that usually decides
The attribute deep-dive: local preference on its own, including propagation rules, route-map placement and the ways it is commonly misapplied.
Understand the attributes the algorithm reads
Well-known, optional, transitive and discretionary: what each attribute is for before it becomes a tiebreaker.

If selection is behaving correctly but the winning route still is not forwarding traffic, the problem has moved downstream into installation, a separate diagnostic entirely. For everything else, the BGP reference hub collects the neighbour, attribute, policy and design material in one place.

Take the BGP reference with you
The free BGP field-reference PDF: path attributes, best-path order, and the show commands that matter. Delivered by email, no card required.
Get the free PDF

Read next

Terminal card showing a repeating CDP native VLAN mismatch log naming Ethernet0/0 native VLAN 1 against SW2 Ethernet0/0 native VLAN 99
VLANs ·

Native VLAN Mismatch: Read the CDP Log, Fix the Trunk

%CDP-4-NATIVE_VLAN_MISMATCH hands you both interfaces and both native VLANs in one line. The real damage is underneath it: untagged frames get re-homed at the trunk boundary and two VLANs quietly become one. Captured live on IOS XE 17.18.2 in CML.