[ONOS-5932] New FlowObjective compiler for LinkCollection Intent
Change-Id: I50ca991bf0997a24dd18cf68c060c2c0912f294c
diff --git a/core/api/src/test/java/org/onosproject/net/NetTestTools.java b/core/api/src/test/java/org/onosproject/net/NetTestTools.java
index dd03a09..86ee0f7 100644
--- a/core/api/src/test/java/org/onosproject/net/NetTestTools.java
+++ b/core/api/src/test/java/org/onosproject/net/NetTestTools.java
@@ -234,6 +234,12 @@
.build();
}
+ public static TrafficSelector ethDstSelector(String macAddress) {
+ return DefaultTrafficSelector.builder()
+ .matchEthDst(MacAddress.valueOf(macAddress))
+ .build();
+ }
+
/**
* Builds an empty treatment.
*
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/IntentConfigurableRegistrator.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/IntentConfigurableRegistrator.java
index 40f7f77..e14115c 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/IntentConfigurableRegistrator.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/IntentConfigurableRegistrator.java
@@ -17,6 +17,7 @@
package org.onosproject.net.intent.impl.compiler;
import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -35,6 +36,7 @@
import org.slf4j.Logger;
import java.util.Map;
+import java.util.Set;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.slf4j.LoggerFactory.getLogger;
@@ -79,8 +81,22 @@
label = "Indicates whether or not to use copy ttl in the link collection compiler")
private boolean useCopyTtl = DEFAULT_COPY_TTL;
+ /**
+ * Temporary for switching old compiler and new compiler.
+ * @deprecated 1.10 Kingfisher
+ */
+ private static final String DEFAULT_FLOW_OBJECTIVE_COMPILER =
+ "org.onosproject.net.intent.impl.compiler.LinkCollectionIntentFlowObjectiveCompiler";
+ @Deprecated
+ @Property(name = "defaultFlowObjectiveCompiler",
+ value = DEFAULT_FLOW_OBJECTIVE_COMPILER,
+ label = "Default compiler to generate flow objective")
+ private String defaultFlowObjectiveCompiler = DEFAULT_FLOW_OBJECTIVE_COMPILER;
+
private final Map<Class<Intent>, IntentCompiler<Intent>> flowRuleBased = Maps.newConcurrentMap();
- private final Map<Class<Intent>, IntentCompiler<Intent>> flowObjectiveBased = Maps.newConcurrentMap();
+
+ // FIXME: temporary code for switching old compiler to new compiler
+ private final Map<Class<Intent>, Set<IntentCompiler<Intent>>> flowObjectiveBased = Maps.newConcurrentMap();
@Activate
public void activate() {
@@ -101,6 +117,9 @@
log.info("Settings: labelSelection={}", labelSelection);
log.info("Settings: useFlowOptimization={}", useFlowOptimization);
log.info("Settings: useCopyTtl={}", useCopyTtl);
+
+ // FIXME: temporary code for switching old compiler to new compiler
+ log.info("Settings: defaultFlowObjectiveCompiler={}", defaultFlowObjectiveCompiler);
return;
}
@@ -118,6 +137,21 @@
log.info("Settings: useFlowObjectives={}", useFlowObjectives);
}
+ // FIXME: temporary code for switching old compiler to new compiler
+ String newDefaultFlowObjectiveCompiler;
+ try {
+ String s = Tools.get(context.getProperties(), "defaultFlowObjectiveCompiler");
+ newDefaultFlowObjectiveCompiler = isNullOrEmpty(s) ? defaultFlowObjectiveCompiler : s.trim();
+ } catch (ClassCastException e) {
+ newDefaultFlowObjectiveCompiler = defaultFlowObjectiveCompiler;
+ }
+
+ if (!defaultFlowObjectiveCompiler.equals(newDefaultFlowObjectiveCompiler)) {
+ defaultFlowObjectiveCompiler = newDefaultFlowObjectiveCompiler;
+ changeCompilers();
+ log.info("Settings: defaultFlowObjectiveCompiler={}", defaultFlowObjectiveCompiler);
+ }
+
String newLabelSelection;
try {
String s = Tools.get(context.getProperties(), "labelSelection");
@@ -173,7 +207,15 @@
<T extends Intent> void registerCompiler(Class<T> cls, IntentCompiler<T> compiler,
boolean flowBased) {
if (flowBased) {
- flowObjectiveBased.put((Class<Intent>) cls, (IntentCompiler<Intent>) compiler);
+ // FIXME: temporary code for switching old compiler to new compiler
+ flowObjectiveBased.compute((Class<Intent>) cls, (clz, compilers) -> {
+ if (compilers == null) {
+ compilers = Sets.newHashSet();
+ }
+
+ compilers.add((IntentCompiler<Intent>) compiler);
+ return compilers;
+ });
} else {
flowRuleBased.put((Class<Intent>) cls, (IntentCompiler<Intent>) compiler);
}
@@ -204,7 +246,15 @@
private void changeCompilers() {
if (useFlowObjectives) {
flowRuleBased.forEach((cls, compiler) -> extensionService.unregisterCompiler(cls));
- flowObjectiveBased.forEach((cls, compiler) -> extensionService.registerCompiler(cls, compiler));
+ // FIXME: temporary code for switching old compiler to new compiler
+ flowObjectiveBased.forEach((cls, compilers) -> {
+ compilers.forEach(compiler -> {
+ // filter out flow objective compiler which doesn't match
+ if (compiler.getClass().getName().equals(defaultFlowObjectiveCompiler)) {
+ extensionService.registerCompiler(cls, compiler);
+ }
+ });
+ });
} else {
flowObjectiveBased.forEach((cls, compiler) -> extensionService.unregisterCompiler(cls));
flowRuleBased.forEach((cls, compiler) -> extensionService.registerCompiler(cls, compiler));
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentFlowObjectiveCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentFlowObjectiveCompiler.java
index 0aa4e87..9396ab5 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentFlowObjectiveCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentFlowObjectiveCompiler.java
@@ -52,7 +52,9 @@
/**
* Compiler to produce flow objectives from link collections.
+ * @deprecated 1.10 Kingfisher
*/
+@Deprecated
@Component(immediate = true)
public class LinkCollectionIntentFlowObjectiveCompiler
extends LinkCollectionCompiler<Objective>
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentObjectiveCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentObjectiveCompiler.java
new file mode 100644
index 0000000..2af0be5
--- /dev/null
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentObjectiveCompiler.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.impl.compiler;
+
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.SetMultimap;
+import com.google.common.collect.Sets;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.util.Identifier;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.EthCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flowobjective.DefaultFilteringObjective;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.DefaultNextObjective;
+import org.onosproject.net.flowobjective.FilteringObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.NextObjective;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.intent.FlowObjectiveIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentCompiler;
+import org.onosproject.net.intent.LinkCollectionIntent;
+import org.onosproject.net.intent.constraint.EncapsulationConstraint;
+import org.onosproject.net.resource.ResourceService;
+import org.onosproject.net.resource.impl.LabelAllocator;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+
+import static org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT;
+
+/**
+ * Compiler to produce flow objectives from link collections.
+ */
+@Component(immediate = true)
+public class LinkCollectionIntentObjectiveCompiler
+ extends LinkCollectionCompiler<Objective>
+ implements IntentCompiler<LinkCollectionIntent> {
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected IntentConfigurableRegistrator registrator;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowObjectiveService flowObjectiveService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ResourceService resourceService;
+
+ private ApplicationId appId;
+
+ @Activate
+ public void activate() {
+ appId = coreService.registerApplication("org.onosproject.net.intent");
+ registrator.registerCompiler(LinkCollectionIntent.class, this, true);
+ if (labelAllocator == null) {
+ labelAllocator = new LabelAllocator(resourceService);
+ }
+ }
+
+
+ @Deactivate
+ public void deactivate() {
+ registrator.unregisterCompiler(LinkCollectionIntent.class, true);
+ }
+
+ @Override
+ public List<Intent> compile(LinkCollectionIntent intent, List<Intent> installable) {
+
+ SetMultimap<DeviceId, PortNumber> inputPorts = HashMultimap.create();
+ SetMultimap<DeviceId, PortNumber> outputPorts = HashMultimap.create();
+ Map<ConnectPoint, Identifier<?>> labels = ImmutableMap.of();
+
+ Optional<EncapsulationConstraint> encapConstraint = this.getIntentEncapConstraint(intent);
+
+ computePorts(intent, inputPorts, outputPorts);
+
+ if (encapConstraint.isPresent()) {
+ labels = labelAllocator.assignLabelToPorts(intent.links(),
+ intent.id(),
+ encapConstraint.get().encapType());
+ }
+
+ List<Objective> objectives = new ArrayList<>();
+ List<DeviceId> devices = new ArrayList<>();
+ for (DeviceId deviceId: outputPorts.keySet()) {
+ List<Objective> deviceObjectives =
+ createRules(intent,
+ deviceId,
+ inputPorts.get(deviceId),
+ outputPorts.get(deviceId),
+ labels);
+ deviceObjectives.forEach(objective -> {
+ objectives.add(objective);
+ devices.add(deviceId);
+ });
+ }
+ return Collections.singletonList(
+ new FlowObjectiveIntent(appId, intent.key(), devices,
+ objectives,
+ intent.resources(),
+ intent.resourceGroup()));
+ }
+
+ @Override
+ protected List<Objective> createRules(LinkCollectionIntent intent,
+ DeviceId deviceId,
+ Set<PortNumber> inPorts,
+ Set<PortNumber> outPorts,
+ Map<ConnectPoint, Identifier<?>> labels) {
+
+ List<Objective> objectives = new ArrayList<>(inPorts.size() * 2);
+
+ /*
+ * Looking for the encapsulation constraint
+ */
+ Optional<EncapsulationConstraint> encapConstraint = this.getIntentEncapConstraint(intent);
+
+ inPorts.forEach(inport -> {
+
+ ForwardingInstructions instructions = this.createForwardingInstruction(
+ encapConstraint,
+ intent,
+ inport,
+ outPorts,
+ deviceId,
+ labels
+ );
+
+ Set<TrafficTreatment> treatmentsWithDifferentPort =
+ Sets.newHashSet();
+
+ TrafficTreatment.Builder treatmentBuilder =
+ DefaultTrafficTreatment.builder();
+
+ for (Instruction inst : instructions.treatment().allInstructions()) {
+ if (inst.type() == OUTPUT) {
+ treatmentBuilder.add(inst);
+ treatmentsWithDifferentPort.add(treatmentBuilder.build());
+ treatmentBuilder = DefaultTrafficTreatment.builder();
+ } else {
+ treatmentBuilder.add(inst);
+ }
+ }
+
+ EthCriterion ethDst = (EthCriterion) instructions.selector()
+ .getCriterion(Criterion.Type.ETH_DST);
+ boolean broadcastObjective = ethDst != null &&
+ (ethDst.mac().isBroadcast() || ethDst.mac().isMulticast());
+
+ if (treatmentsWithDifferentPort.size() < 2 && !broadcastObjective) {
+ objectives.addAll(createSimpleNextObjective(instructions, intent));
+ } else {
+ objectives.addAll(createBroadcastObjective(instructions,
+ treatmentsWithDifferentPort,
+ intent));
+ }
+ });
+
+ return objectives;
+ }
+
+ private List<Objective> createBroadcastObjective(ForwardingInstructions instructions,
+ Set<TrafficTreatment> treatmentsWithDifferentPort,
+ LinkCollectionIntent intent) {
+ List<Objective> objectives = Lists.newArrayList();
+ FilteringObjective filteringObjective;
+ ForwardingObjective forwardingObjective;
+ NextObjective nextObjective;
+
+ Integer nextId = flowObjectiveService.allocateNextId();
+
+ forwardingObjective = buildForwardingObjective(instructions.selector(),
+ nextId, intent.priority());
+
+ DefaultNextObjective.Builder nxBuilder = DefaultNextObjective.builder();
+ nxBuilder.withId(nextId)
+ .withMeta(instructions.selector())
+ .withType(NextObjective.Type.BROADCAST)
+ .fromApp(appId)
+ .withPriority(intent.priority())
+ .makePermanent();
+
+ treatmentsWithDifferentPort.forEach(nxBuilder::addTreatment);
+ nextObjective = nxBuilder.add();
+
+ filteringObjective = buildFilteringObjective(instructions.selector(), intent.priority());
+
+ objectives.add(filteringObjective);
+ objectives.add(forwardingObjective);
+ objectives.add(nextObjective);
+
+ return objectives;
+ }
+
+ private List<Objective> createSimpleNextObjective(ForwardingInstructions instructions,
+ LinkCollectionIntent intent) {
+ List<Objective> objectives = Lists.newArrayList();
+ FilteringObjective filteringObjective;
+ ForwardingObjective forwardingObjective;
+ NextObjective nextObjective;
+
+ Integer nextId = flowObjectiveService.allocateNextId();
+
+ forwardingObjective = buildForwardingObjective(instructions.selector(),
+ nextId, intent.priority());
+
+ DefaultNextObjective.Builder nxBuilder = DefaultNextObjective.builder();
+ nextObjective = nxBuilder.withId(nextId)
+ .withMeta(instructions.selector())
+ .addTreatment(instructions.treatment())
+ .withType(NextObjective.Type.SIMPLE)
+ .fromApp(appId)
+ .makePermanent()
+ .withPriority(intent.priority())
+ .add();
+
+ filteringObjective = buildFilteringObjective(instructions.selector(), intent.priority());
+
+ objectives.add(filteringObjective);
+ objectives.add(forwardingObjective);
+ objectives.add(nextObjective);
+
+ return objectives;
+ }
+
+ private ForwardingObjective buildForwardingObjective(TrafficSelector selector, Integer nextId, int priority) {
+ return DefaultForwardingObjective.builder()
+ .withMeta(selector)
+ .withSelector(selector)
+ .nextStep(nextId)
+ .fromApp(appId)
+ .withPriority(priority)
+ .withFlag(ForwardingObjective.Flag.SPECIFIC)
+ .makePermanent()
+ .add();
+ }
+
+ private FilteringObjective buildFilteringObjective(TrafficSelector selector, int priority) {
+ FilteringObjective.Builder builder = DefaultFilteringObjective.builder();
+ builder.fromApp(appId)
+ .permit()
+ .makePermanent()
+ .withPriority(priority);
+
+ Criterion inPortCriterion =
+ selector.getCriterion(Criterion.Type.IN_PORT);
+
+ if (inPortCriterion != null) {
+ builder.withKey(inPortCriterion);
+ }
+
+ selector.criteria().forEach(builder::addCondition);
+ return builder.add();
+ }
+
+}
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/AbstractLinkCollectionTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/AbstractLinkCollectionTest.java
index bd2c7c7..f6e5dc8 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/AbstractLinkCollectionTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/AbstractLinkCollectionTest.java
@@ -24,6 +24,7 @@
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
+import org.onosproject.net.ResourceGroup;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
@@ -66,6 +67,7 @@
final ConnectPoint of1p1 = connectPoint("of1", 1);
final ConnectPoint of1p2 = connectPoint("of1", 2);
+ final ConnectPoint of1p3 = connectPoint("of1", 3);
final ConnectPoint of2p1 = connectPoint("of2", 1);
final ConnectPoint of2p2 = connectPoint("of2", 2);
final ConnectPoint of2p3 = connectPoint("of2", 3);
@@ -124,6 +126,9 @@
final TrafficSelector mpls100Selector = mplsSelector("100");
final TrafficSelector mpls200Selector = mplsSelector("200");
final TrafficSelector ipPrefixSelector = ipPrefixDstSelector("192.168.100.0/24");
+ final TrafficSelector ethDstSelector = ethDstSelector("C0:FF:EE:C0:FF:EE");
+ final ResourceGroup resourceGroup1 = ResourceGroup.of(1L);
+ final ResourceGroup resourceGroup2 = ResourceGroup.of(1L);
final List<Constraint> constraintsForVlan = vlanConstraint();
final List<Constraint> constraintsForMPLS = mplsConstraint();
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentObjectiveCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentObjectiveCompilerTest.java
new file mode 100644
index 0000000..22ecf48
--- /dev/null
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentObjectiveCompilerTest.java
@@ -0,0 +1,862 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.net.intent.impl.compiler;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.cfg.ComponentConfigAdapter;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.FilteredConnectPoint;
+import org.onosproject.net.Link;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flowobjective.FilteringObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveServiceAdapter;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.NextObjective;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.intent.FlowObjectiveIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentExtensionService;
+import org.onosproject.net.intent.LinkCollectionIntent;
+import org.onosproject.net.resource.MockResourceService;
+import org.onosproject.net.resource.ResourceService;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import static org.easymock.EasyMock.*;
+import static org.hamcrest.CoreMatchers.hasItem;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
+import static org.onosproject.net.Link.Type.DIRECT;
+import static org.onosproject.net.NetTestTools.PID;
+
+public class LinkCollectionIntentObjectiveCompilerTest extends AbstractLinkCollectionTest {
+
+ private LinkCollectionIntentObjectiveCompiler compiler;
+ private FlowObjectiveServiceAdapter flowObjectiveService;
+
+ private NextObjective nextObjective;
+ private ForwardingObjective forwardingObjective;
+ private FilteringObjective filteringObjective;
+
+ private ResourceService resourceService;
+
+ @Before
+ public void setUp() {
+ compiler = new LinkCollectionIntentObjectiveCompiler();
+ coreService = createMock(CoreService.class);
+ expect(coreService.registerApplication("org.onosproject.net.intent"))
+ .andReturn(appId);
+ flowObjectiveService = new FlowObjectiveServiceAdapter();
+ resourceService = new MockResourceService();
+ compiler.coreService = coreService;
+ compiler.flowObjectiveService = flowObjectiveService;
+
+ Intent.bindIdGenerator(idGenerator);
+
+ intentExtensionService = createMock(IntentExtensionService.class);
+ intentExtensionService.registerCompiler(LinkCollectionIntent.class, compiler);
+ intentExtensionService.unregisterCompiler(LinkCollectionIntent.class);
+
+ registrator = new IntentConfigurableRegistrator();
+ registrator.extensionService = intentExtensionService;
+ registrator.cfgService = new ComponentConfigAdapter();
+ registrator.activate();
+
+ compiler.registrator = registrator;
+ compiler.resourceService = resourceService;
+
+ LinkCollectionCompiler.optimize = false;
+ LinkCollectionCompiler.copyTtl = false;
+
+ replay(coreService, intentExtensionService);
+
+ }
+
+ @After
+ public void tearDown() {
+ Intent.unbindIdGenerator(idGenerator);
+ }
+
+ /**
+ * We test the proper compilation of a simple link collection intent
+ * with connect points, empty trivial treatment and empty trivial selector.
+ */
+ @Test
+ public void testCompile() {
+ compiler.activate();
+
+ LinkCollectionIntent intent = LinkCollectionIntent.builder()
+ .appId(appId)
+ .selector(selector)
+ .treatment(treatment)
+ .links(links)
+ .filteredIngressPoints(ImmutableSet.of(new FilteredConnectPoint(d1p1)))
+ .filteredEgressPoints(ImmutableSet.of(new FilteredConnectPoint(d3p1)))
+ .build();
+
+ List<Intent> result = compiler.compile(intent, Collections.emptyList());
+ assertThat(result, hasSize(1));
+ assertThat(result.get(0), instanceOf(FlowObjectiveIntent.class));
+
+ FlowObjectiveIntent foIntent = (FlowObjectiveIntent) result.get(0);
+ List<Objective> objectives = foIntent.objectives();
+ assertThat(objectives, hasSize(9));
+
+ /*
+ * First set of objective
+ */
+ filteringObjective = (FilteringObjective) objectives.get(0);
+ forwardingObjective = (ForwardingObjective) objectives.get(1);
+ nextObjective = (NextObjective) objectives.get(2);
+
+ // expect selector and treatment
+ TrafficSelector expectSelector = DefaultTrafficSelector.builder()
+ .matchInPort(PortNumber.portNumber(1))
+ .build();
+ TrafficTreatment expectTreatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(1))
+ .build();
+ PortCriterion inPortCriterion =
+ (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+ // test case for first filtering objective
+ assertThat(filteringObjective.key(), is(inPortCriterion));
+ assertThat(filteringObjective.priority(), is(intent.priority()));
+ assertThat(filteringObjective.meta(), nullValue());
+ assertThat(filteringObjective.appId(), is(appId));
+ assertThat(filteringObjective.permanent(), is(true));
+ assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+
+ // test case for first next objective
+ assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
+ assertThat(nextObjective.next(), hasSize(1));
+ assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
+ assertThat(nextObjective.meta(), is(expectSelector));
+ assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+
+ // test case for first forwarding objective
+ assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
+ assertThat(forwardingObjective.selector(), is(expectSelector));
+ assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
+ assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+
+ /*
+ * Second set of objective
+ */
+ filteringObjective = (FilteringObjective) objectives.get(3);
+ forwardingObjective = (ForwardingObjective) objectives.get(4);
+ nextObjective = (NextObjective) objectives.get(5);
+
+
+ expectSelector = DefaultTrafficSelector.builder()
+ .matchInPort(PortNumber.portNumber(0))
+ .build();
+
+ inPortCriterion =
+ (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+ // test case for first filtering objective
+ assertThat(filteringObjective.key(), is(inPortCriterion));
+ assertThat(filteringObjective.priority(), is(intent.priority()));
+ assertThat(filteringObjective.meta(), nullValue());
+ assertThat(filteringObjective.appId(), is(appId));
+ assertThat(filteringObjective.permanent(), is(true));
+ assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+
+ // test case for second next objective
+ assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
+ assertThat(nextObjective.next(), hasSize(1));
+ assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
+ assertThat(nextObjective.meta(), is(expectSelector));
+ assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+
+ // test case for second forwarding objective
+ assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
+ assertThat(forwardingObjective.selector(), is(expectSelector));
+ assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
+ assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+
+ /*
+ * 3rd set of objective
+ */
+ filteringObjective = (FilteringObjective) objectives.get(6);
+ forwardingObjective = (ForwardingObjective) objectives.get(7);
+ nextObjective = (NextObjective) objectives.get(8);
+
+ expectSelector = DefaultTrafficSelector.builder()
+ .matchInPort(PortNumber.portNumber(1))
+ .build();
+
+ inPortCriterion =
+ (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+ // test case for first filtering objective
+ assertThat(filteringObjective.key(), is(inPortCriterion));
+ assertThat(filteringObjective.priority(), is(intent.priority()));
+ assertThat(filteringObjective.meta(), nullValue());
+ assertThat(filteringObjective.appId(), is(appId));
+ assertThat(filteringObjective.permanent(), is(true));
+ assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+
+ // test case for 3rd next objective
+ assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
+ assertThat(nextObjective.next(), hasSize(1));
+ assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
+ assertThat(nextObjective.meta(), is(expectSelector));
+ assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+
+ // test case for 3rd forwarding objective
+ assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
+ assertThat(forwardingObjective.selector(), is(expectSelector));
+ assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
+ assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+
+ compiler.deactivate();
+ }
+
+ /**
+ * Single point to multi point case. Scenario is the follow:
+ *
+ * -1 of1 2-1 of2 2--1 of3 2-
+ * 3
+ * `-1 of4 2-
+ *
+ * We test the proper compilation of sp2mp with trivial selector,
+ * empty treatment and points.
+ *
+ */
+ @Test
+ public void testFilteredConnectPointForSp() {
+ compiler.activate();
+ Set<Link> testLinks = ImmutableSet.of(
+ DefaultLink.builder().providerId(PID).src(of1p2).dst(of2p1).type(DIRECT).build(),
+ DefaultLink.builder().providerId(PID).src(of2p2).dst(of3p1).type(DIRECT).build(),
+ DefaultLink.builder().providerId(PID).src(of2p3).dst(of4p1).type(DIRECT).build()
+ );
+
+ Set<FilteredConnectPoint> ingress = ImmutableSet.of(
+ new FilteredConnectPoint(of1p1, vlan100Selector)
+ );
+
+ Set<FilteredConnectPoint> egress = ImmutableSet.of(
+ new FilteredConnectPoint(of3p2, vlan100Selector),
+ new FilteredConnectPoint(of4p2, vlan100Selector)
+ );
+
+ TrafficSelector broadcastSelector = DefaultTrafficSelector.builder()
+ .matchEthDst(MacAddress.BROADCAST)
+ .build();
+
+ LinkCollectionIntent intent = LinkCollectionIntent.builder()
+ .appId(appId)
+ .selector(broadcastSelector)
+ .treatment(treatment)
+ .links(testLinks)
+ .filteredIngressPoints(ingress)
+ .filteredEgressPoints(egress)
+ .applyTreatmentOnEgress(true)
+ .resourceGroup(resourceGroup1)
+ .build();
+
+ List<Intent> result = compiler.compile(intent, Collections.emptyList());
+ assertThat(result, hasSize(1));
+ assertThat(result.get(0), instanceOf(FlowObjectiveIntent.class));
+
+ FlowObjectiveIntent foIntent = (FlowObjectiveIntent) result.get(0);
+ List<Objective> objectives = foIntent.objectives();
+ assertThat(objectives, hasSize(12));
+
+ /*
+ * First set of objective
+ */
+ filteringObjective = (FilteringObjective) objectives.get(0);
+ forwardingObjective = (ForwardingObjective) objectives.get(1);
+ nextObjective = (NextObjective) objectives.get(2);
+
+ // expect selector and treatment
+ TrafficSelector expectSelector = DefaultTrafficSelector.builder()
+ .matchInPort(PortNumber.portNumber(1))
+ .matchVlanId(VlanId.vlanId("100"))
+ .matchEthDst(MacAddress.BROADCAST)
+ .build();
+ TrafficTreatment expectTreatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(2))
+ .build();
+
+ PortCriterion inPortCriterion =
+ (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+ // test case for first filtering objective
+ assertThat(filteringObjective.key(), is(inPortCriterion));
+ assertThat(filteringObjective.priority(), is(intent.priority()));
+ assertThat(filteringObjective.meta(), nullValue());
+ assertThat(filteringObjective.appId(), is(appId));
+ assertThat(filteringObjective.permanent(), is(true));
+ assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+
+ // test case for first next objective
+ assertThat(nextObjective.type(), is(NextObjective.Type.BROADCAST));
+ assertThat(nextObjective.next(), hasSize(1));
+ assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
+ assertThat(nextObjective.meta(), is(expectSelector));
+ assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+
+ // test case for first forwarding objective
+ assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
+ assertThat(forwardingObjective.selector(), is(expectSelector));
+ assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
+ assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+
+ /*
+ * Second set of objective
+ */
+ filteringObjective = (FilteringObjective) objectives.get(3);
+ forwardingObjective = (ForwardingObjective) objectives.get(4);
+ nextObjective = (NextObjective) objectives.get(5);
+
+ inPortCriterion =
+ (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+ // test case for first filtering objective
+ assertThat(filteringObjective.key(), is(inPortCriterion));
+ assertThat(filteringObjective.priority(), is(intent.priority()));
+ assertThat(filteringObjective.meta(), nullValue());
+ assertThat(filteringObjective.appId(), is(appId));
+ assertThat(filteringObjective.permanent(), is(true));
+ assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+
+ // test case for second next objective
+ assertThat(nextObjective.type(), is(NextObjective.Type.BROADCAST));
+ assertThat(nextObjective.next(), hasSize(1));
+ assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
+ assertThat(nextObjective.meta(), is(expectSelector));
+ assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+
+ // test case for second forwarding objective
+ assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
+ assertThat(forwardingObjective.selector(), is(expectSelector));
+ assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
+ assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+
+ /*
+ * 3rd set of objective
+ */
+ filteringObjective = (FilteringObjective) objectives.get(6);
+ forwardingObjective = (ForwardingObjective) objectives.get(7);
+ nextObjective = (NextObjective) objectives.get(8);
+
+ inPortCriterion =
+ (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+ // test case for first filtering objective
+ assertThat(filteringObjective.key(), is(inPortCriterion));
+ assertThat(filteringObjective.priority(), is(intent.priority()));
+ assertThat(filteringObjective.meta(), nullValue());
+ assertThat(filteringObjective.appId(), is(appId));
+ assertThat(filteringObjective.permanent(), is(true));
+ assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+
+ // test case for 3rd next objective
+ assertThat(nextObjective.type(), is(NextObjective.Type.BROADCAST));
+ assertThat(nextObjective.next(), hasSize(1));
+ assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
+ assertThat(nextObjective.meta(), is(expectSelector));
+ assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+
+ // test case for 3rd forwarding objective
+ assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
+ assertThat(forwardingObjective.selector(), is(expectSelector));
+ assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
+ assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+
+ /*
+ * 4th set of objective
+ */
+ filteringObjective = (FilteringObjective) objectives.get(9);
+ forwardingObjective = (ForwardingObjective) objectives.get(10);
+ nextObjective = (NextObjective) objectives.get(11);
+
+ inPortCriterion =
+ (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+ // test case for first filtering objective
+ assertThat(filteringObjective.key(), is(inPortCriterion));
+ assertThat(filteringObjective.priority(), is(intent.priority()));
+ assertThat(filteringObjective.meta(), nullValue());
+ assertThat(filteringObjective.appId(), is(appId));
+ assertThat(filteringObjective.permanent(), is(true));
+ assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+
+ // test case for 3rd next objective
+ assertThat(nextObjective.type(), is(NextObjective.Type.BROADCAST));
+
+ // have 2 treatments in this objective
+ assertThat(nextObjective.next(), hasSize(2));
+ expectTreatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(2))
+ .build();
+ assertThat(nextObjective.next(), hasItem(expectTreatment));
+
+ expectTreatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(3))
+ .build();
+ assertThat(nextObjective.next(), hasItem(expectTreatment));
+
+ assertThat(nextObjective.meta(), is(expectSelector));
+ assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+
+ // test case for 3rd forwarding objective
+ assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
+ assertThat(forwardingObjective.selector(), is(expectSelector));
+ assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
+ assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+
+ compiler.deactivate();
+ }
+
+ /**
+ * Multi point to single point intent with filtered connect point.
+ * Scenario is the follow:
+ *
+ * -1 of1 2-1 of2 2-1 of4 2-
+ * 3
+ * -1 of3 2---/
+ *
+ */
+ @Test
+ public void testFilteredConnectPointForMp() {
+ compiler.activate();
+ Set<Link> testLinks = ImmutableSet.of(
+ DefaultLink.builder().providerId(PID).src(of1p2).dst(of2p1).type(DIRECT).build(),
+ DefaultLink.builder().providerId(PID).src(of3p2).dst(of2p3).type(DIRECT).build(),
+ DefaultLink.builder().providerId(PID).src(of2p2).dst(of4p1).type(DIRECT).build()
+ );
+
+ Set<FilteredConnectPoint> ingress = ImmutableSet.of(
+ new FilteredConnectPoint(of3p1, vlan100Selector),
+ new FilteredConnectPoint(of1p1, vlan100Selector)
+ );
+
+ Set<FilteredConnectPoint> egress = ImmutableSet.of(
+ new FilteredConnectPoint(of4p2, vlan100Selector)
+ );
+
+
+
+ LinkCollectionIntent intent = LinkCollectionIntent.builder()
+ .appId(appId)
+ .selector(ethDstSelector)
+ .treatment(treatment)
+ .links(testLinks)
+ .filteredIngressPoints(ingress)
+ .filteredEgressPoints(egress)
+ .build();
+
+ List<Intent> result = compiler.compile(intent, Collections.emptyList());
+ assertThat(result, hasSize(1));
+ assertThat(result.get(0), instanceOf(FlowObjectiveIntent.class));
+
+ FlowObjectiveIntent foIntent = (FlowObjectiveIntent) result.get(0);
+ List<Objective> objectives = foIntent.objectives();
+ assertThat(objectives, hasSize(15));
+
+ TrafficSelector expectSelector = DefaultTrafficSelector
+ .builder(ethDstSelector)
+ .matchInPort(PortNumber.portNumber(1))
+ .matchVlanId(VlanId.vlanId("100"))
+ .build();
+
+ TrafficTreatment expectTreatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(2))
+ .build();
+
+ /*
+ * First set of objective
+ */
+ filteringObjective = (FilteringObjective) objectives.get(0);
+ forwardingObjective = (ForwardingObjective) objectives.get(1);
+ nextObjective = (NextObjective) objectives.get(2);
+
+ PortCriterion inPortCriterion =
+ (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+ // test case for first filtering objective
+ assertThat(filteringObjective.key(), is(inPortCriterion));
+ assertThat(filteringObjective.priority(), is(intent.priority()));
+ assertThat(filteringObjective.meta(), nullValue());
+ assertThat(filteringObjective.appId(), is(appId));
+ assertThat(filteringObjective.permanent(), is(true));
+ assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+
+ // test case for first next objective
+ assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
+ assertThat(nextObjective.next(), hasSize(1));
+ assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
+ assertThat(nextObjective.meta(), is(expectSelector));
+ assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+
+ // test case for first forwarding objective
+ assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
+ assertThat(forwardingObjective.selector(), is(expectSelector));
+ assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
+ assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+
+ /*
+ * Second set of objective
+ */
+ filteringObjective = (FilteringObjective) objectives.get(3);
+ forwardingObjective = (ForwardingObjective) objectives.get(4);
+ nextObjective = (NextObjective) objectives.get(5);
+
+ // test case for first filtering objective
+ assertThat(filteringObjective.key(), is(inPortCriterion));
+ assertThat(filteringObjective.priority(), is(intent.priority()));
+ assertThat(filteringObjective.meta(), nullValue());
+ assertThat(filteringObjective.appId(), is(appId));
+ assertThat(filteringObjective.permanent(), is(true));
+ assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+
+ // test case for first next objective
+ assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
+ assertThat(nextObjective.next(), hasSize(1));
+ assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
+ assertThat(nextObjective.meta(), is(expectSelector));
+ assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+
+ // test case for first forwarding objective
+ assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
+ assertThat(forwardingObjective.selector(), is(expectSelector));
+ assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
+ assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+
+ /*
+ * 3rd set of objective
+ */
+ filteringObjective = (FilteringObjective) objectives.get(6);
+ forwardingObjective = (ForwardingObjective) objectives.get(7);
+ nextObjective = (NextObjective) objectives.get(8);
+
+ // test case for first filtering objective
+ assertThat(filteringObjective.key(), is(inPortCriterion));
+ assertThat(filteringObjective.priority(), is(intent.priority()));
+ assertThat(filteringObjective.meta(), nullValue());
+ assertThat(filteringObjective.appId(), is(appId));
+ assertThat(filteringObjective.permanent(), is(true));
+ assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+
+ // test case for first next objective
+ assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
+ assertThat(nextObjective.next(), hasSize(1));
+ assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
+ assertThat(nextObjective.meta(), is(expectSelector));
+ assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+
+ // test case for first forwarding objective
+ assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
+ assertThat(forwardingObjective.selector(), is(expectSelector));
+ assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
+ assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+
+ /*
+ * 4th set of objective
+ */
+ filteringObjective = (FilteringObjective) objectives.get(9);
+ forwardingObjective = (ForwardingObjective) objectives.get(10);
+ nextObjective = (NextObjective) objectives.get(11);
+
+ // test case for first filtering objective
+ assertThat(filteringObjective.key(), is(inPortCriterion));
+ assertThat(filteringObjective.priority(), is(intent.priority()));
+ assertThat(filteringObjective.meta(), nullValue());
+ assertThat(filteringObjective.appId(), is(appId));
+ assertThat(filteringObjective.permanent(), is(true));
+ assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+
+ // test case for first next objective
+ assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
+ assertThat(nextObjective.next(), hasSize(1));
+ assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
+ assertThat(nextObjective.meta(), is(expectSelector));
+ assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+
+ // test case for first forwarding objective
+ assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
+ assertThat(forwardingObjective.selector(), is(expectSelector));
+ assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
+ assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+
+ /*
+ * 5th set of objective
+ */
+ filteringObjective = (FilteringObjective) objectives.get(12);
+ forwardingObjective = (ForwardingObjective) objectives.get(13);
+ nextObjective = (NextObjective) objectives.get(14);
+
+ expectSelector = DefaultTrafficSelector.builder(ethDstSelector)
+ .matchVlanId(VlanId.vlanId("100"))
+ .matchInPort(PortNumber.portNumber(3))
+ .build();
+
+ inPortCriterion =
+ (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+ // test case for first filtering objective
+ assertThat(filteringObjective.key(), is(inPortCriterion));
+ assertThat(filteringObjective.priority(), is(intent.priority()));
+ assertThat(filteringObjective.meta(), nullValue());
+ assertThat(filteringObjective.appId(), is(appId));
+ assertThat(filteringObjective.permanent(), is(true));
+ assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+
+ // test case for first next objective
+ assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
+ assertThat(nextObjective.next(), hasSize(1));
+ assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
+ assertThat(nextObjective.meta(), is(expectSelector));
+ assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+
+ // test case for first forwarding objective
+ assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
+ assertThat(forwardingObjective.selector(), is(expectSelector));
+ assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
+ assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+ compiler.deactivate();
+ }
+
+ /**
+ * Multiple point to single point intent with only one switch.
+ * We test the proper compilation of mp2sp with
+ * trivial selector, trivial treatment and 1 hop.
+ */
+ @Test
+ public void singleHopTestForMp() {
+ compiler.activate();
+ Set<Link> testLinks = ImmutableSet.of();
+
+ Set<FilteredConnectPoint> ingress = ImmutableSet.of(
+ new FilteredConnectPoint(of1p1, vlan100Selector),
+ new FilteredConnectPoint(of1p2, vlan100Selector)
+ );
+
+ Set<FilteredConnectPoint> egress = ImmutableSet.of(
+ new FilteredConnectPoint(of1p3, vlan100Selector)
+ );
+
+
+ LinkCollectionIntent intent = LinkCollectionIntent.builder()
+ .appId(appId)
+ .selector(ethDstSelector)
+ .treatment(treatment)
+ .links(testLinks)
+ .filteredIngressPoints(ingress)
+ .filteredEgressPoints(egress)
+ .build();
+
+ List<Intent> result = compiler.compile(intent, Collections.emptyList());
+ assertThat(result, hasSize(1));
+ assertThat(result.get(0), instanceOf(FlowObjectiveIntent.class));
+
+ FlowObjectiveIntent foIntent = (FlowObjectiveIntent) result.get(0);
+ List<Objective> objectives = foIntent.objectives();
+ assertThat(objectives, hasSize(6));
+
+ TrafficSelector expectSelector = DefaultTrafficSelector
+ .builder(ethDstSelector)
+ .matchInPort(PortNumber.portNumber(1))
+ .matchVlanId(VlanId.vlanId("100"))
+ .build();
+
+ TrafficTreatment expectTreatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(3))
+ .build();
+
+ /*
+ * First set of objective
+ */
+ filteringObjective = (FilteringObjective) objectives.get(0);
+ forwardingObjective = (ForwardingObjective) objectives.get(1);
+ nextObjective = (NextObjective) objectives.get(2);
+
+ PortCriterion inPortCriterion =
+ (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+ // test case for first filtering objective
+ assertThat(filteringObjective.key(), is(inPortCriterion));
+ assertThat(filteringObjective.priority(), is(intent.priority()));
+ assertThat(filteringObjective.meta(), nullValue());
+ assertThat(filteringObjective.appId(), is(appId));
+ assertThat(filteringObjective.permanent(), is(true));
+ assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+
+ // test case for first next objective
+ assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
+ assertThat(nextObjective.next(), hasSize(1));
+ assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
+ assertThat(nextObjective.meta(), is(expectSelector));
+ assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+
+ // test case for first forwarding objective
+ assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
+ assertThat(forwardingObjective.selector(), is(expectSelector));
+ assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
+ assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+
+ /*
+ * Second set of objective
+ */
+ filteringObjective = (FilteringObjective) objectives.get(3);
+ forwardingObjective = (ForwardingObjective) objectives.get(4);
+ nextObjective = (NextObjective) objectives.get(5);
+
+ expectSelector = DefaultTrafficSelector.builder(ethDstSelector)
+ .matchInPort(PortNumber.portNumber(2))
+ .matchVlanId(VlanId.vlanId("100"))
+ .build();
+
+ inPortCriterion =
+ (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+ // test case for first filtering objective
+ assertThat(filteringObjective.key(), is(inPortCriterion));
+ assertThat(filteringObjective.priority(), is(intent.priority()));
+ assertThat(filteringObjective.meta(), nullValue());
+ assertThat(filteringObjective.appId(), is(appId));
+ assertThat(filteringObjective.permanent(), is(true));
+ assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+
+ // test case for first next objective
+ assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
+ assertThat(nextObjective.next(), hasSize(1));
+ assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
+ assertThat(nextObjective.meta(), is(expectSelector));
+ assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+
+ // test case for first forwarding objective
+ assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
+ assertThat(forwardingObjective.selector(), is(expectSelector));
+ assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
+ assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+ compiler.deactivate();
+ }
+
+ /**
+ * Single point to multiple point intent with only one switch.
+ * We test the proper compilation of sp2mp with
+ * trivial selector, trivial treatment and 1 hop.
+ */
+ @Test
+ public void singleHopTestForSp() {
+ compiler.activate();
+ Set<Link> testLinks = ImmutableSet.of();
+
+ Set<FilteredConnectPoint> ingress = ImmutableSet.of(
+ new FilteredConnectPoint(of1p1, vlan100Selector)
+ );
+
+ Set<FilteredConnectPoint> egress = ImmutableSet.of(
+ new FilteredConnectPoint(of1p2, vlan100Selector),
+ new FilteredConnectPoint(of1p3, vlan100Selector)
+ );
+
+
+ LinkCollectionIntent intent = LinkCollectionIntent.builder()
+ .appId(appId)
+ .selector(ethDstSelector)
+ .treatment(treatment)
+ .links(testLinks)
+ .filteredIngressPoints(ingress)
+ .filteredEgressPoints(egress)
+ .applyTreatmentOnEgress(true)
+ .resourceGroup(resourceGroup2)
+ .build();
+
+ List<Intent> result = compiler.compile(intent, Collections.emptyList());
+ assertThat(result, hasSize(1));
+ assertThat(result.get(0), instanceOf(FlowObjectiveIntent.class));
+
+ FlowObjectiveIntent foIntent = (FlowObjectiveIntent) result.get(0);
+ List<Objective> objectives = foIntent.objectives();
+ assertThat(objectives, hasSize(3));
+
+ TrafficSelector expectSelector = DefaultTrafficSelector
+ .builder(ethDstSelector)
+ .matchInPort(PortNumber.portNumber(1))
+ .matchVlanId(VlanId.vlanId("100"))
+ .build();
+
+ TrafficTreatment expectTreatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(3))
+ .build();
+
+ /*
+ * First set of objective
+ */
+ filteringObjective = (FilteringObjective) objectives.get(0);
+ forwardingObjective = (ForwardingObjective) objectives.get(1);
+ nextObjective = (NextObjective) objectives.get(2);
+
+ PortCriterion inPortCriterion =
+ (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+ // test case for first filtering objective
+ assertThat(filteringObjective.key(), is(inPortCriterion));
+ assertThat(filteringObjective.priority(), is(intent.priority()));
+ assertThat(filteringObjective.meta(), nullValue());
+ assertThat(filteringObjective.appId(), is(appId));
+ assertThat(filteringObjective.permanent(), is(true));
+ assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+
+ // test case for first next objective
+ assertThat(nextObjective.type(), is(NextObjective.Type.BROADCAST));
+ assertThat(nextObjective.next(), hasSize(2));
+ assertThat(nextObjective.next(), hasItem(expectTreatment));
+ expectTreatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(3))
+ .build();
+ assertThat(nextObjective.next(), hasItem(expectTreatment));
+ assertThat(nextObjective.meta(), is(expectSelector));
+ assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+
+ // test case for first forwarding objective
+ assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
+ assertThat(forwardingObjective.selector(), is(expectSelector));
+ assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
+ assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+
+ compiler.deactivate();
+
+ }
+
+
+}