16 package org.openkilda.pce.algo;
23 import com.google.common.collect.Lists;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.HashMap;
30 import java.util.LinkedList;
31 import java.util.List;
66 private int allowedDepth;
67 private int bestCost = Integer.MAX_VALUE;
68 private SearchNode bestPath = null;
71 this.network = network;
74 this.allowedDepth = allowedDepth;
75 if (this.start == null) {
76 logger.warn(
"SOURCE node doesn't exist. It isn't in the AVAILABLE network: {}", srcDpid);
78 if (this.end == null) {
79 logger.warn(
"DESTINATION node doesn't exist. It isn't in the AVAILABLE network: {}", dstDpid);
91 HashMap<SimpleSwitch, SearchNode> toVisitLookup =
new HashMap<>();
92 LinkedList<SearchNode> toVisit =
new LinkedList<>();
93 HashMap<SimpleSwitch, SearchNode> visited =
new HashMap<>();
95 if (start != null && end != null) {
96 toVisitLookup.put(start,
new SearchNode(allowedDepth, 0, start));
97 toVisit.add(toVisitLookup.get(start));
100 while (toVisit.size() > 0) {
101 SearchNode current = toVisit.pop();
104 if (current.dstSw.equals(end)) {
106 if (current.parentCost < bestCost) {
109 bestCost = current.parentCost;
117 SearchNode prior = visited.get(current.dstSw);
120 if (current.parentCost >= prior.parentCost) {
126 visited.put(current.dstSw, current);
129 if (current.allowedDepth < 0 || current.parentCost > bestCost) {
135 for (Set<SimpleIsl> isls: current.dstSw.outbound.values()) {
137 toVisit.add(current.addNode(isl));
142 return (bestPath != null) ? bestPath.parentPath :
new LinkedList<>();
159 public LinkedList<SimpleIsl>
getPath(List<SimpleIsl> hint) {
162 if (hint != null && hint.size() > 0) {
166 logger.trace(
"getPath w/ Hint: Reversing the path from {}->{} to {}->{}", from, to, to, from);
168 hint = swapSrcDst(Lists.reverse(hint));
176 logger.trace(
"getPath w/ Hint: hint matches start/ed {}->{}", from, to);
178 SearchNode best = confirmIsls(hint);
180 logger.debug(
"getPath w/ Hint: the hint path EXISTS for {}->{}", from, to);
181 bestCost = best.parentCost;
184 logger.info(
"getPath w/ Hint: the hint path DOES NOT EXIST for {}->{}, will find new path",
195 private List<SimpleIsl> swapSrcDst(List<SimpleIsl> originalIsls) {
196 List<SimpleIsl> mirrorIsls =
new ArrayList<>();
197 for (
SimpleIsl original : originalIsls) {
199 mirrorIsls.add(
new SimpleIsl(original.getDstDpid(), original.getSrcDpid(), original.getDstPort(),
200 original.getSrcPort(), original.getCost(), original.getLatency()));
211 private static final Set<SimpleIsl> safeSet(Set<SimpleIsl> other) {
212 return other == null ? Collections.EMPTY_SET : other;
218 private SearchNode confirmIsls(List<SimpleIsl> srcIsls) {
220 LinkedList<SimpleIsl> confirmedIsls =
new LinkedList<>();
222 boolean validPath =
true;
223 for (SimpleIsl
i : srcIsls) {
224 boolean foundThisOne =
false;
226 if (srcSwitch != null) {
227 Set<SimpleIsl> pathsToDst = safeSet(srcSwitch.outbound.get(
i.getDstDpid()));
228 if (pathsToDst.equals(Collections.EMPTY_SET)) {
229 logger.debug(
"No ISLS from {} to {}",
i.getSrcDpid(),
i.getDstDpid());
231 for (SimpleIsl orig : pathsToDst) {
232 if (
i.equals(orig)) {
234 confirmedIsls.add(orig);
235 totalCost += orig.getCost();
240 logger.warn(
"confirmIsls: Found a null switch during getPath(hint): {}",
i.getSrcDpid());
249 return new SearchNode(this.allowedDepth - confirmedIsls.size(), totalCost,
250 network.
getSimpleSwitch(confirmedIsls.peekLast().getDstDpid()), confirmedIsls);
260 private class SearchNode
implements Cloneable {
264 LinkedList<SimpleIsl> parentPath;
268 public SearchNode(
int allowedDepth,
int parentCost, SimpleSwitch dstSw) {
269 this(allowedDepth, parentCost, dstSw,
new LinkedList<SimpleIsl>());
272 public SearchNode(
int allowedDepth,
int parentCost, SimpleSwitch dstSw, LinkedList<SimpleIsl> parentPath) {
274 this.allowedDepth = allowedDepth;
275 this.parentCost = parentCost;
276 this.parentPath = parentPath;
279 public SearchNode addNode(SimpleIsl nextIsl) {
280 SearchNode newNode = this.clone();
281 newNode.parentPath.add(nextIsl);
283 newNode.allowedDepth--;
284 newNode.parentCost += nextIsl.getCost();
289 @SuppressWarnings(
"unchecked")
290 protected SearchNode clone() {
291 return new SearchNode(allowedDepth, parentCost, dstSw, (LinkedList<SimpleIsl>) parentPath.clone());
295 private void createSearchNode() {
LinkedList< SimpleIsl > getPath()
Map< SwitchId, SimpleSwitch > getSwitches()
LinkedList< SimpleIsl > getPath(List< SimpleIsl > hint)
SimpleGetShortestPath(AvailableNetwork network, SwitchId srcDpid, SwitchId dstDpid, int allowedDepth)
SimpleSwitch getSimpleSwitch(SwitchId dpid)