mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-23 21:31:00 +02:00
Adds OfdpaPipelineUtility
Change-Id: I96086e408dd9d7265325414dace512b64a048e9a
This commit is contained in:
parent
d19b7143c5
commit
9469f3e47e
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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<Pair<ForwardingObjective, Collection<FlowRule>>> 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<String> getNextMappings(NextGroup nextGroup) {
|
||||
List<String> 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.
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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<Deque<GroupKey>> allGroupKeys = new ArrayList<>();
|
||||
List<GroupInfo> unsentGroups = new ArrayList<>();
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -31,7 +31,6 @@
|
||||
<suppress files="org.onlab.jdvue.*" checks="AbbreviationAsWordInName" />
|
||||
<suppress files="org.onosproject.driver.pipeline.*" checks="AbbreviationAsWordInName" />
|
||||
<suppress files="org.onosproject.driver.pipeline.ofdpa.Ofdpa2GroupHandler.java" checks="FileLength" />
|
||||
<suppress files="org.onosproject.driver.pipeline.ofdpa.Ofdpa2Pipeline.java" checks="FileLength" />
|
||||
<suppress files="org.onosproject.segmentrouting.*" checks="AbbreviationAsWordInName" />
|
||||
|
||||
<!-- These files carry AT&T copyrights -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user