[ONOS-7242] Support MPLS by fabric.p4 pipeliner

Change-Id: I56a8f266e6d0afe5ad6737b8d0e399758fb75378
diff --git a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricForwardingPipeliner.java b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricForwardingPipeliner.java
index dfd8d85..bceefdd 100644
--- a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricForwardingPipeliner.java
+++ b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricForwardingPipeliner.java
@@ -30,6 +30,7 @@
 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.MplsCriterion;
 import org.onosproject.net.flow.criteria.VlanIdCriterion;
 import org.onosproject.net.flowobjective.ForwardingObjective;
 import org.onosproject.net.flowobjective.ObjectiveError;
@@ -97,6 +98,7 @@
         VlanIdCriterion vlanIdCriterion = null;
         EthCriterion ethDstCriterion = null;
         IPCriterion ipDstCriterion = null;
+        MplsCriterion mplsCriterion = null;
 
         for (Criterion criterion : criteria) {
             switch (criterion.type()) {
@@ -109,6 +111,13 @@
                 case IPV4_DST:
                     ipDstCriterion = (IPCriterion) criterion;
                     break;
+                case MPLS_LABEL:
+                    mplsCriterion = (MplsCriterion) criterion;
+                    break;
+                case ETH_TYPE:
+                case MPLS_BOS:
+                    // do nothing
+                    break;
                 default:
                     log.warn("Unsupported criterion {}", criterion);
                     break;
@@ -127,10 +136,12 @@
             case IPV4_UNICAST:
                 processIpv4UnicastRule(ipDstCriterion, fwd, resultBuilder);
                 break;
+            case MPLS:
+                processMplsRule(mplsCriterion, fwd, resultBuilder);
+                break;
             case IPV4_MULTICAST:
             case IPV6_UNICAST:
             case IPV6_MULTICAST:
-            case MPLS:
             default:
                 log.warn("Unsupported forwarding function type {}", criteria);
                 resultBuilder.setError(ObjectiveError.UNSUPPORTED);
@@ -228,6 +239,41 @@
         resultBuilder.addFlowRule(flowRule);
     }
 
+    private void processMplsRule(MplsCriterion mplsCriterion, ForwardingObjective fwd,
+                                 PipelinerTranslationResult.Builder resultBuilder) {
+        checkNotNull(mplsCriterion, "Mpls criterion should not be null");
+        if (fwd.nextId() == null) {
+            log.warn("Forwarding objective for MPLS should contains next id");
+            resultBuilder.setError(ObjectiveError.BADPARAMS);
+            return;
+        }
+        TrafficSelector selector = DefaultTrafficSelector.builder()
+                .add(mplsCriterion)
+                .build();
+
+        PiActionParam nextIdParam = new PiActionParam(FabricConstants.ACT_PRM_NEXT_ID_ID,
+                                                      ImmutableByteSequence.copyFrom(fwd.nextId().byteValue()));
+        PiAction nextIdAction = PiAction.builder()
+                .withId(FabricConstants.ACT_POP_MPLS_AND_NEXT_ID)
+                .withParameter(nextIdParam)
+                .build();
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .piTableAction(nextIdAction)
+                .build();
+
+        FlowRule flowRule = DefaultFlowRule.builder()
+                .withSelector(selector)
+                .withTreatment(treatment)
+                .fromApp(fwd.appId())
+                .withPriority(fwd.priority())
+                .makePermanent()
+                .forDevice(deviceId)
+                .forTable(FabricConstants.TBL_MPLS_ID)
+                .build();
+
+        resultBuilder.addFlowRule(flowRule);
+    }
+
     private static TrafficTreatment buildSetNextIdTreatment(Integer nextId) {
         PiActionParam nextIdParam = new PiActionParam(FabricConstants.ACT_PRM_NEXT_ID_ID,
                                                       ImmutableByteSequence.copyFrom(nextId.byteValue()));
@@ -240,5 +286,4 @@
                 .piTableAction(nextIdAction)
                 .build();
     }
-
 }