SDN控制器Floodlight源码学习(五)--控制器和交换机交互(3)

来源:互联网 发布:js 倒计时 编辑:程序博客网 时间:2024/06/05 08:28

上两篇诣在说明控制器和交换机的交互,但是感觉还是没有理的特别清楚

http://blog.csdn.net/crystonesc/article/details/70143117
http://blog.csdn.net/crystonesc/article/details/70170482

今天打算结合openflow协议和代码来说明,openflow版本较多,我选了具有代表性的1.0和1.3版本进行学习,主要还是要搞清楚floodlight中控制器和交换机的交互过程.
前面的两篇文章讲到,控制器与交换机建立连接后,是通过netty的pipeline交由

net.floodlightcontroller.core.internal.OFChannelHandler

这个handler来处理,这个handler主要完成hello,Feature,echo的状态交互,完成这些简单的握手后,OFChannelHandler将连接传递给更高级的处理层面,它是:
net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler
那么这个handler完成更多复杂的交互.值得说明这两个handler都在其内部设置了类似于状态机的内部类来完成状态的切换,所以通过查看这两个状态类,能够很快的跟踪到交互的过程。以下是OFChannelHandler的状态机类:
这里写图片描述
OFSwitchHandshakeHandler 状态机类如下:
这里写图片描述
当然通过抓包也能够很快的看出交互的过程,以下分别为of1.0和of1.3的抓包截图:
这里写图片描述
这里写图片描述
具体这些交互过程在做什么这里不做具体的介绍,有兴趣可以参考
OpenFlow Switch Specification(1.0/1.3)
我们继续往下看代码,在交换机和控制器交互的过程中,控制器会声明自己的角色(master/slave/equal),这里多嘴一句,只有master的控制器才能对交换机进行写的操作,而slave状态的控制器只能够进行读操作。那么我们看看作为master的控制器要做哪些工作:

public class MasterState extends OFSwitchHandshakeState {        MasterState() {            super(true);        }        @Override        void enterState() {            if (OFSwitchManager.clearTablesOnEachTransitionToMaster) {                log.info("Clearing flow tables of {} on upcoming transition to MASTER.", sw.getId().toString());                //清除已有的流表                clearAllTables();            } else if (OFSwitchManager.clearTablesOnInitialConnectAsMaster && initialRole == null) { /* don't do it if we were slave first */                initialRole = OFControllerRole.ROLE_MASTER;                log.info("Clearing flow tables of {} on upcoming initial role as MASTER.", sw.getId().toString());                clearAllTables();            }            sendBarrier(); /* Need to make sure the tables are clear before adding default flows */            addDefaultFlows();            /*             * We also need a barrier between adding flows and notifying modules of the             * transition to master. Some modules might modify the flow tables and expect              * the clear/default flow operations above to have completed.             */            sendBarrier();            setSwitchStatus(SwitchStatus.MASTER);        }}

可以看到,在master状态的交换机,首先要清除交换机的流表信息,然后添加默认的流表信息,最后将交换机的中自己的角色设置为master。(交换机是不能够自己修改其中维护的controller的角色的)
同时处于master的控制器还承担这分发交换机上传消息的职责,例如pack_i数据包:

@Overridevoid processOFPacketIn(OFPacketIn m) {            dispatchMessage(m);}/**     * Dispatches the message to the controller packet pipeline     */private void dispatchMessage(OFMessage m) {        this.switchManager.handleMessage(this.sw, m, null);} @Override public void handleMessage(IOFSwitchBackend sw, OFMessage m, FloodlightContext bContext) {        floodlightProvider.handleMessage(sw, m, bContext); }

最终pack_in数据包的处理是在floodlightProvider中来处理,也就是controller类中.

//controller将消息分发到IOFMessageListeners@Overridepublic void handleMessage(IOFSwitch sw, OFMessage m,                                 FloodlightContext bContext) {        Ethernet eth = null;        log.trace("Dispatching OFMessage to listeners.");        //如果contrller角色不是master,则不进行分发        if (this.notifiedRole == HARole.STANDBY) {            counters.dispatchMessageWhileStandby.increment();            // We are SLAVE. Do not dispatch messages to listeners.            return;        }        counters.dispatchMessage.increment();        switch (m.getType()) {            case PACKET_IN:                counters.packetIn.increment();                OFPacketIn pi = (OFPacketIn)m;                //获取packet-in消息的数据                if (pi.getData().length <= 0) {                    log.error("Ignoring PacketIn (Xid = " + pi.getXid() + ") because the data field is empty.");                    return;                }                //反序列化pack-in消息中的data                if (alwaysDecodeEth) {                    eth = new Ethernet();                    eth.deserialize(pi.getData(), 0, pi.getData().length);                }                // fall through to default case...            default:                List<IOFMessageListener> listeners = null;                if (messageListeners.containsKey(m.getType())) {                    listeners = messageListeners.get(m.getType()).getOrderedListeners();                }                FloodlightContext bc = null;                if (listeners != null) {                    // Check if floodlight context is passed from the calling                    // function, if so use that floodlight context, otherwise                    // allocate one                    if (bContext == null) {                        bc = flcontext_alloc();                    } else {                        bc = bContext;                    }                    if (eth != null) {                        IFloodlightProviderService.bcStore.put(bc,                                IFloodlightProviderService.CONTEXT_PI_PAYLOAD,                                eth);                    }                    // Get the starting time (overall and per-component) of                    // the processing chain for this packet if performance                    // monitoring is turned on                    pktinProcTimeService.bootstrap(listeners);                    pktinProcTimeService.recordStartTimePktIn();                    Command cmd;                    for (IOFMessageListener listener : listeners) {                        pktinProcTimeService.recordStartTimeComp(listener);                        cmd = listener.receive(sw, m, bc);                        pktinProcTimeService.recordEndTimeComp(listener);                        if (Command.STOP.equals(cmd)) {                            break;                        }                    }                    pktinProcTimeService.recordEndTimePktIn(sw, m, bc);                }                // paag                // And just before we exit the controller loop we see if anyone                // is interested in knowing that we are exiting the loop                for (IControllerCompletionListener listener : completionListeners)                    listener.onMessageConsumed(sw, m, bc);                if ((bContext == null) && (bc != null)) flcontext_free(bc);        }    }

可以看出pack_in消息会通过controller传递给其它实现了IOFMessageListeners的模块,由模块进行处理。至此交换机和控制器的数据就进入了各个模块中进行处理。下一节应该学习学习模块了.

0 0
原创粉丝点击