QoS (Quality of Service) on older Cisco Catalyst switches is not as easy as configuring it on routers. The big difference is that on routers, QoS runs in software, while on our switches, it’s done in hardware. Since switching is done in hardware (ASICs) we also have to do our congestion management (queuing) in hardware. The downside of this is that QoS is in effect immediately. In this lesson, I will give you an overview of all the different commands and an explanation of how QoS works. If you are totally new to LAN QoS, do yourself a favor and watch this video:

The first 54 minutes are about classification, marking, and policing, so if you only care about congestion management and queuing you can skip the first part. Having said that, let’s walk through the different commands.

Priority Queue

If your switch supports ingress queuing then on most switches (Cisco Catalyst 3560 and 3750) queue 2 will be the priority queue by default. Keep in mind that there are only 2 ingress queues. If we want we can make queue 1 the priority queue and we can also change the bandwidth. Here’s how to do it:

Switch(config)#mls qos srr-queue input priority-queue 1 bandwidth 20

The command makes queue one the priority queue and limits it to 20% of the bandwidth of the total internal ring bandwidth.

For our egress queuing, we have to enable the priority queue ourselves! It’s not enabled by default. Here’s how you can do it:

Switch(config)#interface fa0/1
Switch(config-if)#priority-queue out

The command above will enable the outbound priority queue for interface fa0/1. By default, queue 1 is the priority queue!

Queue-set

The queue-set is like a template for QoS configurations on our switches. There are 2 queue-sets that we can use and by default, all interfaces are assigned to queue-set 1. If you plan to make changes to buffers etc., it’s better to use queue-set 2 for this. If you change queue-set 1 you will apply you new changes to all interfaces.

This is how you can assign an interface to a different queue-set:

Switch(config)#interface fa0/2
Switch(config-if)#queue-set 2

Above we put interface fa0/2 in queue-set 2. Keep in mind that we only have queue-sets for egress queuing, not for ingress.

Buffer Allocation

For each queue, we need to configure the assigned buffers. The buffer is like the ‘storage’ space for the interface, and we have to divide it among the different queues. This is how to do it:

mls qos queue-set output <queue set> buffers Q1 Q2 Q3 Q4

Above, you see the mls qos command. First, we select the queue-set and then we can divide the buffers between queues 1,2,3 and 4. For queues 1,3 and 4 you can select a value between 0 and 99. If you type 0, you will disable the queue. You can’t do this for queue 2 because it is used for the CPU buffer. Let’s take a look at an actual example:

Switch(config)#mls qos queue-set output 2 buffers 33 17 25 25

This will divide the buffer space like this:

  • 33% for queue 1.
  • 17% for queue 2.
  • 25% for queue 3.
  • 25% for queue 4.

Besides dividing the buffer space between the queues, we also have to configure the following values per queue:

  • Threshold 1 value
  • Threshold 2 value
  • Reserved value
  • Maximum value

The command to configure these values looks like this:

mls qos queue-set output <queue-set> threshold <queue number> T1 T2 RESERVED MAXIMUM

First, you need to select a queue-set, select the queue number and finally configure a threshold 1 and 2 value, reserved value, and the maximum value.

Here’s an example:

Switch(config)#mls qos queue-set output 2 threshold 3 33 66 100 300

In the example above we configure queue-set 2. We select queue 3 and set the following values:

  • Threshold 1 = 33%
  • Threshold 2 = 66%
  • Reserved = 100%
  • Maximum = 300%

This means that threshold 1 can go up to 33% of the queue. Threshold 2 can go up to 66% of the queue. We reserve 100% buffer space for this queue and in case the queue is full we can borrow more buffer space from the common pool. 300% means we can get twice our queue size from the common pool.

Assign marked packets/frames to the correct queue

You now know how to configure the buffers and thresholds, but we still have to tell the switch which CoS and DSCP values have to go to which queue. Here’s the command for it:

mls qos srr-queue <direction> <marking> <queue> <threshold> <values>

This is what it means:

  • Direction: input or output.
  • Marking: CoS or DSCP.
  • Queue: The queue number.
  • Threshold: this can be threshold 1,2 or 3.
  • Values: The CoS or DSCP values you want to put here.

Let’s take a look at an actual example:

Switch(config)#mls qos srr-queue output cos-map queue 1 threshold 1 0 1

The command assigns CoS values 0 and 1 to queue 1 up to threshold 1.

Switch(config)#mls qos srr-queue output cos-map queue 1 threshold 2 2 3

This example assigns CoS values 2 and 3 to queue 1 up to threshold 2.

Switch(config)#mls qos srr-queue output cos-map queue 4 threshold 2 6 7

And this one assigns CoS values 6 and 7 to queue 4 up to threshold 2.

Bandwidth Allocation

The buffers determine how large the queues are. In other words, how ‘big is our storage’. The bandwidth is basically how often we visit our queues. We can change the bandwidth allocation for each interface. Here’s what it looks like for our ingress queuing:

mls qos srr-queue input bandwidth Q1 Q2

Ingress queuing only has two queues. We can divide the weight between the two queues. Here’s an example:

Switch(config)#mls qos srr-queue input bandwidth 30 70

With the command above queue 1 will receive 30% of the bandwidth and queue, 2 will receive 70%. These two values are “weighted” and don’t have to add up to 100%. If I would have typed something like “70 60” then queue 1 would receive 60/130 = about 46% of the bandwidth and queue 2 would receive 70/130 = about 53%. Of course, it’s easier to calculate if you make these values add up to 100.

For our egress queues, we have to do the same thing, but it will be on the interface level. We can also choose between shaping or sharing. Sharing means the queues will divide the available bandwidth between each other. Shaping means you set a fixed limit, it’s like policing. Here’s an example:

Switch(config)#interface fa0/1
Switch(config-if)#srr-queue bandwidth share 30 20 25 25

This will divide the bandwidth as follows:

  • Queue 1: 30%
  • Queue 2: 20%
  • Queue 3: 25%
  • Queue 4: 25%

In this case, we have a 100Mbit interface which means queue 1 will receive 30Mbit, queue 2 20Mbit, queue 3 25Mbit, and queue 4 25Mbit. If there is no congestion, our queues can go above their bandwidth limit. This is why it’s called “sharing.”

If I want, I can enable shaping for one or more queues. This is how you do it:

Switch(config)#interface fa0/1
Switch(config-if)#srr-queue bandwidth shape 20 0 0 0

This value is weighted. The other queues are not shaped because there’s a 0. When you configure shaping for a queue, it will be removed from the sharing mechanism. So how much bandwidth does queue 1 really get? We can calculate it like this:

  • 1/20 = 0.05 x 100Mbit = 5Mbit.

So traffic in queue one will be shaped to 5Mbit. Since queue 1 is now removed from the sharing mechanism…how much bandwidth will queues 2,3 and 4 get?

Let’s take a look again at the sharing configuration that I just showed you:

Switch(config)#interface fa0/1
Switch(config-if)#srr-queue bandwidth share 30 20 25 25

I just explained to you that queue one would receive 30Mbit, queue two 20Mbit, queue three 25Mbit, and queue four also 25Mbit. Since I enabled shaping for queue 1, it doesn’t join the sharing mechanism anymore. This means there is more bandwidth for queues 2,3 and 4. Here’s what the calculation looks like now:

  • Interface fa0/1 is 100Mbit.
  • We configured shaping to 5Mbit for queue 1, so there is 95Mbit left.
  • We configured a weighted of value 20,25 and 25 for queues 2,3 and 4.
  • 20 + 25 + 25 = 70 total.
  • Queue 2 will receive 20/70 = 0.28 * (100 Mbit – 5 Mbit) = 27.1 Mbit.
  • Queue 3 will receive 25/70 = 0.35 * (100 Mbit – 5 Mbit) = 33.9 Mbit.
  • Queue 4 will receive 25/70 = 0.35 * (100 Mbit – 5 Mbit) = 33.9 Mbit.

If we add all these values together:

  • Queue 1 is shaped to 5 Mbit.
  • Queue 2 is shared to 27.1 Mbit.
  • Queue 3 is shared to 33.9 Mbit.
  • Queue 4 is shared to 33.9 Mbit.
  • 5 + 27.1 + 33.9 + 33.9 =  Total bandwidth of 100 Mbit.

That’s how you do it!

It’s also possible to rate-limit the entire interface for egress traffic if you want to save the hassle of configuring shaping. This is how you do it:

Switch(config)#interface fa0/1
Switch(config-if)#srr-queue bandwidth limit 85

This will limit our 100 Mbit interface to 85%, so you’ll end up with 85 Mbit.

Verification and troubleshooting

Now you know how to configure everything. Let’s take a look at the different commands you can use to verify everything!

First, you should check the capabilities of a switch. You can do this on the interface level as follows:

Switch#show interfaces fa0/23 capabilities
FastEthernet0/23
Model:                 WS-C3560-24PS
Type:                  10/100BaseTX
Speed:                 10,100,auto
Duplex:                half,full,auto
Trunk encap. type:     802.1Q,ISL
Trunk mode:            on,off,desirable,nonegotiate
Channel:               yes
Broadcast suppression: percentage(0-100)
Flowcontrol:           rx-(off,on,desired),tx-(none)
Fast Start:            yes
QoS scheduling:        rx-(not configurable on per port basis),
tx-(4q3t) (3t: Two configurable values and one fixed.)
CoS rewrite:           yes
ToS rewrite:           yes
UDLD:                  yes
Inline power:          yes
SPAN:                  source/destination
PortSecure:            yes
Dot1x:                 yes

Above, you can see that this Cisco Catalyst 3560 switch has four queues with 3 threshold levels.

If you are configuring QoS, you need to ensure you enabled it globally first with the mls qos command. You can verify if QoS is active or not with the following command:

Switch#show mls qos
QoS is enabled
QoS ip packet dscp rewrite is enabled

It tells us that QoS is enabled globally. We can also check the QoS parameters for each interface as follows:

Switch#show mls qos interface fa0/1
FastEthernet0/1
trust state: trust cos
trust mode: trust cos
trust enabled flag: ena
COS override: dis
default COS: 1
DSCP Mutation Map: Default DSCP Mutation Map
Trust device: none
qos mode: port-based

Above, you can see the trust state for this interface. We can also verify the queue-sets for this switch. If you didn’t configure them, you will find some default values:

Switch#show mls qos queue-set
Queueset: 1
Queue     :       1       2       3       4
----------------------------------------------
buffers   :      25      25      25      25
threshold1:     100     200     100     100
threshold2:     100     200     100     100
reserved  :      50      50      50      50
maximum   :     400     400     400     400
Queueset: 2
Queue     :       1       2       3       4
----------------------------------------------
buffers   :      33      17      25      25
threshold1:     100      33      33     100
threshold2:     100      66      66     100
reserved  :      50     100     100      50
maximum   :     400     200     200     400

Above you will find queue-set 1 and 2. You can see how the buffers are divided per queue and the values for our thresholds, reserved, and maximum values.

We can check how queuing is configured per interface. This is how you do it:

Switch#show mls qos interface fastEthernet 0/24 queuing
FastEthernet0/24
Egress Priority Queue : disabled
Shaped queue weights (absolute) :  25 0 0 0
Shared queue weights  :  25 25 25 25
The port bandwidth limit : 100  (Operational Bandwidth:100.0)
The port is mapped to qset : 1

Above, you see that the priority queue is disabled. Also, you see the shaped and shared values and that this interface belongs to queue-set 1.

If you are troubleshooting, you should check if you see any drops within the queues. You can do it like this:

Switch#show platform port-asic stats drop FastEthernet 0/1

Interface Fa0/1 TxQueue Drop Statistics
Queue 0
Weight 0 Frames 0
Weight 1 Frames 0
Weight 2 Frames 0
Queue 1
Weight 0 Frames 0
Weight 1 Frames 0
Weight 2 Frames 0
Queue 2
Weight 0 Frames 0
Weight 1 Frames 0
Weight 2 Frames 0
Queue 3
Weight 0 Frames 0
Weight 1 Frames 0
Weight 2 Frames 0

Here you can see the drops for each queue. We can also verify if we are receiving traffic that is marked:

Switch#show mls qos interface fastEthernet 0/1 statistics
FastEthernet0/1 (All statistics are in packets)

dscp: incoming
-------------------------------

0 -  4 :           0            0            0            0            0
5 -  9 :           0            0            0            0            0
10 - 14 :           0            0            0            0            0
15 - 19 :           0            0            0            0            0
20 - 24 :           0            0            0            0            0
25 - 29 :           0            0            0            0            0
30 - 34 :           0            0            0            0            0
35 - 39 :           0            0            0            0            0
40 - 44 :           0            0            0            0            0
45 - 49 :           0            0            0            0            0
50 - 54 :           0            0            0            0            0
55 - 59 :           0            0            0            0            0
60 - 64 :           0            0            0            0
dscp: outgoing
-------------------------------

0 -  4 :           0            0            0            0            0
5 -  9 :           0            0            0            0            0
10 - 14 :           0            0            0            0            0
15 - 19 :           0            0            0            0            0
20 - 24 :           0            0            0            0            0
25 - 29 :           0            0            0            0            0
30 - 34 :           0            0            0            0            0
35 - 39 :           0            0            0            0            0
40 - 44 :           0            0            0            0            0
45 - 49 :           0            0            0            0            0
50 - 54 :           0            0            0            0            0
55 - 59 :           0            0            0            0            0
60 - 64 :           0            0            0            0
cos: incoming
-------------------------------

0 -  4 :           2            0            0            0            0
5 -  7 :           0            0            0
cos: outgoing
-------------------------------

0 -  4 :           0            0            0            0            0
5 -  7 :           0            0            0
Policer: Inprofile:            0 OutofProfile:            0

That’s all I have for you for now! I suggest you check out these commands on your own switches to become familiar with them. If you enjoyed this lesson, please leave a comment!