内容简介:【编者的话】本文为OpenFlowPlugin(0.6.2)源码分析第二篇,也是OpenFlowPlugin为上层北向应用提供服务的关键逻辑的开篇!回顾第一篇笔记,在Switch连上控制器Handshake完成后,会调用先给出总结:在OpenFlowPlugin中,每个Switch都有唯一的
【编者的话】本文为OpenFlowPlugin(0.6.2)源码分析第二篇,也是OpenFlowPlugin为上层北向应用提供服务的关键逻辑的开篇!
回顾第一篇笔记,在Switch连上控制器Handshake完成后,会调用 ContextChainHolderImpl.deviceConnected 方法,会为Switch创建其对应的 ContextChain 对象则创建。
createContextChain(connectionContext);
先给出总结:在OpenFlowPlugin中,每个Switch都有唯一的 ContextChain 对象,管理其在OpenFlowPlugin的生命周期。
创建生命周期管理对象ContextChain
为连上的Switch创建 contextChain 对象,通过调用 ContextChainHolderImpl.createContextChain 方法。在创建ContextChain前,会先为Switch创建四个对象DeviceContext、RpcContext、StatisticsContext、RoleContext,四个对象封装了Switch的四种类型操作:Device基本信息、RPC请求、Statistics数据收集、Master/Slava角色调用。最后,将四个Context对象都传入ContextChain中管理。在下面会详细展开,每个步骤。
ContextChainHolderImpl.createContextChain 方法是Switch连上控制器Handshake完成后的核心调用,这个方法主要逻辑:
创建DeviceContext
创建deviceContext,且传入自身对象(ContextChainHolderImpl)引用:
final DeviceContext deviceContext = deviceManager.createContext(connectionContext); deviceContext.registerMastershipWatcher(this);
创建 deviceContext 处理:
- 设置
ConnectionAdapterImpl对象中设置packetIn filter为true,目的是为了过滤后续过程中收到底层Switch的packetIn message
- 注:可以看到在
ContextChainHolderImpl.createContextChain方法后面会将packetIn filter恢复为false。
- 注:可以看到在
- 创建
OutboundQueueHandler对象并传入对象引用到connectionAdapterImpl和connectionContext
-
OutboundQueueHandler对象用于Packet output先到Queue,再到ConnectionAdapterImpl对象。另外一篇:《OpenFlowPlugin outbound机制》会展开,在此不深入。
-
- 创建
DeviceContextImpl对象 - 创建
OpenflowProtocolListenerFullImpl对象,并传入引用到connectionAdapterImpl对象(setMessageListener和setAlienMessageListener),用于处理底层Switch传递给控制器的所有message。
- 注意:在上两篇笔记中,当Switch连上控制器时调用
ConnectionManagerImpl.onSwitchConnected()方法,会同样会传入一个MessageListener对象OpenflowProtocolListenerInitialImpl,此对象仅能出来Hello message,在Handshake阶段使用。而此时Handshake已经结束,重新传入OpenflowProtocolListenerFullImpl用于处理所有message。
- 注意:在上两篇笔记中,当Switch连上控制器时调用
创建RpcContext
创建RpcContext,且传入自身对象(ContextChainHolderImpl)引用:
final RpcContext rpcContext = rpcManager.createContext(deviceContext); rpcContext.registerMastershipWatcher(this);
创建rpcContext处理:
- 创建
RpcContextImpl对象
创建StatisticsContext
创建StatisticsContext,且传入自身对象(ContextChainHolderImpl)引用:
final StatisticsContext statisticsContext = statisticsManager.createContext(deviceContext, ownershipChangeListener.isReconciliationFrameworkRegistered()); statisticsContext.registerMastershipWatcher(this);
创建StatisticsContext处理:
- 创建
MultipartWriterProvider对象
- 注意这里传入了deviceContext,是为了write到device的operational yang。
deviceContextImpl中有写入device对应yang需要的TransactionChain
- 注意这里传入了deviceContext,是为了write到device的operational yang。
- 创建
StatisticsContextImpl对象
- 传入了
MultipartWriterProvider对象,目的是StatisticsContextImpl收集的数据可以写入device operational yang节点
- 传入了
创建RoleContext
创建RoleContext,且传入自身对象(ContextChainHolderImpl)引用:
final RoleContext roleContext = roleManager.createContext(deviceContext); roleContext.registerMastershipWatcher(this);
创建RoleContext处理:
- 创建
RoleContextImpl对象; - 创建
SalRoleServiceImpl对象,传入RoleContextImpl。用于后续步骤,设置Switch的Master/Slave role。
创建ContextChain
在创建4个Context后,创建 ContextChainImpl 对象。然后向 ContextChainImpl 对象注册/加入各个对象:
- 给
ContextChainImpl对象注册registerDeviceRemovedHandler,用于后续Switch下线过程清除Manger中各个Context的索引。 - 给
ContextChainImpl对象添加Context(addContext)。 - 最后将
ContextChainImpl对象保存到ContextChainHolderImpl.contextChainMap中,相当于一个索引。ContextChainHolderImpl维护了各个Switch的ContextChain对象。
注意 addContext 是把传入的deviceContext/rpcContext/statisticsContext/roleContext封装到 GuardedContextImpl 对象。 GuardedContextImpl 对象仅做多一层封装,会记录具体Context的状态等。
@Override
public <T extends OFPContext> void addContext(@Nonnull final T context) {
contexts.add(new GuardedContextImpl(context));
}
最后,完成创建 ContextChainImpl 对象后,将设备从 connectingDevices 索引中删除。表示已经在控制器connected。
开始选举Master/Slave
上文基本展开了 ContextChainHolderImpl.createContextChain 方法详细讲解,唯独缺少最后一行代码,这也是最关键一行!调用ContextChain的registerServices方法:
contextChain.registerServices(singletonServiceProvider);
在展开这一行代码的逻辑之前,我们先回顾一下全文!可以看到,在Switch完成Handshake后,OpenFlowPlugin会为Switch创建ContextChain对象(包括各个Context)。考虑到多个控制器情况下,当Switch设置多个控制器(比如OVS:set-controller),那么哪个控制器能够对Switch操作,比如下发流表。因为在每个控制器,OpenFlowPlugin都会为Switch创建ContextChain对象。
OpenFlow协议,支持多个控制器,且控制器有角色有三类Master、Master、Equal。为了控制层高可用使用Master/Slave模式;为了控制器负载均衡使用equal模式。
在此,我们不讨论Equal模式,我们讨论Master/Slave模型。OpenFlowPlugin默认是以集群模型实现的,假设存在三个控制器节点,那么就会选举出一个节点作为某一个Switch的Master(不同Switch,Master不一定相同);如果OpenFlowPlugin作为单点控制器运行,那么它就是所有连上的Switch的Master。
假设在三节点的集群情况下,Switch连上所有控制节点,此时每个控制节点都有Switch的ContextChain对象,那么哪个节点是该Switch的Master?关键就是上面的这一行代码!由于篇幅问题,我们在下篇展开!
总结
在Switch完成Handshake后,OpenFlowPlugin会为Switch创建各个Context对象(Device/RPC/Statistics/Role),以及ContextChain对象。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 深入OpenFlowPlugin源码分析OpenFlow握手过程(一)
- 源码角度分析 OkHttp 实现 WebSocket:握手/保活/数据处理...
- TCP 的 三次握手 四次握手
- TCP连接为什么是三次握手,而不是两次握手,也不是四次握手?
- 握手过程中,非对称密钥的应用
- 用 Wireshark 图解 TCP 三次握手
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
无懈可击的Web设计
【美】Dan Cederholm / 马跃 / 清华大学出版社 / 2012-5 / 39.00元
本书将指导您采用标准设计策略来满足以各种方式浏览网页的各类用户的需要。每章首先列举一个沿用传统HTML技术的实例,然后指出该实例的局限性,并利用XHTML和CSS对其进行重构。从中您将学会如何用简洁高效的HTML标记和CSS来取代臃肿的代码,从而创建加载速度极快、能供所有用户使用的网站。本书最后将前面各章讨论的所有页面组件珠联璧合地结合在一起,制作了一个页面模板。这一版全面润色和更新了上一版本,介......一起来看看 《无懈可击的Web设计》 这本书的介绍吧!