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
|
* @return Path between the two
|
||||||
* @throws PathNotFoundException if a path cannot be found
|
* @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,
|
protected Path getPath(ConnectivityIntent intent,
|
||||||
ElementId one, ElementId two) {
|
ElementId one, ElementId two) {
|
||||||
Set<Path> paths = pathService.getPaths(one, two, weight(intent.constraints()));
|
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))
|
.filter(path -> checkPath(path, constraints))
|
||||||
.toList();
|
.toList();
|
||||||
if (filtered.isEmpty()) {
|
if (filtered.isEmpty()) {
|
||||||
throw new PathNotFoundException(one, two);
|
return null;
|
||||||
}
|
}
|
||||||
// TODO: let's be more intelligent about this eventually
|
// TODO: let's be more intelligent about this eventually
|
||||||
return filtered.iterator().next();
|
return filtered.iterator().next();
|
||||||
|
|||||||
@ -82,9 +82,9 @@ public class HostToHostIntentCompiler
|
|||||||
}
|
}
|
||||||
|
|
||||||
boolean isAsymmetric = intent.constraints().contains(new AsymmetricPathConstraint());
|
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 ?
|
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 one = hostService.getHost(intent.one());
|
||||||
Host two = hostService.getHost(intent.two());
|
Host two = hostService.getHost(intent.two());
|
||||||
|
|||||||
@ -70,8 +70,8 @@ public class MplsIntentCompiler extends ConnectivityIntentCompiler<MplsIntent>
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Link> links = new ArrayList<>();
|
List<Link> links = new ArrayList<>();
|
||||||
Path path = getPath(intent, ingressPoint.deviceId(),
|
Path path = getPathOrException(intent, ingressPoint.deviceId(),
|
||||||
egressPoint.deviceId());
|
egressPoint.deviceId());
|
||||||
|
|
||||||
links.add(createEdgeLink(ingressPoint, true));
|
links.add(createEdgeLink(ingressPoint, true));
|
||||||
links.addAll(path.links());
|
links.addAll(path.links());
|
||||||
|
|||||||
@ -28,19 +28,16 @@ import org.onosproject.net.Link;
|
|||||||
import org.onosproject.net.Path;
|
import org.onosproject.net.Path;
|
||||||
import org.onosproject.net.device.DeviceService;
|
import org.onosproject.net.device.DeviceService;
|
||||||
import org.onosproject.net.intent.Intent;
|
import org.onosproject.net.intent.Intent;
|
||||||
import org.onosproject.net.intent.IntentCompiler;
|
|
||||||
import org.onosproject.net.intent.IntentException;
|
import org.onosproject.net.intent.IntentException;
|
||||||
import org.onosproject.net.intent.IntentExtensionService;
|
import org.onosproject.net.intent.IntentExtensionService;
|
||||||
import org.onosproject.net.intent.LinkCollectionIntent;
|
import org.onosproject.net.intent.LinkCollectionIntent;
|
||||||
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
|
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
|
||||||
import org.onosproject.net.intent.PointToPointIntent;
|
import org.onosproject.net.intent.PointToPointIntent;
|
||||||
import org.onosproject.net.topology.PathService;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.onosproject.net.intent.constraint.PartialFailureConstraint.intentAllowsPartialFailure;
|
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)
|
@Component(immediate = true)
|
||||||
public class MultiPointToSinglePointIntentCompiler
|
public class MultiPointToSinglePointIntentCompiler
|
||||||
implements IntentCompiler<MultiPointToSinglePointIntent> {
|
extends ConnectivityIntentCompiler<MultiPointToSinglePointIntent> {
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||||
protected IntentExtensionService intentManager;
|
protected IntentExtensionService intentManager;
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
|
||||||
protected PathService pathService;
|
|
||||||
|
|
||||||
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||||
protected DeviceService deviceService;
|
protected DeviceService deviceService;
|
||||||
|
|
||||||
@ -78,22 +72,23 @@ public class MultiPointToSinglePointIntentCompiler
|
|||||||
ConnectPoint egressPoint = intent.egressPoint();
|
ConnectPoint egressPoint = intent.egressPoint();
|
||||||
|
|
||||||
final boolean allowMissingPaths = intentAllowsPartialFailure(intent);
|
final boolean allowMissingPaths = intentAllowsPartialFailure(intent);
|
||||||
boolean partialTree = false;
|
boolean hasPaths = false;
|
||||||
boolean anyMissingPaths = false;
|
boolean missingSomePaths = false;
|
||||||
|
|
||||||
for (ConnectPoint ingressPoint : intent.ingressPoints()) {
|
for (ConnectPoint ingressPoint : intent.ingressPoints()) {
|
||||||
if (ingressPoint.deviceId().equals(egressPoint.deviceId())) {
|
if (ingressPoint.deviceId().equals(egressPoint.deviceId())) {
|
||||||
if (deviceService.isAvailable(ingressPoint.deviceId())) {
|
if (deviceService.isAvailable(ingressPoint.deviceId())) {
|
||||||
partialTree = true;
|
hasPaths = true;
|
||||||
} else {
|
} else {
|
||||||
anyMissingPaths = true;
|
missingSomePaths = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Path path = getPath(ingressPoint, intent.egressPoint());
|
Path path = getPath(intent, ingressPoint.deviceId(), intent.egressPoint().deviceId());
|
||||||
|
|
||||||
if (path != null) {
|
if (path != null) {
|
||||||
partialTree = true;
|
hasPaths = true;
|
||||||
|
|
||||||
for (Link link : path.links()) {
|
for (Link link : path.links()) {
|
||||||
if (links.containsKey(link.dst().deviceId())) {
|
if (links.containsKey(link.dst().deviceId())) {
|
||||||
@ -107,14 +102,14 @@ public class MultiPointToSinglePointIntentCompiler
|
|||||||
links.put(link.src().deviceId(), link);
|
links.put(link.src().deviceId(), link);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
anyMissingPaths = true;
|
missingSomePaths = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!partialTree) {
|
if (!hasPaths) {
|
||||||
throw new IntentException("Could not find any paths between ingress and egress points.");
|
throw new IntentException("Cannot find any path between ingress and egress points.");
|
||||||
} else if (!allowMissingPaths && anyMissingPaths) {
|
} else if (!allowMissingPaths && missingSomePaths) {
|
||||||
throw new IntentException("Missing some paths between ingress and egress ports.");
|
throw new IntentException("Missing some paths between ingress and egress points.");
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent result = LinkCollectionIntent.builder()
|
Intent result = LinkCollectionIntent.builder()
|
||||||
@ -131,20 +126,4 @@ public class MultiPointToSinglePointIntentCompiler
|
|||||||
|
|
||||||
return Collections.singletonList(result);
|
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,
|
ConnectPoint egressPoint,
|
||||||
PointToPointIntent intent) {
|
PointToPointIntent intent) {
|
||||||
List<Link> links = new ArrayList<>();
|
List<Link> links = new ArrayList<>();
|
||||||
Path path = getPath(intent, ingressPoint.deviceId(),
|
Path path = getPathOrException(intent, ingressPoint.deviceId(),
|
||||||
egressPoint.deviceId());
|
egressPoint.deviceId());
|
||||||
|
|
||||||
links.add(createEdgeLink(ingressPoint, true));
|
links.add(createEdgeLink(ingressPoint, true));
|
||||||
links.addAll(path.links());
|
links.addAll(path.links());
|
||||||
@ -174,8 +174,8 @@ public class PointToPointIntentCompiler
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<Intent> createUnprotectedLinkCollectionIntent(PointToPointIntent intent) {
|
private List<Intent> createUnprotectedLinkCollectionIntent(PointToPointIntent intent) {
|
||||||
Path path = getPath(intent, intent.filteredIngressPoint().connectPoint().deviceId(),
|
Path path = getPathOrException(intent, intent.filteredIngressPoint().connectPoint().deviceId(),
|
||||||
intent.filteredEgressPoint().connectPoint().deviceId());
|
intent.filteredEgressPoint().connectPoint().deviceId());
|
||||||
|
|
||||||
return asList(createLinkCollectionIntent(ImmutableSet.copyOf(path.links()),
|
return asList(createLinkCollectionIntent(ImmutableSet.copyOf(path.links()),
|
||||||
path.cost(),
|
path.cost(),
|
||||||
@ -274,8 +274,8 @@ public class PointToPointIntentCompiler
|
|||||||
PointToPointIntent intent,
|
PointToPointIntent intent,
|
||||||
List<Intent> installable) {
|
List<Intent> installable) {
|
||||||
List<Link> links = new ArrayList<>();
|
List<Link> links = new ArrayList<>();
|
||||||
Path onlyPath = getPath(intent, ingressPoint.deviceId(),
|
Path onlyPath = getPathOrException(intent, ingressPoint.deviceId(),
|
||||||
egressPoint.deviceId());
|
egressPoint.deviceId());
|
||||||
|
|
||||||
List<Intent> reusableIntents = null;
|
List<Intent> reusableIntents = null;
|
||||||
if (installable != 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.Activate;
|
||||||
import org.apache.felix.scr.annotations.Component;
|
import org.apache.felix.scr.annotations.Component;
|
||||||
import org.apache.felix.scr.annotations.Deactivate;
|
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.ConnectPoint;
|
||||||
import org.onosproject.net.Link;
|
import org.onosproject.net.Link;
|
||||||
import org.onosproject.net.Path;
|
import org.onosproject.net.Path;
|
||||||
|
import org.onosproject.net.device.DeviceService;
|
||||||
import org.onosproject.net.intent.Intent;
|
import org.onosproject.net.intent.Intent;
|
||||||
|
import org.onosproject.net.intent.IntentException;
|
||||||
import org.onosproject.net.intent.LinkCollectionIntent;
|
import org.onosproject.net.intent.LinkCollectionIntent;
|
||||||
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
|
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
|
||||||
import org.onosproject.net.provider.ProviderId;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.onosproject.net.intent.constraint.PartialFailureConstraint.intentAllowsPartialFailure;
|
||||||
|
|
||||||
@Component(immediate = true)
|
@Component(immediate = true)
|
||||||
public class SinglePointToMultiPointIntentCompiler
|
public class SinglePointToMultiPointIntentCompiler
|
||||||
extends ConnectivityIntentCompiler<SinglePointToMultiPointIntent> {
|
extends ConnectivityIntentCompiler<SinglePointToMultiPointIntent> {
|
||||||
|
|
||||||
// TODO: use off-the-shell core provider ID
|
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
|
||||||
private static final ProviderId PID =
|
protected DeviceService deviceService;
|
||||||
new ProviderId("core", "org.onosproject.core", true);
|
|
||||||
|
|
||||||
@Activate
|
@Activate
|
||||||
public void activate() {
|
public void activate() {
|
||||||
intentManager.registerCompiler(SinglePointToMultiPointIntent.class,
|
intentManager.registerCompiler(SinglePointToMultiPointIntent.class, this);
|
||||||
this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deactivate
|
@Deactivate
|
||||||
@ -51,19 +54,40 @@ public class SinglePointToMultiPointIntentCompiler
|
|||||||
intentManager.unregisterCompiler(SinglePointToMultiPointIntent.class);
|
intentManager.unregisterCompiler(SinglePointToMultiPointIntent.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Intent> compile(SinglePointToMultiPointIntent intent,
|
public List<Intent> compile(SinglePointToMultiPointIntent intent,
|
||||||
List<Intent> installable) {
|
List<Intent> installable) {
|
||||||
Set<Link> links = new HashSet<>();
|
Set<Link> links = new HashSet<>();
|
||||||
|
|
||||||
|
final boolean allowMissingPaths = intentAllowsPartialFailure(intent);
|
||||||
|
boolean hasPaths = false;
|
||||||
|
boolean missingSomePaths = false;
|
||||||
|
|
||||||
for (ConnectPoint egressPoint : intent.egressPoints()) {
|
for (ConnectPoint egressPoint : intent.egressPoints()) {
|
||||||
if (egressPoint.deviceId().equals(intent.ingressPoint().deviceId())) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Path path = getPath(intent, intent.ingressPoint().deviceId(), egressPoint.deviceId());
|
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()
|
Intent result = LinkCollectionIntent.builder()
|
||||||
|
|||||||
@ -293,7 +293,6 @@ public class MultiPointToSinglePointIntentCompilerTest extends AbstractIntentTes
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testNonTrivialSelectorsIntent() {
|
public void testNonTrivialSelectorsIntent() {
|
||||||
|
|
||||||
Set<FilteredConnectPoint> ingress = ImmutableSet.of(
|
Set<FilteredConnectPoint> ingress = ImmutableSet.of(
|
||||||
new FilteredConnectPoint(connectPoint("of1", 1),
|
new FilteredConnectPoint(connectPoint("of1", 1),
|
||||||
DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("100")).build()),
|
DefaultTrafficSelector.builder().matchVlanId(VlanId.vlanId("100")).build()),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user