[SDFAB-102] Backport changes required for policies to fabric.p4 (Redirect)

Change-Id: I357c908d31abad9c3f8d74723d937ea948e54808
diff --git a/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/FabricInterpreterTest.java b/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/FabricInterpreterTest.java
index 2ea8b29..3852629 100644
--- a/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/FabricInterpreterTest.java
+++ b/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/FabricInterpreterTest.java
@@ -69,78 +69,6 @@
         interpreter = new FabricInterpreter(allCapabilities);
     }
 
-    /* Filtering control block */
-
-    /**
-     * Map treatment to push_internal_vlan action.
-     */
-    @Test
-    public void testFilteringTreatmentPermitWithInternalVlan() throws Exception {
-        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                .pushVlan()
-                .setVlanId(VLAN_100)
-                .build();
-        PiAction mappedAction = interpreter.mapTreatment(treatment,
-                                                         FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
-        PiActionParam param = new PiActionParam(FabricConstants.VLAN_ID,
-                                                ImmutableByteSequence.copyFrom(VLAN_100.toShort()));
-        PiAction expectedAction = PiAction.builder()
-                .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT_WITH_INTERNAL_VLAN)
-                .withParameter(param)
-                .build();
-
-        assertEquals(expectedAction, mappedAction);
-    }
-
-    /**
-     * Map empty treatment to permit action.
-     */
-    @Test
-    public void testFilteringTreatmentPermit() throws Exception {
-        TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
-        PiAction mappedAction = interpreter.mapTreatment(treatment,
-                                                         FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
-        PiAction expectedAction = PiAction.builder()
-                .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT)
-                .build();
-
-        assertEquals(expectedAction, mappedAction);
-    }
-
-    /**
-     * Map empty treatment and wipeDeferred to permit action.
-     */
-    @Test
-    public void testFilteringTreatmentPermit2() throws Exception {
-        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                .wipeDeferred()
-                .build();
-        PiAction mappedAction = interpreter.mapTreatment(treatment,
-                FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
-        PiAction expectedAction = PiAction.builder()
-                .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT)
-                .build();
-
-        assertEquals(expectedAction, mappedAction);
-    }
-
-    /**
-     * Map popVlan to permit action.
-     */
-    @Test
-    public void testFilteringTreatmentPermit3() throws Exception {
-        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                .popVlan()
-                .build();
-        PiAction mappedAction = interpreter.mapTreatment(treatment,
-                FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
-        PiAction expectedAction = PiAction.builder()
-                .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT)
-                .build();
-
-        assertEquals(expectedAction, mappedAction);
-    }
-
     /* Forwarding control block */
 
     /**
@@ -230,45 +158,39 @@
     }
 
     /**
-     * Map treatment for hashed table to routing v4 action.
+     * Map treatment to set_vlan_output action.
      */
     @Test
-    public void testNextTreatmentHashedRoutingMpls() throws Exception {
+    public void testNextVlanTreatment() throws Exception {
         TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                .setEthSrc(SRC_MAC)
-                .setEthDst(DST_MAC)
-                .setOutput(PORT_1)
-                .pushMpls()
-                .setMpls(MPLS_10)
+                .setVlanId(VLAN_100)
                 .build();
         PiAction mappedAction = interpreter.mapTreatment(
-                treatment, FabricConstants.FABRIC_INGRESS_NEXT_HASHED);
-        PiActionParam ethSrcParam = new PiActionParam(FabricConstants.SMAC, SRC_MAC.toBytes());
-        PiActionParam ethDstParam = new PiActionParam(FabricConstants.DMAC, DST_MAC.toBytes());
-        PiActionParam portParam = new PiActionParam(FabricConstants.PORT_NUM, PORT_1.toLong());
-        PiActionParam mplsParam = new PiActionParam(FabricConstants.LABEL, MPLS_10.toInt());
+                treatment, FabricConstants.FABRIC_INGRESS_PRE_NEXT_NEXT_VLAN);
+        PiActionParam vlanParam = new PiActionParam(
+                FabricConstants.VLAN_ID, VLAN_100.toShort());
         PiAction expectedAction = PiAction.builder()
-                .withId(FabricConstants.FABRIC_INGRESS_NEXT_MPLS_ROUTING_HASHED)
-                .withParameters(ImmutableList.of(ethSrcParam, ethDstParam, portParam, mplsParam))
+                .withId(FabricConstants.FABRIC_INGRESS_PRE_NEXT_SET_VLAN)
+                .withParameter(vlanParam)
                 .build();
         assertEquals(expectedAction, mappedAction);
     }
 
     /**
-     * Map treatment to set_vlan_output action.
+     * Map treatment to set_mpls action.
      */
     @Test
-    public void testNextTreatment3() throws Exception {
+    public void testNextMplsTreatment() throws Exception {
         TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                .setVlanId(VLAN_100)
+                .setMpls(MPLS_10)
                 .build();
         PiAction mappedAction = interpreter.mapTreatment(
-                treatment, FabricConstants.FABRIC_INGRESS_NEXT_NEXT_VLAN);
-        PiActionParam vlanParam = new PiActionParam(
-                FabricConstants.VLAN_ID, VLAN_100.toShort());
+                treatment, FabricConstants.FABRIC_INGRESS_PRE_NEXT_NEXT_MPLS);
+        PiActionParam mplsParam = new PiActionParam(
+                FabricConstants.LABEL, MPLS_10.toInt());
         PiAction expectedAction = PiAction.builder()
-                .withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_VLAN)
-                .withParameter(vlanParam)
+                .withId(FabricConstants.FABRIC_INGRESS_PRE_NEXT_SET_MPLS_LABEL)
+                .withParameter(mplsParam)
                 .build();
         assertEquals(expectedAction, mappedAction);
     }
diff --git a/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/BaseObjectiveTranslatorTest.java b/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/BaseObjectiveTranslatorTest.java
index 72f49be..5015d4e 100644
--- a/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/BaseObjectiveTranslatorTest.java
+++ b/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/BaseObjectiveTranslatorTest.java
@@ -44,6 +44,8 @@
     static final VlanId VLAN_200 = VlanId.vlanId("200");
     static final MacAddress HOST_MAC = MacAddress.valueOf("00:00:00:00:00:01");
     static final MacAddress ROUTER_MAC = MacAddress.valueOf("00:00:00:00:02:01");
+    static final MacAddress SPINE1_MAC = MacAddress.valueOf("00:00:00:00:03:01");
+    static final MacAddress SPINE2_MAC = MacAddress.valueOf("00:00:00:00:03:02");
     static final IpPrefix IPV4_UNICAST_ADDR = IpPrefix.valueOf("10.0.0.1/32");
     static final IpPrefix IPV4_MCAST_ADDR = IpPrefix.valueOf("224.0.0.1/32");
     static final IpPrefix IPV6_UNICAST_ADDR = IpPrefix.valueOf("2000::1/32");
diff --git a/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/FabricPipelinerTest.java b/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/FabricPipelinerTest.java
index a2fa47b..d3a7c5c 100644
--- a/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/FabricPipelinerTest.java
+++ b/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/FabricPipelinerTest.java
@@ -49,6 +49,7 @@
 import static org.easymock.EasyMock.reset;
 import static org.easymock.EasyMock.verify;
 import static org.junit.Assert.assertTrue;
+import static org.onosproject.pipelines.fabric.impl.behaviour.Constants.PORT_TYPE_INTERNAL;
 
 public class FabricPipelinerTest {
 
@@ -95,6 +96,7 @@
                 .piTableAction(PiAction.builder()
                         .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT_WITH_INTERNAL_VLAN)
                         .withParameter(new PiActionParam(FabricConstants.VLAN_ID, DEFAULT_VLAN))
+                        .withParameter(new PiActionParam(FabricConstants.PORT_TYPE, PORT_TYPE_INTERNAL))
                         .build())
                 .build();
         final FlowRule expectedCpuIgVlanRule = DefaultFlowRule.builder()
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 71e45b1..73039b5 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
@@ -44,15 +44,22 @@
 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.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.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;
 
 /**
  * Test cases for fabric.p4 pipeline filtering control block.
  */
 public class FilteringObjectiveTranslatorTest extends BaseObjectiveTranslatorTest {
 
-    public static final byte[] ONE = {1};
-    public static final byte[] ZERO = {0};
-    public static final short EXACT_MATCH_ETH_TYPE = (short) 0xFFFF;
     private FilteringObjectiveTranslator translator;
 
     @Before
@@ -77,6 +84,7 @@
                 VlanId.NONE,
                 VlanId.NONE,
                 VLAN_100,
+                PORT_TYPE_EDGE,
                 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
 
         // forwarding classifier ipv4
@@ -85,7 +93,7 @@
                 ROUTER_MAC,
                 null,
                 Ethernet.TYPE_IPV4,
-                FilteringObjectiveTranslator.FWD_IPV4_ROUTING));
+                FWD_IPV4_ROUTING));
 
         // forwarding classifier ipv6
         expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
@@ -93,7 +101,7 @@
                 ROUTER_MAC,
                 null,
                 Ethernet.TYPE_IPV6,
-                FilteringObjectiveTranslator.FWD_IPV6_ROUTING));
+                FWD_IPV6_ROUTING));
 
         // forwarding classifier mpls
         expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
@@ -101,7 +109,7 @@
                 ROUTER_MAC,
                 null,
                 Ethernet.MPLS_UNICAST,
-                FilteringObjectiveTranslator.FWD_MPLS));
+                FWD_MPLS));
 
 //        ObjectiveTranslation.Builder expectedTranslationBuilder = ObjectiveTranslation.builder()
 //                .addFlowRule(inportFlowRuleExpected);
@@ -148,6 +156,7 @@
                 VlanId.NONE,
                 VlanId.NONE,
                 VLAN_100,
+                PORT_TYPE_EDGE,
                 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
 
         // forwarding classifier
@@ -156,7 +165,7 @@
                 MacAddress.IPV4_MULTICAST,
                 MacAddress.IPV4_MULTICAST_MASK,
                 Ethernet.TYPE_IPV4,
-                FilteringObjectiveTranslator.FWD_IPV4_ROUTING));
+                FWD_IPV4_ROUTING));
 
         ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules);
 
@@ -192,6 +201,7 @@
                 VlanId.NONE,
                 VlanId.NONE,
                 VLAN_100,
+                PORT_TYPE_EDGE,
                 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
 
         flowRules.addAll(buildExpectedFwdClassifierRule(
@@ -199,7 +209,7 @@
                 MacAddress.IPV6_MULTICAST,
                 MacAddress.IPV6_MULTICAST_MASK,
                 Ethernet.TYPE_IPV6,
-                FilteringObjectiveTranslator.FWD_IPV6_ROUTING));
+                FWD_IPV6_ROUTING));
 
         ObjectiveTranslation expectedTranslation = buildExpectedTranslation(flowRules);
 
@@ -222,6 +232,7 @@
                 VlanId.NONE,
                 VlanId.NONE,
                 VLAN_100,
+                PORT_TYPE_EDGE,
                 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN);
 
         // No rules in forwarding classifier, will do default action: set fwd type to bridging
@@ -297,18 +308,18 @@
         Collection<FlowRule> expectedFlowRules = Lists.newArrayList();
         // Ingress port vlan rule
         expectedFlowRules.add(buildExpectedVlanInPortRule(
-                PORT_1, VLAN_100, VLAN_200, VlanId.NONE,
+                PORT_1, VLAN_100, VLAN_200, VlanId.NONE, PORT_TYPE_EDGE,
                 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
         // Forwarding classifier rules (ipv6, ipv4, mpls)
         expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
                 PORT_1, ROUTER_MAC, null, Ethernet.TYPE_IPV4,
-                FilteringObjectiveTranslator.FWD_IPV4_ROUTING));
+                FWD_IPV4_ROUTING));
         expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
                 PORT_1, ROUTER_MAC, null, Ethernet.TYPE_IPV6,
-                FilteringObjectiveTranslator.FWD_IPV6_ROUTING));
+                FWD_IPV6_ROUTING));
         expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
                 PORT_1, ROUTER_MAC, null, Ethernet.MPLS_UNICAST,
-                FilteringObjectiveTranslator.FWD_MPLS));
+                FWD_MPLS));
         ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules);
 
         assertEquals(expectedTranslation, actualTranslation);
@@ -349,7 +360,7 @@
      * ingress_port_vlan table.
      */
     @Test
-    public void testPortUpdate() throws FabricPipelinerException {
+    public void testIsPortUpdate() throws FabricPipelinerException {
         // Tagged port scenario
         FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
                 .withKey(Criteria.matchInPort(PORT_1))
@@ -366,7 +377,7 @@
         Collection<FlowRule> expectedFlowRules = Lists.newArrayList();
         // Ingress port vlan rule
         expectedFlowRules.add(buildExpectedVlanInPortRule(
-                PORT_1, VLAN_100, null, VlanId.NONE,
+                PORT_1, VLAN_100, null, VlanId.NONE, PORT_TYPE_EDGE,
                 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
         ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules);
         assertEquals(expectedTranslation, actualTranslation);
@@ -389,7 +400,7 @@
         expectedFlowRules = Lists.newArrayList();
         // Ingress port vlan rule
         expectedFlowRules.add(buildExpectedVlanInPortRule(
-                PORT_1, VlanId.NONE, null, VLAN_200,
+                PORT_1, VlanId.NONE, null, VLAN_200, PORT_TYPE_EDGE,
                 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
         expectedTranslation = buildExpectedTranslation(expectedFlowRules);
         assertEquals(expectedTranslation, actualTranslation);
@@ -414,7 +425,7 @@
         Collection<FlowRule> expectedFlowRules = Lists.newArrayList();
         // Ingress port vlan rule
         expectedFlowRules.add(buildExpectedVlanInPortRule(
-                PORT_1, VLAN_100, null, VlanId.NONE,
+                PORT_1, VLAN_100, null, VlanId.NONE, PORT_TYPE_EDGE,
                 FabricConstants.FABRIC_INGRESS_FILTERING_INGRESS_PORT_VLAN));
         // forwarding classifier ipv4
         expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
@@ -422,26 +433,109 @@
                 ROUTER_MAC,
                 null,
                 Ethernet.TYPE_IPV4,
-                FilteringObjectiveTranslator.FWD_IPV4_ROUTING));
+                FWD_IPV4_ROUTING));
         // forwarding classifier ipv6
         expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
                 PORT_1,
                 ROUTER_MAC,
                 null,
                 Ethernet.TYPE_IPV6,
-                FilteringObjectiveTranslator.FWD_IPV6_ROUTING));
+                FWD_IPV6_ROUTING));
         // forwarding classifier mpls
         expectedFlowRules.addAll(buildExpectedFwdClassifierRule(
                 PORT_1,
                 ROUTER_MAC,
                 null,
                 Ethernet.MPLS_UNICAST,
-                FilteringObjectiveTranslator.FWD_MPLS));
+                FWD_MPLS));
 
         ObjectiveTranslation expectedTranslation = buildExpectedTranslation(expectedFlowRules);
         assertEquals(expectedTranslation, actualTranslation);
     }
 
+    /**
+     * Test is infra port scenarios for filtering objective.
+     */
+    @Test
+    public void testIsInfraPort() throws FabricPipelinerException {
+        // PW transport vlan
+        FilteringObjective filteringObjective = DefaultFilteringObjective.builder()
+                .withKey(Criteria.matchInPort(PORT_1))
+                .addCondition(Criteria.matchEthDst(ROUTER_MAC))
+                .addCondition(Criteria.matchVlanId(VlanId.vlanId((short) DEFAULT_PW_TRANSPORT_VLAN)))
+                .withPriority(PRIORITY)
+                .fromApp(APP_ID)
+                .permit()
+                .add();
+        ObjectiveTranslation actualTranslation = translator.translate(filteringObjective);
+
+        Collection<FlowRule> expectedFlowRules = Lists.newArrayList();
+        expectedFlowRules.add(buildExpectedVlanInPortRule(
+                PORT_1, VlanId.vlanId((short) DEFAULT_PW_TRANSPORT_VLAN), 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);
+
+        // Untagged port scenario
+        filteringObjective = DefaultFilteringObjective.builder()
+                .withKey(Criteria.matchInPort(PORT_1))
+                .addCondition(Criteria.matchEthDst(ROUTER_MAC))
+                .addCondition(Criteria.matchVlanId(VlanId.NONE))
+                .withPriority(PRIORITY)
+                .fromApp(APP_ID)
+                .withMeta(DefaultTrafficTreatment.builder()
+                        .pushVlan()
+                        .setVlanId(VlanId.vlanId((short) DEFAULT_VLAN))
+                        .build())
+                .permit()
+                .add();
+        actualTranslation = translator.translate(filteringObjective);
+        expectedFlowRules = Lists.newArrayList();
+        expectedFlowRules.add(buildExpectedVlanInPortRule(
+                PORT_1, null, null, VlanId.vlanId((short) DEFAULT_VLAN),
+                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));
+
+        expectedTranslation = buildExpectedTranslation(expectedFlowRules);
+        assertEquals(expectedTranslation, actualTranslation);
+    }
+
     /* Utilities */
 
     private void assertError(ObjectiveError error, ObjectiveTranslation actualTranslation) {
@@ -473,6 +567,7 @@
                                                  VlanId vlanId,
                                                  VlanId innerVlanId,
                                                  VlanId internalVlan,
+                                                 byte portType,
                                                  TableId tableId) {
 
         TrafficSelector.Builder selector = DefaultTrafficSelector.builder()
@@ -482,8 +577,8 @@
         if (!vlanValid(vlanId)) {
             piAction = PiAction.builder()
                     .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT_WITH_INTERNAL_VLAN)
-                    .withParameter(new PiActionParam(
-                            FabricConstants.VLAN_ID, internalVlan.toShort()))
+                    .withParameter(new PiActionParam(FabricConstants.VLAN_ID, internalVlan.toShort()))
+                    .withParameter(new PiActionParam(FabricConstants.PORT_TYPE, portType))
                     .build();
         } else {
             selector.matchVlanId(vlanId);
@@ -492,6 +587,7 @@
             }
             piAction = PiAction.builder()
                     .withId(FabricConstants.FABRIC_INGRESS_FILTERING_PERMIT)
+                    .withParameter(new PiActionParam(FabricConstants.PORT_TYPE, portType))
                     .build();
         }
 
@@ -567,13 +663,13 @@
         Collection<FlowRule> flowRules = Lists.newArrayList();
         TrafficSelector selectorIpv4 = selectorBuilder
                 .add(PiCriterion.builder()
-                             .matchTernary(FabricConstants.HDR_ETH_TYPE, Ethernet.MPLS_UNICAST, EXACT_MATCH_ETH_TYPE)
+                             .matchTernary(FabricConstants.HDR_ETH_TYPE, Ethernet.MPLS_UNICAST, ETH_TYPE_EXACT_MASK)
                              .matchExact(FabricConstants.HDR_IP_ETH_TYPE, Ethernet.TYPE_IPV4)
                              .build())
                 .build();
         TrafficSelector selectorIpv6 = selectorBuilder
                 .add(PiCriterion.builder()
-                             .matchTernary(FabricConstants.HDR_ETH_TYPE, Ethernet.MPLS_UNICAST, EXACT_MATCH_ETH_TYPE)
+                             .matchTernary(FabricConstants.HDR_ETH_TYPE, Ethernet.MPLS_UNICAST, ETH_TYPE_EXACT_MASK)
                              .matchExact(FabricConstants.HDR_IP_ETH_TYPE, Ethernet.TYPE_IPV6)
                              .build())
                 .build();
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 14253e7..dfae0df 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
@@ -34,6 +34,7 @@
 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.PiCriterion;
 import org.onosproject.net.flowobjective.DefaultForwardingObjective;
 import org.onosproject.net.flowobjective.ForwardingObjective;
 import org.onosproject.net.group.DefaultGroupBucket;
@@ -52,6 +53,9 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+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;
 
 /**
  * Test cases for fabric.p4 pipeline forwarding control block.
@@ -185,7 +189,150 @@
 
         assertTrue(expectedFlowRule.exactMatch(actualFlowRule));
     }
-/**
+
+    /**
+     * Test versatile flag of forwarding objective with next step.
+     */
+    @Test
+    public void testAclNext() {
+        // ACL 8-tuples
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchEthType(Ethernet.TYPE_IPV4)
+                .matchIPDst(IPV4_UNICAST_ADDR)
+                .build();
+        ForwardingObjective fwd = DefaultForwardingObjective.builder()
+                .withSelector(selector)
+                .withPriority(PRIORITY)
+                .fromApp(APP_ID)
+                .makePermanent()
+                .withFlag(ForwardingObjective.Flag.VERSATILE)
+                .nextStep(NEXT_ID_1)
+                .add();
+
+        ObjectiveTranslation result = translator.translate(fwd);
+
+        List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
+        List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
+        assertEquals(1, flowRulesInstalled.size());
+        assertTrue(groupsInstalled.isEmpty());
+
+        FlowRule actualFlowRule = flowRulesInstalled.get(0);
+        PiAction piAction = PiAction.builder()
+                .withId(FabricConstants.FABRIC_INGRESS_ACL_SET_NEXT_ID_ACL)
+                .withParameter(new PiActionParam(FabricConstants.NEXT_ID, NEXT_ID_1))
+                .build();
+        FlowRule expectedFlowRule = DefaultFlowRule.builder()
+                .forDevice(DEVICE_ID)
+                .forTable(FabricConstants.FABRIC_INGRESS_ACL_ACL)
+                .withPriority(PRIORITY)
+                .makePermanent()
+                .withSelector(selector)
+                .withTreatment(DefaultTrafficTreatment.builder()
+                        .piTableAction(piAction).build())
+                .fromApp(APP_ID)
+                .build();
+
+        assertTrue(expectedFlowRule.exactMatch(actualFlowRule));
+    }
+
+    /**
+     * Test versatile flag of forwarding objective with next step and port type.
+     */
+    @Test
+    public void testAclNextWithPortType() {
+        // ACL 8-tuples
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .matchEthType(Ethernet.TYPE_IPV4)
+                .matchIPDst(IPV4_UNICAST_ADDR)
+                .build();
+        TrafficSelector metaSelector = DefaultTrafficSelector.builder()
+                .matchMetadata(PORT_TYPE_EDGE)
+                .build();
+        ForwardingObjective fwd = DefaultForwardingObjective.builder()
+                .withSelector(selector)
+                .withPriority(PRIORITY)
+                .fromApp(APP_ID)
+                .makePermanent()
+                .withFlag(ForwardingObjective.Flag.VERSATILE)
+                .nextStep(NEXT_ID_1)
+                .withMeta(metaSelector)
+                .add();
+
+        ObjectiveTranslation result = translator.translate(fwd);
+
+        List<FlowRule> flowRulesInstalled = (List<FlowRule>) result.flowRules();
+        List<GroupDescription> groupsInstalled = (List<GroupDescription>) result.groups();
+        assertEquals(1, flowRulesInstalled.size());
+        assertTrue(groupsInstalled.isEmpty());
+
+        FlowRule actualFlowRule = flowRulesInstalled.get(0);
+        PiAction piAction = PiAction.builder()
+                .withId(FabricConstants.FABRIC_INGRESS_ACL_SET_NEXT_ID_ACL)
+                .withParameter(new PiActionParam(FabricConstants.NEXT_ID, NEXT_ID_1))
+                .build();
+        TrafficSelector expectedSelector = DefaultTrafficSelector.builder()
+                .matchEthType(Ethernet.TYPE_IPV4)
+                .matchIPDst(IPV4_UNICAST_ADDR)
+                .matchPi(PiCriterion.builder()
+                        .matchTernary(FabricConstants.HDR_PORT_TYPE, PORT_TYPE_EDGE, PORT_TYPE_MASK)
+                        .build())
+                .build();
+        FlowRule expectedFlowRule = DefaultFlowRule.builder()
+                .forDevice(DEVICE_ID)
+                .forTable(FabricConstants.FABRIC_INGRESS_ACL_ACL)
+                .withPriority(PRIORITY)
+                .makePermanent()
+                .withSelector(expectedSelector)
+                .withTreatment(DefaultTrafficTreatment.builder()
+                        .piTableAction(piAction).build())
+                .fromApp(APP_ID)
+                .build();
+
+        assertTrue(expectedFlowRule.exactMatch(actualFlowRule));
+
+        metaSelector = DefaultTrafficSelector.builder()
+                .matchMetadata(PORT_TYPE_INFRA)
+                .build();
+        fwd = DefaultForwardingObjective.builder()
+                .withSelector(selector)
+                .withPriority(PRIORITY)
+                .fromApp(APP_ID)
+                .makePermanent()
+                .withFlag(ForwardingObjective.Flag.VERSATILE)
+                .nextStep(NEXT_ID_1)
+                .withMeta(metaSelector)
+                .add();
+
+        result = translator.translate(fwd);
+
+        flowRulesInstalled = (List<FlowRule>) result.flowRules();
+        groupsInstalled = (List<GroupDescription>) result.groups();
+        assertEquals(1, flowRulesInstalled.size());
+        assertTrue(groupsInstalled.isEmpty());
+
+        actualFlowRule = flowRulesInstalled.get(0);
+        expectedSelector = DefaultTrafficSelector.builder()
+                .matchEthType(Ethernet.TYPE_IPV4)
+                .matchIPDst(IPV4_UNICAST_ADDR)
+                .matchPi(PiCriterion.builder()
+                        .matchTernary(FabricConstants.HDR_PORT_TYPE, PORT_TYPE_INFRA, PORT_TYPE_MASK)
+                        .build())
+                .build();
+        expectedFlowRule = DefaultFlowRule.builder()
+                .forDevice(DEVICE_ID)
+                .forTable(FabricConstants.FABRIC_INGRESS_ACL_ACL)
+                .withPriority(PRIORITY)
+                .makePermanent()
+                .withSelector(expectedSelector)
+                .withTreatment(DefaultTrafficTreatment.builder()
+                        .piTableAction(piAction).build())
+                .fromApp(APP_ID)
+                .build();
+
+        assertTrue(expectedFlowRule.exactMatch(actualFlowRule));
+    }
+
+    /**
      * Test versatile flag of forwarding objective with acl drop.
      */
     @Test
diff --git a/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/NextObjectiveTranslatorTest.java b/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/NextObjectiveTranslatorTest.java
index 393ba45..6647a83 100644
--- a/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/NextObjectiveTranslatorTest.java
+++ b/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/NextObjectiveTranslatorTest.java
@@ -57,6 +57,7 @@
     private NextObjectiveTranslator translatorSimple;
 
     private FlowRule vlanMetaFlowRule;
+    private FlowRule mplsFlowRule;
 
     @Before
     public void setup() {
@@ -72,7 +73,7 @@
                 .matchPi(nextIdCriterion)
                 .build();
         PiAction piAction = PiAction.builder()
-                .withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_VLAN)
+                .withId(FabricConstants.FABRIC_INGRESS_PRE_NEXT_SET_VLAN)
                 .withParameter(new PiActionParam(FabricConstants.VLAN_ID, VLAN_100.toShort()))
                 .build();
         TrafficTreatment treatment = DefaultTrafficTreatment.builder()
@@ -81,7 +82,24 @@
         vlanMetaFlowRule = DefaultFlowRule.builder()
                 .withSelector(selector)
                 .withTreatment(treatment)
-                .forTable(FabricConstants.FABRIC_INGRESS_NEXT_NEXT_VLAN)
+                .forTable(FabricConstants.FABRIC_INGRESS_PRE_NEXT_NEXT_VLAN)
+                .makePermanent()
+                // FIXME: currently next objective doesn't support priority, ignore this
+                .withPriority(0)
+                .forDevice(DEVICE_ID)
+                .fromApp(APP_ID)
+                .build();
+        piAction = PiAction.builder()
+                .withId(FabricConstants.FABRIC_INGRESS_PRE_NEXT_SET_MPLS_LABEL)
+                .withParameter(new PiActionParam(FabricConstants.LABEL, MPLS_10.toInt()))
+                .build();
+        treatment = DefaultTrafficTreatment.builder()
+                .piTableAction(piAction)
+                .build();
+        mplsFlowRule = DefaultFlowRule.builder()
+                .withSelector(selector)
+                .withTreatment(treatment)
+                .forTable(FabricConstants.FABRIC_INGRESS_PRE_NEXT_NEXT_MPLS)
                 .makePermanent()
                 // FIXME: currently next objective doesn't support priority, ignore this
                 .withPriority(0)
@@ -91,6 +109,164 @@
     }
 
     /**
+     * Test program mpls ecmp output group for Hashed table.
+     */
+    @Test
+    public void testMplsHashedOutput() throws Exception {
+        TrafficTreatment treatment1 = DefaultTrafficTreatment.builder()
+                .setEthSrc(ROUTER_MAC)
+                .setEthDst(SPINE1_MAC)
+                .pushMpls()
+                .copyTtlOut()
+                .setMpls(MPLS_10)
+                .popVlan()
+                .setOutput(PORT_1)
+                .build();
+        TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
+                .setEthSrc(ROUTER_MAC)
+                .setEthDst(SPINE2_MAC)
+                .pushMpls()
+                .copyTtlOut()
+                .setMpls(MPLS_10)
+                .popVlan()
+                .setOutput(PORT_2)
+                .build();
+
+        NextObjective nextObjective = DefaultNextObjective.builder()
+                .withId(NEXT_ID_1)
+                .withPriority(PRIORITY)
+                .withMeta(VLAN_META)
+                .addTreatment(treatment1)
+                .addTreatment(treatment2)
+                .withType(NextObjective.Type.HASHED)
+                .makePermanent()
+                .fromApp(APP_ID)
+                .add();
+
+        ObjectiveTranslation actualTranslation = translatorHashed.doTranslate(nextObjective);
+
+        // Expected hashed table flow rule.
+        PiCriterion nextIdCriterion = PiCriterion.builder()
+                .matchExact(FabricConstants.HDR_NEXT_ID, NEXT_ID_1)
+                .build();
+        TrafficSelector nextIdSelector = DefaultTrafficSelector.builder()
+                .matchPi(nextIdCriterion)
+                .build();
+        PiActionProfileGroupId actionGroupId = PiActionProfileGroupId.of(NEXT_ID_1);
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .piTableAction(actionGroupId)
+                .build();
+        FlowRule expectedFlowRule = DefaultFlowRule.builder()
+                .forDevice(DEVICE_ID)
+                .fromApp(APP_ID)
+                .makePermanent()
+                // FIXME: currently next objective doesn't support priority, ignore this
+                .withPriority(0)
+                .forTable(FabricConstants.FABRIC_INGRESS_NEXT_HASHED)
+                .withSelector(nextIdSelector)
+                .withTreatment(treatment)
+                .build();
+
+        // First egress rule - port1
+        PortNumber outPort = outputPort(treatment1);
+        PiCriterion egressVlanTableMatch = PiCriterion.builder()
+                .matchExact(FabricConstants.HDR_EG_PORT, outPort.toLong())
+                .build();
+        TrafficSelector selectorForEgressVlan = DefaultTrafficSelector.builder()
+                .matchPi(egressVlanTableMatch)
+                .matchVlanId(VLAN_100)
+                .build();
+        PiAction piActionForEgressVlan = PiAction.builder()
+                .withId(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_POP_VLAN)
+                .build();
+        TrafficTreatment treatmentForEgressVlan = DefaultTrafficTreatment.builder()
+                .piTableAction(piActionForEgressVlan)
+                .build();
+        FlowRule expectedEgressVlanPopRule1 = DefaultFlowRule.builder()
+                .withSelector(selectorForEgressVlan)
+                .withTreatment(treatmentForEgressVlan)
+                .forTable(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN)
+                .makePermanent()
+                .withPriority(nextObjective.priority())
+                .forDevice(DEVICE_ID)
+                .fromApp(APP_ID)
+                .build();
+
+        // Second egress rule - port2
+        outPort = outputPort(treatment2);
+        egressVlanTableMatch = PiCriterion.builder()
+                .matchExact(FabricConstants.HDR_EG_PORT, outPort.toLong())
+                .build();
+        selectorForEgressVlan = DefaultTrafficSelector.builder()
+                .matchPi(egressVlanTableMatch)
+                .matchVlanId(VLAN_100)
+                .build();
+        FlowRule expectedEgressVlanPopRule2 = DefaultFlowRule.builder()
+                .withSelector(selectorForEgressVlan)
+                .withTreatment(treatmentForEgressVlan)
+                .forTable(FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN)
+                .makePermanent()
+                .withPriority(nextObjective.priority())
+                .forDevice(DEVICE_ID)
+                .fromApp(APP_ID)
+                .build();
+
+        // Expected group
+        PiAction piAction1 = PiAction.builder()
+                .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_HASHED)
+                .withParameter(new PiActionParam(
+                        FabricConstants.SMAC, ROUTER_MAC.toBytes()))
+                .withParameter(new PiActionParam(
+                        FabricConstants.DMAC, SPINE1_MAC.toBytes()))
+                .withParameter(new PiActionParam(
+                        FabricConstants.PORT_NUM, PORT_1.toLong()))
+                .build();
+        PiAction piAction2 = PiAction.builder()
+                .withId(FabricConstants.FABRIC_INGRESS_NEXT_ROUTING_HASHED)
+                .withParameter(new PiActionParam(
+                        FabricConstants.SMAC, ROUTER_MAC.toBytes()))
+                .withParameter(new PiActionParam(
+                        FabricConstants.DMAC, SPINE2_MAC.toBytes()))
+                .withParameter(new PiActionParam(
+                        FabricConstants.PORT_NUM, PORT_2.toLong()))
+                .build();
+        treatment1 = DefaultTrafficTreatment.builder()
+                .piTableAction(piAction1)
+                .build();
+        treatment2 = DefaultTrafficTreatment.builder()
+                .piTableAction(piAction2)
+                .build();
+        List<TrafficTreatment> treatments = ImmutableList.of(treatment1, treatment2);
+        List<GroupBucket> buckets = treatments.stream()
+                .map(DefaultGroupBucket::createSelectGroupBucket)
+                .collect(Collectors.toList());
+        GroupBuckets groupBuckets = new GroupBuckets(buckets);
+        PiGroupKey groupKey = new PiGroupKey(FabricConstants.FABRIC_INGRESS_NEXT_HASHED,
+                FabricConstants.FABRIC_INGRESS_NEXT_HASHED_SELECTOR,
+                NEXT_ID_1);
+        GroupDescription expectedGroup = new DefaultGroupDescription(
+                DEVICE_ID,
+                GroupDescription.Type.SELECT,
+                groupBuckets,
+                groupKey,
+                NEXT_ID_1,
+                APP_ID
+        );
+
+        ObjectiveTranslation expectedTranslation = ObjectiveTranslation.builder()
+                .addFlowRule(expectedFlowRule)
+                .addFlowRule(vlanMetaFlowRule)
+                .addFlowRule(mplsFlowRule)
+                .addGroup(expectedGroup)
+                .addFlowRule(expectedEgressVlanPopRule1)
+                .addFlowRule(expectedEgressVlanPopRule2)
+                .build();
+
+        assertEquals(expectedTranslation, actualTranslation);
+    }
+
+    // TODO: add profile with simple next or remove tests
+    /**
      * Test program output rule for Simple table.
      */
     @Test
@@ -269,7 +445,7 @@
                 .build();
 
         PiAction piActionPush = PiAction.builder()
-                .withId(FabricConstants.FABRIC_INGRESS_NEXT_SET_DOUBLE_VLAN)
+                .withId(FabricConstants.FABRIC_INGRESS_PRE_NEXT_SET_DOUBLE_VLAN)
                 .withParameter(new PiActionParam(
                         FabricConstants.INNER_VLAN_ID, VLAN_100.toShort()))
                 .withParameter(new PiActionParam(
@@ -298,7 +474,7 @@
                 .withTreatment(DefaultTrafficTreatment.builder()
                                        .piTableAction(piActionPush)
                                        .build())
-                .forTable(FabricConstants.FABRIC_INGRESS_NEXT_NEXT_VLAN)
+                .forTable(FabricConstants.FABRIC_INGRESS_PRE_NEXT_NEXT_VLAN)
                 .makePermanent()
                 // FIXME: currently next objective doesn't support priority, ignore this
                 .withPriority(0)