diff --git a/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/Constants.java b/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/Constants.java index 6f92cad862..5267572680 100644 --- a/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/Constants.java +++ b/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/Constants.java @@ -16,6 +16,10 @@ package org.onosproject.pipelines.fabric.impl.behaviour; +import com.google.common.collect.ImmutableMap; + +import java.util.Map; + /** * Constant values. */ @@ -48,6 +52,63 @@ public final class Constants { public static final int DEFAULT_TC = 0; public static final byte DEFAULT_QFI = (byte) 0x00; + ////////////////////////////////////////////////////////////////////////////// + // 64 .... 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 // + // X X X X X X X X X X X X X X X X X X X X X 1 1 1 1 1 // + ////////////////////////////////////////////////////////////////////////////// + // Metadata instruction is used as 8 byte sequence to carry up to 64 metadata + + // FIXME We are assuming SR as the only app programming this meta. + // SDFAB-530 to get rid of this limitation + + /** + * SR is setting this metadata when a double tagged filtering objective is removed + * and no other hosts is sharing the same input port. Thus, termination mac entries + * can be removed together with the vlan table entries. + * + * See org.onosproject.segmentrouting.RoutingRulePopulator#buildDoubleTaggedFilteringObj() + * See org.onosproject.segmentrouting.RoutingRulePopulator#processDoubleTaggedFilter() + */ + public static final long CLEANUP_DOUBLE_TAGGED_HOST_ENTRIES = 1; + + /** + * SR is setting this metadata when an interface config update has been performed + * and thus termination mac entries should not be removed. + * + * See org.onosproject.segmentrouting.RoutingRulePopulator#processSinglePortFiltersInternal + */ + public static final long INTERFACE_CONFIG_UPDATE = 1L << 1; + + /** + * SR is setting this metadata to signal the driver when the config is for the pair port, + * i.e. ports connecting two leaves. + * + * See org.onosproject.segmentrouting.RoutingRulePopulator#portType + */ + public static final long PAIR_PORT = 1L << 2; + + /** + * SR is setting this metadata to signal the driver when the config is for an edge port, + * i.e. ports facing an host. + * + * See org.onosproject.segmentrouting.policy.impl.PolicyManager#trafficMatchFwdObjective + * See org.onosproject.segmentrouting.RoutingRulePopulator#portType + */ + public static final long EDGE_PORT = 1L << 3; + + /** + * SR is setting this metadata to signal the driver when the config is for an infra port, + * i.e. ports connecting a leaf with a spine. + */ + public static final long INFRA_PORT = 1L << 4; + + public static final long METADATA_MASK = 0x1FL; + + public static final Map METADATA_TO_PORT_TYPE = ImmutableMap.builder() + .put(PAIR_PORT, PORT_TYPE_INFRA) + .put(EDGE_PORT, PORT_TYPE_EDGE) + .put(INFRA_PORT, PORT_TYPE_INFRA) + .build(); // hide default constructor private Constants() { diff --git a/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/FabricUtils.java b/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/FabricUtils.java index 4496f19073..5d89f99bf2 100644 --- a/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/FabricUtils.java +++ b/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/FabricUtils.java @@ -20,11 +20,15 @@ import org.onosproject.net.PortNumber; 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.MetadataCriterion; 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.flowobjective.DefaultNextTreatment; +import org.onosproject.net.flowobjective.FilteringObjective; +import org.onosproject.net.flowobjective.ForwardingObjective; import org.onosproject.net.flowobjective.NextTreatment; +import org.onosproject.net.flowobjective.Objective; import org.onosproject.net.pi.model.PiPipelineInterpreter; import org.onosproject.net.pi.model.PiTableId; @@ -34,6 +38,11 @@ import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkNotNull; import static java.lang.String.format; +import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.EDGE_PORT; +import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.INFRA_PORT; +import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.METADATA_MASK; +import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.METADATA_TO_PORT_TYPE; +import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PAIR_PORT; /** * Utility class with methods common to fabric pipeconf operations. @@ -123,4 +132,87 @@ public final class FabricUtils { throw new PiPipelineInterpreter.PiInterpreterException(format( "Invalid treatment for table '%s', %s: %s", tableId, explanation, treatment)); } + + /** + * Port type metadata conversion. + * + * @param obj the objective + * @return the port type associated to the metadata, null otherwise + */ + public static Byte portType(Objective obj) { + Byte portType = null; + if (isSrMetadataSet(obj, PAIR_PORT) && METADATA_TO_PORT_TYPE.containsKey(PAIR_PORT)) { + portType = METADATA_TO_PORT_TYPE.get(PAIR_PORT); + } else if (isSrMetadataSet(obj, EDGE_PORT) && METADATA_TO_PORT_TYPE.containsKey(EDGE_PORT)) { + portType = METADATA_TO_PORT_TYPE.get(EDGE_PORT); + } else if (isSrMetadataSet(obj, INFRA_PORT) && METADATA_TO_PORT_TYPE.containsKey(INFRA_PORT)) { + portType = METADATA_TO_PORT_TYPE.get(INFRA_PORT); + } + return portType; + } + + /** + * Check metadata passed from SegmentRouting app. + * + * @param obj the objective containing the metadata + * @return true if the objective contains valid metadata, false otherwise + */ + public static boolean isValidSrMetadata(Objective obj) { + long meta = 0; + if (obj instanceof FilteringObjective) { + FilteringObjective filtObj = (FilteringObjective) obj; + if (filtObj.meta() == null) { + return true; + } + Instructions.MetadataInstruction metaIns = filtObj.meta().writeMetadata(); + if (metaIns == null) { + return true; + } + meta = metaIns.metadata() & metaIns.metadataMask(); + } else if (obj instanceof ForwardingObjective) { + ForwardingObjective fwdObj = (ForwardingObjective) obj; + if (fwdObj.meta() == null) { + return true; + } + MetadataCriterion metaCrit = (MetadataCriterion) fwdObj.meta().getCriterion(Criterion.Type.METADATA); + if (metaCrit == null) { + return true; + } + meta = metaCrit.metadata(); + } + return meta != 0 && ((meta ^ METADATA_MASK) <= METADATA_MASK); + } + + /** + * Verify if a given flag has been set into the metadata. + * + * @param obj the objective containing the metadata + * @param flag the flag to verify + * @return true if the flag is set, false otherwise + */ + public static boolean isSrMetadataSet(Objective obj, long flag) { + long meta = 0; + if (obj instanceof FilteringObjective) { + FilteringObjective filtObj = (FilteringObjective) obj; + if (filtObj.meta() == null) { + return false; + } + Instructions.MetadataInstruction metaIns = filtObj.meta().writeMetadata(); + if (metaIns == null) { + return false; + } + meta = metaIns.metadata() & metaIns.metadataMask(); + } else if (obj instanceof ForwardingObjective) { + ForwardingObjective fwdObj = (ForwardingObjective) obj; + if (fwdObj.meta() == null) { + return false; + } + MetadataCriterion metaCrit = (MetadataCriterion) fwdObj.meta().getCriterion(Criterion.Type.METADATA); + if (metaCrit == null) { + return false; + } + meta = metaCrit.metadata(); + } + return (meta & flag) == flag; + } } 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 bfdcc2ba19..387230b5f2 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,7 +32,6 @@ import org.onosproject.net.flow.criteria.EthCriterion; 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.L2SubType; import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction; import org.onosproject.net.flowobjective.FilteringObjective; @@ -54,21 +53,21 @@ import static org.onosproject.net.flow.criteria.Criterion.Type.VLAN_VID; import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_ID; import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_POP; import static org.onosproject.net.pi.model.PiPipelineInterpreter.PiInterpreterException; -import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.DEFAULT_VLAN; -import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.DEFAULT_PW_TRANSPORT_VLAN; +import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.CLEANUP_DOUBLE_TAGGED_HOST_ENTRIES; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.ETH_TYPE_EXACT_MASK; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.FWD_MPLS; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.FWD_IPV4_ROUTING; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.FWD_IPV6_ROUTING; +import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.INTERFACE_CONFIG_UPDATE; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.ONE; -import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PORT_TYPE_EDGE; -import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PORT_TYPE_INFRA; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.ZERO; +import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.isSrMetadataSet; +import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.isValidSrMetadata; +import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.portType; import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.l2InstructionOrFail; import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.criterion; import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.l2Instruction; - /** * ObjectiveTranslator implementation for FilteringObjective. */ @@ -79,8 +78,6 @@ class FilteringObjectiveTranslator .withId(FabricConstants.FABRIC_INGRESS_FILTERING_DENY) .build(); - private static final int INTERFACE_CONFIG_UPDATE = 2; - FilteringObjectiveTranslator(DeviceId deviceId, FabricCapabilities capabilities) { super(deviceId, capabilities); } @@ -98,6 +95,12 @@ class FilteringObjectiveTranslator ObjectiveError.BADPARAMS); } + if (!isValidSrMetadata(obj)) { + throw new FabricPipelinerException( + format("Unsupported metadata configuration: metadata=%s", obj.meta()), + ObjectiveError.BADPARAMS); + } + final PortCriterion inPort = (PortCriterion) obj.key(); final VlanIdCriterion outerVlan = (VlanIdCriterion) criterion( @@ -134,44 +137,9 @@ class FilteringObjectiveTranslator // AND it is a port REMOVE event OR // - it refers to double tagged traffic // and SR is triggering the removal of forwarding classifier rules. - return (obj.op() == Objective.Operation.ADD && !isInterfaceConfigUpdate(obj)) || - (!isDoubleTagged(obj) && !isInterfaceConfigUpdate(obj)) || - (isDoubleTagged(obj) && isLastDoubleTaggedForPort(obj)); - } - - /** - * Check if the given filtering objective is triggered by a interface config change. - * - * @param obj Filtering objective to check. - * @return True if SR is signaling to not remove the forwarding classifier rule, - * false otherwise. - */ - private boolean isInterfaceConfigUpdate(FilteringObjective obj) { - if (obj.meta() == null) { - return false; - } - Instructions.MetadataInstruction meta = obj.meta().writeMetadata(); - // SR is setting this metadata when an interface config update has - // been performed and thus fwd classifier rules should not be removed - return (meta != null && (meta.metadata() & meta.metadataMask()) == INTERFACE_CONFIG_UPDATE); - } - - /** - * Check if the given filtering objective is the last filtering objective - * for a double-tagged host for a specific port. - *

- * {@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); + return (obj.op() == Objective.Operation.ADD && !isSrMetadataSet(obj, INTERFACE_CONFIG_UPDATE)) || + (!isDoubleTagged(obj) && !isSrMetadataSet(obj, INTERFACE_CONFIG_UPDATE)) || + (isDoubleTagged(obj) && isSrMetadataSet(obj, CLEANUP_DOUBLE_TAGGED_HOST_ENTRIES)); } private boolean isDoubleTagged(FilteringObjective obj) { @@ -218,15 +186,12 @@ class FilteringObjectiveTranslator if (obj.type().equals(FilteringObjective.Type.DENY)) { treatmentBuilder.piTableAction(DENY); } else { - byte portType = PORT_TYPE_EDGE; - if (!innerVlanValid && outerVlanValid && - outerVlanCriterion.vlanId().toShort() == DEFAULT_PW_TRANSPORT_VLAN) { - portType = PORT_TYPE_INFRA; - } else if (obj.meta() != null) { - ModVlanIdInstruction modVlanIdInstruction = (ModVlanIdInstruction) l2Instruction(obj.meta(), VLAN_ID); - if (modVlanIdInstruction != null && modVlanIdInstruction.vlanId().toShort() == DEFAULT_VLAN) { - portType = PORT_TYPE_INFRA; - } + // FIXME SDFAB-52 to complete the work on metadata + Byte portType = portType(obj); + if (portType == null) { + throw new FabricPipelinerException( + format("Unsupported port_type configuration: metadata=%s", obj.meta()), + ObjectiveError.BADPARAMS); } try { treatmentBuilder.piTableAction(mapFilteringTreatment(obj.meta(), diff --git a/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/ForwardingObjectiveTranslator.java b/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/ForwardingObjectiveTranslator.java index d5272286b3..e0c7ec1037 100644 --- a/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/ForwardingObjectiveTranslator.java +++ b/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/ForwardingObjectiveTranslator.java @@ -32,7 +32,6 @@ 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.IPCriterion; -import org.onosproject.net.flow.criteria.MetadataCriterion; import org.onosproject.net.flow.criteria.MplsCriterion; import org.onosproject.net.flow.criteria.PiCriterion; import org.onosproject.net.flow.criteria.VlanIdCriterion; @@ -59,6 +58,10 @@ import java.util.stream.Collectors; import static java.lang.String.format; import static org.onosproject.net.group.DefaultGroupBucket.createCloneGroupBucket; +import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PAIR_PORT; +import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.isSrMetadataSet; +import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.isValidSrMetadata; +import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.portType; import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.criterionNotNull; import static org.onosproject.pipelines.fabric.impl.behaviour.FabricUtils.outputPort; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PORT_TYPE_MASK; @@ -119,6 +122,13 @@ class ForwardingObjectiveTranslator @Override public ObjectiveTranslation doTranslate(ForwardingObjective obj) throws FabricPipelinerException { + + if (!isValidSrMetadata(obj)) { + throw new FabricPipelinerException( + format("Unsupported metadata configuration: metadata=%s", obj.meta()), + ObjectiveError.BADPARAMS); + } + final ObjectiveTranslation.Builder resultBuilder = ObjectiveTranslation.builder(); switch (obj.flag()) { @@ -299,11 +309,11 @@ class ForwardingObjectiveTranslator } TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder(obj.selector()); // Meta are used to signal the port type which can be edge or infra - if (obj.meta() != null && obj.meta().getCriterion(Criterion.Type.METADATA) != null) { - long portType = ((MetadataCriterion) obj.meta().getCriterion(Criterion.Type.METADATA)).metadata(); + Byte portType = portType(obj); + if (portType != null && !isSrMetadataSet(obj, PAIR_PORT)) { if (portType == PORT_TYPE_EDGE || portType == PORT_TYPE_INFRA) { selectorBuilder.matchPi(PiCriterion.builder() - .matchTernary(FabricConstants.HDR_PORT_TYPE, portType, PORT_TYPE_MASK) + .matchTernary(FabricConstants.HDR_PORT_TYPE, (long) portType, PORT_TYPE_MASK) .build()); } else { throw new FabricPipelinerException(format("Port type '%s' is not allowed for table '%s'", diff --git a/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/FilteringObjectiveTranslatorTest.java b/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/FilteringObjectiveTranslatorTest.java index 73039b5382..5e126cccd9 100644 --- a/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/FilteringObjectiveTranslatorTest.java +++ b/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/FilteringObjectiveTranslatorTest.java @@ -46,11 +46,14 @@ import java.util.List; import static org.junit.Assert.assertEquals; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.DEFAULT_PW_TRANSPORT_VLAN; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.DEFAULT_VLAN; +import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.EDGE_PORT; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.ETH_TYPE_EXACT_MASK; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.FWD_IPV4_ROUTING; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.FWD_IPV6_ROUTING; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.FWD_MPLS; +import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.INFRA_PORT; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.ONE; +import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PAIR_PORT; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PORT_TYPE_EDGE; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PORT_TYPE_INFRA; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.ZERO; @@ -75,7 +78,7 @@ public class FilteringObjectiveTranslatorTest extends BaseObjectiveTranslatorTes */ @Test public void testRouterMacAndVlanFilter() throws FabricPipelinerException { - FilteringObjective filteringObjective = buildFilteringObjective(ROUTER_MAC); + FilteringObjective filteringObjective = buildFilteringObjective(ROUTER_MAC, EDGE_PORT); ObjectiveTranslation actualTranslation = translator.translate(filteringObjective); Collection expectedFlowRules = Lists.newArrayList(); // in port vlan flow rule @@ -137,6 +140,7 @@ public class FilteringObjectiveTranslatorTest extends BaseObjectiveTranslatorTes TrafficTreatment treatment = DefaultTrafficTreatment.builder() .pushVlan() .setVlanId(VLAN_100) + .writeMetadata(EDGE_PORT, 0xffffffffffffffffL) .build(); FilteringObjective filteringObjective = DefaultFilteringObjective.builder() .permit() @@ -182,6 +186,7 @@ public class FilteringObjectiveTranslatorTest extends BaseObjectiveTranslatorTes TrafficTreatment treatment = DefaultTrafficTreatment.builder() .pushVlan() .setVlanId(VLAN_100) + .writeMetadata(EDGE_PORT, 0xffffffffffffffffL) .build(); FilteringObjective filteringObjective = DefaultFilteringObjective.builder() .permit() @@ -223,7 +228,7 @@ public class FilteringObjectiveTranslatorTest extends BaseObjectiveTranslatorTes */ @Test public void testFwdBridging() throws Exception { - FilteringObjective filteringObjective = buildFilteringObjective(null); + FilteringObjective filteringObjective = buildFilteringObjective(null, EDGE_PORT); ObjectiveTranslation actualTranslation = translator.translate(filteringObjective); // in port vlan flow rule @@ -300,8 +305,9 @@ public class FilteringObjectiveTranslatorTest extends BaseObjectiveTranslatorTes .withPriority(PRIORITY) .fromApp(APP_ID) .withMeta(DefaultTrafficTreatment.builder() - .popVlan() - .build()) + .popVlan() + .writeMetadata(EDGE_PORT, 0xffffffffffffffffL) + .build()) .permit() .add(); ObjectiveTranslation actualTranslation = translator.translate(filteringObjective); @@ -369,7 +375,7 @@ public class FilteringObjectiveTranslatorTest extends BaseObjectiveTranslatorTes .withPriority(PRIORITY) .fromApp(APP_ID) .withMeta(DefaultTrafficTreatment.builder() - .writeMetadata(2, 0xffffffffffffffffL) + .writeMetadata(10, 0xffffffffffffffffL) .build()) .permit() .add(); @@ -392,7 +398,7 @@ public class FilteringObjectiveTranslatorTest extends BaseObjectiveTranslatorTes .withMeta(DefaultTrafficTreatment.builder() .pushVlan() .setVlanId(VLAN_200) - .writeMetadata(2, 0xffffffffffffffffL) + .writeMetadata(10, 0xffffffffffffffffL) .build()) .permit() .add(); @@ -418,7 +424,10 @@ public class FilteringObjectiveTranslatorTest extends BaseObjectiveTranslatorTes .addCondition(Criteria.matchVlanId(VLAN_100)) .withPriority(PRIORITY) .fromApp(APP_ID) - .withMeta(DefaultTrafficTreatment.builder().wipeDeferred().build()) + .withMeta(DefaultTrafficTreatment.builder() + .writeMetadata(EDGE_PORT, 0xffffffffffffffffL) + .wipeDeferred() + .build()) .permit() .add(); ObjectiveTranslation actualTranslation = translator.translate(filteringObjective); @@ -464,6 +473,9 @@ public class FilteringObjectiveTranslatorTest extends BaseObjectiveTranslatorTes .addCondition(Criteria.matchEthDst(ROUTER_MAC)) .addCondition(Criteria.matchVlanId(VlanId.vlanId((short) DEFAULT_PW_TRANSPORT_VLAN))) .withPriority(PRIORITY) + .withMeta(DefaultTrafficTreatment.builder() + .writeMetadata(INFRA_PORT, 0xffffffffffffffffL) + .build()) .fromApp(APP_ID) .permit() .add(); @@ -505,6 +517,7 @@ public class FilteringObjectiveTranslatorTest extends BaseObjectiveTranslatorTes .withMeta(DefaultTrafficTreatment.builder() .pushVlan() .setVlanId(VlanId.vlanId((short) DEFAULT_VLAN)) + .writeMetadata(INFRA_PORT, 0xffffffffffffffffL) .build()) .permit() .add(); @@ -536,6 +549,74 @@ public class FilteringObjectiveTranslatorTest extends BaseObjectiveTranslatorTes assertEquals(expectedTranslation, actualTranslation); } + /** + * Test is pair port scenarios for filtering objective. + */ + @Test + public void testIsPairPort() throws FabricPipelinerException { + // Only pair port flag + FilteringObjective filteringObjective = DefaultFilteringObjective.builder() + .withKey(Criteria.matchInPort(PORT_1)) + .addCondition(Criteria.matchEthDst(ROUTER_MAC)) + .addCondition(Criteria.matchVlanId(VLAN_100)) + .withPriority(PRIORITY) + .withMeta(DefaultTrafficTreatment.builder() + .writeMetadata(PAIR_PORT, 0xffffffffffffffffL) + .build()) + .fromApp(APP_ID) + .permit() + .add(); + ObjectiveTranslation actualTranslation = translator.translate(filteringObjective); + + Collection expectedFlowRules = Lists.newArrayList(); + expectedFlowRules.add(buildExpectedVlanInPortRule( + PORT_1, VLAN_100, null, VlanId.NONE, + PORT_TYPE_INFRA, FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN)); + expectedFlowRules.addAll(buildExpectedFwdClassifierRule( + PORT_1, + ROUTER_MAC, + null, + Ethernet.TYPE_IPV4, + FWD_IPV4_ROUTING)); + expectedFlowRules.addAll(buildExpectedFwdClassifierRule( + PORT_1, + ROUTER_MAC, + null, + Ethernet.TYPE_IPV6, + FWD_IPV6_ROUTING)); + expectedFlowRules.addAll(buildExpectedFwdClassifierRule( + PORT_1, + ROUTER_MAC, + null, + Ethernet.MPLS_UNICAST, + FWD_MPLS)); + + ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules); + assertEquals(expectedTranslation, actualTranslation); + + // Pair port and config update flags + filteringObjective = DefaultFilteringObjective.builder() + .withKey(Criteria.matchInPort(PORT_1)) + .addCondition(Criteria.matchEthDst(ROUTER_MAC)) + .addCondition(Criteria.matchVlanId(VLAN_100)) + .withPriority(PRIORITY) + .fromApp(APP_ID) + .withMeta(DefaultTrafficTreatment.builder() + .writeMetadata(6, 0xffffffffffffffffL) + .build()) + .permit() + .add(); + + actualTranslation = translator.translate(filteringObjective); + expectedFlowRules = Lists.newArrayList(); + // Ingress port vlan rule + expectedFlowRules.add(buildExpectedVlanInPortRule( + PORT_1, VLAN_100, null, VlanId.NONE, PORT_TYPE_INFRA, + FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN)); + expectedTranslation = buildExpectedTranslation(expectedFlowRules); + assertEquals(expectedTranslation, actualTranslation); + } + /* Utilities */ private void assertError(ObjectiveError error, ObjectiveTranslation actualTranslation) { @@ -543,10 +624,11 @@ public class FilteringObjectiveTranslatorTest extends BaseObjectiveTranslatorTes assertEquals(expectedTranslation, actualTranslation); } - private FilteringObjective buildFilteringObjective(MacAddress dstMac) { + private FilteringObjective buildFilteringObjective(MacAddress dstMac, long portType) { TrafficTreatment treatment = DefaultTrafficTreatment.builder() .pushVlan() .setVlanId(VLAN_100) + .writeMetadata(portType, 0xffffffffffffffffL) .build(); DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder() .permit() diff --git a/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/ForwardingObjectiveTranslatorTest.java b/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/ForwardingObjectiveTranslatorTest.java index dfae0df4a5..94517bf62f 100644 --- a/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/ForwardingObjectiveTranslatorTest.java +++ b/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/ForwardingObjectiveTranslatorTest.java @@ -53,6 +53,8 @@ import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.EDGE_PORT; +import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.INFRA_PORT; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PORT_TYPE_EDGE; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PORT_TYPE_INFRA; import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PORT_TYPE_MASK; @@ -246,7 +248,7 @@ public class ForwardingObjectiveTranslatorTest extends BaseObjectiveTranslatorTe .matchIPDst(IPV4_UNICAST_ADDR) .build(); TrafficSelector metaSelector = DefaultTrafficSelector.builder() - .matchMetadata(PORT_TYPE_EDGE) + .matchMetadata(EDGE_PORT) .build(); ForwardingObjective fwd = DefaultForwardingObjective.builder() .withSelector(selector) @@ -291,7 +293,7 @@ public class ForwardingObjectiveTranslatorTest extends BaseObjectiveTranslatorTe assertTrue(expectedFlowRule.exactMatch(actualFlowRule)); metaSelector = DefaultTrafficSelector.builder() - .matchMetadata(PORT_TYPE_INFRA) + .matchMetadata(INFRA_PORT) .build(); fwd = DefaultForwardingObjective.builder() .withSelector(selector)