[AETHER-1032] Backport AETHER-538 to fabric.p4

AETHER-538 introduces a new design for the egress pipeline
where the tagged ports are explicitily matched in the
egress_vlan table. Moreover, no match means dropped with
this new design.

Change-Id: If6f8c73aad0effd01f18c87c147535378e8db84c
diff --git a/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/NextObjectiveTranslator.java b/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/NextObjectiveTranslator.java
index 1e0e52d..a8c4c6f 100644
--- a/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/NextObjectiveTranslator.java
+++ b/pipelines/fabric/impl/src/main/java/org/onosproject/pipelines/fabric/impl/behaviour/pipeliner/NextObjectiveTranslator.java
@@ -247,35 +247,30 @@
             throws FabricPipelinerException {
         final PortNumber outPort = outputPort(treatment);
         final Instruction popVlanInst = l2Instruction(treatment, VLAN_POP);
-        if (popVlanInst != null && outPort != null) {
+        if (outPort != null) {
             if (strict && treatment.allInstructions().size() > 2) {
                 throw new FabricPipelinerException(
                         "Treatment contains instructions other " +
                                 "than OUTPUT and VLAN_POP, cannot generate " +
                                 "egress rules");
             }
-            egressVlanPop(outPort, obj, resultBuilder);
+            // We cannot program if there are no proper metadata in the objective
+            if (obj.meta() != null && obj.meta().getCriterion(Criterion.Type.VLAN_VID) != null) {
+                egressVlan(outPort, obj, popVlanInst, resultBuilder);
+            } else {
+                log.warn("NextObjective {} is trying to program {} without {} information",
+                        obj, FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN,
+                        obj.meta() == null ? "metadata" : "vlanId");
+            }
         }
     }
 
-    private void egressVlanPop(PortNumber outPort, NextObjective obj,
-                               ObjectiveTranslation.Builder resultBuilder)
+    private void egressVlan(PortNumber outPort, NextObjective obj, Instruction popVlanInst,
+                            ObjectiveTranslation.Builder resultBuilder)
             throws FabricPipelinerException {
 
-        if (obj.meta() == null) {
-            throw new FabricPipelinerException(
-                    "Cannot process egress pop VLAN rule, NextObjective has null meta",
-                    ObjectiveError.BADPARAMS);
-        }
-
         final VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) criterion(
                 obj.meta(), Criterion.Type.VLAN_VID);
-        if (vlanIdCriterion == null) {
-            throw new FabricPipelinerException(
-                    "Cannot process egress pop VLAN rule, missing VLAN_VID criterion " +
-                            "in NextObjective meta",
-                    ObjectiveError.BADPARAMS);
-        }
 
         final PiCriterion egressVlanTableMatch = PiCriterion.builder()
                 .matchExact(FabricConstants.HDR_EG_PORT, outPort.toLong())
@@ -284,13 +279,16 @@
                 .matchPi(egressVlanTableMatch)
                 .matchVlanId(vlanIdCriterion.vlanId())
                 .build();
-        final TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                .popVlan()
-                .build();
+        final TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
+        if (popVlanInst == null) {
+            treatmentBuilder.pushVlan();
+        } else {
+            treatmentBuilder.popVlan();
+        }
 
         resultBuilder.addFlowRule(flowRule(
                 obj, FabricConstants.FABRIC_EGRESS_EGRESS_NEXT_EGRESS_VLAN,
-                selector, treatment));
+                selector, treatmentBuilder.build()));
     }
 
     private TrafficSelector nextIdSelector(int nextId) {