STUDY · NETWORK GUIDE

5-10 ハンズオン: 音声優先化 — 信頼境界と LLQ の通し検証

端末から出た音声をアクセス端で EF にマーキングし、WAN 出口の LLQ で守るところまでを Catalyst 9000v (IOS-XE 17.15.03) と csr1000v (17.03.08a) の直列ラボで通す再現手順。同じトラフィックのまま構成だけを 4 通りに変え、①素の輻輳 ②マーキングのみ ③LLQ のみ ④マーキング + LLQ を受信側の損失とジッタで対比する。②は印が完全に入れ替わっても損失が 1 割から 2 割の水準にとどまり、③は信頼境界が無いために優先枠を EF を詐称したアプリが占拠する。音声が無損失になるのは④だけで、受信側は 0/1003 (0%)・ジッタ 7.425 ms。優先クラスに入ったトラフィックの正体はパケット長 (554 バイト = 詐称アプリ / 84 バイト = 音声) から読める。割当を IP 層で計算すると守るはずの音声だけがポリサで落ちることも実測する。

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

前節 5-9 LAN QoS / WAN QoS 設計 では、QoS 設計が「どこまで信じるか・何をどの印にするか・どの速度に絞るか・絞った中をどう分けるか」の 4 つの決定でできていることを扱いました。実測の核は帯域配分のトレードオフで、音声に 10 % (50 kbps) しか与えない構成では守るはずの EF が 79 % 失われました。守る対象は選べても、守る総量は増やせません。

5-9 の検証ラボは、LAN セグメントと WAN セグメントを同じラボに置きながら相互に接続していませんでした。設計者が LAN 側で何を決め、WAN 側で何を決めるかを独立に観察するための構成です。本節はこの 2 つを 1 本に繋ぎ、端末から出たトラフィックがアクセススイッチを通って WAN 出口から出ていくまでを、1 つの経路として扱います。

本節の主題は 2 つあります。1 つはアクセス端に置く信頼境界で、端末が付けてきた印を採るか捨てるかを決める場所です。もう 1 つは WAN 出口の LLQ (Low Latency Queuing) で、絞った帯域から優先枠を音声に割り当てる仕組みです。この 2 つは片方だけでは成立しません。 それを、同じトラフィックのまま構成を 4 通りに変えて実測します。

本節は Cisco Modeling Labs (CML) で再現できる順序で構成しています。トポロジと day0 の投入から始め、素通しの状態で端末が何を名乗るかを観測し、そこへ①契約帯域への絞り込み、②アクセス端の信頼境界、③WAN 出口の LLQ、④その両方を順に足していきます。本検証の絶対値は実務値ではなく、経路の実効天井から逆算した縮尺モデルです (§9・§11)。

2. 何を作るか — 完成形と 3 つの観測点

作るのは、端末 2 台・アクセススイッチ 1 台・WAN エッジルータ 1 台・対向端末 1 台を直列に繋いだ経路です。PC1 は IP 電話に相当し、印を付けずに音声を出します。PC2 は一般の PC に相当し、自分で EF を名乗る自称優先アプリと、印を付けない素の業務データの 2 本を出します。

この図を大きく開く ↗

検証ラボの直列構成と 3 つの観測点。左の PC1 (IP 電話に相当) と PC2 (一般 PC) はどちらも SW1 (cat9000v-uadp) の VLAN 10 アクセスポートに収容され、SW1 Gi1/0/3 から R1 (csr1000v) Gi2 へ 1 本で上がり、R1 Gi3 が WAN 出口として PC3 へ抜ける。観測点①は SW1 の入口で、端末が名乗った印を採るか捨てるかを決める場所。観測点②は R1 Gi3 で、契約帯域へ絞った中をどのクラスへ落とすかを決める場所。観測点③は受信側 PC3 で、tcpdump の tos が実際に届いた印を、iperf サーバの損失とジッタが守れたかどうかを示す。SW1 は SVI を持たない純 L2 で、PC1 と PC2 のデフォルトゲートウェイは R1 Gi2。管理はどちらも Mgmt-vrf 経由。

観測点は 3 つです。観測点①は SW1 の入口で、端末が名乗った印を採るか捨てるかを決める場所。観測点②は R1 の WAN 出口 Gi3 で、契約帯域へ絞った中をどのクラスへ落とすかを決める場所。観測点③は受信側の PC3 で、tcpdump の tos と iperf サーバの損失・ジッタを読む場所です。

送出は 4 状態を通じて 1 度も変えません。変えるのは構成だけです。

#状態SW1 の信頼境界R1 Gi3 の構成見るもの
素の輻輳なし親 shape のみ印が誰にも読まれない状態
マーキングのみあり親 shape のみ印が入れ替わっても変わらない結果
LLQ のみなし親 shape + LLQ優先枠を誰が取るか
マーキング + LLQあり親 shape + LLQ何が守られ、誰が代償を払うか

①から②への差が「印だけでは足りない」ことを、①から③への差が「優先制御だけでは足りない」ことを示します。④はその両方を揃えた形です。

3. 準備 — トポロジと day0

CML のノードは cat9000v-uadp 1 台、csr1000v 1 台、Alpine Linux の端末 3 台、外部接続用の System Bridge 2 つです。アドレスは LAN 側が 192.168.10.0/24、WAN 側が 192.168.20.0/24 です。

SW1 は SVI を持たない純 L2 として構成します。Gi1/0/1・Gi1/0/2・Gi1/0/3 の 3 ポートをすべて VLAN 10 のアクセスポートにし、L3 は一切持たせません。アクセススイッチが信頼境界であるという役割を、設定の上でも純化するためです。

snippet
hostname SW1
vlan 10
 name LAB-VOICE-DATA
!
vrf definition Mgmt-vrf
 address-family ipv4
 exit-address-family
!
interface GigabitEthernet0/0
 description Management to lab gateway
 vrf forwarding Mgmt-vrf
 ip address 172.16.1.211 255.255.255.0
 no shutdown
!
interface GigabitEthernet1/0/1
 description PC1 (IP phone) - trust boundary apply point
 switchport mode access
 switchport access vlan 10
 spanning-tree portfast
 no shutdown
!
interface GigabitEthernet1/0/2
 description PC2 (untrusted PC) - trust boundary apply point
 switchport mode access
 switchport access vlan 10
 spanning-tree portfast
 no shutdown
!
interface GigabitEthernet1/0/3
 description Uplink to R1 Gi2 (WAN edge)
 switchport mode access
 switchport access vlan 10
 spanning-tree portfast
 no shutdown

R1 は Gi2 が LAN 側、Gi3 が WAN 側です。Gi3 が契約帯域への絞り込みと優先制御の適用点になります。

snippet
hostname R1
vrf definition Mgmt-vrf
 address-family ipv4
 exit-address-family
!
interface GigabitEthernet1
 description Management
 vrf forwarding Mgmt-vrf
 ip address 172.16.1.221 255.255.255.0
 no shutdown
interface GigabitEthernet2
 description to SW1 Gi1/0/3 (LAN side / ingress)
 ip address 192.168.10.1 255.255.255.0
 no shutdown
interface GigabitEthernet3
 description to PC3 (WAN side = sub-rate shaper + LLQ apply point / egress)
 ip address 192.168.20.1 255.255.255.0
 no shutdown
ip routing

端末は 3 台とも Alpine Linux です。PC1 と PC2 のデフォルトゲートウェイは R1 Gi2、PC3 は R1 Gi3 になります。

snippet
# PC1
ip addr add 192.168.10.10/24 dev eth0
ip route add default via 192.168.10.1
# PC2
ip addr add 192.168.10.11/24 dev eth0
ip route add default via 192.168.10.1
# PC3
ip addr add 192.168.20.20/24 dev eth0
ip route add default via 192.168.20.1

投入後に L3 疎通を確認します。SW1 を L2 で通り、R1 でルーティングされて PC3 に届くことが前提です。

snippet
PC1 $ ping -c 3 -W 2 192.168.20.20
PING 192.168.20.20 (192.168.20.20): 56 data bytes
64 bytes from 192.168.20.20: seq=0 ttl=42 time=25.045 ms
64 bytes from 192.168.20.20: seq=1 ttl=42 time=19.914 ms
64 bytes from 192.168.20.20: seq=2 ttl=42 time=42.122 ms

--- 192.168.20.20 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 19.914/29.027/42.122 ms

使用した機器と IOS-XE は次のとおりです。R1 の csr1000v は 5-6 から 5-9 で使ったものと同じです。

snippet
SW1# show version | include Cisco IOS-XE Software|C9KV|Version
Cisco IOS XE Software, Version 17.15.03
Cisco IOS Software [IOSXE], Catalyst L3 Switch Software (CAT9K_IOSXE), Version 17.15.3, RELEASE SOFTWARE (fc1)
(GPL ライセンス表記の 3 行を省略)
cisco C9KV-UADP-8P (VXE) processor (revision VXE) with 743842K/3075K bytes of memory.
Switch Ports Model              SW Version        SW Image              Mode   
*    1 24    C9KV-UADP-8P       17.15.03          CAT9K_IOSXE           INSTALL
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)
(GPL ライセンス表記の 3 行を省略)
cisco CSR1000V (VXE) processor (revision VXE) with 1104920K/3075K bytes of memory.

端末側の計測ツールは iperf 2 系のみで、iperf3 は入っていません。tcpdumpsudo 付きで使えます。

snippet
PC1 $ iperf --version
iperf version 2.2.0 (10 April 2024) pthreads
PC1 $ sudo tcpdump --version
tcpdump version 4.99.5
libpcap version 1.10.5 (with TPACKET_V3)

流すトラフィックは 4 状態を通じて共通です。受信側の PC3 で 3 つのポートに iperf サーバを立て、送信側の 2 台から 3 本を同時に起動します。サーバには -i 1 を付けます。 輻輳下では最終サマリ行が出ないことがあり、interval 行が読めないと受信量を追えなくなるためです (§11)。

snippet
PC3 $ nohup iperf -s -u -p 5001 -i 1 >/tmp/s5001.log 2>&1 &   (5002 / 5003 も同様)
PC1 $ iperf -c 192.168.20.20 -u -b 11200 -l 42  -t 30 -p 5001 &            (音声)
PC2 $ iperf -c 192.168.20.20 -u -b 30400 -l 512 -S 0xb8 -t 30 -p 5002 &    (自称優先アプリ)
PC2 $ iperf -c 192.168.20.20 -u -b 44600 -l 512 -t 30 -p 5003 &            (素の業務データ)

3 本の帯域は L2 ヘッダ込みで 22.4・32.9・48.3 kbps、合計 103.6 kbps です。契約帯域を 85 kbps に置くので、どの状態でも 122 % の輻輳が続きます。-S 0xb8 は自称優先アプリが EF を詐称するための指定で、ToS バイトは上位 6 ビットが DSCP、下位 2 ビットが ECN で、値は (DSCP << 2) | ECN です。本検証は ECN を使わないので 46 << 2 = 184 = 0xb8 になります。

音声フローの中身は RTP そのものではありません。 -l 42 は RTP の固定ヘッダ 12 バイトと G.729 の 30 ms 分 30 バイトを足した長さに合わせた UDP ペイロードで、実際に RTP ヘッダが入っているわけではありません。本検証が見るのはパケット長と送出間隔がスケジューラにどう扱われるかなので、中身が RTP である必要はありません。

4. 端末が名乗る印は自己申告にすぎない

QoS の一次資料は、印を付ける場所と端末の扱いについて 2 つの原則を示しています。

“Based on design recommendations, classification and marking should be done closest to the source of traffic as administratively and technically possible.”

“As a rule, it is not recommended to trust markings set by end users leveraging PCs or other endpoint devices.”

— Cisco Press, QoS Design Principles and Best Practices — Classification and Marking Design Principles (出典)

前半は「発生源にできるだけ近い場所で分類とマーキングを行う」、後半は「PC などの端末が設定した印を信頼することは推奨されない」を意味します。この 2 文は同時に成り立ちます。 発生源に近い場所とは端末そのものではなく、端末を収容するアクセススイッチです。

この図を大きく開く ↗

端末が名乗った印が、アクセス端で正され、WAN 出口では印だけを見て振り分けられるまでの通し。①PC1 は印を付けずに音声を出し、PC2 は EF を詐称したアプリと素の業務データを出す。この時点の印は端末の自己申告にすぎない。②SW1 は特定のポートを特別扱いするのではなく、同じ規律を全ポートに当てる。分類条件に一致したものだけ EF を付け、一致しないものは既定へ潰す。③R1 は DSCP しか見ておらず、誰がその印を付けたのかを知る手段を持たない。だから印の正しさはアクセス端で作るしかない。受信側 PC3 の tcpdump の tos が、印が実際に入れ替わったかどうかを確かめられる唯一の場所になる。

まず QoS を一切入れない状態で 8 秒だけ流し、端末が名乗った印がそのまま PC3 に届くかを見ます。受信側で tcpdump を 60 パケット分だけ取ります。

snippet
PC3 $ sudo tcpdump -n -v -i eth0 udp port 5001 -c 60
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
02:40:05.951633 IP (tos 0x0, ttl 63, id 26409, offset 0, flags [DF], proto UDP (17), length 108)
    192.168.10.10.44312 > 192.168.20.20.5001: UDP, length 80
02:40:05.971352 IP (tos 0x0, ttl 63, id 26410, offset 0, flags [DF], proto UDP (17), length 70)
snippet
PC3 $ sudo tcpdump -n -v -i eth0 udp port 5002 -c 60
tcpdump: listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
02:40:06.567372 IP (tos 0xb8, ttl 63, id 62431, offset 0, flags [DF], proto UDP (17), length 540)
    192.168.10.11.43333 > 192.168.20.20.5002: UDP, length 512
02:40:06.685438 IP (tos 0xb8, ttl 63, id 62432, offset 0, flags [DF], proto UDP (17), length 540)

音声の 1 パケット目だけ IP 長が 108 バイトで、2 パケット目以降は指定どおりの 70 バイト (-l 42 + UDP 8 + IPv4 20) です。iperf のクライアントは最初のデータグラムに制御情報を載せるため、先頭だけが大きくなります。この 1 個だけという事実は、後で見る R1 のカウンタの総バイト数から裏付けられます。 状態④の優先クラスは 1010 パケットで 84878 バイトですが、これは定常パケット 84 バイト (IP 70 + Ethernet 14) が 1009 個と、先頭の 122 バイト (IP 108 + Ethernet 14) が 1 個の合計に一致します。

60 パケットの tos を数えると、音声が 60 tos 0x0、自称優先アプリが 60 tos 0xb8、素の業務データが 60 tos 0x0 です。SW1 のアクセスポートは端末が付けてきた DSCP をそのまま保存します。 音声は印を持たないまま、詐称された EF は EF のまま WAN 側へ抜けていき、WAN 側のルータが見る DSCP だけでは、この 2 つを区別できません。

次に SW1 へ信頼境界を投入して、同じ 8 秒を流します。分類は送信元 IP と UDP ポートの両方を見る拡張 ACL で行い、一致したものに EF を付け、一致しないものを既定へ潰します。

snippet
SW1(config)#ip access-list extended ACL-VOICE
SW1(config-ext-nacl)# permit udp host 192.168.10.10 any eq 5001
SW1(config-ext-nacl)#exit
SW1(config)#class-map match-all CM-VOICE
SW1(config-cmap)# match access-group name ACL-VOICE
SW1(config-cmap)#exit
SW1(config)#policy-map PM-TRUST-BOUNDARY
SW1(config-pmap)# class CM-VOICE
SW1(config-pmap-c)#  set dscp ef
SW1(config-pmap-c)# exit
SW1(config-pmap)# class class-default
SW1(config-pmap-c)#  set dscp default
SW1(config-pmap-c)# exit
SW1(config-pmap)#exit
SW1(config)#interface GigabitEthernet1/0/1
SW1(config-if)# service-policy input PM-TRUST-BOUNDARY
SW1(config-if)#exit
SW1(config)#interface GigabitEthernet1/0/2
SW1(config-if)# service-policy input PM-TRUST-BOUNDARY
SW1(config-if)#exit
SW1(config)#end

同じ policy-map を 2 つのポートに当てているのが、この構成の要点です。 電話が繋がるポートだけを特別扱いするのではなく、どのポートでも端末の印を信じないという 1 つの規律を置きます。PC1 のトラフィックは ACL に一致して EF になり、PC2 の詐称 EF は class-default に落ちて set dscp default で潰れます。

投入後に届いた印は次のとおりです。

snippet
PC3 $ sudo tcpdump -n -v -i eth0 udp port 5001 -c 60
02:41:22.101624 IP (tos 0xb8, ttl 63, id 61052, offset 0, flags [DF], proto UDP (17), length 108)
    192.168.10.10.60839 > 192.168.20.20.5001: UDP, length 80
PC3 $ sudo tcpdump -n -v -i eth0 udp port 5002 -c 60
02:41:22.699210 IP (tos 0x0, ttl 63, id 43911, offset 0, flags [DF], proto UDP (17), length 540)
    192.168.10.11.43176 > 192.168.20.20.5002: UDP, length 512
音声 (port 5001)自称優先アプリ (5002)素の業務データ (5003)
信頼境界なし60 tos 0x060 tos 0xb860 tos 0x0
信頼境界あり60 tos 0xb860 tos 0x060 tos 0x0

印を持たずに出た音声に EF が付き、詐称された EF が剥がされました。 この 2 回の測定で変えたのは SW1 の service-policy の有無だけなので、書き換えが起きた場所は SW1 に限定できます。§10 では policy を 1 ポートだけに当てた差分カウンタで、SW1 が実際にこのトラフィックを分類していることを確かめています (仮想 Catalyst 9000v は QoS Set にパケット数を付けないため、書き換えそのものの証拠は受信側の tos になります)。 5-3 信頼境界 は EF を既定へ潰す方向を、5-4 Classification と Marking は AF41 から AF31 への付け替えを扱っており、0 から非 0 へ書き込む方向は本検証で初めて確認したものです。

実務では、分類条件に RTP のポート範囲 (16384-32767) と電話機のアドレス空間を使います。本検証は観測を単純にするため、iperf が使う 5001 に固定しています。この構成をそのまま実務へ持ち込むときは、class-defaultset dscp default が音声以外のすべてを既定へ潰すことに注意が必要です。 呼制御 (CS3) や映像 (AF41) を別に扱う網では、それぞれを分類するクラスを先に置かないと、守りたい他のトラフィックの印まで消えます。

本検証が潰しているのは DSCP の詐称だけです。 分類条件が送信元 IP と UDP ポートである以上、端末がアドレスやポートまで偽れば同じクラスに入れます。実務ではこの層を、音声 VLAN の分離・ポート認証・DHCP snooping や IP Source Guard による送信元の担保・電話機の識別と組み合わせて成立させます。信頼境界は 1 つの service-policy で完結する仕組みではありません。

5. 手順① 契約帯域に絞る

最初に置くのは、WAN 出口の契約帯域への絞り込みです。5-9 の sub-rate shaping で扱ったとおり、自網で絞らなければ、契約を超えた分は事業者側の設備で捨てられ、どのクラスが失われるかを自網で制御できません。

状態①は「SW1 に信頼境界が無く、R1 が親 shaper だけを持つ」状態です。§4 で投入した信頼境界をここで外します。各状態は前の状態の設定を引きずらないよう、投入前に撤去してから作り直します。

snippet
SW1(config)#interface GigabitEthernet1/0/1
SW1(config-if)# no service-policy input PM-TRUST-BOUNDARY
SW1(config-if)#exit
SW1(config)#interface GigabitEthernet1/0/2
SW1(config-if)# no service-policy input PM-TRUST-BOUNDARY
SW1(config-if)#exit
SW1(config)#end

R1 の Gi3 に、class-default だけを持つ policy-map で親 shaper を置きます。信頼境界は入れず、子ポリシーも持たせません。

snippet
R1(config)#policy-map PM-WAN-SHAPE-ONLY
R1(config-pmap)# class class-default
R1(config-pmap-c)#  shape average 85000
R1(config-pmap-c)# exit
R1(config-pmap)#exit
R1(config)#interface GigabitEthernet3
R1(config-if)# service-policy output PM-WAN-SHAPE-ONLY
R1(config-if)#end

この状態で 3 本を 30 秒同時に送出します。受信側 PC3 のサーバが記録した結果です。

snippet
## 音声 (port 5001) 受信側 PC3 iperf サーバレポート
[  1] 0.00-31.57 sec  35.4 KBytes  9.18 Kbits/sec  21.866 ms 141/1003 (14%)
## 自称優先アプリ (port 5002, EF を詐称) 受信側 PC3 iperf サーバレポート
[  1] 0.00-31.21 sec  98.5 KBytes  25.9 Kbits/sec  27.735 ms 29/226 (13%)
## 素の業務データ (port 5003) 受信側 PC3 iperf サーバレポート
[  1] 0.00-30.98 sec   142 KBytes  37.4 Kbits/sec  30.637 ms 47/330 (14%)

3 本ともほぼ同じ割合で失われています。ルータ側のカウンタは、絞った先が 1 本の待ち行列であることを示します。

snippet
R1# show policy-map interface GigabitEthernet3
 GigabitEthernet3 

  Service-policy output: PM-WAN-SHAPE-ONLY

    Class-map: class-default (match-any)  
      1954 packets, 533124 bytes
      5 minute offered rate 12000 bps, drop rate 3000 bps
      Match: any 
      Queueing
      queue limit 64 packets
      (queue depth/total drops/no-buffer drops) 30/392/0
      (pkts output/bytes output) 1562/433774
      shape (average) cir 85000, bc 340, be 340
      target shape rate 85000

total drops 392 は 1 つのクラスの中で発生しています。契約帯域に絞るだけの構成では、溢れた分は到着した順に捨てられ、どのトラフィックを失うかを設計側から指定する手段がありません。 受信側 PC3 で見た印は音声が 60 tos 0x0、自称優先アプリが 60 tos 0xb8 のままで、端末の名乗りは網の奥まで届いています。それを読んでクラスを分ける仕組みが無いため、印は事実上ただのビット列です。

6. 手順② アクセス端に信頼境界を置く

次に、R1 側は状態①と同じ構成 (親 shaper のみ) のまま、SW1 に §4 の信頼境界を戻します。スケジューリングの設計は変えず、変わるのは印だけです。

ただし R1 のポリシーは状態ごとに当て直します。 クラス別カウンタは policy-map を適用し直すとゼロに戻るため、当て直しておくと各状態のカウンタをその状態だけの値として読めます。当て直さずに続けて測ると前の状態の値が積み上がり、後で使うパケット長の指紋が読めなくなります。

snippet
R1(config)#interface GigabitEthernet3
R1(config-if)# no service-policy output PM-WAN-SHAPE-ONLY
R1(config-if)#exit
R1(config)#no policy-map PM-WAN-SHAPE-ONLY
R1(config)#policy-map PM-WAN-SHAPE-ONLY
R1(config-pmap)# class class-default
R1(config-pmap-c)#  shape average 85000
R1(config-pmap-c)# exit
R1(config-pmap)#exit
R1(config)#interface GigabitEthernet3
R1(config-if)# service-policy output PM-WAN-SHAPE-ONLY
R1(config-if)#end

そのうえで SW1 に信頼境界を戻します。

snippet
SW1(config)#interface GigabitEthernet1/0/1
SW1(config-if)# service-policy input PM-TRUST-BOUNDARY
SW1(config-if)#exit
SW1(config)#interface GigabitEthernet1/0/2
SW1(config-if)# service-policy input PM-TRUST-BOUNDARY
SW1(config-if)#exit
SW1(config)#end

受信側 PC3 に届いた印は、音声が 60 tos 0xb8、自称優先アプリが 60 tos 0x0 に入れ替わっています。印の付け替えは完全に成功しています。 同じ 30 秒を流した結果です。

snippet
## 音声 (port 5001) 受信側 PC3 iperf サーバレポート
[  1] 0.00-31.44 sec  33.5 KBytes  8.74 Kbits/sec  24.929 ms 186/1003 (19%)
## 自称優先アプリ (port 5002, EF を詐称) 受信側 PC3 iperf サーバレポート
[  1] 0.00-31.71 sec  96.5 KBytes  24.9 Kbits/sec  25.260 ms 36/229 (16%)
## 素の業務データ (port 5003) 受信側 PC3 iperf サーバレポート
[  1] 0.00-31.47 sec   144 KBytes  37.6 Kbits/sec  28.428 ms 42/331 (13%)

音声は 186/1003 (19 %) を失っており、状態①の 141/1003 (14 %) から改善していません。R1 側に子ポリシーが無い以上、機構としては状態①と同一です。 印が変わってもスケジューリングは変わらないため、状態②で悪化したと読むものではありません。本検証は各状態を 30 秒 1 回ずつ測っているだけなので、この 5 ポイントの差から統計的な結論は引けません。 引けるのは「印を変えても損失は 1 割から 2 割の水準にとどまり、④のような質的な変化は起きない」ところまでです。ルータ側のカウンタも状態①と同じ形で、1 つのクラスに total drops 444 が計上されています。

snippet
R1# show policy-map interface GigabitEthernet3
 GigabitEthernet3 

  Service-policy output: PM-WAN-SHAPE-ONLY

    Class-map: class-default (match-any)  
      1964 packets, 552930 bytes
      5 minute offered rate 11000 bps, drop rate 3000 bps
      Match: any 
      Queueing
      queue limit 64 packets
      (queue depth/total drops/no-buffer drops) 64/444/0
      (pkts output/bytes output) 1520/434832
      shape (average) cir 85000, bc 340, be 340
      target shape rate 85000

印は分類の材料であって、それ自体は何も守りません。 マーキングを整備した直後は「QoS を導入した」ように見えますが、印を読んでキューを分ける側が無ければ、通信の質は変わりません。この状態は、設定作業としては完了しているのに効果がゼロという形で表面化します。

7. 手順③ WAN 出口に LLQ を入れる (信頼境界なし)

今度は逆に、SW1 の信頼境界を撤去して、R1 側にだけ優先制御を入れます。まず SW1 の信頼境界を外します。

snippet
SW1(config)#interface GigabitEthernet1/0/1
SW1(config-if)# no service-policy input PM-TRUST-BOUNDARY
SW1(config-if)#exit
SW1(config)#interface GigabitEthernet1/0/2
SW1(config-if)# no service-policy input PM-TRUST-BOUNDARY
SW1(config-if)#exit
SW1(config)#end

R1 側は状態①②で当てた親 shaper を外します。

snippet
R1(config)#interface GigabitEthernet3
R1(config-if)# no service-policy output PM-WAN-SHAPE-ONLY
R1(config-if)#exit
R1(config)#no policy-map PM-WAN-SHAPE-ONLY

親ポリシーが契約帯域へ絞り、その配下の子ポリシーが match dscp ef に一致したものを優先キューへ入れる階層構成です。

snippet
R1(config)#class-map match-all CM-VOICE-WAN
R1(config-cmap)# match dscp ef
R1(config-cmap)#exit
R1(config)#policy-map PM-WAN-CHILD
R1(config-pmap)# class CM-VOICE-WAN
R1(config-pmap-c)#  priority percent 30
R1(config-pmap-c)# exit
R1(config-pmap)# class class-default
R1(config-pmap-c)# exit
R1(config-pmap)#exit
R1(config)#policy-map PM-WAN-PARENT
R1(config-pmap)# class class-default
R1(config-pmap-c)#  shape average 85000
R1(config-pmap-c)#  service-policy PM-WAN-CHILD
R1(config-pmap-c)# exit
R1(config-pmap)#exit
R1(config)#interface GigabitEthernet3
R1(config-if)# service-policy output PM-WAN-PARENT
R1(config-if)#end

同じ 30 秒を流した結果です。

snippet
## 音声 (port 5001) 受信側 PC3 iperf サーバレポート
[  1] 0.00-31.83 sec  36.7 KBytes  9.46 Kbits/sec  32.666 ms 108/1003 (11%)
## 自称優先アプリ (port 5002, EF を詐称) 受信側 PC3 iperf サーバレポート
[  1] 0.00-30.28 sec  86.5 KBytes  23.4 Kbits/sec  14.939 ms 53/226 (23%)
## 素の業務データ (port 5003) 受信側 PC3 iperf サーバレポート
[  1] 0.00-31.64 sec   148 KBytes  38.2 Kbits/sec  31.255 ms 36/331 (11%)

音声は 108/1003 (11 %) で、依然として 1 割を失っています。理由はルータ側のカウンタが示しています。

snippet
R1# show policy-map interface GigabitEthernet3
 GigabitEthernet3 

  Service-policy output: PM-WAN-PARENT

    Class-map: class-default (match-any)  
      1909 packets, 503024 bytes
      5 minute offered rate 13000 bps, drop rate 2000 bps
      Match: any 
      Queueing
      queue limit 64 packets
      (queue depth/total drops/no-buffer drops) 0/358/0
      (pkts output/bytes output) 1551/409274
      shape (average) cir 85000, bc 340, be 340
      target shape rate 85000

      Service-policy : PM-WAN-CHILD

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

        Class-map: CM-VOICE-WAN (match-all)  
          244 packets, 135176 bytes
          5 minute offered rate 6000 bps, drop rate 3000 bps
          Match:  dscp ef (46)
          Priority: 30% (25 kbps), burst bytes 1500, b/w exceed drops: 65
          

        Class-map: class-default (match-any)  
          1665 packets, 367848 bytes
          5 minute offered rate 10000 bps, drop rate 3000 bps
          Match: any 
          
          queue limit 64 packets
          (queue depth/total drops/no-buffer drops) 0/293/0
          (pkts output/bytes output) 1372/310108

優先クラス CM-VOICE-WAN には 244 packets, 135176 bytes が入っています。1 パケットあたり 554.0 バイトで、これは音声のサイズではありません。 自称優先アプリのペイロード 512 バイトに UDP 8・IPv4 20・Ethernet 14 を足した値です。信頼境界が無いため EF を名乗ったアプリがそのまま優先キューに入り、印を持たない音声は class-default で素の業務データと一緒に溢れています。一次資料が「端末の印を信じるな」と警告している事態が、そのまま実機で成立しています。

優先クラスの b/w exceed drops: 65 は 244 パケットのうち 26.6 % で、優先枠 25.5 kbps に対して自称優先アプリが 32.9 kbps を投げ込んだ超過分です。受信側で自称優先アプリだけが 53/226 (23 %) と高い損失を示すのはこのためで、LLQ の内蔵ポリサは優先枠を守る方向にも働きます。 ただしその枠は本来音声のために確保したものであり、実際に守られたものは何もありません。

音声の損失は状態①の 14 % から 11 % になっています。機構の上では、下がる向きに働く要因があります。自称優先アプリが class-default から優先クラスへ移るため、音声が入る class-default の入力は 103.6 kbps から 70.7 kbps (音声 22.4 + 素の業務データ 48.3) へ減り、使える帯域も 85 kbps から 59.5 kbps へ減ります。超過率で見ると 122 % から 119 % へわずかに下がります。優先枠を超えた分は class-default へ回されるのではなく破棄されるので、減っているのは「入力の内訳」であって「捨てられた分の行き先」ではありません。

ただし、11 % と 14 % の差がこの 3 ポイントの超過率差によるものだと確かめたわけではありません。 各状態は 30 秒 1 回の測定なので、この程度の差を読み分けるには足りません。確かなのは、音声が優先クラスに入っておらず、素の業務データと同じ待ち行列で 1 割の損失を出していることです。音声が守られた結果ではありません。

なお、この結果が成り立つのは WAN 出口の子ポリシーが match dscp ef だけを見ているためです。WAN エッジ側で送信元 IP や UDP ポートを条件に分類する設計も取れるので、本検証が示しているのは「優先制御そのものが無力である」ことではなく、DSCP だけを条件に優先キューへ入れる設計では、手前に信頼境界が無いと EF の詐称を防げないという限定です。逆に言えば、印を正す場所を持たない網では、優先制御を入れる側が端末の名乗り以外の材料を持たなければなりません。

8. 手順④ 両方を揃える

最後に、SW1 の信頼境界を戻します。設計として新しいものは何もなく、§4 と §7 で決めた 2 つを同時に有効にするだけです。R1 の階層ポリシーも §6 と同じ理由で当て直し、カウンタをゼロから読みます。

snippet
R1(config)#interface GigabitEthernet3
R1(config-if)# no service-policy output PM-WAN-PARENT
R1(config-if)#exit
R1(config)#no policy-map PM-WAN-PARENT
R1(config)#no policy-map PM-WAN-CHILD

このあと §7 と同じ手順で PM-WAN-CHILDPM-WAN-PARENT を作り直して Gi3 に当て、SW1 側の信頼境界を戻します。

snippet
SW1(config)#interface GigabitEthernet1/0/1
SW1(config-if)# service-policy input PM-TRUST-BOUNDARY
SW1(config-if)#exit
SW1(config)#interface GigabitEthernet1/0/2
SW1(config-if)# service-policy input PM-TRUST-BOUNDARY
SW1(config-if)#exit
SW1(config)#end

この図を大きく開く ↗

同じトラフィックのまま構成だけを 4 通りに変えたときに、優先枠を誰が取り、誰が代償を払うか。①親 shaper だけの構成では絞った先が 1 本の待ち行列で、落ちるものを設計側から指定できない。②アクセス端で印を正しても、WAN 出口が 1 本の待ち行列のままなら結果は①と変わらない。③信頼境界を外して優先キューだけを入れると、EF を名乗ったアプリが優先枠に入り、印を持たない音声は class-default へ落ちる。④両方が揃って初めて優先枠に入るのが音声になり、名乗りだけの印は既定クラスへ回される。入る 3 本は毎回同じで、変わるのは出ていく順序と、誰が失われるかだけ。

同じ 30 秒を流した結果です。

snippet
## 音声 (port 5001) 受信側 PC3 iperf サーバレポート
[  1] 0.00-30.03 sec  41.2 KBytes  11.2 Kbits/sec   7.425 ms 0/1003 (0%)
## 自称優先アプリ (port 5002, EF を詐称) 受信側 PC3 iperf サーバレポート
[  1] 0.00-33.62 sec  99.0 KBytes  24.1 Kbits/sec  34.981 ms 28/226 (12%)
## 素の業務データ (port 5003) 受信側 PC3 iperf サーバレポート
[  1] 0.00-33.38 sec   148 KBytes  36.2 Kbits/sec  37.704 ms 35/330 (11%)

音声は 0/1003 (0 %) で、1 パケットも失われていません。 ジッタも 7.425 ms で、状態①②③の 21.866 / 24.929 / 32.666 ms と比べて明確に低い値です。輻輳の条件は 4 状態を通じて変わっていないため、この差は構成だけが生んだものです。

ルータ側のカウンタは、優先キューに入ったものが入れ替わったことを示します。

snippet
R1# show policy-map interface GigabitEthernet3
 GigabitEthernet3 

  Service-policy output: PM-WAN-PARENT

    Class-map: class-default (match-any)  
      1707 packets, 468880 bytes
      5 minute offered rate 14000 bps, drop rate 1000 bps
      Match: any 
      Queueing
      queue limit 64 packets
      (queue depth/total drops/no-buffer drops) 0/134/0
      (pkts output/bytes output) 1573/396780
      shape (average) cir 85000, bc 340, be 340
      target shape rate 85000

      Service-policy : PM-WAN-CHILD

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

        Class-map: CM-VOICE-WAN (match-all)  
          1010 packets, 84878 bytes
          5 minute offered rate 4000 bps, drop rate 0000 bps
          Match:  dscp ef (46)
          Priority: 30% (25 kbps), burst bytes 1500, b/w exceed drops: 0
          

        Class-map: class-default (match-any)  
          697 packets, 384002 bytes
          5 minute offered rate 12000 bps, drop rate 3000 bps
          Match: any 
          
          queue limit 64 packets
          (queue depth/total drops/no-buffer drops) 63/134/0
          (pkts output/bytes output) 563/311902

優先クラスは 1010 packets, 84878 bytes で、1 パケットあたり 84.04 バイトです。RTP 12・G.729 の 30 ms 分 30 バイト・UDP 8・IPv4 20・Ethernet 14 を足した音声のサイズと一致します。同じ match dscp ef という 1 行が、信頼境界の有無だけで全く違うトラフィックを掴んでいます。 554.0 バイトと 84.04 バイトが、その指紋です。

優先キューの (queue depth/total drops/no-buffer drops) 0/0/0pkts output 1010 は、入った 1010 パケットが 1 つも落ちずに出ていったことを示します。受信側の 0/1003 (0%) も欠落ゼロで、ルータ側と受信側の両方で破棄が観測されていません (ルータが数える 1010 と iperf が数える 1003 の差は本節では追っていません。差はフローによって一定ではなく、状態④の class-default では 697 対 556 と開くため、単一の原因では説明できません)。b/w exceed drops も 0 で、優先枠を超過していません。

4 状態を並べます。

状態信頼境界R1音声音声のジッタ自称優先アプリ素の業務データ
① 素の輻輳なしshape のみ141/1003 (14%)21.866 ms29/226 (13%)47/330 (14%)
② マーキングのみありshape のみ186/1003 (19%)24.929 ms36/229 (16%)42/331 (13%)
③ LLQ のみなしshape + LLQ108/1003 (11%)32.666 ms53/226 (23%)36/331 (11%)
④ マーキング + LLQありshape + LLQ0/1003 (0%)7.425 ms28/226 (12%)35/330 (11%)

送出パケット数は全状態でほぼ一定 (音声 1003・自称優先アプリ 226〜229・素の業務データ 330〜331) なので、この比較は公正です。**ただし各状態は 30 秒 1 回ずつの測定なので、①②③ の間の数ポイントの差を読み分けることはできません。**①②③ はいずれも音声が 1 割から 2 割を失っており、「守られていない」という点で同じです。質的に違うのは④だけです。 代償を払うのは class-default 側で、自称優先アプリと素の業務データは④でも 1 割以上を失い続けています。守る対象を選べるようになった代わりに、失われる側が必ず現れます。

9. 割当はどう決めるか

優先クラスに何 % を与えるかには、一次資料が上限を示しています。

“In other words, it is recommended that no more than 33 percent of the bandwidth be used for the expedite forwarding (EF) queue.”

“It is also important to note that this 33 percent design principle is simply a best practices design recommendation and not necessarily a mandatory rule.”

— Cisco Press, QoS Design Principles and Best Practices — Per-Hop Behavior Queue Design Principles (出典)

strict-priority キューに使うのはリンク帯域の 33 % までという原則で、後半の 1 文は、これが必須の規則ではなくベストプラクティスとしての推奨であると断っています。本検証の契約帯域 85 kbps に当てると、33 % は 28.05 kbps です。同じ原則はリンク帯域の 1/3 までとも表現され、その場合は 28.3 kbps になります。priority percent 30 が解決する 25.5 kbps はどちらの取り方でも範囲に収まります。なお priority percent 30 が指す 25,500 bps を直接示す出力はありません。実機の show policy-map interfacePriority: 30% (25 kbps) と整数の kbps で表示するため、25.5 kbps は 30 % から計算した値です。5-9 で試した 45 % は割当を動かす実験値であり、実務で採る値ではありません。

上限とは別に下限があります。優先クラスの割当は、守る対象の実需要より大きくなければ意味がありません。 G.729 の符号化速度は 8 kbps で、30 ms ごとにパケット化すると音声ペイロードは 30 バイト、そこに RTP の固定ヘッダ 12 バイトが乗ります。

“The first twelve octets are present in every RTP packet”

— RFC 3550 §5.1 RTP Fixed Header Fields (出典)

RTP 12 に UDP 8 と IPv4 20 を足すと、いわゆる 40 バイトのヘッダになります。計算はここで終わりではありません。 本検証機では、Ethernet ヘッダ 14 バイトを足した 84 バイト優先クラスのカウンタとポリサの数える 1 パケットでした (§9 後半の実測)。親シェーパが同じ基準で数えているかは、本検証の条件では判別できません (IP 層で合計しても契約帯域を超えるため、どちらでも輻輳します)。この扱いは機種と実装に依存するので、別の機器では自分で確かめる必要があります。30 ms ごとに 1 パケットなので 84 × 8 ÷ 0.03 = 22,400 bps となり、これが割当の下限になります。

この 14 バイトを落とした回も実測してあります。音声を IP 層の 70 バイト = 18.7 kbps と見積もり、shape average 70000priority percent 30 = 21 kbps を与えた構成で、計算上は無損失になるはずでした。

snippet
R1# show policy-map interface GigabitEthernet3
(親 class-default、優先クラス全体のキュー統計、class-default 子クラスの表示を省略)
        Class-map: CM-VOICE-WAN (match-all)  
          1008 packets, 84710 bytes
          5 minute offered rate 3000 bps, drop rate 1000 bps
          Match:  dscp ef (46)
          Priority: 30% (21 kbps), burst bytes 1500, b/w exceed drops: 52
snippet
## 音声 (port 5001) 受信側 PC3 iperf サーバレポート
[  1] 0.00-30.03 sec  39.1 KBytes  10.7 Kbits/sec   7.279 ms 50/1003 (5%)

84710 / 1008 = 84.04 バイトで、設計上の IP 長 70 バイトとの差はちょうど 14 バイトです。音声の実レートは IP 層で見積もった 18.7 kbps ではなく、実測で 22.6 kbps (84710 バイト / 30 秒) でした。設計値として本節が使う 22.4 kbps は 1 パケット 84 バイトを 30 ms 間隔で送る計算値で、実測の 22.6 kbps との差は、先頭パケットの膨らみ・送出間隔のゆらぎ・ルータだけが数える終了通知データグラムの 3 つが積み上がったものです。いずれにせよ割当 21 kbps を超えています。守るつもりで作った優先クラスの中で、守る対象だけがポリサに落とされています。 この回の自称優先アプリでも 161214 / 291 = 554.0 バイトが同じ「IP 長 + 14」に一致しており、2 つの独立したフローで確認できます。FCS の 4 バイトは含まれません。

割当の上限と下限を両側から締めると、設計値は 1 つの範囲に収まります。契約帯域 85 kbps に対する上限は 33 % の 28.05 kbps、下限は G.729 1 通話の設計値 22.4 kbps で、priority percent 30 が解決する 25.5 kbps はその間に入ります。守る対象に対して 1 割強の余裕があります。

モデルに書かれた % をそのまま当てはめると破綻します。 Cisco の 8 クラスモデルは音声について次のように書いています。

“Voice: Marked with EF and limited to 10 percent of link bandwidth in a strict-priority queue”

— Cisco Press, QoS Design Principles and Best Practices — QoS Strategy Models (出典)

この 10 % を契約 85 kbps に当てると 8.5 kbps で、G.729 の 1 通話 22.4 kbps すら入りません。 5-9 で観測した EF 79 % 損失は、まさにこの状態でした。モデルの % は「そのリンクに載せる通話数から逆算した結果」であって、どんなリンクでも 10 % でよいという意味ではありません。逆算する向きは通話数から帯域へで、% は結果として出てきます。

10. 確認コマンドの読み方

カウンタの読み方には、検証機固有の制約が 3 つあります。

1 つ目は、同一の policy-map を複数のインタフェースへ当てると show policy-map interface <if> がポリシー単位の合算を返すことです。 両ポートへ PM-TRUST-BOUNDARY を適用し、Gi1/0/1 からしか入らない音声だけを 6 秒流したときの値が次のものです。

読んだインタフェースCM-VOICE 基準 → 測定後class-default
Gi1/0/1 (音声が実際に入る)906 → 1214 (+308)544 → 568 (+24)
Gi1/0/2 (無トラフィック)906 → 1214 (+308)544 → 568 (+24)

無トラフィックのポートも同じだけ増えます。 「カウンタが増えたからそのポートで効いている」という読み方は成り立ちません。同じ policy を 1 ポートだけに当てた場合は帰属が正確で、PC2 だけを流したときは CM-VOICE が 401 のまま変わらず、PC1 だけを流したときに 401 から 704 へ +303 増えました。この切り分けは送出設計を改訂する前に実施しており、当時の音声は 50 pps (-l 200 -b 80k) だったので、6 秒の送出は設計値で 300 パケットです (本節の最終設計は 33.3 pps なので 6 秒なら 200 パケットになります)。match access-group name が実際に分類していることの裏付けでもあります。本検証で印が入れ替わった証拠に受信側 PC3 の tos を使っているのは、この合算表示があるためです。

2 つ目は、clear policy-map counters が本機に存在しないことです。

snippet
SW1#clear policy-map counters
                           ^
% Invalid input detected at '^' marker.

値は累積になるので、測定の前後で読んで差分で扱います。3 つ目は、カウンタの更新に遅延があることです。 音声 6 秒分の送出が +203+105 に分かれて計上され (合計 308)、1 回目の読み取りだけでは 203 しか見えなかった例があります。送出直後に読むと過小に見えます。読む前に 30 秒待つのが安全です。

R1 側の b/w exceed drops は積分値であって現在の状態ではありません。ポリシーを当て直さない限り前の測定で発生したドロップが残るため、状態を語るときは受信側 iperf の損失率と、クラス行の drop rate を使います。 主張ごとに根拠となる出力を固定しておくと読み違えが減ります。

確かめたいこと見る場所
端末が何を名乗って送ってきたかQoS 無しの状態で取った PC3 の tcpdump の tos
印が付け替わったか各状態の PC3 の tcpdump の tos
どちらが優先キューに入ったかR1 の show policy-map interface Gi3 のクラス別 packets / bytes
音声が守られたか受信側 PC3 の iperf サーバレポート (損失とジッタ)

送信側 iperf の表示がこの表に無い理由は §11 で扱います。

11. 落とし穴・補足

経路の実効天井は、機器のデモ天井とは別に存在します。 R1 の show platform hardware throughput levelThe current throughput level is 1000 kb/s を返しますが、直列経路で実際に通る量はそれよりはるかに低い値でした。

測定条件定常スループット (先頭 3 行と末尾 3 行を除く interval 行の平均)
PC2 → PC3 (SW1 + R1 経由)1400 バイトで 1000 kbps を要求169 kbps / 15.4 pps
PC2 → PC3 (SW1 + R1 経由)200 バイトで 1000 kbps を要求129 kbps / 80.5 pps
PC1 → PC2 (SW1 の中だけ)1400 バイトで 1000 kbps を要求167 kbps / 15.2 pps

pps が 5 倍違っても bps が同水準なので、これは bps 基準の天井です。R1 を通らない SW1 内の L2 転送でも同じ 167 kbps に張り付くため、天井の正体は仮想 Catalyst 9000v のデータプレーンです。5-9 が 800 kbps を流せたのは、経路に Catalyst 9000v が無かったためです。

契約帯域は、経路の実効天井より下に置く必要があります。 天井のほうが低いとシェーパは一度も溢れず、輻輳下の比較そのものが成立しません。初版の設計は合計 780 kbps を契約 500 kbps へ流し込む構成でしたが、天井の上にあったため状態①の R1 Gi3 が (queue depth/total drops/no-buffer drops) 0/0/0 を返しました。契約 85 kbps は天井 167 kbps の 51 % として逆算した値です。

送信側 iperf の表示は、網を通った量ではありません。 クライアントが表示するのはソケットに書けた量で、経路のバッファに溜まっている分も含みます。初版の診断では、PC2 から 2 本 (300 kbps + 400 kbps 指定) を 12 秒流したときにクライアントが 302 kbps と 402 kbps を報告した一方、受信側は同じ送出を 22 秒かけて受け取り、毎秒 67 kbps から 112 kbps しか届いていませんでした。ジッタも 29 ms から 122 ms の水準へ上がっており (途中で下がる区間もあります)、経路のバッファに溜まり続けていたことが読めます。正本は受信側の記録です。 本節が各状態で引いているのは受信側サーバの最終サマリ行で、サマリが出ない場合の保険として interval 行を使います。

輻輳下では iperf の終了通知データグラムが落ち、サーバが最終サマリ行を出さないことがあります。 iperf は送出の終わりに制御用のデータグラムを送り、サーバはそれを受けて最終サマリを出します。UDP には TCP のような接続終了手順が無いため、この通知が落ちればサーバは終わりを知る手段を持ちません。 サマリ行だけを見ていると受信量が読めなくなるため、サーバに -i 1 を付けて interval 行からも読めるようにします。

本ラボは縮尺モデルです。 契約帯域 85 kbps も、音声 1 通話 22.4 kbps も、上記の実効天井から逆算した値であって実務値ではありません。実務では音声コーデックに G.711 を使うことが多く、その場合は 1 通話 80 kbps 前後、WAN の契約帯域は数百 kbps から数 Mbps の桁になります。絶対値をそのまま実務へ持ち込むことはできません。 縮尺しても壊れないのは次の 3 つの比率で、本検証が示しているのはこちらです。

  1. 優先クラスはリンク帯域の 1/3 以内に収める (本検証は 30 %)
  2. 優先クラスの割当は守る対象の設計値より大きくする (25.5 kbps > 22.4 kbps)
  3. 総送出が契約帯域を超えている (総送出 103.6 kbps は契約帯域 85 kbps の 122 %)

priority は輻輳時にだけ効く条件付きポリサです。 明示的な police を併記しない限り、競合が無く帯域に余裕がある間は割当を超えて送れます。平常時のテストで「効いている」と判断できないのはこのためで、全状態を 122 % の輻輳下に置いているのはこの性質に合わせた設計です。

検証後の最終形です。同じ policy-map が 2 つのアクセスポートに当たっています。

snippet
SW1# show running-config | section class-map|policy-map|ip access-list
(システム既定の system-cpp-* / non-client-nrt-class / policy-map system-cpp-policy を省略)
class-map match-all CM-VOICE
 match access-group name ACL-VOICE
policy-map PM-TRUST-BOUNDARY
 class CM-VOICE
  set dscp ef
 class class-default
  set dscp default
ip access-list extended ACL-VOICE
 10 permit udp host 192.168.10.10 any eq 5001
snippet
SW1# show running-config interface GigabitEthernet1/0/1
(Building configuration... / 空行 / Current configuration : N bytes / ! の 4 行を省略)
interface GigabitEthernet1/0/1
 description PC1 (IP phone) - trust boundary apply point
 switchport access vlan 10
 switchport mode access
 spanning-tree portfast
 service-policy input PM-TRUST-BOUNDARY
end

R1 側は、親ポリシーが契約帯域へ絞り、子ポリシーが優先枠を切る 2 段構成です。

snippet
R1# show running-config | section policy-map
policy-map PM-WAN-CHILD
 class CM-VOICE-WAN
  priority percent 30
 class class-default
policy-map PM-WAN-PARENT
 class class-default
  shape average 85000   
   service-policy PM-WAN-CHILD
snippet
R1# show running-config interface GigabitEthernet3
(Building configuration... / 空行 / Current configuration : N bytes / ! の 4 行を省略)
interface GigabitEthernet3
 description to PC3 (WAN side = sub-rate shaper + LLQ apply point / egress)
 ip address 192.168.20.1 255.255.255.0
 negotiation auto
 no mop enabled
 no mop sysid
 service-policy output PM-WAN-PARENT
end

12. まとめと次節

本節では、端末から出た音声をアクセス端で EF にマーキングし、WAN 出口の LLQ で守るところまでを 1 本の経路で通しました。同じトラフィックのまま構成だけを 4 通りに変えた結果、音声が無損失になったのは両方が揃った状態だけで、受信側の実測は 0/1003 (0%)、ジッタ 7.425 ms でした。

印を整えただけの状態では、受信側の印が完全に入れ替わっても損失は変わりません。優先制御だけを入れた状態では、EF を名乗ったアプリが優先枠を占拠し、印を持たない音声は class-default へ落ちます。優先クラスに入ったものの正体はパケット長という指紋から読め、554.0 バイトなら自称優先アプリ、84.04 バイトなら音声です。信頼境界と LLQ は、どちらか片方では成立しません。

割当を決めるときは、上限を 33 % の原則で、下限を守る対象の実需要で締めます。実需要は L2 ヘッダ 14 バイトを含めて数え、IP 層で計算すると守るつもりの音声だけがポリサに落とされます。

ここまでで、設計・配分・実装の一通りが揃いました。残るのは、組んだ QoS が期待どおりに効いていないときの切り分けです。次節 5-11 では、QoS のトラブルシュートを、分類・マーキング・キューイングのどの段で崩れているかを特定する手順として見ていきましょう。