(一)ODL OpenflowPlugin启动流程源码分析

作者简介:陈卓文,国内某游戏公司私有云团队开发者,主要从事SDN/NFV开发。

本文为OpenflowPlugin源码分析第一篇,会有一系列文章深入openflowplugin,包括device上线handshake、master选举、调用ofp提供rpc服务、statistics gather。本文首先从OpenflowPlugin是如何启动展开。

读者约定:基本掌握Opendaylight的思想/有一定实践经验,想要深入理解openflowplugin源码/想对openflowplugin源码修改。

启动过程

1.创建SwitchConnectionProviderFactoryImpl作为service注入OSGI

openflow-protocol-impl/src/main/resources/org/opendaylight/blueprint/openflow-protocol-impl.xml中实例化SwitchConnectionProviderFactoryImpl.java作为service注入OSGI

SwitchConnectionProviderFactoryImpl作用是提供newInstance()工厂方法,创建SwitchConnectionProviderImpl对象。

2.创建SwitchConnectionProvider对象作为service注入OSGI

openflowjava/openflowjava-blueprint-config/src/main/resources/org/opendaylight/blueprint/openflowjava.xml中:

1.引用上面注入OSGI的switchConnectionProviderFactory服务

2.读取配置,调用switchConnectionProviderFactory工厂方法newInstance()创建switchConnectionProvider:

特别说明:
1)上面分别读取了配置文件,创建了两个switchConnectionProvider:defaultSwitchConnProvider及legacySwitchConnConfig
2)两个provider分别会监听6653、6633端口,分别是支持openflow1.3、openflow1.0
3)在blueprint中,将defaultSwitchConnProvider及legacySwitchConnProvider作为服务注入到OSGI,供后续其他bundle引用

调用switchConnectionProviderFactory的newInstance()方法,实际就是new SwitchConnectionProviderImpl()。过程会创建serializationFactory、deserializationFactory:

说明:
SwitchConnectionProviderImpl对象,为switch连上控制器提供端口监听tcp/udp 6633/6653。

至此,SwitchConnectionProviderImpl对象已经被创建,且创建了serializationFactory、deserializationFactory。但是,还没有看到启动服务监听端口的调用,后续我们会看到其他bundle引用SwitchConnectionProviderImpl,然后启动服务监听端口。

而上述“其他bundle”正是openflowPlugin的bundle,在下面展开。

SwitchConnectionProviderImpl除了OpenflowPlugin中会引用,在openflow项目下的onf-extension及niciria-extension会对其进行扩展register Serializer/Deserializer.

3.创建OpenFlowPluginProviderFactoryImpl作为service注入OSGI

openflowplugin-impl/src/main/resources/org/opendaylight/blueprint/openflowplugin-impl.xml中,实例化OpenFlowPluginProviderFactoryImpl.java作为service注入OSGI

OpenFlowPluginProviderFactoryImpl作用是提供newInstance()工厂方法,创建OpenFlowPluginProviderImpl对象:

  • newInstance()方法创建OpenFlowPluginProviderImpl对象,并调用其initialize()
    方法

4.创建OpenFlowPluginProvider对象作为service注入OSGI

openflowplugin-blueprint-config/src/main/resources/org/opendaylight/blueprint/openflowplugin.xml中,引用reference 上描述在OGSI中作为serviceOpenFlowPluginProviderFactoryImpl,并调用其工厂方法newInstance();并将其创建的openflowPluginProvider作为service注入到OSGI中。

OpenflowPluginProviderImplnewInstance()方法调用:

  • 注册MXBean
  • 创建线程池对象
  • 创建DeviceManagerImpl
  • 创建RpcManagerImpl
  • 创建StatisticsManagerImpl
  • 创建RoleManagerImpl
  • 创建ContextChainHolderImpl
  • 创建ConnectionManagerImpl
  • 调用DeviceManagerImpl.initialize()

OpenflowPluginProvider初始化过程

1.创建了四个managerDeviceManagerImpl,RpcManagerImpl,StatisticsManagerImpl,RoleManagerImpl,用于当有switch连上控制器时用于为connection处理。

2.创建ContextChainHolderImpl对象,将四个manager addManager()进去。而ContextChainHolderImpl会在switch连上控制器时,为每个connection创建ContextChainImpl

3.创建ConnectionManagerImpl,用于底层openflowjava到openflowplugin的关键桥梁对象,当switch连上控制器,会触发ConnectionManagerImpl.onSwitchConnected方法。用于manager connection,后面会详细阐述。

4.调用DeviceManagerImpl.initialize(),创建线程监听消息,比如统计,具体处理在MessageIntelligenceAgencyImpl.java

注意,OpenflowPlugin0.6.2与0.5.4-SNATSHOP版本有一个最大的区别,OpenflowPluginProvider.startSwitchConnections方法被调用方式。
在0.5.4-SNATSHOP中,此方法是在initialize()方法最后会被调用。而0.6.2 OpenflowPluginProvider实现了接口SystemReadyListener,用于当系统ready时候可以做某些操作,而在OpenflowPluginProvider 0.6.2的处理是调用startSwitchConnections方法:

可以看到startSwitchConnections方法,最重要的逻辑是:

其目的是,将OpenflowPluginProvider中创建的connectionManager传入到上面提及Openflowjava中的SwitchConnectionProviderImpl对象,并调用其startup方法。

可以注意到这里SwitchConnectionProviderImpl是在openflowjava的blueprint中创建的,而实际调用其startup方法是在OpenflowPlugin中,这里很能体现OSGI模块化的思想。

接下来可以展开SwitchConnectionProviderImpl.startup()方法:其最终作用是创建tcp/udp的server监听6633、6653端口,当switch连上端口(控制器)时,调用connectionManager的onSwitchConnected方法,进而进入接下来OpenflowPlugin的处理(比如Handshake,创建各个context,mastership选举等)。

以TCP为例,展开。startup方法的核心是serverFacade = createAndConfigureServer();

在这个方法内,几个关键地方,可以说明Openflowjava中有switch连上后,触发ConnectionManagerImpl的onSwitchConnected方法的调用:
1.switchConnectionHandler是在OpenflowPlugin创建的ConnectionManagerImplChannelInitializerFactory对象创建后是通过setSwitchConnectionHandler(switchConnectionHandler)方法设置了ConnectionManagerImpl对象;

2.通过ChannelInitializerFactory factory对象创建的TcpChannelInitializer对象是有ConnectionManagerImpl对象,并set到tcp servier对象。

3.用于初始化tcp connection的对象TcpConnectionInitializer中,是有传入(setChannelInitializer)TcpChannelInitializer channelInitializer(TcpChannelInitializer带有ConnectionManagerImpl对象引用)

然后回到startup方法,new Thread(serverFacade).start();将tcp server(TcpHandler对象)运行。

TcpHandler.run方法中,.childHandler(channelInitializer)调用上述创建的TcpChannelInitializer对象(带有ConnectionManagerImpl对象引用)。

对netty底层的调用不熟悉,大胆猜测。当有switch通过tcp connect到6633/6653监听端口(TcpHandler),就会调用TcpChannelInitializer对象的initChannel方法。在initChannel方法中可以看到调用ConnectionManagerImpl的onSwitchConnected方法:

下篇笔记再讲述switch连上控制器后,怎么进行握手handshake等动作。

总结

至此,可以完整看Openflowjava/Openflowplugin启动流程,ODL是如何监听openflow端口,并且当switch连上控制器后如何开始调用OpenflowPlugin中的方法。openflowplugin项目充分利用了OSGI的特性,各个“bundle”通过OSGI实现调用。

本文,只描述Openflowjava和OpenflowPlugin启动过程,而onSwitchConnected方法的后续调用,下篇笔记展开。

关键类/对象

个人理解整理:

学习时间

未来网络学院小程序上线了,全场课程限时优惠,口碑课程历史低价,欢迎扫描下图关注哦。

1

1


  • 本站原创文章仅代表作者观点,不代表SDNLAB立场。所有原创内容版权均属SDNLAB,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用,转载须注明来自 SDNLAB并附上本文链接。 本站中所有编译类文章仅用于学习和交流目的,编译工作遵照 CC 协议,如果有侵犯到您权益的地方,请及时联系我们。
  • 本文链接https://www.sdnlab.com/21199.html
分享到:
相关文章
条评论

登录后才可以评论

陈卓文 发表于18-08-01
3