QoS pre-classification
Implementing quality of service provisions on virtual tunnel interfaces (VTIs) poses a challenge: QoS policy enforcement is normally applied only after tunnel encapsulation has taken place. Consider the following service policy applied to a GRE tunnel:
class-map match-all ICMP match access-group name MATCH_ICMP class-map match-all GRE match access-group name MATCH_GRE ! ! policy-map MyPolicy class ICMP class GRE ! interface Tunnel0 ip address 192.168.0.1 255.255.255.252 tunnel source 10.0.0.1 tunnel destination 10.0.0.2 ! interface FastEthernet0/0 ip address 10.0.0.1 255.255.255.252 service-policy output MyPolicy ! ip access-list extended MATCH_GRE permit gre any any ip access-list extended MATCH_ICMP permit icmp any any
(Note that the policy map used as an example here does not actually enforce any policy; its class maps are included simply to illustrate the manner in which packets are being matched.)
In default operation, our QoS policy will be applied to packets exiting the physical interface only after they have undergone tunnel encapsulation:

When we generate ICMP traffic to the far end of the tunnel, we can verify that our policy only matches the packets as GRE traffic:
R1# ping 192.168.0.2 repeat 10 Type escape sequence to abort. Sending 10, 100-byte ICMP Echos to 192.168.0.2, timeout is 2 seconds: !!!!!!!!!! Success rate is 100 percent (10/10), round-trip min/avg/max = 8/10/24 ms R1# show policy-map interface f0/0 FastEthernet0/0 Service-policy output: MyPolicy Class-map: ICMP (match-all) 0 packets, 0 bytes 30 second offered rate 0 bps Match: protocol icmp Class-map: GRE (match-all) 10 packets, 1240 bytes 30 second offered rate 0 bps Match: protocol gre Class-map: class-default (match-any) 5 packets, 620 bytes 30 second offered rate 0 bps, drop rate 0 bps Match: any
This hinders our ability to differentiate between packets which have undergone tunnel encapsulation. However, enabling QoS pre-classification configures the tunnel interface to maintain a copy of the original packet in memory long enough for the physical interface policy to inspect it.

After enabling pre-classification, our policy is applied to the original "inner" header instead of the encapsulation header:
R1# conf t Enter configuration commands, one per line. End with CNTL/Z. R1(config)# interface tunnel0 R1(config-if)# qos pre-classify R1(config-if)# ^Z R1# clear counters f0/0 Clear "show interface" counters on this interface [confirm] R1# ping 192.168.0.2 repeat 10 Type escape sequence to abort. Sending 10, 100-byte ICMP Echos to 192.168.0.2, timeout is 2 seconds: !!!!!!!!!! Success rate is 100 percent (10/10), round-trip min/avg/max = 4/8/12 ms R1# show policy-map interface f0/0 FastEthernet0/0 Service-policy output: MyPolicy Class-map: ICMP (match-all) 10 packets, 1240 bytes 30 second offered rate 0 bps Match: access-group name MATCH_ICMP Class-map: GRE (match-all) 0 packets, 0 bytes 30 second offered rate 0 bps Match: access-group name MATCH_GRE Class-map: class-default (match-any) 2 packets, 120 bytes 30 second offered rate 0 bps, drop rate 0 bps Match: any
A couple side notes from my experiments on IOS 12.4(22)T:
-
I initially wrote the class maps to utilize NBAR (match protocol), but for some reason the ICMP class map didn't appear to take effect, so I switched to extended ACLs. Your mileage may vary.
-
Pre-classification seems to have no effect when applied to a VTI performing native IPsec encapsulation (versus a crypto map). Again, this may be IOS version-specific.
Comments
Gran articulo.. me parece estupendo el apote. Se agradecen los comnocimientos :-)
Hi Jeremy Nice article and good explanation of the pre-classification but with VTIs you could also put the policy-map directly onto the VTI itself, same goes for a GRE Tunnel. No need for a pre-classification in that way. best regards
Michel
It might also be important to ensure everyone understands that "qos pre-classify" only carries the temporary copy of the header on the local router.
Once the traffic has exited the physical interface, the header is discarded. Thanks for the quick write up.
The article is really awesome but still I have a doubt how to implement it in IP VPN cloud where in 90% of the customers use GRE.
If the classification policy matches on the ToS byte (and not by using ACLs like in your example), it is not necessary to use the qos pre-classify command. The ToS byte from the original IP header is copied to the outer header by the tunneling mechanism by default.
Good point made by Jan-Klaas Kesteloot above. I would avoid using QoS pre-classify if at all possible as this "feature" regularly has quite a few bugs - advice I received from Cisco TAC. Try a search in the bug tool for "QoS preclassify". Much safer and more reliable to have the traffic marked already and apply based on the ToS byte that is copied from the original packet into the GRE packet.
Hey Stretch, I know this article is a bit old, but I wanted you to know that it helped me out. I was labbing another bloggers post (really close to this one) on this same subject in preparation for my ONT exam, and ran into some NBAR troubles. I was classifying esp, gre, and icmp, and for some reason gre (when using NBAR) was getting the hits when I had the policy applied to the physical int, and the qos pre-classify applied to the tunnel, when I pinged across. I found your article confirming my suspicions and replaced them with acl's and whoila! Works as designed. Do you think this is an IOS bug or just the way NBAR looks at traffic?


Great article! I don't think I've ever seen QoS pre-classification presented so clearly and simply. I was never sure I completely understood it after the ONT book.