From fcad2a31db6a4ba784bc3af8dc22c955c0c82272 Mon Sep 17 00:00:00 2001 From: Ryan Izard <ryan.izard@bigswitch.com> Date: Fri, 15 Jul 2016 20:30:10 -0400 Subject: [PATCH] Add PathNode and LinkedPathNode classes for use in better defining paths in the topology. --- .../core/types/PathNode.java | 169 ++++++++++++++++++ .../topology/TopologyInstance.java | 110 ++++++------ 2 files changed, 220 insertions(+), 59 deletions(-) create mode 100644 src/main/java/net/floodlightcontroller/core/types/PathNode.java diff --git a/src/main/java/net/floodlightcontroller/core/types/PathNode.java b/src/main/java/net/floodlightcontroller/core/types/PathNode.java new file mode 100644 index 000000000..da9fde403 --- /dev/null +++ b/src/main/java/net/floodlightcontroller/core/types/PathNode.java @@ -0,0 +1,169 @@ +package net.floodlightcontroller.core.types; + +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFPort; + +public class PathNode { + private DatapathId node; + private OFPort in; + private OFPort out; + private int hopId; + + private PathNode() { } + + private PathNode(DatapathId node, OFPort in, OFPort out, int hopId) { + this.node = node; + this.in = in; + this.out = out; + this.hopId = hopId; + } + + public static PathNode of(DatapathId node, OFPort in, OFPort out, int hopId) { + return new PathNode(node, in, out, hopId); + } + + public DatapathId getNode() { + return node; + } + + public OFPort getInPort() { + return in; + } + + public OFPort getOutPort() { + return out; + } + + public int getHopId() { + return hopId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + hopId; + result = prime * result + ((in == null) ? 0 : in.hashCode()); + result = prime * result + ((node == null) ? 0 : node.hashCode()); + result = prime * result + ((out == null) ? 0 : out.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PathNode other = (PathNode) obj; + if (hopId != other.hopId) + return false; + if (in == null) { + if (other.in != null) + return false; + } else if (!in.equals(other.in)) + return false; + if (node == null) { + if (other.node != null) + return false; + } else if (!node.equals(other.node)) + return false; + if (out == null) { + if (other.out != null) + return false; + } else if (!out.equals(other.out)) + return false; + return true; + } + + @Override + public String toString() { + return "PathNode [node=" + node + ", in=" + in + ", out=" + out + ", hopId=" + hopId + "]"; + } + + public static class LinkedPathNode extends PathNode { + private LinkedPathNode prev; + private LinkedPathNode next; + + private LinkedPathNode() { + super(); + } + + private LinkedPathNode(DatapathId node, OFPort in, OFPort out, + int hopId, LinkedPathNode prev, LinkedPathNode next) { + super(node, in, out, hopId); + this.prev = prev; + this.next = next; + } + + public static LinkedPathNode of(DatapathId node, OFPort in, OFPort out, + int hopId, LinkedPathNode prev, LinkedPathNode next) { + return new LinkedPathNode(node, in, out, hopId, prev, next); + } + + public static LinkedPathNode of(PathNode n, LinkedPathNode prev, LinkedPathNode next) { + return new LinkedPathNode(n.node, n.in, n.out, n.hopId, prev, next); + } + + public LinkedPathNode getPrevious() { + return prev; + } + + public LinkedPathNode getNext() { + return next; + } + + public boolean isStart() { + if (prev == null && next != null) { + return true; + } + return false; + } + + public boolean isEnd() { + if (prev != null && next == null) { + return true; + } + return false; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((next == null) ? 0 : next.hashCode()); + result = prime * result + ((prev == null) ? 0 : prev.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + LinkedPathNode other = (LinkedPathNode) obj; + if (next == null) { + if (other.next != null) + return false; + } else if (!next.equals(other.next)) + return false; + if (prev == null) { + if (other.prev != null) + return false; + } else if (!prev.equals(other.prev)) + return false; + return true; + } + + @Override + public String toString() { + return "LinkedPathNode [prev=" + prev + ", " + + super.toString() + ", next=" + next + "]"; + } + } +} diff --git a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java index b3fe8b3c7..07a0404b5 100644 --- a/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java +++ b/src/main/java/net/floodlightcontroller/topology/TopologyInstance.java @@ -70,15 +70,14 @@ public class TopologyInstance { /* Per-cluster */ private Set<Cluster> clusters; - private Map<DatapathId, Set<NodePortTuple>> clusterPorts; - private Map<DatapathId, Cluster> clustersPerSwitch; - private Map<DatapathId, BroadcastTree> clusterBroadcastTrees; + private Map<DatapathId, Set<NodePortTuple>> clusterPorts; /* ports in the cluster ID */ + private Map<DatapathId, Cluster> clusterFromSwitch; /* cluster for each switch */ /* Per-archipelago */ - private Set<Archipelago> archipelagos; + private Set<Archipelago> archipelagos; /* connected clusters */ private Map<Cluster, Archipelago> archipelagoFromCluster; - private Map<DatapathId, Set<NodePortTuple>> portsBroadcastPerArchipelago; - private Map<PathId, List<Path>> pathcache; /* contains computed paths ordered best to worst */ + private Map<DatapathId, Set<NodePortTuple>> portsBroadcastPerArchipelago; /* broadcast ports in each archipelago ID */ + private Map<PathId, List<Path>> pathcache; /* contains computed paths ordered best to worst */ public TopologyInstance(Map<DatapathId, Set<OFPort>> portsWithLinks, Set<NodePortTuple> portsBlocked, @@ -125,11 +124,9 @@ public class TopologyInstance { this.linksBlocked = new HashSet<Link>(); this.clusters = new HashSet<Cluster>(); - this.clustersPerSwitch = new HashMap<DatapathId, Cluster>(); - this.clusterBroadcastTrees = new HashMap<DatapathId, BroadcastTree>(); + this.clusterFromSwitch = new HashMap<DatapathId, Cluster>(); this.portsBroadcastAll= new HashSet<NodePortTuple>(); this.portsBroadcastPerSwitch = new HashMap<DatapathId,Set<OFPort>>(); - this.clusterBroadcastTrees = new HashMap<DatapathId, BroadcastTree>(); this.pathcache = new HashMap<PathId, List<Path>>(); @@ -211,17 +208,14 @@ public class TopologyInstance { } private void printTopology() { - log.info("-----------------Topology-----------------------"); - log.info("All Links: {}", links); - log.info("Cluser Broadcast Trees: {}", clusterBroadcastTrees); - log.info("Cluster Ports: {}", clusterPorts); - log.info("Tunnel Ports: {}", portsTunnel); - log.info("Clusters: {}", clusters); - log.info("Broadcast Ports Per Node (!!): {}", portsBroadcastPerSwitch); - log.info("Broadcast Domain Ports: {}", portsWithMoreThanTwoLinks); - log.info("Broadcast Node Ports: {}", portsWithMoreThanTwoLinks); - log.info("Archipelagos: {}", archipelagos); - log.info("-----------------------------------------------"); + log.debug("-----------------Topology-----------------------"); + log.debug("All Links: {}", links); + log.debug("Tunnel Ports: {}", portsTunnel); + log.debug("Clusters: {}", clusters); + log.debug("Broadcast Ports Per Node (!!): {}", portsBroadcastPerSwitch); + log.debug("3+ Link Ports: {}", portsWithMoreThanTwoLinks); + log.debug("Archipelagos: {}", archipelagos); + log.debug("-----------------------------------------------"); } private void identifyIntraClusterLinks() { @@ -234,8 +228,8 @@ public class TopologyInstance { for (Link l : linksNonBcastNonTunnel.get(np)) { if (isBlockedLink(l)) continue; if (isBroadcastLink(l)) continue; - Cluster c1 = clustersPerSwitch.get(l.getSrc()); - Cluster c2 = clustersPerSwitch.get(l.getDst()); + Cluster c1 = clusterFromSwitch.get(l.getSrc()); + Cluster c2 = clusterFromSwitch.get(l.getDst()); if (c1 == c2) { c1.addLink(l); /* link is within cluster */ } else { @@ -338,7 +332,7 @@ public class TopologyInstance { // ignore if the destination is already added to // another cluster - if (clustersPerSwitch.get(dstSw) != null) continue; + if (clusterFromSwitch.get(dstSw) != null) continue; // ignore the link if it is blocked. if (isBlockedLink(l)) continue; @@ -391,7 +385,7 @@ public class TopologyInstance { Cluster sc = new Cluster(); for (DatapathId sw : currSet) { sc.add(sw); - clustersPerSwitch.put(sw, sc); + clusterFromSwitch.put(sw, sc); } // delete all the nodes in the current set. currSet.clear(); @@ -749,28 +743,28 @@ public class TopologyInstance { /* * Calculates and stores n possible paths using Yen's algorithm, - * looping through every switch. - * These lists of routes are stored in pathcache. + * looping through every switch. These lists of routes are stored + * in the pathcache. */ private void computeOrderedPaths() { - List<Path> routes; - PathId routeId; + List<Path> paths; + PathId pathId; pathcache.clear(); for (Archipelago a : archipelagos) { /* for each archipelago */ Set<DatapathId> srcSws = a.getSwitches(); Set<DatapathId> dstSws = a.getSwitches(); - log.info("SRC {}", srcSws); - log.info("DST {}", dstSws); + log.debug("SRC {}", srcSws); + log.debug("DST {}", dstSws); for (DatapathId src : srcSws) { /* permute all member switches */ for (DatapathId dst : dstSws) { - log.warn("Calling Yens {} {}", src, dst); - routes = yens(src, dst, TopologyManager.getMaxPathsToComputeInternal(), + log.debug("Calling Yens {} {}", src, dst); + paths = yens(src, dst, TopologyManager.getMaxPathsToComputeInternal(), getArchipelago(src), getArchipelago(dst)); - routeId = new PathId(src, dst); - pathcache.put(routeId, routes); - log.info("Adding paths {}", routes); + pathId = new PathId(src, dst); + pathcache.put(pathId, paths); + log.debug("Adding paths {}", paths); } } } @@ -791,7 +785,7 @@ public class TopologyInstance { // This is a switch that is not connected to any other switch // hence there was no update for links (and hence it is not // in the network) - log.info("buildpath: Standalone switch: {}", srcId); + log.debug("buildpath: Standalone switch: {}", srcId); // The only possible non-null path for this case is // if srcId equals dstId --- and that too is an 'empty' path [] @@ -893,27 +887,27 @@ public class TopologyInstance { /** * - * This function returns K number of routes between a source and destination. It will attempt to retrieve - * these routes from the pathcache. If the user requests more routes than are stored, Yen's algorithm will be + * This function returns K number of paths between a source and destination. It will attempt to retrieve + * these paths from the pathcache. If the user requests more paths than are stored, Yen's algorithm will be * run using the K value passed in. * * - * @param src: DatapathId of the route source. - * @param dst: DatapathId of the route destination. - * @param k: The number of routes that you want. Must be positive integer. - * @return ArrayList of Routes or null if bad parameters + * @param src: DatapathId of the path source. + * @param dst: DatapathId of the path destination. + * @param k: The number of path that you want. Must be positive integer. + * @return list of paths or empty */ public List<Path> getPathsSlow(DatapathId src, DatapathId dst, int k) { - PathId routeId = new PathId(src, dst); - List<Path> routes = pathcache.get(routeId); + PathId pathId = new PathId(src, dst); + List<Path> paths = pathcache.get(pathId); - if (routes == null || k < 1) return ImmutableList.of(); + if (paths == null || k < 1) return ImmutableList.of(); - if (k >= TopologyManager.getMaxPathsToComputeInternal() || k >= routes.size()) { + if (k >= TopologyManager.getMaxPathsToComputeInternal() || k >= paths.size()) { return yens(src, dst, k, getArchipelago(src), getArchipelago(dst)); /* heavy computation */ } else { - return new ArrayList<Path>(routes.subList(0, k)); + return new ArrayList<Path>(paths.subList(0, k)); } } @@ -955,8 +949,8 @@ public class TopologyInstance { private List<Path> yens(DatapathId src, DatapathId dst, Integer K, Archipelago aSrc, Archipelago aDst) { log.debug("YENS ALGORITHM -----------------"); - log.debug("Asking for routes from {} to {}", src, dst); - log.debug("Asking for {} routes", K); + log.debug("Asking for paths from {} to {}", src, dst); + log.debug("Asking for {} paths", K); // Find link costs Map<Link, Integer> linkCost = initLinkCostMap(); @@ -970,7 +964,7 @@ public class TopologyInstance { List<Path> A = new ArrayList<Path>(); List<Path> B = new ArrayList<Path>(); - // The number of routes requested should never be less than 1. + // The number of paths requested should never be less than 1. if (K < 1) { return A; } @@ -1000,7 +994,7 @@ public class TopologyInstance { log.debug("Found shortest path in Yens {}", newroute); } else { - log.debug("No routes found in Yen's!"); + log.debug("No paths found in Yen's!"); return A; } @@ -1043,12 +1037,10 @@ public class TopologyInstance { // Builds the new topology without the parts we want removed copyOfLinkDpidMap = buildLinkDpidMap(switchesCopy, portsWithLinks, allLinksCopy); - //log.debug("About to build route."); - //log.debug("Switches: {}", switchesCopy); // Uses Dijkstra's to try to find a shortest path from the spur node to the destination Path spurPath = buildPath(new PathId(spurNode, dst), dijkstra(copyOfLinkDpidMap, dst, linkCost, true)); if (spurPath == null || spurPath.getPath().isEmpty()) { - //log.debug("spurPath is null"); + log.debug("spurPath is null"); continue; } @@ -1245,7 +1237,7 @@ public class TopologyInstance { } public DatapathId getClusterId(DatapathId switchId) { - Cluster c = clustersPerSwitch.get(switchId); + Cluster c = clusterFromSwitch.get(switchId); if (c != null) { return c.getId(); } @@ -1253,7 +1245,7 @@ public class TopologyInstance { } public DatapathId getArchipelagoId(DatapathId switchId) { - Cluster c = clustersPerSwitch.get(switchId); + Cluster c = clusterFromSwitch.get(switchId); if (c != null) { return archipelagoFromCluster.get(c).getId(); } @@ -1261,7 +1253,7 @@ public class TopologyInstance { } public Set<DatapathId> getSwitchesInCluster(DatapathId switchId) { - Cluster c = clustersPerSwitch.get(switchId); + Cluster c = clusterFromSwitch.get(switchId); if (c != null) { return c.getNodes(); } @@ -1270,8 +1262,8 @@ public class TopologyInstance { } public boolean isInSameCluster(DatapathId switch1, DatapathId switch2) { - Cluster c1 = clustersPerSwitch.get(switch1); - Cluster c2 = clustersPerSwitch.get(switch2); + Cluster c1 = clusterFromSwitch.get(switch1); + Cluster c2 = clusterFromSwitch.get(switch2); if (c1 != null && c2 != null) { return c1.getId().equals(c2.getId()); } -- GitLab