diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java index 0b93c527bc..5e3d2ae090 100644 --- a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java +++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java @@ -31,6 +31,7 @@ import org.onosproject.net.flow.criteria.Criterion; import org.onosproject.net.flow.criteria.ExtensionCriterion; import org.onosproject.net.flow.criteria.ExtensionSelector; import org.onosproject.net.flow.criteria.ExtensionSelectorType; +import org.onosproject.net.flow.criteria.PiCriterion; import java.util.Collection; import java.util.Collections; @@ -41,6 +42,7 @@ import java.util.Objects; import java.util.Set; import java.util.TreeSet; +import static com.google.common.base.Preconditions.checkNotNull; import static org.onosproject.net.flow.criteria.Criterion.Type.EXTENSION; /** @@ -412,6 +414,11 @@ public final class DefaultTrafficSelector implements TrafficSelector { return add(Criteria.matchArpOp(arpOp)); } + @Override + public Builder matchPi(PiCriterion piCriterion) { + return add(checkNotNull(piCriterion, "Protocol-independent criterion cannot be null")); + } + @Override public TrafficSelector.Builder extension(ExtensionSelector extensionSelector, DeviceId deviceId) { diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java index 08c9cf5429..f932f04408 100644 --- a/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java +++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java @@ -35,6 +35,8 @@ import org.onosproject.net.meter.MeterId; import com.google.common.base.MoreObjects; import com.google.common.collect.ImmutableList; +import org.onosproject.net.pi.runtime.PiTableAction; + import static com.google.common.base.Preconditions.checkNotNull; /** @@ -244,6 +246,7 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { case L2MODIFICATION: case L3MODIFICATION: case L4MODIFICATION: + case PROTOCOL_INDEPENDENT: case EXTENSION: current.add(instruction); break; @@ -472,6 +475,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment { return add(Instructions.modL3ArpOp(op)); } + @Override + public Builder piTableAction(PiTableAction piTableAction) { + return add(Instructions.piTableAction(piTableAction)); + } + @Override public TrafficTreatment.Builder extension(ExtensionTreatment extension, DeviceId deviceId) { diff --git a/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java b/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java index 1b264b55d2..d5fcded220 100644 --- a/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java +++ b/core/api/src/main/java/org/onosproject/net/flow/TrafficSelector.java @@ -15,6 +15,7 @@ */ package org.onosproject.net.flow; +import com.google.common.annotations.Beta; import org.onlab.packet.Ip4Address; import org.onlab.packet.Ip6Address; import org.onlab.packet.IpPrefix; @@ -26,6 +27,7 @@ import org.onosproject.net.DeviceId; import org.onosproject.net.PortNumber; import org.onosproject.net.flow.criteria.Criterion; import org.onosproject.net.flow.criteria.ExtensionSelector; +import org.onosproject.net.flow.criteria.PiCriterion; import java.util.Set; @@ -456,6 +458,15 @@ public interface TrafficSelector { */ Builder matchArpOp(int arpOp); + /** + * Matches protocol independent fields. + * + * @param piCriterion protocol-independent criterion + * @return a selection builder + */ + @Beta + Builder matchPi(PiCriterion piCriterion); + /** * Uses an extension selector. * diff --git a/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java b/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java index f527a8382c..beddf5c53b 100644 --- a/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java +++ b/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java @@ -17,6 +17,7 @@ package org.onosproject.net.flow; import java.util.List; +import com.google.common.annotations.Beta; import org.onlab.packet.EthType; import org.onlab.packet.IpAddress; import org.onlab.packet.MacAddress; @@ -30,6 +31,7 @@ import org.onosproject.net.flow.instructions.ExtensionTreatment; import org.onosproject.net.flow.instructions.Instruction; import org.onosproject.net.flow.instructions.Instructions; import org.onosproject.net.meter.MeterId; +import org.onosproject.net.pi.runtime.PiTableAction; /** * Abstraction of network traffic treatment. @@ -395,6 +397,15 @@ public interface TrafficTreatment { */ Builder setArpOp(short op); + /** + * Sets the protocol independent table action. + * + * @param piTableAction protocol-independent table action + * @return a treatment builder. + */ + @Beta + Builder piTableAction(PiTableAction piTableAction); + /** * Uses an extension treatment. * diff --git a/core/api/src/main/java/org/onosproject/net/flow/criteria/PiCriterion.java b/core/api/src/main/java/org/onosproject/net/flow/criteria/PiCriterion.java index ab05f262d9..c9335c257b 100644 --- a/core/api/src/main/java/org/onosproject/net/flow/criteria/PiCriterion.java +++ b/core/api/src/main/java/org/onosproject/net/flow/criteria/PiCriterion.java @@ -18,11 +18,22 @@ package org.onosproject.net.flow.criteria; import com.google.common.annotations.Beta; import com.google.common.base.Objects; +import com.google.common.collect.Maps; import org.onosproject.net.pi.runtime.PiFieldMatch; +import org.onosproject.net.pi.runtime.PiHeaderFieldId; +import org.onosproject.net.pi.runtime.PiExactFieldMatch; +import org.onosproject.net.pi.runtime.PiTernaryFieldMatch; +import org.onosproject.net.pi.runtime.PiLpmFieldMatch; +import org.onosproject.net.pi.runtime.PiRangeFieldMatch; +import org.onosproject.net.pi.runtime.PiValidFieldMatch; import java.util.Collection; +import java.util.Map; import java.util.StringJoiner; +import static com.google.common.base.Preconditions.checkArgument; +import static org.onlab.util.ImmutableByteSequence.copyFrom; + /** * Protocol-indepedent criterion. */ @@ -36,7 +47,7 @@ public final class PiCriterion implements Criterion { * * @param fieldMatches fields to match */ - PiCriterion(Collection fieldMatches) { + private PiCriterion(Collection fieldMatches) { this.fieldMatches = fieldMatches; } @@ -77,4 +88,250 @@ public final class PiCriterion implements Criterion { fieldMatches.forEach(f -> stringParams.add(f.toString())); return stringParams.toString(); } -} + + /** + * Returns the PiCriterion builder. + * + * @return PiCriterion builder + */ + public static Builder builder() { + return new Builder(); + } + + /** + * PiCriterion Builder. + */ + @Beta + public static final class Builder { + + private final Map piFieldMatches = Maps.newHashMap(); + + private Builder() { + // ban constructor. + } + + /** + * Adds an exact field match for the given fieldId and value. + * + * @param fieldId protocol-independent header field Id + * @param value exact match value + * @return this + */ + public Builder matchExact(PiHeaderFieldId fieldId, short value) { + piFieldMatches.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value))); + return this; + } + + /** + * Adds an exact field match for the given fieldId and value. + * + * @param fieldId protocol-independent header field Id + * @param value exact match value + * @return this + */ + public Builder matchExact(PiHeaderFieldId fieldId, int value) { + piFieldMatches.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value))); + return this; + } + + /** + * Adds an exact field match for the given fieldId and value. + * + * @param fieldId protocol-independent header field Id + * @param value exact match value + * @return this + */ + public Builder matchExact(PiHeaderFieldId fieldId, long value) { + piFieldMatches.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value))); + return this; + } + + /** + * Adds an exact field match for the given fieldId and value. + * + * @param fieldId protocol-independent header field Id + * @param value exact match value + * @return this + */ + public Builder matchExact(PiHeaderFieldId fieldId, byte[] value) { + piFieldMatches.put(fieldId, new PiExactFieldMatch(fieldId, copyFrom(value))); + return this; + } + + /** + * Adds a ternary field match for the given fieldId, value and mask. + * + * @param fieldId protocol-independent header field Id + * @param value ternary match value + * @param mask ternary match mask + * @return this + */ + public Builder matchTernary(PiHeaderFieldId fieldId, short value, short mask) { + piFieldMatches.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask))); + return this; + } + + /** + * Adds a ternary field match for the given fieldId, value and mask. + * + * @param fieldId protocol-independent header field Id + * @param value ternary match value + * @param mask ternary match mask + * @return this + */ + public Builder matchTernary(PiHeaderFieldId fieldId, int value, int mask) { + piFieldMatches.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask))); + return this; + } + + /** + * Adds a ternary field match for the given fieldId, value and mask. + * + * @param fieldId protocol-independent header field Id + * @param value ternary match value + * @param mask ternary match mask + * @return this + */ + public Builder matchTernary(PiHeaderFieldId fieldId, long value, long mask) { + piFieldMatches.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask))); + return this; + } + + /** + * Adds a ternary field match for the given fieldId, value and mask. + * + * @param fieldId protocol-independent header field Id + * @param value ternary match value + * @param mask ternary match mask + * @return this + */ + public Builder matchTernary(PiHeaderFieldId fieldId, byte[] value, byte[] mask) { + piFieldMatches.put(fieldId, new PiTernaryFieldMatch(fieldId, copyFrom(value), copyFrom(mask))); + return this; + } + + /** + * Adds a longest-prefix field match for the given fieldId, value and prefix length. + * + * @param fieldId protocol-independent header field Id + * @param value lpm match value + * @param prefixLength lpm match prefix length + * @return this + */ + public Builder matchLpm(PiHeaderFieldId fieldId, short value, int prefixLength) { + piFieldMatches.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength)); + return this; + } + + /** + * Adds a longest-prefix field match for the given fieldId, value and prefix length. + * + * @param fieldId protocol-independent header field Id + * @param value lpm match value + * @param prefixLength lpm match prefix length + * @return this + */ + public Builder matchLpm(PiHeaderFieldId fieldId, int value, int prefixLength) { + piFieldMatches.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength)); + return this; + } + + /** + * Adds a longest-prefix field match for the given fieldId, value and prefix length. + * + * @param fieldId protocol-independent header field Id + * @param value lpm match value + * @param prefixLength lpm match prefix length + * @return this + */ + public Builder matchLpm(PiHeaderFieldId fieldId, long value, int prefixLength) { + piFieldMatches.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength)); + return this; + } + + /** + * Adds a longest-prefix field match for the given fieldId, value and prefix length. + * + * @param fieldId protocol-independent header field Id + * @param value lpm match value + * @param prefixLength lpm match prefix length + * @return this + */ + public Builder matchLpm(PiHeaderFieldId fieldId, byte[] value, int prefixLength) { + piFieldMatches.put(fieldId, new PiLpmFieldMatch(fieldId, copyFrom(value), prefixLength)); + return this; + } + + /** + * Adds a valid field match for the given fieldId and flag. + * + * @param fieldId protocol-independent header field Id + * @param flag a boolean value + * @return this + */ + public Builder matchValid(PiHeaderFieldId fieldId, boolean flag) { + piFieldMatches.put(fieldId, new PiValidFieldMatch(fieldId, flag)); + return this; + } + + /** + * Adds a range field match for the given fieldId, low and high. + * + * @param fieldId protocol-independent header field Id + * @param low range match low value + * @param high range match high value + * @return this + */ + public Builder matchRange(PiHeaderFieldId fieldId, short low, short high) { + piFieldMatches.put(fieldId, new PiRangeFieldMatch(fieldId, copyFrom(low), copyFrom(high))); + return this; + } + + /** + * Adds a range field match for the given fieldId, low and high. + * + * @param fieldId protocol-independent header field Id + * @param low range match low value + * @param high range match high value + * @return this + */ + public Builder matchRange(PiHeaderFieldId fieldId, int low, int high) { + piFieldMatches.put(fieldId, new PiRangeFieldMatch(fieldId, copyFrom(low), copyFrom(high))); + return this; + } + /** + * Adds a range field match for the given fieldId, low and high. + * + * @param fieldId protocol-independent header field Id + * @param low range match low value + * @param high range match high value + * @return this + */ + public Builder matchRange(PiHeaderFieldId fieldId, long low, long high) { + piFieldMatches.put(fieldId, new PiRangeFieldMatch(fieldId, copyFrom(low), copyFrom(high))); + return this; + } + /** + * Adds a range field match for the given fieldId, low and high. + * + * @param fieldId protocol-independent header field Id + * @param low range match low value + * @param high range match high value + * @return this + */ + public Builder matchRange(PiHeaderFieldId fieldId, byte[] low, byte[] high) { + piFieldMatches.put(fieldId, new PiRangeFieldMatch(fieldId, copyFrom(low), copyFrom(high))); + return this; + } + + /** + * Builds a PiCriterion. + * + * @return PiCriterion + */ + public Criterion build() { + checkArgument(piFieldMatches.size() > 0); + return new PiCriterion(piFieldMatches.values()); + } + } +} \ No newline at end of file diff --git a/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java b/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java index 01d2c1edba..0020e538a4 100644 --- a/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java +++ b/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java @@ -40,6 +40,7 @@ import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModTtlIns import org.onosproject.net.flow.instructions.L4ModificationInstruction.L4SubType; import org.onosproject.net.flow.instructions.L4ModificationInstruction.ModTransportPortInstruction; import org.onosproject.net.meter.MeterId; +import org.onosproject.net.pi.runtime.PiTableAction; import java.util.Objects; @@ -471,6 +472,17 @@ public final class Instructions { return new ModTransportPortInstruction(L4SubType.UDP_DST, port); } + /** + * Creates a protocol independent instruction. + * + * @param piTableAction protocol independent instruction + * @return extension instruction + */ + public static PiInstruction piTableAction(PiTableAction piTableAction) { + checkNotNull(piTableAction, "PiTableAction instruction cannot be null"); + return new PiInstruction(piTableAction); + } + /** * Creates an extension instruction. *