博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Floodlight 源码解读 :Main
阅读量:7255 次
发布时间:2019-06-29

本文共 6333 字,大约阅读时间需要 21 分钟。

Floodlight 的 Main 解析图


需要理解的概念

模块(Module)

Module 是指继承了 IFloodlightModule 接口的类

IFloodlightModule的相关注释

Defines an interface for loadable Floodlight modules. At a high level, these functions are called in the following order:   getModuleServices() : 获得模块实现的服务列表  getServiceImpls(); 实例化并返回:服务实现类-实现此服务的对象 映射  getModuleDependencies() : 获得模块依赖的列表  init() : internal initializations (don't touch other modules)  startUp() : external initializations (do touch other modules)

所有可加载的模块都有这几种方法,在接下来的加载模块时需要使用到。

每个具体的模块都会重写这几个函数,下面举个 FloodlightProvider 的例子。

getModuleServices()

@Overridepublic Collection
> getModuleServices() { Collection
> services = new ArrayList
>(1); services.add(IFloodlightProviderService.class); return services;}

获得 FloodlightProvider 的服务 IFloodlightProviderService

getServiceImple()

@Overridepublic Map
, IFloodlightService> getServiceImpls() { controller = new Controller(); Map
, IFloodlightService> m = new HashMap
, IFloodlightService>(); m.put(IFloodlightProviderService.class, controller); return m;}

返回服务实现类和实现用的对象的Map。

getModuleDependencies()

@Overridepublic Collection
> getModuleDependencies() { Collection
> dependencies = new ArrayList
>(4); dependencies.add(IStorageSourceService.class); dependencies.add(IPktInProcessingTimeService.class); dependencies.add(IRestApiService.class); dependencies.add(IDebugCounterService.class); dependencies.add(IOFSwitchService.class); dependencies.add(IThreadPoolService.class); dependencies.add(ISyncService.class); return dependencies;}

返回依赖的列表

其他

init(),startup(),到对应的模块去看就可以了。

有的模块是没有服务依赖的,比如 ThreadPool模块。

服务(Service)

Service 是指继承了 IFloodlightService 接口的类。

public abstract interface IFloodlightService {   // This space is intentionally left blank....don't touch it}

模块使用getModuleServices()方法可以获得对应的服务列表,可以到源码去看对应的服务功能。

Main函数

  1. 解析命令行参数
  2. 加载模块
  3. 启动 REST 服务器
  4. 启动 Controller

命令行参数解析

CmdLineSetting 定义了命令行参数的格式

public static final String DEFAULT_CONFIG_FILE = "src/main/resources/floodlightdefault.properties";@Option(name="-cf", aliases="--configFile", metaVar="FILE", usage="Floodlight configuration file")private String configFile = DEFAULT_CONFIG_FILE;

如果没有使用-cf指定配置文件路径,则使用默认路径“src/main/resources/floodlightdefault.properties”

CmdLineParser 解析命令参数

CmdLineParser parser = new CmdLineParser(settings)parser.parserArgument(args)

加载模块

moduleContext=fml.loadModulesFromConfig(settings.getModuleFile())

settings.getModuleFile()提供配置文件的路径

mergeProperties()

  • 目的是获得配置文件里的模块的集合configMods和prop是除去配置文件里的模块键值对后剩余的配置信息(模块的配置参数)

loadModulesFromList(configsMods,prop)

findAllModule(configMods)
  • 填充moduleNameMap,moduleServiceMap,ServiceMap

这个方法比较重要的是这个 ServiceLoader,返回服务加载器

ServiceLoader
moduleLoader = ServiceLoader.load(IFloodlightModule.class, cl);

ServiceLoader 为了注册服务,需要在类路径 src/main/resources/META_INF/services文件夹内列好注册服务的模块,可以得到继承了 IFloodlightModule 接口的实现类

使用moduleLoader.iterator()迭代器去填充moduleNameMap,moduleServiceMap,ServiceMap
moduleNameMap 模块名称-模块对象 Map
moduleServiceMAP 模块名称-模块服务 Map
ServiceMap 模块服务-模块名称 Map

traverseDeps(moduleName,modsToLoad,moduleList,moduleMap,modsVisited)
addModule()
  • 添加模块到模块的哈希集moduleMap,同时注册它们的服务(即得到已加载模块序列 moduleList)
parseConfigParameters(prop)
  • 解析每个模块的配置参数

取配置文件的一条参数配置net.floodlightcontroller.forwarding.Forwarding.match=in-port, vlan, mac, ip, transport举例

key:net.floodlightcontroller.forwarding.Forwarding.match

String configKey=key.substring(LastPeriod+1)

获到的就是 match,即 configKey=match

String systemKey = System.getProperty(key);if (systemKey != null) {            configValue = systemKey;        } else {            configValue = prop.getProperty(key);        }

如果系统属性已经存在,则使用系统属性的值,如果不存在,则configValue = prop.getProperty(key);【即 configValue 在此处为in-port, vlan, mac, ip, transport】

floodlightModuleContext.addConfigParam(mod,configKey,configValue)
  • 添加模块的配置参数

FloodlightModuleLoader 类下的方法

public void addConfigParam(IFloodlightModule mod, String key, String value) {    Map
moduleParams = configParams.get(mod.getClass()); if (moduleParams == null) { moduleParams = new HashMap
(); configParams.put(mod.getClass(), moduleParams); } moduleParams.put(key, value);}
initModules(moduleList)
  • 初始化已加载模块列表下的模块

获得模块的服务实例

Map
, IFloodlightService> simpls = module.getServiceImpls();

添加服务到 floodlightModuleContext

if (floodlightModuleContext.getServiceImpl(s.getKey()) == null) {                    floodlightModuleContext.addService(s.getKey(),                                                       s.getValue());

遍历已加载模块集,开始初始化模块,调用模块的方法:init

for (IFloodlightModule module : moduleSet) {        // init the module        if (logger.isDebugEnabled()) {            logger.debug("Initializing " +                         module.getClass().getCanonicalName());        }        module.init(floodlightModuleContext);    }
startupModules(moduleList)
  • 调用已加载模块的启动方法

遍历已加载模块集,调用每个模块的启动方法

for (IFloodlightModule m : moduleSet) {        if (logger.isDebugEnabled()) {            logger.debug("Starting " + m.getClass().getCanonicalName());        }        m.startUp(floodlightModuleContext);    }
return floodlightModuleContext

返回公共环境变量

fml.runModules()

  • 运动控制器模块和所有模块

getModuleList()

  • 获得一个按初始化顺序的模块列表

返回一个不可修改的已加载模块序列,如果没被初始化则返回 null

public List
getModuleList() { if (loadedModuleList == null) return Collections.emptyList(); else return Collections.unmodifiableList(loadedModuleList);}

runModules()

for (IFloodlightModule m : getModuleList()) {        for (Method method : m.getClass().getDeclaredMethods()) {            Run runAnnotation = method.getAnnotation(Run.class);            if (runAnnotation != null) {                RunMethod runMethod = new RunMethod(m, method);                if(runAnnotation.mainLoop()) {                    mainLoopMethods.add(runMethod);                } else {                    runMethod.run();                }            }        }    }

for 循环遍历模块中的方法,找到@run注解的方法为主方法,以下的就是 FloodlightProvider 提供的 run 方法

@Run(mainLoop=true)public void run() throws FloodlightModuleException {    controller.run();}

运行控制器的模块

mainLoopMethods.get(0).run();

转载地址:http://encdm.baihongyu.com/

你可能感兴趣的文章
docker for mysql
查看>>
css中nth-child的使用注意
查看>>
scss中文报错解决办法
查看>>
美国白宫都使用的内容管理系统——Drupal!
查看>>
linux快速学习之linux目录结构详细介绍
查看>>
MySQL数据库表名、列名、别名区分大小写的问题
查看>>
Java入门第五篇:Java集合框架的Collection、List、Set、Map接口
查看>>
搭建 MongoDB 服务器,MongoDB 基本使用,数据导入导出
查看>>
Linux系统的根目录下主要包括哪些文件夹,各自的作用
查看>>
Windows 10再推新策略 外接储存装置可直接拔掉免安全移除程序
查看>>
网络工程师成长日记309-西安李宁项目
查看>>
PXE网络自动装机
查看>>
Java之品优购课程讲义_day05(3)
查看>>
解决h5网页微信分享链接不能显示缩略
查看>>
简练软考知识点整理-制定项目章程过程
查看>>
Android Bundle详解
查看>>
看书2遍,汪博士1遍,视频2遍,刷题通过PMP考试
查看>>
链盟| 链改这趟快车,你能上吗?
查看>>
galera mysql 多主复制启动顺序及命令
查看>>
双十二,1+1双班启航,祝你开启高薪道路!
查看>>