Ray Milkey

ONOS-1334 - Allow multi to single intent across a single switch

Change-Id: I8be3dbc403ea1202fd496e666955402247f71bf1
...@@ -27,6 +27,7 @@ import org.onosproject.core.CoreService; ...@@ -27,6 +27,7 @@ import org.onosproject.core.CoreService;
27 import org.onosproject.core.DefaultGroupId; 27 import org.onosproject.core.DefaultGroupId;
28 import org.onosproject.net.ConnectPoint; 28 import org.onosproject.net.ConnectPoint;
29 import org.onosproject.net.DeviceId; 29 import org.onosproject.net.DeviceId;
30 +import org.onosproject.net.EdgeLink;
30 import org.onosproject.net.Link; 31 import org.onosproject.net.Link;
31 import org.onosproject.net.PortNumber; 32 import org.onosproject.net.PortNumber;
32 import org.onosproject.net.flow.DefaultFlowRule; 33 import org.onosproject.net.flow.DefaultFlowRule;
...@@ -77,8 +78,18 @@ public class LinkCollectionIntentCompiler implements IntentCompiler<LinkCollecti ...@@ -77,8 +78,18 @@ public class LinkCollectionIntentCompiler implements IntentCompiler<LinkCollecti
77 SetMultimap<DeviceId, PortNumber> outputPorts = HashMultimap.create(); 78 SetMultimap<DeviceId, PortNumber> outputPorts = HashMultimap.create();
78 79
79 for (Link link : intent.links()) { 80 for (Link link : intent.links()) {
80 - inputPorts.put(link.dst().deviceId(), link.dst().port()); 81 + DeviceId srcDeviceId;
81 - outputPorts.put(link.src().deviceId(), link.src().port()); 82 + DeviceId dstDeviceId;
83 +
84 + if (link instanceof EdgeLink) {
85 + EdgeLink edgeLink = (EdgeLink) link;
86 + dstDeviceId = edgeLink.hostLocation().deviceId();
87 + srcDeviceId = dstDeviceId;
88 + } else {
89 + inputPorts.put(link.dst().deviceId(), link.dst().port());
90 + srcDeviceId = link.src().deviceId();
91 + }
92 + outputPorts.put(srcDeviceId, link.src().port());
82 } 93 }
83 94
84 for (ConnectPoint ingressPoint : intent.ingressPoints()) { 95 for (ConnectPoint ingressPoint : intent.ingressPoints()) {
......
...@@ -43,6 +43,8 @@ import org.onosproject.net.topology.PathService; ...@@ -43,6 +43,8 @@ import org.onosproject.net.topology.PathService;
43 import com.google.common.collect.ImmutableSet; 43 import com.google.common.collect.ImmutableSet;
44 import com.google.common.collect.Sets; 44 import com.google.common.collect.Sets;
45 45
46 +import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
47 +
46 /** 48 /**
47 * An intent compiler for 49 * An intent compiler for
48 * {@link org.onosproject.net.intent.MultiPointToSinglePointIntent}. 50 * {@link org.onosproject.net.intent.MultiPointToSinglePointIntent}.
...@@ -71,28 +73,37 @@ public class MultiPointToSinglePointIntentCompiler ...@@ -71,28 +73,37 @@ public class MultiPointToSinglePointIntentCompiler
71 public List<Intent> compile(MultiPointToSinglePointIntent intent, List<Intent> installable, 73 public List<Intent> compile(MultiPointToSinglePointIntent intent, List<Intent> installable,
72 Set<LinkResourceAllocations> resources) { 74 Set<LinkResourceAllocations> resources) {
73 Map<DeviceId, Link> links = new HashMap<>(); 75 Map<DeviceId, Link> links = new HashMap<>();
76 + Map<DeviceId, Link> edgeLinks = new HashMap<>();
77 + ConnectPoint egressPoint = intent.egressPoint();
74 78
75 for (ConnectPoint ingressPoint : intent.ingressPoints()) { 79 for (ConnectPoint ingressPoint : intent.ingressPoints()) {
76 - Path path = getPath(ingressPoint, intent.egressPoint()); 80 + if (ingressPoint.deviceId().equals(egressPoint.deviceId())) {
77 - for (Link link : path.links()) { 81 + edgeLinks.put(ingressPoint.deviceId(), createEdgeLink(ingressPoint, true));
78 - if (links.containsKey(link.src().deviceId())) { 82 + edgeLinks.put(egressPoint.deviceId(), createEdgeLink(egressPoint, false));
79 - // We've already reached the existing tree with the first 83 + } else {
80 - // part of this path. Add the merging point with different 84 + Path path = getPath(ingressPoint, intent.egressPoint());
81 - // incoming port, but don't add the remainder of the path 85 + for (Link link : path.links()) {
82 - // in case it differs from the path we already have. 86 + if (links.containsKey(link.src().deviceId())) {
87 + // We've already reached the existing tree with the first
88 + // part of this path. Add the merging point with different
89 + // incoming port, but don't add the remainder of the path
90 + // in case it differs from the path we already have.
91 + links.put(link.src().deviceId(), link);
92 + break;
93 + }
94 +
83 links.put(link.src().deviceId(), link); 95 links.put(link.src().deviceId(), link);
84 - break;
85 } 96 }
86 -
87 - links.put(link.src().deviceId(), link);
88 } 97 }
89 } 98 }
90 99
100 + Set<Link> allLinks = Sets.newHashSet(links.values());
101 + allLinks.addAll(edgeLinks.values());
91 Intent result = LinkCollectionIntent.builder() 102 Intent result = LinkCollectionIntent.builder()
92 .appId(intent.appId()) 103 .appId(intent.appId())
93 .selector(intent.selector()) 104 .selector(intent.selector())
94 .treatment(intent.treatment()) 105 .treatment(intent.treatment())
95 - .links(Sets.newHashSet(links.values())) 106 + .links(Sets.newHashSet(allLinks))
96 .ingressPoints(intent.ingressPoints()) 107 .ingressPoints(intent.ingressPoints())
97 .egressPoints(ImmutableSet.of(intent.egressPoint())) 108 .egressPoints(ImmutableSet.of(intent.egressPoint()))
98 .priority(intent.priority()) 109 .priority(intent.priority())
......
...@@ -19,6 +19,7 @@ import java.util.Collection; ...@@ -19,6 +19,7 @@ import java.util.Collection;
19 19
20 import org.hamcrest.Description; 20 import org.hamcrest.Description;
21 import org.hamcrest.TypeSafeMatcher; 21 import org.hamcrest.TypeSafeMatcher;
22 +import org.onosproject.net.EdgeLink;
22 import org.onosproject.net.Link; 23 import org.onosproject.net.Link;
23 24
24 /** 25 /**
...@@ -46,6 +47,14 @@ public class LinksHaveEntryWithSourceDestinationPairMatcher extends ...@@ -46,6 +47,14 @@ public class LinksHaveEntryWithSourceDestinationPairMatcher extends
46 @Override 47 @Override
47 public boolean matchesSafely(Collection<Link> links) { 48 public boolean matchesSafely(Collection<Link> links) {
48 for (Link link : links) { 49 for (Link link : links) {
50 + if (source.equals(destination) && link instanceof EdgeLink) {
51 + EdgeLink edgeLink = (EdgeLink) link;
52 + if (edgeLink.hostLocation().elementId()
53 + .toString().endsWith(source)) {
54 + return true;
55 + }
56 + }
57 +
49 if (link.src().elementId().toString().endsWith(source) && 58 if (link.src().elementId().toString().endsWith(source) &&
50 link.dst().elementId().toString().endsWith(destination)) { 59 link.dst().elementId().toString().endsWith(destination)) {
51 return true; 60 return true;
......
...@@ -15,10 +15,14 @@ ...@@ -15,10 +15,14 @@
15 */ 15 */
16 package org.onosproject.net.intent.impl.compiler; 16 package org.onosproject.net.intent.impl.compiler;
17 17
18 +import java.util.HashSet;
19 +import java.util.List;
20 +import java.util.Set;
21 +
18 import org.hamcrest.Matchers; 22 import org.hamcrest.Matchers;
19 import org.junit.Test; 23 import org.junit.Test;
20 -import org.onosproject.core.ApplicationId;
21 import org.onosproject.TestApplicationId; 24 import org.onosproject.TestApplicationId;
25 +import org.onosproject.core.ApplicationId;
22 import org.onosproject.net.ConnectPoint; 26 import org.onosproject.net.ConnectPoint;
23 import org.onosproject.net.ElementId; 27 import org.onosproject.net.ElementId;
24 import org.onosproject.net.Path; 28 import org.onosproject.net.Path;
...@@ -32,10 +36,7 @@ import org.onosproject.net.intent.MultiPointToSinglePointIntent; ...@@ -32,10 +36,7 @@ import org.onosproject.net.intent.MultiPointToSinglePointIntent;
32 import org.onosproject.net.topology.LinkWeight; 36 import org.onosproject.net.topology.LinkWeight;
33 import org.onosproject.net.topology.PathService; 37 import org.onosproject.net.topology.PathService;
34 38
35 -import java.util.HashSet; 39 +import static org.hamcrest.CoreMatchers.instanceOf;
36 -import java.util.List;
37 -import java.util.Set;
38 -
39 import static org.hamcrest.CoreMatchers.notNullValue; 40 import static org.hamcrest.CoreMatchers.notNullValue;
40 import static org.hamcrest.MatcherAssert.assertThat; 41 import static org.hamcrest.MatcherAssert.assertThat;
41 import static org.hamcrest.Matchers.hasSize; 42 import static org.hamcrest.Matchers.hasSize;
...@@ -76,9 +77,11 @@ public class MultiPointToSinglePointIntentCompilerTest extends AbstractIntentTes ...@@ -76,9 +77,11 @@ public class MultiPointToSinglePointIntentCompilerTest extends AbstractIntentTes
76 77
77 String[] allHops = new String[pathHops.length + 1]; 78 String[] allHops = new String[pathHops.length + 1];
78 allHops[0] = src.toString(); 79 allHops[0] = src.toString();
79 - System.arraycopy(pathHops, 0, allHops, 1, pathHops.length); 80 + if (pathHops.length != 0) {
80 - 81 + System.arraycopy(pathHops, 0, allHops, 1, pathHops.length);
82 + }
81 result.add(createPath(allHops)); 83 result.add(createPath(allHops));
84 +
82 return result; 85 return result;
83 } 86 }
84 87
...@@ -98,7 +101,7 @@ public class MultiPointToSinglePointIntentCompilerTest extends AbstractIntentTes ...@@ -98,7 +101,7 @@ public class MultiPointToSinglePointIntentCompilerTest extends AbstractIntentTes
98 */ 101 */
99 private MultiPointToSinglePointIntent makeIntent(String[] ingressIds, String egressId) { 102 private MultiPointToSinglePointIntent makeIntent(String[] ingressIds, String egressId) {
100 Set<ConnectPoint> ingressPoints = new HashSet<>(); 103 Set<ConnectPoint> ingressPoints = new HashSet<>();
101 - ConnectPoint egressPoint = connectPoint(egressId, 1); 104 + ConnectPoint egressPoint = connectPoint(egressId, 2);
102 105
103 for (String ingressId : ingressIds) { 106 for (String ingressId : ingressIds) {
104 ingressPoints.add(connectPoint(ingressId, 1)); 107 ingressPoints.add(connectPoint(ingressId, 1));
...@@ -228,4 +231,35 @@ public class MultiPointToSinglePointIntentCompilerTest extends AbstractIntentTes ...@@ -228,4 +231,35 @@ public class MultiPointToSinglePointIntentCompilerTest extends AbstractIntentTes
228 assertThat(linkIntent.links(), linksHasPath("n1", egress)); 231 assertThat(linkIntent.links(), linksHasPath("n1", egress));
229 } 232 }
230 } 233 }
234 +
235 + /**
236 + * Tests ingress and egress on the same device.
237 + */
238 + @Test
239 + public void testSameDeviceCompilation() {
240 + String[] ingress = {"i1", "i2"};
241 + String egress = "i1";
242 +
243 + MultiPointToSinglePointIntent intent = makeIntent(ingress, egress);
244 + assertThat(intent, is(notNullValue()));
245 +
246 + final String[] hops = {"i1", "i2"};
247 + MultiPointToSinglePointIntentCompiler compiler = makeCompiler(hops);
248 + assertThat(compiler, is(notNullValue()));
249 +
250 + List<Intent> result = compiler.compile(intent, null, null);
251 + assertThat(result, is(notNullValue()));
252 + assertThat(result, hasSize(1));
253 + Intent resultIntent = result.get(0);
254 + assertThat(resultIntent, instanceOf(LinkCollectionIntent.class));
255 +
256 + if (resultIntent instanceof LinkCollectionIntent) {
257 + LinkCollectionIntent linkIntent = (LinkCollectionIntent) resultIntent;
258 + assertThat(linkIntent.links(), hasSize(ingress.length + 1));
259 +
260 + assertThat(linkIntent.links(), linksHasPath("i2", "i1"));
261 +
262 + assertThat(linkIntent.links(), linksHasPath("i1", "i1"));
263 + }
264 + }
231 } 265 }
......