blob: 9451beb2ff3353a4366a5d2ce75f604c6404eb74 [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
Sangho Shinfbc572c2014-10-02 16:37:05 -070037 *
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 /**
Sangho Shinfbc572c2014-10-02 16:37:05 -0700143 * Return root switch for the graph
144 *
145 * @return root switch
146 */
147 public Switch getRootSwitch() {
148 return rootSwitch;
149 }
150
151 /**
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700152 * Return the computed ECMP paths from the root switch to a given switch in
153 * the network
Sangho Shinfbc572c2014-10-02 16:37:05 -0700154 *
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700155 * @param targetSwitch the target switch
156 * @return the list of ECMP Paths from the root switch to the target switch
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700157 */
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700158 public ArrayList<Path> getECMPPaths(Switch targetSwitch) {
159 ArrayList<Path> pathArray = paths.get(targetSwitch.getDpid());
160 if (pathArray == null && switchSearched.containsKey(
161 targetSwitch.getDpid())) {
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -0700162 pathArray = new ArrayList<>();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700163 Path path = new Path();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700164 Dpid sw = targetSwitch.getDpid();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700165 getDFSPaths(sw, path, pathArray);
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700166 paths.put(targetSwitch.getDpid(), pathArray);
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700167 }
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700168 return pathArray;
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700169 }
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700170
171 /**
172 * Return the complete info of the computed ECMP paths for each switch
173 * learned in multiple iterations from the root switch
Sangho Shinfbc572c2014-10-02 16:37:05 -0700174 *
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700175 * @return the hash table of Switches learned in multiple Dijkstra
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700176 * iterations and corresponding ECMP paths to it from the root
177 * switch
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700178 */
179 public HashMap<Integer, HashMap<Switch,
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700180 ArrayList<Path>>> getCompleteLearnedSwitchesAndPaths() {
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700181
182 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> pathGraph = new
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700183 HashMap<Integer, HashMap<Switch, ArrayList<Path>>>();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700184
185 for (Integer itrIndx : distanceSwitchMap.keySet()) {
186 HashMap<Switch, ArrayList<Path>> swMap = new
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700187 HashMap<Switch, ArrayList<Path>>();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700188 for (Switch sw : distanceSwitchMap.get(itrIndx)) {
189 swMap.put(sw, getECMPPaths(sw));
190 }
191 pathGraph.put(itrIndx, swMap);
192 }
193
194 return pathGraph;
195 }
196
197 /**
198 * Return the complete info of the computed ECMP paths for each switch
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700199 * learned in multiple iterations from the root switch in the form of {
200 * Iteration1, Switch<> via {Switch<>, Switch<>} Switch<> via {Switch<>,
201 * Switch<>} Iteration2, Switch<> via {Switch<>, Switch<>, Switch<>}
202 * {Switch<>, Switch<>, Switch<>} Switch<> via {Switch<>, Switch<>,
203 * Switch<>} }
Sangho Shinfbc572c2014-10-02 16:37:05 -0700204 *
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700205 * @return the hash table of Switches learned in multiple Dijkstra
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700206 * iterations and corresponding ECMP paths in terms of Switches to
207 * be traversed to it from the root switch
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700208 */
209 public HashMap<Integer, HashMap<Switch,
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700210 ArrayList<ArrayList<Dpid>>>> getAllLearnedSwitchesAndVia() {
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700211
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700212 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>> switchViaMap = new HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>>();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700213
214 for (Integer itrIndx : distanceSwitchMap.keySet()) {
Srikanth Vavilapalli5ddf8f02014-09-24 11:02:28 -0700215 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swMap =
216 new HashMap<Switch, ArrayList<ArrayList<Dpid>>>();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700217
218 for (Switch sw : distanceSwitchMap.get(itrIndx)) {
219 ArrayList<ArrayList<Dpid>> swViaArray = new ArrayList<>();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700220 for (Path path : getECMPPaths(sw)) {
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700221 ArrayList<Dpid> swVia = new ArrayList<>();
Srikanth Vavilapallif25c7b02014-10-01 14:30:43 -0700222 for (LinkData link : path.subList(0, path.size())) {
223 if (link.getSrc().getDpid().equals(rootSwitch.getDpid())) {
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700224 /* No need to add the root switch again in
225 * the Via list
226 */
227 continue;
228 }
229 swVia.add(link.getSrc().getDpid());
230 }
231 swViaArray.add(swVia);
232 }
233 swMap.put(sw, swViaArray);
234 }
235 switchViaMap.put(itrIndx, swMap);
236 }
237 return switchViaMap;
238 }
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700239}