Lesson Contents
In this lesson you will learn about the QoS Pre-classify feature. When you use tunnelling, your Cisco IOS router will do classification based on the outer (post) header, not the inner (pre) header. This can cause issues with QoS policies that are applied to the physical interfaces. I will explain the issue and we will take a look how we can fix it. Here’s the topology that we will use:
Below is the tunnel configuration, I’m using a static route so that R1 and R3 can reach each other’s loopback interfaces through the tunnel:
R1(config)#interface Tunnel 0
R1(config-if)#tunnel source 192.168.12.1
R1(config-if)#tunnel destination 192.168.23.3
R1(config-if)#ip address 172.16.13.1 255.255.255.0
R1(config)#ip route 3.3.3.3 255.255.255.255 172.16.13.3
The configuration on R3 is similar:
R3(config)#interface Tunnel 0
R3(config-if)#tunnel source 192.168.23.3
R3(config-if)#tunnel destination 192.168.12.1
R3(config-if)#ip address 172.16.13.3 255.255.255.0
R3(config)#ip route 1.1.1.1 255.255.255.255 172.16.13.1
The tunnel is up and running, before we play with classification and service policies, let’s take a look at the default classification behaviour of Cisco IOS when it comes to tunnelling…
Default Classification Behaviour
IOS will copy the information in the TOS (Type of Service) byte from the inner IP header to the outer IP header by default. We can demonstrate this with a simple ping, here’s how:
R1#ping
Protocol [ip]:
Target IP address: 3.3.3.3
Repeat count [5]:
Datagram size [100]:
Timeout in seconds [2]:
Extended commands [n]: y
Source address or interface: 1.1.1.1
Type of service [0]: 160
Set DF bit in IP header? [no]:
Validate reply data? [no]:
Data pattern [0xABCD]:
Loose, Strict, Record, Timestamp, Verbose[none]:
Sweep range of sizes [n]:
Type escape sequence to abort.
Sending 5, 100-byte ICMP Echos to 3.3.3.3, timeout is 2 seconds:
Packet sent with a source address of 1.1.1.1
!!!!!
Success rate is 100 percent (5/5), round-trip min/avg/max = 1/2/4 ms
This ping between 1.1.1.1 and 3.3.3.3 will go through the tunnel and I marked the TOS byte of this IP packet with 160 (decimal). 160 in binary is 10100000, remove the last two bits and you have our 6 DSCP bits. 101000 in binary is 40 in decimal which is the same as the CS5.
Below you can see a wireshark capture of this ping:
As you can see, Cisco IOS automatically copied the TOS byte from the inner IP header to the outer IP header. This is a good thing, I’m using GRE in my example so we can see both headers but if this was an encrypted IPSEC tunnel then we (and any device in between) could only see the outer header.
When you have QoS policies based on the TOS byte then you will have no problems at all because the TOS byte is copied from the inner to the outer header. You will run into issues when you have policies based on access-lists that match on source / destination addresses and/or port numbers. Let me give you an example…
Post Header Classification
I’m going to create two class-maps, one for telnet traffic and another one for GRE traffic. Both class-maps will use an access-list to classify traffic:
R1(config)#ip access-list extended TELNET
R1(config-ext-nacl)#permit tcp any any eq telnet
R1(config)#class-map TELNET
R1(config-cmap)#match access-group name TELNET
R1(config)#ip access-list extended GRE
R1(config-ext-nacl)#permit gre any any
R1(config)#class-map GRE
R1(config-cmap)#match access-group name GRE
The two class-maps will be used in a policy-map:
R1(config)#policy-map POLICE
R1(config-pmap)#class TELNET
R1(config-pmap-c)#police 128000
R1(config-pmap-c-police)#exit
R1(config-pmap-c)#exit
R1(config-pmap)#class GRE
R1(config-pmap-c)#exit
R1(config-pmap)#exit
I’ve added policing for telnet traffic and nothing for GRE. It doesn’t matter what “actions” we configure here, even without an action the traffic will still be classified and it will show up in the policy-map. Let’s activate it on the physical interface:
R1(config)#interface FastEthernet 0/0
R1(config-if)#service-policy output POLICE
Something to keep in mind is that when you enable a policy on the physical interface, it will be applied to all tunnel interfaces. Let’s generate some telnet traffic between R1 and R3 so it goes through the tunnel:
R1#telnet 3.3.3.3 /source-interface loopback 0
Trying 3.3.3.3 ... Open
Now take a look at the policy-map:
R1#show policy-map interface FastEthernet 0/0
FastEthernet0/0
Service-policy output: POLICE
Class-map: TELNET (match-all)
0 packets, 0 bytes
5 minute offered rate 0 bps, drop rate 0 bps
Match: access-group name TELNET
police:
cir 128000 bps, bc 4000 bytes
conformed 0 packets, 0 bytes; actions:
transmit
exceeded 0 packets, 0 bytes; actions:
drop
conformed 0 bps, exceed 0 bps
Class-map: GRE (match-all)
11 packets, 735 bytes
5 minute offered rate 0 bps
Match: access-group name GRE
Class-map: class-default (match-any)
2 packets, 120 bytes
5 minute offered rate 0 bps, drop rate 0 bps
Match: any
See how it only matches the GRE traffic? We don’t have any matches for the telnet traffic. If this was a real network, it means that telnet traffic will never get policed (or any other action you configured). The reason that we don’t see any matches is because Cisco IOS first encapsulates the IP packet and then applies the policy to the GRE traffic. Let me illustrate this:
The blue IP header on top is our original IP packet with telnet traffic, this is encapsulated and the router adds a GRE header and a new IP header (the red one). The policy-map is then applied to this outer IP header.
How do we fix this? There are a couple of options…let’s look at the first one!
Very clear and concise explanation, thank you
Thanks a lot for your excelent explanation…
Hello Rene,
I was very happy to find you had a lab on this subject. I went through this myself and everything worked as described, except one area. When I moved the service policy off the FA0/0 interface and put it on the Tunnel 0 interface (and removed the qos pre-qualify from the tunnel), the encapsulated IP header had the CS5 markings, but the outer header did not (as seen below)
Outer:
Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00: Not-ECT (Not ECN-Capable Transport))
Inner:
Differentiated Services Field: 0xa0 (DSCP 0x28: Class Select
... Continue reading in our forumHi None N
I tested this scenario again (GNS3, IOS 15.1), and confirmed my prior results. It sure looks like your configuration is the same as mine. When you did your extended ping, you chose TOS of 96, right?
Since all the config happens on R1, here’s the full config. If you paste this in, and still get different results, try again using an IOS 15 version for R1 (mine is c7200-adventerprisek9-mz.152-4.M6)
... Continue reading in our forumHello
I used the example above and everything works until I apply encryption and now I noticed that classification no longer works. Here are the configs from R1.
... Continue reading in our forumThe only thing I changed was the routing protocol over the tunnel and added some VTY password and now Im using VTI.
When I classify based on the ESP header it works as I see matches in my policy-map but thats not very useful when you want to match specific traffic within the inner packet as in this case, Telnet and police that traffic.