◆ 単純なブリッジの実装その4~Open vSwitch対策~【OpenFlow1.0をTremaの土管として使う】
以前書いた記事『◆ 単純なブリッジの実装その3~より完璧な土管化~【OpenFlow1.0をTremaの土管として使う】』の保守リリースです。
Open vSwitch と接続した場合に、イーサネットの最低フレーム長に満たないデータが packet_in に入ってくる現象が発生し、そのまま転送しようとすると Trema が終了してしまうので対策することにしました。
こういうケースを想定した処理は堅牢なプログラムにするためには必要でしたね。
■発生環境
・OS: Lubuntu 13.04 Desktop (i386)
・Trema: 0.4.7
・OpenFlowスイッチ: Open vSwitch 1.9.0 (※同OS上に apt-get でインストール)
・仮想ホストとして、ネットワークネームスペース
※記事『◆ Lubuntu 13.04 に Open vSwitch をインストールした時のログ』
作成方法詳細は後述します。
■現象
以下のメッセージを出力して Trema が停止する。
The length of the provided Ethernet frame is shorter than the minimum length of an Ethernet frame (= 64 bytes).
■原因
送信データが、イーサネットの最小フレームサイズ(64バイト)に満たないため。
ARP パケットを受け取った時に packet_in に入ってくる PacketIn メッセージの data のサイズが 42 バイトで渡ってくる。これをそのまま send_packet_out で送ろうとすると、
42 + 4(FCS分) = 46 バイト
となり、64バイトに満たない。
■対策
send_packet_out に渡すデータのデータ長の最低長が、64 から FCS分の4バイトを除いた 60 バイトとなるようにする。
send_packet_out で送る data が 60 バイトに満たない場合、後ろを 0 で埋めて 60 バイトにする。
■ソースコード
赤字が変更箇所です。
class SimpleBridge4 < Controller MIN_PACKET_DATA_LEN = 60 def start @port_list = [ 1, 2, 3 ] # all port numbers end def switch_ready( datapath_id ) info "Switch[0x%016x] is up." % datapath_id send_flow_mod_add( datapath_id, :priority => 100 ) @port_list.each do | port | send_flow_mod_add( datapath_id, :match => Match.new( :in_port => port ), :actions => SendOutPort.new( OFPP_CONTROLLER ) ) end end def switch_disconnected( datapath_id ) info "Switch[0x%016x] is disconnected." % datapath_id end def packet_in( datapath_id, message ) return unless message.reason == Trema::PacketIn::OFPR_ACTION # padding. length of sending data must be >= 60 data_len = message.data.length if ( data_len < MIN_PACKET_DATA_LEN ) data = message.data + "\x00" * ( MIN_PACKET_DATA_LEN - data_len ) else data = message.data end actions = [ ] @port_list.each do | port | if ( message.in_port != port ) actions.push( SendOutPort.new( port ) ) end end send_packet_out( datapath_id, :in_port => message.in_port, :data => data,
:actions => actions ) end end
■再現環境
(1)再現環境の作り方
以下のコマンドを実行します。当然、すでに Open vSwitch がインストール済であることが前提です。
sudo ovs-vsctl add-br ofs1 sudo ovs-vsctl set-fail-mode ofs1 secure sudo ip netns add vhost1 sudo ip link add name vlink1-0 type veth peer name vlink1-1 sudo ip link set vlink1-1 netns vhost1 sudo ip netns exec vhost1 ifconfig vlink1-1 up 192.168.0.1 sudo ip link set vlink1-0 up sudo ovs-vsctl add-port ofs1 vlink1-0 sudo ip netns add vhost2 sudo ip link add name vlink2-0 type veth peer name vlink2-1 sudo ip link set vlink2-1 netns vhost2 sudo ip netns exec vhost2 ifconfig vlink2-1 up 192.168.0.2 sudo ip link set vlink2-0 up sudo ovs-vsctl add-port ofs1 vlink2-0 sudo ovs-vsctl set-controller ofs1 tcp:127.0.0.1:6653 sudo ovs-vsctl set controller ofs1 connection-mode=out-of-band sudo ovs-vsctl set controller ofs1 inactivity-probe=180
(2)現象を発生させるコマンド
192.168.0.2 への ARP キャッシュを消して、必ず ARP リクエストが生じるようにしてから ping を実行します。
あらかじめ Trema を実行させておきスイッチと接続が完了したことを確認した上で、以下のコマンドを実行します。1つ目のコマンド実行時に、ARPエントリがありません、といったメッセージがでるかもしれませんが構いません。
sudo ip netns exec vhost1 arp -d 192.168.0.2 sudo ip netns exec vhost1 ping -c 10 192.168.0.2
(3)再現環境の削除の仕方
sudo ovs-vsctl del-br ofs1 sudo ip netns delete vhost1 sudo ip netns delete vhost2
以上
« ◆ ポートベースVLANの作成【OpenFlow1.0をTremaの土管として使う】 | トップページ | ◆ Lubuntu 13.04 の apt-get install で「Not Found」となる現象への対処 »
「Tremaでネットワーク機器プログラミング」カテゴリの記事
- ◆単純なブリッジに仮想インターフェースを追加【OpenFlow1.0をTremaの土管として使う】(2014.08.02)
- ◆ 単純なブリッジの実装その4~Open vSwitch対策~【OpenFlow1.0をTremaの土管として使う】(2014.07.13)
- ◆ ポートベースVLANの作成【OpenFlow1.0をTremaの土管として使う】(2014.07.05)
- ◆ 単純なブリッジの実装その3~より完璧な土管化~【OpenFlow1.0をTremaの土管として使う】(2014.06.29)
- ◆ 単純なブリッジの実装その2~複数ポート対応~【OpenFlow1.0をTremaの土管として使う】(2013.11.02)
コメント
この記事へのコメントは終了しました。
« ◆ ポートベースVLANの作成【OpenFlow1.0をTremaの土管として使う】 | トップページ | ◆ Lubuntu 13.04 の apt-get install で「Not Found」となる現象への対処 »
無知ですいません
この環境状態でpingをvhost1からvhost2へ送ると繋がるのでしょうか?
よろしくお願いします。
投稿: | 2017年9月28日 (木) 18時08分