秒単位の遅延すら許されない現場へ:RSTP(IEEE 802.1w)のProposal/Agreementメカニズムを完全理解する
ネットワークエンジニアの皆さん、こんにちは。日々のインフラ運用や設計、本当にお疲れ様です。Web APIがミリ秒単位の応答速度を競い合う現代において、ネットワークの基盤を支えるレイヤー2の世界でも「スピード」は絶対正義です。
皆さんは、L2ループを防ぐために長年愛されてきたSTP(Spanning Tree Protocol / IEEE 802.1d)のコンバージェンス(収束)を待たされて、冷や汗をかいた経験はないでしょうか。「リンク障害が起きたのに、通信が復旧するまでに30秒〜50秒もかかる……その間に監視アラートが鳴り響き、関係各所からチャットが飛んでくる」。あの胃が痛くなるような待ち時間は、もう過去のものです。
今回は、その旧来のSTPの呪縛を完全に打ち破り、ミリ秒単位での高速収束を実現する RSTP(Rapid Spanning Tree Protocol / IEEE 802.1w)、特にその心臓部である Proposal/Agreement(提案/同意)ハンドシェイク の挙動について、実務の現場で役立つ知見を交えて徹底解説します。
—
1. なぜ従来のSTPは遅かったのか?(おさらい)
IEEE 802.1dの伝統的なSTPが遅い最大の理由は、「タイマー依存の受動的なメカニズム」だからです。
障害やトポロジー変更が発生した際、STPは「他のスイッチからのトポロジー変更通知(TCN)を待つ」「ListeningからLearningへ移行するのに各15秒(合計30秒)のForward Delayタイマーを待つ」という仕様になっていました。つまり、ネットワーク自身が「今、道が安全か?」を確認するために、ひたすらタイマーが満了するのをボーッと待っていたのです。これでは、現代の冗長化されたデータセンターやキャンパスネットワークの要件を満たせないのは明白です。
この課題を根本から解決するために策定されたのが IEEE 802.1w(現在はIEEE 802.1D-2004に統合)であり、その核心こそが RSTP です。
—
2. RSTPの真髄:Proposal/Agreement(P/A)ハンドシェイクの全貌
RSTPが圧倒的に速い(通常1秒未満で収束する)理由は、タイマーに頼るのをやめ、スイッチ間の「能動的なネゴシエーション(対話)」に切り替えたからです。
従来のSTPが「私はこう思うのですが……(タイマー待ち)」だったのに対し、RSTPは「新しいルートポートにするから、そっちのポートはブロックして即座に返事してくれ!(Proposal)」「了解、こちらをブロックした(Agreement)」というダイレクトなやり取りを行います。
01. ポート役割(Port Roles)の再定義
RSTPでは、ポートの役割が以下のように整理されました。
- Root Port (RP): ルートブリッジに向かう最適パスのポート
- Designated Port (DP): セグメントに対してフレームを送出する(ルートに向かう)ポート
- Alternative Port (AP): ルートポートのバックアップ(次善のルート)。従来のNon-Designated Portに相当し、即座に切り替え可能(Backup Portを含む)
02. P/Aハンドシェイクのステップ・バイ・ステップ
リンクアップ時や障害発生時、隣接するスイッチ間で以下のような電撃的なハンドシェイクが実行されます。
1. Proposal(提案)の送信
新しいリンクが確立すると、双方が自分のポートを Designated かつ Discarding(破棄)状態にした上で、相手に対して Proposal フラグが立ったBPDUを送信します。
2. 同期(Synchronization)の実行
Proposal を受信したスイッチは、「おっ、ここが新しいルートへのパスだな」と判断します。しかし、ループを防ぐために、自分自身の下流にある他のすべての「エッジポート以外のポート」を一時的に Discarding 状態(同期状態)にします。これにより、ネットワーク全体の整合性が一瞬で保たれます。
3. Agreement(同意)の返信
同期が完了すると、受信側スイッチは元のポートを Root Port に昇格させ、相手に向けて Agreement フラグが立ったBPDUを返します。
4. 即座のForwarding移行
Agreement を受け取った側は、タイマーを待つことなく、そのポートを即座に Forwarding 状態へと移行させます。
この一連の連鎖が、トポロジーの末端からルートに向かって「ドミノ倒し」のように一瞬で伝播するため、ネットワーク全体が数秒(場合によっては1秒未満)でコンバージェンスするのです。
—
3. 実務で直面する罠:RSTPが高速化しないケース
「よし、スイッチ全部でRSTPを有効にしたぞ!」と意気込んでも、実務では期待通りに高速収束しないトラブルに遭遇することがあります。シニアエンジニアとして、現場でよくあるハマりどころをいくつか共有しておきます。
罠1: レガシーなCisco 802.1D(PVST+など)との混在
もし接続先の対向機器が旧来のSTPで動作している場合、RSTPは自動的に下位互換モード(STP Compatibility Mode)にフォールバックします。この状態ではP/Aハンドシェイクが無効化され、結局あの懐かしい30秒のタイマー待ちに戻ってしまいます。設計時は必ず全ノードがRSTP(またはRapid PVST+)をサポートしていることを確認しましょう。
罠2: エッジポート(Portfast)の切り忘れ
エンドデバイス(サーバーのNICや仮想マシンのハイパーバイザー、アクセスポイントなど)が接続されるポートにRSTPのProposal/Agreementを走らせようとすると、接続のたびに無駄なトポロジー計算が発生します。
Cisco環境であれば spanning-port edge(旧 PortFast)、他社製L2スイッチであれば Edge Port の設定を必ず有効にしてください。これにより、ポートはリンクアップと同時に即座に Forwarding になり、P/Aプロセスの対象外となります。
—
4. 設定実例:実務で使えるスイッチ設定サンプル
ここでは、実務で最も遭遇する確率が高いCisco Catalyst(IOS)および現代的なLinuxベースのネットワーク環境(L2スイッチ代わりのブリッジ設定)を想定した設定・確認方法のサンプルを示します。
Cisco IOS / IOS-XE での設定例
Cisco環境でRSTP(厳密にはVLANごとのRapid PVST+)を有効にし、エッジポートを適切に設定する標準的なコンフィグです。
! グローバルコンフィギュレーションモード
spanning-tree mode rapid-pvst
!
! デフォルトで接続されるエンドデバイス向けポートにPortfast(RSTP Edge Port)を適用
spanning-tree portfast default
spanning-tree portfast bpduguard default ! 予期せぬBPDUを受信した際にポートをerr-disableにする安全策
!
! アップリンク側のスイッチ間ポート設定
interface GigabitEthernet0/1
description === Uplink to Core Switch ===
switchport mode trunk
no shutdown
!
! エンドデバイス(サーバー等)接続ポートの設定
interface GigabitEthernet0/24
description === Connection to Web API Server ===
switchport mode access
switchport access vlan 100
no shutdown
動作確認とデバッグコマンド
障害試験や切り戻し検証の際、P/Aが正しく機能しているか、あるいはループが発生していないかをCLIで確認する定番コマンドです。
! 特定のVLANにおけるRSTPのステータスと、ポートの役割(Root/Desg/Altn)を確認
show spanning-tree vlan 100
! 出力例の読み方:
! Port Role Sts Cost Prio.Nbr Type
! Fa0/1 Desg FWD 4 128.1 P2p <-- Point-to-Pointで高速収束中
! Gi0/1 Root FWD 4 128.257 P2p <-- 正常なルートポート
! RSTPの詳細なデバッグ(※本番環境での多用はCPU負荷に注意)
debug spanning-tree bpdu transmit
debug spanning-tree bpdu receive
—
5. ネットワーク自動化・監視への応用(Pythonによる状態監視のススメ)
インフラ運用において、「STPのトポロジー変更(TCN)が頻発していないか」をモニタリングすることは、物理レイヤーやケーブルの品質不良(フラッピング)を検知する上で極めて重要です。
ここでは、ネットワーク機器のAPIやSNMP、あるいはSSH経由でスパニングツリーのステータス変化をPython(Netmiko等)で定期チェックする簡易的なスクリプトの概念コードを紹介します。実務では、こうしたスクリプトをZabbixやPrometheus(Exporters)と組み合わせてメトリクス化します。
import time
from netmiko import ConnectHandler
def check_rstp_status(device_ip, username, password):
"""
CiscoスイッチにSSH接続し、スパニングツリーのトポロジー変更カウンタをチェックする関数
"""
cisco_device = {
'device_type': 'cisco_ios',
'ip': device_ip,
'username': username,
'password': password,
}
try:
# 機器へのセッション確立
net_connect = ConnectHandler(**cisco_device)
print(f"Connected successfully to {device_ip}")
# スパニングツリーのサマリー情報を取得
output = net_connect.send_command("show spanning-tree summary")
# 簡易的な解析(実際にはパースライブラリやTextFSMを使用することを推奨)
if "is executing the rstp compatible" in output:
print("[INFO] RSTP mode is active.")
else:
print("[WARN] RSTP might not be fully active or fallback to legacy STP.")
print("\n--- Spanning-Tree Summary ---")
print(output)
net_connect.disconnect()
except Exception as e:
print(f"[ERROR] Failed to connect or execute command: {e}")
if __name__ == "__main__":
# テスト用のダミーIPと資格情報
TARGET_SWITCH = "192.168.10.1"
USER = "admin"
PASS = "secret_password"
# 定期実行のループ(実運用ではモニタリングツールへ組み込みます)
check_rstp_status(TARGET_SWITCH, USER, PASS)
—
まとめ:高速なL2基盤が信頼性の高いWebシステムを支える
RSTPのProposal/Agreementメカニズムは、単なる「STPの高速版」という枠を超え、現代の冗長化されたインフラにおいて「一瞬の障害を無かったことにする」ための極めて洗練されたアルゴリズムです。
L3以上のルーティングプロトコル(BGPやOSPF)の高速化ばかりに目が行きがちですが、その足元を支えるL2スイッチングの挙動、そしてRSTPの背後にあるP/Aハンドシェイクの理屈を深く理解しておくことは、シニアなインフラエンジニアにとって必須の素養です。
現場でL2の切り替わり遅延や思わぬトラフィックドロップに直面したときは、ぜひ今回の記事を思い出し、BPDUのキャプチャやポートステータス(Discarding/Forwarding)の遷移を冷静に追ってみてください。確実な技術的知識があれば、どんな障害も必ずロジカルに解決できます。
それでは、また次の深淵なネットワークの世界でお会いしましょう!
コメント