ONOS-4383 Updating traffic selector for {MP2SP,SP2MP}IntentCompilers
Apply egress action to ingress selector for non-ingress devices
Change-Id: I98b4c591d09cc4b5d0e0ff89eaeac44ba07e6326
diff --git a/cli/src/main/java/org/onosproject/cli/net/AddSinglePointToMultiPointIntentCommand.java b/cli/src/main/java/org/onosproject/cli/net/AddSinglePointToMultiPointIntentCommand.java
index 30133bd..87ede2b 100644
--- a/cli/src/main/java/org/onosproject/cli/net/AddSinglePointToMultiPointIntentCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/AddSinglePointToMultiPointIntentCommand.java
@@ -18,7 +18,6 @@
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.intent.Constraint;
@@ -59,7 +58,7 @@
}
TrafficSelector selector = buildTrafficSelector();
- TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
+ TrafficTreatment treatment = buildTrafficTreatment();
List<Constraint> constraints = buildConstraints();
SinglePointToMultiPointIntent intent =
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 04e740d..d582f6e 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
@@ -22,6 +22,8 @@
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpPrefix;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
@@ -34,10 +36,25 @@
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsBosInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpEthInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpIPInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModArpOpInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
+import org.onosproject.net.flow.instructions.L4ModificationInstruction.ModTransportPortInstruction;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentCompiler;
import org.onosproject.net.intent.LinkCollectionIntent;
+import org.onosproject.net.intent.impl.IntentCompilationException;
import java.util.ArrayList;
import java.util.Collections;
@@ -109,15 +126,20 @@
.forEach(ingressTreatmentBuilder::setOutput);
TrafficTreatment ingressTreatment = ingressTreatmentBuilder.build();
+ TrafficSelector defaultTrafficSelector = applyTreatmentToSelector(intent.selector(), ingressTreatment);
+
List<FlowRule> rules = new ArrayList<>(inPorts.size());
for (PortNumber inPort: inPorts) {
- TrafficSelector selector = DefaultTrafficSelector.builder(intent.selector()).matchInPort(inPort).build();
+ TrafficSelector.Builder selectorBuilder;
TrafficTreatment treatment;
if (ingressPorts.contains(inPort)) {
+ selectorBuilder = DefaultTrafficSelector.builder(intent.selector());
treatment = ingressTreatment;
} else {
+ selectorBuilder = DefaultTrafficSelector.builder(defaultTrafficSelector);
treatment = defaultTreatment;
}
+ TrafficSelector selector = selectorBuilder.matchInPort(inPort).build();
FlowRule rule = DefaultFlowRule.builder()
.forDevice(deviceId)
@@ -132,4 +154,169 @@
return rules;
}
+
+ private TrafficSelector applyTreatmentToSelector(TrafficSelector selector, TrafficTreatment treatment) {
+ TrafficSelector.Builder defaultSelectorBuilder = DefaultTrafficSelector.builder(selector);
+ treatment.allInstructions().forEach(instruction -> {
+ switch (instruction.type()) {
+ case L0MODIFICATION:
+ case L1MODIFICATION:
+ throw new IntentCompilationException("L0 and L1 mods not supported");
+ case L2MODIFICATION:
+ L2ModificationInstruction l2mod = (L2ModificationInstruction) instruction;
+ switch (l2mod.subtype()) {
+ case ETH_SRC:
+ case ETH_DST:
+ ModEtherInstruction ethInstr = (ModEtherInstruction) l2mod;
+ switch (ethInstr.subtype()) {
+ case ETH_SRC:
+ defaultSelectorBuilder.matchEthSrc(ethInstr.mac());
+ break;
+ case ETH_DST:
+ defaultSelectorBuilder.matchEthDst(ethInstr.mac());
+ break;
+ default:
+ throw new IntentCompilationException("Bad eth subtype");
+ }
+ break;
+ case VLAN_ID:
+ ModVlanIdInstruction vlanIdInstr = (ModVlanIdInstruction) l2mod;
+ defaultSelectorBuilder.matchVlanId(vlanIdInstr.vlanId());
+ break;
+ case VLAN_PUSH:
+ //FIXME
+ break;
+ case VLAN_POP:
+ //TODO how do we handle dropped label? remove the selector?
+ throw new IntentCompilationException("Can't handle pop label");
+ case VLAN_PCP:
+ ModVlanPcpInstruction vlanPcpInstruction = (ModVlanPcpInstruction) l2mod;
+ defaultSelectorBuilder.matchVlanPcp(vlanPcpInstruction.vlanPcp());
+ break;
+ case MPLS_LABEL:
+ case MPLS_PUSH:
+ //FIXME
+ ModMplsLabelInstruction mplsInstr = (ModMplsLabelInstruction) l2mod;
+ defaultSelectorBuilder.matchMplsLabel(mplsInstr.label());
+ break;
+ case MPLS_POP:
+ //TODO how do we handle dropped label? remove the selector?
+ throw new IntentCompilationException("Can't handle pop label");
+ case DEC_MPLS_TTL:
+ // no-op
+ break;
+ case MPLS_BOS:
+ ModMplsBosInstruction mplsBosInstr = (ModMplsBosInstruction) l2mod;
+ defaultSelectorBuilder.matchMplsBos(mplsBosInstr.mplsBos());
+ break;
+ case TUNNEL_ID:
+ ModTunnelIdInstruction tunInstr = (ModTunnelIdInstruction) l2mod;
+ defaultSelectorBuilder.matchTunnelId(tunInstr.tunnelId());
+ break;
+ default:
+ throw new IntentCompilationException("Unknown L2 Modification instruction");
+ }
+ break;
+ case L3MODIFICATION:
+ L3ModificationInstruction l3mod = (L3ModificationInstruction) instruction;
+ // TODO check ethernet proto
+ switch (l3mod.subtype()) {
+ case IPV4_SRC:
+ case IPV4_DST:
+ case IPV6_SRC:
+ case IPV6_DST:
+ ModIPInstruction ipInstr = (ModIPInstruction) l3mod;
+ // TODO check if ip falls in original prefix
+ IpPrefix prefix = ipInstr.ip().toIpPrefix();
+ switch (ipInstr.subtype()) {
+ case IPV4_SRC:
+ defaultSelectorBuilder.matchIPSrc(prefix);
+ break;
+ case IPV4_DST:
+ defaultSelectorBuilder.matchIPSrc(prefix);
+ break;
+ case IPV6_SRC:
+ defaultSelectorBuilder.matchIPv6Src(prefix);
+ break;
+ case IPV6_DST:
+ defaultSelectorBuilder.matchIPv6Dst(prefix);
+ break;
+ default:
+ throw new IntentCompilationException("Bad type for IP instruction");
+ }
+ break;
+ case IPV6_FLABEL:
+ ModIPv6FlowLabelInstruction ipFlowInstr = (ModIPv6FlowLabelInstruction) l3mod;
+ defaultSelectorBuilder.matchIPv6FlowLabel(ipFlowInstr.flowLabel());
+ break;
+ case DEC_TTL:
+ // no-op
+ break;
+ case TTL_OUT:
+ // no-op
+ break;
+ case TTL_IN:
+ // no-op
+ break;
+ case ARP_SPA:
+ ModArpIPInstruction arpIpInstr = (ModArpIPInstruction) l3mod;
+ if (arpIpInstr.ip().isIp4()) {
+ defaultSelectorBuilder.matchArpSpa((Ip4Address) arpIpInstr.ip());
+ } else {
+ throw new IntentCompilationException("IPv6 not supported for ARP");
+ }
+ break;
+ case ARP_SHA:
+ ModArpEthInstruction arpEthInstr = (ModArpEthInstruction) l3mod;
+ defaultSelectorBuilder.matchArpSha(arpEthInstr.mac());
+ break;
+ case ARP_OP:
+ ModArpOpInstruction arpOpInstr = (ModArpOpInstruction) l3mod;
+ //FIXME is the long to int cast safe?
+ defaultSelectorBuilder.matchArpOp((int) arpOpInstr.op());
+ break;
+ default:
+ throw new IntentCompilationException("Unknown L3 Modification instruction");
+ }
+ break;
+ case L4MODIFICATION:
+ if (instruction instanceof ModTransportPortInstruction) {
+ // TODO check IP proto
+ ModTransportPortInstruction l4mod = (ModTransportPortInstruction) instruction;
+ switch (l4mod.subtype()) {
+ case TCP_SRC:
+ defaultSelectorBuilder.matchTcpSrc(l4mod.port());
+ break;
+ case TCP_DST:
+ defaultSelectorBuilder.matchTcpDst(l4mod.port());
+ break;
+ case UDP_SRC:
+ defaultSelectorBuilder.matchUdpSrc(l4mod.port());
+ break;
+ case UDP_DST:
+ defaultSelectorBuilder.matchUdpDst(l4mod.port());
+ break;
+ default:
+ throw new IntentCompilationException("Unknown L4 Modification instruction");
+ }
+ } else {
+ throw new IntentCompilationException("Unknown L4 Modification instruction");
+ }
+ break;
+ case NOACTION:
+ case OUTPUT:
+ case GROUP:
+ case QUEUE:
+ case TABLE:
+ case METER:
+ case METADATA:
+ case EXTENSION: // TODO is extension no-op or unsupported?
+ // Nothing to do
+ break;
+ default:
+ throw new IntentCompilationException("Unknown instruction type");
+ }
+ });
+ return defaultSelectorBuilder.build();
+ }
}