Skip to content
Snippets Groups Projects
Commit 39084928 authored by Ryan Izard's avatar Ryan Izard
Browse files

Merge pull request #665 from cbarrin/archipelagos

Archipelagos
parents 89e98048 6e778998
No related branches found
No related tags found
No related merge requests found
/**
* Created by geddingsbarrineau on 4/1/16.
*/
package net.floodlightcontroller.topology;
import net.floodlightcontroller.routing.BroadcastTree;
import org.projectfloodlight.openflow.types.DatapathId;
import java.util.HashSet;
import java.util.Set;
public class Archipelago {
private DatapathId id; // the lowest id of the nodes
private final Set<Cluster> clusters;
private BroadcastTree destinationRootedFullTree;
public Archipelago() {
id = DatapathId.NONE;
clusters = new HashSet<Cluster>();
destinationRootedFullTree = null;
}
public DatapathId getId() {
return id;
}
protected Set<Cluster> getClusters() {
return clusters;
}
Archipelago add(Cluster c) {
if (clusters.add(c)) {
if (id.equals(DatapathId.NONE) || c.getId().compareTo(id) < 0) {
id = c.getId();
}
}
return this;
}
boolean isMember(Cluster c) {
return clusters.contains(c);
}
boolean isMember(DatapathId id) {
for (Cluster c : clusters) {
if(c.getNodes().contains(id)) return true;
}
return false;
}
void merge(Archipelago a) {
clusters.addAll(a.getClusters());
if (id.equals(DatapathId.NONE) || !a.getId().equals(DatapathId.NONE) || a.getId().compareTo(id) < 0) {
id = a.getId();
}
}
BroadcastTree getBroadcastTree() {
return destinationRootedFullTree;
}
void setBroadcastTree(BroadcastTree bt) {
destinationRootedFullTree = bt;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Archipelago that = (Archipelago) o;
if (!id.equals(that.id)) return false;
return clusters.equals(that.clusters);
}
@Override
public int hashCode() {
int result = id.hashCode();
result = 31 * result + clusters.hashCode();
return result;
}
public String toString() {
return "[Archipelago id=" + id.toString() + ", " + clusters.toString() + "]";
}
}
...@@ -16,16 +16,15 @@ ...@@ -16,16 +16,15 @@
package net.floodlightcontroller.topology; package net.floodlightcontroller.topology;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import org.projectfloodlight.openflow.types.DatapathId;
import org.projectfloodlight.openflow.types.OFPort;
import net.floodlightcontroller.core.module.IFloodlightService; import net.floodlightcontroller.core.module.IFloodlightService;
import net.floodlightcontroller.core.types.NodePortTuple; import net.floodlightcontroller.core.types.NodePortTuple;
import net.floodlightcontroller.routing.Link; import net.floodlightcontroller.routing.Link;
import org.projectfloodlight.openflow.types.DatapathId;
import org.projectfloodlight.openflow.types.OFPort;
import java.util.Date;
import java.util.Map;
import java.util.Set;
public interface ITopologyService extends IFloodlightService { public interface ITopologyService extends IFloodlightService {
...@@ -102,7 +101,7 @@ public interface ITopologyService extends IFloodlightService { ...@@ -102,7 +101,7 @@ public interface ITopologyService extends IFloodlightService {
* Determines if the switch+port is blocked. If blocked, it * Determines if the switch+port is blocked. If blocked, it
* should not be allowed to send/receive any traffic. * should not be allowed to send/receive any traffic.
* @param sw * @param sw
* @param port * @param portId
* @return * @return
*/ */
public boolean isAllowed(DatapathId sw, OFPort portId); public boolean isAllowed(DatapathId sw, OFPort portId);
...@@ -111,7 +110,7 @@ public interface ITopologyService extends IFloodlightService { ...@@ -111,7 +110,7 @@ public interface ITopologyService extends IFloodlightService {
* Determines if the switch+port is blocked. If blocked, it * Determines if the switch+port is blocked. If blocked, it
* should not be allowed to send/receive any traffic. * should not be allowed to send/receive any traffic.
* @param sw * @param sw
* @param port * @param portId
* @param tunnelEnabled * @param tunnelEnabled
* @return * @return
*/ */
...@@ -211,7 +210,7 @@ public interface ITopologyService extends IFloodlightService { ...@@ -211,7 +210,7 @@ public interface ITopologyService extends IFloodlightService {
* broadcast, this method provides the topologically equivalent * broadcast, this method provides the topologically equivalent
* incoming broadcast-allowed src port. * incoming broadcast-allowed src port.
* @param src * @param src
* @param dst * @param srcPort
* @return * @return
*/ */
public NodePortTuple getAllowedIncomingBroadcastPort(DatapathId src, OFPort srcPort); public NodePortTuple getAllowedIncomingBroadcastPort(DatapathId src, OFPort srcPort);
...@@ -221,7 +220,7 @@ public interface ITopologyService extends IFloodlightService { ...@@ -221,7 +220,7 @@ public interface ITopologyService extends IFloodlightService {
* broadcast, this method provides the topologically equivalent * broadcast, this method provides the topologically equivalent
* incoming broadcast-allowed src port. * incoming broadcast-allowed src port.
* @param src * @param src
* @param dst * @param srcPort
* @param tunnelEnabled * @param tunnelEnabled
* @return * @return
*/ */
......
...@@ -16,32 +16,22 @@ ...@@ -16,32 +16,22 @@
package net.floodlightcontroller.topology; package net.floodlightcontroller.topology;
import java.util.ArrayList; import com.google.common.cache.CacheBuilder;
import java.util.Arrays; import com.google.common.cache.CacheLoader;
import java.util.HashMap; import com.google.common.cache.LoadingCache;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;
import net.floodlightcontroller.core.types.NodePortTuple; import net.floodlightcontroller.core.types.NodePortTuple;
import net.floodlightcontroller.routing.BroadcastTree; import net.floodlightcontroller.routing.BroadcastTree;
import net.floodlightcontroller.routing.Link; import net.floodlightcontroller.routing.Link;
import net.floodlightcontroller.routing.Route; import net.floodlightcontroller.routing.Route;
import net.floodlightcontroller.routing.RouteId; import net.floodlightcontroller.routing.RouteId;
import net.floodlightcontroller.util.ClusterDFS; import net.floodlightcontroller.util.ClusterDFS;
import org.projectfloodlight.openflow.types.DatapathId; import org.projectfloodlight.openflow.types.DatapathId;
import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.U64; import org.projectfloodlight.openflow.types.U64;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.common.cache.CacheBuilder; import java.util.*;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
/** /**
* A representation of a network topology. Used internally by * A representation of a network topology. Used internally by
...@@ -93,9 +83,12 @@ public class TopologyInstance { ...@@ -93,9 +83,12 @@ public class TopologyInstance {
protected Map<NodePortTuple, Set<Link>> allLinks; protected Map<NodePortTuple, Set<Link>> allLinks;
//Set of all ports organized by DatapathId. Note that switchPorts map contains only ports with links. //Set of all ports organized by DatapathId. Note that switchPorts map contains only ports with links.
protected Map<DatapathId, Set<OFPort>> allPorts; protected Map<DatapathId, Set<OFPort>> allPorts;
//Set of all the inter-island or "external" links. Also known as portBroadcastDomainLinks in TopologyManager.
protected Map<NodePortTuple, Set<Link>> externalLinks;
// Maps broadcast ports to DatapathId // Maps broadcast ports to DatapathId
protected Map<DatapathId, Set<OFPort>> broadcastPortMap; protected Map<DatapathId, Set<OFPort>> broadcastPortMap;
protected Set<Archipelago> archipelagos;
protected class PathCacheLoader extends CacheLoader<RouteId, Route> { protected class PathCacheLoader extends CacheLoader<RouteId, Route> {
TopologyInstance ti; TopologyInstance ti;
...@@ -119,8 +112,9 @@ public class TopologyInstance { ...@@ -119,8 +112,9 @@ public class TopologyInstance {
Map<NodePortTuple, Set<Link>> switchPortLinks, Map<NodePortTuple, Set<Link>> switchPortLinks,
Set<NodePortTuple> broadcastDomainPorts, Set<NodePortTuple> broadcastDomainPorts,
Set<NodePortTuple> tunnelPorts, Set<NodePortTuple> tunnelPorts,
Map<NodePortTuple, Set<Link>> allLinks, Map<NodePortTuple, Set<Link>> allLinks,
Map<DatapathId, Set<OFPort>> allPorts) { Map<DatapathId, Set<OFPort>> allPorts,
Map<NodePortTuple, Set<Link>> externalLinks) {
this.switches = new HashSet<DatapathId>(switchPorts.keySet()); this.switches = new HashSet<DatapathId>(switchPorts.keySet());
this.switchPorts = new HashMap<DatapathId, Set<OFPort>>(); this.switchPorts = new HashMap<DatapathId, Set<OFPort>>();
...@@ -143,6 +137,13 @@ public class TopologyInstance { ...@@ -143,6 +137,13 @@ public class TopologyInstance {
for (NodePortTuple npt : allLinks.keySet()) { for (NodePortTuple npt : allLinks.keySet()) {
this.allLinks.put(npt, new HashSet<Link>(allLinks.get(npt))); this.allLinks.put(npt, new HashSet<Link>(allLinks.get(npt)));
} }
this.externalLinks = new HashMap<NodePortTuple, Set<Link>>();
for (NodePortTuple npt : externalLinks.keySet()) {
this.externalLinks.put(npt, new HashSet<Link>(externalLinks.get(npt)));
}
this.archipelagos = new HashSet<Archipelago>();
this.broadcastDomainPorts = new HashSet<NodePortTuple>(broadcastDomainPorts); this.broadcastDomainPorts = new HashSet<NodePortTuple>(broadcastDomainPorts);
this.tunnelPorts = new HashSet<NodePortTuple>(tunnelPorts); this.tunnelPorts = new HashSet<NodePortTuple>(tunnelPorts);
...@@ -194,6 +195,11 @@ public class TopologyInstance { ...@@ -194,6 +195,11 @@ public class TopologyInstance {
// The trees are rooted at the destination. // The trees are rooted at the destination.
// Cost for tunnel links and direct links are the same. // Cost for tunnel links and direct links are the same.
calculateAllShortestPaths(); 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). // Step 5. Compute broadcast tree for the whole topology (needed to avoid loops).
// Cost for tunnel links are high to discourage use of // Cost for tunnel links are high to discourage use of
...@@ -584,6 +590,68 @@ public class TopologyInstance { ...@@ -584,6 +590,68 @@ public class TopologyInstance {
BroadcastTree ret = new BroadcastTree(nexthoplinks, cost); BroadcastTree ret = new BroadcastTree(nexthoplinks, cost);
return ret; return ret;
} }
private void calculateArchipelagos() {
// Iterate through each external link and create/merge archipelagos based on the
// islands that each link is connected to
Cluster srcCluster = null;
Cluster dstCluster = null;
Archipelago srcArchipelago = null;
Archipelago dstArchipelago = null;
Set<Link> links = new HashSet<Link>();
for (Set<Link> linkset : externalLinks.values()) {
links.addAll(linkset);
}
for (Link l : links) {
for (Cluster c : clusters) {
if(c.getNodes().contains(l.getSrc())) srcCluster = c;
if(c.getNodes().contains(l.getDst())) dstCluster = c;
}
for (Archipelago a : archipelagos) {
// Is source cluster a part of an existing archipelago?
if(a.isMember(srcCluster)) srcArchipelago = a;
// Is destination cluster a part of an existing archipelago?
if(a.isMember(dstCluster)) dstArchipelago = a;
}
// Are they both found in an archipelago? If so, then merge the two.
if(srcArchipelago != null && dstArchipelago != null && srcArchipelago != dstArchipelago) {
srcArchipelago.merge(dstArchipelago);
archipelagos.remove(dstArchipelago);
}
// If neither were found in an existing, then form a new archipelago.
else if(srcArchipelago == null && dstArchipelago == null) {
archipelagos.add(new Archipelago().add(srcCluster).add(dstCluster));
}
// If only one is found in an existing, then add the one not found to the existing.
else if(srcArchipelago != null && dstArchipelago == null) {
srcArchipelago.add(dstCluster);
}
else if(srcArchipelago == null && dstArchipelago != null) {
dstArchipelago.add(srcCluster);
}
srcCluster = null;
dstCluster = null;
srcArchipelago = null;
dstArchipelago = null;
}
// Choose a broadcast tree for each archipelago
for (Archipelago a : archipelagos) {
for (DatapathId id : destinationRootedFullTrees.keySet()) {
if (a.isMember(id)) {
a.setBroadcastTree(destinationRootedFullTrees.get(id));
break;
}
}
}
}
/* /*
* Dijkstra that calculates destination rooted trees over the entire topology. * Dijkstra that calculates destination rooted trees over the entire topology.
...@@ -695,9 +763,9 @@ public class TopologyInstance { ...@@ -695,9 +763,9 @@ public class TopologyInstance {
} }
//finiteBroadcastTree is randomly chosen in this implementation //finiteBroadcastTree is randomly chosen in this implementation
if (this.destinationRootedFullTrees.size() > 0) { // if (this.destinationRootedFullTrees.size() > 0) {
this.finiteBroadcastTree = destinationRootedFullTrees.values().iterator().next(); // this.finiteBroadcastTree = destinationRootedFullTrees.values().iterator().next();
} // }
} }
protected void calculateShortestPathTreeInClusters() { protected void calculateShortestPathTreeInClusters() {
...@@ -734,21 +802,23 @@ public class TopologyInstance { ...@@ -734,21 +802,23 @@ public class TopologyInstance {
protected Set<NodePortTuple> getAllBroadcastNodePorts() { protected Set<NodePortTuple> getAllBroadcastNodePorts() {
return this.broadcastNodePorts; return this.broadcastNodePorts;
} }
protected void calculateAllBroadcastNodePorts() { protected void calculateAllBroadcastNodePorts() {
if (this.destinationRootedFullTrees.size() > 0) { if (this.destinationRootedFullTrees.size() > 0) {
this.finiteBroadcastTree = destinationRootedFullTrees.values().iterator().next(); //this.finiteBroadcastTree = destinationRootedFullTrees.values().iterator().next();
Map<DatapathId, Link> links = finiteBroadcastTree.getLinks(); for (Archipelago a : archipelagos) {
if (links == null) return; Map<DatapathId, Link> links = a.getBroadcastTree().getLinks();
for (DatapathId nodeId : links.keySet()) { if (links == null) return;
Link l = links.get(nodeId); for (DatapathId nodeId : links.keySet()) {
if (l == null) continue; Link l = links.get(nodeId);
NodePortTuple npt1 = new NodePortTuple(l.getSrc(), l.getSrcPort()); if (l == null) continue;
NodePortTuple npt2 = new NodePortTuple(l.getDst(), l.getDstPort()); NodePortTuple npt1 = new NodePortTuple(l.getSrc(), l.getSrcPort());
this.broadcastNodePorts.add(npt1); NodePortTuple npt2 = new NodePortTuple(l.getDst(), l.getDstPort());
this.broadcastNodePorts.add(npt2); this.broadcastNodePorts.add(npt1);
} this.broadcastNodePorts.add(npt2);
} }
}
}
} }
protected void calculateBroadcastPortMap(){ protected void calculateBroadcastPortMap(){
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment