diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/XpliantPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/XpliantPipeline.java index 3d09258747..b5b202d667 100644 --- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/XpliantPipeline.java +++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/XpliantPipeline.java @@ -22,6 +22,8 @@ import org.onosproject.net.flowobjective.ForwardingObjective; import org.onosproject.driver.pipeline.ofdpa.Ofdpa3Pipeline; import java.util.Collection; +import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.ACL_TABLE; + public class XpliantPipeline extends Ofdpa3Pipeline { @Override diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java index 52d5382d62..7db00a811b 100644 --- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java +++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java @@ -90,6 +90,7 @@ import java.util.stream.Collectors; import static org.onlab.util.Tools.groupedThreads; import static org.onosproject.driver.pipeline.ofdpa.Ofdpa2Pipeline.*; +import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.*; import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.*; import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.L2_MULTICAST_TYPE; import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.l2MulticastGroupKey; diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java index f4ab685c44..071bf983e7 100644 --- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java +++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java @@ -47,7 +47,6 @@ import org.onosproject.net.behaviour.Pipeliner; import org.onosproject.net.behaviour.PipelinerContext; import org.onosproject.net.device.DeviceService; import org.onosproject.net.driver.AbstractHandlerBehaviour; -import org.onosproject.net.driver.Driver; import org.onosproject.net.flow.DefaultFlowRule; import org.onosproject.net.flow.DefaultTrafficSelector; import org.onosproject.net.flow.DefaultTrafficTreatment; @@ -61,8 +60,6 @@ import org.onosproject.net.flow.criteria.Criteria; import org.onosproject.net.flow.criteria.Criterion; import org.onosproject.net.flow.criteria.EthCriterion; import org.onosproject.net.flow.criteria.EthTypeCriterion; -import org.onosproject.net.flow.criteria.ExtensionCriterion; -import org.onosproject.net.flow.criteria.ExtensionSelector; import org.onosproject.net.flow.criteria.IPCriterion; import org.onosproject.net.flow.criteria.Icmpv6CodeCriterion; import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion; @@ -77,8 +74,6 @@ import org.onosproject.net.flow.instructions.Instructions.OutputInstruction; import org.onosproject.net.flow.instructions.Instructions.NoActionInstruction; import org.onosproject.net.flow.instructions.L2ModificationInstruction; import org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType; -import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction; -import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction; import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsHeaderInstruction; import org.onosproject.net.flow.instructions.L3ModificationInstruction; import org.onosproject.net.flow.instructions.L3ModificationInstruction.L3SubType; @@ -117,7 +112,7 @@ import static org.onlab.util.Tools.groupedThreads; import static org.onosproject.driver.extensions.Ofdpa3CopyField.OXM_ID_PACKET_REG_1; import static org.onosproject.driver.extensions.Ofdpa3CopyField.OXM_ID_VLAN_VID; import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.*; -import static org.onosproject.net.flow.criteria.Criterion.Type.ETH_TYPE; +import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.*; import static org.onosproject.net.group.GroupDescription.Type.SELECT; import static org.slf4j.LoggerFactory.getLogger; import static org.onosproject.net.flow.criteria.Criterion.Type.MPLS_BOS; @@ -129,43 +124,7 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline // Timer for the accumulator private static final Timer TIMER = new Timer("fwdobj-batching"); private Accumulator>> accumulator; - - protected static final int PORT_TABLE = 0; - protected static final int VLAN_TABLE = 10; - protected static final int VLAN_1_TABLE = 11; - protected static final int MPLS_L2_PORT_FLOW_TABLE = 13; - protected static final int MPLS_L2_PORT_PCP_TRUST_FLOW_TABLE = 16; - protected static final int TMAC_TABLE = 20; - protected static final int UNICAST_ROUTING_TABLE = 30; - protected static final int MULTICAST_ROUTING_TABLE = 40; - protected static final int MPLS_TABLE_0 = 23; - protected static final int MPLS_TABLE_1 = 24; - protected static final int MPLS_L3_TYPE_TABLE = 27; - protected static final int MPLS_TYPE_TABLE = 29; - protected static final int BRIDGING_TABLE = 50; - protected static final int ACL_TABLE = 60; - protected static final int EGRESS_VLAN_FLOW_TABLE = 210; - protected static final int EGRESS_DSCP_PCP_REMARK_FLOW_TABLE = 230; - protected static final int EGRESS_TPID_FLOW_TABLE = 235; - protected static final int MAC_LEARNING_TABLE = 254; - protected static final long OFPP_MAX = 0xffffff00L; - - protected static final int HIGHEST_PRIORITY = 0xffff; - protected static final int DEFAULT_PRIORITY = 0x8000; - protected static final int LOWEST_PRIORITY = 0x0; - - protected static final int MPLS_L2_PORT_PRIORITY = 2; - protected static final int MPLS_TUNNEL_ID_BASE = 0x10000; - protected static final int MPLS_TUNNEL_ID_MAX = 0x1FFFF; - - protected static final int MPLS_UNI_PORT_MAX = 0x0000FFFF; - protected static final int MPLS_NNI_PORT_BASE = 0x00020000; - protected static final int MPLS_NNI_PORT_MAX = 0x0002FFFF; - - protected static final short ALLOW_VLAN_TRANSLATION = 1; - protected static final int COPY_FIELD_NBITS = 12; - protected static final int COPY_FIELD_OFFSET = 0; - + // Internal objects private final Logger log = getLogger(getClass()); protected ServiceDirectory serviceDirectory; protected FlowRuleService flowRuleService; @@ -188,8 +147,6 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline // flows installations to be retried private ScheduledExecutorService retryExecutorService = newScheduledThreadPool(5, groupedThreads("OfdpaPipeliner", "retry-%d", log)); - private static final int MAX_RETRY_ATTEMPTS = 10; - private static final int RETRY_MS = 1000; // accumulator executor service private ScheduledExecutorService accumulatorExecutorService @@ -206,7 +163,7 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline flowObjectiveStore = context.store(); deviceService = serviceDirectory.get(DeviceService.class); // Init the accumulator, if enabled - if (isAccumulatorEnabled()) { + if (isAccumulatorEnabled(this)) { accumulator = new ForwardingObjectiveAccumulator(context.accumulatorMaxObjectives(), context.accumulatorMaxBatchMillis(), context.accumulatorMaxIdleMillis()); @@ -234,15 +191,6 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline // software switches does require table-miss-entries. } - public boolean isAccumulatorEnabled() { - Driver driver = super.data().driver(); - // we cannot determine the property - if (driver == null) { - return false; - } - return Boolean.parseBoolean(driver.getProperty(ACCUMULATOR_ENABLED)); - } - /** * Determines whether this pipeline requires MPLS POP instruction. * @@ -402,7 +350,7 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline @Override public void onSuccess(FlowRuleOperations ops) { log.trace("Flow rule operations onSuccess {}", ops); - fwdObjs.forEach(Ofdpa2Pipeline::pass); + fwdObjs.forEach(OfdpaPipelineUtility::pass); } @Override @@ -1828,14 +1776,6 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline return null; } - protected static void pass(Objective obj) { - obj.context().ifPresent(context -> context.onSuccess(obj)); - } - - protected static void fail(Objective obj, ObjectiveError error) { - obj.context().ifPresent(context -> context.onError(obj, error)); - } - @Override public List getNextMappings(NextGroup nextGroup) { List mappings = new ArrayList<>(); @@ -1869,119 +1809,6 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline return mappings; } - /** - * Returns true iff the given selector matches on BOS==true, indicating that - * the selector is trying to match on a label that is bottom-of-stack. - * - * @param selector the given match - * @return true iff BoS==true; false if BOS==false, or BOS matching is not - * expressed in the given selector - */ - static boolean isMplsBos(TrafficSelector selector) { - MplsBosCriterion bosCriterion = (MplsBosCriterion) selector.getCriterion(MPLS_BOS); - return bosCriterion != null && bosCriterion.mplsBos(); - } - - /** - * Returns true iff the given selector matches on BOS==false, indicating - * that the selector is trying to match on a label that is not the - * bottom-of-stack label. - * - * @param selector the given match - * @return true iff BoS==false; - * false if BOS==true, or BOS matching is not expressed in the given selector - */ - static boolean isNotMplsBos(TrafficSelector selector) { - MplsBosCriterion bosCriterion = (MplsBosCriterion) selector.getCriterion(MPLS_BOS); - return bosCriterion != null && !bosCriterion.mplsBos(); - } - - /** - * Returns true iff the forwarding objective includes a treatment to pop the - * MPLS label. - * - * @param fwd the given forwarding objective - * @return true iff mpls pop treatment exists - */ - static boolean isMplsPop(ForwardingObjective fwd) { - if (fwd.treatment() != null) { - for (Instruction instr : fwd.treatment().allInstructions()) { - if (instr instanceof L2ModificationInstruction - && ((L2ModificationInstruction) instr) - .subtype() == L2SubType.MPLS_POP) { - return true; - } - } - } - return false; - } - - private static boolean isIpv6(TrafficSelector selector) { - EthTypeCriterion ethTypeCriterion = (EthTypeCriterion) selector.getCriterion(ETH_TYPE); - return ethTypeCriterion != null && ethTypeCriterion.ethType().toShort() == Ethernet.TYPE_IPV6; - } - - static VlanId readVlanFromSelector(TrafficSelector selector) { - if (selector == null) { - return null; - } - Criterion criterion = selector.getCriterion(Criterion.Type.VLAN_VID); - return (criterion == null) - ? null : ((VlanIdCriterion) criterion).vlanId(); - } - - static MacAddress readEthDstFromSelector(TrafficSelector selector) { - if (selector == null) { - return null; - } - Criterion criterion = selector.getCriterion(Criterion.Type.ETH_DST); - return (criterion == null) - ? null : ((EthCriterion) criterion).mac(); - } - - static IpPrefix readIpDstFromSelector(TrafficSelector selector) { - if (selector == null) { - return null; - } - Criterion criterion = selector.getCriterion(Criterion.Type.IPV4_DST); - return (criterion == null) ? null : ((IPCriterion) criterion).ip(); - } - - private static VlanId readVlanFromTreatment(TrafficTreatment treatment) { - if (treatment == null) { - return null; - } - for (Instruction i : treatment.allInstructions()) { - if (i instanceof ModVlanIdInstruction) { - return ((ModVlanIdInstruction) i).vlanId(); - } - } - return null; - } - - protected static MacAddress readEthDstFromTreatment(TrafficTreatment treatment) { - if (treatment == null) { - return null; - } - for (Instruction i : treatment.allInstructions()) { - if (i instanceof ModEtherInstruction) { - ModEtherInstruction modEtherInstruction = (ModEtherInstruction) i; - if (modEtherInstruction.subtype() == L2SubType.ETH_DST) { - return modEtherInstruction.mac(); - } - } - } - return null; - } - - static ExtensionSelector readExtensionFromSelector(TrafficSelector selector) { - if (selector == null) { - return null; - } - ExtensionCriterion criterion = (ExtensionCriterion) selector.getCriterion(Criterion.Type.EXTENSION); - return (criterion == null) ? null : criterion.extensionSelector(); - } - /** * Utility class that retries sending flows a fixed number of times, even if * some of the attempts are successful. Used only for forwarding objectives. diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3GroupHandler.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3GroupHandler.java index 6d28a11ee2..d427a6cb3e 100644 --- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3GroupHandler.java +++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3GroupHandler.java @@ -29,8 +29,6 @@ import org.onosproject.driver.extensions.OfdpaSetVlanVid; 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.VlanIdCriterion; import org.onosproject.net.flow.instructions.Instruction; import org.onosproject.net.flow.instructions.Instructions; import org.onosproject.net.flow.instructions.L2ModificationInstruction; @@ -101,7 +99,7 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler { ); if (groupInfo == null) { log.error("Could not process nextObj={} in dev:{}", nextObjective.id(), deviceId); - Ofdpa2Pipeline.fail(nextObjective, ObjectiveError.GROUPINSTALLATIONFAILED); + OfdpaPipelineUtility.fail(nextObjective, ObjectiveError.GROUPINSTALLATIONFAILED); return; } // We update the chain with the last two groups; @@ -128,7 +126,7 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler { log.error("Next Objective for pseudo wire should have at " + "most {} mpls instruction sets. Next Objective Id:{}", MAX_DEPTH_UNPROTECTED_PW, nextObjective.id()); - Ofdpa2Pipeline.fail(nextObjective, ObjectiveError.BADPARAMS); + OfdpaPipelineUtility.fail(nextObjective, ObjectiveError.BADPARAMS); return; } @@ -487,28 +485,4 @@ public class Ofdpa3GroupHandler extends Ofdpa2GroupHandler { return new GroupInfo(l2groupDescription, outerGrpDesc); } - /** - * Helper method to decide whether L2 Interface group or L2 Unfiltered group needs to be created. - * L2 Unfiltered group will be created if meta has VlanIdCriterion with VlanId.ANY, and - * treatment has set Vlan ID action. - * - * @param treatment treatment passed in by the application as part of the nextObjective - * @param meta metadata passed in by the application as part of the nextObjective - * @return true if L2 Unfiltered group needs to be created, false otherwise. - */ - private boolean isUnfiltered(TrafficTreatment treatment, TrafficSelector meta) { - if (meta == null || treatment == null) { - return false; - } - VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) meta.getCriterion(Criterion.Type.VLAN_VID); - if (vlanIdCriterion == null || !vlanIdCriterion.vlanId().equals(VlanId.ANY)) { - return false; - } - - return treatment.allInstructions().stream() - .filter(i -> (i.type() == Instruction.Type.L2MODIFICATION - && ((L2ModificationInstruction) i).subtype() == L2ModificationInstruction.L2SubType.VLAN_ID)) - .count() == 1; - } - } diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3Pipeline.java index 7168f6d405..dbf1280f77 100644 --- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3Pipeline.java +++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa3Pipeline.java @@ -64,6 +64,7 @@ import java.util.Deque; import java.util.List; import static org.onlab.packet.MacAddress.NONE; +import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.*; import static org.onosproject.driver.extensions.Ofdpa3MplsType.VPWS; import static org.onosproject.net.flow.criteria.Criterion.Type.INNER_VLAN_VID; import static org.onosproject.net.flow.criteria.Criterion.Type.IN_PORT; @@ -445,45 +446,6 @@ public class Ofdpa3Pipeline extends Ofdpa2Pipeline { return ImmutableList.of(outerRule, innerRule); } - /** - * Determines if the filtering objective will be used for double-tagged packets. - * - * @param fob Filtering objective - * @return True if the objective was created for double-tagged packets, false otherwise. - */ - private boolean isDoubleTagged(FilteringObjective fob) { - return fob.meta() != null && - fob.meta().allInstructions().stream().anyMatch(inst -> inst.type() == L2MODIFICATION - && ((L2ModificationInstruction) inst).subtype() == L2SubType.VLAN_POP) && - fob.conditions().stream().filter(criterion -> criterion.type() == VLAN_VID).count() == 2; - } - - /** - * Determines if the filtering objective will be used for a pseudowire. - * - * @param filteringObjective - * @return True if objective was created for a pseudowire, false otherwise. - */ - private boolean isPseudowire(FilteringObjective filteringObjective) { - - - if (filteringObjective.meta() != null) { - - TrafficTreatment treatment = filteringObjective.meta(); - for (Instruction instr : treatment.immediate()) { - if (instr.type().equals(Instruction.Type.L2MODIFICATION)) { - - L2ModificationInstruction l2Instr = (L2ModificationInstruction) instr; - if (l2Instr.subtype().equals(L2SubType.TUNNEL_ID)) { - return true; - } - } - } - } - - return false; - } - /** * Method to process the pw related filtering objectives. * @@ -813,52 +775,6 @@ public class Ofdpa3Pipeline extends Ofdpa2Pipeline { return Collections.singletonList(ruleBuilder.build()); } - /** - * Utility function to get the mod tunnel id instruction - * if present. - * - * @param treatment the treatment to analyze - * @return the mod tunnel id instruction if present, - * otherwise null - */ - private ModTunnelIdInstruction getModTunnelIdInstruction(TrafficTreatment treatment) { - if (treatment == null) { - return null; - } - - L2ModificationInstruction l2ModificationInstruction; - for (Instruction instruction : treatment.allInstructions()) { - if (instruction.type() == L2MODIFICATION) { - l2ModificationInstruction = (L2ModificationInstruction) instruction; - if (l2ModificationInstruction.subtype() == L2SubType.TUNNEL_ID) { - return (ModTunnelIdInstruction) l2ModificationInstruction; - } - } - } - return null; - } - - /** - * Utility function to get the output instruction - * if present. - * - * @param treatment the treatment to analyze - * @return the output instruction if present, - * otherwise null - */ - private OutputInstruction getOutputInstruction(TrafficTreatment treatment) { - if (treatment == null) { - return null; - } - - for (Instruction instruction : treatment.allInstructions()) { - if (instruction.type() == Instruction.Type.OUTPUT) { - return (OutputInstruction) instruction; - } - } - return null; - } - /** * Helper method for dividing the tunnel instructions from the mpls * instructions. @@ -910,4 +826,5 @@ public class Ofdpa3Pipeline extends Ofdpa2Pipeline { } } } + } diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaGroupHandlerUtility.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaGroupHandlerUtility.java index d4e364ffee..afab73f332 100644 --- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaGroupHandlerUtility.java +++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaGroupHandlerUtility.java @@ -51,7 +51,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; -import static org.onosproject.driver.pipeline.ofdpa.Ofdpa2Pipeline.isNotMplsBos; +import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.isNotMplsBos; import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.OfdpaMplsGroupSubType.OFDPA_GROUP_TYPE_SHIFT; import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.OfdpaMplsGroupSubType.OFDPA_MPLS_SUBTYPE_SHIFT; import static org.onosproject.net.flowobjective.NextObjective.Type.HASHED; @@ -794,4 +794,28 @@ public final class OfdpaGroupHandlerUtility { return L3_UNICAST_TYPE | 1 << 27 | (vlanId.toShort() << 15) | (int) (portNum & 0x7FFF); } + /** + * Helper method to decide whether L2 Interface group or L2 Unfiltered group needs to be created. + * L2 Unfiltered group will be created if meta has VlanIdCriterion with VlanId.ANY, and + * treatment has set Vlan ID action. + * + * @param treatment treatment passed in by the application as part of the nextObjective + * @param meta metadata passed in by the application as part of the nextObjective + * @return true if L2 Unfiltered group needs to be created, false otherwise. + */ + static boolean isUnfiltered(TrafficTreatment treatment, TrafficSelector meta) { + if (meta == null || treatment == null) { + return false; + } + VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) meta.getCriterion(Criterion.Type.VLAN_VID); + if (vlanIdCriterion == null || !vlanIdCriterion.vlanId().equals(VlanId.ANY)) { + return false; + } + + return treatment.allInstructions().stream() + .filter(i -> (i.type() == Instruction.Type.L2MODIFICATION + && ((L2ModificationInstruction) i).subtype() == L2ModificationInstruction.L2SubType.VLAN_ID)) + .count() == 1; + } + } diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaPipelineUtility.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaPipelineUtility.java new file mode 100644 index 0000000000..683b9f607b --- /dev/null +++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaPipelineUtility.java @@ -0,0 +1,363 @@ +/* + * Copyright 2019-present Open Networking Foundation + * + * 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.driver.pipeline.ofdpa; + +import org.onlab.packet.Ethernet; +import org.onlab.packet.IpPrefix; +import org.onlab.packet.MacAddress; +import org.onlab.packet.VlanId; +import org.onosproject.net.driver.Driver; +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.criteria.EthTypeCriterion; +import org.onosproject.net.flow.criteria.ExtensionCriterion; +import org.onosproject.net.flow.criteria.ExtensionSelector; +import org.onosproject.net.flow.criteria.IPCriterion; +import org.onosproject.net.flow.criteria.MplsBosCriterion; +import org.onosproject.net.flow.criteria.VlanIdCriterion; +import org.onosproject.net.flow.instructions.Instruction; +import org.onosproject.net.flow.instructions.Instructions; +import org.onosproject.net.flow.instructions.L2ModificationInstruction; +import org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType; +import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction; +import org.onosproject.net.flowobjective.FilteringObjective; +import org.onosproject.net.flowobjective.ForwardingObjective; +import org.onosproject.net.flowobjective.Objective; +import org.onosproject.net.flowobjective.ObjectiveError; + +import static org.onosproject.net.behaviour.Pipeliner.ACCUMULATOR_ENABLED; +import static org.onosproject.net.flow.criteria.Criterion.Type.ETH_TYPE; +import static org.onosproject.net.flow.criteria.Criterion.Type.MPLS_BOS; +import static org.onosproject.net.flow.criteria.Criterion.Type.VLAN_VID; +import static org.onosproject.net.flow.instructions.Instruction.Type.L2MODIFICATION; +import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction; +import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction; + +public final class OfdpaPipelineUtility { + + private OfdpaPipelineUtility() { + // Utility classes should not have a public or default constructor. + } + + // Ofdpa specific tables number + static final int PORT_TABLE = 0; + static final int VLAN_TABLE = 10; + static final int VLAN_1_TABLE = 11; + static final int MPLS_L2_PORT_FLOW_TABLE = 13; + static final int MPLS_L2_PORT_PCP_TRUST_FLOW_TABLE = 16; + static final int TMAC_TABLE = 20; + static final int UNICAST_ROUTING_TABLE = 30; + static final int MULTICAST_ROUTING_TABLE = 40; + static final int MPLS_TABLE_0 = 23; + static final int MPLS_TABLE_1 = 24; + static final int MPLS_L3_TYPE_TABLE = 27; + static final int MPLS_TYPE_TABLE = 29; + static final int BRIDGING_TABLE = 50; + public static final int ACL_TABLE = 60; + static final int EGRESS_VLAN_FLOW_TABLE = 210; + static final int EGRESS_DSCP_PCP_REMARK_FLOW_TABLE = 230; + static final int EGRESS_TPID_FLOW_TABLE = 235; + static final int MAC_LEARNING_TABLE = 254; + + // OF max port number + static final long OFPP_MAX = 0xffffff00L; + + // Priority values + static final int HIGHEST_PRIORITY = 0xffff; + static final int DEFAULT_PRIORITY = 0x8000; + static final int LOWEST_PRIORITY = 0x0; + + // MPLS L2 table values + static final int MPLS_L2_PORT_PRIORITY = 2; + static final int MPLS_TUNNEL_ID_BASE = 0x10000; + static final int MPLS_TUNNEL_ID_MAX = 0x1FFFF; + static final int MPLS_UNI_PORT_MAX = 0x0000FFFF; + static final int MPLS_NNI_PORT_BASE = 0x00020000; + static final int MPLS_NNI_PORT_MAX = 0x0002FFFF; + + // Egress table values + static final short ALLOW_VLAN_TRANSLATION = 1; + static final int COPY_FIELD_NBITS = 12; + static final int COPY_FIELD_OFFSET = 0; + + // Flow retry values + static final int MAX_RETRY_ATTEMPTS = 10; + static final int RETRY_MS = 1000; + + ////////////////////////////// + // Helper and utility methods + ////////////////////////////// + + /** + * Check whether the accumulator is enabled or not. + * @param pipeline the pipeline + * @return true if the accumulator is enabled. Otherwise not + */ + static boolean isAccumulatorEnabled(Ofdpa2Pipeline pipeline) { + Driver driver = pipeline.data().driver(); + // we cannot determine the property + if (driver == null) { + return false; + } + return Boolean.parseBoolean(driver.getProperty(ACCUMULATOR_ENABLED)); + } + + static void pass(Objective obj) { + obj.context().ifPresent(context -> context.onSuccess(obj)); + } + + static void fail(Objective obj, ObjectiveError error) { + obj.context().ifPresent(context -> context.onError(obj, error)); + } + + /** + * Returns true iff the given selector matches on BOS==true, indicating that + * the selector is trying to match on a label that is bottom-of-stack. + * + * @param selector the given match + * @return true iff BoS==true; false if BOS==false, or BOS matching is not + * expressed in the given selector + */ + static boolean isMplsBos(TrafficSelector selector) { + MplsBosCriterion bosCriterion = (MplsBosCriterion) selector.getCriterion(MPLS_BOS); + return bosCriterion != null && bosCriterion.mplsBos(); + } + + /** + * Returns true iff the given selector matches on BOS==false, indicating + * that the selector is trying to match on a label that is not the + * bottom-of-stack label. + * + * @param selector the given match + * @return true iff BoS==false; + * false if BOS==true, or BOS matching is not expressed in the given selector + */ + static boolean isNotMplsBos(TrafficSelector selector) { + MplsBosCriterion bosCriterion = (MplsBosCriterion) selector.getCriterion(MPLS_BOS); + return bosCriterion != null && !bosCriterion.mplsBos(); + } + + /** + * Returns true iff the forwarding objective includes a treatment to pop the + * MPLS label. + * + * @param fwd the given forwarding objective + * @return true iff mpls pop treatment exists + */ + static boolean isMplsPop(ForwardingObjective fwd) { + if (fwd.treatment() != null) { + for (Instruction instr : fwd.treatment().allInstructions()) { + if (instr instanceof L2ModificationInstruction + && ((L2ModificationInstruction) instr) + .subtype() == L2SubType.MPLS_POP) { + return true; + } + } + } + return false; + } + + /** + * Returns true iff the given selector matches on ethtype==ipv6, indicating + * that the selector is trying to match on ipv6 traffic. + * + * @param selector the given match + * @return true iff ethtype==ipv6; false otherwise + */ + static boolean isIpv6(TrafficSelector selector) { + EthTypeCriterion ethTypeCriterion = (EthTypeCriterion) selector.getCriterion(ETH_TYPE); + return ethTypeCriterion != null && ethTypeCriterion.ethType().toShort() == Ethernet.TYPE_IPV6; + } + + /** + * Reads vlan id from selector. + * + * @param selector the given match + * @return the vlan id if found. null otherwise + */ + static VlanId readVlanFromSelector(TrafficSelector selector) { + if (selector == null) { + return null; + } + Criterion criterion = selector.getCriterion(Criterion.Type.VLAN_VID); + return (criterion == null) + ? null : ((VlanIdCriterion) criterion).vlanId(); + } + + /** + * Reads eth dst from selector. + * + * @param selector the given match + * @return the eth dst if found. null otherwise + */ + static MacAddress readEthDstFromSelector(TrafficSelector selector) { + if (selector == null) { + return null; + } + Criterion criterion = selector.getCriterion(Criterion.Type.ETH_DST); + return (criterion == null) + ? null : ((EthCriterion) criterion).mac(); + } + + /** + * Reads ipv4 dst from selector. + * + * @param selector the given match + * @return the ipv4 dst if found. null otherwise + */ + static IpPrefix readIpDstFromSelector(TrafficSelector selector) { + if (selector == null) { + return null; + } + Criterion criterion = selector.getCriterion(Criterion.Type.IPV4_DST); + return (criterion == null) ? null : ((IPCriterion) criterion).ip(); + } + + /** + * Reads vlan id from treatment. + * + * @param treatment the given actions + * @return the vlan id if found. null otherwise + */ + static VlanId readVlanFromTreatment(TrafficTreatment treatment) { + if (treatment == null) { + return null; + } + for (Instruction i : treatment.allInstructions()) { + if (i instanceof ModVlanIdInstruction) { + return ((ModVlanIdInstruction) i).vlanId(); + } + } + return null; + } + + /** + * Reads eth dst from treatment. + * + * @param treatment the given actions + * @return the eth dst if found. null otherwise + */ + static MacAddress readEthDstFromTreatment(TrafficTreatment treatment) { + if (treatment == null) { + return null; + } + for (Instruction i : treatment.allInstructions()) { + if (i instanceof ModEtherInstruction) { + ModEtherInstruction modEtherInstruction = (ModEtherInstruction) i; + if (modEtherInstruction.subtype() == L2SubType.ETH_DST) { + return modEtherInstruction.mac(); + } + } + } + return null; + } + + /** + * Reads extensions from selector. + * @param selector the given match + * @return the extensions if found. null otherwise + */ + static ExtensionSelector readExtensionFromSelector(TrafficSelector selector) { + if (selector == null) { + return null; + } + ExtensionCriterion criterion = (ExtensionCriterion) selector.getCriterion(Criterion.Type.EXTENSION); + return (criterion == null) ? null : criterion.extensionSelector(); + } + + /** + * Determines if the filtering objective will be used for a pseudowire. + * + * @param filteringObjective the filtering objective + * @return True if objective was created for a pseudowire, false otherwise. + */ + static boolean isPseudowire(FilteringObjective filteringObjective) { + if (filteringObjective.meta() != null) { + TrafficTreatment treatment = filteringObjective.meta(); + for (Instruction instr : treatment.immediate()) { + if (instr.type().equals(Instruction.Type.L2MODIFICATION)) { + + L2ModificationInstruction l2Instr = (L2ModificationInstruction) instr; + if (l2Instr.subtype().equals(L2SubType.TUNNEL_ID)) { + return true; + } + } + } + } + return false; + } + + /** + * Utility function to get the mod tunnel id instruction + * if present. + * + * @param treatment the treatment to analyze + * @return the mod tunnel id instruction if present, + * otherwise null + */ + static ModTunnelIdInstruction getModTunnelIdInstruction(TrafficTreatment treatment) { + if (treatment == null) { + return null; + } + L2ModificationInstruction l2ModificationInstruction; + for (Instruction instruction : treatment.allInstructions()) { + if (instruction.type() == L2MODIFICATION) { + l2ModificationInstruction = (L2ModificationInstruction) instruction; + if (l2ModificationInstruction.subtype() == L2SubType.TUNNEL_ID) { + return (ModTunnelIdInstruction) l2ModificationInstruction; + } + } + } + return null; + } + + /** + * Utility function to get the output instruction + * if present. + * + * @param treatment the treatment to analyze + * @return the output instruction if present, + * otherwise null + */ + static Instructions.OutputInstruction getOutputInstruction(TrafficTreatment treatment) { + if (treatment == null) { + return null; + } + for (Instruction instruction : treatment.allInstructions()) { + if (instruction.type() == Instruction.Type.OUTPUT) { + return (Instructions.OutputInstruction) instruction; + } + } + return null; + } + + /** + * Determines if the filtering objective will be used for double-tagged packets. + * + * @param fob Filtering objective + * @return True if the objective was created for double-tagged packets, false otherwise. + */ + static boolean isDoubleTagged(FilteringObjective fob) { + return fob.meta() != null && + fob.meta().allInstructions().stream().anyMatch(inst -> inst.type() == L2MODIFICATION + && ((L2ModificationInstruction) inst).subtype() == L2SubType.VLAN_POP) && + fob.conditions().stream().filter(criterion -> criterion.type() == VLAN_VID).count() == 2; + } + +} diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OvsOfdpaGroupHandler.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OvsOfdpaGroupHandler.java index beabae0d34..d45b0c1c49 100644 --- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OvsOfdpaGroupHandler.java +++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OvsOfdpaGroupHandler.java @@ -248,7 +248,7 @@ public class OvsOfdpaGroupHandler extends Ofdpa2GroupHandler { // the transport of a VPWS. The necessary info are contained in the // meta selector. In particular we are looking for the case of BoS==False; TrafficSelector metaSelector = nextObjective.meta(); - if (metaSelector != null && Ofdpa2Pipeline.isNotMplsBos(metaSelector)) { + if (metaSelector != null && OfdpaPipelineUtility.isNotMplsBos(metaSelector)) { // storage for all group keys in the chain of groups created List> allGroupKeys = new ArrayList<>(); List unsentGroups = new ArrayList<>(); diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OvsOfdpaPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OvsOfdpaPipeline.java index e3b4b06a66..8c20f50199 100644 --- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OvsOfdpaPipeline.java +++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OvsOfdpaPipeline.java @@ -90,8 +90,8 @@ import static org.onlab.packet.MacAddress.BROADCAST; import static org.onlab.packet.MacAddress.NONE; import static org.onlab.util.Tools.groupedThreads; import static org.onosproject.driver.pipeline.ofdpa.OfdpaGroupHandlerUtility.*; +import static org.onosproject.driver.pipeline.ofdpa.OfdpaPipelineUtility.*; import static org.onosproject.net.flow.criteria.Criterion.Type.VLAN_VID; -import static org.onosproject.net.flow.instructions.Instruction.Type.L2MODIFICATION; import static org.slf4j.LoggerFactory.getLogger; /** @@ -161,10 +161,11 @@ public class OvsOfdpaPipeline extends Ofdpa2Pipeline { groupChecker.scheduleAtFixedRate(new PopVlanPuntGroupChecker(), 20, 50, TimeUnit.MILLISECONDS); super.init(deviceId, context); } + protected void processFilter(FilteringObjective filteringObjective, boolean install, ApplicationId applicationId) { - if (isDoubleTagged(filteringObjective)) { + if (OfdpaPipelineUtility.isDoubleTagged(filteringObjective)) { processDoubleTaggedFilter(filteringObjective, install, applicationId); } else { // If it is not a double-tagged filter, we fall back @@ -173,20 +174,6 @@ public class OvsOfdpaPipeline extends Ofdpa2Pipeline { } } - /** - * Determines if the filtering objective will be used for double-tagged packets. - * - * @param fob Filtering objective - * @return True if the objective was created for double-tagged packets, false otherwise. - */ - private boolean isDoubleTagged(FilteringObjective fob) { - return fob.meta() != null && - fob.meta().allInstructions().stream().anyMatch(inst -> inst.type() == L2MODIFICATION - && ((L2ModificationInstruction) inst).subtype() == - L2ModificationInstruction.L2SubType.VLAN_POP) && - fob.conditions().stream().filter(criterion -> criterion.type() == VLAN_VID).count() == 2; - } - /** * Determines if the forwarding objective will be used for double-tagged packets. * diff --git a/tools/build/conf/src/main/resources/onos/suppressions.xml b/tools/build/conf/src/main/resources/onos/suppressions.xml index f87d11f683..d1c613b64a 100644 --- a/tools/build/conf/src/main/resources/onos/suppressions.xml +++ b/tools/build/conf/src/main/resources/onos/suppressions.xml @@ -31,7 +31,6 @@ -