blob: 0a66cdda642487fd77d3f4d7d7ec634bd566d626 [file] [log] [blame]
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -07001package net.onrc.onos.apps.segmentrouting;
2
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -07003import java.util.ArrayList;
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -07004import java.util.HashMap;
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -07005import java.util.LinkedList;
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -07006
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -07007import net.onrc.onos.core.intent.Path;
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -07008import net.onrc.onos.core.topology.Link;
9import net.onrc.onos.core.topology.LinkData;
10import net.onrc.onos.core.topology.Switch;
11import net.onrc.onos.core.util.Dpid;
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070012
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070013import org.projectfloodlight.openflow.util.HexString;
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070014import org.slf4j.Logger;
15import org.slf4j.LoggerFactory;
16
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070017/**
18 * This class creates bandwidth constrained breadth first tree and returns paths
19 * from root switch to leaf switches which satisfies the bandwidth condition. If
20 * bandwidth parameter is not specified, the normal breadth first tree will be
21 * calculated. The paths are snapshot paths at the point of the class
22 * instantiation.
23 */
24public class ECMPShortestPathGraph {
25 LinkedList<Switch> switchQueue = new LinkedList<>();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070026 LinkedList<Integer> distanceQueue = new LinkedList<>();
27 HashMap<Dpid, Integer> switchSearched = new HashMap<>();
28 HashMap<Dpid, ArrayList<LinkData>> upstreamLinks = new HashMap<>();
29 HashMap<Dpid, ArrayList<Path>> paths = new HashMap<>();
30 HashMap<Integer, ArrayList<Switch>> distanceSwitchMap = new HashMap<>();
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070031 Switch rootSwitch;
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070032 private static final Logger log = LoggerFactory
33 .getLogger(SegmentRoutingManager.class);
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070034
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070035 /**
Saurav Dasc0aa04c2014-09-22 10:22:23 -070036 * Constructor
37 *
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070038 * @param rootSwitch root of the BFS tree
39 */
40 public ECMPShortestPathGraph(Switch rootSwitch) {
41 this.rootSwitch = rootSwitch;
42 calcECMPShortestPathGraph();
43 }
44
45 /**
46 * Calculates the BFS tree using any provided constraints and Intents.
47 */
48 private void calcECMPShortestPathGraph() {
49 switchQueue.add(rootSwitch);
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070050 int currDistance = 0;
51 distanceQueue.add(currDistance);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070052 switchSearched.put(rootSwitch.getDpid(), currDistance);
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070053 while (!switchQueue.isEmpty()) {
54 Switch sw = switchQueue.poll();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070055 Switch prevSw = null;
56 currDistance = distanceQueue.poll();
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070057 for (Link link : sw.getOutgoingLinks()) {
58 Switch reachedSwitch = link.getDstPort().getSwitch();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070059 if ((prevSw != null)
60 && (prevSw.getDpid().equals(reachedSwitch.getDpid())))
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070061 {
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070062 /* Ignore LAG links between the same set of switches */
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070063 continue;
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070064 }
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070065 else
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070066 {
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070067 prevSw = reachedSwitch;
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070068 }
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070069
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070070 Integer distance = switchSearched.get(reachedSwitch.getDpid());
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070071 if ((distance != null) && (distance.intValue() < (currDistance + 1))) {
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070072 continue;
73 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070074 if (distance == null) {
75 /* First time visiting this switch node */
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070076 switchQueue.add(reachedSwitch);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070077 distanceQueue.add(currDistance + 1);
78 switchSearched.put(reachedSwitch.getDpid(), currDistance + 1);
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070079
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070080 ArrayList<Switch> distanceSwArray = distanceSwitchMap
81 .get(currDistance + 1);
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070082 if (distanceSwArray == null)
83 {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070084 distanceSwArray = new ArrayList<Switch>();
85 distanceSwArray.add(reachedSwitch);
86 distanceSwitchMap.put(currDistance + 1, distanceSwArray);
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070087 }
88 else
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070089 distanceSwArray.add(reachedSwitch);
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070090 }
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070091
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070092 ArrayList<LinkData> upstreamLinkArray =
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070093 upstreamLinks.get(reachedSwitch.getDpid());
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070094 if (upstreamLinkArray == null)
95 {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070096 upstreamLinkArray = new ArrayList<LinkData>();
97 upstreamLinkArray.add(new LinkData(link));
98 upstreamLinks.put(reachedSwitch.getDpid(), upstreamLinkArray);
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070099 }
100 else
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700101 /* ECMP links */
102 upstreamLinkArray.add(new LinkData(link));
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700103 }
104 }
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700105
106 log.debug("ECMPShortestPathGraph:switchSearched for switch {} is {}",
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700107 HexString.toHexString(rootSwitch.getDpid().value()), switchSearched);
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700108 log.debug("ECMPShortestPathGraph:upstreamLinks for switch {} is {}",
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700109 HexString.toHexString(rootSwitch.getDpid().value()), upstreamLinks);
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700110 log.debug("ECMPShortestPathGraph:distanceSwitchMap for switch {} is {}",
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700111 HexString.toHexString(rootSwitch.getDpid().value()), distanceSwitchMap);
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700112 /*
113 for (Integer distance: distanceSwitchMap.keySet()){
114 for (Switch sw: distanceSwitchMap.get(distance)){
115 ArrayList<Path> path = getPath(sw);
116 log.debug("ECMPShortestPathGraph:Paths in Pass{} from switch {} to switch {} is {}",
117 distance,
118 HexString.toHexString(rootSwitch.getDpid().value()),
119 HexString.toHexString(sw.getDpid().value()), path);
120 }
121 }*/
122 }
123
124 private void getDFSPaths(Dpid dstSwitchDpid, Path path, ArrayList<Path> paths) {
125 Dpid rootSwitchDpid = rootSwitch.getDpid();
126 for (LinkData upstreamLink : upstreamLinks.get(dstSwitchDpid)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700127 /* Deep clone the path object */
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -0700128 Path sofarPath = new Path();
129 if (!path.isEmpty())
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700130 sofarPath.addAll(path.subList(0, path.size()));
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -0700131 sofarPath.add(upstreamLink);
132 if (upstreamLink.getSrc().getDpid().equals(rootSwitchDpid))
133 {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700134 paths.add(sofarPath);
135 return;
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -0700136 }
137 else
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700138 getDFSPaths(upstreamLink.getSrc().getDpid(), sofarPath, paths);
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700139 }
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700140 }
141
142 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700143 * Return the computed ECMP paths from the root switch to a given switch in
144 * the network
145 *
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700146 * @param targetSwitch the target switch
147 * @return the list of ECMP Paths from the root switch to the target switch
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700148 */
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700149 public ArrayList<Path> getECMPPaths(Switch targetSwitch) {
150 ArrayList<Path> pathArray = paths.get(targetSwitch.getDpid());
151 if (pathArray == null && switchSearched.containsKey(
152 targetSwitch.getDpid())) {
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -0700153 pathArray = new ArrayList<>();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700154 Path path = new Path();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700155 Dpid sw = targetSwitch.getDpid();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700156 getDFSPaths(sw, path, pathArray);
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700157 paths.put(targetSwitch.getDpid(), pathArray);
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700158 }
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700159 return pathArray;
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700160 }
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700161
162 /**
163 * Return the complete info of the computed ECMP paths for each switch
164 * learned in multiple iterations from the root switch
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700165 *
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700166 * @return the hash table of Switches learned in multiple Dijkstra
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700167 * iterations and corresponding ECMP paths to it from the root
168 * switch
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700169 */
170 public HashMap<Integer, HashMap<Switch,
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700171 ArrayList<Path>>> getCompleteLearnedSwitchesAndPaths() {
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700172
173 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> pathGraph = new
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700174 HashMap<Integer, HashMap<Switch, ArrayList<Path>>>();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700175
176 for (Integer itrIndx : distanceSwitchMap.keySet()) {
177 HashMap<Switch, ArrayList<Path>> swMap = new
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700178 HashMap<Switch, ArrayList<Path>>();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700179 for (Switch sw : distanceSwitchMap.get(itrIndx)) {
180 swMap.put(sw, getECMPPaths(sw));
181 }
182 pathGraph.put(itrIndx, swMap);
183 }
184
185 return pathGraph;
186 }
187
188 /**
189 * Return the complete info of the computed ECMP paths for each switch
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700190 * learned in multiple iterations from the root switch in the form of {
191 * Iteration1, Switch<> via {Switch<>, Switch<>} Switch<> via {Switch<>,
192 * Switch<>} Iteration2, Switch<> via {Switch<>, Switch<>, Switch<>}
193 * {Switch<>, Switch<>, Switch<>} Switch<> via {Switch<>, Switch<>,
194 * Switch<>} }
195 *
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700196 * @return the hash table of Switches learned in multiple Dijkstra
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700197 * iterations and corresponding ECMP paths in terms of Switches to
198 * be traversed to it from the root switch
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700199 */
200 public HashMap<Integer, HashMap<Switch,
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700201 ArrayList<ArrayList<Dpid>>>> getAllLearnedSwitchesAndVia() {
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700202
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700203 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchViaMap = new HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>>();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700204
205 for (Integer itrIndx : distanceSwitchMap.keySet()) {
Srikanth Vavilapalli5ddf8f02014-09-24 11:02:28 -0700206 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swMap =
207 new HashMap<Switch, ArrayList<ArrayList<Dpid>>>();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700208
209 for (Switch sw : distanceSwitchMap.get(itrIndx)) {
210 ArrayList<ArrayList<Dpid>> swViaArray = new ArrayList<>();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700211 for (Path path : getECMPPaths(sw)) {
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700212 ArrayList<Dpid> swVia = new ArrayList<>();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700213 for (LinkData link : path.subList(0, path.size())) {
214 if (link.getSrc().getDpid().equals(rootSwitch.getDpid())) {
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700215 /* No need to add the root switch again in
216 * the Via list
217 */
218 continue;
219 }
220 swVia.add(link.getSrc().getDpid());
221 }
222 swViaArray.add(swVia);
223 }
224 swMap.put(sw, swViaArray);
225 }
226 switchViaMap.put(itrIndx, swMap);
227 }
228 return switchViaMap;
229 }
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700230}