Floodlight源码阅读之网络拓扑

来源:互联网 发布:mac ftpserver工具 编辑:程序博客网 时间:2024/05/11 04:40

在上一篇文章中介绍Floodlight怎样做拓扑发现,这篇文章介绍一下网络拓扑是怎样形成的。TopologyManager这个类负责网络拓扑的产生。这个类首先实现了IFloodlightModule这个接口,是Floodlight的一个模块。其实是实现了ILinkDiscoveryListener用于监听网络中链路的变化;还实现了IOFMessageListener用于接收和处理网络包。

和其他的Floodlight模块一样,首先看启动方法startup。

    @Override    public void startUp(FloodlightModuleContext context) {        clearCurrentTopology();        // Initialize role to floodlight provider role.        this.role = floodlightProviderService.getRole();        ScheduledExecutorService ses = threadPoolService.getScheduledExecutor();        newInstanceTask = new SingletonTask(ses, new UpdateTopologyWorker());        if (role != HARole.STANDBY) {            newInstanceTask.reschedule(TOPOLOGY_COMPUTE_INTERVAL_MS, TimeUnit.MILLISECONDS);        }        linkDiscoveryService.addListener(this);        floodlightProviderService.addOFMessageListener(OFType.PACKET_IN, this);        floodlightProviderService.addHAListener(this.haListener);        addRestletRoutable();    }

在这个启动方法中第一行就是清理拓扑

    /**     * Clears the current topology. Note that this does NOT     * send out updates.     */    public void clearCurrentTopology() {        this.clear();        linksUpdated = true;        dtLinksUpdated = true;        tunnelPortsUpdated = true;        createNewInstance("startup");        lastUpdateTime = new Date();    }
clear方法清理所以内存中保存的节点链路拓扑信息。

    public void clear() {        switchPorts.clear();        tunnelPorts.clear();        switchPortLinks.clear();        portBroadcastDomainLinks.clear();        directLinks.clear();    }
关于这个nosql内存数据库下一章讲解。

当清理完数据后开始创建新的拓扑

  /**     * This function computes a new topology instance.     * It ignores links connected to all broadcast domain ports     * and tunnel ports. The method returns if a new instance of     * topology was created or not.     */    protected boolean createNewInstance(String reason) {        Set<NodePortTuple> blockedPorts = new HashSet<NodePortTuple>();        if (!linksUpdated) return false;        Map<NodePortTuple, Set<Link>> openflowLinks;        openflowLinks =                new HashMap<NodePortTuple, Set<Link>>();        Set<NodePortTuple> nptList = switchPortLinks.keySet();        if (nptList != null) {            for (NodePortTuple npt : nptList) {                Set<Link> linkSet = switchPortLinks.get(npt);                if (linkSet == null) continue;                openflowLinks.put(npt, new HashSet<Link>(linkSet));            }        }        // Identify all broadcast domain ports.        // Mark any port that has inconsistent set of links        // as broadcast domain ports as well.        Set<NodePortTuple> broadcastDomainPorts =                identifyBroadcastDomainPorts();        // Remove all links incident on broadcast domain ports.        for (NodePortTuple npt : broadcastDomainPorts) {            if (switchPortLinks.get(npt) == null) continue;            for (Link link : switchPortLinks.get(npt)) {                removeLinkFromStructure(openflowLinks, link);            }        }        // Remove all tunnel links.        for (NodePortTuple npt : tunnelPorts) {            if (switchPortLinks.get(npt) == null) continue;            for (Link link : switchPortLinks.get(npt)) {                removeLinkFromStructure(openflowLinks, link);            }        }        //switchPorts contains only ports that are part of links. Calculation of broadcast ports needs set of all ports.        Map<DatapathId, Set<OFPort>> allPorts = new HashMap<DatapathId, Set<OFPort>>();        ;        for (DatapathId sw : switchPorts.keySet()) {            allPorts.put(sw, this.getPorts(sw));        }        TopologyInstance nt = new TopologyInstance(switchPorts,                blockedPorts,                openflowLinks,                broadcastDomainPorts,                tunnelPorts,                switchPortLinks,                allPorts,                portBroadcastDomainLinks);        nt.compute();        // We set the instances with and without tunnels to be identical.        // If needed, we may compute them differently.        currentInstance = nt;        currentInstanceWithoutTunnels = nt;        TopologyEventInfo topologyInfo =                new TopologyEventInfo(0, nt.getClusters().size(),                        new HashMap<DatapathId, List<NodePortTuple>>(),                        0);        eventCategory.newEventWithFlush(new TopologyEvent(reason, topologyInfo));        return true;    }

主要计算方法是nt.conpute()这个方法

这个方法有七步看代码如下

    public void compute() {        // Step 1: Compute clusters ignoring broadcast domain links        // Create nodes for clusters in the higher level topology        // Must ignore blocked links.        identifyOpenflowDomains();        // Step 1.1: Add links to clusters        // Avoid adding blocked links to clusters        addLinksToOpenflowDomains();        // Step 2. Compute shortest path trees in each cluster for        // unicast routing.  The trees are rooted at the destination.        // Cost for tunnel links and direct links are the same.        calculateShortestPathTreeInClusters();// Step 3. Compute broadcast tree in each cluster.        // Cost for tunnel links are high to discourage use of        // tunnel links.  The cost is set to the number of nodes        // in the cluster + 1, to use as minimum number of        // clusters as possible.        calculateBroadcastNodePortsInClusters();                // Step 4. Compute e2e shortest path trees on entire topology for unicast routing.// The trees are rooted at the destination.        // Cost for tunnel links and direct links are the same.calculateAllShortestPaths();        // Compute the archipelagos (def: cluster of islands). An archipelago will        // simply be a group of connected islands. Each archipelago will have its own        // finiteBroadcastTree which will be randomly chosen.        calculateArchipelagos();// Step 5. Compute broadcast tree for the whole topology (needed to avoid loops).        // Cost for tunnel links are high to discourage use of        // tunnel links.  The cost is set to the number of nodes        // in the cluster + 1, to use as minimum number of        // clusters as possible.        calculateAllBroadcastNodePorts();// Step 6. Compute set of ports for broadcasting. Edge ports are included.       calculateBroadcastPortMap();               // Step 7. print topology.        printTopology();    }

identifyOpenflowDomains这个方法通过深度优先遍历算法遍历拓扑节点

addLinksToOpenflowDomains添加集群直接的的link

calculateShortestPathTreeInClusters通过给链路添加权重在通clusterDijkstra最短路径算法计算拓扑最短路径

后面几个方法是整个网络的最短路径计算,详细部分文章后面一一解说




0 0
原创粉丝点击