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报文

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