[VOL-3816] Support PPPoED trap rules installation on Olt app.

Signed-off-by: Gustavo Silva <gsilva@furukawalatam.com>
Change-Id: I71868eddbeecc688095e7966b76f42fb158095ed
diff --git a/app/src/main/java/org/opencord/olt/impl/OltFlowService.java b/app/src/main/java/org/opencord/olt/impl/OltFlowService.java
index 429dd95..14fa4f9 100644
--- a/app/src/main/java/org/opencord/olt/impl/OltFlowService.java
+++ b/app/src/main/java/org/opencord/olt/impl/OltFlowService.java
@@ -84,6 +84,7 @@
         ENABLE_DHCP_V6 + ":Boolean=" + ENABLE_DHCP_V6_DEFAULT,
         ENABLE_IGMP_ON_NNI + ":Boolean=" + ENABLE_IGMP_ON_NNI_DEFAULT,
         ENABLE_EAPOL + ":Boolean=" + ENABLE_EAPOL_DEFAULT,
+        ENABLE_PPPOE + ":Boolean=" + ENABLE_PPPOE_DEFAULT,
         DEFAULT_TP_ID + ":Integer=" + DEFAULT_TP_ID_DEFAULT
 })
 public class OltFlowService implements AccessDeviceFlowService {
@@ -149,6 +150,11 @@
     protected boolean enableEapol = ENABLE_EAPOL_DEFAULT;
 
     /**
+     * Send PPPoED authentication trap flows before subscriber provisioning.
+     **/
+    protected boolean enablePppoe = ENABLE_PPPOE_DEFAULT;
+
+    /**
      * Default technology profile id that is used for authentication trap flows.
      **/
     protected int defaultTechProfileId = DEFAULT_TP_ID_DEFAULT;
@@ -205,14 +211,20 @@
             enableEapol = eap;
         }
 
+        Boolean pppoe = Tools.isPropertyEnabled(properties, ENABLE_PPPOE);
+        if (pppoe != null) {
+            enablePppoe = pppoe;
+        }
+
         String tpId = get(properties, DEFAULT_TP_ID);
         defaultTechProfileId = isNullOrEmpty(tpId) ? DEFAULT_TP_ID_DEFAULT : Integer.parseInt(tpId.trim());
 
         log.info("modified. Values = enableDhcpOnNni: {}, enableDhcpV4: {}, " +
                          "enableDhcpV6:{}, enableIgmpOnNni:{}, " +
-                         "enableEapol{}, defaultTechProfileId: {}",
+                         "enableEapol{}, enablePppoe{}, defaultTechProfileId: {}",
                  enableDhcpOnNni, enableDhcpV4, enableDhcpV6,
-                 enableIgmpOnNni, enableEapol, defaultTechProfileId);
+                 enableIgmpOnNni, enableEapol,  enablePppoe,
+                 defaultTechProfileId);
 
     }
 
@@ -332,6 +344,77 @@
     }
 
     @Override
+    public void processPPPoEDFilteringObjectives(DeviceId devId, PortNumber portNumber,
+                                                 MeterId upstreamMeterId,
+                                                 UniTagInformation tagInformation,
+                                                 boolean install,
+                                                 boolean upstream) {
+        if (!enablePppoe) {
+            log.debug("PPPoED filtering is disabled. Ignoring request.");
+            return;
+        }
+
+        int techProfileId = NONE_TP_ID;
+        VlanId cTag = VlanId.NONE;
+        VlanId unitagMatch = VlanId.ANY;
+        Byte vlanPcp = null;
+
+        if (tagInformation != null) {
+            techProfileId = tagInformation.getTechnologyProfileId();
+            cTag = tagInformation.getPonCTag();
+            unitagMatch = tagInformation.getUniTagMatch();
+            if (tagInformation.getUsPonCTagPriority() != NO_PCP) {
+                vlanPcp = (byte) tagInformation.getUsPonCTagPriority();
+            }
+        }
+
+        DefaultFilteringObjective.Builder builder = DefaultFilteringObjective.builder();
+        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
+        CompletableFuture<Object> meterFuture = new CompletableFuture<>();
+
+        if (upstreamMeterId != null) {
+            treatmentBuilder.meter(upstreamMeterId);
+        }
+
+        if (techProfileId != NONE_TP_ID) {
+            treatmentBuilder.writeMetadata(createTechProfValueForWm(cTag, techProfileId), 0);
+        }
+
+        DefaultFilteringObjective.Builder pppoedBuilder = (install ? builder.permit() : builder.deny())
+                .withKey(Criteria.matchInPort(portNumber))
+                .addCondition(Criteria.matchEthType(EthType.EtherType.PPPoED.ethType()))
+                .fromApp(appId)
+                .withPriority(10000);
+
+        if (upstream) {
+            treatmentBuilder.setVlanId(cTag);
+            if (!VlanId.vlanId(VlanId.NO_VID).equals(unitagMatch)) {
+                pppoedBuilder.addCondition(Criteria.matchVlanId(unitagMatch));
+            }
+            if (vlanPcp != null) {
+                treatmentBuilder.setVlanPcp(vlanPcp);
+            }
+        }
+        pppoedBuilder = pppoedBuilder.withMeta(treatmentBuilder.setOutput(PortNumber.CONTROLLER).build());
+
+        FilteringObjective pppoed = pppoedBuilder
+                .add(new ObjectiveContext() {
+                    @Override
+                    public void onSuccess(Objective objective) {
+                        log.info("PPPoED filter for {} on {} {}.",
+                                devId, portNumber, (install) ? INSTALLED : REMOVED);
+                    }
+
+                    @Override
+                    public void onError(Objective objective, ObjectiveError error) {
+                        log.info("PPPoED filter for {} on {} failed {} because {}",
+                                devId, portNumber, (install) ? INSTALLATION : REMOVAL, error);
+                    }
+                });
+        flowObjectiveService.filter(devId, pppoed);
+    }
+
+    @Override
     public void processIgmpFilteringObjectives(DeviceId devId, PortNumber port,
                                                MeterId upstreamMeterId,
                                                UniTagInformation tagInformation,
@@ -590,6 +673,7 @@
         processLldpFilteringObjective(devId, port, install);
         processDhcpFilteringObjectives(devId, port, null, null, install, false);
         processIgmpFilteringObjectives(devId, port, null, null, install, false);
+        processPPPoEDFilteringObjectives(devId, port, null, null, install, false);
     }