ONOS使用OFChannelHandler类来处理交换机和控制器的信道连接,同时将switch message分发到合适的位置,代码在package org.onosproject.openflow.controller.impl中。
1. OpenFlow状态机:ChanelState
在OFChannelHandler类中,最重要的就是一个ChanelState的枚举类了,枚举类中的各个枚举实例表示Channel所处的状态,用来描述OpenFlow状态机信息,在枚举类中添加了处理OpenFlow消息的方法,各个枚举实例也根据自身的状态重写了部分方法。
OpenFlow状态机共定义了8种状态(INIT, WAIT_HELLO, WAIT_FEATURES_REPLY, WAIT_PORT_DESC_REPLY, WAIT_CONFIG_REPLY, WAIT_DESCRIPTION_STAT_REPLY, WAIT_SWITCH_DRIVER_SUB_HANDSHAKE, ACTIVE),任何时候,Channel处于状态机中的任意一种状态。每个状态(枚举实例)都有一个默认初始化参数,其中false表示交换机握手没有成功,true表示交换机握手成功,枚举类的构造函数和获取交换机握手状态的代码块如下:
1 | private final boolean handshakeComplete; |
2. OpenFlow状态机启动流程
ONOS使用netty通信框架(参考:Netty 实战),在这里就不考虑netty相关的NIO过程了。ONOS启动ChannelHander对应的实例时,构造函数OFChannelHandler(Controller controller) 会引用当前的控制器实例,同时会将stage初始化为ChannelState.INIT状态,表示Channel处于连接之前(代码注释很清楚)。注意,OFChannelHandler中的state变量是volatile类型,这是为了确保HandshakeTimeoutHandler检测到的state状态都是最新的,至于volatile关键字的用法,建议参考:Java并发编程:volatile关键字解析
当Channel检测到交换机连接时,会调用OFChannelHandler类中的channelConnected函数:
1 |
|
在这里,state被设置为ChannelState.WAIT_HELLO状态,顾名思义,就是等待交换机的hello消息了。当Channel得到交换机发往控制器的消息时,就会调用messageReceived函数,messageReceived又会调用当前状态机实例的processOFMessage方法,处理OFMessage消息,各种不同的OFMessage消息对应了不同的消息处理函数,在ChannelState枚举类中都有定义。需要注意的是,不同的状态机实例可能根据当前状态重写ChannelState中的消息处理函数,因此同一消息类型在不同的状态下的处理逻辑可能是不一样的。OFMessage处理完成后,调用setState方法来切换状态机,握手成功后,状态机处于ACTIVE(true)状态。
1 |
|
1 | /** |
以上就是状态机启动的基本流程了,更详细的过程看OFChannelHandler源码。
参考: