Introduction
Quality of Service (QoS) is the mechanism by which a network device identifies, classifies, and applies differential treatment to traffic flows. Without QoS, all packets compete equally for bandwidth — a video conference can be starved by a bulk file transfer sharing the same WAN link. On Cisco IOS and IOS-XE platforms, the Modular QoS CLI (MQC) provides a structured, three-step framework: classify traffic with class-maps, define actions with policy-maps, and apply policies to interfaces with service-policy commands.
This run book covers the complete MQC workflow on routers and switches running IOS/IOS-XE (ASR 1000, ISR 4000, Catalyst 9000), using hostnames and domain names consistent with InfraRunBook lab conventions.
Lab Topology
All examples use the following topology:
- rtr-infrarunbook-core — ASR 1001-X, IOS-XE 17.x (WAN-facing router)
- sw-infrarunbook-dist01 — Catalyst 9300 (distribution switch)
- WAN uplink:
GigabitEthernet0/0/0
, 100 Mbps committed, 150 Mbps burst - LAN downlink:
GigabitEthernet0/0/1
- Management:
10.10.0.0/24
, Voice VLAN:10.20.0.0/24
, Data VLAN:10.30.0.0/24
Understanding DSCP and Per-Hop Behaviours
Differentiated Services Code Point (DSCP) is a 6-bit field in the IP header (bits 0–5 of the ToS byte). It defines a Per-Hop Behaviour (PHB) — the treatment a packet receives at each router. The most important PHBs are:
- EF (Expedited Forwarding, DSCP 46 / 0x2E) — low latency, low jitter; ideal for VoIP RTP streams
- AF (Assured Forwarding) classes AF11–AF43 — four classes, three drop precedences per class; used for transactional and streaming data
- CS (Class Selector) 0–7 — backward-compatible with IP Precedence
- Default (BE, DSCP 0) — best-effort, drop-tail treatment
The table below maps common application types to recommended DSCP values used throughout this guide:
- VoIP bearer (RTP): EF (46)
- VoIP signalling (SIP): CS3 (24)
- Video conferencing: AF41 (34)
- Business-critical data: AF21 (18)
- Bulk / backup: CS1 (8)
- Best effort / scavenger: Default (0)
Step 1 — Define Class-Maps
Class-maps match traffic using
matchstatements. Use
match-any(logical OR) or
match-all(logical AND). Best practice is to start with DSCP-based matching for traffic that is already marked upstream (e.g., by IP phones), and ACL-based matching for unmarked traffic.
Class-Map for VoIP RTP (already marked EF by IP phone)
rtr-infrarunbook-core(config)# class-map match-any CM-VOICE-RTP
rtr-infrarunbook-core(config-cmap)# match dscp ef
rtr-infrarunbook-core(config-cmap)# description VoIP RTP bearer - matched by EF DSCP
rtr-infrarunbook-core(config-cmap)# exit
Class-Map for VoIP Signalling (SIP on TCP/UDP 5060 and 5061)
rtr-infrarunbook-core(config)# ip access-list extended ACL-VOIP-SIG
rtr-infrarunbook-core(config-ext-nacl)# permit tcp 10.20.0.0 0.0.0.255 any eq 5060
rtr-infrarunbook-core(config-ext-nacl)# permit udp 10.20.0.0 0.0.0.255 any eq 5060
rtr-infrarunbook-core(config-ext-nacl)# permit tcp 10.20.0.0 0.0.0.255 any eq 5061
rtr-infrarunbook-core(config-ext-nacl)# exit
rtr-infrarunbook-core(config)# class-map match-any CM-VOICE-SIG
rtr-infrarunbook-core(config-cmap)# match access-group name ACL-VOIP-SIG
rtr-infrarunbook-core(config-cmap)# description SIP signalling from infrarunbook-prod voice VLAN
rtr-infrarunbook-core(config-cmap)# exit
Class-Map for Business-Critical Data (SAP, custom ERP on TCP 8443)
rtr-infrarunbook-core(config)# ip access-list extended ACL-BIZ-CRITICAL
rtr-infrarunbook-core(config-ext-nacl)# permit tcp 10.30.0.0 0.0.0.255 host 203.0.113.50 eq 8443
rtr-infrarunbook-core(config-ext-nacl)# permit tcp 10.30.0.0 0.0.0.255 host 203.0.113.51 eq 8443
rtr-infrarunbook-core(config-ext-nacl)# exit
rtr-infrarunbook-core(config)# class-map match-any CM-BIZ-CRITICAL
rtr-infrarunbook-core(config-cmap)# match access-group name ACL-BIZ-CRITICAL
rtr-infrarunbook-core(config-cmap)# match dscp af21
rtr-infrarunbook-core(config-cmap)# exit
Class-Map for Bulk / Backup Traffic
rtr-infrarunbook-core(config)# ip access-list extended ACL-BULK
rtr-infrarunbook-core(config-ext-nacl)# permit tcp any any eq 445
rtr-infrarunbook-core(config-ext-nacl)# permit tcp any any eq 2049
rtr-infrarunbook-core(config-ext-nacl)# permit tcp 10.30.0.0 0.0.0.255 host 10.10.0.100 eq 9100
rtr-infrarunbook-core(config-ext-nacl)# exit
rtr-infrarunbook-core(config)# class-map match-any CM-BULK
rtr-infrarunbook-core(config-cmap)# match access-group name ACL-BULK
rtr-infrarunbook-core(config-cmap)# match dscp cs1
rtr-infrarunbook-core(config-cmap)# exit
Step 2 — Define Policy-Maps (Marking, Policing, Shaping, Queuing)
Policy-maps are where actions are assigned to each class. On the WAN egress interface, a hierarchical policy-map (H-QoS) is used: a parent policy shapes the aggregate to the committed WAN rate, while a child policy applies per-class treatment.
Child Policy-Map: Per-Class Queuing and Marking
rtr-infrarunbook-core(config)# policy-map PM-CHILD-WAN-EGRESS
! ── VoIP RTP: LLQ (strict priority), 20% of link ──────────────
rtr-infrarunbook-core(config-pmap)# class CM-VOICE-RTP
rtr-infrarunbook-core(config-pmap-c)# priority percent 20
rtr-infrarunbook-core(config-pmap-c)# set dscp ef
rtr-infrarunbook-core(config-pmap-c)# exit
! ── VoIP Signalling: CBWFQ 5% ─────────────────────────────────
rtr-infrarunbook-core(config-pmap)# class CM-VOICE-SIG
rtr-infrarunbook-core(config-pmap-c)# bandwidth percent 5
rtr-infrarunbook-core(config-pmap-c)# set dscp cs3
rtr-infrarunbook-core(config-pmap-c)# exit
! ── Business-Critical: CBWFQ 40%, police to 40 Mbps ──────────
rtr-infrarunbook-core(config-pmap)# class CM-BIZ-CRITICAL
rtr-infrarunbook-core(config-pmap-c)# bandwidth percent 40
rtr-infrarunbook-core(config-pmap-c)# set dscp af21
rtr-infrarunbook-core(config-pmap-c)# police rate 40000000 bps burst 1500000
rtr-infrarunbook-core(config-pmap-c-police)# conform-action transmit
rtr-infrarunbook-core(config-pmap-c-police)# exceed-action set-dscp-transmit af22
rtr-infrarunbook-core(config-pmap-c-police)# violate-action drop
rtr-infrarunbook-core(config-pmap-c-police)# exit
rtr-infrarunbook-core(config-pmap-c)# exit
! ── Bulk: CBWFQ 10%, re-mark to CS1 ──────────────────────────
rtr-infrarunbook-core(config-pmap)# class CM-BULK
rtr-infrarunbook-core(config-pmap-c)# bandwidth percent 10
rtr-infrarunbook-core(config-pmap-c)# set dscp cs1
rtr-infrarunbook-core(config-pmap-c)# exit
! ── Default: remainder ────────────────────────────────────────
rtr-infrarunbook-core(config-pmap)# class class-default
rtr-infrarunbook-core(config-pmap-c)# bandwidth percent 25
rtr-infrarunbook-core(config-pmap-c)# set dscp default
rtr-infrarunbook-core(config-pmap-c)# exit
rtr-infrarunbook-core(config-pmap)# exit
Parent Policy-Map: H-QoS Traffic Shaping to WAN Rate
rtr-infrarunbook-core(config)# policy-map PM-PARENT-WAN-EGRESS
rtr-infrarunbook-core(config-pmap)# class class-default
rtr-infrarunbook-core(config-pmap-c)# shape average 100000000
rtr-infrarunbook-core(config-pmap-c)# service-policy PM-CHILD-WAN-EGRESS
rtr-infrarunbook-core(config-pmap-c)# exit
rtr-infrarunbook-core(config-pmap)# exit
The
shape average 100000000(100 Mbps) limits egress to the committed WAN rate, preventing the ISP from dropping packets due to contract violations.
Step 3 — Apply Service-Policies to Interfaces
rtr-infrarunbook-core(config)# interface GigabitEthernet0/0/0
rtr-infrarunbook-core(config-if)# description WAN-TO-ISP-SOLVETHENETWORK
rtr-infrarunbook-core(config-if)# service-policy output PM-PARENT-WAN-EGRESS
rtr-infrarunbook-core(config-if)# exit
For ingress policing (protecting the router from inbound bursts), add an ingress policy on the same interface:
rtr-infrarunbook-core(config)# policy-map PM-WAN-INGRESS-POLICE
rtr-infrarunbook-core(config-pmap)# class class-default
rtr-infrarunbook-core(config-pmap-c)# police rate 100000000 bps burst 3000000
rtr-infrarunbook-core(config-pmap-c-police)# conform-action transmit
rtr-infrarunbook-core(config-pmap-c-police)# exceed-action drop
rtr-infrarunbook-core(config-pmap-c-police)# exit
rtr-infrarunbook-core(config-pmap-c)# exit
rtr-infrarunbook-core(config-pmap)# exit
rtr-infrarunbook-core(config)# interface GigabitEthernet0/0/0
rtr-infrarunbook-core(config-if)# service-policy input PM-WAN-INGRESS-POLICE
rtr-infrarunbook-core(config-if)# exit
Step 4 — Marking at the Distribution Switch (sw-infrarunbook-dist01)
IP phones auto-mark their own RTP traffic as EF. However, PC data traffic arriving on the same access port must be re-marked at the switch before it reaches the router. The Catalyst 9300 supports MQC-based marking on access and trunk ports.
sw-infrarunbook-dist01(config)# class-map match-any CM-PC-DATA
sw-infrarunbook-dist01(config-cmap)# match vlan 30
sw-infrarunbook-dist01(config-cmap)# exit
sw-infrarunbook-dist01(config)# policy-map PM-INGRESS-TRUST
sw-infrarunbook-dist01(config-pmap)# class CM-PC-DATA
sw-infrarunbook-dist01(config-pmap-c)# set dscp default
sw-infrarunbook-dist01(config-pmap-c)# exit
sw-infrarunbook-dist01(config-pmap)# class class-default
sw-infrarunbook-dist01(config-pmap-c)# set dscp default
sw-infrarunbook-dist01(config-pmap-c)# exit
sw-infrarunbook-dist01(config-pmap)# exit
! Apply to uplink toward rtr-infrarunbook-core
sw-infrarunbook-dist01(config)# interface GigabitEthernet1/0/49
sw-infrarunbook-dist01(config-if)# description UPLINK-TO-RTR-INFRARUNBOOK-CORE
sw-infrarunbook-dist01(config-if)# service-policy input PM-INGRESS-TRUST
sw-infrarunbook-dist01(config-if)# exit
Best practice: Never trust DSCP markings from PC endpoints — always re-mark at the first trusted device (distribution switch or router). Trust markings only from authenticated IP phones (via CDP device classification onmls qos trust dscporswitchport voice vlan).
Step 5 — Policing vs Shaping: When to Use Each
Policing measures traffic against a token bucket. Conforming traffic is transmitted (or re-marked); exceeding traffic is dropped immediately. This creates a hard rate limit with potential packet loss — acceptable for bulk or scavenger traffic but never for voice.
Shaping delays excess traffic in a queue (smoothing bursts) rather than dropping it. It consumes memory (the shape queue) and adds delay, making it unsuitable for EF/LLQ classes. Use shaping at the parent policy to match the WAN CIR.
The token bucket parameters:
- CIR (Committed Information Rate) — the average allowed rate in bps
- Bc (Committed Burst) — bytes that can be sent in one interval, = CIR × Tc
- Be (Excess Burst, shaping only) — additional bytes that may be sent after idle periods
! Policing example: 10 Mbps CIR, 1.25 MB Bc
rtr-infrarunbook-core(config-pmap-c)# police rate 10000000 bps burst 1250000
rtr-infrarunbook-core(config-pmap-c-police)# conform-action transmit
rtr-infrarunbook-core(config-pmap-c-police)# exceed-action drop
rtr-infrarunbook-core(config-pmap-c-police)# exit
! Shaping example: 50 Mbps CIR, 6.25 MB Bc, 6.25 MB Be
rtr-infrarunbook-core(config-pmap-c)# shape average 50000000 6250000 6250000
Step 6 — Verification and Monitoring
Verify class-map matching
rtr-infrarunbook-core# show class-map
Class Map match-any CM-VOICE-RTP (id 1)
Match: dscp ef (46)
Class Map match-any CM-VOICE-SIG (id 2)
Match: access-group name ACL-VOIP-SIG
Class Map match-any CM-BIZ-CRITICAL (id 3)
Match: access-group name ACL-BIZ-CRITICAL
Match: dscp af21 (18)
Class Map match-any CM-BULK (id 4)
Match: access-group name ACL-BULK
Match: dscp cs1 (8)
Verify policy-map configuration
rtr-infrarunbook-core# show policy-map PM-CHILD-WAN-EGRESS
Policy Map PM-CHILD-WAN-EGRESS
Class CM-VOICE-RTP
Priority: 20% (20000 kbps), burst bytes 500000, b/w exceed drops: 0
set dscp ef
Class CM-VOICE-SIG
Bandwidth: 5% (5000 kbps), Max Threshold 64 packets
set dscp cs3
Class CM-BIZ-CRITICAL
Bandwidth: 40% (40000 kbps), Max Threshold 64 packets
set dscp af21
police:
cir 40000000 bps, bc 1500000 byte
Verify real-time counters on interface
rtr-infrarunbook-core# show policy-map interface GigabitEthernet0/0/0 output
GigabitEthernet0/0/0
Service-policy output: PM-PARENT-WAN-EGRESS
Class-map: class-default (match-any)
packets: 48291742, bytes: 61811830100
shape (average) cir 100000000, bc 4000000, be 4000000
Service-policy : PM-CHILD-WAN-EGRESS
Class-map: CM-VOICE-RTP (match-any)
packets: 2810445, bytes 449671200
Priority: 20000 kbps, burst bytes 500000, b/w exceed drops: 0
Class-map: CM-BIZ-CRITICAL (match-any)
packets: 11203920, bytes 14340729600
police:
cir 40000000 bps, bc 1500000 byte
conformed 10891204 packets; actions: transmit
exceeded 312716 packets; actions: set-dscp-transmit af22
violated 0 packets; actions: drop
Check queue depth and drops
rtr-infrarunbook-core# show queue GigabitEthernet0/0/0
Input queue: 0/75/0/0 (size/max/drops/flushes); Total output drops: 0
Queueing strategy: fifo
Output queue: 0/40 (size/max)
rtr-infrarunbook-core# show interfaces GigabitEthernet0/0/0 | include output drops
Output queue: 0/40 (size/drops)
Verify DSCP markings on egress packets
rtr-infrarunbook-core# debug ip packet detail
! Or use IP SLA probes with DSCP marking verification:
rtr-infrarunbook-core(config)# ip sla 1
rtr-infrarunbook-core(config-ip-sla)# udp-jitter 203.0.113.1 50000 source-ip 10.10.0.1 source-port 50001
rtr-infrarunbook-core(config-ip-sla-jitter)# tos 0xB8
rtr-infrarunbook-core(config-ip-sla-jitter)# frequency 60
rtr-infrarunbook-core(config-ip-sla)# exit
rtr-infrarunbook-core(config)# ip sla schedule 1 life forever start-time now
Step 7 — NBAR2-Based Classification (Protocol Discovery)
When ACL-based matching is impractical (e.g., encrypted flows, dynamic ports), use NBAR2 (Network-Based Application Recognition) to classify by application protocol. NBAR2 is available on ISR 4000 and ASR 1000 with the Cisco DNA Advantage license.
rtr-infrarunbook-core(config)# class-map match-any CM-WEBEX
rtr-infrarunbook-core(config-cmap)# match protocol webex-media
rtr-infrarunbook-core(config-cmap)# match protocol cisco-jabber-video
rtr-infrarunbook-core(config-cmap)# exit
rtr-infrarunbook-core(config)# class-map match-any CM-YOUTUBE
rtr-infrarunbook-core(config-cmap)# match protocol youtube
rtr-infrarunbook-core(config-cmap)# exit
! Enable NBAR2 protocol discovery on the interface first:
rtr-infrarunbook-core(config)# interface GigabitEthernet0/0/0
rtr-infrarunbook-core(config-if)# ip nbar protocol-discovery
rtr-infrarunbook-core(config-if)# exit
! Verify:
rtr-infrarunbook-core# show ip nbar protocol-discovery interface GigabitEthernet0/0/0 stats bit-rate
Step 8 — Saving and Maintaining the Configuration
rtr-infrarunbook-core# copy running-config startup-config
Destination filename [startup-config]?
Building configuration...
[OK]
! Archive for rollback (configure archive before making changes):
rtr-infrarunbook-core(config)# archive
rtr-infrarunbook-core(config-archive)# path tftp://10.10.0.200/infrarunbook-core-$t
rtr-infrarunbook-core(config-archive)# maximum 10
rtr-infrarunbook-core(config-archive)# write-memory
rtr-infrarunbook-core(config-archive)# exit
! Rollback to previous:
rtr-infrarunbook-core# configure replace tftp://10.10.0.200/infrarunbook-core-Jan-1-2026
Frequently Asked Questions
Q: What is MQC and why is it used instead of legacy QoS commands?
A: MQC (Modular QoS CLI) separates classification (class-map), action definition (policy-map), and application (service-policy) into three independent steps. Legacy commands like
priority-listand
custom-queue-listmixed these concerns and did not scale. MQC enables reuse of class-maps across multiple policies and supports hierarchical policies — features essential for WAN QoS.
Q: Can I apply both an input and output service-policy on the same interface?
A: Yes. Cisco IOS/IOS-XE supports one input service-policy and one output service-policy per interface simultaneously. On rtr-infrarunbook-core, the WAN interface (
GigabitEthernet0/0/0) typically carries an ingress police policy (input) and an H-QoS shape+queue policy (output).
Q: What is the difference between CBWFQ and LLQ?
A: CBWFQ (Class-Based Weighted Fair Queuing) allocates a guaranteed minimum bandwidth to each class using the
bandwidthkeyword. Unused bandwidth is shared proportionally. LLQ (Low Latency Queuing) adds a strict-priority queue on top of CBWFQ using the
prioritykeyword. Traffic in the priority queue is always serviced first, making it ideal for VoIP RTP which cannot tolerate jitter or delay.
Q: How do I prevent the LLQ priority queue from starving other classes?
A: The
priority percent 20command automatically rate-limits (polices) the priority class to 20% of the shaped rate. If VoIP traffic exceeds this, it is dropped — but under normal conditions, VoIP is well within the limit and other classes are not starved. Always size the priority queue to the peak VoIP load, not the average.
Q: What burst values should I use for the police command?
A: A safe starting point is
burst = CIR × 250msin bytes. For a 40 Mbps CIR:
40,000,000 × 0.25 / 8 = 1,250,000 bytes. For applications with large TCP windows or file transfers, increase to 375ms worth. Undersized burst values cause excessive drops on legitimate TCP sessions.
Q: What is H-QoS (Hierarchical QoS) and when is it required?
A: H-QoS nests a child policy-map inside a parent policy-map. The parent typically applies a
shapecommand to limit aggregate bandwidth to the WAN CIR, while the child applies per-class actions (priority, bandwidth, police). H-QoS is required when the physical interface speed (e.g., 1 Gbps Ethernet) is faster than the WAN committed rate (e.g., 100 Mbps) — without the parent shaper, per-class bandwidth percentages are calculated against 1 Gbps, not 100 Mbps.
Q: How do I verify that DSCP markings are being applied correctly?
A: Use
show policy-map interface <name>and verify packet counters increment on the correct class. For in-flight verification, use Embedded Packet Capture (EPC) on IOS-XE:
monitor capture CAP interface GigabitEthernet0/0/0 out match ipv4 any anythen
monitor capture CAP start, then
show monitor capture CAP buffer briefand examine the DSCP field in the exported PCAP.
Q: Does QoS affect CPU performance on ASR or ISR platforms?
A: On ASR 1000 with ESP (Embedded Services Processor) and ISR 4000 with Quantum Flow Processor, QoS classification and queuing is handled in hardware. CPU impact is minimal. NBAR2 deep-packet inspection does consume more CPU cycles; monitor with
show platform resourcesand
show processes cpu sortedafter enabling NBAR2.
Q: How do I reset QoS counters without reloading?
A: Use
clear counters GigabitEthernet0/0/0to reset all interface counters, including QoS. Alternatively, detach and re-attach the service-policy:
no service-policy output PM-PARENT-WAN-EGRESSthen
service-policy output PM-PARENT-WAN-EGRESS. This also resets the token bucket state for policers.
Q: Can NBAR2 classify encrypted traffic like HTTPS or QUIC?
A: NBAR2 uses deep-packet inspection and protocol signatures. For TLS-encrypted flows, NBAR2 can identify the application during the TLS handshake (via SNI and certificate fields) and by flow metadata patterns. Full payload inspection is not possible for encrypted flows. Update the protocol pack regularly:
ip nbar protocol-pack bootflash:pp-adv-isrg2-154-9.0.0.pack.
Q: What happens to QoS if the WAN link goes down and comes back up?
A: Service-policies are re-applied automatically when the interface returns to up state. The shaper token bucket and policer token buckets are reset to full, which means there will be a brief burst of traffic immediately after link restoration. To mitigate this, consider pre-conditioning on the LAN interface or implementing TCP optimisation on critical flows.
Q: How do I configure QoS on a sub-interface (dot1q tunnel)?
A: Service-policies can be applied to sub-interfaces. Apply the child policy directly to the sub-interface and let the parent shaper on the physical interface manage the aggregate:
rtr-infrarunbook-core(config)# interface GigabitEthernet0/0/1.30
rtr-infrarunbook-core(config-subif)# encapsulation dot1Q 30
rtr-infrarunbook-core(config-subif)# service-policy output PM-CHILD-WAN-EGRESS
rtr-infrarunbook-core(config-subif)# exit
Note: when both a sub-interface and the main interface carry service-policies, ensure bandwidth percentages account for the shared physical bandwidth across all sub-interfaces.
