diff --git a/src/main/java/net/floodlightcontroller/topology/internal/TopologyImpl.java b/src/main/java/net/floodlightcontroller/topology/internal/TopologyImpl.java index e079b1e94f89957fcb1c5d1b16f3a2e378f91c78..ba962f4dbbbd681870de2815a772bd7766757865 100644 --- a/src/main/java/net/floodlightcontroller/topology/internal/TopologyImpl.java +++ b/src/main/java/net/floodlightcontroller/topology/internal/TopologyImpl.java @@ -171,8 +171,9 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, protected Map<IOFSwitch, SwitchCluster> switchClusterMap; protected Set<SwitchCluster> clusters; protected Set<BroadcastDomain> broadcastDomains; - protected Map<SwitchPortTuple, BroadcastDomain> portGroupMap; - protected Map<IOFSwitch, BroadcastDomain> switchGroupMap; + protected Map<SwitchPortTuple, BroadcastDomain> switchPortBroadcastDomainMap; + + protected boolean isTopologyValid = false; public static enum UpdateOperation {ADD, UPDATE, REMOVE, @@ -546,16 +547,16 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, OFPhysicalPort port = sw.getPort(swt.getPort()); if (port != null) { - sendLLDPs(sw, port, LLDP_BSN_DST_MAC_STRING); sendLLDPs(sw, port, LLDP_STANDARD_DST_MAC_STRING); + sendLLDPs(sw, port, LLDP_BSN_DST_MAC_STRING); } } protected void sendLLDPs(IOFSwitch sw) { if (sw.getEnabledPorts() != null) { for (OFPhysicalPort port : sw.getEnabledPorts()) { - sendLLDPs(sw, port, LLDP_BSN_DST_MAC_STRING); sendLLDPs(sw, port, LLDP_STANDARD_DST_MAC_STRING); + sendLLDPs(sw, port, LLDP_BSN_DST_MAC_STRING); } } } @@ -1240,14 +1241,24 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, return linkInfo.linkStpBlocked(); } + /** + * This function clusters and broadcast domains based on the links and switches + * identified thus far. The function will set isTopologyValid flag to be true + * if the computation is successful, otherwise it will be set to false. + * + * TODO We may want to recompute updateOpenFlow clusters until it returns true. + */ protected void updateClusters() { if (!lock.isWriteLockedByCurrentThread()) { log.error("Expected lock in updateClusters()"); return; } - updateOpenFlowClusters(); - updateBroadcastDomains(); + isTopologyValid = false; + if (updateOpenFlowClusters()) { + updateBroadcastDomains(); + isTopologyValid = true; + } } protected void addLinkToBroadcastDomain(LinkTuple lt) { @@ -1291,6 +1302,7 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, Map<SwitchPortTuple, Set<LinkTuple>> pbdLinks = getPortBroadcastDomainLinks(); Set<SwitchPortTuple> visitedSwt = new HashSet<SwitchPortTuple>(); Set<BroadcastDomain> bdSets = new HashSet<BroadcastDomain>(); + Map<SwitchPortTuple, BroadcastDomain> spbdMap = new HashMap<SwitchPortTuple, BroadcastDomain>(); // Do a breadth first search to get all the connected components for(SwitchPortTuple swt: pbdLinks.keySet()) { @@ -1315,6 +1327,7 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, queue.add(otherSwt); visitedSwt.add(otherSwt); bd.add(otherSwt); + spbdMap.put(otherSwt, bd); } } } @@ -1325,6 +1338,7 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, //Replace the current broadcast domains in the topology. broadcastDomains = bdSets; + switchPortBroadcastDomainMap = spbdMap; if (bdSets.isEmpty()) { if (log.isTraceEnabled()) { @@ -1350,7 +1364,7 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, * * http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm */ - protected void updateOpenFlowClusters() { + protected boolean updateOpenFlowClusters() { // NOTE: This function assumes that the caller has already acquired // a write lock on the "lock" data member. @@ -1380,12 +1394,13 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, if (cdfs == null) { log.error("Do DFS object for key found."); }else if (!cdfs.isVisited()) { - this.dfsTraverse(0, 1, sw, switches, dfsList, currSet, clusters); + if (this.dfsTraverse(0, 1, sw, switches, dfsList, currSet, clusters) < 0) return false; } } } updates.add(new Update(UpdateOperation.CLUSTER_MERGED)); + return true; } /** @@ -1405,6 +1420,10 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, * cluster should be formed is modified as we do not remove switches that * are already part of a cluster. * + * A return value of -1 indicates that dfsTraverse failed somewhere in the middle + * of computation. This could happen when a switch is removed during the cluster + * computation procedure. + * * @param parentIndex: DFS index of the parent node * @param currIndex: DFS index to be assigned to a newly visited node * @param currSw: Object for the current switch @@ -1436,6 +1455,8 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, IOFSwitch dstSw = lt.getDst().getSw(); LinkInfo info = links.get(lt); + if (dstSw == null) return -1; + // ignore incoming links. if (dstSw == currSw) continue; @@ -1448,6 +1469,8 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, // Get the DFS object corresponding to the dstSw ClusterDFS dstDFS = dfsList.get(dstSw); + if (dstDFS == null) return -1; + if (dstDFS.getDfsIndex() < currDFS.getDfsIndex()) { // could be a potential lowpoint if (dstDFS.getDfsIndex() < currDFS.getLowpoint()) @@ -1458,6 +1481,8 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, currIndex = dfsTraverse(currDFS.getDfsIndex(), currIndex, dstSw, switches, dfsList, currSet, clusters); + if (currIndex < 0) return -1; + // update lowpoint after the visit if (dstDFS.getLowpoint() < currDFS.getLowpoint()) currDFS.setLowpoint(dstDFS.getLowpoint());