Changes related to the "LinkCollectionIntent" type of intents
(e.g., Multipoint-to-singlepoint and Singlepoint-to-multipoint)
* Apply the Intent-defined traffic treatment only on the flowmods
on the ingress switch with ingress inport for a flowmod.
Previously, the traffic treatments were applied on each switch,
and semantically it is not the correct (default) behavior.
* Express the flowmods by explicitly specifying the expected inport
in the matching conditions for each flowmod.
Previously, the inport was not included in the matching conditions.
[Merge from branch onos-1.0 - manually]
Change-Id: Ic378b6e8be033a70b016f4ba5550d91fe08ddd9a
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/LinkCollectionIntentInstaller.java b/core/net/src/main/java/org/onosproject/net/intent/impl/LinkCollectionIntentInstaller.java
index 260bd5b..0d788e5 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/LinkCollectionIntentInstaller.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/LinkCollectionIntentInstaller.java
@@ -43,9 +43,9 @@
import org.onosproject.net.intent.LinkCollectionIntent;
import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import java.util.stream.Collectors;
/**
* Installer for {@link org.onosproject.net.intent.LinkCollectionIntent} path
@@ -88,35 +88,29 @@
LinkCollectionIntent intent, FlowRuleOperation.Type operation) {
//TODO do we need a set here?
+ SetMultimap<DeviceId, PortNumber> inputPorts = HashMultimap.create();
SetMultimap<DeviceId, PortNumber> outputPorts = HashMultimap.create();
for (Link link : intent.links()) {
+ inputPorts.put(link.dst().deviceId(), link.dst().port());
outputPorts.put(link.src().deviceId(), link.src().port());
}
+ for (ConnectPoint ingressPoint : intent.ingressPoints()) {
+ inputPorts.put(ingressPoint.deviceId(), ingressPoint.port());
+ }
+
for (ConnectPoint egressPoint : intent.egressPoints()) {
outputPorts.put(egressPoint.deviceId(), egressPoint.port());
}
- //FIXME change to new api
- /* Fear of streams */
- /*
- Set<FlowRuleBatchEntry> rules = Sets.newHashSet();
- for (DeviceId deviceId : outputPorts.keys()) {
- rules.add(createBatchEntry(operation,
- intent, deviceId,
- outputPorts.get(deviceId)));
- }
- */
-
- Set<FlowRuleOperation> rules =
- outputPorts
- .keys()
- .stream()
- .map(deviceId -> createBatchEntry(operation,
- intent, deviceId,
- outputPorts.get(deviceId)))
- .collect(Collectors.toSet());
+ List<FlowRuleOperation> rules = Lists.newArrayList();
+ outputPorts.keys().stream()
+ .map(deviceId -> createBatchEntries(operation,
+ intent, deviceId,
+ inputPorts.get(deviceId),
+ outputPorts.get(deviceId)))
+ .forEach(rules::addAll);
return Lists.newArrayList(ImmutableSet.of(rules));
}
@@ -132,35 +126,72 @@
}
/**
- * Creates a FlowRuleBatchEntry based on the provided parameters.
+ * Creates a collection of FlowRuleOperation based on the provided
+ * parameters.
*
- * @param operation the FlowRuleOperation to use
+ * @param operation the FlowRuleOperation type to use
* @param intent the link collection intent
* @param deviceId the device ID for the flow rule
+ * @param inPorts the logical input ports of the flow rule
* @param outPorts the set of output ports for the flow rule
- * @return the new flow rule batch entry
+ * @return a collection with the new flow rule batch entries
*/
- private FlowRuleOperation createBatchEntry(FlowRuleOperation.Type operation,
- LinkCollectionIntent intent,
- DeviceId deviceId,
- Set<PortNumber> outPorts) {
+ private Collection<FlowRuleOperation> createBatchEntries(
+ FlowRuleOperation.Type operation,
+ LinkCollectionIntent intent,
+ DeviceId deviceId,
+ Set<PortNumber> inPorts,
+ Set<PortNumber> outPorts) {
+ Collection<FlowRuleOperation> result = Lists.newLinkedList();
+ Set<PortNumber> ingressPorts = new HashSet<PortNumber>();
- TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment
- .builder(intent.treatment());
-
- for (PortNumber outPort : outPorts) {
- treatmentBuilder.setOutput(outPort);
+ //
+ // Collect all ingress ports for this device.
+ // The intent treatment is applied only on those ports.
+ //
+ for (ConnectPoint cp : intent.ingressPoints()) {
+ if (cp.deviceId().equals(deviceId)) {
+ ingressPorts.add(cp.port());
+ }
}
- TrafficTreatment treatment = treatmentBuilder.build();
- TrafficSelector selector = DefaultTrafficSelector
- .builder(intent.selector()).build();
+ //
+ // Create two treatments: one for setting the output ports,
+ // and a second one that applies the intent treatment and sets the
+ // output ports.
+ // NOTE: The second one is created only if there are ingress ports.
+ //
+ TrafficTreatment.Builder defaultTreatmentBuilder =
+ DefaultTrafficTreatment.builder();
+ for (PortNumber outPort : outPorts) {
+ defaultTreatmentBuilder.setOutput(outPort);
+ }
+ TrafficTreatment defaultTreatment = defaultTreatmentBuilder.build();
+ TrafficTreatment intentTreatment = null;
+ if (!ingressPorts.isEmpty()) {
+ TrafficTreatment.Builder intentTreatmentBuilder =
+ DefaultTrafficTreatment.builder(intent.treatment());
+ for (PortNumber outPort : outPorts) {
+ intentTreatmentBuilder.setOutput(outPort);
+ }
+ intentTreatment = intentTreatmentBuilder.build();
+ }
- FlowRule rule = new DefaultFlowRule(deviceId,
+ for (PortNumber inPort : inPorts) {
+ TrafficSelector selector = DefaultTrafficSelector
+ .builder(intent.selector()).matchInPort(inPort).build();
+ TrafficTreatment treatment = defaultTreatment;
+ if (ingressPorts.contains(inPort)) {
+ // Use the intent treatment if this is ingress port
+ treatment = intentTreatment;
+ }
+ FlowRule rule = new DefaultFlowRule(deviceId,
selector, treatment, 123, appId,
new DefaultGroupId((short) (intent.id().fingerprint() & 0xffff)),
0, true);
+ result.add(new FlowRuleOperation(rule, operation));
+ }
- return new FlowRuleOperation(rule, operation);
+ return result;
}
}
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
index c016f41..b4889f4 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MultiPointToSinglePointIntentCompiler.java
@@ -16,6 +16,7 @@
package org.onosproject.net.intent.impl.compiler;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -40,6 +41,7 @@
import org.onosproject.net.resource.LinkResourceAllocations;
import org.onosproject.net.topology.PathService;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
/**
@@ -76,8 +78,10 @@
for (Link link : path.links()) {
if (links.containsKey(link.src().deviceId())) {
// We've already reached the existing tree with the first
- // part of this path. Don't add the remainder of the path
+ // part of this path. Add the merging point with different
+ // incoming port, but don't add the remainder of the path
// in case it differs from the path we already have.
+ links.put(link.src().deviceId(), link);
break;
}
@@ -87,7 +91,10 @@
Intent result = new LinkCollectionIntent(intent.appId(),
intent.selector(), intent.treatment(),
- Sets.newHashSet(links.values()), intent.egressPoint());
+ Sets.newHashSet(links.values()),
+ intent.ingressPoints(),
+ ImmutableSet.of(intent.egressPoint()),
+ Collections.emptyList());
return Arrays.asList(result);
}
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 fd344e2..8360820 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
@@ -33,6 +33,8 @@
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.resource.LinkResourceAllocations;
+import com.google.common.collect.ImmutableSet;
+
@Component(immediate = true)
public class SinglePointToMultiPointIntentCompiler
extends ConnectivityIntentCompiler<SinglePointToMultiPointIntent> {
@@ -67,6 +69,7 @@
Intent result = new LinkCollectionIntent(intent.appId(),
intent.selector(),
intent.treatment(), links,
+ ImmutableSet.of(intent.ingressPoint()),
intent.egressPoints(), Collections.emptyList());
return Arrays.asList(result);