🤖

パケットキャプチャでSTPを学ぶ(4) ポートの役割

2022/06/26に公開

前回のおさらい

STP(Spanning Tree Protocol)のパケットキャプチャができる環境作りとパケットキャプチャ取得をして、Root Bridgeが選出されるところまでを見てきました。

https://zenn.dev/takai404/articles/4950308b787eec

今回は各ポートの役割を決定してSTPのトポロジが完成するまでを確認してみます。

ポートの役割

標準STPの役割は3種類です。どのポートも以下のどれかの役割に就きます。

  • Root Port: Bridgeのポートの中で、最もRoot Bridgeに近いポートです。
  • Designated Port: ケーブルの両端のうち、Root Bridgeに近いポートです。日本語だと代表ポートとか指定ポートと呼ばれます。
  • Blocking Port: Root PortでもDesignate Portでもないポートで、その名の通りデータ転送をブロックします。non Designated Portと呼ばれることもあります。

Root Portは名前がややこしいと思うんですよね。STPには「Root Bridge」という概念があることは前回紹介しました。「Root Port」というと「Root Bridge」のポートのこと?とも思えるのですが、実際には「Root Bridgeへ最短で行けるポート」を指します。1つのスイッチの中に1つだけ存在します。

Designated Portは「ケーブルの両端のうち、Root Bridgeに近いポート」と書きました。一般的なSTP構成ではこの認識でOKです。

Blocking Portは何か条件を満たしたときになるわけではなくて、Root PortにもDesignated Portにも落選した余り物のポートがBlocking Portになります。

Root Portの決定方法

Root BridgeにはRoot Portはありません。Root Portの定義が「最もRoot Bridgeに近いポート」なので自明ですね。
Root Bridge以外は1つだけRoot Portを持ちます。「最も」近いポートがRoot Portなので、複数経路でRoot Bridgeに行ける場合でもその中の1つがRoot Portになります。

「近さ」の定義は以下の通りです。各ポートが受信したBPDUを見て、条件1が同位の場合は条件2で、条件2が同位の場合は条件3で決定します。

  1. ルートパスコストが最小
  2. Bridge IDが最小
  3. ポートIDが最小

先に結論を書いておきます。今回のRoot Portは以下の形になります。白抜きの〇がRoot Portです。
この図のCode(Graphviz)

ルートパスコスト

ルートパスコストはRoot Bridgeからそのブリッジに到達するまでのポート(ケーブル)のコストを積算したものです。ポートコストはデフォルトでは以下のように定義されています。

帯域 ポートコスト(標準STP) 参考:ポートコスト(RSTP, MSTP) 参考:ポートコスト(標準STP旧規格)
10 Mbps 100 2,000,000 100
100 Mbps 19 200,000 10
1 Gbps 4 20,000 1
10 Gbps 2 2,000 1

標準STPはかつては\frac{1Gbps}{帯域(kbps)}で定義されていたのが、時代の流れで広帯域規格が出てきて改訂されています。
RSTPは\frac{20Tbps}{帯域(kbps)}で定義されています。1 Gbpsだと、1 Gbps = 1,000,000 kbpsなので\frac{20,000,000,000}{1,000,000}=20,000です。つまり将来20Tbpsを超えるネットワーク規格が出てきたときに20Tbpsも100Tbpsも同じコストになり、適正なパス選択が行えなくなります。その頃には規格改定が行われるかSTPが廃れているかのどちらかでしょう。

自分の管理するネットワーク特性によってポートコストを変更することができます。
とはいえ、実際に変更するとしたら、STPとRSTPが混在する環境でSTPのコストをRSTP流にするときくらいでしょう。

access3がaccess4宛に送っているBPDUがこちらです。


access3はRoot Bridgeなので、Root Path Cost=0で送出しています。


次にaccess4が下位のcore2宛に送っているBPDUがこちらです。


Root Path Cost=2になっています。
vethで仮想的に作ったケーブルについてethtoolでリンクスピードを確認すると以下の通りSpeed: 10000Mb/sとなっています。10000Mb/s=10Gb/sなので、標準STPではaccess4のe0のポートコストは2です。

# ethtool access4_e0
Settings for access4_e0:
        Supported ports: [ ]
        Supported link modes:   Not reported
        Supported pause frame use: No
        Supports auto-negotiation: No
        Supported FEC modes: Not reported
        Advertised link modes:  Not reported
        Advertised pause frame use: No
        Advertised auto-negotiation: No
        Advertised FEC modes: Not reported
        Speed: 10000Mb/s
        Duplex: Full
        Port: Twisted Pair
        PHYAD: 0
        Transceiver: internal
        Auto-negotiation: off
        MDI-X: Unknown
        Link detected: yes

上位から受信したBPDUのルートパスコストに自分のe0ポートのポートコストを加算して0+2=2を下位に送信するBPDUのルートパスコストに書き込んでいます。


さらにcore2が下位のaccess2宛に送っているBPDUがこちらです。


上位から受信したBPDUのルートパスコストに自分のe2ポートのポートコストを加算して2+2=4を下位に送信するBPDUのルートパスコストに書き込んでいます。


図には書かなかったのですが、access2の先にはpc2がつながっています。pc2はBPDUを理解しませんが、access2はpc2宛にもBPDUを送信しています。


上位から受信したBPDUのルートパスコストに自分のe1ポートのポートコストを加算して4+2=6を下位に送信するBPDUのルートパスコストに書き込んでいます。

Bridge ID

Bridge IDは前回説明した通りです。

Port ID

ポートIDは2バイト(16ビット)です。
標準STPでは上位8ビットがPort Priority、下位8ビットがPort Numberです。
Port Priorityは8ビットなので0~255の256通りの値を利用可能ですが、0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240を使うことが多いです。

各BridgeのRoot Port

それぞれのBridgeのRoot Portがどれなのかをパケットキャプチャから確認してみましょう。

access1

Root Bridgeが選出されて、STPのトポロジが収束に向かう段階になるとaccess1宛にBPDUを送ってくるのはcore1だけです。
core1につながるe1がaccess1のRoot Portです。
(access1はe2, e0からBPDUを送信しますが、Root Port選定には関係ないです)


access2

access2宛にBPDUを送ってくるのはcore2, access1です。
ルートパスコストを見るとどちらも4なので、この情報だけでは決着しないです。

送信者のBridge IDを比較します。


どちらもPriorityは32768で同じ、MACアドレスの差でcore2の方が数値が小さいので勝ちです。
core2につながるe1がaccess2のRoot Portです。

access3

access3は自身がRoot Bridgeなので、Root Portは持ちません

access4

access4宛にBPDUを送ってくるのはaccess3だけです。
access3につながるe0がaccess4のRoot Portです。


core1

core1宛にBPDUを送ってくるのはaccess3だけです。
access3につながるe2がcore1のRoot Portです。


core2

core2宛にBPDUを送ってくるのはaccess4, core1です。

  • ルートパスコストを見るとどちらも2なので、この情報だけでは決着しないです。
  • 送信者Bride ID
    • Bridge Priorityは32768で同じ
    • MACアドレスはaccess4(42:bf:cd:48:42:30)の方が小さい(core1は6a:78:dc:b8:0a:3d)

access4につながるe2がcore2のRoot Portです。

以上でRoot Portが決定しました。

Designated Port

次にDesignated Portを決めます。
Designated Portの決定基準はRoot Portの決定基準と同じです。

  1. ルートパスコストが最小
  2. Bridge IDが最小
  3. ポートIDが最小

Root Portは、1つのBridgeに注目し、そのBridgeが受信する全ポートのBPDUを見て上記決定基準で1つのPortを選びました。
Designated Portは、1本のLANケーブルに着目し、そのケーブルの両端が送信しようとするBPDUを見て上記決定基準で片方のPortを選びます。
「送信しようとする」と書いたのはBridge間でBPDUをやり取りしたとき、上位のBridgeは自分より弱いBPDUが来ても継続してBPDUを出し続けるのに対し、下位のBridgeは上位のBridgeに対してBPDU送信をやめるため、収束状態ではBPDUを出さないためです。

Root Bridge

Root Bridgeが出すBPDUはルートパスコストが0なので、「ルートパスコストが最小」という条件によって必ずDesignated Portになります。
数の黒丸はDesignated Portです。

Root Portの対向側

Root Portは「最もRoot Bridgeに近いポート」でした。
以下の図のaccess4とcore2の間のケーブル(黄色のところ)に注目すると、access4が送出するBPDUのルートパスコストは2です。core2が送出(しようと)するBPDUのルートパスコストはaccess4が出してきたBPDUに2を加算したものです。
なのでどう考えてもRoot PortよりもRoot Portの対向側の方が強いBPDUを出します。

Root Portの対向側はDesignated Portになります。

Root Portがないケーブル

Root Portがないケーブル(黄色のところ)についても片端がDesignated Portになります
core1が出すBPDUは赤の経路で示すように10Gbpsケーブル1本しか経由していないので、core1が出すBPDUのルートパスコストは2です。
core2が出すBPDUは青の経路で示すように10Gbpsケーブル2本経由しているので、core2が出そうとするBPDUのルートパスコストは2+2=4です。

パケットキャプチャで見ると、BPDUを出している方がDesignated Portです。
以下はcore1とcore2の間のパケットキャプチャです。

途中からcore1しかBPDUを出していないです。
core2は起動直後の自分がRoot Bridgeだと思い込んでいた時にBPDUを出していた以外はBPDUを出していないです。core1が自分より上位のBPDUを投げてくるので沈黙しています

Blocking Port

残ったポートがBlocking Portです。
下図の二重バーで示したところがBlocking Portです。

STPトポロジ

Bridgeのポートの役割が決まってSTPトポロジが分かりました。
この図のCode(Graphviz)

これまで説明しなかったのですが、PCなどのBPDUを理解しない(BPDUを送ってこない)機器がつながっているポートはDesignated Portになります。
この図のCode(Graphviz)

別の形で書いた図がこちら。
この図のCode(drawthe.net)

port priorityのことを調べているときに気になったのですが、bridgeコマンドでポートの詳細を表示するとpriority 32というのが出てきます。これはport priorityのことだと思っていたのですが…

# bridge -d link show dev core1_e1
16: core1_e1@access1_e1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master core1 state forwarding priority 32 cost 2
    hairpin off guard off root_block off fastleave off learning on flood on mcast_flood on mcast_to_unicast off neigh_suppress off vlan_tunnel off isolated off

パケットキャプチャで見ると0x80(10進数128)が出ているよう見えるんですよね。謎。

まとめ

STPのトポロジが収束するまでをパケットキャプチャで見てみました。
次はどうしましょうかね?
Bridge Priorityを変更してまともなトポロジにするか、ポート障害時のPing途絶時間を計ってみるかですかね。

Discussion