STUDY · NETWORK GUIDE

5-4 Classification と Marking — 分類してクラス別にマーキングする

class-map の match で複数クラスに分類し、policy-map の set でクラス別に DSCP をマーキングする MQC の作り込みを Cat9000v (IOS-XE 17.15.03) の実機で扱う。多クラス policy-map・match access-group・table-map・NBAR2 を、受信側 PC2 の tcpdump が示す ToS の 3 分布で検証しながら解説する第 5 章 QoS 編の実機節。

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

前節 5-3 Trust Boundary では、アクセス端に信頼境界を引く判断を Cat9000v の実機で扱いました。Catalyst 9000 (IOS-XE) の QoS は mls qos を持たない MQC (Modular QoS CLI) モデルであること、既定では外来 DSCP がそのまま信頼されて宛先まで運ばれること、そして untrust (set dscp default) で境界を引くと DSCP が 0 に付け直されることを、show 出力と受信側の tcpdump で確かめました。

前節は「信頼するか、0 に付け直すか」という 単一クラスの 2 値の判断 に焦点を絞りました。前節の最後に、信頼境界の内側で行う 分類とマーキングの作り込み = class-map で通信をどう見分け、policy-map で DSCP や CoS をどう設定するかを、次節で掘り下げると予告しました。

本節はその予告に応えます。扱うのは、任意の match 基準で複数のクラスに切り分け、クラスごとに別の DSCP へ付け直す という MQC の一般化した姿です。前節の「1 つのクラスを trust/untrust する」を、音声 (VOICE)・映像 (VIDEO)・その他 (BE) の 3 クラスへ分けてクラス別にマーキングする ところまで広げます。分類基準も match dscp だけでなく、送信元 IP を見る match access-group、アプリを見分ける NBAR2 (match protocol) まで扱います。効き目の検証は前節と同じく、受信側 PC2 の tcpdump が示す ToS の分布 を正本とします。

2. 分類とマーキングの MQC 3 段パイプライン

Catalyst 9000 の分類とマーキングは、3 段のパイプライン で組み立てます。何を見てクラスに仕分けるかを決める class-map (分類段)、クラスごとに何を書き込むかを決める policy-map (マーキング段)、そのポリシーをどのインタフェースのどちら向きに当てるかを決める service-policy (適用段) の 3 つです。

snippet
class-map   … 分類段: 何を見てクラスに仕分けるか (match dscp / match access-group / match protocol)
policy-map  … マーキング段: クラスごとに何を set するか (set dscp / set cos / table-map)
service-policy input  … 適用段: アクセス端 = パイプライン入口に当てる

class-map は「このクラスに入れる条件」を match 文で書きます。policy-map は「そのクラスに対して何をするか」を class <名前> ごとに書き、本節では set dscpset cos でマーキングします。service-policy は完成したポリシーをインタフェースに input (入口) 方向で当てます。分類とマーキングは外来トラフィックが最初に触れるアクセス端で行うため、方向は input です。

この 3 段を 1 枚に通したのが、本節の検証ラボです。端末 PC1 が複数の ToS を混在させて送り、SW1 のアクセス端 Gi1/0/1 で分類・マーキングし、受信端末 PC2 が届いた ToS を tcpdump で観察します。

検証ラボのトポロジと分類・マーキングの 3 段パイプライン。端末 PC1 が EF/AF/BE を混在させた UDP を送り、SW1 (Cat9000v) の Gi1/0/1 = 信頼境界 = パイプライン入口で ① class-map が分類し ② policy-map が set でマーキングし ③ 同一 VLAN の Gi1/0/2 から PC2 へ転送する。分類基準は match dscp / match access-group / match protocol(NBAR2) の複数、マーキングは set dscp / set cos / table-map。★効いたかどうかは受信 PC2 の tcpdump(tos) で検証する。仮想機の QoS Set カウンタは増えない

前節との違いは、policy-map が持つクラスの数です。前節は class-default だけの単一クラスでしたが、本節は VOICE・VIDEO・class-default の複数クラスを持ち、それぞれに別の set dscp を書きます。

3. Cat9000v は MQC モデル

本節の検証機も前節と同じ Cat9000v で、QoS は MQC で表現します。前節で詳説したとおり、Catalyst 3560/3750 系の mls qos は Catalyst 9000 (IOS-XE) には存在せず、打っても受け付けられません。念のため本節でも確認しておきます。

snippet
SW1# show mls qos
           ^
% Invalid input detected at '^' marker.

mls qos が無いため、分類も信頼もマーキングもすべて class-map / policy-map / table-map で組みます。使用した機器と IOS-XE は次のとおりで、前節と同一です。

snippet
SW1# show version | include Cisco IOS-XE Software|C9|cat9|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)
Switch Ports Model              SW Version        SW Image              Mode
*    1 24    C9KV-UADP-8P       17.15.03          CAT9K_IOSXE           INSTALL

機種は C9KV-UADP-8P (VXE)、ソフトウェアは IOS-XE 17.15.03 です。仮想機である点は、後述するマーキングカウンタと NBAR2 の見え方に効いてきます。

4. 多クラス policy-map で 3 クラスをクラス別にマーキング

ここが本節の核です。match dscp で 3 つのクラスに分類し、クラスごとに別の DSCP へマーキングする MQC を実機で組み、その効果を受信側の tcpdump で確かめます。

まず分類段の class-map を切ります。音声を EF (DSCP46) で拾う CM-VOICE、映像を AF41 (DSCP34) で拾う CM-VIDEO の 2 つを定義します。どちらにも入らない残りは、policy-map 側の暗黙のクラス class-default が拾います。次にマーキング段の policy-map PM-MARK を組み、クラスごとに別の set dscp を書きます。最後に適用段として、入口 Gi1/0/1 に service-policy input で当てます。

snippet
! ---- 分類段: match dscp で 2 クラスを切る (残りは class-default) ----
class-map match-any CM-VOICE
 match dscp ef
class-map match-any CM-VIDEO
 match dscp af41
!
! ---- マーキング段: クラスごとに別 DSCP を set する多クラス policy-map ----
policy-map PM-MARK
 class CM-VOICE
  set dscp ef            ! 音声は EF を維持
 class CM-VIDEO
  set dscp af31          ! 映像は AF41 -> AF31 に格下げ再マーキング
 class class-default
  set dscp default       ! 未分類は BE(0) に付け直す
!
! ---- 適用段: パイプライン入口 (アクセス端) に当てる ----
interface GigabitEthernet1/0/1
 service-policy input PM-MARK

match-any は「並べた match 基準のいずれかに一致すればそのクラス」という指定です。ここでは match 基準が 1 つずつなので match-all との差は出ませんが、複数の基準を並べたときに OR (any) か AND (all) かが分かれます。分類段が正しく切れているかは show class-map で確認できます。

snippet
SW1# show class-map
 Class Map match-any CM-VOICE (id 62)
   Match   dscp ef (46)

 Class Map match-any CM-VIDEO (id 63)
   Match   dscp af41 (34)

CM-VOICE は DSCP ef(46)、CM-VIDEO は DSCP af41(34) を match しています。次に、PM-MARK を Gi1/0/1 に当てた状態で、入口が何を見てどう set しているかをインタフェース単位で確認します。PC1 は EF・AF41・BE の 3 系統を並行して送り続けています。

snippet
SW1# show policy-map interface GigabitEthernet1/0/1
 GigabitEthernet1/0/1

  Service-policy input: PM-MARK

    Class-map: CM-VOICE (match-any)
      135 packets
      Match:  dscp ef (46)
      QoS Set
        dscp ef

    Class-map: CM-VIDEO (match-any)
      134 packets
      Match:  dscp af41 (34)
      QoS Set
        dscp af31

    Class-map: class-default (match-any)
      134 packets
      Match: any
      QoS Set
        dscp default

分類のカウンタは各クラスで増えています (CM-VOICE=135・CM-VIDEO=134・class-default=134 packets)。3 系統が期待どおり 3 つのクラスに振り分けられている証拠です。一方、その下の QoS Set 行 (dscp ef / dscp af31 / dscp default) には、マーキングした packet 数が付きません。この検証機が仮想の C9KV-UADP で、マーキングのハードウェア処理を完全にはエミュレートしないためです (前節 §8 と同じ制約)。したがって「set が効いたかどうか」は、この show のカウンタでは判定できません。

効き目の正本は、受信側 PC2 に届いたパケットの ToS です。まず基準として、PM-MARK を当てる前 (policy 未適用) の状態で PC2 が観測する ToS を撮ります。

snippet
PC2:~$ sudo timeout 8 tcpdump -n -v -c 18 -i eth0 'udp and dst 192.168.10.20' 2>/dev/null \
       | grep -o 'tos 0x[0-9a-f]*' | sort | uniq -c
      6 tos 0x0
      6 tos 0x88
      6 tos 0xb8

上の 3 行は、PC1 が送った 3 系統がそのまま届いていることを示します。tos 0x0 が BE (DSCP 0)、tos 0x88 が AF41 (DSCP 34)、tos 0xb8 が EF (DSCP 46) です。policy を当てる前は、既定の信頼 (trust) で 3 系統とも入口の印のまま PC2 に届いています。ここで PM-MARK を Gi1/0/1 に当て、同じ 3 系統を送りながら再度 PC2 の ToS を撮ります。

snippet
PC2:~$ sudo timeout 8 tcpdump -n -v -c 18 -i eth0 'udp and dst 192.168.10.20' 2>/dev/null \
       | grep -o 'tos 0x[0-9a-f]*' | sort | uniq -c
      6 tos 0x0
      6 tos 0x68
      6 tos 0xb8

3 つの分布が、policy-map の 3 クラスの set と一対一で対応しています。1 行目 tos 0x0 は class-default の set dscp defaultBE (DSCP 0) に付け直された ものです。2 行目 tos 0x68 は CM-VIDEO の set dscp af31AF41 から AF31 (DSCP 26) へ格下げ されたもの、3 行目 tos 0xb8 は CM-VOICE の set dscp efEF (DSCP 46) が維持 されたものです。DSCP26 (AF31) は二進で 011010、これを ToS バイトの上位 6 ビットに置くと 01101000 = 0x68 です。とりわけ VIDEO レーンの 0x88 → 0x68 は、印を消す方向ではなく、ある印から別の印へ付け替えた 証拠で、多クラスのクラス別マーキングが受信側で決定的に観測できました。

多クラス policy-map による 3 レーンの分類とマーキング。PC1 が EF(0xb8)/AF41(0x88)/BE(0x00) の 3 系統を入口 Gi1/0/1 へ送る。① class-map が CM-VOICE/CM-VIDEO/class-default に振り分け ② policy-map がクラス別に set: VOICE=set dscp ef 維持(0xb8) / VIDEO=set dscp af31 格下げ(0x88→0x68) / BE=set dscp default(0x00)。効いたかは受信 PC2 の tcpdump の 3 分布(0xb8/0x68/0x00)で検証する。仮想機の QoS Set カウンタは増えない

前節の untrust (単一クラスを 0 に付け直す) は、この多クラスマーキングの最小の場合にあたります。本節はそれを N クラスへ広げ、クラスごとに別の DSCP を割り当てました。

5. 分類基準を広げる — match access-group と set cos

分類の基準は DSCP だけではありません。送信元 IP アドレスでクラスを切りたい 場合は、ACL を作って match access-group で参照します。ここでは PC1 (192.168.10.10) からの通信を 1 クラスにまとめる例を示します。

snippet
ip access-list extended PERMIT-PC1
 permit ip host 192.168.10.10 any
!
class-map match-all CM-SRC
 match access-group name PERMIT-PC1
!
policy-map PM-MARK
 class CM-SRC
  set cos 5              ! L2 CoS 印 (tagged trunk 越しに有効)

match access-group name は、指定した ACL に許可 (permit) されるパケットをそのクラスに入れます。DSCP を見る match dscp と違い、送信元・宛先 IP やプロトコル・ポートなど ACL で表現できる条件でクラスを切れます。上の CM-SRC には set cos 5 を書きました。CoS は L2 (イーサネットフレーム) の印です。policy-map に CM-SRC を足した状態は、show policy-map の定義で確認できます。

snippet
SW1# show policy-map PM-MARK
  Policy Map PM-MARK
    Class CM-VOICE
      set dscp ef
    Class CM-VIDEO
      set dscp af31
    Class CM-SRC
      set cos 5
    Class class-default
      set dscp default

ここで注意が必要です。set cos 5 の効果は、本節の tcpdump では観測できません。tcpdump で見ている ToS は L3 (IP ヘッダ) の DSCP であり、CoS は L2 のフレームヘッダに乗る別の印だからです。しかも CoS が乗るのはタグ付き (トランク) のフレームだけで、本ラボの PC1・PC2 は同一 VLAN のアクセスポート (untagged) に接続しているため、フレームに CoS タグが付きません。したがって set cos は「構文としてはこう書く」「show policy-map の定義にはこう出る」までを押さえ、効き目の tos 実証は前節・本節 §4 の set dscp に一本化します。tcpdump で CoS を探しても見つからない、という点が誤解しやすいところです。

6. table-map による CoS→DSCP 一括マッピング

クラスごとに set dscp を手書きする代わりに、対応表 (table-map) を 1 枚作って一括で写す 方法もあります。入ってきた印 (ここでは L2 の CoS) を、表に従って別の印 (L3 の DSCP) へ変換する仕組みです。前節でも table-map (COS-TO-DSCP) を扱いましたが、本節ではクラス別の手書き set との 対比 として位置づけます。

snippet
table-map COS-TO-DSCP
 map from 0 to 0
 map from 5 to 46
 map from 6 to 48
 default 0
!
policy-map PM-COS
 class class-default
  set dscp cos table COS-TO-DSCP

table-map は「入り値 → 出し値」の写像を並べたもので、default はどの行にも当たらない入り値の既定の出し先です。この表を policy-map の set dscp cos table から呼ぶと、入力の CoS を見て DSCP へ写せます。定義は show table-map で確認できます。

snippet
SW1# show table-map COS-TO-DSCP
 Table Map COS-TO-DSCP
 from 0 to 0
 from 5 to 46
 from 6 to 48
 default 0
snippet
SW1# show policy-map PM-COS
  Policy Map PM-COS
    Class class-default
      set dscp cos table COS-TO-DSCP

CoS5 を DSCP46 (EF) に、CoS6 を DSCP48 (CS6) に写す表です。クラスを増やさずに、多くの入り値を 1 枚の表でまとめて変換できるのが手書き set との違いです。ただし、この table-map の効果も本節の tcpdump では実証しません。set dscp cos table が見る「入りの CoS」は、アクセスポート (untagged) では常に 0 になり、表は from 0 または default を引いて DSCP0 を返すだけになるためです。「効いた」場合と「何も設定しない」場合が tcpdump で区別できない状態 (silent failure) になります。table-map は トランクや音声 VLAN 経由で CoS を持つ入力があって初めて効く写像器 であり、そうした入力のある環境で使う道具です。

なお set dscp cos table は、Cisco の Catalyst 9300 QoS 設定ガイド (IOS-XE 17.15) の構文一覧には明記されていません。前節と同様、実機の ? ヘルプで裏を取ってから使うのが安全です。

7. NBAR2 — アプリを見分ける分類

これまでの分類基準 (DSCP・送信元 IP) は、パケットのヘッダを見るものでした。アプリケーションそのものを見分けて分類したい 場合に使うのが NBAR2 (Network Based Application Recognition 2) です。NBAR2 はパケットのペイロードまで踏み込んで L7 のアプリを識別し、match protocol でクラスに入れます。たとえば HTTP を 1 クラスにまとめて AF21 でマーキングする設定は次のとおりです。

snippet
class-map match-any CM-HTTP
 match protocol http
!
policy-map PM-MARK
 class CM-HTTP
  set dscp af21
!
interface GigabitEthernet1/0/1
 ip nbar protocol-discovery       ! NBAR2 をインタフェースで起動
 service-policy input PM-MARK

match protocol http が NBAR2 の分類基準で、ip nbar protocol-discovery はインタフェースで NBAR2 の識別エンジンを起動します。DSCP や IP アドレスでは区別できない「HTTP か否か」を、ペイロードの中身から判定できるのが NBAR2 の強みです。本節の検証機でも、この構文の投入と ip nbar protocol-discovery の適用は受け付けられました。

ただし、識別のカウンタは増えませんでした。HTTP の合成トラフィックを流した後で protocol-discovery の集計を撮ると、次のように Total が 0 のままです。

snippet
SW1# show ip nbar protocol-discovery interface GigabitEthernet1/0/1

 GigabitEthernet1/0/1

 Last clearing of "show ip nbar protocol-discovery" counters 00:00:23

                                  Input                    Output
                                  -----                    ------
 Protocol                         Packet Count             Packet Count
                                  Byte Count               Byte Count
 -------------------------------- ------------------------ ------------------------
 Total                            0                        0
                                  0                        0

これは、本節の検証機が仮想の C9KV-UADP で、ソフトウェアのデータプレーンで L7 の DPI (Deep Packet Inspection) を実際には動かさない ためです。構文と protocol-discovery の起動は通っても、ペイロードの L7 識別が走らないので count が 0 のままになります。物理の Catalyst 9000 では NBAR2 の識別エンジンが動作し、HTTP を識別してカウンタが増えます。本節では NBAR2 を「概念と設定例」として提示し、実機の識別ヒットは仮想機の限界として主張しません。

8. 落とし穴・補足

分類とマーキングは MQC の 3 段を組み合わせる作業で、仮想機の制約や印の階層を取り違えると、効いていないのに効いたつもりになります。本節の実機に関わる注意点をまとめます。

マーキングの証拠は show カウンタでなく受信側の tcpdump。 本節の検証機は仮想の C9KV-UADP で、show policy-map interfaceQoS Set 行にマーキングの packet 数が付きません (§4)。分類 (match) のカウンタは増えるのに、マーキング (QoS Set) の数は出ない、という非対称が起きます。物理の Catalyst 9000 ではマーキングのカウンタも動きますが、「印がどう変わったかは受信側で観測する」 姿勢は実機でも確実です。set が効いたかどうかを show のカウンタだけで断定しないのが安全です。

set cos は L2 の印なので L3 の tcpdump では見えない。 tcpdump で観察している ToS は IP ヘッダの DSCP (L3) です。set cos が書き込むのはイーサネットフレームの CoS (L2) で、しかも CoS はタグ付きフレームにしか乗りません。同一 VLAN のアクセスポート (untagged) では CoS タグ自体が付かないため、set cos の効果は tcpdump では確認できません (§5)。「マーキングしたのに tcpdump で変わらない」と焦る前に、それが L2 の印か L3 の印かを切り分けます。

table-map は入りの CoS が要る。 set dscp cos table は「入ってきた CoS」を見て DSCP へ写します。アクセスポート (untagged) では入りの CoS が常に 0 になるため、表は 0 か default を引くだけで、意味のある変換になりません (§6)。table-map はトランクや音声 VLAN 経由で CoS を持つ入力があって初めて効きます。

仮想機の NBAR2 は count が 0 のことがある。 構文と ip nbar protocol-discovery の起動が通っても、仮想の C9KV-UADP はソフトウェアデータプレーンで L7 の DPI を動かさないため、protocol-discovery の Total が 0 のままになります (§7)。これは NBAR2 が使えないという意味ではなく、物理 Catalyst 9000 では動きます。仮想機の識別ヒットの有無だけで NBAR2 の可否を判断しないのが正確です。

mls qos を探さない。 前節と同じく、Catalyst 3560/3750 の記憶で mls qos を打っても Catalyst 9000 では通りません (§3)。分類・マーキングはすべて class-map / policy-map / table-map で組みます。

最後に、本節で組んだ QoS 定義を running-config から抜き出すと次のようになります。分類段の class-map、マーキング段の policy-map、対応表の table-map が、記事で見てきた形でまとまっています。

snippet
SW1# show running-config | section class-map|policy-map|table-map
table-map COS-TO-DSCP
 map from 0 to 0
 map from 5 to 46
 map from 6 to 48
 default 0
class-map match-any CM-VOICE
 match dscp ef
class-map match-any CM-VIDEO
 match dscp af41
class-map match-all CM-SRC
 match access-group name PERMIT-PC1
class-map match-any CM-HTTP
 match protocol http
policy-map PM-MARK
 class CM-VOICE
  set dscp ef
 class CM-VIDEO
  set dscp af31
 class CM-SRC
  set cos 5
 class class-default
  set dscp default

9. 次節

本節では、分類とマーキングの作り込みを Cat9000v の実機で組み立てました。match dscp で 3 クラスに分類し (CM-VOICE/CM-VIDEO/class-default)、policy-map の set dscp でクラス別にマーキングして、その効果を受信側 PC2 の tcpdump の 3 分布 (VOICE=0xb8 維持 / VIDEO=0x88→0x68 格下げ / BE=0x00) で確かめました。分類基準を送信元 IP (match access-group) やアプリ (match protocol=NBAR2) へ広げる構文、クラス別 set と対比した table-map の一括写像も扱い、set cos や table-map・NBAR2 が仮想機・アクセスポートでどこまで観測できるかを show 出力の逐語で押さえました。

ここまでの 5-3・5-4 で、印を「信頼する / 付け直す」の判断と「クラス別にマーキングする」作り込みが揃いました。次節 5-5 Policing と Shaping では、印をつけたトラフィックを 帯域で制御する 段階に進みます。契約帯域を超えた分を捨てる (または再マーキングする) ポリシング (policing) と、超過分をいったんバッファに溜めて平準化するシェーピング (shaping) の違いを、実機で見ていきましょう。