Trema/SimpleL3Switch(2)
主要な変更点
packet_in
def packet_in(datapath_id, message) if to_me?(message) if message.arp_request? handle_arp_request datapath_id, message elsif message.arp_reply? handle_arp_reply message elsif message.ipv4? handle_ipv4 datapath_id, message else # noop. end else # forwarding local handle_switched_traffic datapath_id, message end end
- 基本的には simple router と同様。
- 自分の持っているセグメント内でのフォワーディングする処理を追加してある。(
handle_switched_traffic
)
- 自分の持っているセグメント内でのフォワーディングする処理を追加してある。(
handle_arp_request
def handle_arp_request(dpid, message) port = message.in_port daddr = message.arp_tpa interface = @interfaces.find_by_ipaddr(daddr) if interface arp_reply = create_arp_reply_from message, interface.hwaddr packet_out dpid, arp_reply, SendOutPort.new(port) else handle_switched_traffic dpid, message end end
handle_switched_traffic
def handle_switched_traffic(datapath_id, message) if message.arp? @arp_table.update message.in_port, message.arp_spa, message.arp_sha elsif message.ipv4? @arp_table.update message.in_port, message.ipv4_saddr, message.macsa end arp_entry = @arp_table.lookup_by_hwaddr(message.macda) if arp_entry flow_mod datapath_id, message, SendOutPort.new(arp_entry.port) packet_out datapath_id, message.data, SendOutPort.new(arp_entry.port) else # Broadcast, Unknown Unicast flood_to_segment( datapath_id, message.data, @segments.include(@port_name_of[message.in_port]), message.in_port ) end end
flood_to_segment
def flood_to_segment(datapath_id, data, segment_name, in_port = nil) if segment_name port_names = @segments.port_name_list_of(segment_name).dup port_names.delete(@port_name_of[in_port]) actions = [] port_names.each do |each| actions << SendOutPort.new(@port_number_of[each]) end send_packet_out( datapath_id, :data => data, :actions => actions, :zero_padding => true ) else info "SimpleL3Switch: not found a segment that has port:#{ in_port }" end end
- Simple L3Switch のローカルネットワークセグメントに対して flooding する処理。
- broadcast domain を制限するために
OFPP_FLOOD
は使っていない。 - segment に所属しているポート一覧からパケットが入っているポートを除いて、それらのポートに対して packet out する。ただ、自分宛の ARP Request に対する応答など、
in_port
がないデータを送信する場合(handle_unresolved_packet
)もあるので、in_port
は省略可能。(in_port
を省略した場合は、セグメントに含まれる全ポートに対して packet out するだけ。)
- broadcast domain を制限するために
- 一回、以下のようなエラーで落ちたことがあるので、
send_packet_out
では、zero_padding
を有効にしてある。
Sat Jan 19 22:16:35 2013 [critical] The length of the provided Ethernet frame is shorter than the minimum length of an Ethernet frame (= 64 bytes).
課題
機能上の課題、あるいは今後の拡張としてどういう発展が考えられるか。
- 現状、OVS で VM が追加されたりした場合、コントローラ側でそのフォローができていない。最初に features reply で情報もらってくるだけなので。その場合、ポートの投げ先とかセグメントの情報に齟齬が出てコントローラがコケる。これは本当は話にならないので、スイッチ側のポート追加削除とかの変更とかに対して追従できる仕掛けを追加する必要がある。
- いまのところ、1つのスイッチに対する処理を前提に作り込んでしまっている。複数スイッチで構成された環境だとどうなるか? (どうするべきか?)
- セグメントの情報は、現時点では単なるポートグループでしかない。VLAN IDをつけるとか、Trunk Portを扱えるようにする、という拡張はすぐ考えられそう。