ONOS-5799: Make SP2MP compiler partial failure constraint aware
Change-Id: I741c3a22916e7e51e5882bd3993d425e78f18bda
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java
index 62c027a..cb57aee 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/ConnectivityIntentCompiler.java
@@ -94,6 +94,25 @@
* @return Path between the two
* @throws PathNotFoundException if a path cannot be found
*/
+ @Deprecated
+ protected Path getPathOrException(ConnectivityIntent intent,
+ ElementId one, ElementId two) {
+ Path path = getPath(intent, one, two);
+ if (path == null) {
+ throw new PathNotFoundException(one, two);
+ }
+ // TODO: let's be more intelligent about this eventually
+ return path;
+ }
+
+ /**
+ * Computes a path between two ConnectPoints.
+ *
+ * @param intent intent on which behalf path is being computed
+ * @param one start of the path
+ * @param two end of the path
+ * @return Path between the two, or null if no path can be found
+ */
protected Path getPath(ConnectivityIntent intent,
ElementId one, ElementId two) {
Set<Path> paths = pathService.getPaths(one, two, weight(intent.constraints()));
@@ -102,7 +121,7 @@
.filter(path -> checkPath(path, constraints))
.toList();
if (filtered.isEmpty()) {
- throw new PathNotFoundException(one, two);
+ return null;
}
// TODO: let's be more intelligent about this eventually
return filtered.iterator().next();
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompiler.java
index dad8e3b..f0f0046 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/HostToHostIntentCompiler.java
@@ -82,9 +82,9 @@
}
boolean isAsymmetric = intent.constraints().contains(new AsymmetricPathConstraint());
- Path pathOne = getPath(intent, intent.one(), intent.two());
+ Path pathOne = getPathOrException(intent, intent.one(), intent.two());
Path pathTwo = isAsymmetric ?
- getPath(intent, intent.two(), intent.one()) : invertPath(pathOne);
+ getPathOrException(intent, intent.two(), intent.one()) : invertPath(pathOne);
Host one = hostService.getHost(intent.one());
Host two = hostService.getHost(intent.two());
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsIntentCompiler.java
index c8ccf68..4f466de 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsIntentCompiler.java
@@ -70,8 +70,8 @@
}
List<Link> links = new ArrayList<>();
- Path path = getPath(intent, ingressPoint.deviceId(),
- egressPoint.deviceId());
+ Path path = getPathOrException(intent, ingressPoint.deviceId(),
+ egressPoint.deviceId());
links.add(createEdgeLink(ingressPoint, true));
links.addAll(path.links());
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
index cac5d68..758c21b5 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
@@ -28,19 +28,16 @@
import org.onosproject.net.Path;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.intent.Intent;
-import org.onosproject.net.intent.IntentCompiler;
import org.onosproject.net.intent.IntentException;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.LinkCollectionIntent;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.intent.PointToPointIntent;
-import org.onosproject.net.topology.PathService;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import static org.onosproject.net.intent.constraint.PartialFailureConstraint.intentAllowsPartialFailure;
@@ -51,15 +48,12 @@
*/
@Component(immediate = true)
public class MultiPointToSinglePointIntentCompiler
- implements IntentCompiler<MultiPointToSinglePointIntent> {
+ extends ConnectivityIntentCompiler<MultiPointToSinglePointIntent> {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentExtensionService intentManager;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected PathService pathService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceService deviceService;
@Activate
@@ -78,22 +72,23 @@
ConnectPoint egressPoint = intent.egressPoint();
final boolean allowMissingPaths = intentAllowsPartialFailure(intent);
- boolean partialTree = false;
- boolean anyMissingPaths = false;
+ boolean hasPaths = false;
+ boolean missingSomePaths = false;
+
for (ConnectPoint ingressPoint : intent.ingressPoints()) {
if (ingressPoint.deviceId().equals(egressPoint.deviceId())) {
if (deviceService.isAvailable(ingressPoint.deviceId())) {
- partialTree = true;
+ hasPaths = true;
} else {
- anyMissingPaths = true;
+ missingSomePaths = true;
}
-
continue;
}
- Path path = getPath(ingressPoint, intent.egressPoint());
+ Path path = getPath(intent, ingressPoint.deviceId(), intent.egressPoint().deviceId());
+
if (path != null) {
- partialTree = true;
+ hasPaths = true;
for (Link link : path.links()) {
if (links.containsKey(link.dst().deviceId())) {
@@ -107,14 +102,14 @@
links.put(link.src().deviceId(), link);
}
} else {
- anyMissingPaths = true;
+ missingSomePaths = true;
}
}
- if (!partialTree) {
- throw new IntentException("Could not find any paths between ingress and egress points.");
- } else if (!allowMissingPaths && anyMissingPaths) {
- throw new IntentException("Missing some paths between ingress and egress ports.");
+ if (!hasPaths) {
+ throw new IntentException("Cannot find any path between ingress and egress points.");
+ } else if (!allowMissingPaths && missingSomePaths) {
+ throw new IntentException("Missing some paths between ingress and egress points.");
}
Intent result = LinkCollectionIntent.builder()
@@ -131,20 +126,4 @@
return Collections.singletonList(result);
}
-
- /**
- * Computes a path between two ConnectPoints.
- *
- * @param one start of the path
- * @param two end of the path
- * @return Path between the two
- */
- private Path getPath(ConnectPoint one, ConnectPoint two) {
- Set<Path> paths = pathService.getPaths(one.deviceId(), two.deviceId());
- if (paths.isEmpty()) {
- return null;
- }
- // TODO: let's be more intelligent about this eventually
- return paths.iterator().next();
- }
}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java
index a6fac6f..c3fc348 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java
@@ -161,8 +161,8 @@
ConnectPoint egressPoint,
PointToPointIntent intent) {
List<Link> links = new ArrayList<>();
- Path path = getPath(intent, ingressPoint.deviceId(),
- egressPoint.deviceId());
+ Path path = getPathOrException(intent, ingressPoint.deviceId(),
+ egressPoint.deviceId());
links.add(createEdgeLink(ingressPoint, true));
links.addAll(path.links());
@@ -174,8 +174,8 @@
}
private List<Intent> createUnprotectedLinkCollectionIntent(PointToPointIntent intent) {
- Path path = getPath(intent, intent.filteredIngressPoint().connectPoint().deviceId(),
- intent.filteredEgressPoint().connectPoint().deviceId());
+ Path path = getPathOrException(intent, intent.filteredIngressPoint().connectPoint().deviceId(),
+ intent.filteredEgressPoint().connectPoint().deviceId());
return asList(createLinkCollectionIntent(ImmutableSet.copyOf(path.links()),
path.cost(),
@@ -274,8 +274,8 @@
PointToPointIntent intent,
List<Intent> installable) {
List<Link> links = new ArrayList<>();
- Path onlyPath = getPath(intent, ingressPoint.deviceId(),
- egressPoint.deviceId());
+ Path onlyPath = getPathOrException(intent, ingressPoint.deviceId(),
+ egressPoint.deviceId());
List<Intent> reusableIntents = null;
if (installable != null) {
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java
index 22c4e89..a3f7c49 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java
@@ -19,31 +19,34 @@
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Link;
import org.onosproject.net.Path;
+import org.onosproject.net.device.DeviceService;
import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentException;
import org.onosproject.net.intent.LinkCollectionIntent;
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
-import org.onosproject.net.provider.ProviderId;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import static org.onosproject.net.intent.constraint.PartialFailureConstraint.intentAllowsPartialFailure;
+
@Component(immediate = true)
public class SinglePointToMultiPointIntentCompiler
extends ConnectivityIntentCompiler<SinglePointToMultiPointIntent> {
- // TODO: use off-the-shell core provider ID
- private static final ProviderId PID =
- new ProviderId("core", "org.onosproject.core", true);
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
@Activate
public void activate() {
- intentManager.registerCompiler(SinglePointToMultiPointIntent.class,
- this);
+ intentManager.registerCompiler(SinglePointToMultiPointIntent.class, this);
}
@Deactivate
@@ -51,19 +54,40 @@
intentManager.unregisterCompiler(SinglePointToMultiPointIntent.class);
}
-
@Override
public List<Intent> compile(SinglePointToMultiPointIntent intent,
List<Intent> installable) {
Set<Link> links = new HashSet<>();
+ final boolean allowMissingPaths = intentAllowsPartialFailure(intent);
+ boolean hasPaths = false;
+ boolean missingSomePaths = false;
+
for (ConnectPoint egressPoint : intent.egressPoints()) {
if (egressPoint.deviceId().equals(intent.ingressPoint().deviceId())) {
+ // Do not need to look for paths, since ingress and egress
+ // devices are the same.
+ if (deviceService.isAvailable(egressPoint.deviceId())) {
+ hasPaths = true;
+ } else {
+ missingSomePaths = true;
+ }
continue;
}
Path path = getPath(intent, intent.ingressPoint().deviceId(), egressPoint.deviceId());
- links.addAll(path.links());
+ if (path != null) {
+ hasPaths = true;
+ links.addAll(path.links());
+ } else {
+ missingSomePaths = true;
+ }
+ }
+
+ if (!hasPaths) {
+ throw new IntentException("Cannot find any path between ingress and egress points.");
+ } else if (!allowMissingPaths && missingSomePaths) {
+ throw new IntentException("Missing some paths between ingress and egress points.");
}
Intent result = LinkCollectionIntent.builder()
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java
index ce5f3b7..2eb4d9f 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompilerTest.java
@@ -293,7 +293,6 @@
*/
@Test
public void testNonTrivialSelectorsIntent() {
-
Set<FilteredConnectPoint> ingress = ImmutableSet.of(
new FilteredConnectPoint(connectPoint("of1", 1),
DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("100")).build()),