Quản lý lưu lượng & QoSTraffic Management & QoS
Thuộc bộ kiến thức Network Engineer Roadmap.
Tổng quan
Mỗi link trong mạng đều có capacity hữu hạn, và phần lớn thời gian capacity đó là dư dùng. Những thời điểm đáng chú ý — những khoảnh khắc quyết định trải nghiệm của người dùng — xảy ra khi có congestion, tức là khi lượng traffic muốn đi qua một link nhiều hơn khả năng link tải được tại thời điểm đó. Khi điều này xảy ra, router hay switch phải ra quyết định: packet nào đi trước, packet nào phải chờ, và packet nào bị loại bỏ. Quality of Service (QoS) là tập hợp các công cụ giúp bạn ra quyết định đó một cách có chủ đích, theo mức độ ưu tiên của nghiệp vụ, thay vì để mặc cho may rủi.
Không có QoS, mạng hoạt động theo cơ chế best-effort: mọi packet được đối xử như nhau, first-in-first-out, và khi congestion thì packet nào đến lúc buffer đầy sẽ bị drop. Điều đó hoàn toàn ổn với một lượt download file — TCP sẽ retransmit và người dùng chỉ chờ thêm vài mili-giây. Nhưng nó là thảm hoạ với một cuộc gọi voice, nơi mà latency 200 ms hay 2% loss biến giọng nói thành tiếng lắp bắp như robot. Trên một converged network — mạng chở cả voice, video và data trên cùng hạ tầng — các loại traffic này có nhu cầu rất khác nhau, và best-effort không thể phục vụ tất cả cùng lúc.
Traffic management là bộ môn rộng hơn: kiểm soát cách traffic sử dụng mạng — không chỉ ưu tiên khi congestion (QoS đúng nghĩa), mà còn shaping để làm mượt các burst cho khớp với tốc độ cam kết, policing để chặn traffic vượt giới hạn, rate-limiting từng người dùng hay ứng dụng, và điều hướng các flow qua các link. Ghi chú này đi từ các performance metrics gốc mà bạn muốn bảo vệ, qua các mô hình và cơ chế QoS, đến cách tất cả kết hợp lại trên một WAN link thực tế.
QoS liên quan mật thiết đến các chủ đề khác trong roadmap. Nó nằm trên các transport và application protocol trong ./06-core-protocols.md (một cuộc gọi VoIP là RTP trên UDP; một lượt download là TCP), nó bổ trợ cho redundancy và load balancing trong ./09-redundancy-and-high-availability.md, và các metric nó bảo vệ chính là những metric bạn đo bằng công cụ trong ./15-tools-and-troubleshooting.md.
Kiến thức nền tảng
Performance metrics: QoS thực sự bảo vệ điều gì
Bạn không thể quản lý thứ mình không định nghĩa được. Bốn metric dưới đây là “đơn vị tiền tệ” của traffic management — mọi cơ chế QoS đều tồn tại để cải thiện một hoặc nhiều metric này cho traffic quan trọng.
Bandwidth vs throughput vs goodput
Ba khái niệm này hay bị nhầm lẫn, nhưng chúng khác nhau:
| Thuật ngữ | Định nghĩa | Ví dụ |
|---|---|---|
| Bandwidth | Tốc độ tối đa lý thuyết mà một link tải được, do công nghệ physical/link quyết định. Là capacity, không phải phép đo. | Một link Ethernet 1 Gbps có bandwidth 1 Gbps. |
| Throughput | Tốc độ dữ liệu thực sự được truyền thành công qua link, đo theo thời gian. Luôn ≤ bandwidth. | Link 1 Gbps đó có thể chỉ đạt throughput 940 Mbps sau overhead và tranh chấp. |
| Goodput | Tốc độ dữ liệu ứng dụng hữu ích được truyền, loại trừ overhead protocol, retransmission và header. Luôn ≤ throughput. | Trong 940 Mbps throughput, có thể chỉ 900 Mbps là payload file thật — phần còn lại là header TCP/IP/Ethernet và retransmit. |
Khoảng cách giữa bandwidth và throughput đến từ overhead protocol, collision half-duplex, tranh chấp, và quan hệ TCP window/RTT. Khoảng cách giữa throughput và goodput đến từ header và retransmission. Khi người dùng nói “mạng chậm”, họ hầu như luôn muốn nói goodput cảm thấy thấp, dù bandwidth họ trả tiền là cao.
Latency (delay) và các thành phần
Latency là thời gian một packet đi từ nguồn đến đích (one-way delay), hoặc đi và về (round-trip time, RTT). Nó là tổng của nhiều thành phần độc lập, và biết thành phần nào chiếm ưu thế sẽ cho bạn biết phải sửa gì:
| Thành phần | Nguyên nhân | Cách giảm |
|---|---|---|
| Propagation delay | Thời gian tín hiệu di chuyển vật lý qua khoảng cách, giới hạn bởi tốc độ ánh sáng trong môi trường (~5 µs/km trong fibre). | Đường ngắn hơn / server gần hơn (CDN). Không thắng được vật lý. |
| Serialization delay | Thời gian đẩy toàn bộ bit của packet lên dây = kích thước packet ÷ tốc độ link. Packet 1500 byte trên link 1 Mbps mất 12 ms; trên 1 Gbps mất 12 µs. | Link nhanh hơn, packet nhỏ hơn (fragmentation cho link chậm). |
| Queuing delay | Thời gian packet chờ trong buffer sau các packet khác khi congestion. Rất biến động — đây chính là thứ QoS kiểm soát. | Ưu tiên packet (LLQ/PQ), giảm độ sâu queue, quản lý congestion (WRED). |
| Processing delay | Thời gian thiết bị kiểm tra header, tra bảng, ACL, NAT. Thường nhỏ trên phần cứng hiện đại. | Phần cứng nhanh hơn, hardware offload. |
Điểm mấu chốt: QoS không thể giảm propagation hay serialization delay — chúng cố định bởi địa lý và tốc độ link. Thứ QoS kiểm soát là queuing delay, bằng cách chọn packet của ai phải chờ và của ai thì không.
Jitter (biến động delay)
Jitter là sự biến động của one-way latency giữa các packet liên tiếp. Nếu các packet trong luồng voice đến cách nhau 20 ms, 22 ms, 19 ms, 45 ms, 18 ms thì jitter là độ trải của các khoảng thời gian đến này. Ứng dụng real-time phát audio/video ở tốc độ không đổi, nên phía nhận dùng jitter buffer (de-jitter buffer) để hấp thụ biến động — nhưng buffer quá nhỏ sẽ drop packet đến muộn, còn quá lớn thì thêm delay. Jitter chủ yếu do queuing delay biến động gây ra, đó chính là lý do đưa voice vào một queue latency thấp giúp giảm jitter.
Packet loss
Packet loss là tỷ lệ phần trăm packet không bao giờ đến. Nguyên nhân gồm buffer tràn khi congestion (tail drop), lỗi bit ở physical layer, drop do policing, và thay đổi routing. TCP phục hồi loss bằng retransmit (đánh đổi goodput và delay); media real-time trên UDP thường không retransmit — một packet voice mất là mất luôn, nghe thành tiếng “tách” hoặc khoảng trống.
Giá trị mục tiêu cho các loại traffic phổ biến
| Loại traffic | One-way latency | Jitter | Loss |
|---|---|---|---|
| Voice (VoIP) | ≤ 150 ms | ≤ 30 ms | ≤ 1% |
| Video tương tác | ≤ 200 ms | ≤ 30 ms | ≤ 0.1–1% |
| Video streaming (có buffer) | Lỏng (buffer vài giây) | Lỏng | ≤ 1–2% |
| Bulk data (file, backup) | Lỏng | Không quan trọng | TCP phục hồi |
| Data giao dịch | ≤ 400 ms | Không quan trọng | TCP phục hồi |
Đo lường các metric
Bạn kiểm chứng những con số này bằng các công cụ trong ./15-tools-and-troubleshooting.md, tóm tắt:
ping— RTT và loss, kiểm tra reachability nhanh.iperf3— throughput/goodput giữa hai host, TCP hoặc UDP; chế độ UDP báo cáo jitter và loss.- Speedtest (Ookla/Fast.com) — throughput download/upload và latency đến server gần, từ góc nhìn end-user.
mtr— kết hợp traceroute và ping để hiện latency và loss theo từng hop, khoanh vùng nơi xảy ra vấn đề.
# Throughput (TCP) giữa client và server đang chạy `iperf3 -s`
iperf3 -c 10.0.0.1 -t 30
# Test UDP ở 5 Mbps — báo cáo jitter và packet loss, lý tưởng để mô phỏng VoIP
iperf3 -c 10.0.0.1 -u -b 5M -t 30
Vì sao cần QoS: converged network và congestion
Trước đây voice chạy trên mạng điện thoại TDM riêng còn data chạy trên IP; mỗi bên được thiết kế cho traffic của riêng nó. Mạng hiện đại hội tụ (converge) mọi thứ lên IP để giảm chi phí và đơn giản hoá vận hành — nhưng giờ một job backup có thể lấp đầy cùng một WAN link với một cuộc gọi bán hàng đang diễn ra. Vì các ứng dụng này có yêu cầu trái ngược (bulk cần throughput và chịu được delay; voice cần delay thấp và chấp nhận mất throughput), mạng cần cách phân biệt và đối xử khác nhau với chúng. Đó là lý do QoS tồn tại.
QoS chỉ làm gì đó khi có congestion. Trên một link không nghẽn, mọi packet đi ra ngay lập tức bất kể priority — chẳng có gì để ưu tiên. Giá trị của QoS hoàn toàn nằm ở cách nó hành xử khi cầu vượt cung, điều mà trên các link WAN và hướng internet xảy ra thường xuyên hơn bạn tưởng, thậm chí ở dạng microburst ngay cả khi utilisation trung bình trông thấp.
Khái niệm chính
Các mô hình QoS
Có ba cách tiếp cận kiến trúc cho QoS. Mạng thực tế thường chạy DiffServ, nhưng bạn nên hiểu cả ba.
| Mô hình | Cách hoạt động | Khả năng mở rộng | State ở core | Cam kết |
|---|---|---|---|---|
| Best-Effort | Không QoS. Mọi packet bình đẳng, FIFO. | Vô hạn | Không | Không |
| IntServ (Integrated Services) | Ứng dụng báo hiệu nhu cầu end-to-end bằng RSVP; mỗi router reserve tài nguyên theo từng flow. | Kém — per-flow state ở mọi nơi | Theo flow | Cứng, theo flow |
| DiffServ (Differentiated Services) | Packet được đánh dấu thành vài class ở edge; mỗi router áp dụng per-hop behaviour (PHB) cho class. | Xuất sắc | Chỉ theo class | Mềm, theo class |
- Best-effort là mặc định của internet và là chuẩn nền mà mọi thứ khác cải thiện lên.
- IntServ cho cam kết cứng nhưng không mở rộng được: một router core chở hàng triệu flow không thể giữ reservation state cho từng flow. RSVP ngày nay chủ yếu sống sót dưới dạng RSVP-TE cho MPLS traffic engineering, không phải QoS mức host.
- DiffServ (RFC 2474/2475) là kẻ thắng thực tế. Traffic được classify và mark thành một nhúm class ở edge của mạng, và mỗi hop áp dụng một Per-Hop Behaviour (PHB) chỉ dựa trên dấu đó. Không có per-flow state nên mở rộng được ra cả internet. Gần như toàn bộ QoS doanh nghiệp là DiffServ.
Classification và marking
Classification là việc quyết định packet thuộc class nào (theo port, protocol, ACL, DPI, hoặc một dấu đã có). Marking ghi quyết định đó vào một field trong header để các thiết bị downstream tin dùng mà không cần classify lại. Nguyên tắc vàng: classify và mark một lần, càng gần nguồn càng tốt (trust boundary), rồi tin dùng dấu đó ở mọi nơi khác.
Layer 2: CoS (802.1p)
Bên trong 802.1Q VLAN tag có một field PCP (Priority Code Point) 3 bit, thường gọi là CoS (Class of Service). Nó cho 8 giá trị (0–7). Vì nằm trong VLAN tag, CoS chỉ tồn tại trong một Layer 2 domain — nó bị gỡ khi router bỏ tag, nên không mang priority qua một WAN đã routed.
Layer 3: DSCP (công cụ chủ lực)
Byte ToS của IPv4 (và byte Traffic Class của IPv6) được RFC 2474 định nghĩa lại thành field DSCP (Differentiated Services Code Point) 6 bit (cộng 2 bit nay dùng cho ECN). 6 bit cho 64 giá trị. Vì DSCP nằm trong IP header, nó tồn tại qua các routed hop end-to-end, đó là lý do nó là dấu chính cho QoS doanh nghiệp.
Các giá trị DSCP chuẩn và PHB của chúng:
| Tên DSCP | Thập phân | Lớp PHB | Dùng điển hình |
|---|---|---|---|
| EF (Expedited Forwarding) | 46 | Expedited Forwarding (RFC 3246) | Voice — latency thấp nghiêm ngặt, loss thấp |
| CS5 / AF41 | 40 / 34 | Class Selector / Assured Forwarding | Video tương tác/broadcast |
| AF31 / AF32 / AF33 | 26 / 28 / 30 | Assured Forwarding (RFC 2597) | Mission-critical / signalling |
| AF21–AF23 | 18 / 20 / 22 | Assured Forwarding | Data giao dịch |
| CS6 | 48 | Class Selector | Network control (routing protocol) |
| BE / DF (Default) | 0 | Default Forwarding | Data best-effort |
AF (Assured Forwarding) định nghĩa 4 class (AF1x–AF4x), mỗi class có 3 mức drop precedence (ví dụ AF31 bị drop cuối cùng, AF33 đầu tiên trong class 3). Điều này giúp một class đảm bảo bandwidth trong khi drop những packet ít quan trọng nhất trong nó trước khi congestion. EF (Expedited Forwarding) là PHB cao cấp: delay thấp, jitter thấp, loss thấp — dành riêng cho voice.
Queuing và scheduling
Khi packet phải chờ lúc congestion, chúng nằm trong các queue, và một scheduler quyết định thứ tự chúng rời đi. Đây chính là nơi việc ưu tiên thực sự diễn ra.
| Cơ chế | Cách hoạt động | Ưu điểm | Nhược điểm |
|---|---|---|---|
| FIFO | Một queue duy nhất, first-in-first-out. | Đơn giản, mặc định. | Không ưu tiên; một flow nặng làm đói các flow khác. |
| PQ (Priority Queuing) | Nhiều queue theo priority; queue cao hơn luôn được phục vụ trước, hết mới thôi. | Ưu tiên tuyệt đối cho traffic quan trọng. | Starvation — queue priority cao bận rộn có thể làm đói hoàn toàn queue thấp. |
| WFQ (Weighted Fair Queuing) | Các flow tự động chia bandwidth công bằng, có trọng số theo IP precedence. | Công bằng, không cần cấu hình, bảo vệ flow nhỏ. | Không có cam kết per-class rõ ràng; mở rộng kém trên link nhanh. |
| CBWFQ (Class-Based WFQ) | Admin định nghĩa class và cho mỗi class một phần bandwidth đảm bảo; phần dư chia sẻ. | Cam kết tối thiểu per-class rõ ràng. | Chưa đủ cho voice — không có latency thấp nghiêm ngặt. |
| LLQ (Low Latency Queuing) | CBWFQ cộng thêm một strict-priority queue (PQ) được phục vụ trước nhưng bị policed đến một mức trần. | Tốt nhất cả hai: latency thấp cho voice, đảm bảo cho data, không starvation. | Cấu hình phức tạp hơn chút; phải kích cỡ priority queue đúng. |
LLQ là chuẩn de facto cho converged network. Voice vào strict-priority queue (phục vụ trước nên latency và jitter thấp nhất) nhưng queue đó bị chặn trần để không làm đói data. Mọi thứ còn lại dùng các class CBWFQ với bandwidth đảm bảo.
Congestion management vs congestion avoidance
Đây là hai công việc khác nhau, dễ nhầm:
- Congestion management quyết định cách phục vụ các queue khi congestion đã tồn tại — tức là scheduling ở trên (LLQ, CBWFQ). Nó xử lý phần tồn đọng.
- Congestion avoidance cố ngăn các queue đầy lên ngay từ đầu, bằng cách drop một số packet sớm để báo hiệu bên gửi chậm lại trước khi buffer tràn.
Tail drop (mặc định ngây thơ)
Khi queue đầy, mọi packet mới đều bị drop (“drop ở đuôi”). Đơn giản, nhưng gây hai vấn đề cho TCP:
- Global synchronisation — nhiều flow TCP mất packet cùng lúc, tất cả cùng back off, rồi tất cả cùng tăng tốc lại, tạo hình răng cưa của lúc thiếu tải và quá tải.
- TCP starvation / loss theo burst — flow hung hăng và flow mong manh bị phạt như nhau.
WRED (Weighted Random Early Detection)
RED tránh tail drop bằng cách drop packet một cách ngẫu nhiên khi độ sâu queue trung bình tăng lên, trước khi queue đầy. Việc drop sớm ngẫu nhiên đánh vào các flow khác nhau ở thời điểm khác nhau, nên các flow TCP back off lệch nhau — không còn global synchronisation, utilisation mượt hơn. WRED thêm trọng số theo DSCP/drop-precedence: nó drop packet priority thấp (ví dụ AF33) sớm hơn và mạnh hơn packet priority cao (AF31). WRED chỉ hợp lý cho traffic TCP (thứ phản ứng với loss); bạn không bao giờ áp WRED cho queue voice/EF, vốn không được lợi gì khi bị bảo “chậm lại”. ECN là bản tinh chỉnh hiện đại — thay vì drop, router mark packet để bên gửi chậm lại mà không mất packet nào.
Traffic shaping vs policing
Cả hai đều áp một rate limit, nhưng xử lý phần traffic vượt ngưỡng theo hai cách trái ngược:
| Shaping | Policing | |
|---|---|---|
| Traffic vượt ngưỡng | Buffer (xếp queue) và gửi sau | Drop (hoặc re-mark) ngay lập tức |
| Ảnh hưởng tới rate | Làm mượt burst thành rate đều | Áp trần cứng, cho phép burst đến một giới hạn |
| Thêm delay/jitter | Có (do buffering) | Không (không buffering) |
| Thêm loss | Không (trừ khi buffer tràn) | Có (drop phần vượt) |
| Chiều | Thường outbound | Inbound hoặc outbound |
| Dùng điển hình | Khớp CIR cam kết ở WAN handoff; tránh bị policer downstream drop | ISP áp rate của khách; chặn traffic không quan trọng |
| Thân thiện TCP | Nhẹ nhàng (không gây retransmit) | Gắt (gây retransmit) |
Cách dùng kinh điển của shaping là khi port vật lý của bạn là 1 Gbps nhưng bạn chỉ mua 200 Mbps committed rate (CIR) từ carrier: bạn shape egress xuống 200 Mbps để bạn buffer và trì hoãn phần vượt, thay vì bắn 1 Gbps rồi để policer của carrier drop (gây retransmission và throughput tệ hơn). Policing là thứ carrier dùng ở đầu kia, và là thứ bạn dùng để chặn traffic bạn không quan tâm (ví dụ guest Wi-Fi).
Token bucket
Cả shaping lẫn policing đều được cài đặt bằng thuật toán token bucket:
- Token được thêm vào bucket ở committed rate (CIR), ví dụ một token mỗi bit.
- Bucket có kích thước tối đa, committed burst (Bc) — cho phép các burst ngắn vượt trung bình.
- Khi một packet đến, nó cần lượng token bằng kích thước của nó. Nếu đủ token, packet conform (gửi đi, trừ token). Nếu không, nó exceed — policer drop/re-mark; shaper xếp queue chờ token tích luỹ.
Biến thể dual-rate (CIR + PIR, với excess burst Be) cho ba màu — conform (xanh), exceed (vàng, thường bị re-mark sang drop precedence cao hơn), violate (đỏ, drop) — nền tảng của policing trTCM RFC 2698.
Bandwidth management và rate limiting
Rate limiting là hành động chung: chặn một flow, người dùng, hay ứng dụng đến một rate tối đa — cài đặt qua policing (drop) hoặc shaping (buffer). Ngoài các QoS class thô, đây là cách bạn:
- Áp fair use (chặn mỗi guest user ở 5 Mbps).
- Bảo vệ dịch vụ quan trọng khỏi một job backup mất kiểm soát.
- Cài bảo vệ API/DDoS ở edge (kiểu rate limiting của Cloudflare).
- Đảm bảo mức tối thiểu bằng CBWFQ và mức tối đa bằng policer trên cùng một class.
Packet prioritization trong thực tế
Ghép các mảnh lại trên một router WAN edge điển hình: classify ở ingress, mark bằng DSCP, rồi ở egress đang congestion áp LLQ để EF (voice) được strict priority, các AF class được bandwidth đảm bảo kèm WRED, còn best-effort lấy phần còn lại.
Ví dụ Cisco MQC (classify → mark → queue → shape)
QoS của Cisco dùng Modular QoS CLI (MQC): class-map (classify) → policy-map (làm gì) → service-policy (áp lên interface).
! 1. Classify traffic thành các class
class-map match-any VOICE
match protocol rtp ! hoặc: match dscp ef
class-map match-any CALL-SIGNALING
match dscp cs3 af31
class-map match-any CRITICAL-DATA
match access-group name BUSINESS-APPS
! 2. Policy marking ở trust boundary (ingress)
policy-map MARK-INGRESS
class VOICE
set dscp ef
class CALL-SIGNALING
set dscp cs3
class CRITICAL-DATA
set dscp af21
class class-default
set dscp default
! 3. Policy queuing cho egress đang congestion (LLQ)
policy-map WAN-EDGE-OUT
class VOICE
priority percent 20 ! strict-priority (LLQ), chặn trần ở 20%
class CALL-SIGNALING
bandwidth percent 5 ! đảm bảo CBWFQ
class CRITICAL-DATA
bandwidth percent 35
random-detect dscp-based ! WRED cho class TCP này
class class-default
bandwidth percent 25
random-detect ! WRED cho best-effort
fair-queue
! 4. Shape tổng egress xuống 200 Mbps cam kết, rồi queue bên trong đó
policy-map WAN-SHAPE
class class-default
shape average 200000000
service-policy WAN-EDGE-OUT ! lồng nhau: queue trong rate đã shape
! 5. Áp lên các interface
interface GigabitEthernet0/1
description LAN
service-policy input MARK-INGRESS
interface GigabitEthernet0/0
description WAN to carrier
service-policy output WAN-SHAPE
Kiểm tra bằng show policy-map interface GigabitEthernet0/0 — nó hiện số packet, drop và độ sâu queue theo từng class.
Ví dụ Linux tc (HTB shaping + priority)
Trên Linux, tc (traffic control) với qdisc HTB (Hierarchical Token Bucket) làm shaping và chia sẻ bandwidth theo class; một priority class xử lý traffic latency thấp.
# Root HTB qdisc trên eth0, class mặc định 30
tc qdisc add dev eth0 root handle 1: htb default 30
# Class cha = tổng rate đã shape (200 Mbit)
tc class add dev eth0 parent 1: classid 1:1 htb rate 200mbit
# Voice: đảm bảo 20 Mbit, có thể mượn đến 200, priority cao nhất
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 20mbit ceil 200mbit prio 0
# Critical data: đảm bảo 100 Mbit
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 100mbit ceil 200mbit prio 1
# Best-effort mặc định: đảm bảo 30 Mbit
tc class add dev eth0 parent 1:1 classid 1:30 htb rate 30mbit ceil 200mbit prio 2
# Cho voice một leaf qdisc latency thấp; cho data một qdisc fair/AQM (fq_codel)
tc qdisc add dev eth0 parent 1:10 handle 10: pfifo
tc qdisc add dev eth0 parent 1:20 handle 20: fq_codel
tc qdisc add dev eth0 parent 1:30 handle 30: fq_codel
# Filter: match DSCP EF (0xb8 trong byte ToS) vào class voice
tc filter add dev eth0 parent 1: protocol ip prio 1 u32 \
match ip tos 0xb8 0xfc flowid 1:10
# Policing ingress đơn giản: drop mọi thứ vượt 50 Mbit ở ingress
tc qdisc add dev eth0 handle ffff: ingress
tc filter add dev eth0 parent ffff: protocol ip u32 match u32 0 0 \
police rate 50mbit burst 100k drop flowid :1
fq_codel đáng nhắc đến: nó là một qdisc AQM (Active Queue Management) hiện đại chống lại bufferbloat (latency dư thừa do buffer quá lớn) bằng cách tự động giữ queue ngắn — đây là leaf qdisc mặc định hợp lý cho traffic thông thường.
Traffic management và load balancing
QoS quyết định cách đối xử với packet trên một link cho trước; load balancing quyết định flow dùng link hay server nào, trải tải để ngay từ đầu không path hay server nào bị nghẽn — nội dung trong ./09-redundancy-and-high-availability.md. Chúng bổ trợ nhau: load balancing giảm tần suất congestion bằng cách dùng capacity hiệu quả, còn QoS xử lý congestion một cách duyên dáng khi nó vẫn xảy ra. Một WAN thiết kế tốt dùng cả hai — ECMP/load-sharing qua các link dự phòng cộng với QoS policy trên từng link — và không cái nào thay thế được cái kia, cũng không thay được việc đơn giản là có đủ bandwidth.
Bảng tổng hợp các cơ chế QoS
| Cơ chế | Nhóm | Tác dụng | Cisco / Linux |
|---|---|---|---|
| Classification | Nhận diện | Phân packet vào các class | class-map / tc filter |
| Marking | Đánh dấu | Ghi DSCP/CoS để bên khác tin dùng | set dscp / tc ... set dsfield |
| CBWFQ | Congestion mgmt | Đảm bảo bandwidth theo class | bandwidth percent / HTB rate |
| LLQ / PQ | Congestion mgmt | Queue strict latency thấp (voice) | priority / HTB prio 0 |
| WFQ | Congestion mgmt | Công bằng per-flow tự động | fair-queue / fq_codel |
| WRED / RED | Congestion avoidance | Drop sớm để tránh tail drop & TCP sync | random-detect / RED qdisc |
| Shaping | Rate control | Buffer phần vượt về rate đều | shape average / HTB ceil |
| Policing | Rate control | Drop/re-mark phần vượt ngay lập tức | police / tc ... police |
| AQM (CoDel) | Congestion avoidance | Chống bufferbloat, giữ queue ngắn | — / fq_codel, codel |
Best Practices
- Classify và mark một lần, ở trust boundary. Mark càng gần nguồn càng tốt (lý tưởng là IP phone hoặc access switch), rồi tin dùng DSCP ở mọi nơi khác. Classify lại sâu trong mạng vừa tốn kém vừa dễ sai. Lập một trust boundary: endpoint không tin cậy sẽ bị re-mark/reset ở access port để người dùng không tự mark traffic bulk của mình thành EF.
- Dùng một scheme DSCP nhất quán, theo chuẩn, end-to-end. Theo khuyến nghị class của RFC 4594 (EF cho voice, AF41 cho video, AF31 cho signalling, v.v.) để dấu của bạn có cùng ý nghĩa ở mọi hop và qua các carrier. Xác nhận carrier ISP/MPLS honour giá trị DSCP nào — nhiều bên remark về BE ở handoff trừ khi bạn mua dịch vụ có QoS.
- QoS chỉ cần ở nơi có congestion — hầu như luôn là WAN edge và uplink internet, hiếm khi ở LAN core đã over-provision. Áp policy chi tiết ở đó; giữ core đơn giản (chỉ trust và forward).
- Không bao giờ để queue priority (LLQ) làm đói mọi thứ khác. Luôn chặn trần nó (
priority percent) và kích cỡ theo nhu cầu voice thực (~33% link trở xuống là trần phổ biến). Voice vượt trần nên bị chặn bởi admission control, không phải để nó đè bẹp data. - Shape ở egress cho khớp rate của carrier. Nếu carrier police ở handoff, shape dưới CIR của họ để router của bạn buffer (không retransmit) thay vì policer của họ drop (nhiều retransmit).
- Chỉ áp WRED cho traffic TCP/phản ứng được. Không bao giờ áp WRED hay ECN cho queue EF/voice — media real-time trên UDP không thể chậm lại khi bị loss.
- Ưu tiên shaping hơn policing cho traffic bạn quan tâm (buffer, đừng drop); dùng policing cho trần cứng với traffic bạn không quan tâm (guest, scavenger class).
- Chống bufferbloat. Buffer quá lớn, không được quản lý sẽ thêm latency ngay cả khi không có “vấn đề” QoS. Dùng AQM (
fq_codel, CoDel, PIE) trên các queue thông thường để giữ latency thấp khi tải cao. - Nhớ rằng QoS quản lý sự khan hiếm, nó không tạo ra bandwidth. Nếu một link nghẽn kinh niên, QoS bảo vệ voice nhưng data vẫn khổ — cách sửa thật sự là thêm capacity hoặc load balancing tốt hơn (
./09-redundancy-and-high-availability.md). QoS mua cho bạn sự suy giảm duyên dáng, không phải capacity miễn phí. - Đo trước và sau. Lấy baseline latency, jitter và loss bằng công cụ trong
./15-tools-and-troubleshooting.md, thay đổi từng policy một, và kiểm chứng bằngshow policy-map interface/tc -s qdisc showrằng packet rơi vào đúng class và drop rơi đúng nơi bạn muốn.
Tài liệu tham khảo
- RFC 2474 — Definition of the Differentiated Services Field (DS Field / DSCP)
- RFC 2475 — An Architecture for Differentiated Services
- RFC 2597 — Assured Forwarding PHB Group & RFC 3246 — Expedited Forwarding PHB
- RFC 4594 — Configuration Guidelines for DiffServ Service Classes
- Cisco — Quality of Service (QoS) Configuration Guides & Design
- Cisco — Comparing Traffic Policing and Traffic Shaping
- Cloudflare — What is Quality of Service (QoS)?
- Linux
tc(traffic control) manual pages — tc(8), tc-htb(8), tc-fq_codel(8)
Part of the Network Engineer Roadmap knowledge base.
Overview
Every link on a network has a finite capacity, and for most of the day that capacity is more than enough. The interesting moments — the ones that make or break a user’s experience — happen during congestion, when more traffic wants to cross a link than the link can carry at that instant. When that happens the router or switch has to make a decision: which packets go first, which packets wait, and which packets get thrown away. Quality of Service (QoS) is the collection of tools that lets you make that decision deliberately, according to business priorities, instead of leaving it to chance.
Without QoS a network is best-effort: every packet is treated identically, first-in-first-out, and during congestion the packets that arrive when the buffer is full are simply dropped. That is perfectly fine for a file download — TCP will retransmit and the user waits a few extra milliseconds. It is a disaster for a voice call, where a 200 ms delay or a 2% loss turns speech into a robotic stutter. On a converged network — one that carries voice, video, and data over the same infrastructure — these traffic types have wildly different needs, and best-effort cannot serve all of them at once.
Traffic management is the broader discipline of controlling how traffic uses the network: not only prioritising during congestion (QoS proper), but also shaping bursts to fit a contracted rate, policing traffic that exceeds a limit, rate-limiting individual users or applications, and steering flows across links. This note builds up from the raw performance metrics you are trying to protect, through the QoS models and mechanisms, to how it all comes together on a real WAN link.
QoS relates closely to other topics in this roadmap. It sits on top of the transport and application protocols in ./06-core-protocols.md (a VoIP call is RTP over UDP; a download is TCP), it complements the redundancy and load-balancing techniques in ./09-redundancy-and-high-availability.md, and the metrics it protects are the same ones you measure with the tools in ./15-tools-and-troubleshooting.md.
Fundamentals
Performance metrics: what QoS actually protects
You cannot manage what you cannot define. The four metrics below are the currency of traffic management — every QoS mechanism exists to improve one or more of them for the traffic that matters.
Bandwidth vs throughput vs goodput
These three are constantly confused, but they are distinct:
| Term | Definition | Example |
|---|---|---|
| Bandwidth | The theoretical maximum rate a link can carry, set by the physical/link technology. A capacity, not a measurement. | A 1 Gbps Ethernet link has 1 Gbps of bandwidth. |
| Throughput | The actual rate of data successfully delivered over the link, measured over time. Always ≤ bandwidth. | That 1 Gbps link might only deliver 940 Mbps of throughput after overhead and contention. |
| Goodput | The rate of useful application data delivered, excluding protocol overhead, retransmissions, and headers. Always ≤ throughput. | Of 940 Mbps throughput, maybe 900 Mbps is actual file payload — the rest is TCP/IP/Ethernet headers and retransmits. |
The gap between bandwidth and throughput comes from protocol overhead, half-duplex collisions, contention, and the TCP window/RTT relationship. The gap between throughput and goodput comes from headers and retransmissions. When a user says “the internet is slow” they almost always mean goodput feels low, even though the bandwidth they pay for is high.
Latency (delay) and its components
Latency is the time for a packet to travel from source to destination (one-way delay), or there and back (round-trip time, RTT). It is the sum of several independent components, and knowing which one dominates tells you what to fix:
| Component | Cause | How to reduce |
|---|---|---|
| Propagation delay | Time for the signal to physically travel the distance, limited by the speed of light in the medium (~5 µs/km in fibre). | Shorter path / closer server (CDN). Cannot beat physics. |
| Serialization delay | Time to clock all the bits of a packet onto the wire = packet size ÷ link rate. A 1500-byte packet on a 1 Mbps link takes 12 ms; on 1 Gbps it takes 12 µs. | Faster links, smaller packets (fragmentation for slow links). |
| Queuing delay | Time a packet waits in a buffer behind other packets during congestion. Highly variable — this is what QoS controls. | Prioritise the packet (LLQ/PQ), reduce queue depth, manage congestion (WRED). |
| Processing delay | Time the device spends inspecting headers, doing lookups, ACLs, NAT. Usually small on modern hardware. | Faster hardware, hardware offload. |
The critical insight: QoS cannot reduce propagation or serialization delay — those are fixed by geography and link speed. What QoS controls is queuing delay, by choosing whose packets wait and whose do not.
Jitter (delay variation)
Jitter is the variation in one-way latency between consecutive packets. If packets in a voice stream arrive 20 ms, 22 ms, 19 ms, 45 ms, 18 ms apart, the jitter is the spread of those inter-arrival times. Real-time applications play out audio/video at a constant rate, so a receiver uses a jitter buffer (de-jitter buffer) to absorb variation — but a buffer that is too small drops late packets, and one that is too large adds delay. Jitter is caused mainly by variable queuing delay, which is exactly why prioritising voice into a low-latency queue reduces jitter.
Packet loss
Packet loss is the percentage of packets that never arrive. Causes include buffer overflow during congestion (tail drop), bit errors on the physical layer, policing drops, and routing changes. TCP recovers from loss by retransmitting (at the cost of goodput and delay); UDP-based real-time media generally does not retransmit — a lost voice packet is simply gone, heard as a click or gap.
Target values for common traffic types
| Traffic type | One-way latency | Jitter | Loss |
|---|---|---|---|
| Voice (VoIP) | ≤ 150 ms | ≤ 30 ms | ≤ 1% |
| Interactive video | ≤ 200 ms | ≤ 30 ms | ≤ 0.1–1% |
| Streaming video (buffered) | Loose (seconds of buffer) | Loose | ≤ 1–2% |
| Bulk data (file, backup) | Loose | Irrelevant | Recovered by TCP |
| Transactional data | ≤ 400 ms | Irrelevant | Recovered by TCP |
Measuring the metrics
You verify these numbers with the tools covered in ./15-tools-and-troubleshooting.md, briefly:
ping— RTT and loss, quick reachability check.iperf3— throughput/goodput between two hosts, TCP or UDP; UDP mode reports jitter and loss.- Speedtest (Ookla/Fast.com) — download/upload throughput and latency to a nearby server, from an end-user perspective.
mtr— combines traceroute and ping to show per-hop latency and loss, isolating where the problem is.
# Throughput (TCP) between client and a server running `iperf3 -s`
iperf3 -c 10.0.0.1 -t 30
# UDP test at 5 Mbps — reports jitter and packet loss, ideal for VoIP simulation
iperf3 -c 10.0.0.1 -u -b 5M -t 30
Why QoS: converged networks and congestion
Historically voice ran on a dedicated TDM phone network and data ran on IP; each was engineered for its own traffic. Modern networks converge everything onto IP to cut cost and simplify operations — but now a bulk backup can fill the same WAN link as a live sales call. Because these applications have opposite requirements (bulk wants throughput and tolerates delay; voice wants low delay and tolerates loss of throughput), the network needs a way to tell them apart and treat them differently. That is the reason QoS exists.
QoS only does anything during congestion. On an uncongested link every packet goes out immediately regardless of priority — there is nothing to prioritise. The value of QoS is entirely in how it behaves when demand exceeds capacity, which on WAN and internet-facing links happens more often than you would expect, in microbursts even when average utilisation looks low.
Key Concepts
QoS models
There are three architectural approaches to QoS. Real networks usually run DiffServ, but you should understand all three.
| Model | How it works | Scalability | State in core | Guarantee |
|---|---|---|---|---|
| Best-Effort | No QoS. All packets equal, FIFO. | Infinite | None | None |
| IntServ (Integrated Services) | Apps signal their needs end-to-end with RSVP; every router reserves resources per flow. | Poor — per-flow state everywhere | Per-flow | Hard, per-flow |
| DiffServ (Differentiated Services) | Packets are marked into a few classes at the edge; each router applies a per-hop behaviour (PHB) to the class. | Excellent | Per-class only | Soft, per-class |
- Best-effort is the internet’s default and the baseline everything else improves on.
- IntServ offers hard guarantees but does not scale: a core router carrying millions of flows cannot hold reservation state for each. RSVP survives today mainly as RSVP-TE for MPLS traffic engineering, not for host-level QoS.
- DiffServ (RFC 2474/2475) is the practical winner. Traffic is classified and marked into a handful of classes at the network edge, and each hop applies a Per-Hop Behaviour (PHB) based only on the mark. No per-flow state, so it scales to the whole internet. Almost all enterprise QoS is DiffServ.
Classification and marking
Classification is deciding which class a packet belongs to (by port, protocol, ACL, DPI, or an existing mark). Marking writes that decision into a header field so downstream devices can trust it without re-classifying. The golden rule: classify and mark once, as close to the source as possible (the trust boundary), then trust the mark everywhere else.
Layer 2: CoS (802.1p)
Inside an 802.1Q VLAN tag there is a 3-bit PCP (Priority Code Point) field, commonly called CoS (Class of Service). It gives 8 values (0–7). Because it lives in the VLAN tag, CoS only survives within a Layer 2 domain — it is stripped when a router removes the tag, so it cannot carry priority across a routed WAN.
Layer 3: DSCP (the workhorse)
The IPv4 ToS byte (and IPv6 Traffic Class byte) was redefined by RFC 2474 into a 6-bit DSCP (Differentiated Services Code Point) field (plus 2 bits now used for ECN). 6 bits give 64 values. Because DSCP lives in the IP header, it survives across routed hops end-to-end, which is why it is the primary marking for enterprise QoS.
Standard DSCP values and their PHBs:
| DSCP name | Decimal | PHB class | Typical use |
|---|---|---|---|
| EF (Expedited Forwarding) | 46 | Expedited Forwarding (RFC 3246) | Voice — strict low-latency, low-loss |
| CS5 / AF41 | 40 / 34 | Class Selector / Assured Forwarding | Interactive/broadcast video |
| AF31 / AF32 / AF33 | 26 / 28 / 30 | Assured Forwarding (RFC 2597) | Mission-critical / signalling |
| AF21–AF23 | 18 / 20 / 22 | Assured Forwarding | Transactional data |
| CS6 | 48 | Class Selector | Network control (routing protocols) |
| BE / DF (Default) | 0 | Default Forwarding | Best-effort data |
AF (Assured Forwarding) defines 4 classes (AF1x–AF4x), each with 3 drop precedences (e.g. AF31 is dropped last, AF33 first within class 3). This lets a class guarantee bandwidth while dropping the least-important packets within it first during congestion. EF (Expedited Forwarding) is the premium PHB: low delay, low jitter, low loss — reserved for voice.
Queuing and scheduling
When packets wait during congestion they sit in queues, and a scheduler decides the order they leave. This is where prioritisation actually happens.
| Discipline | How it works | Pros | Cons |
|---|---|---|---|
| FIFO | Single queue, first-in-first-out. | Simple, default. | No prioritisation; one heavy flow starves others. |
| PQ (Priority Queuing) | Multiple queues by priority; higher queue always served first, completely. | Absolute priority for critical traffic. | Starvation — a busy high-priority queue can starve lower ones entirely. |
| WFQ (Weighted Fair Queuing) | Flows get fair share of bandwidth automatically, weighted by IP precedence. | Fair, no config, protects small flows. | No explicit per-class guarantees; scales poorly on fast links. |
| CBWFQ (Class-Based WFQ) | Admin defines classes and gives each a guaranteed bandwidth share; excess is shared. | Explicit per-class minimum guarantees. | Not enough alone for voice — no strict low latency. |
| LLQ (Low Latency Queuing) | CBWFQ plus a strict-priority queue (PQ) that is served first but policed to a cap. | Best of both: low latency for voice, guarantees for data, no starvation. | Slightly more config; must size the priority queue right. |
LLQ is the de facto standard for converged networks. Voice goes into the strict-priority queue (served first, so lowest latency and jitter) but that queue is capped so it cannot starve data. Everything else uses CBWFQ classes with guaranteed bandwidth.
Congestion management vs congestion avoidance
These are two different jobs, easy to confuse:
- Congestion management decides how to service the queues once congestion exists — i.e. the scheduling above (LLQ, CBWFQ). It handles the backlog.
- Congestion avoidance tries to prevent the queues from ever filling up, by dropping some packets early to signal senders to slow down before the buffer overflows.
Tail drop (the naive default)
When a queue is full, every new packet is dropped (“dropped off the tail”). Simple, but it causes two problems for TCP:
- Global synchronisation — many TCP flows lose packets at the same instant, all back off together, then all ramp up together, producing a sawtooth of under- and over-utilisation.
- TCP starvation / bursty loss — aggressive flows and fragile flows are punished equally.
WRED (Weighted Random Early Detection)
RED avoids tail drop by randomly dropping packets as the average queue depth grows, before the queue is full. Random early drops hit different flows at different times, so TCP flows back off at staggered moments — no global synchronisation, smoother utilisation. WRED adds weighting by DSCP/drop-precedence: it drops lower-priority (e.g. AF33) packets earlier and more aggressively than higher-priority (AF31) ones. WRED is only sensible for TCP traffic (which responds to loss); you never apply it to the voice/EF queue, which cannot benefit from being told to slow down. ECN is the modern refinement — instead of dropping, the router marks packets so senders slow down without any loss at all.
Traffic shaping vs policing
Both enforce a rate limit, but they handle excess traffic in opposite ways:
| Shaping | Policing | |
|---|---|---|
| Excess traffic | Buffered (queued) and sent later | Dropped (or re-marked) immediately |
| Effect on rate | Smooths bursts into a steady rate | Enforces a hard ceiling, allows bursts to a limit |
| Adds delay/jitter | Yes (buffering) | No (no buffering) |
| Adds loss | No (unless buffer overflows) | Yes (drops excess) |
| Direction | Usually outbound | Inbound or outbound |
| Typical use | Match a contracted CIR on a WAN handoff; avoid downstream policer drops | ISP enforcing a customer’s rate; capping non-critical traffic |
| TCP friendliness | Kind (retransmit-free) | Harsh (causes retransmits) |
The classic use of shaping is when your physical port is 1 Gbps but you only bought 200 Mbps of committed rate (CIR) from the carrier: you shape your egress to 200 Mbps so you buffer and delay the excess, rather than blasting 1 Gbps and letting the carrier’s policer drop it (which would cause retransmissions and worse throughput). Policing is what the carrier uses on the other side, and what you use to cap traffic you do not care about (e.g. guest Wi-Fi).
Token bucket
Both shaping and policing are implemented with a token bucket algorithm:
- Tokens are added to a bucket at the committed rate (CIR), e.g. one token per bit.
- The bucket has a maximum size, the committed burst (Bc) — this allows short bursts above the average.
- When a packet arrives, it needs tokens equal to its size. If enough tokens exist, the packet conforms (sent, tokens removed). If not, it exceeds — a policer drops/re-marks it; a shaper queues it until tokens accumulate.
A dual-rate variant (CIR + PIR, with an excess burst Be) gives three colours — conform (green), exceed (yellow, often re-marked to a higher drop precedence), violate (red, dropped) — the basis of RFC 2698 trTCM policing.
Bandwidth management and rate limiting
Rate limiting is the general act of capping a flow, user, or application to a maximum rate — implemented via policing (drop) or shaping (buffer). Beyond raw QoS classes it is how you:
- Enforce fair use (cap each guest user to 5 Mbps).
- Protect critical services from a runaway backup job.
- Implement API/DDoS protection at the edge (see Cloudflare-style rate limiting).
- Guarantee a minimum via CBWFQ and a maximum via a policer on the same class.
Packet prioritization in practice
Putting the pieces together on a typical WAN edge router: classify at ingress, mark with DSCP, then on the congested egress apply LLQ so EF (voice) gets strict priority, AF classes get guaranteed bandwidth with WRED, and best-effort takes what’s left.
Cisco MQC example (classify → mark → queue → shape)
Cisco QoS uses the Modular QoS CLI (MQC): class-map (classify) → policy-map (what to do) → service-policy (apply to interface).
! 1. Classify traffic into classes
class-map match-any VOICE
match protocol rtp ! or: match dscp ef
class-map match-any CALL-SIGNALING
match dscp cs3 af31
class-map match-any CRITICAL-DATA
match access-group name BUSINESS-APPS
! 2. Marking policy at the trust boundary (ingress)
policy-map MARK-INGRESS
class VOICE
set dscp ef
class CALL-SIGNALING
set dscp cs3
class CRITICAL-DATA
set dscp af21
class class-default
set dscp default
! 3. Queuing policy for the congested egress (LLQ)
policy-map WAN-EDGE-OUT
class VOICE
priority percent 20 ! strict-priority (LLQ), capped at 20%
class CALL-SIGNALING
bandwidth percent 5 ! CBWFQ guarantee
class CRITICAL-DATA
bandwidth percent 35
random-detect dscp-based ! WRED for this TCP class
class class-default
bandwidth percent 25
random-detect ! WRED for best-effort
fair-queue
! 4. Shape total egress to the contracted 200 Mbps, then queue inside it
policy-map WAN-SHAPE
class class-default
shape average 200000000
service-policy WAN-EDGE-OUT ! nested: queue within the shaped rate
! 5. Apply to interfaces
interface GigabitEthernet0/1
description LAN
service-policy input MARK-INGRESS
interface GigabitEthernet0/0
description WAN to carrier
service-policy output WAN-SHAPE
Verify with show policy-map interface GigabitEthernet0/0 — it shows per-class packet counts, drops, and queue depths.
Linux tc example (HTB shaping + priority)
On Linux, tc (traffic control) with the HTB (Hierarchical Token Bucket) qdisc does shaping and class-based bandwidth sharing; a priority class handles low-latency traffic.
# Root HTB qdisc on eth0, default class 30
tc qdisc add dev eth0 root handle 1: htb default 30
# Parent class = total shaped rate (200 Mbit)
tc class add dev eth0 parent 1: classid 1:1 htb rate 200mbit
# Voice: guaranteed 20 Mbit, can borrow up to 200, highest priority
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 20mbit ceil 200mbit prio 0
# Critical data: guaranteed 100 Mbit
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 100mbit ceil 200mbit prio 1
# Best-effort default: guaranteed 30 Mbit
tc class add dev eth0 parent 1:1 classid 1:30 htb rate 30mbit ceil 200mbit prio 2
# Give voice a low-latency leaf qdisc; give data a fair/AQM qdisc (fq_codel)
tc qdisc add dev eth0 parent 1:10 handle 10: pfifo
tc qdisc add dev eth0 parent 1:20 handle 20: fq_codel
tc qdisc add dev eth0 parent 1:30 handle 30: fq_codel
# Filter: match DSCP EF (0xb8 in the ToS byte) into the voice class
tc filter add dev eth0 parent 1: protocol ip prio 1 u32 \
match ip tos 0xb8 0xfc flowid 1:10
# Simple ingress policing: drop anything over 50 Mbit on ingress
tc qdisc add dev eth0 handle ffff: ingress
tc filter add dev eth0 parent ffff: protocol ip u32 match u32 0 0 \
police rate 50mbit burst 100k drop flowid :1
fq_codel deserves a mention: it is a modern AQM (Active Queue Management) qdisc that fights bufferbloat (excess latency from oversized buffers) by keeping queues short automatically — it is the sensible default leaf qdisc for general traffic.
Traffic management and load balancing
QoS decides how to treat packets on a given link; load balancing decides which link or server a flow uses, spreading load so no single path or server congests in the first place — covered in ./09-redundancy-and-high-availability.md. They are complementary: load balancing reduces the frequency of congestion by using capacity efficiently, while QoS handles congestion gracefully when it still happens. A well-designed WAN uses both — ECMP/load-sharing across redundant links plus per-link QoS policies — and neither is a substitute for the other, nor for simply having enough bandwidth.
Summary table of QoS mechanisms
| Mechanism | Category | What it does | Cisco / Linux |
|---|---|---|---|
| Classification | Identify | Sort packets into classes | class-map / tc filter |
| Marking | Mark | Write DSCP/CoS so others trust it | set dscp / tc ... set dsfield |
| CBWFQ | Congestion mgmt | Guarantee bandwidth per class | bandwidth percent / HTB rate |
| LLQ / PQ | Congestion mgmt | Strict low-latency queue (voice) | priority / HTB prio 0 |
| WFQ | Congestion mgmt | Automatic per-flow fairness | fair-queue / fq_codel |
| WRED / RED | Congestion avoidance | Drop early to prevent tail drop & TCP sync | random-detect / RED qdisc |
| Shaping | Rate control | Buffer excess to a steady rate | shape average / HTB ceil |
| Policing | Rate control | Drop/re-mark excess immediately | police / tc ... police |
| AQM (CoDel) | Congestion avoidance | Fight bufferbloat, keep queues short | — / fq_codel, codel |
Best Practices
- Classify and mark once, at the trust boundary. Mark as close to the source as possible (ideally the IP phone or the access switch), then trust the DSCP everywhere else. Re-classifying deep in the network is expensive and error-prone. Establish a trust boundary: untrusted endpoints get re-marked/reset at the access port so users cannot mark their own bulk traffic as EF.
- Use a consistent, standards-based DSCP scheme end-to-end. Follow RFC 4594 class recommendations (EF for voice, AF41 for video, AF31 for signalling, etc.) so your marks mean the same thing at every hop and across carriers. Confirm what DSCP values your ISP/MPLS carrier honours — many remark to BE at the handoff unless you buy a QoS-enabled service.
- QoS is only needed where congestion happens — almost always the WAN edge and internet uplinks, rarely the over-provisioned LAN core. Apply detailed policies there; keep the core simple (just trust and forward).
- Never let the priority (LLQ) queue starve everything else. Always cap it (
priority percent) and size it to real voice demand (~33% or less of the link is a common ceiling). Voice above the cap should be dropped by admission control, not allowed to crush data. - Shape on egress to match your carrier’s rate. If the carrier polices your handoff, shape below their CIR so your router does the buffering (retransmit-free) instead of their policer dropping (retransmit-heavy).
- Only apply WRED to TCP/responsive traffic. Never apply WRED or ECN to the EF/voice queue — UDP real-time media cannot slow down in response to loss.
- Prefer shaping over policing for traffic you care about (buffer, don’t drop); use policing for hard caps on traffic you don’t (guest, scavenger class).
- Fight bufferbloat. Oversized, unmanaged buffers add latency even without a QoS “problem.” Use AQM (
fq_codel, CoDel, PIE) on general queues to keep latency low under load. - Remember QoS manages scarcity, it does not create bandwidth. If a link is chronically saturated, QoS protects voice but data still suffers — the real fix is more capacity or better load balancing (
./09-redundancy-and-high-availability.md). QoS buys you graceful degradation, not free capacity. - Measure before and after. Baseline latency, jitter, and loss with the tools in
./15-tools-and-troubleshooting.md, change one policy at a time, and verify withshow policy-map interface/tc -s qdisc showthat packets land in the right class and drops fall where you intend.
References
- RFC 2474 — Definition of the Differentiated Services Field (DS Field / DSCP)
- RFC 2475 — An Architecture for Differentiated Services
- RFC 2597 — Assured Forwarding PHB Group & RFC 3246 — Expedited Forwarding PHB
- RFC 4594 — Configuration Guidelines for DiffServ Service Classes
- Cisco — Quality of Service (QoS) Configuration Guides & Design
- Cisco — Comparing Traffic Policing and Traffic Shaping
- Cloudflare — What is Quality of Service (QoS)?
- Linux
tc(traffic control) manual pages — tc(8), tc-htb(8), tc-fq_codel(8)