How to Implement Priority Queuing on the ASA

Last week, I wrote about one of the typical scenarios that we run into with ASA implementation. As described here, that scenario is one in which the ASA can transmit traffic at 100Mb/s (or 1000Mb/s), but our service provider dropped traffic that was beyond the contract rate. The problem with that was that the ASA, under our administrative control, had no discrimination in the packets that were dropped. The solution to this problem was to move the network bottleneck into the ASA. Then it can drop traffic that is outside the acceptable rate and use a priority queue to bypass other queued packets. This is known as hierarchical priority queuing. Today’s article demonstrates the use of hierarchical priority queuing in the ASA.

For this example, we will reference the following diagram.

To build out this scenario, I used Cisco 1760 Routers and an ASA5505. The “Host” is actually a Cisco router used to emulate a PC.

The ASA has a basic configuration and a tunnel built for a loopback IP address on the router “Outside”. The router “Outside” has a “rate-limit” (aka car) statement to limit the traffic to about 1Mb/s. The rate-limit configuration is as follows.

Outside#show run int fa0/0
Building configuration...

Current configuration : 204 bytes
!
interface FastEthernet0/0
description To Customer
ip address 192.0.2.1 255.255.255.0
ip access-group 101 in
rate-limit input 1000000 10000 10000 conform-action transmit exceed-action drop
speed auto
crypto map MYMAP
end

The next challenge is creating enough traffic that we exceed our contract rate of 1Mb/s. I have found that I can achieve this by sending large pings with a timeout of zero. On my 1760’s, this seems to produce close to 8Mb/s. To do this, I ping an interface on “Outside” with the following command. I used router “Inside” as the source of this traffic.

Inside>en
Inside#ping 192.0.2.1 repeat 2147483647 timeout 0 size 1250

Type escape sequence to abort.
Sending 2147483647, 1250-byte ICMP Echos to 192.0.2.1, timeout is 0 seconds:
......................................................................
......................................................................
......................................................................
......................................................................
......................................................................
......................................................................
......................................................................
......................................................................

The above will generate traffic for quite a while. When I need to stop it, I simply do a “ctrl-shift-6”.

With our contract rate being oversubscribed, we can send some normal pings to “Outside” from “HOST”.

HOST#ping 192.0.2.1 repeat 40 size 1250 

Type escape sequence to abort.
Sending 40, 1250-byte ICMP Echos to 192.0.2.1, timeout is 2 seconds:
...!!!!!!..!!!!!!..!!!!!!!!..!!!!!..!!!!
Success rate is 72 percent (29/40), round-trip min/avg/max = 176/178/181 ms

HOST#ping 192.0.2.1 repeat 40

Type escape sequence to abort.
Sending 40, 100-byte ICMP Echos to 192.0.2.1, timeout is 2 seconds:
!!!!!!.!.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Success rate is 95 percent (38/40), round-trip min/avg/max = 16/17/20 ms

The results are not terrible with the 100 byte pings, but drops are occurring. The issue is more pronounced with the 1250 byte packets. These drops are most likely occurring beyond our ASA. The ASA should certainly be able to handle the traffic we are sending to it. So what happens if we send it some traffic that is marked with the TOS value of 184  (DSCP EF) like voice would have?

HOST#ping
Protocol [ip]:
Target IP address: 192.0.2.1
Repeat count [5]: 40
Datagram size [100]: 1250
Timeout in seconds [2]:
Extended commands [n]: y
Source address or interface:
Type of service [0]: 184
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 40, 1250-byte ICMP Echos to 192.0.2.1, timeout is 2 seconds:
....!!!!!!.....!!!..!!!!!!..!!!!!!!..!!!
Success rate is 62 percent (25/40), round-trip min/avg/max = 176/178/181 ms
HOST#

The results are roughly the same as sending traffic without special TOS markings.

Let’s give our EF (TOS 184) packets priority by throttling back that traffic in our ASA and assigning EF to the priority queue.

//this shapes all traffic to 1Mb/s
//moving the bottleneck to the ASA
ASA(config-pmap-c)# policy-map HPQ
ASA(config-pmap)#class class-default
ASA(config-pmap-c)#shape average 1000000

//attach the policy to the outside interface
ASA(config)#service-policy HPQ interface outside

//to prioritize the EF traffic, we need to embed
//another policy inside the policy map HPQ
//but first we need to create it

//configure a class map to match EF
ASA(config)#class-map EF
ASA(config-cmap)#match dscp ef

//configure a policy map to prioritize traffic
ASA(config)# policy-map PRIORITY
ASA(config-pmap)#class EF
ASA(config-pmap-c)#priority

//embed the priority policy into the
//already created shaping policy
ASA(config-pmap-c)#policy-map HPQ
ASA(config-pmap)#class class-default
ASA(config-pmap-c)#service-policy PRIORITY

//not absolutely sure if the interface needs the pq command,
//but its definitely something to be aware of
ASA(config)#priority-queue outside

//clear connection so connections will be new and shaped
ASA(config)# clear conn
0 connection(s) deleted.

//final configuration
ASA(config)# show run class-map EF
!
class-map EF
 match dscp ef
!
ASA(config)# show run policy-map PRIORITY
!
policy-map PRIORITY
 class EF
  priority
!
ASA(config)# show run policy-map HPQ
!
policy-map HPQ
 class class-default
  shape average 1000000
  service-policy PRIORITY
!
ASA(config)# show run service-policy
service-policy global_policy global
service-policy HPQ interface outside

Now we need to make sure we are exceeding our contract rate and retest our traffic from “HOST”.

Inside#ping 192.0.2.1 repeat 2147483647 timeout 0 size 1250

Type escape sequence to abort.
Sending 2147483647, 1250-byte ICMP Echos to 192.0.2.1, timeout is 0 seconds:
......................................................................
......................................................................
......................................................................
......................................................................
......................................................................
......................................................................
......................................................................
......................................................................

Now to test from HOST.

HOST#ping
Protocol [ip]:
Target IP address: 192.0.2.1
Repeat count [5]: 100
Datagram size [100]: 1250
Timeout in seconds [2]:
Extended commands [n]: y
Source address or interface:
Type of service [0]: 184
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 100, 1250-byte ICMP Echos to 192.0.2.1, timeout is 2 seconds:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Success rate is 100 percent (100/100), round-trip min/avg/max = 176/178/181 ms
HOST#

Great 100% is much better than 62%. But let’s test a little more.

//a little more EF traffic shows that we still aren't 100%

HOST#ping
Protocol [ip]:
Target IP address: 192.0.2.1
Repeat count [5]: 400
Datagram size [100]:
Timeout in seconds [2]:
Extended commands [n]: y
Source address or interface:
Type of service [0]: 184
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 400, 100-byte ICMP Echos to 192.0.2.1, timeout is 2 seconds:
!!!!!!!!!!.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.
!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!!!!!!!!.!!!.!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!!.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!.!!!.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Success rate is 96 percent (387/400), round-trip min/avg/max = 16/17/24 ms

//but it is significatly better than ToS 0

HOST#ping 192.0.2.1 repeat 1000

Type escape sequence to abort.
Sending 1000, 100-byte ICMP Echos to 192.0.2.1, timeout is 2 seconds:
!!!!!!!!!!!!!!!!!!!!!!!!!!!..!!!!!!!!!!!!.!.!..!!!!!!!!!!!!!!!!!!!!!!!
!!!!!..!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!.!...
Success rate is 88 percent (101/114), round-trip min/avg/max = 16/64/698 ms
HOST#

As you can see, I am getting inconsistent results still. 96% is better than 62%, but I have just statistically made my odds better. There are still drops that are not occurring in the ASA’s shaping queue. Let’s lower the queue just a bit. This must be done in multiples of 8000.

ASA(config)# policy-map HPQ
ASA(config-pmap)# class class-default
ASA(config-pmap-c)# shape average 992000
ASA(config-pmap-c)# exit
ASA(config)# clear conn
0 connection(s) deleted.

Now let’s test a couple more times.

//first with small packets
HOST#ping
Protocol [ip]:
Target IP address: 192.0.2.1
Repeat count [5]: 400
Datagram size [100]:
Timeout in seconds [2]:
Extended commands [n]: y
Source address or interface:
Type of service [0]: 184
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 400, 100-byte ICMP Echos to 192.0.2.1, timeout is 2 seconds:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Success rate is 100 percent (400/400), round-trip min/avg/max = 16/17/21 ms

//then with larger ones
HOST#ping
Protocol [ip]:
Target IP address: 192.0.2.1
Repeat count [5]: 400
Datagram size [100]: 1250
Timeout in seconds [2]:
Extended commands [n]: y
Source address or interface:
Type of service [0]: 184
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 400, 1250-byte ICMP Echos to 192.0.2.1, timeout is 2 seconds:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Success rate is 100 percent (400/400), round-trip min/avg/max = 176/178/204 ms
HOST#

//now let's compare it to the pings with the default TOS.

//small packets/low priority/default tos
HOST#ping 192.0.2.1 repeat 100

Type escape sequence to abort.
Sending 100, 100-byte ICMP Echos to 192.0.2.1, timeout is 2 seconds:
...!!!!!!!!!!!!!!!!!!!!!!!!!!!!..!!!!!!!!!!!!!!!!!!!!!!!!!!!!..!!!!!!!
!!!!!!!!!!!!!!!!!!!!!..!!!!!!!
Success rate is 91 percent (91/100), round-trip min/avg/max = 16/34/384 ms

//large packets/low priority/default tos
HOST#ping 192.0.2.1 repeat 20 size 1250

Type escape sequence to abort.
Sending 20, 1250-byte ICMP Echos to 192.0.2.1, timeout is 2 seconds:
.!!!..!!..!!!..!!!..
Success rate is 55 percent (11/20), round-trip min/avg/max = 180/284/645 ms

Building further on these examples, let’s extended this VPN. I actually already have a VPN built between my ASA and “outside”. This includes traffic sent to 10.2.2.2.

ASA# show crypto ipsec sa
interface: outside
    Crypto map tag: MYMAP, seq num: 10, local addr: 192.0.2.2

      access-list L2L extended permit ip 192.168.3.0 255.255.255.0 10.2.2.0 255.255.255.0
      local ident (addr/mask/prot/port): (192.168.3.0/255.255.255.0/0/0)
      remote ident (addr/mask/prot/port): (10.2.2.0/255.255.255.0/0/0)
      current_peer: 192.0.2.1

      #pkts encaps: 968, #pkts encrypt: 968, #pkts digest: 968
      #pkts decaps: 968, #pkts decrypt: 968, #pkts verify: 968
      #pkts compressed: 0, #pkts decompressed: 0
      #pkts not compressed: 968, #pkts comp failed: 0, #pkts decomp failed: 0
      #pre-frag successes: 0, #pre-frag failures: 0, #fragments created: 0
      #PMTUs sent: 0, #PMTUs rcvd: 0, #decapsulated frgs needing reassembly: 0
      #send errors: 0, #recv errors: 0

      local crypto endpt.: 192.0.2.2/0, remote crypto endpt.: 192.0.2.1/0
      path mtu 1500, ipsec overhead 74, media mtu 1500
      current outbound spi: C0C49642
      current inbound spi : 5BDF7FA6

    inbound esp sas:
      spi: 0x5BDF7FA6 (1541373862)
         transform: esp-aes esp-sha-hmac no compression
         in use settings ={L2L, Tunnel, }
         slot: 0, conn_id: 372736, crypto-map: MYMAP
         sa timing: remaining key lifetime (kB/sec): (4373887/3516)
         IV size: 16 bytes
         replay detection support: Y
         Anti replay bitmap:
          0xFFFFFFFF 0xFFFFFFFF
    outbound esp sas:
      spi: 0xC0C49642 (3234108994)
         transform: esp-aes esp-sha-hmac no compression
         in use settings ={L2L, Tunnel, }
         slot: 0, conn_id: 372736, crypto-map: MYMAP
         sa timing: remaining key lifetime (kB/sec): (4373887/3516)
         IV size: 16 bytes
         replay detection support: Y
         Anti replay bitmap:
          0x00000000 0x00000001

ASA#

Let’s compare our high priority VPN traffic tagged with EF traffic with default ToS traffic.

//high priority
HOST#ping
Protocol [ip]:
Target IP address: 10.2.2.2
Repeat count [5]: 100
Datagram size [100]:
Timeout in seconds [2]:
Extended commands [n]: y
Source address or interface:
Type of service [0]: 184
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 100, 100-byte ICMP Echos to 10.2.2.2, timeout is 2 seconds:
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Success rate is 100 percent (100/100), round-trip min/avg/max = 20/21/28 ms

//ToS 0
HOST#ping 10.2.2.2 repeat 100

Type escape sequence to abort.
Sending 100, 100-byte ICMP Echos to 10.2.2.2, timeout is 2 seconds:
!!!!!!!!!!!!!!!!!!!!!!..!!!!!!!!!!!!!!!!!!!!!!!..!!!!!!!!!!!!!!!!!!!!!
!!.!.!..!!!!!!!!!!!!!!!!!!!!!!
Success rate is 92 percent (92/100), round-trip min/avg/max = 16/48/729 ms
HOST#

I put together a video a couple of weeks ago that showed DSCP preservation with VPN. This takes it a step further and prioritizes the traffic in addition to copying the DSCP value to the outer header.

This article demonstrated how to use hierarchical priority queueing to solve part of the problem the we often run into. I actually created an environment that is worse than typical in a couple of ways. First, policing is a really harsh way to keep the traffic within the contract rate. Second, I severely over subscribed the contract rate. One important point to note is the fact that I had to slow the circuit down slightly under the contract rate to get 100% success. This solution is only for outbound traffic. If there is a need for priority traffic on a L2L VPN, this solution may need to be implemented on both ends. The final point that has to be made is that we still have no control of the actual realized per-hop behavior in the service provider[s] cloud.

About Paul Stewart, CCIE 26009 (Security)

Paul is a Network and Security Engineer, Trainer and Blogger who enjoys understanding how things really work. With over 15 years of experience in the technology industry, Paul has helped many organizations build, maintain and secure their networks and systems.
This entry was posted in Network, Security, Technology and tagged , , , . Bookmark the permalink.

3 Responses to How to Implement Priority Queuing on the ASA

  1. Bob McCouch says:

    Great post, Paul! I find it interesting that you were able to move the congestion point to the ASA’s shaper with only a very slight reduction in the shaper size below the SP’s policed rate. I’ve always made the “parent shaper” about 95% of the contract rate because that has always seemed to be the threshold where the prioritization works based on subjective testing. Your testing method here is clearly more rigorous.

  2. Pingback: Classifying IPSec Traffic for Hierarchical Priority Queuing with the ASA | PacketU

Comments are closed.