Monthly Archives: July 2015

MPLS-TE with Class-Based Tunnel Selection

Someone asked about class based tunnel selection on a forum that I visit (www.techexams.net) and I thought that it would make a decent blog post. The question:

Now I want to simulate Class based tunnel selection in MPLS Core network running with IS-IS. Could be OSPF as well. Would be grate if in PE is configured VRF as well. And if I send packet from one PE vrf to another, different packets goes to different path.[1] 

From this question we are able to extract the following:

  • We need to create a MPLS-TE based VPN between two PE routers.
  • Transport across the core needs to use at least 4 different LSPs to allow packets to use different paths in both directions.
  • BGP needs to be involved to distribute VPNv4 or VPNv6 prefixes between PE routers.
  • Class-Based Tunnel Selection should be used on the PE routers to direct packets into a specific tunnel based on the packet marking.

1. Using MPLS-TE for VPNs

The data plane of an MPLS Layer 3 VPNs involves attaching two labels to each packet at the ingress PE router. The bottom label is called the VPN label and it’s sent from the egress PE to the ingree PE by BGP. It’s used by the egress PE router to switch the packet to the correct outgoing interface. The top label is called the IGP label and its purpose is to get the packet to the correct egress PE based on the BGP next hop of the destination. Now, in most cases the IGP label is distributed by LDP, but this doesn’t necessarily have to be the case, as we’ll see in this blog post.

2. What is MPLS-TE?

In a nutshell, MPLS Traffic Engineering is way to create an LSP between a ‘head end router’ (the LSP’s first router) and an IP destination. The traffic engineering aspect of it is that you have great control over how this LSP is created. For example, you can specify every single hop that the LSP should take, which allows you to route packets in ways that would be impossible using other methods, such as traditional IP routing protocols. In the next section we’ll start looking at TE  in a specific topology while building towards a solution for the person’s question.

3. Information Distribution

The IGP plays an important role in TE and it must be a link state protocol. Because IS-IS and OSPF are the only link state protocols that we use, that’s what you have to choose from. Here I’ll use OSPF since almost everyone that knows IS-IS knows OSPF, but the opposite isn’t the case. A link state IGP normally only carries information about links between nodes and the IP prefixes attached to these nodes. When TE is activated, the IGP also starts incorporating TE specific information about each link that is enabled for TE. In the case of OSPF, that information is exchanged between routers in a new LSA called the type 10. Before demonstrating this, let’s look at the topology that I’ll use throughout this post:

TE2

Loopbacks use 192.168.1.x where x is the router number. Links use 10.1.xy.z where x is the lowest router number, y the higher one and z the local router number. E.g. 10.1.24.2 on R2’s side of the R2 – R4 links. OSPF is configured as the IGP on all links and loopbacks on the provider routers. I’m using Cisco IOS on all routers.

Our first task will be to activate the TE capabilities of OSPF. That involves the following steps:

  1. Globally activate TE using the command router(config)#mpls traffic-eng tunnels. This doesn’t do anything besides making other TE commands actually. It also, presumably, activates some TE related process(es).
  2. Each interface must also be configured with the same command: router(config-if)#mpls traffic-eng tunnels.
  3. Under the OSPF router process, TE must be enabled for an area (0 in this case), and a TE router-id must be chosen.
    router(config-router)#mpls traffic-eng area 0
    router(config-router)#mpls traffic-eng router-id loopback0

There are a few different ways that we can verify that it’s configured properly. The command ‘show mpls traffic-eng tunnels summary’ should show that processes are running and that forwarding is enabled:

R2#show mpls traffic-eng tunnels summary
Signalling Summary:
    LSP Tunnels Process:            running
    Passive LSP Listener:           running
    RSVP Process:                   running
    Forwarding:                     enabled
    Head: 0 interfaces, 0 active signalling attempts, 0 established
          2 activations, 2 deactivations
          0 SSO recovery attempts, 0 SSO recovered
    Midpoints: 0, Tails: 0
    Periodic reoptimization:        every 3600 seconds, next in 2244 seconds
    Periodic FRR Promotion:         Not Running
    Periodic auto-bw collection:    every 300 seconds, next in 144 seconds

Verifying that the interfaces have TE enabled on them can be done with ‘show mpls interfaces’. The tunnel column should say yes:

R2#show mpls interfaces
Interface              IP            Tunnel   BGP Static Operational
GigabitEthernet0/2     No            Yes      No  No     Yes        
GigabitEthernet0/3     No            Yes      No  No     Yes

So what have we actually achieved by making OSPF “TE aware”? If we take a look at the OSPF database, we’ll see a new LSA called Type 10:

R2#show ip ospf database

...

                Type-10 Opaque Link Area Link States (Area 0)

Link ID         ADV Router      Age         Seq#       Checksum Opaque ID
1.0.0.0         2.2.2.2         183         0x80000013 0x009B10 0       
1.0.0.0         3.3.3.3         338         0x80000013 0x00871F 0       
1.0.0.0         4.4.4.4         64          0x80000013 0x00732E 0       
1.0.0.0         5.5.5.5         40          0x80000013 0x005F3D 0       
1.0.0.2         3.3.3.3         338         0x80000013 0x001FC7 2       
1.0.0.2         4.4.4.4         64          0x80000013 0x000C19 2       
1.0.0.2         5.5.5.5         40          0x80000013 0x00C1E4 2       
1.0.0.3         2.2.2.2         183         0x80000013 0x008D58 3       
1.0.0.3         3.3.3.3         338         0x80000013 0x009925 3       
1.0.0.3         4.4.4.4         64          0x80000013 0x00DA10 3       
1.0.0.3         5.5.5.5         40          0x80000013 0x00A816 3       
1.0.0.4         2.2.2.2         183         0x80000013 0x003E9F 4   

Each LSA represents one interface and it holds TE specific information (there’s also an LSA for each router that carries the MPLS-TE router-id). Let’s take a look at one of these LSAs:

R2#show ip ospf database opaque-area 1.0.0.2

            OSPF Router with ID (2.2.2.2) (Process ID 1)

                Type-10 Opaque Link Area Link States (Area 0)

  LS age: 633
  Options: (No TOS-capability, DC)
  LS Type: Opaque Area Link
  Link State ID: 1.0.0.2
  Opaque Type: 1
  Opaque ID: 2
  Advertising Router: 3.3.3.3
  LS Seq Number: 80000013
  Checksum: 0x1FC7
  Length: 132
  Fragment number : 2

    Link connected to Point-to-Point network
      Link ID : 2.2.2.2
      Interface Address : 10.1.23.3
      Neighbor Address : 10.1.23.2
      Admin Metric : 1
      Maximum bandwidth : 125000000
      Maximum reservable bandwidth : 125000000
      Number of Priority : 8
      Priority 0 : 125000000    Priority 1 : 125000000  
      Priority 2 : 125000000    Priority 3 : 125000000  
      Priority 4 : 125000000    Priority 5 : 125000000  
      Priority 6 : 125000000    Priority 7 : 125000000  
      Affinity Bit : 0x0
      IGP Metric : 1

    Number of Links : 1

The first paragraph gives us some general information, like the OSPF router id of the advertising router. The interface is then described, and using these LSAs, each router builds a database of each TE enabled link. In a normal SPF calculation OSPF finds the lowest cost path to destinations using the type 1,2,3,4,5 and 7 LSAs that we’re used to from IP routing. Similarly, the type 10 LSAs are used to find paths for TE LSPs. The big difference is that when you configure the TE tunnel on the head end router, you can impose various constraints on it based on the information carried in the type 10 LSA.

The most well known of these constraints is the bandwidth requirement. By configuring the ‘ip rsvp bandwidth’ command at the interface level, we can tell the TE database that a certain amount of bandwidth can be reserved in the outgoing direction of that interface. We can then specify that the TE tunnel must use a certain amount of bandwidth, and if that much is available on a path between head end and tail end, the tunnel satisfies the constraints imposed on it. When the tunnel is signaled, the reservable bandwidth is decreased with the amount that the tunnel uses. In my topology I have configured that a full 100% of the interface bandwidth is available to TE, but as we’ll see later, to create the LSPs that we’re interested in here, we don’t need to specify a bandwidth constraint at all.

Other information carried in the LSA is the administrative weigh (admin metric in the output) which is also called the “TE metric”, the attribute flags, the IGP metric, priority values and bandwidth per periority. Neither of these will be of further relevance in this post, but know that they too can be used to impose constraints on the TE tunnel and thereby control which interface a specific TE LSP can traverse.

4. Creating the LSPs

Now that all of our four routers (R2, R3, R4 and R5) have exchanged TE information through the type 10 LSA and built identical databases, we’re able to create the needed LSPs. But what is an LSP exactly? The acronym stands for Label Switched Path and it’s defined as a series of routers that a packet takes as it’s label switched through the network. To accomplish this, a router needs to be aware of what label packets will arrive with, what new label it should swap the incoming label to, and what outgoing interface it should use to send the packet further down the LSP. In the case of MPLS-TE, that information is distributed using the RSVP protocol.

However, before RSVP can do its thing, the head end router (the first router of the LSP) needs to come up with a path that the LSP should follow. There are two main ways that this can be done, dynamically and explicitly. With a dynamic path calculation, the head end uses the TE database to find the lowest metric path to the destination that satisfies any configured constraints, like the required bandwidth. In our case, dynamic paths would not be a good idea because we want the LSPs to take specific paths, and we want to know what LSPs go where.

On R2 we want one LSP that uses the R2 -> R3 -> R5 path and one that uses R2 -> R4 -> R5. Similarly, on R5 we want one LSP that arrives on R2 via R3 and one that goes via R4.

TE3

We need separate LSPs in each direction since an LSP is unidirectional. On R2 and R5, the top LSP that goes through R3 will be named tunnel3, and the bottom LSP will be named tunnel4.

Configuring this tunnel is done in two steps and the first step is define the explicit paths with the ip explicit-path command. Here I have defined one path that uses the link addresses on the R2 – R3 – R5 path, and one that uses the path via R4:

R2#show run | s ip explicit-path  
ip explicit-path name VIA_R3 enable
 next-address 10.1.23.3
 next-address 10.1.35.5
ip explicit-path name VIA_R4 enable
 next-address 10.1.24.4
 next-address 10.1.45.5

Equivalent configuration has been added on R5 for the LSPs in the opposite direction. Once the explicit paths are defined, we’re ready to do the actual tunnel configuration on R2 and R5. A minimal TE tunnel configuration requires the following:

  • Creating a tunnel interface and setting the tunnel mode to MPLS-TE.
  • A tunnel destination.
  • Setting the tunnel IP address by referencing a loopback address with the ip unnumbered feature.
  • Defining a path option.

(Note here that I don’t mention constraints like bandwidth or using the attribute flags/affinity bits. These features can be used, but it’s optional. If you for example don’t care about the bandwidth reservation aspect of MPLS-TE, you don’t have to use it, and in this case I think that it’s unnecessary.)

On R2, the configuration of tunnel3 and tunnel4 look like this:

interface Tunnel3
 ip unnumbered Loopback0
 tunnel mode mpls traffic-eng
 tunnel destination 192.168.1.5
 tunnel mpls traffic-eng path-option 1 explicit name VIA_R3
 no routing dynamic
!
interface Tunnel4
 ip unnumbered Loopback0
 tunnel mode mpls traffic-eng
 tunnel destination 192.168.1.5
 tunnel mpls traffic-eng path-option 1 explicit name VIA_R4
 no routing dynamic

The configuration is identical, except for the fact that the explicit path is different. The command ‘no routing dynamic’ is added by default and it prevents the router from sending routing updates using that interface. We can see the items that I listed before; a destination, tunnel mode is traffic-eng and we have an explicit path configured as the path option. On R5 I have made configuration where the only difference is that the destination is 192.168.1.2 instead of 192.168.1.5.

Once the tunnel configuration is made, RSVP signals the path based on the path option. The head end router initiates this signalling process by sending a message called ‘Path’ to what the path calculation has determined is the next hop. In our case the explicit path defines where the Path message is sent. The next hop router then determines if it has enough bandwidth on its outgoing interface to allow the signalling to take place. Normally, that should not be a problem because when the head end makes the path calculation it takes the the available bandwidth of links into account.

However, that calculation is based on the information that it has in its link state database and that information is not guaranteed to be exactly the same as the local information at all times. Another tunnel could reserve the bandwidth while the path setup is in progress. In our topology, that’s obviously not a problem, and besides, we haven’t even defined a bandwidth requirement.

Assuming that it passes the admission control that is this bandwidth reservation check, the Path message is sent to the next router in the list of hops that the head end has calculated. Eventually the Path message should reach the final router called the tail end router. The tail end router knows that it’s the tail because it’s the final address in the list of hops found in the Path message.

The tail end router replies with a ‘Resv’ (for Reservation) message that follows the same path of routers that the Path message did. The Resv message is what actually creates the LSP because each router uses it to send the label that it wants to see on incoming packets to its upstream neighbor. Then when a router actually receives a packet with that label in the data plane, the routers know what LSP the packet belongs to, and that it should swap the top label to the label that it has received from its downstream neighbor on the LSP. When the Resv message is received by the head end router, the LSP is fully signaled. RSVP is also used to periodically refresh each LSP to prevent it from timing out.

In our scenario we explicitly signaled 4 LSPs, but each tunnel configuration only has this single explicit path, with no other options. This means that if say R3 fails, the two LSPs traversing that router will fail, and they will not be rerouted to a different path. It’s likely that you want them to then instead use the path via R4. We could solve that by either adding a second explicit path with higher preference value, or adding a dynamic path option. I’m choosing the latter here which results in the following tunnel configuration:

interface Tunnel3
 ip unnumbered Loopback0
 tunnel mode mpls traffic-eng
 tunnel destination 192.168.1.5
 tunnel mpls traffic-eng path-option 1 explicit name VIA_R3
 tunnel mpls traffic-eng path-option 2 dynamic
 no routing dynamic
end

As we can see, we now have two path options. The explicit option will still be used first because it has the lower number, but should it fail, the dynamic one will be tried.

Verification of the signaled LSPs can be done with the ‘show mpls traffic-eng tunnels’ command. Here I’m looking at tunnel3 on R2:

R2#show mpls traffic-eng tunnels tunnel 3

Name: R2_t3                               (Tunnel3) Destination: 192.168.1.5
  Status:
    Admin: up         Oper: up     Path: valid       Signalling: connected
    path option 1, type explicit VIA_R3 (Basis for Setup, path weight 2)
    path option 2, type dynamic

...

  InLabel  :  - 
  OutLabel : GigabitEthernet0/2, 16
  RSVP Signalling Info:
       Src 192.168.1.2, Dst 192.168.1.5, Tun_Id 3, Tun_Instance 1
    RSVP Path Info:
      My Address: 10.1.23.2   
      Explicit Route: 10.1.23.3 10.1.35.5 192.168.1.5 
      Record   Route:   NONE
      Tspec: ave rate=0 kbits, burst=1000 bytes, peak rate=0 kbits
    RSVP Resv Info:
      Record   Route:   NONE
      Fspec: ave rate=0 kbits, burst=1000 bytes, peak rate=0 kbits

...

The command is quite verbose so I’ve omitted some of the information. What I have included tells us that the tunnel is up and that it’s using path option 1, our explicit path. We’re also able to tell exactly how the LSP is routed (10.2.23.3 to 10.1.35.5 to 192.168.1.5) and what label packets will get when they’re sent out the tunnel interface (16).

5. VRFs and BGP

Before continuing with the MPLS-TE discussion, let’s do a detour to BGP. In our network we want to combine TE tunnels with MPLS VPNs, and that means that we need VRFs and BGP. I won’t spend too much time on this section since it’s not the main focus of the blog post, but at a minimum we need a VRF on each PE router and a BGP session between the two PEs. I’ll then connect each CE router to its PE using BGP. Each CE will advertise its loopback address (192.168.1.1/32 and 192.168.1.6/32) into BGP.

TE4

The VRFs are configured with appropriate route targets to let routes from R1 reach R6, and vice versa. R2’s configuration is very simple and looks like this:

R2(config-router)#do show run | s router bgp 200
router bgp 200
 bgp log-neighbor-changes
 neighbor 192.168.1.5 remote-as 200
 neighbor 192.168.1.5 update-source Loopback0
 !
 address-family vpnv4
  neighbor 192.168.1.5 activate
  neighbor 192.168.1.5 send-community extended
 exit-address-family
 !
 address-family ipv4 vrf CUST_A
  neighbor 10.1.12.1 remote-as 100
  neighbor 10.1.12.1 activate
 exit-address-family
R2(config-router)#do show run | s ip vrf    
ip vrf CUST_A
 rd 200:100
 route-target export 200:1
 route-target import 200:1

The point here is to have BGP send the customer routes as VPNv4 prefixes from the egress PE to the ingree PE. That update will include a VPN label which we can see with ‘show bgp vpnv4 vrf CUST_A 192.168.1.6’:

R2#show bgp vpnv4 unicast vrf CUST_A 192.168.1.6/32
BGP routing table entry for 200:100:192.168.1.6/32, version 4
Paths: (1 available, best #1, table CUST_A)
  Advertised to update-groups:
     2         
  Refresh Epoch 2
  300, imported path from 200:300:192.168.1.6/32 (global)
    192.168.1.5 (metric 3) (via default) from 192.168.1.5 (192.168.1.5)
      Origin IGP, metric 0, localpref 100, valid, internal, best
      Extended Community: RT:200:1
      mpls labels in/out nolabel/16
      rx pathid: 0, tx pathid: 0x0

This output shows us that R2 needs to use label 16 when sending packets towards R5. When R5 receives packets with label 16, it knows what output interface to use for the packet (the interface towards R6 in this case).

The VPN will not work at this point and the problem is that there’s currently no way to get the VPN labeled packets from ingress to egress PE. In a “normal” MPLS VPN that’s handled by a combination of LDP and the IGP, but as you might expect, we’re instead going to use the TE tunnels that we’ve built between the two PE routers.

6. Forwarding Traffic Down Tunnels

As it stands, our TE tunnels cannot be used for anything. The path is signaled and ready to go, but directing traffic into the tunnels is a separate step that doesn’t happen automatically. There are numerous ways of doing this like static routing, policy based routing, something called autoroute, etc. In our scenario, we’ll use the autoroute feature.

When configuring autoroute on a TE tunnel interface you’re telling the router to see the tunnel as a directly connected link to the tunnel tail. The tunnel can then be used for packets that are destined to the tunnel tail end or to destinations beyond the tail.

What happens in this case when autoroute is enabled on all four tunnel interfaces (remember, LSPs are unidirectional so each PE has two tunnels each) is that the PEs start load sharing using these tunnels. The IGP/underlay path is no longer used at all for traffic between 192.168.1.2 and 192.168.1.5, and because of this, all VPN traffic is funneled into the tunnels as well. Curiously, the tunnel’s metrics are 3, the same as the IGP cost to reach the tunnel destination, and you could imagine that you would load share between the IGP paths and the tunnel paths, but this does not happen for destinations on the tail itself.

There’s a bit more to autoroute than this, but for our purposes it’s good enough to know that when autoroute is enabled, the ingress PE routers will start using their two tunnels to load share traffic destined for the egress PE. It’s easy to verify this with show ip route.

Before autoroute:

R2#show ip route 192.168.1.5
Routing entry for 192.168.1.5/32
  Known via "ospf 1", distance 110, metric 3, type intra area
  Last update from 10.1.23.3 on GigabitEthernet0/2, 00:00:28 ago
  Routing Descriptor Blocks:
  * 10.1.24.4, from 5.5.5.5, 00:00:28 ago, via GigabitEthernet0/3
      Route metric is 3, traffic share count is 1
    10.1.23.3, from 5.5.5.5, 00:00:28 ago, via GigabitEthernet0/2
      Route metric is 3, traffic share count is 1

Configuring autoroute:

R2(config)#int tun3
R2(config-if)#tunnel mpls traffic-eng autoroute announce

After autoroute:

R2#show ip route 192.168.1.5
Routing entry for 192.168.1.5/32
  Known via "ospf 1", distance 110, metric 3, type intra area
  Last update from 192.168.1.5 on Tunnel3, 09:42:13 ago
  Routing Descriptor Blocks:
    192.168.1.5, from 5.5.5.5, 09:42:13 ago, via Tunnel3
      Route metric is 3, traffic share count is 1
  * 192.168.1.5, from 5.5.5.5, 09:42:13 ago, via Tunnel4
      Route metric is 3, traffic share count is 1

There’s an obvious problem with this. While we can now send packets from R1 to R6, we’re not making any kind of decision based on what class packets belong to. This is where Class-Based Tunnel Selection needs to be configured.

7. Class-Based Tunnel Selection

When you have multiple tunnels between the same head- and tail-end it’s possible to make it so that packets choose a tunnel based on the EXP bits in the packet’s label. Because multiple tunnels between the same head and tail is exactly what we have here, we should be able to make CBTS happen. We’ll discuss this from the perspective of a packet that enters R2 from R1, but as with the other things that we have configured in this post, the concepts and configuration are exactly the same when packets enter R5 from R6.

When packets enter R2 from R1, they’re not marked with EXP bits obviously since they’re normal IP packets and don’t have a label. This is not a problem because the tunnel selection happens after the input classification and marking. We can therefore set the EXP bits on incoming packets with a policy map and have the tunnel selection be based on that. To not make things needlessly complicated, we’ll have a real time class that should take the top path via R3 (tunnel 3), and everything else will be sent via R4 (tunnel 4).

Classification of the real time traffic will be based on the customer having marked those packets with CS5 or EF. Such packets then have the EXP bits set to 5 on all their labels (two labels in this case – TE label and VPN label). All other packets will drop down to the default class and will not get any marking. This results in a very simple class-map and policy-map that looks like this:

R2#show run | s class-map|policy-map
class-map match-any REALTIME
 match dscp ef 
 match dscp cs5 
policy-map CUST_A_INGRESS
 class REALTIME
  set mpls experimental imposition 5

The first step in making tunnel3 carry the EXP 5 packets is to configured that tunnel interface with ‘tunnel mpls traffic-eng exp 5’. Tunnel 4 is configured with ‘tunnel mpls traffic-eng exp default’ to indicate that all other EXP markings should use that tunnel. Alternatively, you could explicitly configure tunnel 4 with all seven values that are not 5.

The next step is to configure a so called “master tunnel”. A master tunnel is an MPLS-TE tunnel interface that groups the tunnels that are involved in the CBTS, and then becomes the output interface for all packets that would normally use our tunnel 3 and 4. Once packets (conceptually) enter the master tunnel it directs the packets to the correct member tunnel based on the packet’s EXP value. This is the configuration of my master tunnel on R2:

R2#show run int tun10
!
interface Tunnel10
 ip unnumbered Loopback0
 tunnel mode mpls traffic-eng
 tunnel destination 192.168.1.5
 tunnel mpls traffic-eng autoroute announce
 tunnel mpls traffic-eng exp-bundle master
 tunnel mpls traffic-eng exp-bundle member Tunnel3
 tunnel mpls traffic-eng exp-bundle member Tunnel4
 no routing dynamic
end

If we take a look at show mpls traffic-eng tunnels tunnel10, we see that this isn’t a normal TE tunnel with a signaled LSP:

R2#show mpls traffic-eng tunnels tunnel10

Name: R2_t10                              (Tunnel10) Destination: 192.168.1.5
  Status: Master
    Admin: up         Oper: up     Signalling: N/A

    Member Tunnels:         Member Autoroute: Inactive
 
    Tunnel3: Config Exp:  5 
    Tunnel4: Config Exp:  default


  History:
    Tunnel:
      Time since created: 14 minutes, 18 seconds
      Number of LSP IDs (Tun_Instances) used: 0

The master tunnel is more like a configuration mechanism that’s relevant only locally at the head end. In the output above we’re able to tell that tunnel 3 handles EXP 5 and tunnel 4 everything else (‘default’). Looking at the forwarding to the egress PE the master tunnel is now the outgoing interface:

R2#show ip route 192.168.1.5
Routing entry for 192.168.1.5/32
  Known via "ospf 1", distance 110, metric 3, type intra area
  Last update from 192.168.1.5 on Tunnel10, 00:13:21 ago
  Routing Descriptor Blocks:
  * 192.168.1.5, from 5.5.5.5, 00:13:21 ago, via Tunnel10
      Route metric is 3, traffic share count is 1

At this point our MPLS-TE based VPN with CBTS should actually be operational. However, the post wouldn’t be complete without some kind of verification that packets actually are taking the correct paths based on DSCP markings set at the customer side. The method that I’ve chosen for this verification is to put an incoming policy map on R3 and R4 that matches EXP 5 and the customer prefixes. Assuming that our tunnel selection works, we should see an increase in EXP 5 packets on R3 when we send pings with DSCP 46. When ICMP packets are sent with no marking, we should see an increase in the counter on R4. We’ll also see some “noise” in the counters due to control plane packets, but this should be insignificant compared to our large number of ICMP echoes.

After sending 100 packets with DSCP 46 and 100 without any marking from R1 to R6, these are the results:

R3#show policy-map interface
 GigabitEthernet0/1 

  Service-policy input: EXP_5_COUNTER

    Class-map: EXP_5 (match-all)  
      100 packets, 12200 bytes
      5 minute offered rate 1000 bps
      Match: mpls experimental topmost 5 

    Class-map: class-default (match-any)  
      10 packets, 1308 bytes
      5 minute offered rate 0000 bps, drop rate 0000 bps
      Match: any 

On this router we expect to see packets with EXP 5 because R2 directed the packets down the tunnel that’s configured with an explicit path that traverses this router.

R4#show policy-map interface
 GigabitEthernet0/1 

  Service-policy input: EXP_5_COUNTER

    Class-map: EXP_5 (match-all)  
      0 packets, 0 bytes
      5 minute offered rate 0000 bps
      Match: mpls experimental topmost 5 

    Class-map: class-default (match-any)  
      115 packets, 13910 bytes
      5 minute offered rate 1000 bps, drop rate 0000 bps
      Match: any 

On R4 we’re not seeing any EXP 5 packets and everything is counted in the default class.