RYU控制器的學習筆記(二)

楔子:openflow1.3的狀態轉移圖

0.SDN交換機的TCP主動連接 8s一個包,

同樣的,tcp連接成功後,馬上發送hello包

之後8s一個Hello包

如果沒收到hello的回覆包,是不會進入下一狀態的,會一直重傳hello包

1.ryu控制器是如何發現SDN交換機的?

    def serve(self):

        send_thr = hub.spawn(self._send_loop)

        # send hello message immediately
        hello = self.ofproto_parser.OFPHello(self)
        self.send_msg(hello) // 這一行是最重要的~~

        echo_thr = hub.spawn(self._echo_request_loop)

        try:
            self._recv_loop() // 處理TCP連接發送過來的報文
        finally:
            hub.kill(send_thr)
            hub.kill(echo_thr)
            hub.joinall([send_thr, echo_thr])
            self.is_active = False

可以試試把self.ofproto_parser.OFPHello(self) 這一行註釋掉,

然後你會發現找不到SDN交換機了(笑)因爲沒有hello的回覆包,無法進入下一狀態,

發送了hello包之後,纔會進入recv_loop協程,這個時候調用

    @set_ev_handler(ofp_event.EventOFPHello, HANDSHAKE_DISPATCHER)
    def hello_handler(self, ev):
        ......

        ......
        features_request = datapath.ofproto_parser.OFPFeaturesRequest(datapath)
        datapath.send_msg(features_request)

 

2.RYU控制器如何處理SDN交換機發送過來的TCP報文?

上面的recv_loop 就是,注意看源碼

    @_deactivate
    def _recv_loop(self):
        buf = bytearray()
        count = 0
        min_read_len = remaining_read_len = ofproto_common.OFP_HEADER_SIZE

        while self.state != DEAD_DISPATCHER:
            try:
                read_len = min_read_len
                if remaining_read_len > min_read_len:
                    read_len = remaining_read_len
                ret = self.socket.recv(read_len) # 先讀報文頭
            except SocketTimeout:
                continue
            except ssl.SSLError:
                # eventlet throws SSLError (which is a subclass of IOError)
                # on SSL socket read timeout; re-try the loop in this case.
                continue
            except (EOFError, IOError):
                break

            if not ret:
                break

            buf += ret # 讀到的字節
            buf_len = len(buf)

            while buf_len >= min_read_len:
                (version, msg_type, msg_len, xid) = ofproto_parser.header(buf) # 解析報文頭

                if msg_len < min_read_len:  # msg是包括報文頭的
                    # Someone isn't playing nicely; log it, and try something sane.
                    LOG.debug("Message with invalid length %s received from switch at address %s",
                              msg_len, self.address)
                    msg_len = min_read_len
                if buf_len < msg_len: # 有可能開始讀的只是報文頭,
# 但是msg_len是真實的報文長度,這個時候需要退出並繼續讀
                    remaining_read_len = (msg_len - buf_len)
                    break

                msg = ofproto_parser.msg(
                    self, version, msg_type, msg_len, xid, buf[:msg_len]) # 消息長度纔有意義
                # LOG.debug('queue msg %s cls %s', msg, msg.__class__)
                if msg:
                    ev = ofp_event.ofp_msg_to_ev(msg)
                    # print "in _recv_loop. ev_cls is %s" % ev.__class__
                    self.ofp_brick.send_event_to_observers(ev, self.state)

                    def dispatchers(x):
                        return x.callers[ev.__class__].dispatchers

                    handlers = [handler for handler in
                                self.ofp_brick.get_handlers(ev) if
                                self.state in dispatchers(handler)]
                    for handler in handlers:
                        # print "in _recv_loop, handler %s executed\n" % handler
                        handler(ev)

                buf = buf[msg_len:]  # 可能會有粘包的現象
                buf_len = len(buf)
                remaining_read_len = min_read_len

                # We need to schedule other greenlets. Otherwise, ryu
                # can't accept new switches or handle the existing
                # switches. The limit is arbitrary. We need the better
                # approach in the future.
                count += 1
                if count > 2048:
                    count = 0
                    hub.sleep(0)

3.一個完整的過程

4.OFPT_PACKET_IN報文 (無動作)

5.OFPT_PACKET_OUT響應報文

具體的報文

6.OFPT_FLOW_MOD報文

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章