blob: 5fa76ca14b80fe02ad8d4faad3b09c5469b1569c [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 /**
36 * Constructor.
37 *
38 * @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);
52 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 Vavilapalli878dad12014-09-19 21:02:10 -070059 if ((prevSw != null) && (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 */
62 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());
70 if ((distance != null) && (distance.intValue() < (currDistance+1))) {
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070071 continue;
72 }
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070073 if (distance == null){
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070074 /* First time visiting this switch node */
75 switchQueue.add(reachedSwitch);
76 distanceQueue.add(currDistance+1);
77 switchSearched.put(reachedSwitch.getDpid(),currDistance+1);
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070078
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070079 ArrayList<Switch> distanceSwArray = distanceSwitchMap.get(currDistance+1);
80 if (distanceSwArray == null)
81 {
82 distanceSwArray = new ArrayList<Switch>();
83 distanceSwArray.add(reachedSwitch);
84 distanceSwitchMap.put(currDistance+1, distanceSwArray);
85 }
86 else
87 distanceSwArray.add(reachedSwitch);
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070088 }
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070089
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -070090 ArrayList<LinkData> upstreamLinkArray =
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070091 upstreamLinks.get(reachedSwitch.getDpid());
92 if (upstreamLinkArray == null)
93 {
94 upstreamLinkArray = new ArrayList<LinkData>();
95 upstreamLinkArray.add(new LinkData(link));
96 upstreamLinks.put(reachedSwitch.getDpid(), upstreamLinkArray);
97 }
98 else
99 /* ECMP links */
100 upstreamLinkArray.add(new LinkData(link));
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700101 }
102 }
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700103
104 log.debug("ECMPShortestPathGraph:switchSearched for switch {} is {}",
105 HexString.toHexString(rootSwitch.getDpid().value()), switchSearched);
106 log.debug("ECMPShortestPathGraph:upstreamLinks for switch {} is {}",
107 HexString.toHexString(rootSwitch.getDpid().value()), upstreamLinks);
108 log.debug("ECMPShortestPathGraph:distanceSwitchMap for switch {} is {}",
109 HexString.toHexString(rootSwitch.getDpid().value()), distanceSwitchMap);
110 /*
111 for (Integer distance: distanceSwitchMap.keySet()){
112 for (Switch sw: distanceSwitchMap.get(distance)){
113 ArrayList<Path> path = getPath(sw);
114 log.debug("ECMPShortestPathGraph:Paths in Pass{} from switch {} to switch {} is {}",
115 distance,
116 HexString.toHexString(rootSwitch.getDpid().value()),
117 HexString.toHexString(sw.getDpid().value()), path);
118 }
119 }*/
120 }
121
122 private void getDFSPaths(Dpid dstSwitchDpid, Path path, ArrayList<Path> paths) {
123 Dpid rootSwitchDpid = rootSwitch.getDpid();
124 for (LinkData upstreamLink : upstreamLinks.get(dstSwitchDpid)) {
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -0700125 /* Deep clone the path object */
126 Path sofarPath = new Path();
127 if (!path.isEmpty())
128 sofarPath.addAll(path.subList(0, path.size()));
129 sofarPath.add(upstreamLink);
130 if (upstreamLink.getSrc().getDpid().equals(rootSwitchDpid))
131 {
132 paths.add(sofarPath);
133 return;
134 }
135 else
136 getDFSPaths(upstreamLink.getSrc().getDpid(),sofarPath, paths);
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700137 }
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700138 }
139
140 /**
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700141 * Return the computed ECMP paths from the root switch to a given switch
142 * in the network
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700143 *
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700144 * @param targetSwitch the target switch
145 * @return the list of ECMP Paths from the root switch to the target switch
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700146 */
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700147 public ArrayList<Path> getECMPPaths(Switch targetSwitch) {
148 ArrayList<Path> pathArray = paths.get(targetSwitch.getDpid());
149 if (pathArray == null && switchSearched.containsKey(
150 targetSwitch.getDpid())) {
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -0700151 pathArray = new ArrayList<>();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700152 Path path = new Path();
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700153 Dpid sw = targetSwitch.getDpid();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700154 getDFSPaths(sw, path, pathArray);
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700155 paths.put(targetSwitch.getDpid(), pathArray);
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700156 }
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700157 return pathArray;
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700158 }
Srikanth Vavilapalli363f1dc2014-09-22 14:30:23 -0700159
160 /**
161 * Return the complete info of the computed ECMP paths for each switch
162 * learned in multiple iterations from the root switch
163 *
164 * @return the hash table of Switches learned in multiple Dijkstra
165 * iterations and corresponding ECMP paths to it from the root switch
166 */
167 public HashMap<Integer, HashMap<Switch,
168 ArrayList<Path>>> getCompleteLearnedSwitchesAndPaths() {
169
170 HashMap<Integer, HashMap<Switch, ArrayList<Path>>> pathGraph = new
171 HashMap<Integer, HashMap<Switch, ArrayList<Path>>>();
172
173 for (Integer itrIndx : distanceSwitchMap.keySet()) {
174 HashMap<Switch, ArrayList<Path>> swMap = new
175 HashMap<Switch, ArrayList<Path>>();
176 for (Switch sw : distanceSwitchMap.get(itrIndx)) {
177 swMap.put(sw, getECMPPaths(sw));
178 }
179 pathGraph.put(itrIndx, swMap);
180 }
181
182 return pathGraph;
183 }
184
185 /**
186 * Return the complete info of the computed ECMP paths for each switch
187 * learned in multiple iterations from the root switch in the form of
188 * {
189 * Iteration1,
190 * Switch<> via {Switch<>, Switch<>}
191 * Switch<> via {Switch<>, Switch<>}
192 * Iteration2,
193 * Switch<> via {Switch<>, Switch<>, Switch<>}
194 * {Switch<>, Switch<>, Switch<>}
195 * Switch<> via {Switch<>, Switch<>, Switch<>}
196 * }
197 *
198 * @return the hash table of Switches learned in multiple Dijkstra
199 * iterations and corresponding ECMP paths in terms of Switches to be
200 * traversed to it from the root switch
201 */
202 public HashMap<Integer, HashMap<Switch,
203 ArrayList<ArrayList<Dpid>>>> getAllLearnedSwitchesAndVia() {
204
205 HashMap<Integer, HashMap<Switch, ArrayList<ArrayList<Dpid>>>>
206 switchViaMap = new HashMap();
207
208 for (Integer itrIndx : distanceSwitchMap.keySet()) {
209 HashMap<Switch, ArrayList<ArrayList<Dpid>>> swMap = new HashMap();
210
211 for (Switch sw : distanceSwitchMap.get(itrIndx)) {
212 ArrayList<ArrayList<Dpid>> swViaArray = new ArrayList<>();
213 for (Path path:getECMPPaths(sw)){
214 ArrayList<Dpid> swVia = new ArrayList<>();
215 for (LinkData link:path.subList(0, path.size())){
216 if (link.getSrc().getDpid().equals(rootSwitch.getDpid())){
217 /* No need to add the root switch again in
218 * the Via list
219 */
220 continue;
221 }
222 swVia.add(link.getSrc().getDpid());
223 }
224 swViaArray.add(swVia);
225 }
226 swMap.put(sw, swViaArray);
227 }
228 switchViaMap.put(itrIndx, swMap);
229 }
230 return switchViaMap;
231 }
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700232}