blob: 2dcc33fbef766bfcaa4e15f392219d4754714c7f [file] [log] [blame]
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -07001package net.onrc.onos.apps.segmentrouting;
2
3import java.util.HashMap;
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -07004import java.util.LinkedList;
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -07005import java.util.ArrayList;
6
7import org.projectfloodlight.openflow.util.HexString;
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -07008
9import net.onrc.onos.core.topology.Link;
10import net.onrc.onos.core.topology.LinkData;
11import net.onrc.onos.core.topology.Switch;
12import net.onrc.onos.core.util.Dpid;
13import net.onrc.onos.core.intent.Path;
14
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070015import org.slf4j.Logger;
16import org.slf4j.LoggerFactory;
17
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070018/**
19 * This class creates bandwidth constrained breadth first tree and returns paths
20 * from root switch to leaf switches which satisfies the bandwidth condition. If
21 * bandwidth parameter is not specified, the normal breadth first tree will be
22 * calculated. The paths are snapshot paths at the point of the class
23 * instantiation.
24 */
25public class ECMPShortestPathGraph {
26 LinkedList<Switch> switchQueue = new LinkedList<>();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070027 LinkedList<Integer> distanceQueue = new LinkedList<>();
28 HashMap<Dpid, Integer> switchSearched = new HashMap<>();
29 HashMap<Dpid, ArrayList<LinkData>> upstreamLinks = new HashMap<>();
30 HashMap<Dpid, ArrayList<Path>> paths = new HashMap<>();
31 HashMap<Integer, ArrayList<Switch>> distanceSwitchMap = new HashMap<>();
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070032 Switch rootSwitch;
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070033 private static final Logger log = LoggerFactory
34 .getLogger(SegmentRoutingManager.class);
35
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070036 /**
37 * Constructor.
38 *
39 * @param rootSwitch root of the BFS tree
40 */
41 public ECMPShortestPathGraph(Switch rootSwitch) {
42 this.rootSwitch = rootSwitch;
43 calcECMPShortestPathGraph();
44 }
45
46 /**
47 * Calculates the BFS tree using any provided constraints and Intents.
48 */
49 private void calcECMPShortestPathGraph() {
50 switchQueue.add(rootSwitch);
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070051 int currDistance = 0;
52 distanceQueue.add(currDistance);
53 switchSearched.put(rootSwitch.getDpid(),currDistance);
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070054 while (!switchQueue.isEmpty()) {
55 Switch sw = switchQueue.poll();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070056 Switch prevSw = null;
57 currDistance = distanceQueue.poll();
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070058 for (Link link : sw.getOutgoingLinks()) {
59 Switch reachedSwitch = link.getDstPort().getSwitch();
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070060 if ((prevSw != null) && (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 */
63 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 Vavilapalli878dad12014-09-19 21:02:10 -070069
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070070 Integer distance = switchSearched.get(reachedSwitch.getDpid());
71 if ((distance != null) && (distance.intValue() < (currDistance+1))) {
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -070072 continue;
73 }
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070074 if (distance == null){
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070075 /* First time visiting this switch node */
76 switchQueue.add(reachedSwitch);
77 distanceQueue.add(currDistance+1);
78 switchSearched.put(reachedSwitch.getDpid(),currDistance+1);
79
80 ArrayList<Switch> distanceSwArray = distanceSwitchMap.get(currDistance+1);
81 if (distanceSwArray == null)
82 {
83 distanceSwArray = new ArrayList<Switch>();
84 distanceSwArray.add(reachedSwitch);
85 distanceSwitchMap.put(currDistance+1, distanceSwArray);
86 }
87 else
88 distanceSwArray.add(reachedSwitch);
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -070089 }
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -070090
91 ArrayList<LinkData> upstreamLinkArray =
92 upstreamLinks.get(reachedSwitch.getDpid());
93 if (upstreamLinkArray == null)
94 {
95 upstreamLinkArray = new ArrayList<LinkData>();
96 upstreamLinkArray.add(new LinkData(link));
97 upstreamLinks.put(reachedSwitch.getDpid(), upstreamLinkArray);
98 }
99 else
100 /* 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
105 log.debug("ECMPShortestPathGraph:switchSearched for switch {} is {}",
106 HexString.toHexString(rootSwitch.getDpid().value()), switchSearched);
107 log.debug("ECMPShortestPathGraph:upstreamLinks for switch {} is {}",
108 HexString.toHexString(rootSwitch.getDpid().value()), upstreamLinks);
109 log.debug("ECMPShortestPathGraph:distanceSwitchMap for switch {} is {}",
110 HexString.toHexString(rootSwitch.getDpid().value()), distanceSwitchMap);
111 /*
112 for (Integer distance: distanceSwitchMap.keySet()){
113 for (Switch sw: distanceSwitchMap.get(distance)){
114 ArrayList<Path> path = getPath(sw);
115 log.debug("ECMPShortestPathGraph:Paths in Pass{} from switch {} to switch {} is {}",
116 distance,
117 HexString.toHexString(rootSwitch.getDpid().value()),
118 HexString.toHexString(sw.getDpid().value()), path);
119 }
120 }*/
121 }
122
123 private void getDFSPaths(Dpid dstSwitchDpid, Path path, ArrayList<Path> paths) {
124 Dpid rootSwitchDpid = rootSwitch.getDpid();
125 for (LinkData upstreamLink : upstreamLinks.get(dstSwitchDpid)) {
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -0700126 /* Deep clone the path object */
127 Path sofarPath = new Path();
128 if (!path.isEmpty())
129 sofarPath.addAll(path.subList(0, path.size()));
130 sofarPath.add(upstreamLink);
131 if (upstreamLink.getSrc().getDpid().equals(rootSwitchDpid))
132 {
133 paths.add(sofarPath);
134 return;
135 }
136 else
137 getDFSPaths(upstreamLink.getSrc().getDpid(),sofarPath, paths);
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700138 }
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700139 }
140
141 /**
142 * Return the computed path from the root switch to the leaf switch.
143 *
144 * @param leafSwitch the leaf switch
145 * @return the Path from the root switch to the leaf switch
146 */
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700147 public ArrayList<Path> getPath(Switch leafSwitch) {
148 ArrayList<Path> pathArray = paths.get(leafSwitch.getDpid());
149 if (pathArray == null && switchSearched.containsKey(leafSwitch.getDpid())) {
Srikanth Vavilapalli878dad12014-09-19 21:02:10 -0700150 pathArray = new ArrayList<>();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700151 Path path = new Path();
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700152 Dpid sw = leafSwitch.getDpid();
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700153 getDFSPaths(sw, path, pathArray);
154 paths.put(leafSwitch.getDpid(), pathArray);
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700155 }
Srikanth Vavilapalli174e67c2014-09-19 07:27:17 -0700156 return pathArray;
Srikanth Vavilapalli9338f9d2014-09-18 07:37:09 -0700157 }
158}