blob: b7fbbc9aacdd3da44b4a1f129ba6ab64e3bfe6c4 [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 Vavilapalli174e67c2014-09-19 07:27:17 -070013import org.slf4j.Logger;
14import org.slf4j.LoggerFactory;
15
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070016/**
17 * This class creates bandwidth constrained breadth first tree and returns paths
18 * from root switch to leaf switches which satisfies the bandwidth condition. If
19 * bandwidth parameter is not specified, the normal breadth first tree will be
20 * calculated. The paths are snapshot paths at the point of the class
21 * instantiation.
22 */
23public class ECMPShortestPathGraph {
24 LinkedList<Switch> switchQueue = new LinkedList<>();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070025 LinkedList<Integer> distanceQueue = new LinkedList<>();
26 HashMap<Dpid, Integer> switchSearched = new HashMap<>();
27 HashMap<Dpid, ArrayList<LinkData>> upstreamLinks = new HashMap<>();
28 HashMap<Dpid, ArrayList<Path>> paths = new HashMap<>();
29 HashMap<Integer, ArrayList<Switch>> distanceSwitchMap = new HashMap<>();
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070030 Switch rootSwitch;
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070031 private static final Logger log = LoggerFactory
32 .getLogger(SegmentRoutingManager.class);
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070033
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070034 /**
Saurav Dasc0aa04c2014-09-22 10:22:23 -070035 * Constructor
Sangho Shinfbc572c2014-10-02 16:37:05 -070036 *
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070037 * @param rootSwitch root of the BFS tree
38 */
39 public ECMPShortestPathGraph(Switch rootSwitch) {
40 this.rootSwitch = rootSwitch;
41 calcECMPShortestPathGraph();
42 }
43
44 /**
45 * Calculates the BFS tree using any provided constraints and Intents.
46 */
47 private void calcECMPShortestPathGraph() {
48 switchQueue.add(rootSwitch);
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070049 int currDistance = 0;
50 distanceQueue.add(currDistance);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070051 switchSearched.put(rootSwitch.getDpid(), currDistance);
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070052 while (!switchQueue.isEmpty()) {
53 Switch sw = switchQueue.poll();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070054 Switch prevSw = null;
55 currDistance = distanceQueue.poll();
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070056 for (Link link : sw.getOutgoingLinks()) {
57 Switch reachedSwitch = link.getDstPort().getSwitch();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070058 if ((prevSw != null)
59 && (prevSw.getDpid().equals(reachedSwitch.getDpid())))
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070060 {
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070061 /* Ignore LAG links between the same set of switches */
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070062 continue;
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070063 }
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070064 else
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070065 {
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070066 prevSw = reachedSwitch;
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070067 }
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070068
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070069 Integer distance = switchSearched.get(reachedSwitch.getDpid());
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070070 if ((distance != null) && (distance.intValue() < (currDistance + 1))) {
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070071 continue;
72 }
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070073 if (distance == null) {
74 /* First time visiting this switch node */
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070075 switchQueue.add(reachedSwitch);
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070076 distanceQueue.add(currDistance + 1);
77 switchSearched.put(reachedSwitch.getDpid(), currDistance + 1);
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070078
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070079 ArrayList<Switch> distanceSwArray = distanceSwitchMap
80 .get(currDistance + 1);
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070081 if (distanceSwArray == null)
82 {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070083 distanceSwArray = new ArrayList<Switch>();
84 distanceSwArray.add(reachedSwitch);
85 distanceSwitchMap.put(currDistance + 1, distanceSwArray);
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070086 }
87 else
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070088 distanceSwArray.add(reachedSwitch);
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070089 }
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070090
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070091 ArrayList<LinkData> upstreamLinkArray =
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070092 upstreamLinks.get(reachedSwitch.getDpid());
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070093 if (upstreamLinkArray == null)
94 {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -070095 upstreamLinkArray = new ArrayList<LinkData>();
96 upstreamLinkArray.add(new LinkData(link));
97 upstreamLinks.put(reachedSwitch.getDpid(), upstreamLinkArray);
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070098 }
99 else
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700100 /* ECMP links */
101 upstreamLinkArray.add(new LinkData(link));
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700102 }
103 }
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700104
Sangho Shin5be3e532014-10-03 17:20:58 -0700105 /*
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700106 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);
Sangho Shin5be3e532014-10-03 17:20:58 -0700112 */
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700113 /*
114 for (Integer distance: distanceSwitchMap.keySet()){
115 for (Switch sw: distanceSwitchMap.get(distance)){
116 ArrayList<Path> path = getPath(sw);
117 log.debug("ECMPShortestPathGraph:Paths in Pass{} from switch {} to switch {} is {}",
118 distance,
119 HexString.toHexString(rootSwitch.getDpid().value()),
120 HexString.toHexString(sw.getDpid().value()), path);
121 }
122 }*/
123 }
124
125 private void getDFSPaths(Dpid dstSwitchDpid, Path path, ArrayList<Path> paths) {
126 Dpid rootSwitchDpid = rootSwitch.getDpid();
127 for (LinkData upstreamLink : upstreamLinks.get(dstSwitchDpid)) {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700128 /* Deep clone the path object */
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -0700129 Path sofarPath = new Path();
130 if (!path.isEmpty())
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700131 sofarPath.addAll(path.subList(0, path.size()));
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -0700132 sofarPath.add(upstreamLink);
133 if (upstreamLink.getSrc().getDpid().equals(rootSwitchDpid))
134 {
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700135 paths.add(sofarPath);
136 return;
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -0700137 }
138 else
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700139 getDFSPaths(upstreamLink.getSrc().getDpid(), sofarPath, paths);
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700140 }
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700141 }
142
143 /**
Sangho Shinfbc572c2014-10-02 16:37:05 -0700144 * Return root switch for the graph
145 *
146 * @return root switch
147 */
148 public Switch getRootSwitch() {
149 return rootSwitch;
150 }
151
152 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700153 * Return the computed ECMP paths from the root switch to a given switch in
154 * the network
Sangho Shinfbc572c2014-10-02 16:37:05 -0700155 *
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700156 * @param targetSwitch the target switch
157 * @return the list of ECMP Paths from the root switch to the target switch
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700158 */
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700159 public ArrayList<Path> getECMPPaths(Switch targetSwitch) {
160 ArrayList<Path> pathArray = paths.get(targetSwitch.getDpid());
161 if (pathArray == null && switchSearched.containsKey(
162 targetSwitch.getDpid())) {
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -0700163 pathArray = new ArrayList<>();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700164 Path path = new Path();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700165 Dpid sw = targetSwitch.getDpid();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700166 getDFSPaths(sw, path, pathArray);
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700167 paths.put(targetSwitch.getDpid(), pathArray);
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700168 }
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700169 return pathArray;
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700170 }
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700171
172 /**
173 * Return the complete info of the computed ECMP paths for each switch
174 * learned in multiple iterations from the root switch
Sangho Shinfbc572c2014-10-02 16:37:05 -0700175 *
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700176 * @return the hash table of Switches learned in multiple Dijkstra
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700177 * iterations and corresponding ECMP paths to it from the root
178 * switch
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700179 */
180 public HashMap<Integer, HashMap<Switch,
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700181 ArrayList<Path>>> getCompleteLearnedSwitchesAndPaths() {
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700182
183 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> pathGraph = new
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700184 HashMap<Integer, HashMap<Switch, ArrayList<Path>>>();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700185
186 for (Integer itrIndx : distanceSwitchMap.keySet()) {
187 HashMap<Switch, ArrayList<Path>> swMap = new
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700188 HashMap<Switch, ArrayList<Path>>();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700189 for (Switch sw : distanceSwitchMap.get(itrIndx)) {
190 swMap.put(sw, getECMPPaths(sw));
191 }
192 pathGraph.put(itrIndx, swMap);
193 }
194
195 return pathGraph;
196 }
197
198 /**
199 * Return the complete info of the computed ECMP paths for each switch
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700200 * learned in multiple iterations from the root switch in the form of {
201 * Iteration1, Switch<> via {Switch<>, Switch<>} Switch<> via {Switch<>,
202 * Switch<>} Iteration2, Switch<> via {Switch<>, Switch<>, Switch<>}
203 * {Switch<>, Switch<>, Switch<>} Switch<> via {Switch<>, Switch<>,
204 * Switch<>} }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700205 *
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700206 * @return the hash table of Switches learned in multiple Dijkstra
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700207 * iterations and corresponding ECMP paths in terms of Switches to
208 * be traversed to it from the root switch
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700209 */
210 public HashMap<Integer, HashMap<Switch,
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700211 ArrayList<ArrayList<Dpid>>>> getAllLearnedSwitchesAndVia() {
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700212
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700213 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchViaMap = new HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>>();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700214
215 for (Integer itrIndx : distanceSwitchMap.keySet()) {
Srikanth Vavilapalli5ddf8f02014-09-24 11:02:28 -0700216 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swMap =
217 new HashMap<Switch, ArrayList<ArrayList<Dpid>>>();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700218
219 for (Switch sw : distanceSwitchMap.get(itrIndx)) {
220 ArrayList<ArrayList<Dpid>> swViaArray = new ArrayList<>();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700221 for (Path path : getECMPPaths(sw)) {
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700222 ArrayList<Dpid> swVia = new ArrayList<>();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700223 for (LinkData link : path.subList(0, path.size())) {
224 if (link.getSrc().getDpid().equals(rootSwitch.getDpid())) {
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700225 /* No need to add the root switch again in
226 * the Via list
227 */
228 continue;
229 }
230 swVia.add(link.getSrc().getDpid());
231 }
232 swViaArray.add(swVia);
233 }
234 swMap.put(sw, swViaArray);
235 }
236 switchViaMap.put(itrIndx, swMap);
237 }
238 return switchViaMap;
239 }
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700240}