In this commit: CORD-799
   Bug fix for host-update to not remove and add the same IP addr
   NPE fix in ofdpa3pipeline
   Removing unused code in ofdpa2pipeline
   Ability to add or revoke port filters for port-updates
   Retry filters retry for a longer time
   Bug fix for suppress ports to not suppress filters
   Filters now sent only by master instance
   Removing the MPLS BOS=0 rules for now until inconsitent hardware behavior is fixed

Change-Id: I8b4ee4af6de263531e0696af86e65f1c502f5f85
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
index 4893684..bee1150 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
@@ -27,6 +27,7 @@
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Link;
+import org.onosproject.net.PortNumber;
 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
 import org.onosproject.segmentrouting.config.DeviceConfiguration;
 import org.slf4j.Logger;
@@ -52,8 +53,9 @@
  * routing rule population.
  */
 public class DefaultRoutingHandler {
-    private static final int MAX_CONSTANT_RETRY_ATTEMPTS = 4;
-    private static final int RETRY_INTERVAL_MS = 500;
+    private static final int MAX_CONSTANT_RETRY_ATTEMPTS = 5;
+    private static final int RETRY_INTERVAL_MS = 250;
+    private static final int RETRY_INTERVAL_SCALE = 1;
     private static final String ECMPSPG_MISSING = "ECMP shortest path graph not found";
     private static Logger log = LoggerFactory.getLogger(DefaultRoutingHandler.class);
 
@@ -634,7 +636,9 @@
     }
 
     /**
-     * Populates filtering rules for permitting Router DstMac and VLAN.
+     * Populates filtering rules for port, and punting rules
+     * for gateway IPs, loopback IPs and arp/ndp traffic.
+     * Should only be called by the master instance for this device/port.
      *
      * @param deviceId Switch ID to set the rules
      */
@@ -655,6 +659,28 @@
     }
 
     /**
+     * Populates filtering rules for a port that has been enabled.
+     * Should only be called by the master instance for this device/port.
+     *
+     * @param devId device identifier
+     * @param portnum port identifier
+     */
+    public void populateSinglePortFilteringRules(DeviceId devId, PortNumber portnum) {
+        rulePopulator.populateSinglePortFilters(devId, portnum);
+    }
+
+    /**
+     * Revokes filtering rules for a port that has been disabled.
+     * Should only be called by the master instance for this device/port.
+     *
+     * @param devId device identifier
+     * @param portnum port identifier
+     */
+    public void revokeSinglePortFilteringRules(DeviceId devId, PortNumber portnum) {
+        rulePopulator.revokeSinglePortFilters(devId, portnum);
+    }
+
+    /**
      * Start the flow rule population process if it was never started. The
      * process finishes successfully when all flow rules are set and stops with
      * ABORTED status when any groups required for flows is not set yet.
@@ -743,21 +769,20 @@
     /**
      * Utility class used to temporarily store information about the ports on a
      * device processed for filtering objectives.
-     *
      */
     public final class PortFilterInfo {
-        int disabledPorts = 0, suppressedPorts = 0, filteredPorts = 0;
+        int disabledPorts = 0, errorPorts = 0, filteredPorts = 0;
 
-        public PortFilterInfo(int disabledPorts, int suppressedPorts,
+        public PortFilterInfo(int disabledPorts, int errorPorts,
                            int filteredPorts) {
             this.disabledPorts = disabledPorts;
             this.filteredPorts = filteredPorts;
-            this.suppressedPorts = suppressedPorts;
+            this.errorPorts = errorPorts;
         }
 
         @Override
         public int hashCode() {
-            return Objects.hash(disabledPorts, filteredPorts, suppressedPorts);
+            return Objects.hash(disabledPorts, filteredPorts, errorPorts);
         }
 
         @Override
@@ -771,14 +796,14 @@
             PortFilterInfo other = (PortFilterInfo) obj;
             return ((disabledPorts == other.disabledPorts) &&
                     (filteredPorts == other.filteredPorts) &&
-                    (suppressedPorts == other.suppressedPorts));
+                    (errorPorts == other.errorPorts));
         }
 
         @Override
         public String toString() {
             MoreObjects.ToStringHelper helper = toStringHelper(this)
                     .add("disabledPorts", disabledPorts)
-                    .add("suppressedPorts", suppressedPorts)
+                    .add("errorPorts", errorPorts)
                     .add("filteredPorts", filteredPorts);
             return helper.toString();
         }
@@ -809,7 +834,10 @@
             log.debug("dev:{} prevRun:{} thisRun:{} sameResult:{}", devId, prevRun,
                       thisRun, sameResult);
             if (thisRun == null || !sameResult || (sameResult && --constantAttempts > 0)) {
-                executorService.schedule(this, RETRY_INTERVAL_MS, TimeUnit.MILLISECONDS);
+                // exponentially increasing intervals for retries
+                executorService.schedule(this,
+                    RETRY_INTERVAL_MS * (int) Math.pow(counter, RETRY_INTERVAL_SCALE),
+                    TimeUnit.MILLISECONDS);
                 if (!sameResult) {
                     constantAttempts = MAX_CONSTANT_RETRY_ATTEMPTS; //reset
                 }