(二)深入Openflowplugin源码 Switch生命周期对象
2019-06-11 陈卓文
可直接点击上方蓝字
(网易游戏运维平台)
关注我们,获一手游戏运维方案
陈卓文
陈卓文,网易游戏高级开发工程师,负责网易游戏私有云平台底层SDN/NFV网络的开发工作。
本文为 Openflowplugin(0.6.2) 源码分析第二篇,也是 Openflowplugin 为上层北向应用提供服务的关键逻辑的开篇!
回顾第一篇笔记,
在 Switch 连上控制器 Handshake 完成后,
最终调用ContextChainHolderImpl.deviceConnected
方法,会为 Switch 创建其对应的ContextChain
对象。
createContextChain(connectionContext);
先给出总结:在 Openflowplugin 中,每个 Switch 都有唯一的ContextChain
对象,管理其在 Openflowplugin 的生命周期。
1. 创建生命周期管理对象 ContextChain
通过调用
ContextChainHolderImpl.createContextChain
方法为连上的 switch 创建contextChain
对象,
在创建 ContextChain 前,会先为 Switch 创建四个对象 DeviceContext、RpcContext、StatisticsContext、RoleContext;
四个对象封装了 Switch 的四种类型操作:
Device 基本信息、Rpc 请求、Statistics 数据收集、Master/Slava 角色调用。
最后,将四个 Context 对象都传入 ContextChain 中管理。在下面会详细展开,每个步骤。
ContextChainHolderImpl.createContextChain
方法是 Switch 连上控制器 Handshake 完成后的核心调用,这个方法主要逻辑:
1.1 创建 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
对象。 -
创建
DeviceContextImpl
对象 -
创建
OpenflowProtocolListenerFullImpl
对象,并传入引用到connectionAdapterImpl
对象(setMessageListener
和setAlienMessageListener
),用于处理底层 switch 传递给控制器的所有 message。 -
注意:当 switch 连上控制器时
调用
ConnectionManagerImpl.onSwitchConnected()
方法,会同样会传入一个 MessageListener 对象
OpenflowProtocolListenerInitialImpl
,此对象仅能出来 Hello message,在 Handshake 阶段使用。
而此时 Handshake 已经结束,重新传入
OpenflowProtocolListenerFullImpl
用于处理所有 message。
1.2 创建 RpcContext
创建 rpcContext,且传入自身对象 (ContextChainHolderImpl) 引用
final RpcContext rpcContext = rpcManager.createContext(deviceContext);
rpcContext.registerMastershipWatcher(this);
创建 rpcContext 处理:创建RpcContextImpl
对象
1.3 创建 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 -
创建
StatisticsContextImpl
对象 -
传入了
MultipartWriterProvider
对象,目的是StatisticsContextImpl
收集的数据可以写入 device operational yang 节点
1.4 创建 RoleContext
创建 roleContext,且传入自身对象 (ContextChainHolderImpl) 引用
final RoleContext roleContext = roleManager.createContext(deviceContext);
roleContext.registerMastershipWatcher(this);
创建 roleContext 处理:
-
创建
RoleContextImpl
对象; -
创建
SalRoleServiceImpl
对象,传入
RoleContextImpl
。用于后续步骤,设置 Switch 的 Master/Slave role。
1.5 创建 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。
1.6 开始选举 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、slave、equal。为了控制层高可用使用 master/slave 模式;为了控制器负载均衡使用 equal 模式;
在此,我们不讨论 equal 模式,我们讨论 Master/slave 模型。
Openflowplugin 默认是以集群模型实现的,假设存在三个控制器节点,那么就会选举出一个节点作为某一个 Switch 的 Master( 不同 Switch,Master 不一定相同);
如果 Openflowplugin 作为单点控制器运行,那么它就是所有连上的 Switch 的 Master。
假设在三节点的集群情况下,Switch 连上所有控制节点,此时每个控制节点都有 Switch 的 ContextChain 对象,那么哪个节点是该 Switch 的 Master?
关键就是上面的这一行代码!由于篇幅问题,我们在下篇展开!
2. 总结
在 Switch 完成 Handshake 后,Openflowplugin 会为 Switch 创建各个 Context 对象(Device/Rpc/Statistics/Role),以及 ContextChain 对象。
敬请期待下期
(三)深入Openflowplugin源码 Master选举及Context服务实例化
往期精彩
﹀
﹀
﹀
(一)深入Openflowplugin源码分析Openflow握手过程
网易游戏《荒野行动》《阴阳师》等出海实践-AWS技术峰会演讲实录
感谢阅读,如果好看请点击右下角「在看」,点亮小星星,变亮的星星是小编的动力哦!