Fixed removal of fwd classifier rules when double tagged hosts
Change-Id: Icba49cc4ee8b55ca83686a1c362560f5031a755f
diff --git a/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/FilteringObjectiveTranslator.java b/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/FilteringObjectiveTranslator.java
index a6f0e81..86b893d 100644
--- a/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/FilteringObjectiveTranslator.java
+++ b/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/FilteringObjectiveTranslator.java
@@ -32,17 +32,23 @@
import org.onosproject.net.flow.criteria.PiCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flowobjective.FilteringObjective;
+import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.net.pi.runtime.PiAction;
import org.onosproject.net.pi.runtime.PiActionParam;
import org.onosproject.pipelines.fabric.impl.behaviour.FabricCapabilities;
import org.onosproject.pipelines.fabric.impl.behaviour.FabricConstants;
+import org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils;
import java.util.Collection;
import java.util.List;
import static java.lang.String.format;
+import static org.onosproject.net.flow.criteria.Criterion.Type.INNER_VLAN_VID;
+import static org.onosproject.net.flow.criteria.Criterion.Type.VLAN_VID;
import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.criterion;
/**
@@ -95,11 +101,53 @@
obj.conditions(), Criterion.Type.ETH_DST_MASKED);
ingressPortVlanRule(obj, inPort, outerVlan, innerVlan, resultBuilder);
- fwdClassifierRules(obj, inPort, ethDst, ethDstMasked, resultBuilder);
-
+ if (shouldAddFwdClassifierRule(obj)) {
+ fwdClassifierRules(obj, inPort, ethDst, ethDstMasked, resultBuilder);
+ } else {
+ log.debug("Skipping fwd classifier rules for device {}.", deviceId);
+ }
return resultBuilder.build();
}
+ private boolean shouldAddFwdClassifierRule(FilteringObjective obj) {
+ // NOTE: in fabric pipeline the forwarding classifier acts similarly
+ // to the TMAC table of OFDPA that matches on input port.
+
+ // Forwarding classifier rules should be added to translation when:
+ // - the operation is ADD OR
+ // - it doesn't refer to double tagged traffic OR
+ // - it refers to double tagged traffic
+ // and SR is triggering the removal of forwarding classifier rules.
+ return obj.op() == Objective.Operation.ADD ||
+ !isDoubleTagged(obj) ||
+ (isDoubleTagged(obj) && isLastDoubleTaggedForPort(obj));
+ }
+
+ /**
+ * Check if the given filtering objective is the last filtering objective
+ * for a double-tagged host for a specific port.
+ * <p>
+ * {@see org.onosproject.segmentrouting.RoutingRulePopulator#buildDoubleTaggedFilteringObj()}
+ * {@see org.onosproject.segmentrouting.RoutingRulePopulator#processDoubleTaggedFilter()}
+ *
+ * @param obj Filtering objective to check.
+ * @return True if SR is signaling to remove the forwarding classifier rule,
+ * false otherwise.
+ */
+ private boolean isLastDoubleTaggedForPort(FilteringObjective obj) {
+ Instructions.MetadataInstruction meta = obj.meta().writeMetadata();
+ // SR is setting this metadata when a double tagged filtering objective
+ // is removed and no other hosts is sharing the same input port.
+ return (meta != null && (meta.metadata() & meta.metadataMask()) == 1);
+ }
+
+ private boolean isDoubleTagged(FilteringObjective obj) {
+ return obj.meta() != null &&
+ FabricUtils.l2Instruction(obj.meta(), L2ModificationInstruction.L2SubType.VLAN_POP) != null &&
+ FabricUtils.criterion(obj.conditions(), VLAN_VID) != null &&
+ FabricUtils.criterion(obj.conditions(), INNER_VLAN_VID) != null;
+ }
+
private void ingressPortVlanRule(
FilteringObjective obj,
Criterion inPortCriterion,