こんにちは、ネットワークエンジニアの皆さん。日々のインフラ運用や、クラウド全盛期とはいえ避けて通れない物理・L2レイヤーの設計、本当にお疲れ様です。
Web APIの設計やモダンなアプリケーション開発にどれほど習熟していようとも、基盤を支えるスイッチが「ループ」という名の悪魔に憑りつかれた瞬間、システム全体が沈黙する――そんな冷や汗モノのトラブルを、現場で一度は経験したことがあるのではないでしょうか。
今回は、そんなL2ループを防ぐための守護神、STP(Spanning Tree Protocol / IEEE 802.1D)を取り上げます。中でも、スイッチのポートが物理的に接続されてから実際にトラフィックを転送し始めるまでの「ポート状態遷移(Disabled, Blocking, Listening, Learning, Forwarding)」と、その裏で刻々と刻まれるタイマーの挙動にスポットを当てます。
教科書的な丸暗記はもう終わりです。パケットがスイッチのASIC内部でどう処理され、なぜあの「まどろこしい待ち時間」が必要なのか、シニアの視点から泥臭く、かつ深く紐解いていきましょう。
—
1. なぜSTPのポート遷移には「時間がかかる」のか?
現代の高速なネットワークにおいて、ポートを有効化(no shutdown)してから実際に通信可能になるまで、標準の802.1Dでは最大50秒もの時間がかかります。「たかがL2の接続に50秒も待たされるなんて、クラウドネイティブのスピード感に反する!」と思われるかもしれません。
しかし、これには明確な理由があります。STPの目的は「トポロジーの収束(Convergence)」です。
ネットワーク全体で「唯一無二の木構造(Spanning Tree)」が合意される前に、見切り発車でトラフィックの転送(Forwarding)を許可してしまうと、瞬く間にブロードキャストストームが発生し、数秒でネットワーク全体がメルトダウンします。
あの長い待ち時間は、スイッチたちが「おい、俺たちのトポロジーにループはないか?」「ルートブリッジはあいつで間違いないな?」と、BPDU(Bridge Protocol Data Unit)という名の信書を交わし、慎重に合意形成を行っている厳粛なプロセスなのです。
—
2. 5つのポート状態遷移とデータ処理の裏側
IEEE 802.1Dにおいて、STP有効時のポートは以下の5つのステートを厳密に渡り歩きます。それぞれの状態でASICやCPUが何をしているのか、データプレーンとコントロールプレーンの挙動を覗いてみましょう。
[Port Up]
↓
Disabled (ディスエーブルド)
↓ (管理上有効化 / link up)
Blocking (ブロッキング) ──(Max Age超過/BPDUロスト)──> [トポロジー変化]
↓ (ルート/指定ポート選出)
Listening (リスニング)
↓ (Forward Delay経過: 15秒)
Learning (ラーニング)
↓ (Forward Delay経過: 15秒)
Forwarding (フォワーディング)
① Disabled(無効)
- 概要: 管理的にシャットダウンされている(
shutdown状態)、または物理リンクがダウンしている状態です。 - データ処理: BPDUの送受信も、通常のデータフレームの転送も一切行いません。文字通り「眠っている」状態です。
② Blocking(ブロック)
- 概要: 物理リンクは確立したものの、ループを防ぐためにトラフィックの転送を禁じられた状態です(非指定ポート)。
- データ処理:
- 受信: BPDUを受信してトポロジーの変化を監視します。ただし、データフレームは破棄(Drop)します。
- 送信: BPDUの送信は行いません(ルートブリッジからのBPDUを受動的に待つのみ)。
- MACアドレステーブル: 学習は一切行いません。
③ Listening(リスニング)
- 概要: ルートポートまたは指定ポート(Designated Port)として選出され、「そろそろ転送状態に移行してもいいか?」と周囲の状況を確認し始める状態です。
- データ処理:
- 受信/送信: BPDUの送受信を行います。「自分はこの役割で参加する」という意思表示を周囲と交わします。
- データフレーム: 相変わらず転送(Forward)はしません。
- MACアドレステーブル: まだ学習しません。
- タイマーの役割: この状態に留まる時間が、後述する
Forward Delay(デフォルト15秒) の前半です。
④ Learning(ラーニング)
- 概要: トポロジーの安定が見えてきたため、実際にデータ転送を始める前の「準備運動」を行う状態です。
- データ処理:
- 受信/送信: 引き続きBPDUの送受信を行います。
- データフレーム: ユーザーデータの転送はまだ行いません(破棄します)。
- MACアドレステーブル: ここが重要です! 受信したフレームの送信元MACアドレス(Source MAC)を読み取り、MACアドレステーブルの構築(学習)だけを始めます。
- なぜこの状態が必要か?: いきなりフォワーディングを開始すると、MACアドレステーブルが空の状態であるため、すべてのユニキャストフレームがフラッディング(全ポート転送)されてしまい、一時的なトラフィックのスパイクを招きます。それを防ぐためのクッション期間です。
- タイマーの役割: この状態も
Forward Delay(15秒) の時間を費やします。
⑤ Forwarding(フォワーディング)
- 概要: すべての安全確認が完了し、完全に参加が許可された状態です。
- データ処理: BPDUの送受信を継続しながら、通常のデータフレームの送受信・転送、およびMACアドレスの動的学習を完全に許可します。
—
3. 運命を握る3つのSTPタイマーパラメータ
STPの収束速度や安定性は、以下の3つのタイマーパラメータによって支配されています。Cisco Catalystなどの実機でも、show spanning-treeコマンドで確認できる馴染み深い値です。
| パラメータ名 | デフォルト値 | 意味と役割 |
| :— | :— | :— |
| Hello Time | 2秒 | ルートブリッジがBPDUを送信する間隔。スイッチ間でお互いの生存(健常性)を確認する心拍数のようなものです。 |
| Max Age | 20秒 | スイッチが「ルートブリッジからのBPDU」を受信できなくなってから、トポロジーに障害(リンク断など)が発生したとみなすまでの最大保持時間。Hello Timeの10倍が推奨値です。 |
| Forward Delay | 15秒 | Listening状態、およびLearning状態のそれぞれに留まる時間。トポロジー変更時にループが確実に解消されるのを待つための猶予期間です。 |
50秒ルールの計算式
標準STPで障害が発生し、BlockingだったポートがForwardingに昇格するまでの最悪のシナリオを計算してみましょう。
1. ルートからのBPDUが途絶える:Max Age (20秒)
2. BlockingからListeningへ移行し、合意形成:Listening (15秒)
3. ListeningからLearningへ移行し、MAC学習:Learning (15秒)
合計:$20 + 15 + 15 = \mathbf{50秒}$
現代のWebサービスにおいて、冗長化されたパスの切り替わりに50秒かかるというのは、セッションタイムアウトやクライアント側のリトライ頻度を考慮すると、インシデントレベルのダウンタイムと言えます。
—
4. 実務で役立つ設定例とモダンな代替案
この「50秒の呪い」を打破するため、実務では標準STP(802.1D)をそのまま使うことは稀です。Cisco環境であれば PVST+ / Rapid PVST+ 、オープンスタンダードであれば RSTP (IEEE 802.1w) や MSTP (IEEE 802.1s) を用いるのが現代のインフラ運用の鉄則です。
ここでは、実務でよく使われるCisco IOSおよびLinux(Bridge)での設定・確認のアプローチを見ていきましょう。
実務設定例 1: Cisco CatalystでのRapid PVST+への移行
RSTP(Rapid STP)ベースの設定を行うことで、ポート状態遷移から不要なステート(Listeningなど)を削ぎ落とし、障害時の収束時間を数秒(通常1〜2秒)に短縮できます。
! グローバルコンフィグレーションモード
! STPのモードをRapid PVST+(802.1w互換)に変更する
spanning-tree mode rapid-pvst
! サーバやエンドPCが接続されるエッジポートには、即座にForwardingにする仕掛け(PortFast)を有効化する
! これにより、PC接続時の50秒待ちを完全にバイパスする
spanning-tree portfast default
spanning-tree portfast bpduguard default ! 万が一BPDUが飛んできたらポートをerr-disableにする安全装置
実務設定例 2: PythonとNetmikoを用いたスイッチのSTPステータス監視スクリプト
インフラ運用の現場では、「どのポートがBlockingになっていて、どのポートがトラフィックを通しているか」を定期的にチェックする自動化スクリプトが重宝します。Netmikoライブラリを用いた死活・状態確認のスニペットです。
from netmiko import ConnectHandler
import time
# 接続対象のスイッチ(L2/L3スイッチ)の認証情報
ios_device = {
'device_type': 'cisco_ios',
'ip': '192.168.10.254',
'username': 'admin',
'password': 'StrongPassword123!',
'secret': 'EnablePassword123!',
}
def check_stp_status(device_info):
print(f"Connecting to {device_info['ip']}...")
try:
net_connect = ConnectHandler(**device_info)
net_connect.enable()
# STPの詳細ステータスを取得するコマンドを実行
output = net_connect.send_command('show spanning-tree inconsistentports')
if not output.strip():
print("[INFO] 不整合なSTPポートや予期せぬブロックポートはありません。正常です。")
else:
print("[WARN] 異常なSTPステータスを検出しました!")
print(output)
# ここでSlackやWeb API経由でアラートを飛ばす処理を実装できます
net_connect.disconnect()
except Exception as e:
print(f"[ERROR] 接続またはコマンド実行に失敗しました: {e}")
if __name__ == "__main__":
check_stp_status(ios_device)
—
5. シニアからの現場Tips:トラブルシューティングの極意
最後に、現場でSTP関連の障害に遭遇した際の、実践的なデバッグアプローチをいくつか伝授します。
1. 「まずは show spanning-tree を隅々まで見ろ」
- 障害時に真っ先に見るべきは、自分が意図したスイッチが「Root Bridge(ルートブリッジ)」になっているかです。安価なディストリビューションスイッチや、ユーザーが勝手に持ち込んだ古いL2ハブが勝手に低いプライオリティを主張し、ルートブリッジを乗っ取ってしまう「STPハイジャック」は、現場あるあるの事故です。
2. ポートが BDRV や ALWN でブロックされ続ける場合
- 物理層の片方向障害(Unidirectional Link)を疑ってください。ケーブルの一方が壊れて送信はできるが受信できない場合、STPのBPDUが届かずにループや予期せぬブロッキングを引き起こします。Cisco環境なら UDLD (UniDirectional Link Detection) の有効化を検討しましょう。
3. クラウド環境(AWS/GCP等)や仮想化レイヤーとの違い
- クラウドのVPC内では、物理的なSTPは直接動きません(ハイパーバイザー側でL2ループが論理的に排除されているため)。しかし、オンプレミスとクラウドをL2延伸(VXLANやL2VPN)するようなハイブリッド構成では、オンプレ側のSTPの挙動がクラウド側の仮想スイッチやブリッジドメインに悪影響を及ぼすことがあります。延伸設計の際は、BPDUの透過・ドロップの設計を慎重に行ってください。
—
まとめ
STPのポート状態遷移(Disabled $\rightarrow$ Blocking $\rightarrow$ Listening $\rightarrow$ Learning $\rightarrow$ Forwarding)は、一見すると地味で、現代の高速なネットワークにおいては足枷のように思えるかもしれません。しかし、その裏では、パケットの無限ループというネットワークの致命傷を防ぐために、スイッチたちが綿密な対話と計算を繰り返しています。
プロトコルの基本原理を解像度高く理解しているかどうかが、いざという時の大規模障害シューティングにおける「勘と経験」の鋭さを大きく左右します。
今回の解説が、皆さんの日々のインフラ設計や、トラブルに立ち向かう際の強力な武器となれば幸いです。それでは、また次回の深淵なるプロトコルの世界でお会いしましょう!
コメント