2016-08-31 20 views
0

다음과 같이 호스트 2 개와 스위치 1 개가있는 Ryu 컨트롤러와 Mininet 인스턴스를 실행하고 있습니다. 류 제어기OpenFlow - ICMP 메시지 처리 방법

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 H2 --- --- S

코드 스위치 플로우 테이블 비어있다. 이 경우, 내 미니 콘솔에서 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에 있는지 확인합니다. 그렇다면 포트로 출력하고 동시에 (그 일치 필드는 inport 및 dst_MAC 인) 플로우를 삽입하십시오. else (배열에 없음) 일 경우, 액션은 outport=FLOOD을 할당하여 FLOOD로 설정됩니다.

레이어 2 스위칭의 경우입니다.

레이어 3 스위칭에서 처리하는 ICMP 메시지의 경우 훨씬 더 복잡한 rest_router.py 코드를 읽어야합니다.