Added changes to exclude vlan from write metadate for upstream table 0 flows

Change-Id: I1be4941f5f3bbec52ea0d2461d0c226baea05c5c
diff --git a/impl/src/main/java/org/opencord/olt/driver/OltPipeline.java b/impl/src/main/java/org/opencord/olt/driver/OltPipeline.java
index 493680b..c405b75 100644
--- a/impl/src/main/java/org/opencord/olt/driver/OltPipeline.java
+++ b/impl/src/main/java/org/opencord/olt/driver/OltPipeline.java
@@ -887,10 +887,10 @@
         TrafficTreatment innerTreatment;
         if (noneValueVlanStatus) {
             innerTreatment = buildTreatment(innerPair.getLeft(), innerPair.getRight(), onuUsMeter,
-                                            fetchWriteMetadata(fwd), innerPbitSet,
+                                            writeMetadataExcludingCVlan(fwd), innerPbitSet,
                                             Instructions.transition(QQ_TABLE));
         } else {
-            innerTreatment = buildTreatment(innerPair.getRight(), onuUsMeter, fetchWriteMetadata(fwd),
+            innerTreatment = buildTreatment(innerPair.getRight(), onuUsMeter, writeMetadataExcludingCVlan(fwd),
                                             innerPbitSet, Instructions.transition(QQ_TABLE));
         }
 
@@ -950,7 +950,8 @@
                 .makePermanent()
                 .withPriority(fwd.priority())
                 .withSelector(fwd.selector())
-                .withTreatment(buildTreatment(Instructions.transition(QQ_TABLE), onuUsMeter, fetchWriteMetadata(fwd)));
+                .withTreatment(buildTreatment(Instructions.transition(QQ_TABLE), onuUsMeter,
+                        writeMetadataExcludingCVlan(fwd)));
 
         //match: in port and any-vlan (coming from OLT app.)
         //action: immediate: push:QinQ, vlanId (s-tag), write metadata, meter and output
@@ -1341,6 +1342,27 @@
                 fetchWriteMetadata(fwd).metadata() & 0xFFFF00000000L, 0L);
     }
 
+    /**
+     * Creates and returns the metadata excluding cVlan.
+     *
+     * This function can be used for following scenario.
+     *
+     * The cvlan field in the metadata is used to know that the packet is double or single tagged.
+     * For the ONU to know that the incoming packet at UNI is double tagged the innervlan is added in the cvlan field
+     * of the metadata for the upstream table 0 flows.
+     * As of now only FTTB workflows is using the double tagged at UNI. Other workflows, the cvlan should not be filled.
+     * If the cvlan is filled in the metadata the onu adapter will consider double tagged
+     * and configure rules accordingly.
+     *
+     * @param fwd ForwardingObjective
+     * @return Write Metadata Instruction
+     */
+    private Instruction writeMetadataExcludingCVlan(ForwardingObjective fwd) {
+
+        return Instructions.writeMetadata(
+                fetchWriteMetadata(fwd).metadata() & 0xFFFFFFFFFFFFL, 0L);
+    }
+
     private void fail(Objective obj, ObjectiveError error) {
         obj.context().ifPresent(context -> context.onError(obj, error));
     }
@@ -1455,10 +1477,10 @@
         TrafficTreatment innerTreatment;
         if (noneValueVlanStatus) {
             innerTreatment = buildTreatment(innerPair.getLeft(), innerPair.getRight(), onuUsMeter,
-                    fetchWriteMetadata(fwd), innerPbitSet,
+                    writeMetadataExcludingCVlan(fwd), innerPbitSet,
                     Instructions.transition(QQ_TABLE));
         } else {
-            innerTreatment = buildTreatment(innerPair.getRight(), onuUsMeter, fetchWriteMetadata(fwd),
+            innerTreatment = buildTreatment(innerPair.getRight(), onuUsMeter, writeMetadataExcludingCVlan(fwd),
                     innerPbitSet, Instructions.transition(QQ_TABLE));
         }
 
diff --git a/impl/src/main/java/org/opencord/olt/impl/OltFlowService.java b/impl/src/main/java/org/opencord/olt/impl/OltFlowService.java
index 701450d..10be314 100644
--- a/impl/src/main/java/org/opencord/olt/impl/OltFlowService.java
+++ b/impl/src/main/java/org/opencord/olt/impl/OltFlowService.java
@@ -856,10 +856,12 @@
         // we can remove it based in the match
         FilteringObjective.Builder eapol;
 
+        // Setting VlanId.NONE as cvlan in the metadata as the packet will be single tagged
+        // and cvlan should not be filled.
         TrafficTreatment treatment = treatmentBuilder
                 .meter(meterId)
                 .writeMetadata(OltFlowServiceUtils.createTechProfValueForWriteMetadata(
-                        vlanId,
+                        VlanId.NONE,
                         techProfileId, oltMeterId), 0)
                 .setOutput(PortNumber.CONTROLLER)
                 .pushVlan()
@@ -1166,12 +1168,9 @@
                 .fromApp(appId)
                 .withPriority(MAX_PRIORITY);
 
-        VlanId cVlan = uti.getUniTagMatch();
-
         //VLAN changes and PCP matching need to happen only in the upstream directions
         if (direction == FlowDirection.UPSTREAM) {
             if (serviceName != null && serviceName.equals(FTTB_SERVICE_DPU_MGMT_TRAFFIC)) {
-                cVlan = VlanId.NONE;
                 FttbUtils.addUpstreamDhcpCondition(dhcpBuilder, uti);
                 FttbUtils.addUpstreamDhcpTreatment(treatmentBuilder, uti);
             } else {
@@ -1195,8 +1194,9 @@
         }
 
         if (uti.getTechnologyProfileId() != NONE_TP_ID) {
+            // Setting VlanId.NONE as cvlan, as the packet will be single tagged and cvlan should not be filled.
             treatmentBuilder.writeMetadata(
-                    OltFlowServiceUtils.createTechProfValueForWriteMetadata(cVlan,
+                    OltFlowServiceUtils.createTechProfValueForWriteMetadata(VlanId.NONE,
                             uti.getTechnologyProfileId(), oltMeterId), 0);
         }
 
@@ -1296,8 +1296,9 @@
         }
 
         if (techProfileId != NONE_TP_ID) {
-            treatmentBuilder.writeMetadata(OltFlowServiceUtils.createTechProfValueForWriteMetadata(cTag, techProfileId,
-                    oltMeterId), 0);
+            // Setting VlanId.NONE as cvlan as the packet will be single tagged and cvlan should not be filled.
+            treatmentBuilder.writeMetadata(OltFlowServiceUtils.createTechProfValueForWriteMetadata(VlanId.NONE,
+                    techProfileId, oltMeterId), 0);
         }
 
         DefaultFilteringObjective.Builder pppoedBuilder = ((action == FlowOperation.ADD)
diff --git a/impl/src/test/java/org/opencord/olt/impl/OltFlowServiceTest.java b/impl/src/test/java/org/opencord/olt/impl/OltFlowServiceTest.java
index 878078a..1525bcd 100644
--- a/impl/src/test/java/org/opencord/olt/impl/OltFlowServiceTest.java
+++ b/impl/src/test/java/org/opencord/olt/impl/OltFlowServiceTest.java
@@ -441,7 +441,7 @@
                         DefaultTrafficTreatment.builder()
                                 .meter(MeterId.meterId(1))
                                 .writeMetadata(OltFlowServiceUtils.createTechProfValueForWriteMetadata(
-                                        VlanId.vlanId(eapolDefaultVlan),
+                                        VlanId.NONE,
                                         component.defaultTechProfileId, MeterId.meterId(1)), 0)
                                 .setOutput(PortNumber.CONTROLLER)
                                 .pushVlan()
@@ -494,7 +494,7 @@
                         DefaultTrafficTreatment.builder()
                                 .meter(MeterId.meterId(1))
                                 .writeMetadata(OltFlowServiceUtils.createTechProfValueForWriteMetadata(
-                                        VlanId.vlanId(eapolDefaultVlan),
+                                        VlanId.NONE,
                                         component.defaultTechProfileId, MeterId.meterId(1)), 0)
                                 .setOutput(PortNumber.CONTROLLER)
                                 .pushVlan()