QoS & The MQC – Part 2: Classification with Class Maps and NBAR

In the previous post we looked briefly at the MQC, and set up a basic QoS mechanism to classify a ping packet. In this post we will look closer at Class Maps, the match commands and classification using NBAR (Network Based Application Recognition).Packets are classified using the match command, and we have already seen that the list of things we can match is pretty huge, we can match on layer 2 (MAC addresses), layer 3 (IP, Access-lists, or applications), or even match that grey-area between layers, MPLS. If we choose to match by protocol then IOS will use Network Based Application Recognition (NBAR), and lastly we can match absolutely everything, using the any command.

We can have multiple match statements within a class-map, and here we pick up on something from the previous post:

R1(config)#class-map ?
  WORD       class-map name
  match-all  Logical-AND all matching statements under this classmap
  match-any  Logical-OR all matching statements under this classmap
  type       Configure CPL Class Map

We have the ability to match-all and match-any (a logical AND, or a logical OR), for example, we can match http traffic coming from a machine with a source mac-address:

class-map match-all example1
  match protocol http
  match source-address mac 0000.0000.0000

Or we can match traffic that matches either of these two conditions (either http, or coming from the same mac address:

class-map match-any example2
  match protocol http
  match source-address mac 0000.0000.0000

We can also match another class-map when we use the match-all or match-any option.

class-map match-any example3
  match class-map example1
  match dscp af12
With example3 we will match http and a source mac address of 0000.0000.0000 OR if the dscp value is af12. If we omit the match-any or match-all keyword then the default behaviour will be match-all.

We can match up to four CoS and IPP or eight DSCP values in a single command (match cos, match precedence or match dscp respectively).


NBAR is pretty cool, we have already used it in this post as whenever we use the match protocol command, this actually employs NBAR. What NBAR actually does is classify packets that would otherwise be hard to classify, such as where an application uses dynamic port numbers. NBAR can look into the packet using deep packet inspection and can match on things like host name, URL or MIME type.

Using this topology we have an HTTP server and a client set up:

From the client we can do a curl request to the http server and see a couple of pages, the default index.html page:

And a couple of pages that we will try and control using NBAR:

On R1 we configure the following:

class-map match-all CLS-DENY-FAIL-HTML
 match protocol http url "/fail.html"
interface FastEthernet0/1
 ip address
 duplex auto
 speed auto
 service-policy input POL-DENY-FAIL-HTML

And if we now test from the client machine we can see that (eventually) the curl requests times out:

But the request to pass.html still works:

With our router configuration placement is key. The same class-map and policy map set on R2 on the same interface in the outgoing direction does not work, and this is because our http server is listening on port 80 (http), but requests from the client will come from an ephemeral port, and therefore will not be matched to the http protocol.

We can make this example a bit more interesting and change the QoS values for the pass and fail pages. We will now set the pass.html page to be classified as CS5, and the fail.html page to be classifed as CS1:

class-map match-all CLS-CS1-FAIL-HTML
 match protocol http url "/fail.html"
class-map match-all CLS-CS5-PASS-HTML
 match protocol http url "/pass.html"
  set dscp cs5
  set dscp cs1
interface FastEthernet0/1
 ip address
 duplex auto
 speed auto
 service-policy input POL-CHANGE-CS-HTML

We can now look at the link between R1 and the http server and see that our requests are forwarded to the http server with different DSCP values:


Now if we do another wireshark capture either between the two routers, or between R2 and the client machine we can see that the DSCP value is returned as default – which makes sense because the service-policy is set as “input” on R1 rather than output. We can make sure that the return traffic gets the same DSCP values by specifying the same service-policy on R1 in an output direction, and this way the DSCP value is retained throughout the network.


Wireshark is a great way to confirm that our values are being set as we want them to be! Sadly as I am running a 3600 series router in GNS3 and not a 7200 embedded packet capture is not available. But this would be another way (and something we will cover later on) that would enable us to confirm the DSCP values through traffic capturing.