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

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);}@Overridevoid 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数据包:

@Override
void 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);
}@Overridepublic void handleMessage(IOFSwitchBackend sw, OFMessage m, FloodlightContext bContext) {floodlightProvider.handleMessage(sw, m, bContext);}

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

//controller将消息分发到IOFMessageListeners
@Override
public 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消息中的dataif (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 oneif (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 onpktinProcTimeService.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 loopfor (IControllerCompletionListener listener : completionListeners)listener.onMessageConsumed(sw, m, bc);if ((bContext == null) && (bc != null)) flcontext_free(bc);}}

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

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

  1. lua_gc 源码学习五

    今天来说说 write barrier . 在 GC 的扫描过程中,由于分步执行,难免会出现少描了一半时,那些已经被置黑的对象又被修改,需要重新标记的情况.这就需要在改写对象时,建立 write ba ...

  2. mutations vuex 调用_Vuex源码学习(六)action和mutation如何被调用的(前置准备篇)...

    前言 Vuex源码系列不知不觉已经到了第六篇.前置的五篇分别如下: 长篇连载:Vuex源码学习(一)功能梳理 长篇连载:Vuex源码学习(二)脉络梳理 作为一个Web前端,你知道Vuex的instal ...

  3. action mutation 调用_Vuex源码学习(六)action和mutation如何被调用的(前置准备篇)...

    module与moduleCollection你一定要会啊!Vuex源码学习(五)加工后的module 在组件中使用vuex的dispatch和commit的时候,我们只要把action.mutati ...

  4. Codeigniter 4.0-dev 版源码学习笔记之六——控制器

    前言 其实一开始我是很纠结是否要写控制器的源码分析的,因为控制器的源码太少了,少到你不相信这是一个 MVC 里的一个重头.直觉里,大家都觉得控制器作为各个请求的"入口",其后端应该 ...

  5. ThinkPHP源码解析之控制器

    本文会对控制器的执行顺序还有实现过程.源码解析给出解析, ThinkPHP源码解析之控制器 前言 一.实例化控制器 二.关于ArrayAccess和直接执行魔术访问返回实例的区别 三.执行控制器中的方 ...

  6. 智能家居硬件小制作(含源码)《手势识别控制器》基于PAJ7620手势模块、L298N驱动板、arduino

    智能家居硬件小制作(含源码)<手势识别控制器>基于PAJ7620手势模块.L298N驱动板.arduino 目录 智能家居硬件小制作(含源码)<手势识别控制器>基于PAJ762 ...

  7. Vuex 4源码学习笔记 - 通过dispatch一步步来掌握Vuex整个数据流(五)

    在上一篇笔记中:Vuex 4源码学习笔记 - Store 构造函数都干了什么(四) 我们通过查看Store 构造函数的源代码可以看到主要做了三件事情: 初始化一些内部变量以外 执行installMod ...

  8. Vuex源码学习(五)加工后的module

    没有看过moduleCollection那可不行!Vuex源码学习(四)module与moduleCollection 感谢提出代码块和截图建议的小伙伴 代码块和截图的区别: 代码块部分希望大家按照我 ...

  9. DotText源码学习——ASP.NET的工作机制

    --本文是<项目驱动学习--DotText源码学习>系列的第一篇文章,在这之后会持续发表相关的文章. 概论 在阅读DotText源码之前,让我们首先了解一下ASP.NET的工作机制,可以使 ...

最新文章

  1. 拉格朗日乘数法的原理,我用10幅图把它讲清楚了
  2. centos下tomcat6.0.28配置
  3. 设计模式的理解:组合模式 (Composite)
  4. 【Qt】Qt登录对话框(纯代码实现)
  5. Flink + Iceberg,百亿级实时数据入湖实战
  6. u盘文件名乱码linux,U盘文件名乱码的原因和解决办法
  7. 实用的智力测试智商提升微信小程序源码下载支持多种流量主
  8. FaceBook第三方登录获取姓名,头像,邮箱等个人信息
  9. YOLOV5出现.acceptable suffix is [‘.pt‘]的错误||不使用权重报错
  10. 冉宝的每日一题-8月16日回溯法+ 动态规划压缩
  11. 在网页上面录制声音(chrome、firefox浏览器可用)
  12. 彗星通行证的积分规则是什么?
  13. [英文邮件写作技巧] 表达感谢,提出问题,描述附件
  14. “前程无忧”招聘数据预处理——(2)
  15. stimulsoft入门教程:报表与页面上的图表(一)
  16. MR21修改物料标准价
  17. 2021物理化学实验4:液体饱和蒸气压的测定
  18. python制作刮刮乐惊喜揭秘呀~【趣味代码】
  19. java毕业设计鸿鹄教育培训(附源码、数据库)
  20. 关于如何在XP系统上运行opencv生成的C++动态库

热门文章

  1. Word如何从目录后加页码
  2. Vue美食杰项目个人主页
  3. [深度学习]CNN的基础结构与核心思想
  4. 福清龙华职业中专计算机应用学校什么,福建省福清龙华职业中专学校招生专业|福建省福清龙华职业中专学校有哪些专业...
  5. 【总结】PHP常见面试题汇总(一)
  6. 儿童护眼灯怎么选?国家质检合格的儿童护眼灯
  7. oracle lms进程 内存,lms进程耗用大量内存
  8. ASCP300-63B——三相电气防火限流式保护器
  9. 医院公厕智能化管理需要实现哪些功能
  10. 关于requests.exceptions.SSLError: HTTPSConnectionPool(host='XXX', port=443)问题