Implementing Standards-Based Per-Hop Behavior
Problem
You want to configure your router to follow the RFC-defined Per-Hop Behaviors defined for different DSCP values.
Solution
This recipe constructs an approximate implementation of both Expedited Forwarding and Assured Forwarding, while still ensuring that network control packets do not suffer from delays due to application traffic. With the QoS enhancements provided in IOS Version 12.1(5)T and higher, there is a straightforward way to accomplish this using a combination of WRED, CBWFQ, and Low Latency Queuing (LLQ):
Router#configure terminal
Enter configuration commands, one per line. End with CNTL/Z.
Router(config)#class-map EF
Router(config-cmap)#description Real-time application traffic
Router(config-cmap)#match ip precedence 5
Router(config-cmap)#exit
Router(config)#class-map AF1x
Router(config-cmap)#description Priority Class 1
Router(config-cmap)#match ip precedence 1
Router(config-cmap)#exit
Router(config)#class-map AF2x
Router(config-cmap)#description Priority Class 2
Router(config-cmap)#match ip precedence 2
Router(config-cmap)#exit
Router(config)#class-map AF3x
Router(config-cmap)#description Priority Class 3
Router(config-cmap)#match ip precedence 3
Router(config-cmap)#exit
Router(config)#class-map AF4x
Router(config-cmap)#description Priority Class 4
Router(config-cmap)#match ip precedence 4
Router(config-cmap)#exit
Router(config)#policy-map cbwfq_pq
Router(config-pmap)#class EF
Router(config-pmap-c)#priority 58 800
Router(config-pmap-c)#exit
Router(config-pmap)#class AF1x
Router(config-pmap-c)#bandwidth percent 15
Router(config-pmap-c)#random-detect dscp-based
Router(config-pmap-c)#exit
Router(config-pmap)#class AF2x
Router(config-pmap-c)#bandwidth percent 15
Router(config-pmap-c)#random-detect dscp-based
Router(config-pmap-c)#exit
Router(config-pmap)#class AF3x
Router(config-pmap-c)#bandwidth percent 15
Router(config-pmap-c)#random-detect dscp-based
Router(config-pmap-c)#exit
Router(config-pmap)#class AF4x
Router(config-pmap-c)#bandwidth percent 15
Router(config-pmap-c)#random-detect dscp-based
Router(config-pmap-c)#exit
Router(config-pmap)#class class-default
Router(config-pmap-c)#fair-queue 512
Router(config-pmap-c)#queue-limit 96
Router(config-pmap-c)#exit
Router(config-pmap)#exit
Router(config)#interface HSSI0/1
Router(config-if)#service-policy output cbwfqpolicy
Router(config-if)#exit
Router(config)#end
Router#
If you are running older IOS versions, you can use Custom Queuing to create different levels of forwarding precedence, but you can't combine them with WRED to enforce the standard drop precedence rules.
Discussion
We have repeatedly said throughout this chapter that Priority Queues are dangerous because they allow high-priority traffic to starve all lower priority queues. However, strict prioritization does give excellent real-time behavior for the highest priority traffic because it ensures minimal queuing latency. This recipe uses Cisco's Low Latency Queuing (LLQ), which avoids most of the problems of pure Priority Queuing.
This example creates an approximation of the Differentiated Services model defined in RFCs 2597 and 2598. All real-time and network control traffic uses LLQ to ensure that it is always delivered with minimal delay. All other IP traffic falls into one of the Assured Forwarding classes shown in Table B-3 in Appendix B, with the exception of packets that do not have a DSCP tag value. Untagged traffic, including nonIP traffic, will use the default forwarding behavior.
Each column in Table B-3 represents a precedence class, which we have called AF1x, AF2x, AF3x, and AF4x, respectively. For each of these classes, we have reserved a share of the bandwidth, and we have configured DSCP-based WRED:
Router(config-pmap)#class AF4x
Router(config-pmap-c)#bandwidth percent 15
Router(config-pmap-c)#random-detect dscp-based
Router(config-pmap-c)#exit
In the discussion to Recipe 11.9, we showed how to modify the default WRED thresholds and drop probabilities.
The example also defines a class called EF, which matches all packets with an IP Precedence value of 5, which has a binary representation of 101. Note that technically, the EF DSCP value looks like 101110 in binary. So the example allows packets to join this queue if only the first three bits of the DSCP are correct. This is for backward compatibility and to ensure that we don't leave out any high-priority traffic. However, if you wanted to create a queue for a real EF DSCP value and a separate queue for packets with IP Precedence 5, you could do so like this:
Router(config)#class-map EF
Router(config-cmap)#description Real-time application traffic
Router(config-cmap)#match ip dscp ef
Router(config-cmap)#exit
Router(config)#class-map Prec5
Router(config-cmap)#description Critical application traffic
Router(config-cmap)#match ip precedence 5
Router(config-cmap)#exit
Router(config)#policy-map cbwfq_pq
Router(config-pmap)#class EF
Router(config-pmap-c)#priority 58 800
Router(config-pmap-c)#exit
Router(config-pmap)#class Prec5
Router(config-pmap-c)#bandwidth percent 15
Router(config-pmap-c)#exit
Note that you must define the classes in the policy map in this order because the router matches packets sequentially. If you specified the EF class-map after the Prec5 map, you would find that all of your EF traffic would wind up in the other queue, which is not what you want. Note also that, as we discussed in Recipe 11.7, you have to be careful of the total reserved bandwidth in CBWFQ. Simply adding these lines to the recipe example would give a total of 75 percent allocated bandwidth. This is the default maximum value. If you want to exceed this value, Recipe 11.7 shows how to modify the maximum.
We have already discussed most of the commands shown in the class definitions in other recipes. However, the EF queue contains a special command:
Router(config-pmap-c)#priority 58 800
This defines a strict priority queue for this class with a sustained throughput of 58 Kbps. This is based on the assumption that the EF application uses a standard stream of 56 Kbps, and we have added a small amount on top of this to allow for Layer 2 overhead. The last argument in the priority command is a burst length in bytes. This allows the application to temporarily exceed the defined sustain rate, just long enough to send this many bytes. In this case, we're assuming that the real-time application uses small packets, so allowing it to send a burst of 800 bytes when it has already reached the configured sustain rate of 58 Kbps should be more than sufficient.
Note that this does not imply that there is strict policing on this queue. If you also want to enforce a maximum rate of 65 Kbps on this queue, for example, you could also include a police statement, as follows:
Router(config-pmap)#class EF
Router(config-pmap-c)#priority 58 800
Router(config-pmap-c)#police 65000 1600
Router(config-pmap-c)#exit
In this command we have also been slightly more generous with the burst size, extending it to 1600 bytes. Enforcing an upper limit like this is a good idea on priority queues because it helps to prevent the highest priority traffic from starving the other queues. However, it is not necessary to enforce the upper limit this way just to avoid starving the lower queues. This is because the priority command stops giving strict priority to this queue when the bandwidth rises above the specified limit.
It should be clear from the ability to allocate both minimum and maximum bandwidth with the CBWFQ priority and police commands, LLQ is a much more sophisticated and flexible type of queuing than the simple Priority Queuing discussed in Recipe 11.3. So if your router is capable of supporting CBWFQ, we recommend using LLQ for any situation in which you want Priority Queuing. Cisco introduced the LLQ feature in IOS level 12.0(6)T.