Floodlight源码阅读之链路发现

2024-05-10 18:18

本文主要是介绍Floodlight源码阅读之链路发现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Floodlight的链路发现基于LLDP,LLDP并不是Floodlight发明的,他全称叫做链路层发现协议,一个和厂商无关的二层协议

链路发现的核心代码在LinkDiscoveryManager这个类里面。它实现了IOFMessageListener用于接收消息,还实现了IFloodlightModule,那么它就是Floodlight的一个模块了,整个Floodlight都是模块化的,后续文章讲解Floodlight的各个模块以及模块依赖等。

既然实现了IFloodlightModule模块,就要实现其启动方法,startup。

public void startUp(FloodlightModuleContext context) throws FloodlightModuleException {// Initialize role to floodlight provider role.this.role = floodlightProviderService.getRole();// Create our storage tablesif (storageSourceService == null) {log.error("No storage source found.");return;}storageSourceService.createTable(TOPOLOGY_TABLE_NAME, null);storageSourceService.setTablePrimaryKeyName(TOPOLOGY_TABLE_NAME,TOPOLOGY_ID);readTopologyConfigFromStorage();storageSourceService.createTable(LINK_TABLE_NAME, null);storageSourceService.setTablePrimaryKeyName(LINK_TABLE_NAME, LINK_ID);storageSourceService.deleteMatchingRows(LINK_TABLE_NAME, null);// Register for storage updates for the switch tabletry {storageSourceService.addListener(SWITCH_CONFIG_TABLE_NAME, this);storageSourceService.addListener(TOPOLOGY_TABLE_NAME, this);} catch (StorageException ex) {log.error("Error in installing listener for "+ "switch table {}", SWITCH_CONFIG_TABLE_NAME);}ScheduledExecutorService ses = threadPoolService.getScheduledExecutor();// To be started by the first switch connectiondiscoveryTask = new SingletonTask(ses, new Runnable() {@Overridepublic void run() {try {discoverLinks();} catch (StorageException e) {shutdownService.terminate("Storage exception in LLDP send timer. Terminating process " + e, 0);} catch (Exception e) {log.error("Exception in LLDP send timer.", e);} finally {if (!shuttingDown) {// null role implies HA mode is not enabled.if (role == null || role == HARole.ACTIVE) {log.trace("Rescheduling discovery task as role = {}",role);discoveryTask.reschedule(DISCOVERY_TASK_INTERVAL,TimeUnit.SECONDS);} else {log.trace("Stopped LLDP rescheduling due to role = {}.",role);}}}}});// null role implies HA mode is not enabled.if (role == null || role == HARole.ACTIVE) {log.trace("Setup: Rescheduling discovery task. role = {}", role);discoveryTask.reschedule(DISCOVERY_TASK_INTERVAL,TimeUnit.SECONDS);} else {log.trace("Setup: Not scheduling LLDP as role = {}.", role);}// Setup the BDDP task. It is invoked whenever switch port tuples// are added to the quarantine list.bddpTask = new SingletonTask(ses, new QuarantineWorker());bddpTask.reschedule(BDDP_TASK_INTERVAL, TimeUnit.MILLISECONDS);updatesThread = new Thread(new Runnable() {@Overridepublic void run() {while (true) {try {doUpdatesThread();} catch (InterruptedException e) {return;}}}}, "Topology Updates");updatesThread.start();// Register for the OpenFlow messages we want to receivefloodlightProviderService.addOFMessageListener(OFType.PACKET_IN, this);floodlightProviderService.addOFMessageListener(OFType.PORT_STATUS, this);// Register for switch updatesswitchService.addOFSwitchListener(this);floodlightProviderService.addHAListener(this.haListener);floodlightProviderService.addInfoProvider("summary", this);if (restApiService != null)restApiService.addRestletRoutable(new LinkDiscoveryWebRoutable());setControllerTLV();}

上的启动代码,首先从内存数据建表 createTable,创建controller_topologyconfig、controller_link、controller_switchconfig等表。内存数据库的实现后面章节介绍,主要基于hashmap等java基本数据结构封装实现的。启动一个线程执行链路发现discoverOnAllPorts这个方法是具体实现

	/*** 发送LLDP到每个交换机端口*/protected void discoverOnAllPorts() {log.info("Sending LLDP packets out of all the enabled ports");// Send standard LLDPsfor (DatapathId sw : switchService.getAllSwitchDpids()) {IOFSwitch iofSwitch = switchService.getSwitch(sw);if (iofSwitch == null) continue;if (!iofSwitch.isActive()) continue; /* can't do anything if the switch is SLAVE */Collection<OFPort> c = iofSwitch.getEnabledPortNumbers();if (c != null) {for (OFPort ofp : c) {if (isLinkDiscoverySuppressed(sw, ofp)) {			continue;}log.trace("Enabled port: {}", ofp);sendDiscoveryMessage(sw, ofp, true, false);// If the switch port is not already in the maintenance// queue, add it.NodePortTuple npt = new NodePortTuple(sw, ofp);addToMaintenanceQueue(npt);}}}}
这个方法首先是获取所有的交换机,datapath可以理解为一个交换机,然后再遍历每个OFPort,通过sendDiscoveryMessage方法发送。

protected boolean sendDiscoveryMessage(DatapathId sw, OFPort port,boolean isStandard, boolean isReverse) {// Takes care of all checks including null pointer checks.if (!isOutgoingDiscoveryAllowed(sw, port, isStandard, isReverse))return false;IOFSwitch iofSwitch = switchService.getSwitch(sw);if (iofSwitch == null)             //fix dereference violations in case race conditionsreturn false;OFPortDesc ofpPort = iofSwitch.getPort(port);OFPacketOut po = generateLLDPMessage(iofSwitch, port, isStandard, isReverse);OFPacketOut.Builder pob = po.createBuilder();// Add actionsList<OFAction> actions = getDiscoveryActions(iofSwitch, ofpPort.getPortNo());pob.setActions(actions);// no need to set length anymore// send// no more try-catch. switch will silently failreturn iofSwitch.write(pob.build());}
pob就是openflow的packetout的builder。通过generateLLDPMessage创建LLDP消息,并添加actions,最后通过write方法发送到交换机上。



这篇关于Floodlight源码阅读之链路发现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/977189

相关文章

Java 正则表达式URL 匹配与源码全解析

《Java正则表达式URL匹配与源码全解析》在Web应用开发中,我们经常需要对URL进行格式验证,今天我们结合Java的Pattern和Matcher类,深入理解正则表达式在实际应用中... 目录1.正则表达式分解:2. 添加域名匹配 (2)3. 添加路径和查询参数匹配 (3) 4. 最终优化版本5.设计思

springboot filter实现请求响应全链路拦截

《springbootfilter实现请求响应全链路拦截》这篇文章主要为大家详细介绍了SpringBoot如何结合Filter同时拦截请求和响应,从而实现​​日志采集自动化,感兴趣的小伙伴可以跟随小... 目录一、为什么你需要这个过滤器?​​​二、核心实现:一个Filter搞定双向数据流​​​​三、完整代码

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

Python实现无痛修改第三方库源码的方法详解

《Python实现无痛修改第三方库源码的方法详解》很多时候,我们下载的第三方库是不会有需求不满足的情况,但也有极少的情况,第三方库没有兼顾到需求,本文将介绍几个修改源码的操作,大家可以根据需求进行选择... 目录需求不符合模拟示例 1. 修改源文件2. 继承修改3. 猴子补丁4. 追踪局部变量需求不符合很

SpringCloud之consul服务注册与发现、配置管理、配置持久化方式

《SpringCloud之consul服务注册与发现、配置管理、配置持久化方式》:本文主要介绍SpringCloud之consul服务注册与发现、配置管理、配置持久化方式,具有很好的参考价值,希望... 目录前言一、consul是什么?二、安装运行consul三、使用1、服务发现2、配置管理四、数据持久化总

Spring 中 BeanFactoryPostProcessor 的作用和示例源码分析

《Spring中BeanFactoryPostProcessor的作用和示例源码分析》Spring的BeanFactoryPostProcessor是容器初始化的扩展接口,允许在Bean实例化前... 目录一、概览1. 核心定位2. 核心功能详解3. 关键特性二、Spring 内置的 BeanFactory

SpringBoot项目注入 traceId 追踪整个请求的日志链路(过程详解)

《SpringBoot项目注入traceId追踪整个请求的日志链路(过程详解)》本文介绍了如何在单体SpringBoot项目中通过手动实现过滤器或拦截器来注入traceId,以追踪整个请求的日志链... SpringBoot项目注入 traceId 来追踪整个请求的日志链路,有了 traceId, 我们在排

Go中sync.Once源码的深度讲解

《Go中sync.Once源码的深度讲解》sync.Once是Go语言标准库中的一个同步原语,用于确保某个操作只执行一次,本文将从源码出发为大家详细介绍一下sync.Once的具体使用,x希望对大家有... 目录概念简单示例源码解读总结概念sync.Once是Go语言标准库中的一个同步原语,用于确保某个操

SpringBoot如何使用TraceId日志链路追踪

《SpringBoot如何使用TraceId日志链路追踪》文章介绍了如何使用TraceId进行日志链路追踪,通过在日志中添加TraceId关键字,可以将同一次业务调用链上的日志串起来,本文通过实例代码... 目录项目场景:实现步骤1、pom.XML 依赖2、整合logback,打印日志,logback-sp

Java汇编源码如何查看环境搭建

《Java汇编源码如何查看环境搭建》:本文主要介绍如何在IntelliJIDEA开发环境中搭建字节码和汇编环境,以便更好地进行代码调优和JVM学习,首先,介绍了如何配置IntelliJIDEA以方... 目录一、简介二、在IDEA开发环境中搭建汇编环境2.1 在IDEA中搭建字节码查看环境2.1.1 搭建步