ONOS-1334 - Allow multi to single intent across a single switch
Change-Id: I8be3dbc403ea1202fd496e666955402247f71bf1
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentCompiler.java
index e9e319e..72077f9 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentCompiler.java
@@ -27,6 +27,7 @@
import org.onosproject.core.DefaultGroupId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.EdgeLink;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowRule;
@@ -77,8 +78,18 @@
SetMultimap<DeviceId, PortNumber> outputPorts = HashMultimap.create();
for (Link link : intent.links()) {
- inputPorts.put(link.dst().deviceId(), link.dst().port());
- outputPorts.put(link.src().deviceId(), link.src().port());
+ DeviceId srcDeviceId;
+ DeviceId dstDeviceId;
+
+ if (link instanceof EdgeLink) {
+ EdgeLink edgeLink = (EdgeLink) link;
+ dstDeviceId = edgeLink.hostLocation().deviceId();
+ srcDeviceId = dstDeviceId;
+ } else {
+ inputPorts.put(link.dst().deviceId(), link.dst().port());
+ srcDeviceId = link.src().deviceId();
+ }
+ outputPorts.put(srcDeviceId, link.src().port());
}
for (ConnectPoint ingressPoint : intent.ingressPoints()) {
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 a20b533..d63d379 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
@@ -43,6 +43,8 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
+import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
+
/**
* An intent compiler for
* {@link org.onosproject.net.intent.MultiPointToSinglePointIntent}.
@@ -71,28 +73,37 @@
public List<Intent> compile(MultiPointToSinglePointIntent intent, List<Intent> installable,
Set<LinkResourceAllocations> resources) {
Map<DeviceId, Link> links = new HashMap<>();
+ Map<DeviceId, Link> edgeLinks = new HashMap<>();
+ ConnectPoint egressPoint = intent.egressPoint();
for (ConnectPoint ingressPoint : intent.ingressPoints()) {
- Path path = getPath(ingressPoint, intent.egressPoint());
- for (Link link : path.links()) {
- if (links.containsKey(link.src().deviceId())) {
- // We've already reached the existing tree with the first
- // part of this path. Add the merging point with different
- // incoming port, but don't add the remainder of the path
- // in case it differs from the path we already have.
- links.put(link.src().deviceId(), link);
- break;
- }
+ if (ingressPoint.deviceId().equals(egressPoint.deviceId())) {
+ edgeLinks.put(ingressPoint.deviceId(), createEdgeLink(ingressPoint, true));
+ edgeLinks.put(egressPoint.deviceId(), createEdgeLink(egressPoint, false));
+ } else {
+ Path path = getPath(ingressPoint, intent.egressPoint());
+ for (Link link : path.links()) {
+ if (links.containsKey(link.src().deviceId())) {
+ // We've already reached the existing tree with the first
+ // part of this path. Add the merging point with different
+ // incoming port, but don't add the remainder of the path
+ // in case it differs from the path we already have.
+ links.put(link.src().deviceId(), link);
+ break;
+ }
- links.put(link.src().deviceId(), link);
+ links.put(link.src().deviceId(), link);
+ }
}
}
+ Set<Link> allLinks = Sets.newHashSet(links.values());
+ allLinks.addAll(edgeLinks.values());
Intent result = LinkCollectionIntent.builder()
.appId(intent.appId())
.selector(intent.selector())
.treatment(intent.treatment())
- .links(Sets.newHashSet(links.values()))
+ .links(Sets.newHashSet(allLinks))
.ingressPoints(intent.ingressPoints())
.egressPoints(ImmutableSet.of(intent.egressPoint()))
.priority(intent.priority())
diff --git a/core/net/src/test/java/org/onosproject/net/intent/LinksHaveEntryWithSourceDestinationPairMatcher.java b/core/net/src/test/java/org/onosproject/net/intent/LinksHaveEntryWithSourceDestinationPairMatcher.java
index 48a86c4..d34143c 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/LinksHaveEntryWithSourceDestinationPairMatcher.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/LinksHaveEntryWithSourceDestinationPairMatcher.java
@@ -19,6 +19,7 @@
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
+import org.onosproject.net.EdgeLink;
import org.onosproject.net.Link;
/**
@@ -46,6 +47,14 @@
@Override
public boolean matchesSafely(Collection<Link> links) {
for (Link link : links) {
+ if (source.equals(destination) && link instanceof EdgeLink) {
+ EdgeLink edgeLink = (EdgeLink) link;
+ if (edgeLink.hostLocation().elementId()
+ .toString().endsWith(source)) {
+ return true;
+ }
+ }
+
if (link.src().elementId().toString().endsWith(source) &&
link.dst().elementId().toString().endsWith(destination)) {
return true;
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 0d681a7..a3b4525 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
@@ -15,10 +15,14 @@
*/
package org.onosproject.net.intent.impl.compiler;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
import org.hamcrest.Matchers;
import org.junit.Test;
-import org.onosproject.core.ApplicationId;
import org.onosproject.TestApplicationId;
+import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.ElementId;
import org.onosproject.net.Path;
@@ -32,10 +36,7 @@
import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.PathService;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
+import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
@@ -76,9 +77,11 @@
String[] allHops = new String[pathHops.length + 1];
allHops[0] = src.toString();
- System.arraycopy(pathHops, 0, allHops, 1, pathHops.length);
-
+ if (pathHops.length != 0) {
+ System.arraycopy(pathHops, 0, allHops, 1, pathHops.length);
+ }
result.add(createPath(allHops));
+
return result;
}
@@ -98,7 +101,7 @@
*/
private MultiPointToSinglePointIntent makeIntent(String[] ingressIds, String egressId) {
Set<ConnectPoint> ingressPoints = new HashSet<>();
- ConnectPoint egressPoint = connectPoint(egressId, 1);
+ ConnectPoint egressPoint = connectPoint(egressId, 2);
for (String ingressId : ingressIds) {
ingressPoints.add(connectPoint(ingressId, 1));
@@ -228,4 +231,35 @@
assertThat(linkIntent.links(), linksHasPath("n1", egress));
}
}
+
+ /**
+ * Tests ingress and egress on the same device.
+ */
+ @Test
+ public void testSameDeviceCompilation() {
+ String[] ingress = {"i1", "i2"};
+ String egress = "i1";
+
+ MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
+ assertThat(intent, is(notNullValue()));
+
+ final String[] hops = {"i1", "i2"};
+ MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
+ assertThat(compiler, is(notNullValue()));
+
+ List<Intent> result = compiler.compile(intent, null, null);
+ assertThat(result, is(notNullValue()));
+ assertThat(result, hasSize(1));
+ Intent resultIntent = result.get(0);
+ assertThat(resultIntent, instanceOf(LinkCollectionIntent.class));
+
+ if (resultIntent instanceof LinkCollectionIntent) {
+ LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
+ assertThat(linkIntent.links(), hasSize(ingress.length + 1));
+
+ assertThat(linkIntent.links(), linksHasPath("i2", "i1"));
+
+ assertThat(linkIntent.links(), linksHasPath("i1", "i1"));
+ }
+ }
}