- ブラウザURL入力
- DNS名前→IP
- ルータ経路選択今ここ
- ロードバランサ振り分け
- Nginx受け口
- アプリ処理
- DB保存
前回、ルータが宛先IPから次の行き先を選ぶところまで来ました。しかし「次の行き先」へ実際にフレームを手渡すのは、その一区間(同じ部屋の中)の配達です。今回はルータの一段下、その配達を担うMACアドレスとスイッチを扱います。
まず結論
スイッチは、通過したフレームの「送信元MAC」を見て、どのポートの先に誰がいるかを勝手に覚えます。転送するときに見るのは「宛先MAC」です。学習と転送で見る場所が違います。
表に載っていない宛先は、破棄されずに全ポートへ複製されます(フラッディング)。CPUキャッシュのミスが「遅くなるだけ」なのに対し、こちらは届く相手の数が変わります。外し方が違う、というのが今回の山場です。
スイッチが「宛先MACアドレスが表に載っていないフレーム」を受け取ったとき、どうするでしょうか。
当てることが目的ではありません。外した予測ほど記憶に残るので、直感で選んでください。
ルータが決めるのは方角、スイッチが担うのは一区間の手渡し
前回、ルータが宛先IPアドレスから「次にどこへ流すか」を決めるところまで見ました。しかしルータが選ぶのは次の一区間の相手であって、その相手へ実際にフレームを手渡す作業は別に必要です。
この「同じ部屋の中の手渡し」を担うのがMACアドレスとスイッチです。IPアドレスが街の住所だとすれば、MACアドレスは同じ建物の中で誰に渡すかの名札にあたります。
MACアドレスは48ビットの値です。先頭の第1オクテットには、アドレス全体の性質を示す2つのビットが埋まっています。
ビット位置 0 1 2 3 4 5 6 7. . . . Z Y X M| || +-- M = I/G ビット(最下位)| 0 = ユニキャスト / 1 = グループ+----- X = U/L ビット(下位から2番目)0 = IEEE割当 / 1 = ローカル管理
ここで必ず引っかかる点があります。I/Gビットは第1オクテットの最下位ビットです。最上位ではありません。16進表記を左から読む習慣があるので「先頭の桁なのだから最上位ビットだろう」と思い込みやすいのですが、逆です。RFC 5342(現行は RFC 9542。表記は変わったがビット位置は同じ)が Group bit を 01-00-00、Local bit を 02-00-00 と表記しているのは、どちらも下位2ビットだからです。
なお「前半24ビットがベンダ、後半24ビットが連番」という整理をよく見ます。入門の足場としては有用ですが、「必ず」とは言えません。IEEEは24ビットのMA-L以外に、より小さいMA-MやMA-Sというブロックも割り当てており、その場合ベンダを識別する部分は24ビットではありません。
スイッチは、誰にも教わらずに表を作る
スイッチには、あらかじめ「どのポートに誰がいるか」を設定しません。通過するフレームを見ているだけで、勝手に表ができあがります。
その仕組みは驚くほど単純です。フレームが入ってきたら、その送信元MACアドレスと入ってきたポート番号を対にして記録する。それだけです。
- ・学習に使うのは送信元MAC。宛先MACは転送先を決めるためだけに使う
- ・最初のフレームは必ずフラッディングされる。これは異常ではなく通常の動作
ここが最初の関門です。学習は送信元MAC、転送判断は宛先MAC。見る場所が違います。「スイッチは宛先MACを見て学習する」という説明をどこかで読んだら、それは誤りです。宛先MACを学習に使ったら、まだ一度も喋っていない相手の居場所を記録することになってしまいます。
Linuxのブリッジ実装でも、学習とフラッディングはそれぞれ独立した機能として用意されており、IFLA_BRPORT_LEARNING(学習)も IFLA_BRPORT_UNICAST_FLOOD(未知ユニキャストのフラッディング)も既定で有効です。
スイッチがMACアドレステーブルにエントリを作るとき、フレームのどこを見ていますか。
表に無い宛先は、捨てずに全員へ配る
宛先MACを表で引いて、載っていなかったらどうするか。直感的には「宛先不明なので破棄」と考えたくなりますが、スイッチは破棄しません。受信したポート以外の全ポートへ複製します。これがフラッディングです。
なぜ捨てないのかは、スイッチの立場で考えると分かります。表に載っていないのは「その機器が存在しない」証拠ではなく、「まだ一度も喋っていない」だけかもしれません。表は観測の記録にすぎず、世界の完全な地図ではないのです。捨ててしまえば、まだ喋ったことのない機器へは永久に誰も到達できません。
だから「分からないから配らない」ではなく「分からないから全員に配る」を選びます。届いた相手のうち自分宛でないものは黙って捨て、自分宛だった1台が返信します。その返信でスイッチは相手の居場所を学習し、以降はフラッディングが不要になります。
エントリは時間で消える — しかも容量に余裕があっても
表のエントリは永久には残りません。一定時間そのMACからフレームが来なければ削除されます。これをエージングといいます。
なぜ消すのか。ノートPCを別の会議室へ持って行けば、同じMACアドレスが別のポートの先に現れます。古い記録を握りしめていると、フレームを誰もいないポートへ送り続けることになります。エージングは、物理世界の変化に表を追従させる仕組みです。
出どころ 値RFC 4188 の SYNTAX Integer32 (10..1000000) 秒 ← 許容範囲RFC 4188 の説明文 "802.1D-1998 recommends a default of 300 seconds"Cisco IOS 既定300秒。0(エージング無効)も設定できるLinux bridge BR_DEFAULT_AGEING_TIME = 300 * HZuapiヘッダに「特殊用途では802.1の規格範囲外も許す」と明記
ここでよく見かける誤りを1つ正しておきます。「エージング300秒はIEEE 802.1Dの規定値」という説明です。これは不正確です。
RFC 4188 の dot1dTpAgingTime の定義を読むと、SYNTAX は Integer32 (10..1000000) で、説明文は 802.1D-1998 recommends a default of 300 seconds と書かれています。**recommends a default(推奨される既定値)**であって specifies(規定) ではありません。規格が許すのは10秒から1,000,000秒までで、300秒はその中の推奨値にすぎません。
実装を見ればこの差は明白です。Cisco IOS は既定こそ300秒ですが、0(エージング無効)を設定できる点で規格の範囲(10〜1,000,000秒)の外に出ます。Linux bridge にいたっては、uapiヘッダに「特殊な用途のために802.1の規格範囲外の値も許す」と明示的に書かれています。300秒を「規格が決めた絶対の値」だと思っていると、機器ごとの挙動差を説明できなくなります。
「MACアドレステーブルのエージング時間300秒は、IEEE 802.1Dが規定した値である」という説明は妥当ですか。
CPUキャッシュ — 外しても答えは変わらない
タグを照合して外れたら、下位階層へ取りに行きます。返ってくるデータは必ず正しく、支払うのは時間だけです。ミスは純粋にコストの問題です。
引き方 アドレスのタグで照合外したら L2 → L3 → メモリへ取りに行く結果 必ず正しい。遅くなるだけ埋まり方 これから使うデータを要求に応じて(需要駆動)消え方 容量が足りないので追い出す(LRU等)
MACアドレステーブル — 外すと届く相手が変わる
宛先MACで照合して外れたら、フラッディングします。1台に届くはずだったフレームが全台に届きます。遅くなるのではなく、起きることが変わります。
引き方 宛先MACで照合外したら 全ポートへ複製(フラッディング)結果 届く相手が1台から全台へ変わる埋まり方 通過したフレームの送信元から勝手に(観測駆動)消え方 時間が来たので消す(容量に余裕があっても)
どちらも「キーで引いて、外れたら別経路」という同じ形をしています。では、外れたときに起きることの違いは何でしょうか。そしてその違いは、どこから来るのでしょうか。
キャッシュミスで得られる答えと、フラッディングで起きることを、それぞれ「正しさ」の観点から比べてみてください。
この章のまとめ
- MACアドレスは48ビット。I/Gビットは第1オクテットの最下位ビット、U/Lビットはその1つ内側。16進表記の見た目に引きずられて「最上位」と思い込まないこと。
- 「前半24ビットがベンダ」は入門の整理としては使えるが、MA-M/MA-Sがあるので断定はできない。
- スイッチは送信元MACを見て学習し、宛先MACを見て転送先を決める。見る場所が違う。
- 表に無い宛先は破棄ではなくフラッディング。表は観測の記録であって世界の地図ではないので、無いことは「存在しない」を意味しない。
- スイッチが分割するのは衝突ドメインだけ。ブロードキャストドメインは分割されない(VLANが必要)。
- エージング300秒は規格の規定値ではなく「推奨される既定値」。RFC 4188 の許容範囲は10〜1,000,000秒で、実装はその外にもはみ出す。802.1D は現在 802.1Q に統合されている。
- CPUキャッシュとの対比では**「引き方は同じ、外し方が違う」**が要点。キャッシュミスは遅くなるだけ(コスト)、テーブルのミスは届く相手が変わる(意味)。埋まり方も需要駆動と観測駆動で逆、消え方も容量都合と時間ベースで違う。
自分の現場で確かめる
読んだだけでは身につきません。手元の環境で実際に見てみてください。
理解度チェック
読んだ直後は「分かった」と感じやすいものです。実際に解いて確かめてください。
MACアドレスの第1オクテットにあるI/Gビット(マルチキャストビット)は、どの位置にありますか。
用語集(5語)
- MACアドレス
- 同じネットワーク内で機器を識別する48ビットの値。第1オクテットの最下位ビットがI/G(ユニキャストかグループか)、その次がU/L(IEEE割当かローカル管理か)。
- MACアドレステーブル
- スイッチが持つ「MACアドレス → どのポートの先にいるか」の対応表。通過したフレームの送信元MACから自動的に作られる。
- フラッディング
- 宛先MACがテーブルに無いとき、受信ポート以外の全ポートへフレームを複製して送ること。破棄ではない。
- エージング
- 一定時間参照されなかったテーブルのエントリを消すこと。容量の都合ではなく、機器が移動した可能性に追従するための時間ベースの失効。
- 衝突ドメイン / ブロードキャストドメイン
- 同時に送ると衝突する範囲と、ブロードキャストが届く範囲。スイッチはポートごとに衝突ドメインを分離するが、ブロードキャストドメインは分割しない(分割にはVLANが必要)。
出典(一次ソース)
- RFC 4188 — dot1dTpAgingTime の定義(10..1000000、推奨既定値300秒) ↗
- RFC 9542 — IEEE 802 の第1オクテットのビット配置(I/G・U/L) ↗
- RFC 5342 — Group bit / Local bit の表記(RFC 7042→9542 により廃止。現行 RFC 9542 は M bit を 0x01 と表記し、同じビット位置を指す) ↗
- RFC 3635 — 全二重時の衝突カウンタの扱い ↗
- Linux kernel — bridge の実装とドキュメント ↗
- IEEE — Guidelines for Use of Extended Unique Identifier(ビットの送出順、least significant bit から) ↗
- RFC 2469 — A Caution On The Canonical Ordering Of Link-Layer Addresses ↗