STUDY · NETWORK GUIDE

5-7 HQoS (階層QoS) — 1本のWANを拠点ごとのサブレートに分ける

1 本の物理 WAN (Gi3・1G) を dot1q サブインタフェースで 2 拠点の独立したサブレート契約帯域に分け、各サブ IF の親 shaper (拠点A 400k / 拠点B 300k) で拠点別に帯域を独立させ、その契約帯域の中でさらに子 CBWFQ / LLQ でクラス優先する階層 QoS (HQoS) を csr1000v (IOS-XE 17.03.08a) の実機で扱う。核はサブレート分離で、拠点A を過負荷 (700k) に、拠点B を契約内 (250k) にして並行送出したとき、拠点A が大量 drop (total drops 522・loss 50%) しても拠点B は完全に独立に守られる (drops 0・loss 0%・jitter 0.07ms) ことを実測で示す。物理 IF 直付けの 1 段では表現できない多拠点サブレートの必然を数値で確かめる第 5 章 QoS 編の実機節。

1. 前節の振り返りと本節の内容

前節 5-6 Queuing 基礎 では、輻輳時に複数クラスの送出順を決めるキューイングを csr1000v の実機で組み立てました。キューイングは輻輳時にしか働かないため、親 shaper (shape average 500000) で egress を絞ってボトルネックを作り、その配下に子ポリシーをぶら下げる階層型ポリシーで FIFO・WFQ・CBWFQ・LLQ の 4 機構を対比しました。CBWFQ は帯域を守り、LLQ は遅延を守る、という守る対象の違いを、受信側 PC2 の実測レート・loss・jitter で確かめました。

5-6 で使った階層型ポリシーは、1 つの物理インタフェース (Gi3) に直付けの 1 段構成でした。親 shaper が物理 IF の egress を絞り、その配下の子ポリシーがクラスを並べ替える、という 1 本の階層です。この構成は「1 本の回線の中でクラスの優先度をつける」ことはできますが、「1 本の物理回線を複数の拠点で分け合い、拠点ごとに独立した帯域を保証する」ことはできません。

本節はここから軸を変え、1 本の物理 WAN を、複数の論理サブレート (契約帯域) に分け、各サブレートの中でさらにクラス優先する 構成を扱います。この階層構造を階層 QoS (HQoS: Hierarchical QoS) と呼びます。実務の WAN は、物理インタフェースの速度より低い契約速度で回線を借りるサブレート (sub-rate) の環境が定石で、1 本の物理回線を複数拠点・複数サービスに契約帯域で切り分けます。本節では、物理 Gi3 (1G) を dot1q サブインタフェースで 2 拠点に分け、各拠点が独立したサブレート契約帯域を持ち、その帯域の中でさらに音声を優先する HQoS を csr1000v の実機で組みます。

本節の核は サブレート分離 です。1 本の物理回線を拠点ごとの契約帯域に切ると、ある拠点が契約帯域を超えて過負荷になっても、その影響が他の拠点に波及しません。この独立性を、拠点A を過負荷に、拠点B を契約内にして並行送出したときの受信レート・loss・jitter の差で確かめます。

2. HQoS とは — 物理 1 本を論理サブレートに分ける

HQoS は、1 本の物理インタフェースを複数の論理的な帯域 (サブレート) に分割し、各サブレートの中でさらにクラス別の QoS を適用する階層構造です。5-6 の 1 段の階層型ポリシーが「1 本の回線 → クラス」という 1 階層だったのに対し、HQoS は「物理回線 → 拠点ごとのサブレート契約帯域 → クラス」という論理階層を持ちます。

HQoS が必要になる典型は、WAN のサブレート契約です。物理的には 1 Gbps のインタフェースで拠点間を結んでいても、キャリアとの契約帯域は拠点ごとに 400 kbps や 300 kbps といった低い値で借りることがあります。物理 IF の速度でトラフィックを送り出すと契約帯域を超え、キャリア側の入口で超過分が捨てられます。これを避けるには、ルータの出口で拠点ごとの契約帯域に絞り込み、絞った帯域の中でクラス優先をつける必要があります。この「拠点ごとに絞る + 拠点内でクラス優先」の 2 つを同時に実現するのが HQoS です。

物理 1 本を拠点ごとに分ける手段が、dot1q サブインタフェースです。1 本の物理 Gi3 を dot1q トランクにし、拠点 A 用の Gi3.100 (VLAN 100) と拠点 B 用の Gi3.200 (VLAN 200) という 2 つのサブインタフェースを作ります。各サブインタフェースに、拠点ごとの契約帯域に絞る親 shaper (拠点A は shape average 400000、拠点B は shape average 300000) を当て、その配下に子の CBWFQ / LLQ をぶら下げます。5-6 の親 shaper が物理 IF に 1 つだったのに対し、HQoS では サブインタフェースごとに独立した親 shaper を置くことが、多拠点サブレートの正体です。

サブインタフェース自体には固有の輻輳点がありません。5-6 で確認したとおり、キューイングは送りたい量が送れる量を超えたときにしか働かないため、サブインタフェースに子ポリシーを当てても、親で帯域を絞らなければ輻輳が起きず、子は発火しません。サブインタフェースの親には必ず shaper を置いて契約帯域を作り、その中で子ポリシーがクラスを並べ替える、という 2 段が HQoS の基本形になります。

3. トポロジと 2 拠点サブレートの構成

本節の検証は、5-6 と同じ csr1000v の L3 構成を base に、出口の Gi3 を dot1q トランク化し、2 つのサブインタフェースを新設します。PC1 が 2 拠点宛に VOICE (EF) と DATA (AF11) を並行送出し、R1 (csr1000v) が宛先で該当するサブインタフェースへ振り分け、そのサブインタフェースの HQoS ポリシーが適用されます。受信側 PC2 は 2 つの VLAN サブインタフェースで拠点別に受信し、拠点ごとの実測レートがサブレート分離の正本になります。

検証ラボ。物理 Gi3(1G) を dot1q サブ IF で 2 拠点のサブレートに分割する。Gi3.100 (dot1Q 100 = 拠点A・親 shape 400k)、Gi3.200 (dot1Q 200 = 拠点B・親 shape 300k) がそれぞれ独立した契約帯域を持ち、その中で子 CBWFQ/LLQ がクラス優先する。PC1 が両拠点宛に VOICE+DATA を並行送出し、PC2 が 2 拠点別に実測する。

まず使用した機器と IOS-XE を確認します。

snippet
R1# show version | include Cisco IOS-XE Software|CSR|Version
Cisco IOS XE Software, Version 17.03.08a
Cisco IOS Software [Amsterdam], Virtual XE Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Version 17.3.8a, RELEASE SOFTWARE (fc3)
cisco CSR1000V (VXE) processor (revision VXE) with 1104920K/3075K bytes of memory.

機種は csr1000v (仮想の CSR 1000V ルータ)、ソフトウェアは 5-6 と同じ IOS-XE 17.03.08a です。この csr1000v はデモ用にスループットの上限が 1000 kb/s に絞られています。

snippet
R1# show platform hardware throughput level
The current throughput level is 1000 kb/s

天井が 1 Mbps であるため、本節で送る 2 拠点合計 1 Mbps 弱のトラフィックでは、親 shaper を当てない限り物理 IF では輻輳しません。輻輳は各サブインタフェースの親 shaper (400k / 300k) で人為的に作ります。

物理 Gi3 を dot1q トランクにし、2 つのサブインタフェースを新設した結果、拠点 A・拠点 B の網が connected として現れます。

snippet
R1# show ip route connected
      192.168.10.0/24 is variably subnetted, 2 subnets, 2 masks
C        192.168.10.0/24 is directly connected, GigabitEthernet2
L        192.168.10.1/32 is directly connected, GigabitEthernet2
      192.168.100.0/24 is variably subnetted, 2 subnets, 2 masks
C        192.168.100.0/24 is directly connected, GigabitEthernet3.100
L        192.168.100.1/32 is directly connected, GigabitEthernet3.100
      192.168.200.0/24 is variably subnetted, 2 subnets, 2 masks
C        192.168.200.0/24 is directly connected, GigabitEthernet3.200
L        192.168.200.1/32 is directly connected, GigabitEthernet3.200

拠点 A の網 192.168.100.0/24 が Gi3.100、拠点 B の網 192.168.200.0/24 が Gi3.200 に directly connected です。PC1 (192.168.10.10) から両拠点の受信端まで L3 で到達できることを確認します。

snippet
# PC1→拠点A(192.168.100.20) L3 疎通
PING 192.168.100.20 (192.168.100.20): 56 data bytes
64 bytes from 192.168.100.20: seq=0 ttl=42 time=1.062 ms
--- 192.168.100.20 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
# PC1→拠点B(192.168.200.20) L3 疎通
PING 192.168.200.20 (192.168.200.20): 56 data bytes
64 bytes from 192.168.200.20: seq=0 ttl=42 time=0.970 ms
--- 192.168.200.20 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss

両拠点とも 0% packet loss で到達しています。2 拠点のトラフィックは、5-4 で作った class-map をそのまま流用して分類します。VOICE は DSCP EF、DATA は DSCP AF11 で分類する定義は、両拠点で共通です。

snippet
R1# show class-map
 Class Map match-any class-default (id 0)
   Match any

 Class Map match-any CM-DATA (id 2)
   Match   dscp af11 (10)

 Class Map match-any CM-VOICE (id 1)
   Match   dscp ef (46)

CM-VOICEmatch dscp ef (EF = 46)、CM-DATAmatch dscp af11 (AF11 = 10) です。この 2 クラスを両拠点で共通に使い、各拠点の親 shaper の中で拠点ごとに独立して並べ替えます。

4. サブレート分離 — 拠点 A の過負荷が拠点 B に波及しない

HQoS の核が サブレート分離 です。各サブインタフェースに独立した親 shaper を当てると、ある拠点が契約帯域を超えて過負荷になっても、その輻輳が他の拠点に波及しません。物理は共通の 1 Gbps ですが、契約帯域はサブインタフェースの親 shaper で拠点ごとに独立します。

これを確かめるため、各サブインタフェースに親 shaper だけを当てます。子ポリシーは付けず、各サブレートを FIFO の単一キューにします。拠点 A は shape average 400000、拠点 B は shape average 300000 です。

snippet
R1# show run policy-map PM-PARENT-A
policy-map PM-PARENT-A
 class class-default
  shape average 400000
!
R1# show run policy-map PM-PARENT-B
policy-map PM-PARENT-B
 class class-default
  shape average 300000

この状態で、拠点 A を過負荷 (VOICE 300k + DATA 400k = 700k で契約 400k を超える)、拠点 B を契約内 (VOICE 150k + DATA 100k = 250k で契約 300k に収まる) にして、2 拠点を並行送出します。拠点 A だけが契約帯域を超え、拠点 B は契約帯域に収まる状態です。

snippet
## 拠点A VOICE (dscp ef, port 5001) 受信 PC2 iperf レポート
[  1] 0.00-12.05 sec   187 KBytes   127 Kbits/sec  19.321 ms 132/262 (50%)
## 拠点A DATA (dscp af11, port 5002) 受信 PC2 iperf レポート
[  1] 0.00-11.99 sec   388 KBytes   265 Kbits/sec   8.753 ms 74/344 (22%)
## 拠点B VOICE (dscp ef, port 6001) 受信 PC2 iperf レポート
[  1] 0.00-10.11 sec   188 KBytes   152 Kbits/sec   0.071 ms 0/131 (0%)
## 拠点B DATA (dscp af11, port 6002) 受信 PC2 iperf レポート
[  1] 0.00-10.23 sec   128 KBytes   102 Kbits/sec   0.082 ms 0/89 (0%)

結果は 2 拠点で対照的です。過負荷の拠点 A は、VOICE が 127 Kbits/sec・loss 50%・jitter 19.321 ms、DATA が 265 Kbits/sec・loss 22% で、契約帯域 400k を超えた分が大量に落ちています。一方の 契約内の拠点 B は、VOICE が 152 Kbits/sec・loss 0%・jitter 0.071 ms、DATA が 102 Kbits/sec・loss 0% で、送出したレートがそのまま素通りしています。拠点 A の jitter 19.321 ms は拠点 B の 0.071 ms の約 270 倍で、遅延のばらつきに 2 桁以上の差がついています。

この独立性を、各サブインタフェースの親 shaper のカウンタで確認します。まず過負荷の拠点 A です。

snippet
R1# show policy-map interface GigabitEthernet3.100
 GigabitEthernet3.100

  Service-policy output: PM-PARENT-A

    Class-map: class-default (match-any)
      992 packets, 1495988 bytes
      5 minute offered rate 10000 bps, drop rate 2000 bps
      Match: any
      Queueing
      queue limit 64 packets
      (queue depth/total drops/no-buffer drops) 7/522/0
      (pkts output/bytes output) 470/704636
      shape (average) cir 400000, bc 1600, be 1600
      target shape rate 400000

拠点 A の (queue depth/total drops/no-buffer drops) 7/522/0 が、契約帯域を超えて輻輳が起きた証拠です。total drops が 522 で、shape (average) cir 400000 の契約帯域に入りきらなかった 522 パケットが落ちています。次に契約内の拠点 B です。

snippet
R1# show policy-map interface GigabitEthernet3.200
 GigabitEthernet3.200

  Service-policy output: PM-PARENT-B

    Class-map: class-default (match-any)
      220 packets, 333520 bytes
      5 minute offered rate 4000 bps, drop rate 0000 bps
      Match: any
      Queueing
      queue limit 64 packets
      (queue depth/total drops/no-buffer drops) 0/0/0
      (pkts output/bytes output) 220/333520
      shape (average) cir 300000, bc 1200, be 1200
      target shape rate 300000

拠点 B は (queue depth/total drops/no-buffer drops) 0/0/0 で、total drops が 0 です。drop rate 0000 bps のとおり 1 パケットも落ちていません。過負荷の拠点 A が 522 パケットを落とす裏で、契約内の拠点 B は 1 パケットも落とさずに全て素通りしています。これがサブレート分離です。2 つのサブインタフェースの親 shaper が独立して各拠点の契約帯域を守るため、拠点 A の輻輳が拠点 B に一切波及しません。

サブレート分離。物理 Gi3(1G) の中に拠点A(shape 400k)と拠点B(shape 300k)の 2 つのバケツが並ぶ。拠点A は過負荷(700k>400k)でバケツから溢れて drop する(total drops 522・loss 50%)が、拠点B は契約内(250k<300k)なので独立に守られ全て素通りする(total drops 0・loss 0%)。バケツが互いに独立だから、片方が溢れても他方に影響しない。

物理 IF 直付けの 1 段 (5-6) では、この分離を表現できません。物理 IF に 1 つの親 shaper を置くと、そこを通る全トラフィックが 1 本のボトルネックを共有するため、ある拠点の過負荷が同じ shaper を通る他拠点を巻き込みます。サブインタフェースごとに独立した親 shaper を置く HQoS で初めて、拠点別の契約帯域と拠点間の独立性が両立します。

5. サブレート内のクラス制御 (1) CBWFQ

サブレート分離は「拠点ごとに契約帯域を守る」親 shaper の役割でした。ここから、その契約帯域の中でさらにクラス別の QoS をかけます。まず CBWFQ (Class-Based Weighted Fair Queuing) で、各拠点の契約帯域の中を、クラス別の bandwidth で配分します。

各サブインタフェースの親 shaper の class-default に、子ポリシーを service-policy でぶら下げます。拠点 A の子ポリシーは VOICE に bandwidth 200、DATA に bandwidth 100 を割り当てます。拠点 B は同型で VOICE に bandwidth 150、DATA に bandwidth 75 を割り当てます。

snippet
R1# show run policy-map PM-CHILD-A-CBWFQ
policy-map PM-CHILD-A-CBWFQ
 class CM-VOICE
  bandwidth 200
 class CM-DATA
  bandwidth 100
 class class-default
  fair-queue
!
R1# show run policy-map PM-CHILD-B-CBWFQ
policy-map PM-CHILD-B-CBWFQ
 class CM-VOICE
  bandwidth 150
 class CM-DATA
  bandwidth 75
 class class-default
  fair-queue

この配分を、拠点 A の階層表示のカウンタで確認します。親 shaper (PM-PARENT-A) の配下に子ポリシー (PM-CHILD-A-CBWFQ) が入れ子で表示されます。

snippet
R1# show policy-map interface GigabitEthernet3.100
 GigabitEthernet3.100

  Service-policy output: PM-PARENT-A

    Class-map: class-default (match-any)
      920 packets, 1392092 bytes
      5 minute offered rate 12000 bps, drop rate 0000 bps
      Match: any
      Queueing
      queue limit 64 packets
      (queue depth/total drops/no-buffer drops) 0/387/0
      (pkts output/bytes output) 533/805400
      shape (average) cir 400000, bc 1600, be 1600
      target shape rate 400000

      Service-policy : PM-CHILD-A-CBWFQ

        Class-map: CM-VOICE (match-any)
          459 packets, 695844 bytes
          5 minute offered rate 6000 bps, drop rate 0000 bps
          Match:  dscp ef (46)
          Queueing
          queue limit 64 packets
          (queue depth/total drops/no-buffer drops) 0/143/0
          (pkts output/bytes output) 316/479056
          bandwidth 200 kbps

        Class-map: CM-DATA (match-any)
          459 packets, 695844 bytes
          5 minute offered rate 6000 bps, drop rate 1000 bps
          Match:  dscp af11 (10)
          Queueing
          queue limit 64 packets
          (queue depth/total drops/no-buffer drops) 21/244/0
          (pkts output/bytes output) 215/325940
          bandwidth 100 kbps

拠点 A の親 shaper shape (average) cir 400000 の中に、子の 2 クラスが入れ子で表示されています。CM-VOICEbandwidth 200 kbps・total drops 143、CM-DATAbandwidth 100 kbps・total drops 244 です。bandwidth 比 200:100 = 2:1 に対し、drops は VOICE 143 に対し DATA 244 と、保証帯域の少ない DATA のほうが多く落ちています。サブレート契約帯域 400k の中を、さらにクラス別の bandwidth で配分できています。同じ子 CBWFQ が拠点 B (bandwidth 150:75) でも独立に動きます。

6. サブレート内のクラス制御 (2) LLQ

CBWFQ が守るのは帯域でした。5-6 と同じく、遅延を守るには LLQ (Low Latency Queuing) を使います。各サブインタフェースの契約帯域の中で、音声を priority キューに入れ、他クラスを追い越して即送出します。拠点 A の子ポリシーは VOICE を priority 150、DATA を bandwidth 150 にします。拠点 B は VOICE を priority 100、DATA を bandwidth 100 にします。

snippet
R1# show run policy-map PM-CHILD-A-LLQ
policy-map PM-CHILD-A-LLQ
 class CM-VOICE
  priority 150
 class CM-DATA
  bandwidth 150
 class class-default
  fair-queue
!
R1# show run policy-map PM-CHILD-B-LLQ
policy-map PM-CHILD-B-LLQ
 class CM-VOICE
  priority 100
 class CM-DATA
  bandwidth 100
 class class-default
  fair-queue

拠点 A で VOICE 200k と DATA 300k を並行送出し、拠点 B で VOICE 150k と DATA 200k を並行送出したときの受信レートと jitter を見ます。

snippet
## 拠点A VOICE (dscp ef, port 5001) 受信 PC2 iperf レポート
[  1] 0.00-10.11 sec   185 KBytes   150 Kbits/sec   0.064 ms 45/174 (26%)
## 拠点A DATA (dscp af11, port 5002) 受信 PC2 iperf レポート
[  1] 0.00-11.65 sec   372 KBytes   261 Kbits/sec  14.853 ms 0/259 (0%)
## 拠点B VOICE (dscp ef, port 6001) 受信 PC2 iperf レポート
[  1] 0.00-10.11 sec   125 KBytes   101 Kbits/sec   0.070 ms 44/131 (34%)
## 拠点B DATA (dscp af11, port 6002) 受信 PC2 iperf レポート
[  1] 0.00-10.42 sec   250 KBytes   196 Kbits/sec  18.669 ms 0/174 (0%)

拠点 A の VOICE は jitter 0.064 ms で、同じ拠点 A の DATA の jitter 14.853 ms の約 230 分の 1 です。priority キューで DATA を追い越して即送出するため、遅延のばらつきが桁違いに小さくなっています。拠点 B の VOICE も jitter 0.070 ms で、同じく低遅延です。各拠点の契約帯域の中で、音声が独立して低遅延で送られています。カウンタで priority キューの動作を確認します。

snippet
R1# show policy-map interface GigabitEthernet3.100
 GigabitEthernet3.100

  Service-policy output: PM-PARENT-A

    Class-map: class-default (match-any)
      327 packets, 495732 bytes
      5 minute offered rate 14000 bps, drop rate 0000 bps
      Match: any
      Queueing
      queue limit 64 packets
      (queue depth/total drops/no-buffer drops) 0/33/0
      (pkts output/bytes output) 294/445704
      shape (average) cir 400000, bc 1600, be 1600
      target shape rate 400000

      Service-policy : PM-CHILD-A-LLQ

        queue stats for all priority classes:
          Queueing
          queue limit 512 packets
          (queue depth/total drops/no-buffer drops) 0/33/0
          (pkts output/bytes output) 98/148568

        Class-map: CM-VOICE (match-any)
          131 packets, 198596 bytes
          5 minute offered rate 6000 bps, drop rate 2000 bps
          Match:  dscp ef (46)
          Priority: 150 kbps, burst bytes 3750, b/w exceed drops: 33

        Class-map: CM-DATA (match-any)
          196 packets, 297136 bytes
          5 minute offered rate 8000 bps, drop rate 0000 bps
          Match:  dscp af11 (10)
          Queueing
          queue limit 64 packets
          (queue depth/total drops/no-buffer drops) 39/0/0
          (pkts output/bytes output) 196/297136
          bandwidth 150 kbps

queue stats for all priority classes の行が、優先クラス専用のキューです。その CM-VOICE の行に Priority: 150 kbps, burst bytes 3750, b/w exceed drops: 33 とあります。5-6 で確認したとおり、priority に設定したレートは上限としても働き、priority 150 kbps を超えた 33 パケットが b/w exceed drops で捨てられています。サブレート契約帯域の中に置いた priority キューでも、設定 rate を超える音声は輻輳時に落ちます。優先クラスはサブレート内でも無制限レーンではありません。拠点 B も同型で、Priority: 100 kbps の priority キューに b/w exceed drops: 46 が現れます。

ここまでで、HQoS の 2 段が実機で揃いました。親 shaper がサブレート契約帯域という帯域の天井を作り、その中で子ポリシーがクラスを優先する、という 2 段の入れ子です。

階層 QoS の 2 段。親 policy(shape average 400k)がサブレート契約帯域=帯域の天井として全体を囲い、その中に子 policy(LLQ/CBWFQ)がネストする。子 LLQ が VOICE を priority で追い越して即送出(jitter 0.064ms)し、DATA は bandwidth で後回し(jitter 14.853ms)にする。物理IF→サブIF契約→クラス の論理階層を、親 shape + 子 queuing の 2 段で捌く。

7. 階層は何段まで組めるか

HQoS の「階層」という言葉から、policy を何段でも入れ子にできるように見えます。Cisco の QoS 階層設計ドキュメントは、多くのプラットフォームでスケジューラの階層を 2 レベル (親 shape + 子 queuing) までとし、3 レベル以上のネストは IOS-XR 系のプラットフォームで扱う、と記します。この一般記述だけを見ると、csr1000v では 3 レベルの階層 policy が組めないように読めます。

本検証では、この一般記述を鵜呑みにせず、csr1000v 17.03 に 3 レベルの階層 policy を実際に投入して挙動を確認しました。PM-GRAND-A (shape 500k) の中に PM-MID-A (shape 400k) をネストし、さらにその中に PM-CHILD-A-LLQ (priority / bandwidth) をネストする構成を Gi3.100 にバインドしました。上 2 段は shape average を持つ shaper、最下段はクラス別の queuing (LLQ / CBWFQ) で、shape 動作そのものは 2 段です。

snippet
R1(config)# policy-map PM-MID-A
R1(config-pmap)#  class class-default
R1(config-pmap-c)#   shape average 400000
R1(config-pmap-c)#    service-policy PM-CHILD-A-LLQ
R1(config)# policy-map PM-GRAND-A
R1(config-pmap)#  class class-default
R1(config-pmap-c)#   shape average 500000
R1(config-pmap-c)#    service-policy PM-MID-A
R1(config)# interface GigabitEthernet3.100
R1(config-subif)#  service-policy output PM-GRAND-A

csr1000v 17.03 はこの 3 段構成を拒否メッセージなしで受理し、show policy-map interface でも 3 段の階層を表示しました。GRAND (shape 500k) → MID (shape 400k) → CHILD (priority / bandwidth) の 3 段が入れ子で現れます。

snippet
R1# show policy-map interface GigabitEthernet3.100
 GigabitEthernet3.100

  Service-policy output: PM-GRAND-A

    Class-map: class-default (match-any)
      shape (average) cir 500000, bc 2000, be 2000
      target shape rate 500000

      Service-policy : PM-MID-A

        Class-map: class-default (match-any)
          shape (average) cir 400000, bc 1600, be 1600
          target shape rate 400000

          Service-policy : PM-CHILD-A-LLQ

            queue stats for all priority classes:

            Class-map: CM-VOICE (match-any)
              Match:  dscp ef (46)
              Priority: 150 kbps, burst bytes 3750, b/w exceed drops: 0

            Class-map: CM-DATA (match-any)
              Match:  dscp af11 (10)
              bandwidth 150 kbps

PM-GRAND-A (shape 500000) → PM-MID-A (shape 400000) → PM-CHILD-A-LLQ の 3 段が表示されています。したがって、本節は「csr1000v は 2 レベルまで」とは書きません。実機は 3 段を受理・表示しました。この 3 段のすべてが rate 制御を厳密に効かせるかは、トラフィックを投入した実測を別途行わないと確定できないため、本検証では config の受理と show の表示までを事実として記録します。

一方で、実務の HQoS がこの 3 段目を必要とするかは別の話です。本節で見てきたとおり、「拠点ごとにサブレート契約帯域を守る」目的は親 shaper 1 段で果たせ、「その契約帯域の中でクラス優先する」目的は子 CBWFQ / LLQ 1 段で果たせます。親 shape (サブレート契約) + 子 queuing (クラス制御) の 2 段が、HQoS の目的を過不足なく満たす基本形です。段数を増やせること自体と、目的のために増やす必要があることは、分けて扱います。

8. 掲載用 config 全体

本節で組んだ HQoS の定義を running-config から抜き出すと次のようになります。物理 Gi3 のサブインタフェース、親 shaper (サブレート契約)、子ポリシー (クラス制御) が、記事で見てきた形でまとまっています。

snippet
R1# show running-config | section interface GigabitEthernet3|class-map CM-|policy-map PM-
policy-map PM-CHILD-A-LLQ
 class CM-VOICE
  priority 150
 class CM-DATA
  bandwidth 150
policy-map PM-CHILD-B-LLQ
 class CM-VOICE
  priority 100
 class CM-DATA
  bandwidth 100
policy-map PM-PARENT-B
 class class-default
  shape average 300000
   service-policy PM-CHILD-B-LLQ
policy-map PM-PARENT-A
 class class-default
  shape average 400000
   service-policy PM-CHILD-A-LLQ
interface GigabitEthernet3
 description WAN trunk (physical 1G) - HQoS sub-rate subinterfaces below
 no ip address
 negotiation auto
 no mop enabled
 no mop sysid
interface GigabitEthernet3.100
 description Site-A WAN sub-rate (dot1Q 100 = parent shape apply point)
 encapsulation dot1Q 100
 ip address 192.168.100.1 255.255.255.0
 service-policy output PM-PARENT-A
interface GigabitEthernet3.200
 description Site-B WAN sub-rate (dot1Q 200 = parent shape apply point)
 encapsulation dot1Q 200
 ip address 192.168.200.1 255.255.255.0
 service-policy output PM-PARENT-B

物理 Gi3 は no ip address のトランクで、その下に Gi3.100 (拠点A) と Gi3.200 (拠点B) がそれぞれ IP と親 shaper (service-policy output PM-PARENT-A / PM-PARENT-B) を持ちます。各親 shaper の class-default に、子ポリシー (PM-CHILD-A-LLQ / PM-CHILD-B-LLQ) が service-policy でネストされ、2 段の HQoS が完成しています。

9. 落とし穴・補足

HQoS は、サブインタフェースの親子構造やサブレートの絞り方を取り違えると、拠点別の帯域が守れなかったり、子ポリシーが効かなかったりします。本節の実機に関わる注意点をまとめます。

サブインタフェースの queuing は親 shaper が必須です。 サブインタフェース自体には固有の輻輳点がないため、親に shaper を置いて契約帯域を作らないと、子の CBWFQ / LLQ が発火しません (§2)。5-6 で確認した「キューイングは輻輳時のみ発火する」性質は、サブインタフェースでも変わりません。各サブインタフェースの親には shape average で契約帯域を作り、その class-default に子ポリシーを service-policy でネストします。

親 shaper がサブレート分離を担います。 サブインタフェースごとに独立した親 shaper を置くことが、拠点別の契約帯域と拠点間の独立性を生みます (§4)。物理 IF に 1 つの親 shaper を置く 1 段構成では、全トラフィックが同じボトルネックを共有するため、ある拠点の過負荷が他拠点を巻き込みます。拠点ごとに独立した契約帯域を守るには、サブインタフェースごとの親 shaper が必要です。

帯域は数値で明示します(ただし単位はコマンドで異なります)。 本節では shape average 400000bandwidth 200priority 150 のように帯域を数値で明示しました。ここで単位が揃っていない点に注意します。shape average の数値は bps 指定で、shape average 400000 は 400,000 bps = 400 kbps です。一方 bandwidthpriority の通常の数値指定は kbps 指定で、bandwidth 200 は 200 kbps、priority 150 は 150 kbps です。同じ「400000」と「200」でも桁が 3 桁ずれるのは、コマンドごとに単位が違うためです。percent も使えますが、percent が何の帯域に対する割合になるかは構成に依存します。本節のような親 shaper + 子 queuing の構成では、子ポリシーの percent は親 shaper の rate を基準に解釈されるのが一般的ですが、platform や bandwidth qos-reference の設定によって基準が変わる場合があります。サブレート契約帯域の内側に子を収める意図を明確にするには、割合ではなく kbps で直接指定するのが確実です。

HQoS は出口方向のみに当てます。 キューイングは出力キューを使う仕組みなので、service-policy output の出口方向にしか当てられません (5-6 §8)。本節も各サブインタフェースの output に親 shaper を当てています。入口方向のサブインタフェースにキューイングポリシーを当てることはできません。

priority はサブレート内でも無制限ではありません。 §6 で確認したとおり、サブレート契約帯域の中に置いた priority キューでも、設定した rate を超えた音声は b/w exceed drops で捨てられます。本節では priority 150 に対し VOICE 200k を送ったため、150 kbps を超えた分が輻輳時に落ちました。priority の rate は、各拠点で流す音声の帯域に見合った値に設定します。

仮想機のカウンタと実測レートの扱いです。 この csr1000v では、サブインタフェースごとの親 shaper によるサブレート分離も、子 CBWFQ の bandwidth 比配分も、子 LLQ の低遅延も実機の数値として観測できました。とはいえ効き目の正本は、5-6 と同じく受信側 PC2 の実測レート・loss・jitter に置きます。仮想機は QoS のデータプレーンを完全にはエミュレートしないことがあるため、show のカウンタは補助として扱うのが安全です。

10. 次節

本節では、1 本の物理 WAN を dot1q サブインタフェースで 2 拠点の独立したサブレート契約帯域に分け、各サブレートの中でさらにクラス優先する階層 QoS (HQoS) を csr1000v の実機で組みました。核はサブレート分離で、拠点 A を過負荷 (700k)、拠点 B を契約内 (250k) にして並行送出したとき、拠点 A が total drops 522・loss 50%・jitter 19.321 ms で絞られる裏で、拠点 B は total drops 0・loss 0%・jitter 0.071 ms で完全に独立に守られることを実測しました。各拠点の契約帯域の中では、5-6 と同じく子 CBWFQ が bandwidth 比でクラス別に帯域を配分し (VOICE drops 143 < DATA drops 244)、子 LLQ が priority で音声を低遅延にする (VOICE jitter 0.064 ms・DATA jitter 14.853 ms) ことを確かめました。実務の HQoS は親 shape (サブレート契約) + 子 queuing (クラス制御) の 2 段で目的を果たし、csr1000v は 3 レベルの階層 policy (shape を 2 段重ねた上に子 queuing) も受理・表示することを、実機に忠実に記録しました。

ここまで 5-5 から 5-7 で扱ってきた policing・shaping・queuing・HQoS は、いずれも輻輳が起きたときに「どのパケットを捨て、どれを待たせ、どれを先に送るか」を制御する仕組みでした。キューが満杯になったとき、末尾に来たパケットを一律に捨てる動作を Tail Drop と呼びます。Tail Drop は複数の TCP フローを同時に落とし、それらが一斉に再送を絞って再び一斉に増やす同期現象を引き起こします。次節 5-8 では、キューが満杯になる前に確率的にパケットを落として同期を避ける輻輳回避 (Congestion Avoidance) を主題に、RED (Random Early Detection) と WRED (Weighted RED) を実機で見ていきましょう。