レイヤ2の「格差社会」を読み解く:802.1PとPCPで実現するQoSの最前線
ネットワークエンジニアとして現場を歩いていると、「なぜか特定のトラフィックだけ遅延する」「重要なAPIのレスポンスが、バックグラウンドのログ転送に押し出されている」といった相談をよく受けます。
多くのエンジニアは、まず ping を打ち、次にルーティングテーブルを確認し、L4以上のアプリケーション層を疑います。しかし、真の「パケットの渋滞」は、多くの場合、L2のスイッチ内部でひっそりと発生しているのです。
今回は、イーサネットフレームの深淵に潜む 802.1P(PCP)という、L2レベルの「VIPパス」について、泥臭い現場の知見を交えて解説します。
—
1. そもそも802.1Pとは何か?なぜ必要なのか
イーサネットの基本思想は「ベストエフォート」です。届いた順に処理し、溢れたら捨てる。これがL2の鉄則です。しかし、VoIPやリアルタイム性の高いWeb APIの通信において、この「平等」は時に致命的な遅延を生みます。
ここで登場するのが IEEE 802.1Q タグ内に含まれる PCP(Priority Code Point)フィールドです。いわゆる 802.1P と呼ばれる技術は、この3ビットのフィールドを使って、フレームに「優先度」という名のラベルを貼る仕組みを指します。
優先順位の定義(IEEE 802.1Q/P)
3ビットで表現できるのは0〜7の計8段階。値が大きいほど優先度は高くなります。
- 7 (Network Control): ネットワーク制御用(ルーティングプロトコル等)
- 6 (Internetwork Control): インターネットワーク制御
- 5 (Voice): 10ms未満の低遅延が求められる音声
- 4 (Video): 100ms未満の低遅延が求められる動画
- 3 (Critical Applications): ミッションクリティカルなデータ
- 2 (Excellent Effort): 優先すべきデータ
- 0 (Best Effort): デフォルト(未設定時の扱い)
- 1 (Background): バックグラウンド通信(ログ転送、バックアップ等)
—
2. パケットはどう流れるのか:QoSのシーケンス
スイッチに入力されたフレームがどのように処理されるか、その裏側を追ってみましょう。
1. Ingress(受信): スイッチがフレームを受信。802.1Q タグを確認し、PCP フィールドを読み取る。
2. Mapping(マッピング): スイッチ内部の CoS-to-Queue マッピングテーブルを参照。PCP 値(0-7)が、スイッチ内部のどのハードウェアキュー(例: 0-3など)に割り当てられるかを決定。
3. Scheduling(スケジューリング): 各キューには「優先度の高いキューから先に送出する(Strict Priority)」や「帯域を何%ずつ割り振る(WRR: Weighted Round Robin)」といったルールが適用される。
4. Egress(送信): 優先度の高いキューにあるフレームが先に物理ポートから送り出される。
この仕組みを理解していないと、「スイッチの設定でQoSを入れたのに効果がない!」と悩むことになります。なぜなら、端末側が PCP を付与して送ってこない限り、スイッチはデフォルトの「0」としてしか扱わないからです。
—
3. 実践:インフラ設定とトラフィックの制御
では、実務でどのようにこの仕組みを扱うのか、一般的なL2/L3スイッチ(Cisco Catalyst想定)のコマンド例を見てみましょう。
スイッチ側:CoSマッピングの設定例
受信したフレームの PCP 値に応じて、内部のどのキューに振り分けるかを定義します。
! PCP値5(Voice)を、優先度の高いキュー3へマッピングする設定
mls qos map cos-dscp 0 8 16 24 32 40 48 56
! 上記はCOS値からDSCPへの変換テーブル(現場の標準的な定義)
! インターフェース単位で信頼する設定(これがないとタグは無視される)
interface GigabitEthernet1/0/1
description API_SERVER_LINK
mls qos trust cos ! 受信したタグのCoS値を信頼してキューに割り当てる
アプリケーション側:ソケットでのDSCP/CoS付与
APIサーバー側で自ら PCP を制御するのはOSの権限が必要ですが、多くのLinux環境では setsockopt を用いて、L3の DSCP(DiffServ Code Point)値を設定します。スイッチ側でDSCPとCoSをマッピングさせるのが実務上の定石です。
Pythonで DSCP 値(例: EF=46)をセットするスニペットを以下に示します。
import socket
# ソケットを作成
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# DSCP値(EF: Expedited Forwarding = 46)をセット
# IP_TOSはIPヘッダーのType of Serviceフィールド
# 46 << 2 = 184
dscp_val = 46 << 2
s.setsockopt(socket.IPPROTO_IP, socket.IP_TOS, dscp_val)
# これにより、このソケットから送信される全パケットのIPヘッダーに
# 優先度が刻印され、スイッチのQoS設定を経て優先処理される
s.connect(("api.example.com", 443))
—
4. 現場のトラブルシューティングTips
最後に、シニアエンジニアからのアドバイスを一つ。
「タグが剥がされていないか?」 を必ず疑ってください。
多くのサーバーや仮想スイッチは、OSからネットワークカードにパケットを渡す過程で 802.1Q タグを剥がしてしまうことがあります。パケットキャプチャツール(tcpdump や Wireshark)を叩いた際に、VLAN tag が見えない場合は、NICのオフロード設定やドライバーの仕様を疑う必要があります。
- デバッグ手順:
1. tcpdump -i eth0 -vv でタグ情報が含まれているか確認。
2. スイッチ側で show interface counters errors を叩き、ドロップが特定のキューで発生していないか確認。
3. sh mls qos interface [IF] statistics で、実際にどの優先度のキューにパケットが振り分けられているかカウンタを追う。
技術は教科書通りには動きません。しかし、パケットの「刻印」がどこで消え、どこで読み取られているかを正確に把握できれば、どんな不可解な遅延も必ず解明できます。
皆さんのネットワークが、今日も最適化されたパケットで満たされますように。
コメント