一覧NW-03-1 · スイッチとVLAN

MACアドレスの学習とフレーム転送

同じスイッチへフレームを順に入れ、転送表と出力ポートの変化を確認します。

説明

Ethernetスイッチは受信したフレームの送信元MACから、その端末がいる方向を学習します。宛先が未学習なら同じVLAN内へ広く送り、学習済みなら対応するポートを選びます。

4ポートのスイッチを使い、最初の送信、返信、繰返し通信、端末移動、一定時間後の送信を順に計算します。転送表を毎回残し、どの受信が表を更新したのかを確認します。

1同じVLANの4ポート

AとBはMACの短縮ラベルです。4ポートともVLAN10に所属し、最初の転送表は空とします。

ports = {1: 10, 2: 10, 3: 10, 4: 10}VLAN所属; fdb = {}; age = 30空の転送表と保持秒数; print(ports, fdb)初期状態

FDBはMACとポートの対応を保持する表です。このモデルではVLANもキーに含め、最後に送信元として観測してから30秒で期限切れとします。実機の保持時間は設定によって異なります。

2受信時の学習と出力ポート

関数は期限切れを除去し、送信元を受信ポートへ記録してから宛先を調べます。通常のユニキャストのみを扱います。

def receive(now, ingress, source, destination):時刻と受信フレーム vlan = ports[ingress]受信VLAN expired = [key for key, (_, seen) in fdb.items() if now - seen >= age]期限切れを抽出 for key in expired: del fdb[key]期限切れを削除 fdb[vlan, source] = (ingress, now)送信元を学習 target = fdb.get((vlan, destination))宛先を検索 outputs = [target[0]] if target else [p for p,v in ports.items() if v == vlan]既知の宛先または同じVLAN outputs = [p for p in outputs if p != ingress]受信ポートを除外 print("out=", outputs, "FDB=", sorted(fdb.items()))転送先と表を表示

学習に使うのは送信元で、転送先の検索に使うのは宛先です。通常の動作では入ってきたポートへ同じフレームを送り返しません。この関数はhairpin転送やポート制限等を含まない基本モデルです。

3最初のAからBへの送信

時刻0でAからBへのフレームをポート1に入れます。

receive(0, 1, "A", "B")ポート1でAからBを受信

Aはポート1と学習され、未学習のB宛ては2・3・4へ出ます。フラッディングしても宛先MACをブロードキャストへ書き換えるわけではなく、B宛ての同じフレームを複数方向へ送ります。

4Bからの返信

1秒後、ポート2からBがAへ返信します。

receive(1, 2, "B", "A")ポート2から返信

Bがポート2と学習され、A宛ては既知のポート1だけへ出ます。最初のAの送信が、返信の転送先を決める情報になっています。

5同じAからBでも出力先が変わる

2秒後に最初と同じA→Bを送ります。

receive(2, 1, "A", "B")学習後の同じ通信

今度はポート2だけです。Aの最終観測時刻は2に更新されますが、Bは送信元として観測されていないので時刻1のままです。宛先へ転送しただけで、このモデルのBの保持期限は延長しません。

6端末を別のポートへ移動

Bをポート4へ移し、そこからAへ送信します。その後Aから返信します。

receive(3, 4, "B", "A")Bの新しい受信方向を学習; receive(4, 1, "A", "B")更新後の転送先

Bの対応が2から4へ更新され、Aの返信も4へ出ます。同じMACが短時間に複数ポートを行き来する場合は、端末移動だけでなくループ等も調べます。

7保持時間を過ぎた後の通信

次の送信は36秒時点です。最後の観測から30秒以上たった項目を除去してから転送します。

receive(36, 1, "A", "B")無通信時間の後に再送

Bの対応が期限切れとなり、再び2・3・4へ出ます。Aはこのフレームで新しく学習されています。期限切れは端末の故障を意味せず、最近どの方向にいるかという学習情報が失われた状態です。

8宛先が受信ポート側にある場合

ポート1の先に別のブリッジがあり、AとBがどちらもその先にいる状態を考えます。BからAをポート1で受けます。

receive(37, 1, "B", "A")同じ方向の端末間通信

出力は空です。Aも同じポート1の先と分かっているため、他ポートへ送る必要がありません。スイッチは送信元の学習と宛先の転送判定を分けて行います。

まとめ

FDBは受信した送信元MACから更新し、宛先MACで転送先を調べます。

未知宛先のフラッディングと、宛先MACがブロードキャストであることは別です。

端末移動や保持期限により、同じ宛先でも出力ポートが変わります。

操作履歴と解説を振り返れます。

Python 3

1
ports = {1: 10, 2: 10, 3: 10, 4: 10}; fdb = {}; age = 30; print(ports, fdb)
{1: 10, 2: 10, 3: 10, 4: 10} {}
2
def receive(now, ingress, source, destination): vlan = ports[ingress] expired = [key for key, (_, seen) in fdb.items() if now - seen >= age] for key in expired: del fdb[key] fdb[vlan, source] = (ingress, now) target = fdb.get((vlan, destination)) outputs = [target[0]] if target else [p for p,v in ports.items() if v == vlan] outputs = [p for p in outputs if p != ingress] print("out=", outputs, "FDB=", sorted(fdb.items()))
3
receive(0, 1, "A", "B")
out= [2, 3, 4] FDB= [((10, 'A'), (1, 0))]
4
receive(1, 2, "B", "A")
out= [1] FDB= [((10, 'A'), (1, 0)), ((10, 'B'), (2, 1))]
5
receive(2, 1, "A", "B")
out= [2] FDB= [((10, 'A'), (1, 2)), ((10, 'B'), (2, 1))]
6
receive(3, 4, "B", "A"); receive(4, 1, "A", "B")
out= [1] FDB= [((10, 'A'), (1, 2)), ((10, 'B'), (4, 3))]
out= [4] FDB= [((10, 'A'), (1, 4)), ((10, 'B'), (4, 3))]
7
receive(36, 1, "A", "B")
out= [2, 3, 4] FDB= [((10, 'A'), (1, 36))]
8
receive(37, 1, "B", "A")
out= [] FDB= [((10, 'A'), (1, 36)), ((10, 'B'), (1, 37))]

演習完了