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

相关文章

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 搭建步

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

一、引言 从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts、dts: 打印出来的“pts”实际是AVPacket结构体中的成员变量pts,是以AVStream->time_base为单位的显