【実務・中級編】 STPブリッジID(Bridge ID)の構造とルートブリッジ選出アルゴリズム – インフラ・物理&L2/L3ネットワーク基礎実践ガイド

STPの心臓部を暴く:ブリッジIDの構造とルートブリッジ選出の全貌

こんにちは。ネットワークの現場で幾度となくレイヤ2ループによる全館通信断の阿鼻叫喚を鎮めてきた、シニアネットワークエンジニアの私だ。

モダンなWebアプリケーション開発やAPI設計に携わるエンジニアからすれば、「L2のループ防止? STPなんてスイッチが勝手にやってくれる黒魔術だろ?」と思うかもしれない。しかし、クラウドネイティブな環境であっても、オンプレミスとのハイブリッド接続、あるいはコンテナ基盤を支える物理・仮想ネットワークの足回りでは、このSpanning Tree Protocol(STP)の挙動がシステムの生死を分ける。

今回は、STPの根幹をなす「ブリッジID(Bridge ID)」の構造と、それがネットワーク全体の命運を握る「ルートブリッジ選出アルゴリズム」について、パケットの挙動から現場のトラブルシューティングまで徹底的に解説しよう。

—

1. なぜSTPが必要なのか、そして誰が王を決めるのか

レイヤ2スイッチングの基本は「フラッディングと学習」だ。しかし、冗長性を確保するためにスイッチ同士を複数本のケーブルで物理的に接続(ループを形成)すると、ブロードキャストフレームが無限ループを描き、わずか数秒でネットワーク帯域を食い尽くし、CPU使用率が100%に張り付いてスイッチが沈黙する。この悪夢を防ぐのがSTP(IEEE 802.1D)だ。

STPは、冗長パスの中から「論理的な木構造(スパンニング・ツリー)」を計算し、一部のポートをブロックすることでループを断つ。そのすべての計算の起点、すなわち「ネットワーク全体の中心(根=ルート)」となるのがルートブリッジ(Root Bridge)である。

このルートブリッジを自動的、かつ一意に決定するために使われるのが、各スイッチが持つブリッジID(Bridge ID: BID)なのだ。

—

2. ブリッジID(BID)の解剖学:8バイトの身分証明書

ブリッジIDは合計8バイト(64ビット)で構成されるデータ構造であり、IEEE 802.1Dの世界におけるスイッチの「戸籍謄本」のようなものだ。

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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|       ブリッジ・プライオリティ (16 bits)      |        拡張システムID (12 bits ※PVST+の場合)       |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
+                     ベースMACアドレス (48 bits)               +
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

この8バイトは、大きく2つのフィールドに分かれている。

1. ブリッジ・プライオリティ(Bridge Priority:16ビット)

  • スイッチの「偉さ」を示す値。デフォルトは通常 32768(0x8000)。
  • 4096の倍数で変更可能(0, 4096, 8192 … 61440)。
  • 値が小さいほど優先度が高い(=偉い)。

2. ベースMACアドレス(Base MAC Address:48ビット)

  • スイッチが持つ固有のMACアドレス(バックプレーンや特定のマネジメントポートのMAC)。

拡張システムID(Extended System ID)の罠

Cisco等のモダンなスイッチでVLANごとのSTPインスタンス(PVST+やRapid-PVST+)を動かす場合、16ビットのプライオリティ領域は次のように分割される。

  • プライオリティ(4ビット): 上位4ビット。4096刻みで指定する値がここに入る。
  • 拡張システムID(12ビット): 下位12ビット。ここにVLAN番号(VLAN ID)が自動的に付算される。

例えば、VLAN 10でプライオリティをデフォルト(32768)のままにしていると、実際のBIDのプライオリティフィールドは 32768 + 10 = 32778 として扱われる。この仕様を知らないと、「設定したはずのプライオリティと実際のBIDが微妙に違うぞ?」と現場で首を傾げることになるので注意が必要だ。

—

3. ルートブリッジ選出アルゴリズム:勝者は誰だ?

ネットワーク上のすべてのスイッチは、起動直後、自分がルートブリッジであると信じ込み、自分自身のBIDを送信元とするConfiguration BPDU(Bridge Protocol Data Unit)をすべてのポートから送出する。

BPDUが行き交う中で、スイッチは以下の比較ルール(STPパスコストとBIDの比較プロセス)に従って「より優れた情報」を受け入れる。

比較の優先順位(最重要)

1. 最小のルートBID(Lowest Root BID):
自分が知っている中で、最もプライオリティが高く(値が小さく)、MACアドレスが若いスイッチを「ルート」として認める。
2. 最小のパスコスト(Lowest Root Path Cost):
そのルートブリッジに至るまでのトータルのコスト(リンク速度に基づく。1Gbpsなら4、10Gbpsなら2など)が最も小さいパスを選ぶ。
3. 最小の送信元BID(Lowest Sender BID):
同一セグメント上に複数のスイッチがいる場合、隣接する中で最もBIDが小さいスイッチからのBPDUを優先する。
4. 最小の送信元ポートID(Lowest Sender Port ID):
同一スイッチ間に複数本のケーブルがある場合など。

このアルゴリズムの結果、「ネットワーク全体で最もBID(プライオリティ + MACアドレス)が小さいスイッチ」が、絶対的な王であるルートブリッジとして君臨することになる。

—

4. 現場の落とし穴:なぜ「デフォルト放置」が地獄を生むのか?

新人エンジニアがやりがちな最大のミスが、スイッチを箱から出して初期設定(プライオリティ変更なし=32768)のままネットワークに組み込むことだ。

もし、あなたが中古の安価なスイッチや、たまたまMACアドレスが非常に若い(例: 00:11:22:33:44:55)古びたアクセススイッチをコアレイヤに接続したとしよう。すべてのスイッチのプライオリティが 32768 で並んでいるため、アルゴリズムの判定は最後の砦、「MACアドレスの若さ」に委ねられる。

結果として、「一番性能が低く、古くて安価なスイッチ」がルートブリッジに選出されるという大惨事が起きる。トラフィックがその貧弱なスイッチに集中し、ネットワーク全体がスローダウン、あるいはダウンする。これが、実務において「意図したデバイスを確実にルートブリッジにする」ためのプライオリティ手動チューニングが必須である理由だ。

—

5. 実践:Cisco IOSでのルートブリッジ固定設定

運命を運任せにせず、ネットワーク設計者の意図通りにプライマリのルートブリッジとセカンダリ(冗長用)のルートブリッジを明示的に指定する設定例だ。

! =====================================================================
! プライマリ・ルートブリッジの設定 (VLAN 10および20)
! プライオリティを強制的に「24096」に下げ、他のどの機器よりも優位にする
! =====================================================================
SW-CORE-01# configure terminal
Enter configuration commands, one per line.  End with CNTL/Z.

SW-CORE-01(config)# spanning-tree vlan 10,20 root primary
! ※内部的には priority 24096 が自動計算されて割り当てられる

! =====================================================================
! セカンダリ・ルートブリッジの設定 (万が一の障害時に備える)
! プライオリティを「28672」に設定し、プライマリの次に偉い位置づけにする
! =====================================================================
SW-CORE-02# configure terminal
SW-CORE-02(config)# spanning-tree vlan 10,20 root secondary
! ※内部的には priority 28672 が割り当てられる

状態確認のCLIコマンド

現在のスイッチがルートブリッジとして機能しているか、あるいは誰をルートと仰いでいるのかを確認するには、以下のコマンドを叩く。

SW-ACCESS-01# show spanning-tree vlan 10

VLAN0010
  Spanning tree enabled protocol ieee
  Root ID    Priority    24106  (24096 + SysID 10)
             Address     aabb.cc00.1000
             Cost        4
             Port        1 (GigabitEthernet0/1)
             Hello Time   2 sec  Max Age 20 sec  Forward Delay 15 sec

  Bridge ID  Priority    32778  (32768 + SysID 10)
             Address     aabb.cc00.3000
             PeerCost    4
             ----------------(略)----------------

この出力結果から、次のような状況が瞬時に読み取れる。

  • Root IDのAddress (aabb.cc00.1000): 我々のネットワークの王様(ルートブリッジ)のMACアドレス。
  • Bridge IDのAddress (aabb.cc00.3000): 今自分がログインしてコマンドを叩いているこのスイッチのMACアドレス。
  • Root IDとBridge IDのAddressが異なるため、「このスイッチはルートブリッジではなく、ルートポート(GigabitEthernet0/1)経由でルートにぶら下がっている下位スイッチである」と判断できる。

—

6. PythonでシミュレートするBID比較ロジック

プログラマブルなネットワーク運用や、自製オーケストレーションツール・検証スクリプトを書く際に役立つ、BIDの比較アルゴリズムのPython実装例を示す。ネットワークのパケット処理が裏でどうロジックを回しているのか、直感的に理解できるはずだ。

#!/usr/bin/env python3
"""
Bridge ID (BID) 比較シミュレーションスクリプト
STPのルート選出におけるプライオリティとMACアドレスの優劣判定ロジックを模倣します。
"""

from dataclasses import dataclass

@dataclass
class Bridge:
    name: str
    priority: int
    mac_address: str

    def get_bid(self) -> int:
        """BIDを数値表現に変換する (プライオリティ << 48 + MACの整数値)"""
        mac_int = int(self.mac_address.replace(":", ""), 16)
        return (self.priority << 48) + mac_int

def compare_bridges(bridge_a: Bridge, bridge_b: Bridge) -> Bridge:
    """
    2つのブリッジを比較し、STPのルールに従ってより優れた(BIDが小さい)方を返す。
    """
    bid_a = bridge_a.get_bid()
    bid_b = bridge_b.get_bid()
    
    if bid_a < bid_b:
        return bridge_a
    elif bid_b < bid_a:
        return bridge_b
    else:
        # 理論上あり得ないが完全に同一の場合
        return bridge_a

if __name__ == "__main__":
    # 現場のスイッチに見立てたインスタンス群
    sw_old_cheap = Bridge(name="SW-OLD-ACCESS", priority=32768, mac_address="00:11:22:33:44:55")
    sw_core_1    = Bridge(name="SW-CORE-01",    priority=24096, mac_address="cc:dd:ee:ff:00:11")
    sw_core_2    = Bridge(name="SW-CORE-02",    priority=28672, mac_address="cc:dd:ee:ff:00:22")

    switches = [sw_old_cheap, sw_core_1, sw_core_2]

    # ネットワーク全体で最優秀のブリッジ(ルートブリッジ)を決定する
    current_best = switches[0]
    for sw in switches[1:]:
        current_best = compare_bridges(current_best, sw)

    print(f"=== STP ルートブリッジ選出結果 ===")
    print(フローおよび勝者: f"選出されたルートブリッジ: {current_best.name}")
    print(f"プライオリティ: {current_best.priority}")
    print(f"MACアドレス: {current_best.mac_address}")

このコードを実行すればわかる通り、設定によってプライオリティを 24096 に引き下げた SW-CORE-01 が、MACアドレスの若さ(00:11... vs cc:dd...)を軽々と超越して見事にルートブリッジの座を勝ち取る。

—

7. まとめ

L2ネットワークの平穏は、たった8バイトのブリッジIDと、泥臭い大小比較の積み重ねによって保たれている。

  • BIDはプライオリティ(16bit)とMACアドレス(48bit)の結合体。
  • 数値が小さいほうが「偉い」。
  • デフォルト放置は「最弱のスイッチが王様になる」という恐怖のディザスターを引き起こす。
  • 現場では必ず spanning-tree vlan X root primary/secondary で意図した設計を流し込むこと。

クラウド全盛の時代であっても、パケットを物理的に運ぶレイヤ2の基本原則が変わることはない。この仕組みを腹に落としておけば、万が一のループ障害に直面した際も、冷静に show spanning-tree を叩いて秒速で原因を特定できるはずだ。

インフラの深淵へようこそ。次のパケット解析の旅も楽しんでいこう。

コメント

タイトルとURLをコピーしました