2016-08-31 14 views
0

以下のように、2つのホストと1つのスイッチを持つRyuコントローラとMininetインスタンスを実行しています。OpenFlow - ICMPメッセージの処理方法

H1 --- --- S H2

コードリュコントローラ内

from ryu.base import app_manager 
from ryu.controller import ofp_event 
from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER 
from ryu.controller.handler import set_ev_cls 
from ryu.ofproto import ofproto_v1_3 
from ryu.lib.packet import packet 
from ryu.lib.packet import ethernet 
from ryu.lib.packet import ether_types 


class SimpleSwitch13(app_manager.RyuApp): 

OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION] 

def __init__(self, *args, **kwargs): 
    super(SimpleSwitch13, self).__init__(*args, **kwargs) 
    self.mac_to_port = {} 

@set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER) 
def switch_features_handler(self, ev): 
    datapath = ev.msg.datapath 
    ofproto = datapath.ofproto 
    parser = datapath.ofproto_parser 

基本的スイッチフローテーブルが空です。この場合、私のミニネットコンソールからh1 ping h2を実行し、パケット交換を記録すると、これはホストh1からwiresharkで取得したものです。

enter image description here

mininetインスタンスにはルータがありません。 pingを開始した同じホストからICMP Host Destination Unreachable Messageをどのように受け取っていますか?

答えて

0

ARP要求がh2によって決して応答されないため、ICMP Host Destination Unreachableが発生します。

h1はARP応答を取得しないため、ICMPエラーメッセージは独自のIPスタックから送信されます。

+0

タイムアウト値は、ARP応答が受信されていないことをホストが確認し、ICMPエラーを発行する –

1

あなたが投稿したアプリケーションコードはで、完全ではありませんです。

完全なsimple_switch_13.pyについては、osrg githubから入手できます。

を見てみましょう、それはこのようなものです:

class SimpleSwitch13(app_manager.RyuApp): 
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION] 

    def __init__(self, *args, **kwargs): 
     super(SimpleSwitch13, self).__init__(*args, **kwargs) 
     self.mac_to_port = {} 

    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER) 
    def switch_features_handler(self, ev): 
     datapath = ev.msg.datapath 
     ofproto = datapath.ofproto 
     parser = datapath.ofproto_parser 

     match = parser.OFPMatch() 
     actions = [parser.OFPActionOutput(ofproto.OFPP_CONTROLLER, 
              ofproto.OFPCML_NO_BUFFER)] 
     self.add_flow(datapath, 0, match, actions) 

    def add_flow(self, datapath, priority, match, actions, buffer_id=None): 
     ofproto = datapath.ofproto 
     parser = datapath.ofproto_parser 

     inst = [parser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, 
              actions)] 
     if buffer_id: 
      mod = parser.OFPFlowMod(datapath=datapath, buffer_id=buffer_id, 
            priority=priority, match=match, 
            instructions=inst) 
     else: 
      mod = parser.OFPFlowMod(datapath=datapath, priority=priority, 
            match=match, instructions=inst) 
     datapath.send_msg(mod) 

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER) 
    def _packet_in_handler(self, ev): 
     # If you hit this you might want to increase 
     # the "miss_send_length" of your switch 
     if ev.msg.msg_len < ev.msg.total_len: 
      self.logger.debug("packet truncated: only %s of %s bytes", 
           ev.msg.msg_len, ev.msg.total_len) 
     msg = ev.msg 
     datapath = msg.datapath 
     ofproto = datapath.ofproto 
     parser = datapath.ofproto_parser 
     in_port = msg.match['in_port'] 

     pkt = packet.Packet(msg.data) 
     eth = pkt.get_protocols(ethernet.ethernet)[0] 

     if eth.ethertype == ether_types.ETH_TYPE_LLDP: 
      # ignore lldp packet 
      return 
     dst = eth.dst 
     src = eth.src 

     dpid = datapath.id 
     self.mac_to_port.setdefault(dpid, {}) 

     self.logger.info("packet in %s %s %s %s", dpid, src, dst, in_port) 

     # learn a mac address to avoid FLOOD next time. 
     self.mac_to_port[dpid][src] = in_port 

     if dst in self.mac_to_port[dpid]: 
      out_port = self.mac_to_port[dpid][dst] 
     else: 
      out_port = ofproto.OFPP_FLOOD 

     actions = [parser.OFPActionOutput(out_port)] 

     # install a flow to avoid packet_in next time 
     if out_port != ofproto.OFPP_FLOOD: 
      match = parser.OFPMatch(in_port=in_port, eth_dst=dst) 
      # verify if we have a valid buffer_id, if yes avoid to send both 
      # flow_mod & packet_out 
      if msg.buffer_id != ofproto.OFP_NO_BUFFER: 
       self.add_flow(datapath, 1, match, actions, msg.buffer_id) 
       return 
      else: 
       self.add_flow(datapath, 1, match, actions) 
     data = None 
     if msg.buffer_id == ofproto.OFP_NO_BUFFER: 
      data = msg.data 

     out = parser.OFPPacketOut(datapath=datapath, buffer_id=msg.buffer_id, 
            in_port=in_port, actions=actions, data=data) 
     datapath.send_msg(out) 

このsimple_switch_13.pyアプリは、あなたのケースでレイヤ2転送を処理します。あなたが見ることができるように、接続が確立した後、switch_features_handlerはこのイベントをリッスンし、スイッチ上のsend all flow to controllerフローを追加します

。(table-missフロー)

、通常の状態のため、コントローラはPACKET_INを受け、 dst_MACがmac_to_portにあるかどうかをチェックします。 yesの場合、ポートに出力し、同時にフローを挿入します(一致フィールドはinportおよびdst_MACです)。 else(配列内にない)の場合、アクションはoutport=FLOODを割り当てることによってFLOODに設定されます。

これはレイヤ2スイッチングのケースです。

レイヤ3スイッチングで処理するICMPメッセージでは、より複雑なコードrest_router.pyを読み取る必要があります。

関連する問題