Trema/MyRoutingSwitch(7), Topology Change and Re-route(9)

あいかわらずごちゃごちゃやってます。

トポロジ変化と、それに対してどうパケットの経路制御するかというのを見てきたのですが、KVM/OVS 実機でトポロジ変更させるのがやたらと面倒くさいので、基本的には Trema のネットワークエミュレータ機能を使ってテストをしていました。ただ、最近 vxlan 使ってみたいとかあって久しぶりに実環境の方で作業を行っていて Ubuntu/KVM/OVSでOpenFlowテスト環境をつくる(7) とかやったわけです。で、トポロジいじってて気がついた。特定の設定でポートを消しても OVS が port_status あげてくれないみたいなんすね。今回はその辺のこまごまとした調査結果について書きます。

現象

OpenFlowテスト環境をつくる(7) をやっていたときに、OVS 上のポート作成、削除が発生します。これまで、1ホスト内にOVSで複数のブリッジを作り、ブリッジ間を patch port で接続していました。OVS patch port については OpenFlowテスト環境をつくる(6) 参照。

トポロジを変えるのでポートを消したりつないだりするんですよ。問題は、ovs-vsctl del-port ovsbr1 patch1-2 みたいにしたときに、コントローラ側でトポロジの変化が検出されていない(経路の再計算が行われていない)、という現象です。あ、テストしたのは以下の環境です。

  • OVS/KVM
    • Linux: 3.5.0-25 (Ubuntu12.10, x86_64)
    • OVS: 1.4.3
  • Controller
    • Linux: 3.8.0-19 (Ubuntu13.04, x86_64)
    • trema: 0.3.19

調査

……トポロジの変化が検出されていないという言い方はちょっと語弊がありますね。正確には、del-port によって port_status があがってくるが、port.link_down? が false になっている、ということです。

  def port_status dpid, port_status
    info "[MyRoutingSwitch::port_status] switch:#{dpid.to_hex}"

    updated_port = port_status.port

    # debug
    puts "- port number    : #{ updated_port.number }"
    puts "- port name      : #{ updated_port.name }"
    puts "- port local?    : #{ updated_port.local? }"
    puts "- port link_down?: #{ updated_port.link_down? }"
    puts "- port link_up?  : #{ updated_port.link_up? }"
    puts "- port port_down?: #{ updated_port.port_down? }"
    puts "- port port_up?  : #{ updated_port.port_up? }"

    return if updated_port.local?

    @topology.update_port dpid, updated_port
    # update link info, asap!
    flood_lldp_frames
  end

patch port 消してみる

root@oftest03:~# sudo ovs-vsctl del-port ovsbr2 patch2-3                    

こうなる

[MyRoutingSwitch::port_status] switch:0x2
- port number    : 6
- port name      : patch2-3
- port local?    : false
- port link_down?: false
- port link_up?  : true
- port port_down?: false
- port port_up?  : true

ポート追加してみる

root@oftest03:~# sudo ovs-vsctl add-port ovsbr2 patch2-3 -- set interface patch2-3 type=patch options:peer=patch3-2

こうなる

[MyRoutingSwitch::port_status] switch:0x2
- port number    : 7
- port name      : patch2-3
- port local?    : false
- port link_down?: false
- port link_up?  : true
- port port_down?: false
- port port_up?  : true

ポート消してるのに link_down? が false になっているものだからトポロジが変わったというのがキャッチできませんでした。もうひとつ。patch port を消していますが、対向のブリッジ(対向のポート…上記のコンフィグの場合 peer: ovsbr3, patch3-2 から)から port_status が上がってきません。

さらに、patch port に対してはポートの状態変更(mod_port)ができないようです。たとえば

root@oftest03:~# sudo ovs-ofctl mod-port ovsbr2 patch2-3 down

みたいなことをやると、裏でこういうログが出てます。

root@oftest03:/var/log/openvswitch# tail -f ovs-vswitchd.log
Jul 28 15:41:17|00441|netdev|WARN|failed to set flags for network device patch2-3: Operation not supported

まとめ

…と、いうことで、

  • OVS patch port はどうもポート状態が固定されているらしい。
    • mod port で patch port の状態を変更させることは許可されていない。常に UP で状態は固定。
    • patch port の対向ポートが設定されておらず、リンクとして成立していない場合、つまりリンクの片側しかポートが設定されていない場合でも、ポートの状態は UP で固定
    • patch port が削除された場合も、port_status メッセージにおけるポートの状態は UP で固定。かつ、対向側 patch port も UP 固定なので、対向側ブリッジでもポートダウンが発生せず、port_status message があがらない。

となっているようです。(patch port の仕様ってこういう物、みたいのが見当たらず。コード読めって話なのか。そこまでは追いかけていません…。(知ってる方おしえてください)

でもまあ、OVSの内部でだけ使う設定上のリンクなので、ダウンしないのは、そう言われればまあそうかなとも思います。

これを防ぐには linux veth (virtual ethernet device) を使えば良いですね。OS 上でデバイスとして見えている物については、通常考えるような感じでリンクアップダウンの操作ができますし、リンクアップダウンのイベントが発生します。ただ、OVS patch port を使うと、OVS Config だけでトポロジ情報(ブリッジ間接続)がわかるというメリットもあります。veth を使うと、OVS config + OS device infomation を見る必要があって、設定情報を元にブリッジ間接続を把握するのがちょっと難しい。その辺を考えつつ何をどう使うかというのの判断が必要なのかもしれないですね。