Support [ONOS-4593] and implement [ONOS-4594]
Changes:
- Adds extension to sp2mp intents;
- Adds extension to linkcollection intents;
- Adds extension to sp2mp compiler;
- Adds extension to linkcollection compiler;
- Adds re-ordering of the actions;
- Adds unit tests for both sp2mp intents and linkcollection intents;
Change-Id: Ib925e9066682e077a0bb4bbfd20a4382623b7541
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionCompiler.java
index b37095a..cfc6652 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionCompiler.java
@@ -27,6 +27,7 @@
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
import org.onosproject.net.flow.instructions.L1ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
@@ -211,10 +212,29 @@
}
} else {
if (outPorts.stream().allMatch(egressPorts::contains)) {
- TrafficTreatment.Builder egressTreatmentBuilder =
- DefaultTrafficTreatment.builder(intent.treatment());
- outPorts.forEach(egressTreatmentBuilder::setOutput);
-
+ TrafficTreatment.Builder egressTreatmentBuilder = DefaultTrafficTreatment.builder();
+ if (intent.egressTreatments() != null && !intent.egressTreatments().isEmpty()) {
+ for (PortNumber outPort : outPorts) {
+ Optional<ConnectPoint> connectPoint = intent.egressPoints()
+ .stream()
+ .filter(egressPoint -> egressPoint.port().equals(outPort)
+ && egressPoint.deviceId().equals(deviceId))
+ .findFirst();
+ if (connectPoint.isPresent()) {
+ TrafficTreatment egressTreatment = intent.egressTreatments().get(connectPoint.get());
+ this.addTreatment(egressTreatmentBuilder, egressTreatment);
+ egressTreatmentBuilder = this.updateBuilder(egressTreatmentBuilder, intent.selector());
+ egressTreatmentBuilder.setOutput(outPort);
+ } else {
+ throw new IntentCompilationException("Looking for connect point associated to " +
+ "the treatment. outPort not in egressPoints");
+ }
+ }
+ } else {
+ egressTreatmentBuilder = this
+ .updateBuilder(DefaultTrafficTreatment.builder(intent.treatment()), intent.selector());
+ outPorts.forEach(egressTreatmentBuilder::setOutput);
+ }
selectorBuilder = DefaultTrafficSelector.builder(intent.selector());
treatment = egressTreatmentBuilder.build();
} else {
@@ -230,10 +250,34 @@
}
/**
+ * Update a builder using a treatment.
+ * @param builder the builder to update
+ * @param treatment the treatment to add
+ * @return the new builder
+ */
+ private TrafficTreatment.Builder addTreatment(TrafficTreatment.Builder builder, TrafficTreatment treatment) {
+ builder.deferred();
+ for (Instruction instruction : treatment.deferred()) {
+ builder.add(instruction);
+ }
+ builder.immediate();
+ for (Instruction instruction : treatment.immediate()) {
+ builder.add(instruction);
+ }
+ return builder;
+ }
+
+ /**
* Update the original builder with the necessary operations
* to have a correct forwarding given an ingress selector.
+ * TODO
+ * This means that if the ingress selectors match on different vlanids and
+ * the egress treatment rewrite the vlanid the forwarding works
+ * but if we need to push for example an mpls label at the egress
+ * we need to implement properly this method.
*
* @param treatmentBuilder the builder to modify
+ * @param intentSelector the intent selector to use as input
* @return the new treatment created
*/
private TrafficTreatment.Builder updateBuilder(TrafficTreatment.Builder treatmentBuilder,
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 83547e2..735ea7f 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
@@ -34,6 +34,8 @@
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentCompiler;
import org.onosproject.net.intent.LinkCollectionIntent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
@@ -48,6 +50,9 @@
extends LinkCollectionCompiler<FlowRule>
implements IntentCompiler<LinkCollectionIntent> {
+ private static Logger log = LoggerFactory.getLogger(LinkCollectionIntentCompiler.class);
+
+
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentConfigurableRegistrator registrator;
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java
index 0da2194..76640f2 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/SinglePointToMultiPointIntentCompiler.java
@@ -77,6 +77,7 @@
.priority(intent.priority())
.applyTreatmentOnEgress(true)
.constraints(intent.constraints())
+ .egressTreatments(intent.egressTreatments())
.build();
return Collections.singletonList(result);
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentCompilerTest.java
index 8e89d14..43524da 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentCompilerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentCompilerTest.java
@@ -64,13 +64,18 @@
private final ApplicationId appId = new TestApplicationId("test");
- private final ConnectPoint d1p1 = connectPoint("s1", 0);
+ private final ConnectPoint d1p1 = connectPoint("s1", 1);
private final ConnectPoint d2p0 = connectPoint("s2", 0);
private final ConnectPoint d2p1 = connectPoint("s2", 1);
+ private final ConnectPoint d2p2 = connectPoint("s2", 2);
+ private final ConnectPoint d2p3 = connectPoint("s2", 3);
private final ConnectPoint d3p1 = connectPoint("s3", 1);
private final ConnectPoint d3p2 = connectPoint("s3", 9);
private final ConnectPoint d3p0 = connectPoint("s3", 10);
private final ConnectPoint d1p0 = connectPoint("s1", 10);
+ private final ConnectPoint d4p1 = connectPoint("s4", 1);
+ private final ConnectPoint d4p0 = connectPoint("s4", 10);
+
private final Set<Link> links = ImmutableSet.of(
DefaultLink.builder().providerId(PID).src(d1p1).dst(d2p0).type(DIRECT).build(),
@@ -80,6 +85,11 @@
private final Set<Link> linksMultiple = ImmutableSet.of(
DefaultLink.builder().providerId(PID).src(d3p1).dst(d2p0).type(DIRECT).build());
+ private final Set<Link> linksMultiple2 = ImmutableSet.of(
+ DefaultLink.builder().providerId(PID).src(d2p0).dst(d1p1).type(DIRECT).build(),
+ DefaultLink.builder().providerId(PID).src(d2p1).dst(d3p1).type(DIRECT).build(),
+ DefaultLink.builder().providerId(PID).src(d2p2).dst(d4p1).type(DIRECT).build());
+
private final TrafficSelector selector = DefaultTrafficSelector.builder().build();
private final TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
@@ -101,14 +111,40 @@
.setVlanId(egressVlan)
.build();
+private final VlanId ingressVlan = VlanId.vlanId("10");
+ private final TrafficSelector vlanSelector = DefaultTrafficSelector
+ .builder()
+ .matchVlanId(ingressVlan)
+ .build();
+
+ private final VlanId egressVlan1 = VlanId.vlanId("20");
+ private final TrafficTreatment vlanTreatment1 = DefaultTrafficTreatment
+ .builder()
+ .setVlanId(egressVlan1)
+ .build();
+
+ private final VlanId egressVlan2 = VlanId.vlanId("666");
+ private final TrafficTreatment vlanTreatment2 = DefaultTrafficTreatment
+ .builder()
+ .setVlanId(egressVlan2)
+ .build();
+
+ private final VlanId egressVlan3 = VlanId.vlanId("69");
+ private final TrafficTreatment vlanTreatment3 = DefaultTrafficTreatment
+ .builder()
+ .setVlanId(egressVlan3)
+ .build();
+
+
private CoreService coreService;
private IntentExtensionService intentExtensionService;
private IntentConfigurableRegistrator registrator;
private IdGenerator idGenerator = new MockIdGenerator();
private LinkCollectionIntent intent;
- private LinkCollectionIntent intentMultiple;
-
+ private LinkCollectionIntent intentMultipleSelectors;
+ private LinkCollectionIntent intentMultipleTreatments;
+ private LinkCollectionIntent intentMultipleTreatments2;
private LinkCollectionIntentCompiler sut;
@@ -130,7 +166,7 @@
.ingressPoints(ImmutableSet.of(d1p1))
.egressPoints(ImmutableSet.of(d3p1))
.build();
- intentMultiple = LinkCollectionIntent.builder()
+ intentMultipleSelectors = LinkCollectionIntent.builder()
.appId(APP_ID)
.treatment(vlanTreatment)
.links(linksMultiple)
@@ -138,6 +174,24 @@
.egressPoints(ImmutableSet.of(d2p1))
.ingressSelectors(this.createIngressSelectors())
.build();
+ intentMultipleTreatments = LinkCollectionIntent.builder()
+ .appId(APP_ID)
+ .selector(vlanSelector)
+ .links(linksMultiple)
+ .ingressPoints(ImmutableSet.of(d3p0))
+ .egressPoints(ImmutableSet.of(d2p1, d2p2))
+ .egressTreatments(this.createEgressTreatments())
+ .applyTreatmentOnEgress(true)
+ .build();
+ intentMultipleTreatments2 = LinkCollectionIntent.builder()
+ .appId(APP_ID)
+ .selector(vlanSelector)
+ .links(linksMultiple2)
+ .ingressPoints(ImmutableSet.of(d2p3))
+ .egressPoints(ImmutableSet.of(d1p0, d3p0, d4p0))
+ .egressTreatments(this.createEgressTreatments2())
+ .applyTreatmentOnEgress(true)
+ .build();
intentExtensionService = createMock(IntentExtensionService.class);
intentExtensionService.registerCompiler(LinkCollectionIntent.class, sut);
@@ -208,22 +262,22 @@
sut.deactivate();
}
- @Test
+@Test
public void testCompileMultipleSelectors() {
sut.activate();
- List<Intent> compiled = sut.compile(intentMultiple, Collections.emptyList());
+ List<Intent> compiled = sut.compile(intentMultipleSelectors, Collections.emptyList());
assertThat(compiled, hasSize(1));
Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
- assertThat(rules, hasSize((linksMultiple.size()) + intentMultiple.ingressPoints().size()));
+ assertThat(rules, hasSize((linksMultiple.size()) + intentMultipleSelectors.ingressPoints().size()));
Set<FlowRule> d3Rules = rules
.parallelStream()
.filter(rule -> rule.deviceId().equals(d3p0.deviceId()))
.collect(Collectors.toSet());
- assertThat(d3Rules, hasSize(intentMultiple.ingressPoints().size()));
+ assertThat(d3Rules, hasSize(intentMultipleSelectors.ingressPoints().size()));
FlowRule rule1 = rules.stream()
.filter(rule -> rule.deviceId().equals(d3p0.deviceId())
@@ -233,18 +287,18 @@
.get();
assertThat(rule1.selector(), is(
DefaultTrafficSelector
- .builder(intentMultiple.selector())
+ .builder(intentMultipleSelectors.selector())
.matchInPort(d3p0.port())
.matchVlanId(ingressVlan1)
.build()
));
assertThat(rule1.treatment(), is(
DefaultTrafficTreatment
- .builder(intentMultiple.treatment())
+ .builder(intentMultipleSelectors.treatment())
.setOutput(d3p1.port())
.build()
));
- assertThat(rule1.priority(), is(intentMultiple.priority()));
+ assertThat(rule1.priority(), is(intentMultipleSelectors.priority()));
FlowRule rule2 = rules.stream()
.filter(rule -> rule.deviceId().equals(d3p0.deviceId())
@@ -254,24 +308,24 @@
.get();
assertThat(rule2.selector(), is(
DefaultTrafficSelector
- .builder(intentMultiple.selector())
+ .builder(intentMultipleSelectors.selector())
.matchInPort(d3p2.port())
.matchVlanId(ingressVlan2)
.build()
));
assertThat(rule2.treatment(), is(
DefaultTrafficTreatment
- .builder(intentMultiple.treatment())
+ .builder(intentMultipleSelectors.treatment())
.setOutput(d3p1.port())
.build()
));
- assertThat(rule1.priority(), is(intentMultiple.priority()));
+ assertThat(rule2.priority(), is(intentMultipleSelectors.priority()));
Set<FlowRule> d2Rules = rules
.parallelStream()
.filter(rule -> rule.deviceId().equals(d2p0.deviceId()))
.collect(Collectors.toSet());
- assertThat(d2Rules, hasSize(intentMultiple.egressPoints().size()));
+ assertThat(d2Rules, hasSize(intentMultipleSelectors.egressPoints().size()));
// We do not need in_port filter
FlowRule rule3 = rules.stream()
@@ -280,7 +334,7 @@
.get();
assertThat(rule3.selector(), is(
DefaultTrafficSelector
- .builder(intentMultiple.selector())
+ .builder(intentMultipleSelectors.selector())
.matchInPort(d2p0.port())
.matchVlanId(egressVlan)
.build()
@@ -291,15 +345,216 @@
.setOutput(d2p1.port())
.build()
));
- assertThat(rule3.priority(), is(intentMultiple.priority()));
+ assertThat(rule3.priority(), is(intentMultipleSelectors.priority()));
sut.deactivate();
}
+ @Test
+ public void testCompileMultipleTreatments() {
+ sut.activate();
+
+ List<Intent> compiled = sut.compile(intentMultipleTreatments, Collections.emptyList());
+ assertThat(compiled, hasSize(1));
+
+ Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
+ assertThat(rules, hasSize((linksMultiple.size() + intentMultipleTreatments.egressPoints().size())));
+
+ Set<FlowRule> d3Rules = rules
+ .parallelStream()
+ .filter(rule -> rule.deviceId().equals(d3p0.deviceId()))
+ .collect(Collectors.toSet());
+ assertThat(d3Rules, hasSize(intentMultipleTreatments.ingressPoints().size()));
+
+ FlowRule rule1 = rules.stream()
+ .filter(rule -> rule.deviceId().equals(d3p0.deviceId()))
+ .findFirst()
+ .get();
+ assertThat(rule1.selector(), is(
+ DefaultTrafficSelector
+ .builder(intentMultipleTreatments.selector())
+ .matchInPort(d3p0.port())
+ .matchVlanId(ingressVlan)
+ .build()
+ ));
+ assertThat(rule1.treatment(), is(
+ DefaultTrafficTreatment
+ .builder(intentMultipleTreatments.treatment())
+ .setOutput(d3p1.port())
+ .build()
+ ));
+ assertThat(rule1.priority(), is(intentMultipleTreatments.priority()));
+
+ Set<FlowRule> d2Rules = rules
+ .parallelStream()
+ .filter(rule -> rule.deviceId().equals(d2p0.deviceId()))
+ .collect(Collectors.toSet());
+ assertThat(d2Rules, hasSize(1));
+
+ FlowRule rule2 = rules.stream()
+ .filter(rule -> rule.deviceId().equals(d2p0.deviceId()))
+ .findFirst()
+ .get();
+ assertThat(rule2.selector(), is(
+ DefaultTrafficSelector
+ .builder(intentMultipleTreatments.selector())
+ .matchInPort(d2p0.port())
+ .matchVlanId(ingressVlan)
+ .build()
+ ));
+ assertThat(rule2.treatment(), is(
+ DefaultTrafficTreatment
+ .builder(intentMultipleTreatments.treatment())
+ .setVlanId(egressVlan1)
+ .setOutput(d2p1.port())
+ .setVlanId(egressVlan2)
+ .setOutput(d2p2.port())
+ .build()
+ ));
+ assertThat(rule2.priority(), is(intentMultipleTreatments.priority()));
+
+ }
+
+ @Test
+ public void testCompileMultipleTreatments2() {
+ sut.activate();
+
+ List<Intent> compiled = sut.compile(intentMultipleTreatments2, Collections.emptyList());
+ assertThat(compiled, hasSize(1));
+
+
+ Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
+ assertThat(rules, hasSize((linksMultiple2.size() + intentMultipleTreatments2.egressPoints().size())));
+
+
+ Set<FlowRule> d2Rules = rules
+ .parallelStream()
+ .filter(rule -> rule.deviceId().equals(d2p0.deviceId()))
+ .collect(Collectors.toSet());
+ assertThat(d2Rules, hasSize(1));
+
+
+ FlowRule rule1 = rules.stream()
+ .filter(rule -> rule.deviceId().equals(d2p0.deviceId()))
+ .findFirst()
+ .get();
+ assertThat(rule1.selector(), is(
+ DefaultTrafficSelector
+ .builder(intentMultipleTreatments.selector())
+ .matchInPort(d2p3.port())
+ .matchVlanId(ingressVlan)
+ .build()
+ ));
+ assertThat(rule1.treatment(), is(
+ DefaultTrafficTreatment
+ .builder(intentMultipleTreatments.treatment())
+ .setOutput(d2p0.port())
+ .setOutput(d2p1.port())
+ .setOutput(d2p2.port())
+ .build()
+ ));
+ assertThat(rule1.priority(), is(intentMultipleTreatments.priority()));
+
+ Set<FlowRule> d1Rules = rules
+ .parallelStream()
+ .filter(rule -> rule.deviceId().equals(d1p0.deviceId()))
+ .collect(Collectors.toSet());
+ assertThat(d1Rules, hasSize(1));
+
+ FlowRule rule2 = rules.stream()
+ .filter(rule -> rule.deviceId().equals(d1p0.deviceId()))
+ .findFirst()
+ .get();
+ assertThat(rule2.selector(), is(
+ DefaultTrafficSelector
+ .builder(intentMultipleTreatments2.selector())
+ .matchInPort(d1p1.port())
+ .matchVlanId(ingressVlan)
+ .build()
+ ));
+ assertThat(rule2.treatment(), is(
+ DefaultTrafficTreatment
+ .builder(intentMultipleTreatments2.treatment())
+ .setVlanId(egressVlan1)
+ .setOutput(d1p0.port())
+ .build()
+ ));
+ assertThat(rule2.priority(), is(intentMultipleTreatments.priority()));
+
+ Set<FlowRule> d3Rules = rules
+ .parallelStream()
+ .filter(rule -> rule.deviceId().equals(d3p0.deviceId()))
+ .collect(Collectors.toSet());
+ assertThat(d3Rules, hasSize(1));
+
+ FlowRule rule3 = rules.stream()
+ .filter(rule -> rule.deviceId().equals(d3p0.deviceId()))
+ .findFirst()
+ .get();
+ assertThat(rule3.selector(), is(
+ DefaultTrafficSelector
+ .builder(intentMultipleTreatments2.selector())
+ .matchInPort(d3p1.port())
+ .matchVlanId(ingressVlan)
+ .build()
+ ));
+ assertThat(rule3.treatment(), is(
+ DefaultTrafficTreatment
+ .builder(intentMultipleTreatments2.treatment())
+ .setVlanId(egressVlan2)
+ .setOutput(d3p0.port())
+ .build()
+ ));
+ assertThat(rule3.priority(), is(intentMultipleTreatments.priority()));
+
+ Set<FlowRule> d4Rules = rules
+ .parallelStream()
+ .filter(rule -> rule.deviceId().equals(d4p0.deviceId()))
+ .collect(Collectors.toSet());
+ assertThat(d4Rules, hasSize(1));
+
+ FlowRule rule4 = rules.stream()
+ .filter(rule -> rule.deviceId().equals(d4p0.deviceId()))
+ .findFirst()
+ .get();
+ assertThat(rule4.selector(), is(
+ DefaultTrafficSelector
+ .builder(intentMultipleTreatments2.selector())
+ .matchInPort(d4p1.port())
+ .matchVlanId(ingressVlan)
+ .build()
+ ));
+ assertThat(rule4.treatment(), is(
+ DefaultTrafficTreatment
+ .builder(intentMultipleTreatments2.treatment())
+ .setVlanId(egressVlan3)
+ .setOutput(d4p0.port())
+ .build()
+ ));
+ assertThat(rule4.priority(), is(intentMultipleTreatments.priority()));
+
+ }
+
+ public Map<ConnectPoint, TrafficTreatment> createEgressTreatments() {
+ Map<ConnectPoint, TrafficTreatment> mapToReturn = Maps.newHashMap();
+ mapToReturn.put(d2p1, vlanTreatment1);
+ mapToReturn.put(d2p2, vlanTreatment2);
+ return mapToReturn;
+ }
+
+ public Map<ConnectPoint, TrafficTreatment> createEgressTreatments2() {
+ Map<ConnectPoint, TrafficTreatment> mapToReturn = Maps.newHashMap();
+ mapToReturn.put(d1p0, vlanTreatment1);
+ mapToReturn.put(d3p0, vlanTreatment2);
+ mapToReturn.put(d4p0, vlanTreatment3);
+ return mapToReturn;
+ }
+
public Map<ConnectPoint, TrafficSelector> createIngressSelectors() {
Map<ConnectPoint, TrafficSelector> mapToReturn = Maps.newHashMap();
mapToReturn.put(d3p0, selectorVlan1);
mapToReturn.put(d3p2, selectorVlan2);
return mapToReturn;
}
+
}