Ask ten network engineers to explain the difference between a route distinguisher and a route target and you will get four confident wrong answers, three "they're basically the same thing," and maybe three correct ones. The confusion is understandable: they look identical (65000:1), they are configured three lines apart, and in a simple any-to-any VPN they are usually set to the same value.
They do completely unrelated jobs. This article proves it with a single BGP table containing the same prefix twice. If you need the surrounding configuration, see MPLS L3VPN configuration step by step and the MPLS cluster guide.
One Sentence Each
Or, more bluntly: RD is identity, RT is policy. The RD answers "which route is this?" The RT answers "which VRFs should install it?"
Everything else in this article is a consequence of those two sentences.
The Problem the RD Solves
BGP carries routes. A route is a prefix plus attributes. If two customers both use 10.20.20.0/24 (and they will, because RFC 1918 space is not that big and everyone picks 10.x), then BGP sees two updates for the same prefix, runs the best-path algorithm, picks one, and throws the other away. Customer B's route is gone.
The route distinguisher fixes this by making the prefix longer. An RD is 64 bits. Glue it to the front of a 32-bit IPv4 prefix and you get a 96-bit VPNv4 prefix:
IPv4 prefix : 10.20.20.0/24
RD : 65000:1
VPNv4 prefix : 65000:1:10.20.20.0/24 <-- what BGP actually carriesNow customer A's route is 65000:1:10.20.20.0/24 and customer B's is 65000:2:10.20.20.0/24. Different prefixes. BGP keeps both. No best-path contest, no lost route.
That is the entire job. The RD is a uniqueness prefix. It carries no meaning, controls nothing, and is not used in any import or export decision.
Seeing it in one table
This is PE1 from the lab. VRF CUST-A (RD 65000:1) has learned 10.20.20.0/24 from the remote site over MP-BGP. VRF CUST-B (RD 65000:2) has 10.20.20.0/24 as a directly connected interface. Same prefix, same router, same BGP table:
PE1#show ip bgp vpnv4 all
Network Next Hop Metric LocPrf Weight Path
Route Distinguisher: 65000:1 (default for vrf CUST-A)
*> 1.1.1.1/32 10.20.1.2 0 0 65001 i
*>i 2.2.2.2/32 10.255.0.2 0 100 0 65001 i
*> 10.20.1.0/30 0.0.0.0 0 32768 ?
*>i 10.20.2.0/30 10.255.0.2 0 100 0 ?
*>i 10.20.20.0/24 10.255.0.2 0 100 0 65001 i
*> 192.168.99.0 10.20.1.2 0 0 65001 i
Route Distinguisher: 65000:2 (default for vrf CUST-B)
*> 10.20.20.0/24 0.0.0.0 0 32768 ?
*>i 10.20.99.0/24 10.255.0.2 0 100 0 ?Both 10.20.20.0/24 entries are present, both marked best (*>). Nothing was suppressed. Without the RD, one of them would be gone.
Drill into the prefix and the mechanism is explicit:
PE1#show ip bgp vpnv4 all 10.20.20.0/24
BGP routing table entry for 65000:1:10.20.20.0/24, version 13
Paths: (1 available, best #1, table CUST-A)
10.255.0.2 (metric 21) (via default) from 10.255.0.2 (10.255.0.2)
Origin incomplete, metric 0, localpref 100, valid, internal, best
Extended Community: RT:65000:1
mpls labels in/out nolabel/22
BGP routing table entry for 65000:2:10.20.20.0/24, version 2
Paths: (1 available, best #1, table CUST-B)
0.0.0.0 (via vrf CUST-B) from 0.0.0.0 (10.255.0.1)
Origin incomplete, metric 0, localpref 100, weight 32768, valid, sourced, best
Extended Community: RT:65000:2
mpls labels in/out 19/nolabel(CUST-B)Two distinct BGP table entries, keyed by 65000:1:10.20.20.0/24 and 65000:2:10.20.20.0/24. Each carries its own RT and its own VPN label. And the forwarding follows straight through:
PE1#show ip route vrf CUST-A 10.20.20.0 255.255.255.0
Routing entry for 10.20.20.0/24
Known via "bgp 65000", distance 200, metric 0, type internal
* 10.255.0.2 (default), from 10.255.0.2
MPLS label: 22
MPLS Flags: MPLS Required
PE1#show ip route vrf CUST-B 10.20.20.0 255.255.255.0
Routing entry for 10.20.20.0/24
Known via "connected", distance 0, metric 0 (connected, via interface)
* directly connected, via Loopback11Identical destination address, one router, two entirely different forwarding decisions. In CUST-A the packet gets VPN label 22 and crosses the MPLS core to PE2. In CUST-B it goes out a local interface. Neither customer knows the other exists.
The Problem the RT Solves
The RD made the routes unique. It did not decide who should receive them. That is the route target's job.
An RT is a BGP extended community, an 8-byte tag attached to the route as an attribute. It works in two halves:
route-target export 65000:1"When I send a route out of this VRF, stamp it with RT 65000:1."route-target import 65000:1"When a VPNv4 route arrives carrying RT 65000:1, install it in this VRF."That is the whole mechanism, and it is more powerful than it looks. Import and export lists are independent, and each can hold multiple values. The set of RTs a VRF exports and imports is the VPN topology:
import 999 alongside its own RT. Everyone reaches the shared service; nobody reaches each other.Not one line of that requires touching the RD. You build hub-and-spoke, extranets, management VRFs, and selective route leaking purely by editing import and export lists. This is why the RT is the interesting one and the RD is the plumbing.
Break the RT Import and Watch the VPN Die
Theory is cheap. Here is the same lab with one line removed from PE1's CUST-A VRF:
PE1(config)# vrf definition CUST-A
PE1(config-vrf)# address-family ipv4
PE1(config-vrf-af)# no route-target import 65000:1The export is still there. The RD is unchanged. The BGP session is untouched. Watch what happens:
PE1#show vrf detail CUST-A | include Export|Import|VRF
VRF CUST-A (VRF Id = 1); default RD 65000:1; default VPNID <not set>
Export VPN route-target communities
No Import VPN route-target communities
VRF label distribution protocol: not configured
PE1#show ip bgp vpnv4 all summary
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
10.20.1.2 4 65001 6 12 43 0 0 00:01:33 2
10.255.0.2 4 65000 24 19 43 0 0 00:07:35 1
PE1#show ip bgp vpnv4 rd 65000:1 10.20.20.0/24
BGP routing table entry for 65000:1:10.20.20.0/24, version 42
Paths: (0 available, no best path)
Not advertised to any peerThree things to read there. No Import VPN route-target communities is the smoking gun. The prefix count from the remote PE has collapsed from 4 to 1, because the RT filter is now rejecting almost everything at the door. And the prefix entry still exists in the table but with 0 available, no best path: BGP knows about the route, it just has no VRF willing to accept it.
From the customer's point of view, the VPN is simply broken:
j@llmbits:~$ ping -c 3 10.20.20.1
PING 10.20.20.1 (10.20.20.1) 56(84) bytes of data.
From 192.168.99.1 icmp_seq=1 Destination Host Unreachable
From 192.168.99.1 icmp_seq=2 Destination Host Unreachable
From 192.168.99.1 icmp_seq=3 Destination Host Unreachable
--- 10.20.20.1 ping statistics ---
3 packets transmitted, 0 received, +3 errors, 100% packet lossMP-BGP is up. LDP is up. The IGP is up. The routes are being advertised. And the customer cannot pass a packet, because one import statement is missing. This is the single most common L3VPN misconfiguration, and the reason show vrf detail should be the second command you run when a VPN is broken. There is a full methodology in Troubleshooting MPLS L3VPN: where VPN routes go missing.
A Related Trap: RTs Need Extended Communities Enabled
Because RTs are extended communities, they only survive the trip between PEs if the BGP session is configured to send them. Drop send-community extended from PE2's VPNv4 neighbor statement and the routes still get advertised, but with the RTs stripped off:
PE1#show ip bgp vpnv4 all summary
Neighbor V AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down State/PfxRcd
10.255.0.2 4 65000 44 25 56 0 0 00:12:24 0Zero prefixes received. Not because the session is down (it is up, and messages are flowing) but because every arriving route has no RT and therefore matches no import list. Same symptom as a missing import, different cause. Both live in the RT half of the world; neither has anything to do with the RD.
If They Do Different Jobs, Why Are They Usually the Same Number?
Because in a plain any-to-any VPN, one value works for both and nobody has a reason to complicate it. rd 65000:1, route-target both 65000:1, done.
The moment you build a hub-and-spoke or an extranet, they diverge, and the fact that they were never related becomes obvious. You will have one RD per VRF (often one per VRF per PE, which is a deliberate design for load-balancing and CE multihoming, since two different RDs on the same prefix let a route reflector keep both paths instead of picking one) and a whole set of RTs describing the topology.
The habit worth building: read rd as "identity" and route-target as "policy," even when the numbers match.
FAQ
Is the RD carried in BGP?
Yes, but as part of the prefix itself (the NLRI), not as an attribute. That is precisely why it makes the route unique. The RT is carried separately, as an extended community attribute.
Can two VRFs on the same PE use the same RD?
Technically yes if the prefixes never overlap, but do not. The RD's whole purpose is disambiguation; reusing it removes the safety net for zero benefit.
Can one VRF import multiple RTs?
Yes, and this is how extranets and shared services work. A VRF can import as many RTs as you like, and export more than one too.
Does the RD affect which VRF a route lands in?
No. That is the single most common misconception. Import is decided entirely by the RT. A route with the "wrong" RD but a matching RT will be imported; a route with a matching RD but no matching RT will not.
What format should I use?
ASN:number (65000:1) is by far the most common. IP:number (10.255.0.1:1) is also valid and is sometimes used so the RD identifies the originating PE at a glance.
Key Takeaways
- RD is identity. It prepends 64 bits to the IPv4 prefix, making a 96-bit VPNv4 route so overlapping customer address space does not collide in BGP.
- RT is policy. It is an extended community, stamped on export and filtered on import, and it alone decides which VRFs install a route.
- The RD plays no part in import decisions. Ever.
- VPN topology (any-to-any, hub-and-spoke, extranet) is built entirely from RT import and export lists.
- A missing
route-target importkills the VPN while every other check looks healthy. So does a missingsend-community extended, because RTs are extended communities. - They are usually the same number in simple VPNs. That is a coincidence of convenience, not a relationship.
Next: build the whole thing from scratch, or read the MPLS cluster guide.