[VOL-4577] : Update ONOS olt-app for adding FTTB DPU Management, ANCP traffic & trap rules

Change-Id: Ibb8aad6e68e8bd3b5f5824f0b04f4c5bc2f84a9e
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 bbf1ba7..493680b 100644
--- a/impl/src/main/java/org/opencord/olt/driver/OltPipeline.java
+++ b/impl/src/main/java/org/opencord/olt/driver/OltPipeline.java
@@ -34,6 +34,7 @@
 import org.onlab.util.KryoNamespace;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
+import org.onosproject.net.Annotations;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.behaviour.NextGroup;
@@ -80,6 +81,7 @@
 import org.onosproject.net.group.GroupService;
 import org.onosproject.store.serializers.KryoNamespaces;
 import org.onosproject.store.service.StorageService;
+import org.opencord.olt.impl.fttb.FttbUtils;
 import org.slf4j.Logger;
 
 import java.util.Arrays;
@@ -96,10 +98,17 @@
 import static org.onosproject.core.CoreService.CORE_APP_NAME;
 import static org.opencord.olt.impl.OsgiPropertyConstants.DOWNSTREAM_OLT;
 import static org.opencord.olt.impl.OsgiPropertyConstants.DOWNSTREAM_ONU;
+import static org.opencord.olt.impl.fttb.FttbUtils.FTTB_FLOW_DIRECTION;
+import static org.opencord.olt.impl.fttb.FttbUtils.FTTB_FLOW_DOWNSTREAM;
+import static org.opencord.olt.impl.fttb.FttbUtils.FTTB_FLOW_UPSTREAM;
 import static org.opencord.olt.impl.OsgiPropertyConstants.UPSTREAM_OLT;
 import static org.opencord.olt.impl.OsgiPropertyConstants.UPSTREAM_ONU;
 import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
 import static org.onlab.util.Tools.groupedThreads;
+import static org.opencord.olt.impl.fttb.FttbUtils.FTTB_SERVICE_DPU_ANCP_TRAFFIC;
+import static org.opencord.olt.impl.fttb.FttbUtils.FTTB_SERVICE_DPU_MGMT_TRAFFIC;
+import static org.opencord.olt.impl.fttb.FttbUtils.FTTB_SERVICE_NAME;
+import static org.opencord.olt.impl.fttb.FttbUtils.FTTB_SERVICE_SUBSCRIBER_TRAFFIC;
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
@@ -335,6 +344,12 @@
             return;
         }
 
+        if (FttbUtils.isFttbRule(fwd)) {
+            log.debug("Processing FTTB rule : {}", fwd);
+            processFttbRules(fwd);
+            return;
+        }
+
         TrafficTreatment treatment = fwd.treatment();
 
         List<Instruction> instructions = treatment.allInstructions();
@@ -1137,8 +1152,9 @@
         if (matchVlanId != null) {
             log.debug("Building selector with match VLAN, {}", matchVlanId);
             // in case of TT upstream the packet comes tagged and the vlan is swapped.
+            Criterion vlanPcp = filterForCriterion(filter.conditions(), Criterion.Type.VLAN_PCP);
             selector = buildSelector(filter.key(), ethType, ipProto, udpSrcPort,
-                                     udpDstPort, matchVlanId);
+                                     udpDstPort, matchVlanId, vlanPcp);
             treatment = buildTreatment(output, meter, writeMetadata,
                                        vlanIdInstruction, vlanPcpInstruction);
         } else {
@@ -1485,4 +1501,189 @@
 
         applyRules(fwd, inner, outer);
     }
+
+    private void processFttbRules(ForwardingObjective fwd) {
+        Annotations annotations = fwd.annotations();
+        String direction = annotations.value(FTTB_FLOW_DIRECTION);
+        String serviceName = annotations.value(FTTB_SERVICE_NAME);
+
+        if (direction == null) {
+            log.error("Flow direction not found for Fttb rule {} ", fwd);
+            return;
+        }
+
+        switch (direction) {
+            case FTTB_FLOW_UPSTREAM:
+                processUpstreamFttbRules(fwd, serviceName);
+                break;
+            case FTTB_FLOW_DOWNSTREAM:
+                processDownstreamFttbRules(fwd, serviceName);
+                break;
+            default:
+                log.error("Invalid flow direction {}, for {} ", direction, fwd);
+        }
+    }
+
+    private void processUpstreamFttbRules(ForwardingObjective fwd, String serviceName) {
+        TrafficSelector selector = fwd.selector();
+        TrafficTreatment treatment =  fwd.treatment();
+
+        // Selectors
+        Criterion inPortCriterion = selector.getCriterion(Criterion.Type.IN_PORT);
+        Criterion cVlanVidCriterion = selector.getCriterion(Criterion.Type.VLAN_VID);
+        Criterion cTagPriority = selector.getCriterion(Criterion.Type.VLAN_PCP);
+        Criterion ethSrcCriterion = selector.getCriterion(Criterion.Type.ETH_SRC);
+
+        // Instructions
+        L2ModificationInstruction.ModVlanIdInstruction sVlanSetVid = null;
+        L2ModificationInstruction.ModVlanPcpInstruction sTagPrioritySet = null;
+
+        List<Instruction> instructions = treatment.allInstructions();
+        List<Instruction> vlanIdL2Instructions = findL2Instructions(L2ModificationInstruction.L2SubType.VLAN_ID,
+                instructions);
+        List<Instruction> vlanPcpL2Instructions = findL2Instructions(L2ModificationInstruction.L2SubType.VLAN_PCP,
+                instructions);
+
+        if (!vlanIdL2Instructions.isEmpty()) {
+            sVlanSetVid = (L2ModificationInstruction.ModVlanIdInstruction) vlanIdL2Instructions.get(0);
+        }
+
+        if (!vlanPcpL2Instructions.isEmpty()) {
+            sTagPrioritySet = (L2ModificationInstruction.ModVlanPcpInstruction) vlanPcpL2Instructions.get(0);
+        }
+
+        Instruction output = fetchOutput(fwd, UPSTREAM);
+        Instruction onuUsMeter = fetchMeterById(fwd, fwd.annotations().value(UPSTREAM_ONU));
+        Instruction oltUsMeter = fetchMeterById(fwd, fwd.annotations().value(UPSTREAM_OLT));
+
+        TrafficSelector oltSelector, onuSelector;
+        TrafficTreatment oltTreatment, onuTreatment;
+
+        switch (serviceName) {
+            case FTTB_SERVICE_DPU_MGMT_TRAFFIC:
+            case FTTB_SERVICE_DPU_ANCP_TRAFFIC:
+                onuSelector = buildSelector(inPortCriterion, cVlanVidCriterion, cTagPriority);
+                onuTreatment = buildTreatment(sVlanSetVid, sTagPrioritySet, onuUsMeter,
+                        fetchWriteMetadata(fwd), Instructions.transition(QQ_TABLE));
+
+                oltSelector = buildSelector(inPortCriterion, ethSrcCriterion,
+                        Criteria.matchVlanId(sVlanSetVid.vlanId()));
+                oltTreatment = buildTreatment(oltUsMeter, fetchWriteMetadata(fwd), output);
+                break;
+
+            case FTTB_SERVICE_SUBSCRIBER_TRAFFIC:
+                onuSelector = buildSelector(inPortCriterion, cVlanVidCriterion);
+                onuTreatment = buildTreatment(onuUsMeter, fetchWriteMetadata(fwd), Instructions.transition(QQ_TABLE));
+
+                oltSelector = buildSelector(inPortCriterion, cVlanVidCriterion);
+                oltTreatment = buildTreatment(sVlanSetVid, oltUsMeter, fetchWriteMetadata(fwd), output);
+                break;
+            default:
+                log.error("Unknown service type for Fttb rule : {}", fwd);
+                return;
+        }
+
+        FlowRule.Builder onuBuilder = DefaultFlowRule.builder()
+                .fromApp(fwd.appId())
+                .forDevice(deviceId)
+                .makePermanent()
+                .withPriority(fwd.priority())
+                .withSelector(onuSelector)
+                .withTreatment(onuTreatment);
+
+        FlowRule.Builder oltBuilder = DefaultFlowRule.builder()
+                .fromApp(fwd.appId())
+                .forDevice(deviceId)
+                .forTable(QQ_TABLE)
+                .makePermanent()
+                .withPriority(fwd.priority())
+                .withSelector(oltSelector)
+                .withTreatment(oltTreatment);
+
+        applyRules(fwd, onuBuilder, oltBuilder);
+    }
+
+    private void processDownstreamFttbRules(ForwardingObjective fwd, String serviceName) {
+        TrafficSelector selector = fwd.selector();
+        TrafficTreatment treatment = fwd.treatment();
+
+        // Selectors
+        Criterion inPortCriterion = selector.getCriterion(Criterion.Type.IN_PORT);
+        Criterion sVlanVidCriterion = selector.getCriterion(Criterion.Type.VLAN_VID);
+        Criterion sTagPriority = selector.getCriterion(Criterion.Type.VLAN_PCP);
+        Criterion ethDstCriterion = selector.getCriterion(Criterion.Type.ETH_DST);
+        Criterion metadataSelector = selector.getCriterion(Criterion.Type.METADATA);
+
+        // Instructions
+        L2ModificationInstruction.ModVlanIdInstruction cVlanSetVid = null;
+        L2ModificationInstruction.ModVlanPcpInstruction cTagPrioritySet = null;
+
+        List<Instruction> instructions = treatment.allInstructions();
+        List<Instruction> vlanIdL2Instructions = findL2Instructions(L2ModificationInstruction.L2SubType.VLAN_ID,
+                instructions);
+        List<Instruction> vlanPcpL2Instructions = findL2Instructions(L2ModificationInstruction.L2SubType.VLAN_PCP,
+                instructions);
+
+        if (!vlanIdL2Instructions.isEmpty()) {
+            cVlanSetVid = (L2ModificationInstruction.ModVlanIdInstruction) vlanIdL2Instructions.get(0);
+        }
+
+        if (!vlanPcpL2Instructions.isEmpty()) {
+            cTagPrioritySet = (L2ModificationInstruction.ModVlanPcpInstruction) vlanPcpL2Instructions.get(0);
+        }
+
+        Instruction output = fetchOutput(fwd, DOWNSTREAM);
+        Instruction oltDsMeter = fetchMeterById(fwd, fwd.annotations().value(DOWNSTREAM_OLT));
+        Instruction onuUsMeter = fetchMeterById(fwd, fwd.annotations().value(DOWNSTREAM_ONU));
+
+        TrafficSelector oltSelector, onuSelector;
+        TrafficTreatment oltTreatment, onuTreatment;
+
+        switch (serviceName) {
+            case FTTB_SERVICE_DPU_MGMT_TRAFFIC:
+            case FTTB_SERVICE_DPU_ANCP_TRAFFIC:
+                oltSelector = buildSelector(inPortCriterion, ethDstCriterion,
+                        sVlanVidCriterion);
+                oltTreatment = buildTreatment(oltDsMeter, fetchWriteMetadata(fwd),
+                        Instructions.transition(QQ_TABLE));
+
+                onuSelector = buildSelector(inPortCriterion, sVlanVidCriterion, sTagPriority, ethDstCriterion);
+                onuTreatment = buildTreatment(cVlanSetVid, cTagPrioritySet, onuUsMeter,
+                        fetchWriteMetadata(fwd), output);
+                break;
+
+            case FTTB_SERVICE_SUBSCRIBER_TRAFFIC:
+                oltSelector = buildSelector(inPortCriterion, sVlanVidCriterion);
+                oltTreatment = buildTreatment(cVlanSetVid, oltDsMeter, fetchWriteMetadata(fwd),
+                        Instructions.transition(QQ_TABLE));
+
+                onuSelector = buildSelector(inPortCriterion, Criteria.matchVlanId(cVlanSetVid.vlanId()),
+                        metadataSelector);
+                onuTreatment = buildTreatment(onuUsMeter, fetchWriteMetadata(fwd), output);
+                break;
+
+            default:
+                log.error("Unknown service type for Fttb rule : {}", fwd);
+                return;
+        }
+
+        FlowRule.Builder oltBuilder = DefaultFlowRule.builder()
+                .fromApp(fwd.appId())
+                .forDevice(deviceId)
+                .makePermanent()
+                .withPriority(fwd.priority())
+                .withSelector(oltSelector)
+                .withTreatment(oltTreatment);
+
+        FlowRule.Builder onuBuilder = DefaultFlowRule.builder()
+                .fromApp(fwd.appId())
+                .forDevice(deviceId)
+                .forTable(QQ_TABLE)
+                .makePermanent()
+                .withPriority(fwd.priority())
+                .withSelector(onuSelector)
+                .withTreatment(onuTreatment);
+
+        applyRules(fwd, onuBuilder, oltBuilder);
+    }
 }
\ No newline at end of file