送り主を覚えて、宛先へ送るスイッチ
ラーニングスイッチは、届いた枠の送り主の MAC アドレスと入口のポートを覚え、次からは宛先のポートだけに送るスイッチです。
覚えるまでは全ポートに流し、覚えたあとは1つのポートにだけ送ります。そのため、無駄な通信が減ります。
このレッスンのゴール
メモ
スイッチが MAC アドレスとポートの対応を、どう覚えるかを説明できる。
重要な言葉
| ことば | いみ | れい |
|---|---|---|
| MAC アドレス表 | MAC アドレスと、そのつなぎ先ポートの対応表 | A は1番 |
| 学習 | 届いた枠の送り主を、表に覚えること | |
| フラッディング | 入口以外のすべてのポートへ流すこと | |
| 入口ポート | 枠が入ってきたポート | |
| 送り主と宛先 | 枠に書かれた、出した MAC と、届けたい MAC |
学生が入力するセルは、このプレビューでは空白です。
スイッチは送り主を見て覚える
枠が届くと、スイッチは送り主の MAC アドレスと入口のポートを表に書きます。「この MAC は、このポートの先にいる」という記録です。
次に宛先を表で探します。見つかれば、そのポートだけに送ります。見つからなければ、入口以外のすべてのポートに流します。これがフラッディングです。
例: 5つの枠で表が育つ
| 枠(入口、送り主、宛先) | 覚えること | 出力 |
|---|---|---|
| 1番、A、B | A は1番 | 全ポート(B を知らない) |
| 2番、B、A | B は2番 | 1番(A を知っている) |
| 1番、A、B | A は1番のまま | 2番(B を知っている) |
| 3番、C、A | C は3番 | 1番 |
| 2番、B、C | B は2番のまま | 3番 |
学生が入力するセルは、このプレビューでは空白です。
20行足らずの、学習の動き
# 学習スイッチの表を、小さく動かします。
table = {}
frames = [[1, "A", "B"], [2, "B", "A"], [1, "A", "B"]]
for frame in frames:
in_port = frame[0]
src = frame[1]
dst = frame[2]
# 送り主を覚えます。
table[src] = in_port
# 宛先を知っていれば、そのポートだけに送ります。
if dst in table:
out = table[dst]
else:
out = "flood"
print(frame, "->", out)
# frames に [3, "C", "A"] を足して、もう一度実行しましょう。
Open vSwitch は自分で学習もできる
Open vSwitch には、このとおりに学習する NORMAL というアクションがあります。ここでは、自分用の sw1 で動きを見ます。
ofproto/trace -generate を使うと、試しの枠が学習の記録を残します。ふつうの trace は、表を読むだけです。この回では、sw1 だけで NORMAL を使います。
sw1 を作り直す
sudo ovs-vsctl --if-exists del-br sw1 -- add-br sw1 -- set bridge sw1 datapath_type=system protocols=OpenFlow13 fail-mode=secure -- add-port sw1 p1 -- set interface p1 type=internal ofport_request=1 -- add-port sw1 p2 -- set interface p2 type=internal ofport_request=2 -- add-port sw1 p3 -- set interface p3 type=internal ofport_request=3 -- add-port sw1 p4 -- set interface p4 type=internal ofport_request=4ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
学習するアクションを入れる
sudo ovs-ofctl -O OpenFlow13 add-flow sw1 priority=0,actions=NORMALここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
1番から2番への枠(学習する)
sudo ovs-appctl ofproto/trace -generate sw1 in_port=1,dl_src=00:00:00:00:00:01,dl_dst=00:00:00:00:00:02 | grep floodここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
2番から1番への枠(もう知っている)
sudo ovs-appctl ofproto/trace sw1 in_port=2,dl_src=00:00:00:00:00:02,dl_dst=00:00:00:00:00:01 | grep -E "learned|flood"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
知らない宛先への枠
sudo ovs-appctl ofproto/trace sw1 in_port=2,dl_src=00:00:00:00:00:02,dl_dst=00:00:00:00:00:77 | grep -E "learned|flood"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
覚えた表を見る
sudo ovs-appctl fdb/show sw1 | awk '{print $1, $3}'ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
出力の読み方
1つ目は、宛先 ...02 を知らないので、フラッディングの1行が出ます。同時に、1番に MAC ...01 がいると覚えます。
2つ目は、宛先 ...01 を覚えているので、そのポートに送ります。3つ目は、...77 を知らないのでフラッディングです。表には、1番の MAC ...01 だけが残ります。
覚えた行は変わることがある
パソコンを別のポートにつなぎ替えると、同じ MAC が別のポートから届きます。スイッチは、行を新しいポートに書き換えます。
ポートが使えなくなったときは、そのポートで覚えた行をすべて消します。消さないと、行き止まりに枠を送り続けます。
よくある間違い
注意
スイッチは、宛先の MAC を見て、その場所を覚える、と思いがちです。覚えるのは送り主の MAC です。宛先は、すでに覚えた表を引くためだけに使います。