本文主要是介绍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源码阅读之链路发现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!