TPIDの深淵:802.1QタグフレームとVLANの裏側で何が起きているのか
ネットワークエンジニアとして現場を渡り歩いていると、Webアプリケーションの開発者から「なぜVLAN IDが変わるとAPIのレスポンスが遅延するのか」や、「パケットキャプチャ(Wireshark)を見ると見慣れないEtherTypeが並んでいるがこれは何なのだろうか」という質問をよく受ける。
Web APIの設計やクラウドのオーバーレイネットワーク(VXLANやGeneveなど)の構築において、私たちは普段、レイヤー4以上のトランスポート層やレイヤー7のアプリケーション層に意識を奪われがちだ。しかし、データセンターの足回りでパケットをカプセル化し、ルーティングし、時にはQ-in-Q(IEEE 802.1ad)でトンネリングしているのは、他ならぬレイヤー2のフレーム構造、その中でも先頭に鎮座する小さな16ビットの番人、TPID(Tag Protocol Identifier)に他ならない。
今回は、IEEE 802.1Qタグフレームの構造とTPIDの正体に焦点を当て、パケットがスイッチのASICを通過する際のリアルな挙動から、実務の現場で役立つデバッグ手法までを紐解いていこう。
—
1. イーサネットフレームの拡張とIEEE 802.1Qの基本構造
まずは、私たちが日常的に扱う標準的なイーサネットフレーム(Ethernet II)と、VLANタグが挿入された802.1Qフレームの物理的な違いをおさらいする。
標準的なEthernet IIフレームは、宛先MACアドレス(6バイト)、送信元MACアドレス(6バイト)、そしてEtherType(2バイト)または長さを表すフィールドから始まり、その後にペイロード(最大1500バイトのIPパケットなど)とFCS(4バイト)が続く。
ここにVLAN(Virtual LAN)の概念を持ち込むとき、IEEE 802.1Q規格は送信元MACアドレスの直後に、4バイト(32ビット)のタグヘッダーを挿入(インサート)するというアプローチをとった。これにより、既存のNICやスイッチのハードウェア設計を大きく変更することなく、仮想ネットワークの識別子(VLAN ID)をフレームに同居させることが可能になったのだ。
この4バイトの内訳は以下のようになる。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Destination MAC Address (6 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source MAC Address (6 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| TPID (16 bits) | TCI: PCP+DEI+VLAN ID (16 bits)|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Original EtherType / Length (2 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Payload (IP Packet, TCP Segment, etc.) |
| ... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| FCS (Frame Check Sequence) (4 bytes) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
この4バイトのタグ領域の後半16ビットは、TCI(Tag Control Information)と呼ばれ、以下の要素に分割されている。
- PCP (Priority Code Point – 3ビット): 8段階のCoS(Class of Service)を指定し、QoS(Quality of Service)の優先制御に用いる。
- DEI (Drop Eligible Indicator – 1ビット): 旧CFI(Canonical Format Indicator)。輻輳時に優先的に破棄してよいフレームかを示す。
- VLAN ID (12ビット): 0から4095までのVLAN識別子。0と4095は予約済みのため、実際に使用できるのは1〜4094。
—
2. 主役の「TPID」とは何か? なぜ0x8100なのか
そして、今回主役として取り上げる前半16ビットが TPID(Tag Protocol Identifier) である。標準的な802.1Qタグ付きフレームでは、この値は必ずヘキサデシマルで 0x8100 に設定される。
なぜこの値なのか?
イーサネットの歴史において、EtherTypeフィールド(通常は0x0800のIPv4などが入る位置)の値が 0x05DC(1500)未満であれば「フレームの長さを表す」、それ以上であれば「上位プロトコルの種類(EtherType)を表す」という暗黙のルール(IEEE 802.3)があった。
スイッチのASICやネットワークカードのドライバは、受信したフレームの送信元MACアドレスの直後にある2バイトを覗き見たとき、そこに 0x8100 という値を発見すると、「おっと、これは普通のIPパケットではなく、IEEE 802.1QのVLANタグ付きフレームだぞ。次の2バイトはTCIで、その次が本来のEtherTypeだな」と即座に認識し、パケットのパーシング方法を切り替える。つまり、TPIDはパケットの解釈を切り替えるためのマジックナンバーなのだ。
Q-in-Q(IEEE 802.1ad)とTPIDの拡張
実務の現場、特に通信キャリアや大規模データセンターのマルチテナント環境では、顧客ごとにVLAN IDを割り振るために「VLANの中にさらにVLANを包み込む」Qニ重化(Q-in-Q / IEEE 802.1ad)という技術が使われる。
この場合、外側のタグと内側のタグを区別する必要があるため、外側タグのTPIDには標準の 0x8100 ではなく、プロバイダ独自あるいは規格で定められた 0x88A8 や、シスコ独自のプロプライエタリな環境では 0x9100 などが使用されることがある。
もしスイッチ側でこのTPIDの設定(ether-type や tpid コマンド)がミスマッチを起こしていると、タグが正しく剥がされなかったり、パケットが不正なものとして破棄(ドロップ)されたりする原因になるため、キャリア回線やデータセンター間接続(DCI)を設計・運用する際には必ずチェックすべきポイントとなる。
—
3. スイッチングとパケット処理の舞台裏
ここで、トランクポートを通過するパケットのライフサイクルを追ってみよう。
1. タグの挿入(Tagging / Push):
アクセスポートからパケットを受信したスイッチは、そのポートに割り当てられたネイティブVLANまたはアクセスVLANの情報を元に、MACアドレスの直後に 0x8100 のTPIDとVLAN IDを含む4バイトのタグを挿入する。
2. トランク転送(Transit):
コアスイッチ間を結ぶトランクリンクを、タグ付きフレームが高速に流れていく。このとき、MTU(Maximum Transmission Unit)のサイズに注意が必要である。通常のEthernetフレームは1500バイトだが、4バイトのタグが追加されることでフレーム長は1504バイトになる。もし経路上のジャンボフレーム(Jumbo Frame)の設定が有効になっていない古い機器があると、この「たった4バイトのオーバーヘッド」が原因でフラグメントやパケットロスを引き起こすことがある。
3. タグの剥離(Untagging / Pop):
宛先のアクセスポートに到達する直前で、スイッチはタグを綺麗に剥ぎ取り、元の綺麗なEthernet IIフレームに戻してエンド端末(サーバーやPC)へと送り出す。エンド端末のOS(LinuxやWindows)は、基本的にVLANタグが剥ぎ取られた状態でパケットを受け取るため、アプリーケーション層やOSのネットワークスタックはVLANの存在を意識せずに通信できる(※サーバー側でチーミングやVLANインターフェースを切っている場合を除く)。
—
4. 実務で役立つ設定例とトラブルシューティングTips
ここからは、実務のインフラ構築や、コンテナ・仮想化環境のネットワーク設定において、IEEE 802.1QタグやTPIDを意識するべき具体的な場面をコードや設定例を交えて解説する。
4.1. Linux(iproute2)でのVLANインターフェース作成
ベアメタルサーバーやハイパーバイザー(KVMなど)の上で複数のVLANを終端する場合、Linuxカーネルに対して「どのTPIDとVLAN IDでパケットを処理するか」を明示的に指示する必要がある。
以下のPythonスクリプトやBashスクリプトを実行する前提として、Linux上でVLANサブインターフェースを作成するコマンドを確認しておこう。
# 物理インターフェース eth0 に対し、VLAN ID 100 のサブインターフェース (eth0.100) を作成する
sudo ip link add link eth0 name eth0.100 type vlan id 100
# 作成したVLANインターフェースにIPアドレスを割り当てる
sudo ip addr add 192.168.100.10/24 dev eth0.100
# インターフェースをアップさせる
sudo ip link set dev eth0.100 up
このとき、Linuxのネットワークスタックは内部的に 0x8100 のTPIDを持つフレームを認識し、カーネル空間でVLANタグの付与・剥離を行っている。
4.2. Pythonを用いたパケット解析(Scapyによる802.1Qフレームの構築)
ネットワークのテストツールや自動化スクリプトを書く際、Pythonの強力なパケット操作ライブラリである Scapy を使うと、802.1Qタグ付きフレームを自在に生成・送信できる。以下に、TPIDとVLAN IDを明示的に指定したパケットを構築するサンプルコードを示す。
from scapy.all import Ether, Dot1Q, IP, TCP, sendp
def send_tagged_packet():
"""
IEEE 802.1Q タグ(TPID: 0x8100, VLAN ID: 20)を持つカスタムパケットを構築し、
指定した物理インターフェースから送出するサンプルコード。
"""
# イーサネットヘッダー(宛先および送信元MACアドレス)
eth = Ether(dst="00:11:22:33:44:55", src="66:55:44:33:22:11")
# 802.1Q タグレイヤー
# type=0x8100 (デフォルト), prio=0 (優先度なし), id=0 (CFI/DEI), vlan=20 (VLAN ID)
dot1q = Dot1Q(vlan=20, prio=0, type=0x0800) # 次のペイロードはIPv4 (0x0800)
# IP層およびTCP層の構築
ip = IP(src="10.0.20.10", dst="10.0.20.254")
tcp = TCP(sport=54321, dport=80, flags="S")
# フレーム全体の結合(Ethernet -> 802.1Q -> IP -> TCP)
# ※実際のネットワークカードから送出する場合、Scapyが自動的にEtherのtypeを0x8100に書き換える
packet = eth / dot1q / ip / tcp
print("[*] 送信予定のパケット構造:")
packet.show()
# 実際の物理インターフェース(例: eth0)からレイヤー2で送出
# 注意: 実行にはroot権限が必要です
try:
sendp(packet, iface="eth0", verbose=False)
print("[+] 802.1Qタグ付きパケットの送信に成功しました。")
except Exception as e:
print(fmt_error := f"[-] パケットの送信に失敗しました: {e}")
if __name__ == "__main__":
send_tagged_packet()
4.3. ネットワーク機器(Cisco IOS-XE / Cisco NX-OS)でのトランク設定とTPID確認
データセンターのスイッチ側では、アップリンクやサーバーとの接続ポートでトランクモードを有効にする。以下はCiscoスイッチでの基本的な設定例である。
! 物理インターフェースをトランクポートとして設定し、許可するVLANを指定する
interface GigabitEthernet0/1
description === Connection to Server Hypervisor ===
switchport trunk encapsulation dot1q
switchport mode trunk
switchport trunk allowed vlan 10,20,30,100
spanning-tree portfast trunk
!
! もしQ-in-Q環境などでカスタムTPID(例: 0x88A8)を受け入れる必要がある場合のコマンド例
! service provider環境でよく使われます
! ethernet-tag-protocol-type 0x88a8
4.4. 現場のトラブルシューティング:パケットキャプチャの読み方
「VLAN間ルーティングがおかしい」「特定のサーバーだけ通信できない」という現場のトラブルに直面したとき、私たちは必ず tcpdump や Wireshark でパケットをキャプチャする。
ここで初心者がハマりやすい罠がある。
通常、OSの標準的なインターフェース(例: eth0)で tcpdump -i eth0 を実行すると、NICのドライバやOSの仕様によっては、既にVLANタグが剥ぎ取られた状態のパケットが表示される。そのため、「あれ?パケットに802.1Qのタグが付いていないぞ?」と誤認してしまうことがあるのだ。
もしタグを含めた生のフレーム構造を確認したい場合は、Linuxの仮想パケットキャプチャデバイスである any を指定するか、VLANタグを保持したままキャプチャできる環境(あるいはスイッチのSPANポート)を利用する必要がある。
# すべてのインターフェースを対象に、タグ情報も含めて低レイヤーのパケットをダンプする
sudo tcpdump -nnvvS -i any vlan
このコマンドを実行すると、出力結果の中に .vlan(20) や ethertype 802.1Q (0x8100) といった文字列が現れ、TPIDが正しく付与されているかをリアルタイムで確認できる。
—
まとめ
IEEE 802.1QタグフレームとTPIDは、普段私たちが触れるWebアプリケーションやAPIのコードからは何層も下、OSのカーネルやスイッチのシリコンチップのレベルで黙々と働き続けている縁の下の力持ちだ。
しかし、ネットワークのパフォーマンス低下、MTU超過によるパケットドロップ、あるいはマルチテナント環境でのVLANリークといった泥臭いトラブルに直面したとき、パケットの先頭16ビット(TPID)や4バイトのタグ構造を頭に思い描けるかどうかが、プロのインフラエンジニアとしての分水嶺となる。
今回の解説が、日々のインフラ運用や、より堅牢なネットワーク・API設計を行う上での確かな羅針盤となれば幸いである。
コメント