mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-24 13:51:27 +02:00
ONOS-5799: Make SP2MP compiler partial failure constraint aware
Change-Id: I741c3a22916e7e51e5882bd3993d425e78f18bda
This commit is contained in:
parent
61bb7f4d6a
commit
d26ea65e84
@ -94,6 +94,25 @@ public abstract class ConnectivityIntentCompiler<T extends ConnectivityIntent>
|
||||
* @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 @@ public abstract class ConnectivityIntentCompiler<T extends ConnectivityIntent>
|
||||
.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();
|
||||
|
||||
@ -82,9 +82,9 @@ public class HostToHostIntentCompiler
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
@ -70,8 +70,8 @@ public class MplsIntentCompiler extends ConnectivityIntentCompiler<MplsIntent>
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
@ -28,19 +28,16 @@ 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.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,14 +48,11 @@ import static org.onosproject.net.intent.constraint.PartialFailureConstraint.int
|
||||
*/
|
||||
@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;
|
||||
|
||||
@ -78,22 +72,23 @@ public class MultiPointToSinglePointIntentCompiler
|
||||
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 @@ public class MultiPointToSinglePointIntentCompiler
|
||||
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 @@ public class MultiPointToSinglePointIntentCompiler
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,8 +161,8 @@ public class PointToPointIntentCompiler
|
||||
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 @@ public class PointToPointIntentCompiler
|
||||
}
|
||||
|
||||
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 @@ public class PointToPointIntentCompiler
|
||||
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) {
|
||||
|
||||
@ -19,31 +19,34 @@ import com.google.common.collect.ImmutableSet;
|
||||
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 @@ public class SinglePointToMultiPointIntentCompiler
|
||||
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()
|
||||
|
||||
@ -293,7 +293,6 @@ public class MultiPointToSinglePointIntentCompilerTest extends AbstractIntentTes
|
||||
*/
|
||||
@Test
|
||||
public void testNonTrivialSelectorsIntent() {
|
||||
|
||||
Set<FilteredConnectPoint> ingress = ImmutableSet.of(
|
||||
new FilteredConnectPoint(connectPoint("of1", 1),
|
||||
DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("100")).build()),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user