ONOS-1334 - Allow multi to single intent across a single switch
Change-Id: I8be3dbc403ea1202fd496e666955402247f71bf1
Showing
4 changed files
with
86 additions
and
21 deletions
... | @@ -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 | } | ... | ... |
-
Please register or login to post a comment