↓ Skip to main content
  1. Network Articles/
  2. MPLS-VPN Articles/

Controlling routes with RTs in MPLS VPN (extranet, import and export maps)

Table of Contents

Controlling routes with RTs in MPLS VPN

An RT decides which VRF a route goes into (Route Target (RT) in MPLS VPN). Without touching the VRFs or the RDs, the RTs alone decide which sites can talk to which.

RFC 4364 section 4.3.1 starts by naming the two kinds.

There is a set of Route Targets that a PE router attaches to a route received from site S; these may be called the “Export Targets”. And there is a set of Route Targets that a PE router uses to determine whether a route received from another PE router could be placed in the VRF associated with site S; these may be called the “Import Targets”. The two sets are distinct, and need not be the same.

Export and import are separate sets, and they need not match. The condition for a route to enter a VRF is this.

Note that a particular VPN-IPv4 route is only eligible for installation in a particular VRF if there is some Route Target that is both one of the route’s Route Targets and one of the VRF’s Import Targets.

One of the RTs on the route has to be one of the import targets of the VRF. Everything that follows comes out of that single line.

One RT for everyone gives a full mesh

Section 4.3.5 shows two ways of building a VPN out of this attribute. The first is the one where every site can reach every other.

Suppose it is desired to create a fully meshed closed user group, i.e., a set of sites where each can send traffic directly to the other, but traffic cannot be sent to or received from other sites. Then each site is associated with a VRF, a single Route Target attribute is chosen, that Route Target is assigned to each VRF as both the Import Target and the Export Target, and that Route Target is not assigned to any other VRFs as either the Import Target or the Export Target.

Pick one RT and put it on the export and the import of every VRF. That is the simplest arrangement, and the default shape of an MPLS VPN.

Making them asymmetric cuts the sites off from each other

The second uses two RTs to build a design that goes through a central site.

Alternatively, suppose one desired, for whatever reason, to create a “hub and spoke” kind of VPN. This could be done by the use of two Route Target values, one meaning “Hub” and one meaning “Spoke”. At the VRFs attached to the hub sites, “Hub” is the Export Target and “Spoke” is the Import Target. At the VRFs attached to the spoke site, “Hub” is the Import Target and “Spoke” is the Export Target.

As a table:

VRFexportimport
Central site (hub)HubSpoke
Branch (spoke)SpokeHub

A route from a spoke carries Spoke. No other spoke imports Spoke, so the spokes never receive each other’s routes. The hub does import Spoke, so the hub and each spoke can exchange routes.

What this stops is direct traffic between spokes. Carrying traffic between spokes through the hub needs something more: the hub CE has to re-advertise the routes (covered in hub and spoke in MPLS VPN).

An extranet is the same mechanism

Exchanging RTs with the VRF of another customer shares part of one VPN with the other. That is an extranet. The same holds between two VRFs on one PE, as section 4.3.6 spells out.

the decision to distribute a particular route from one VRF to another within a single PE is the same decision that would be made if the VRFs were on different PEs. That is, it depends on the Route Target attribute that is assigned to the route … and the import target of the second VRF.

Just adding the RT brings in every route of the other VRF. To share only part of it, filter by prefix on import. In IOS XR that is import route-policy.

Filtering on import (IOS XR)
prefix-set B-PRIVATE
  10.2.8.1/32
end-set
!
route-policy EXTRANET-IN
  if destination in B-PRIVATE then
    drop
  else
    pass
  endif
end-policy
!
vrf CUST-A
 address-family ipv4 unicast
  import route-target
   65001:200
  !
  import route-policy EXTRANET-IN

The policy applies to every route being imported. Writing it as “pass only the shared prefix” would drop the routes of your own VPN as well, so the policy drops what should not come in and passes the rest.

The lab

Customer A has a hub (CE-HUB) and two spokes (CE-SP1 and CE-SP2); customer B is a separate VRF. The two spokes are on different PEs. Side by side in one VRF on one PE they could reach each other whatever the RTs say, and the isolation would not be visible. eBGP runs between PE and CE, with a different AS for each CE.

STEPChangeWhat it shows
0Initial state (every VRF on 65001:100)Full mesh. Spoke 1 can ping spoke 2
1Asymmetric RTs (hub export 65001:1000 / import 65001:1001, spokes the other way)The hub is reachable, the spokes are not. The other spoke disappears from the BGP table
2Add import 65001:1001 to the VRF of spoke 1 onlyThe route is there but the ping fails: import is set on the receiving side, so there is no return path
3Undo STEP 2Back to the state of STEP 1
4Extranet (the hub imports 65001:200 with an import route-policy; CUST-B imports the hub)Only the shared prefix of customer B gets through. 10.2.8.1/32 never arrives, and the spokes cannot reach customer B
5Undo STEP 4 (final state)Back to the previous state

One RT for everyone gives a full mesh

In the initial state every VRF has 65001:100 as both its export and its import target.

STEP 0: the VRF on PE1 (excerpt)
VRF CUST-A; RD 65001:1; VPN ID not set
VRF mode: Regular
Description not set
Interfaces:
  GigabitEthernet0/0/0/0
Address family IPV4 Unicast
  Import VPN route-target communities:
    RT:65001:100
  Export VPN route-target communities:
    RT:65001:100
  No import route policy
  No export route policy

The BGP table of spoke 1 holds both the hub (10.1.1.1/32) and the other spoke (10.1.3.1/32).

STEP 0: the BGP table of CE-SP1
RP/0/RP0/CPU0:CE-SP1#show bgp
Mon Oct 12 23:50:55.966 UTC
BGP router identifier 12.12.12.12, local AS number 65102
BGP generic scan interval 60 secs
Non-stop routing is enabled
BGP table state: Active
Table ID: 0xe0000000   RD version: 8
BGP main routing table version 8
BGP NSR Initial initsync version 3 (Reached)
BGP NSR/ISSU Sync-Group versions 0/0
BGP scan interval 60 secs

Status codes: s suppressed, d damped, h history, * valid, > best
              i - internal, r RIB-failure, S stale, N Nexthop-discard
Origin codes: i - IGP, e - EGP, ? - incomplete
   Network            Next Hop            Metric LocPrf Weight Path
*> 10.1.1.1/32        172.16.2.1                             0 65001 65101 i
*> 10.1.2.1/32        0.0.0.0                  0         32768 i
*> 10.1.3.1/32        172.16.2.1                             0 65001 65103 i
*> 172.16.1.0/24      172.16.2.1                             0 65001 ?
*> 172.16.2.0/24      172.16.2.1               0             0 65001 ?
*> 172.16.3.0/24      172.16.2.1                             0 65001 ?

Processed 6 prefixes, 6 paths

Spoke 1 can ping spoke 2.

STEP 0: ping from CE-SP1 to CE-SP2
RP/0/RP0/CPU0:CE-SP1#ping 10.1.3.1 source 10.1.2.1 count 10 timeout 1
Mon Oct 12 23:47:46.834 UTC
Type escape sequence to abort.
Sending 10, 100-byte ICMP Echos to 10.1.3.1 timeout is 1 seconds:
!!!!!!!!!!
Success rate is 100 percent (10/10), round-trip min/avg/max = 12/14/22 ms

Asymmetric RTs cut the spokes off from each other

The VRF of the hub exports 65001:1000 and imports 65001:1001; the spokes do the opposite.

STEP 1: configuration committed on PE1 (the hub side)
vrf CUST-A
 address-family ipv4 unicast
  import route-target
   no 65001:100
   65001:1001
  !
  export route-target
   no 65001:100
   65001:1000
  !
 !
!
end
STEP 1: configuration committed on PE2 (a spoke side)
vrf CUST-A
 address-family ipv4 unicast
  import route-target
   no 65001:100
   65001:1000
  !
  export route-target
   no 65001:100
   65001:1001
  !
 !
!
end

The RT carried in the VPNv4 UPDATE changes with it: a route from the hub now carries 65001:1000. This is No.9 of the attached STEP 1 capture.

STEP 1 No.9 VPNv4 UPDATE (PE1 to P1), Extended Communities (tshark -V excerpt)
        Path Attribute - EXTENDED_COMMUNITIES
            Flags: 0xc0, Optional, Transitive, Complete
                1... .... = Optional: Set
                .1.. .... = Transitive: Set
                ..0. .... = Partial: Not set
                ...0 .... = Extended-Length: Not set
                .... 0000 = Unused: 0x0
            Type Code: EXTENDED_COMMUNITIES (16)
            Length: 8
            Carried extended communities: (1 community)
                Route Target: 65001:1000 [Transitive 2-Octet AS-Specific]
                    Type: Transitive 2-Octet AS-Specific (0x00)
                        0... .... = IANA Authority: Allocated on First Come First Serve Basis
                        .0.. .... = Transitive across ASes: Transitive
                    Subtype (AS2): Route Target (0x02)
                    2-Octet AS: 65001
                    4-Octet AN: 1000
Download the pcap of the packet in the tshark output above (No.9 VPNv4 UPDATE)

The other spoke is gone from the BGP table of spoke 1. The hub is still there.

STEP 1: the BGP table of CE-SP1
RP/0/RP0/CPU0:CE-SP1#show bgp
Mon Oct 12 23:58:18.400 UTC
BGP router identifier 12.12.12.12, local AS number 65102
BGP generic scan interval 60 secs
Non-stop routing is enabled
BGP table state: Active
Table ID: 0xe0000000   RD version: 14
BGP main routing table version 14
BGP NSR Initial initsync version 3 (Reached)
BGP NSR/ISSU Sync-Group versions 0/0
BGP scan interval 60 secs

Status codes: s suppressed, d damped, h history, * valid, > best
              i - internal, r RIB-failure, S stale, N Nexthop-discard
Origin codes: i - IGP, e - EGP, ? - incomplete
   Network            Next Hop            Metric LocPrf Weight Path
*> 10.1.1.1/32        172.16.2.1                             0 65001 65101 i
*> 10.1.2.1/32        0.0.0.0                  0         32768 i
*> 172.16.1.0/24      172.16.2.1                             0 65001 ?
*> 172.16.2.0/24      172.16.2.1               0             0 65001 ?

Processed 4 prefixes, 4 paths

And the ping fails.

STEP 1: ping from CE-SP1 to CE-SP2
RP/0/RP0/CPU0:CE-SP1#ping 10.1.3.1 source 10.1.2.1 count 10 timeout 1
Mon Oct 12 23:54:50.213 UTC
Type escape sequence to abort.
Sending 10, 100-byte ICMP Echos to 10.1.3.1 timeout is 1 seconds:
..........
Success rate is 0 percent (0/10)

Import is set on the receiving side

65001:1001, which the other spoke exports, is added to the VRF of spoke 1 only.

STEP 2: configuration committed on PE2
vrf CUST-A
 address-family ipv4 unicast
  import route-target
   65001:1001
  !
 !
!
end

The route of the other spoke is back in the BGP table of spoke 1.

STEP 2: the BGP table of CE-SP1
RP/0/RP0/CPU0:CE-SP1#show bgp
Tue Oct 13 00:05:30.410 UTC
BGP router identifier 12.12.12.12, local AS number 65102
BGP generic scan interval 60 secs
Non-stop routing is enabled
BGP table state: Active
Table ID: 0xe0000000   RD version: 16
BGP main routing table version 16
BGP NSR Initial initsync version 3 (Reached)
BGP NSR/ISSU Sync-Group versions 0/0
BGP scan interval 60 secs

Status codes: s suppressed, d damped, h history, * valid, > best
              i - internal, r RIB-failure, S stale, N Nexthop-discard
Origin codes: i - IGP, e - EGP, ? - incomplete
   Network            Next Hop            Metric LocPrf Weight Path
*> 10.1.1.1/32        172.16.2.1                             0 65001 65101 i
*> 10.1.2.1/32        0.0.0.0                  0         32768 i
*> 10.1.3.1/32        172.16.2.1                             0 65001 65103 i
*> 172.16.1.0/24      172.16.2.1                             0 65001 ?
*> 172.16.2.0/24      172.16.2.1               0             0 65001 ?
*> 172.16.3.0/24      172.16.2.1                             0 65001 ?

Processed 6 prefixes, 6 paths

The ping still fails.

STEP 2: ping from CE-SP1 to CE-SP2
RP/0/RP0/CPU0:CE-SP1#ping 10.1.3.1 source 10.1.2.1 count 10 timeout 1
Tue Oct 13 00:01:48.348 UTC
Type escape sequence to abort.
Sending 10, 100-byte ICMP Echos to 10.1.3.1 timeout is 1 seconds:
..........
Success rate is 0 percent (0/10)

Import belongs to the VRF that receives. Spoke 1 can now take the other spoke’s route, but spoke 2 does not take spoke 1’s route, so nothing comes back. Adding it on one side alone does not make a working path.

Extranet

The VRF of the hub imports the RT of customer B (65001:200), and an import route-policy drops the prefix that is not shared.

STEP 4: configuration committed on PE1
vrf CUST-A
 address-family ipv4 unicast
  import route-policy EXTRANET-IN
  import route-target
   65001:200
  !
 !
!
prefix-set B-PRIVATE
  10.2.8.1/32
end-set
!
route-policy EXTRANET-IN
  if destination in B-PRIVATE then
    drop
  else
    pass
  endif
end-policy
!
end

Customer B imports the export target of the hub (65001:1000).

STEP 4: configuration committed on PE3
vrf CUST-B
 address-family ipv4 unicast
  import route-target
   65001:1000
  !
 !
!
end

Only the shared prefix of customer B (10.2.9.1/32) is in the BGP table of the hub. 10.2.8.1/32 is not.

STEP 4: the BGP table of CE-HUB
RP/0/RP0/CPU0:CE-HUB#show bgp
Tue Oct 13 00:19:07.218 UTC
BGP router identifier 11.11.11.11, local AS number 65101
BGP generic scan interval 60 secs
Non-stop routing is enabled
BGP table state: Active
Table ID: 0xe0000000   RD version: 18
BGP main routing table version 18
BGP NSR Initial initsync version 3 (Reached)
BGP NSR/ISSU Sync-Group versions 0/0
BGP scan interval 60 secs

Status codes: s suppressed, d damped, h history, * valid, > best
              i - internal, r RIB-failure, S stale, N Nexthop-discard
Origin codes: i - IGP, e - EGP, ? - incomplete
   Network            Next Hop            Metric LocPrf Weight Path
*> 10.1.1.1/32        0.0.0.0                  0         32768 i
*> 10.1.2.1/32        172.16.1.1                             0 65001 65102 i
*> 10.1.3.1/32        172.16.1.1                             0 65001 65103 i
*> 10.2.9.1/32        172.16.1.1                             0 65001 65201 i
*> 172.16.1.0/24      172.16.1.1               0             0 65001 ?
*> 172.16.2.0/24      172.16.1.1                             0 65001 ?
*> 172.16.3.0/24      172.16.1.1                             0 65001 ?
*> 172.16.4.0/24      172.16.1.1                             0 65001 ?

Processed 8 prefixes, 8 paths

The pings agree: the shared prefix answers, the other one does not.

STEP 4: ping from CE-HUB to 10.2.9.1
RP/0/RP0/CPU0:CE-HUB#ping 10.2.9.1 source 10.1.1.1 count 10 timeout 1
Tue Oct 13 00:15:29.309 UTC
Type escape sequence to abort.
Sending 10, 100-byte ICMP Echos to 10.2.9.1 timeout is 1 seconds:
!!!!!!!!!!
Success rate is 100 percent (10/10), round-trip min/avg/max = 12/23/71 ms
STEP 4: ping from CE-HUB to 10.2.8.1
RP/0/RP0/CPU0:CE-HUB#ping 10.2.8.1 source 10.1.1.1 count 10 timeout 1
Tue Oct 13 00:15:30.334 UTC
Type escape sequence to abort.
Sending 10, 100-byte ICMP Echos to 10.2.8.1 timeout is 1 seconds:
..........
Success rate is 0 percent (0/10)

The spokes cannot reach customer B at all, because only the VRF of the hub imports its RT.

STEP 4: ping from CE-SP1 to 10.2.9.1
RP/0/RP0/CPU0:CE-SP1#ping 10.2.9.1 source 10.1.2.1 count 10 timeout 1
Tue Oct 13 00:16:11.037 UTC
Type escape sequence to abort.
Sending 10, 100-byte ICMP Echos to 10.2.9.1 timeout is 1 seconds:
..........
Success rate is 0 percent (0/10)

Verification configs and show output

For every STEP the following files were collected from all eight routers, separated per router. The verification config is ..._run.txt (the final state is the one from the last STEP).

FileContents
..._show.txtshow version / show interface description / the OSPF, LDP, BGP and VRF show commands
..._log.txtshow logging limited to that STEP
..._run.txtshow running-config at that STEP (the verification config)
..._ping.txtping and traceroute for that STEP (from every CE to every CE)
..._trace.txtshow bgp trace (PEs only)
..._commit.cfgThe configuration actually committed in that STEP (only on routers that changed)

STEP 0: Initial state (every VRF on 65001:100)

Routershowsyslogrunning-configpingtracecommitted config
CE-HUBshowlogrunping--
PE1showlogrunpingtrace-
P1showlogrunping--
PE2showlogrunpingtrace-
CE-SP1showlogrunping--
PE3showlogrunpingtrace-
CE-SP2showlogrunping--
CE-Bshowlogrunping--

STEP 1: Asymmetric RTs (hub export 65001:1000 / import 65001:1001, spokes the other way)

Routershowsyslogrunning-configpingtracecommitted config
CE-HUBshowlogrunping--
PE1showlogrunpingtracecommit
P1showlogrunping--
PE2showlogrunpingtracecommit
CE-SP1showlogrunping--
PE3showlogrunpingtracecommit
CE-SP2showlogrunping--
CE-Bshowlogrunping--

STEP 2: Add import 65001:1001 to the VRF of spoke 1 only

Routershowsyslogrunning-configpingtracecommitted config
CE-HUBshowlogrunping--
PE1showlogrunpingtrace-
P1showlogrunping--
PE2showlogrunpingtracecommit
CE-SP1showlogrunping--
PE3showlogrunpingtrace-
CE-SP2showlogrunping--
CE-Bshowlogrunping--

STEP 3: Undo STEP 2

Routershowsyslogrunning-configpingtracecommitted config
CE-HUBshowlogrunping--
PE1showlogrunpingtrace-
P1showlogrunping--
PE2showlogrunpingtracecommit
CE-SP1showlogrunping--
PE3showlogrunpingtrace-
CE-SP2showlogrunping--
CE-Bshowlogrunping--

STEP 4: Extranet (the hub imports 65001:200 with an import route-policy; CUST-B imports the hub)

Routershowsyslogrunning-configpingtracecommitted config
CE-HUBshowlogrunping--
PE1showlogrunpingtracecommit
P1showlogrunping--
PE2showlogrunpingtrace-
CE-SP1showlogrunping--
PE3showlogrunpingtracecommit
CE-SP2showlogrunping--
CE-Bshowlogrunping--

STEP 5: Undo STEP 4 (final state)

Routershowsyslogrunning-configpingtracecommitted config
CE-HUBshowlogrunping--
PE1showlogrunpingtracecommit
P1showlogrunping--
PE2showlogrunpingtrace-
CE-SP1showlogrunping--
PE3showlogrunpingtracecommit
CE-SP2showlogrunping--
CE-Bshowlogrunping--

Packet captures were taken per STEP.

STEPPE1-P1PE2-CE-SP1
0pcappcap
1pcappcap
2pcappcap
3pcappcap
4pcappcap
5pcappcap

Related articles