Skip to main content
RunBook Academy

VyOSXXVI · BGP AttributesAttributes

BGP MED — multi-exit discriminator, eBGP-only, and always-compare-med

Advanced⏱ ~22 minvyosvtyshshow ip bgpshow policy route-mapshow running-config

What you'll learn

  • Explain why MED is optional non-transitive and eBGP-only
  • Configure `set metric` on an outbound route-map to influence a peer's inbound selection
  • Use `bgp always-compare-med` to compare MED across ASes
  • Diagnose MED oscillation and `always-compare-med` interactions

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.

MED (Multi-Exit Discriminator) is the operator’s tool for inbound traffic engineering from a peer’s perspective. It tells the peer: “if you have multiple ways to enter my AS, prefer the path with the lower MED”. On VyOS 1.5 LTS / FRR 10.x, the configuration is set policy route-map ... set metric <0-4294967295> on an outbound route-map.

This lesson is the operator’s reference for MED: the optional non-transitive classification, eBGP-only propagation, MED oscillation, the always-compare-med knob, and how it fails in production.

What MED does

MED is a 32-bit unsigned integer carried in UPDATE messages. It is one of the BGP attributes defined by RFC 4271 with a specific role: it influences the peer’s selection of a path into the local AS.

flowchart LR
  subgraph "AS 64512 (operator)"
    R1["R1\noutbound to Provider A\nMED: 50"]
    R2["R2\noutbound to Provider B\nMED: 100"]
  end
  subgraph "AS 64513 (peer)"
    PR["Provider router\nselecting path into 64512"]
  end
  R1 -- "eBGP\nMED: 50" --> PR
  R2 -- "eBGP\nMED: 100" --> PR
  PR -- "prefers R1 (MED 50 < 100)" --> PR

Provider 64513’s router sees two paths into AS 64512 — one via R1 with MED 50, one via R2 with MED 100. Lower MED wins (best-path rule 6 in RFC 4271). Provider 64513 prefers R1 for traffic destined to AS 64512’s prefixes.

The MED is optional and non-transitive in RFC 4271’s classification:

  • Optional — BGP implementations are not required to recognise it (every modern implementation does).
  • Non-transitive — the attribute is not propagated beyond the receiving AS.

The non-transitive property is critical: MED is sent on eBGP, but is not propagated across iBGP or to the next eBGP peer. The receiving peer can use MED to select a path, but the receiving peer’s iBGP peers do not see the same MED value.

The VyOS configuration

MED is set via set metric on an outbound route-map:

# Define the route-maps
set policy route-map TO-PROVIDER-A rule 10 action permit
set policy route-map TO-PROVIDER-A rule 10 match ip address prefix-list MY-PREFIXES
set policy route-map TO-PROVIDER-A rule 10 set metric 50

set policy route-map TO-PROVIDER-B rule 10 action permit
set policy route-map TO-PROVIDER-B rule 10 match ip address prefix-list MY-PREFIXES
set policy route-map TO-PROVIDER-B rule 10 set metric 100

set policy prefix-list MY-PREFIXES rule 10 action permit
set policy prefix-list MY-PREFIXES rule 10 prefix 192.0.2.0/24

# Apply outbound to the peers
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 export TO-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 export TO-PROVIDER-B

commit
save

Three shape details in that block are worth reading slowly, because they are where a configuration copied from an older reference stops committing:

  • The ASN is the system-as leaf. It is not a node you descend through, so there is no protocols bgp 64512 neighbor ... path on a current release — neighbor is a sibling of system-as.
  • The outbound policy hangs off the neighbour’s address family, not off the neighbour directly, and the direction is a value of the route-map node rather than a trailing word: neighbor 10.0.0.1 address-family ipv4-unicast route-map export TO-PROVIDER-A. Configuring the family is also what activates it for that peer.
  • The prefix-list needs no explicit deny rule. Both prefix-lists and route-maps end in an implicit deny in FRR, and a VyOS prefix-list rule without a prefix fails validation anyway, so a trailing rule 20 action deny with nothing to match is not a belt-and-braces measure — it is a commit error.

After commit, the routes advertised to that peer carry the metric the route-map set. The MED is the Metric column:

Read-only / Safe
vyos@r1:~$ show ip bgp neighbors 10.0.0.1 advertised-routes
BGP table version is 100, local router ID is 1.1.1.1
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal,
            r RIB-failure, S Stale, R Removed

 Network          Next Hop            Metric LocPrf Weight Path
*> 192.0.2.0/24     0.0.0.0                 50         32768 i

Total number of prefixes 1

Illustrative output

If the Metric column is empty rather than showing 50, the route-map did not run on this advertisement — check that it is attached under address-family ipv4-unicast and that rule 10’s prefix-list actually matches the prefix. An unmatched route-map rule is not an error; the route is simply advertised with the attributes it already had.

Default MED

If a route does not have a MED explicitly set, the default is 0. This applies:

  • Routes originated via network (default MED 0).
  • Routes originated via redistribute without a metric (default MED 0).
  • Routes received from a peer without MED (default MED 0 on the receiving router).

The default of 0 means “no preference”. If the operator sets MED 50 on one path and leaves another at the default 0, the MED 0 path is preferred (lower MED wins).

The VyOS configuration for always-compare-med

By default, MED is compared only between paths from the same AS (the AS that advertised the routes). If the paths come from different ASes, MED is not used as a tie-breaker.

# Compare MED across ASes
set protocols bgp parameters always-compare-med

Like the other best-path knobs, this lives under protocols bgp parameters — the tree that holds the router-wide BGP behaviour, alongside router-id, deterministic-med and the bestpath options.

With always-compare-med, the router compares MED even between paths from different ASes. This is useful in multi-peer scenarios where the operator wants to use MED as a global tie-breaker.

flowchart LR
  subgraph "AS 64512 (operator)"
    R1
  end
  subgraph "AS 64513"
    P1["Provider A\nadvertises 8.8.8.0/24 with MED 50"]
  end
  subgraph "AS 64514"
    P2["Provider B\nadvertises 8.8.8.0/24 with MED 100"]
  end
  R1 -- "default behaviour:\nMED only compared\nwithin AS" --> R1
  R1 -- "always-compare-med:\nMED compared across AS" --> R1

Without always-compare-med, R1 may pick Provider B’s path (because Provider B’s AS-path is shorter, for example) and ignore the MED. With always-compare-med, R1 prefers the path with the lower MED (Provider A).

The always-compare-med setting is router-wide. It affects all BGP peers on the local router.

MED oscillation

The persistent oscillation RFC 3345 describes is not two routers arguing over MED values. It is a property of the comparison rule itself, and it is worth being precise about, because the wrong mental model sends the operator hunting for a policy loop that does not exist.

MED is compared only between paths learned from the same neighbouring AS. That restriction is what makes “path A is better than path B” a relation that is not transitive: A can beat B, B can beat C, and C can beat A, because each pairwise comparison stops at a different tie-breaker. A relation like that has no single winner — which winner you get depends on which paths you happened to compare.

When every router sees every path, the ambiguity is harmless: each router compares the same full set and arrives at the same answer. Route reflection and confederations remove that guarantee. A reflector passes on only its own best path, so its clients decide using a subset. The client’s decision changes the reflector’s inputs, the reflector’s new best path changes the client’s inputs, and the pair can settle into a cycle that never converges.

flowchart TB
  subgraph "AS 64512"
    RR["Route reflector
compares only the paths it holds
advertises one best path"]
    C1["Client A
decides on the subset the RR sent"]
    C2["Client B
decides on a different subset"]
  end
  E1["eBGP path from AS 64513
MED 50"] --> RR
  E2["eBGP path from AS 64513
MED 100"] --> C1
  E3["eBGP path from AS 64514
MED 10"] --> C2
  RR --> C1
  RR --> C2
  C1 --> RR
  C2 --> RR

The diagnostic signature is distinctive: the route flaps with no link flap, no session reset and no configuration change underneath it. show ip bgp 192.0.2.0/24 shows the > best-path marker moving between paths whose attributes are static, and the peers’ update counters climb steadily while nothing in the network is changing. That combination — motion in the RIB, stillness everywhere else — is what separates this from an ordinary flap.

VyOS exposes the two BGP parameters that bear on it:

# Make the comparison independent of the order paths arrived in
set protocols bgp parameters deterministic-med

# Make MED comparable across every AS, not just within one
set protocols bgp parameters always-compare-med

They do different jobs, and only one of them addresses the oscillation:

  • deterministic-med forces the router to group paths by neighbouring AS, pick a winner inside each group, and only then compare across groups. That removes the “same inputs, different best path depending on arrival order” class of surprise, which is the reason to have it on. It does not restore a total ordering, so it does not on its own make the reflector oscillation impossible.
  • always-compare-med makes MED comparable between every pair of paths, which does restore a total ordering and does remove the oscillation — at the cost of the behaviour change the callout above describes, applied router-wide. RFC 3345’s own structural remedies are of this shape: make the MED comparison global, or take it out of the decision entirely.

The design fixes are the durable ones. Avoid accepting MED for the same prefixes from more than one neighbouring AS behind a reflector; or give the clients the visibility the comparison assumes, with set protocols bgp neighbor 10.0.0.5 address-family ipv4-unicast addpath-tx-all-paths on the reflector so they see every path rather than one. Be deliberate about that last one — it increases what the reflector advertises, and therefore what its clients must hold.

Validation

# 1. The MED is what the operator expects
show ip bgp 192.0.2.0/24
# Look at the Metric column

# 2. The route-map is attached to the peer, in the right direction.
#    The neighbour detail names it: "Route map for outgoing
#    advertisements is *TO-PROVIDER-A"
show ip bgp neighbors 10.0.0.1

# 3. The metric override is in the route-map
show policy route-map TO-PROVIDER-A
# Look for "set metric"

# 4. The advertised routes carry the MED
show ip bgp neighbors 10.0.0.1 advertised-routes

# 5. The best-path parameters that are actually in effect
show configuration commands | match "protocols bgp parameters"
vtysh -c 'show running-config' | grep -E 'always-compare-med|deterministic-med'

Step 5 is two commands rather than one on purpose. The first reads VyOS’s intent; the second reads what FRR ended up with. They agree on a healthy router, and when they do not, the disagreement is the finding.

For every path the router holds for one prefix — which is the view that matters when you are asking why a particular path won — query the prefix directly:

Read-only / Safe
vyos@r1:~$ show ip bgp 192.0.2.0/24
BGP routing table entry for 192.0.2.0/24
Paths: (2 available, best #1, table default)
64513 15169
  10.0.0.1 from 10.0.0.1 (10.0.0.1)
    Origin IGP, metric 50, localpref 100, valid, external, best (MED)
64514 15169
  10.0.0.2 from 10.0.0.2 (10.0.0.2)
    Origin IGP, metric 100, localpref 100, valid, external

Illustrative output

Two things to read here. metric 50 and metric 100 are the MEDs. The parenthesised reason on the best line — (MED) — is FRR telling you which step of the decision process settled it. If that reason says something other than MED, then MED never got a vote, and whatever it names is the attribute you actually have to change.

Failure modes

MED is set but the peer is not honouring it

The operator set MED on the outbound route-map, but the peer picks a different path based on other attributes.

Diagnostic:

  • The peer’s best-path algorithm may have higher-precedence attributes that override MED (LOCAL_PREF, weight, AS_PATH).
  • The peer may have always-compare-med disabled, in which case MED is only compared within the peer’s AS.
  • The peer may have its own MED-setting policy that overrides the operator’s MED.

The fix: use a stronger attribute (LOCAL_PREF, AS_PATH prepend) to influence the peer’s selection.

Persistent oscillation behind a route reflector

The best-path marker moves between paths on its own. No link flapped, no session reset, and nobody committed anything.

Diagnostic:

  • show ip bgp 192.0.2.0/24 twice, a few seconds apart: the best marker has moved while every attribute in the entry is unchanged.
  • The topology has a route reflector or a confederation, and the prefix is reachable through more than one neighbouring AS.
  • show ip bgp summary shows the update counters climbing on the iBGP sessions with no external trigger.

Fix, in order of how disruptive it is: set protocols bgp parameters deterministic-med so the outcome at least stops depending on arrival order; give the clients full visibility with addpath-tx-all-paths on the reflector; or, if the peering design allows it, protocols bgp parameters always-compare-med to restore a total ordering. Re-read the always-compare-med callout before choosing the last one — it changes every best-path decision on the router, not just the oscillating prefix.

always-compare-med breaks the expected best-path

After enabling always-compare-med, the operator’s router picks a different path than before.

Diagnostic:

  • MED is now compared across ASes, which may invert the selection.

Fix: audit the MED values across all peers; adjust if necessary.

Rollback

# Remove the MED setting from the route-map
delete policy route-map TO-PROVIDER-A rule 10 set metric
commit

# Detach the route-map from the neighbour's address family
delete protocols bgp neighbor 10.0.0.1 address-family ipv4-unicast route-map export
commit

# Disable always-compare-med
delete protocols bgp parameters always-compare-med
commit

The middle command deletes the route-map export node, which takes the value with it. Deleting the whole address-family ipv4-unicast node instead would deactivate the family for that peer and tear the session’s IPv4 advertisements down with it — a much larger change than removing a policy.

The rollback for a MED that caused a routing problem:

  1. Capture the before state (show ip bgp <prefix>).
  2. Remove the MED setting or the route-map.
  3. Verify the after state (MED returns to default 0).
  4. Confirm the peers have re-converged.

Production discipline

Cross-course references

  • Part XXV (XXV-VyOS-BGPAdvertise) covers the origination primitives that produce routes with default MED 0.
  • Part XXVI-01 (XXVI-VyOS-BGPAttributes / local-preference) is the higher-precedence attribute in the best-path algorithm.
  • Part XXVI-02 (XXVI-VyOS-BGPAttributes / as-path) is the next attribute in the best-path algorithm.
  • Part XXVII (XXVII-VyOS-BGPBestPath) covers the best-path algorithm in full.
  • Part XXXIX (XXXIX-VyOS-MultiWAN) covers the multi-WAN use case where MED is the inbound traffic engineering tool.

Quiz

Knowledge check · 4 questions

  1. Q1. An operator wants to influence a peer's selection of which path to use for traffic destined to the operator's AS. Where should the MED be configured?

  2. Q2. MED is propagated across iBGP sessions within the receiving AS.

  3. Q3. A prefix reachable through two upstream ASes keeps changing best path inside your AS. No link has flapped, no session has reset, and nobody has committed a change. The topology uses a route reflector. What is happening, and what do you do about it?

    AS 64512 has one route reflector and two clients. 192.0.2.0/24 is learned from AS 64513 with MED 50 at the reflector and MED 100 at client A, and from AS 64514 with MED 10 at client B. `show ip bgp 192.0.2.0/24`, run twice a few seconds apart, shows the `>` best marker on a different path each time, with every attribute in the entry unchanged between runs. iBGP update counters in `show ip bgp summary` climb steadily. No eBGP session has bounced.

  4. Q4. R1 has two paths to 8.8.8.0/24. Path A is from Provider X (AS 64513, AS-path `64513 15169`, MED 50). Path B is from Provider Y (AS 64514, AS-path `64514`, MED 100). R1 prefers Path B (shorter AS-path). The operator enables `always-compare-med`. R1 now prefers Path A (lower MED). Is this expected?

    Before `always-compare-med`: Path A: AS 64513, MED 50, AS-path 64513 15169 (length 2) Path B: AS 64514, MED 100, AS-path 64514 (length 1) Best-path: Path B (shorter AS-path) After `always-compare-med`: Same paths, but MED is now compared. Best-path: Path A (lower MED)

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