スイッチの「記憶」はなぜ消えるのか?MACアドレステーブルのエイジングタイマーが語るネットワークの真実
「なぜか特定端末への通信が、最初の数パケットだけ遅延する」
「ネットワーク構成変更直後に、妙なフラッディングが起きる」
現場でそんな怪現象に遭遇したことはないだろうか。もし君が「スイッチはパケットを届けるだけの黒い箱」だと思っているなら、それは大きな間違いだ。L2スイッチの心臓部であるMACアドレステーブル、そしてそのエントリを制御するエイジングタイマー(Aging Timer)こそが、ネットワークの「安定」と「混沌」の境界線を引いている。
今日は、教科書には載っていない、現場で生き残るための「MACアドレステーブルの作法」について深掘りしよう。
—
1. なぜスイッチは「忘れる」必要があるのか?
スイッチは、フレームを受信すると送信元のMACアドレスを学習し、ポートと紐付けてMACアドレステーブルに保存する。次にその宛先へフレームを転送する際は、このテーブルを見て適切なポートにのみフレームを投げる(Unicast)。
しかし、ここで一つ問いが生まれる。「なぜ、永久に保持してはいけないのか?」
答えは明白だ。ネットワークは生き物だからだ。端末が物理的に移動したり、NICが故障して交換されたり、あるいはVLANの設定が変更されたりする。もし古い情報が残っていたら、スイッチは存在しない(あるいは別のポートに移動した)端末へフレームを送り続け、通信はブラックホールに消えることになる。
この「情報の鮮度」を保つために存在するのが、エイジングタイマーだ。多くのベンダーでデフォルト 300秒 に設定されているこのタイマーは、タイマーが切れた瞬間にそのエントリを「パージ(抹消)」する。
思考の罠:300秒という数値の重み
300秒という数字は、単なる定数ではない。この間、スイッチは「この端末はまだここにいるか?」を監視し続けている。通信が発生するたびにタイマーはリセットされるため、アクティブな通信が行われている限り、エントリが消えることはない。しかし、ふと通信が止まり、300秒が経過した瞬間、そのMACアドレスはテーブルから消える。
—
2. パケットの挙動と「未知の宛先」への試練
エントリが消去された後、その端末宛にパケットが届いたとき、スイッチは何をするか?
1. Unknown Unicast Flooding: 宛先不明のため、受信ポート以外の全ポートにフレームをコピーしてばら撒く。
2. 学習の再開: 端末が応答を返せば、スイッチは再びそのポートとMACアドレスを紐付けて学習する。
この「再学習」のプロセスが、Web APIの通信に与える影響は小さくない。特に高頻度で短時間の通信を行うマイクロサービス間では、スイッチのエイジングが早すぎると、常にフラッディングが発生し、ブロードキャストドメイン全体に不要なトラフィックを撒き散らすことになる。
—
3. 実践:デバッグと検証のためのTips
現場で「通信が遅延している」と感じたら、まずはテーブルの状態を確認する。Cisco環境なら以下のコマンドで状況が手に取るようにわかる。
# 現在のMACアドレステーブルを確認
show mac address-table dynamic
# 特定のインターフェースにぶら下がっているエントリを確認
show mac address-table interface GigabitEthernet 0/1
もし、特定の端末が頻繁にテーブルから消えて困る場合は、設定でタイマーを調整する。ただし、これは劇薬だ。
# グローバルコンフィグでエイジングタイマーを1800秒(30分)に延長する例
# デフォルト値から変更する場合は、ネットワークの収束速度とのトレードオフを必ず考慮せよ
Switch(config)# mac address-table aging-time 1800
開発者が意識すべき通信の「呼吸」
Web API開発において、Keep-Aliveの挙動は重要だ。TCPセッションが維持されている間は、スイッチのMACアドレステーブルも安泰だ。しかし、接続を切断し、しばらく間隔を開けてから再度リクエストを送るような設計の場合、スイッチのエイジングタイマーに依存する挙動を考慮する必要がある。
以下は、Pythonで通信の「鮮度」を意識したテストコードの例だ。
import requests
import time
# 頻繁に切断・接続を繰り返すようなAPIクライアントのシミュレーション
def test_connection_latency(url):
for i in range(5):
start = time.time()
# セッションを明示的に閉じる設計だと、MAC学習の機会が失われやすい
with requests.get(url) as response:
print(f"Request {i+1}: {time.time() - start:.4f} sec")
# 300秒以上の待機を入れると、スイッチのエイジングが発生し
# 次のリクエストでフラッディングによる遅延が発生する可能性がある
time.sleep(310)
# 実務では、接続のライフサイクルとスイッチのタイマーを
# ネットワークのトポロジ設計と照らし合わせて考えることが重要
—
結論:エンジニアは「見えないパケット」を想像せよ
ネットワークのトラブルシューティングにおいて、一番の敵は「見えないもの」を無視することだ。MACアドレステーブルのエイジングタイマーは、単なるスイッチの設定値ではない。それは、ネットワークという巨大な分散システムが「現状をどう認識しているか」というメモリの掃除頻度そのものだ。
インフラ運用者であれ、API設計者であれ、パケットがスイッチのASIC(専用チップ)を通過し、テーブルを参照し、そして必要とあらば消去される。この一連のライフサイクルを頭の中に描けるようになれば、君はもう一段上のレイヤーでネットワークを語れるようになるはずだ。
次の障害対応では、ぜひコマンドの出力結果の裏側にある「パケットの旅路」を想像してみてほしい。それが、凄腕への第一歩だ。
コメント