useStaleLinkAge for VanishStaleLink

Also include gerrit #22247

Change-Id: Ifd8079172a096bef0edf89daca97395c2d35a5ce
diff --git a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LldpLinkProvider.java b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LldpLinkProvider.java
index 768c207..b99e4be 100644
--- a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LldpLinkProvider.java
+++ b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LldpLinkProvider.java
@@ -100,6 +100,7 @@
                 PROP_PROBE_RATE + ":Integer=" + PROBE_RATE_DEFAULT,
                 PROP_STALE_LINK_AGE + ":Integer=" + STALE_LINK_AGE_DEFAULT,
                 PROP_DISCOVERY_DELAY + ":Integer=" + DISCOVERY_DELAY_DEFAULT,
+                PROP_USE_STALE_LINK_AGE + ":Boolean=" + USE_STALE_LINK_AGE_DEFAULT,
         })
 public class LldpLinkProvider extends AbstractProvider implements ProbedLinkProvider {
 
@@ -107,7 +108,7 @@
 
     private static final String FORMAT =
             "Settings: enabled={}, useBDDP={}, probeRate={}, " +
-                    "staleLinkAge={}, maxLLDPage={}";
+                    "staleLinkAge={}, maxLLDPage={}, useStaleLinkAge={}";
 
     // When a Device/Port has this annotation, do not send out LLDP/BDDP
     public static final String NO_LLDP = "no-lldp";
@@ -170,6 +171,9 @@
     /** Number of millis beyond which an LLDP packet will not be accepted. */
     private int maxDiscoveryDelayMs = DISCOVERY_DELAY_DEFAULT;
 
+    /** If false, StaleLinkAge capability is disabled. */
+    private boolean useStaleLinkAge = USE_STALE_LINK_AGE_DEFAULT;
+
     private final LinkDiscoveryContext context = new InternalDiscoveryContext();
     private final InternalRoleListener roleListener = new InternalRoleListener();
     private final InternalDeviceListener deviceListener = new InternalDeviceListener();
@@ -294,7 +298,7 @@
     public void modified(ComponentContext context) {
         Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
 
-        boolean newEnabled, newUseBddp;
+        boolean newEnabled, newUseBddp, newUseStaleLinkAge;
         int newProbeRate, newStaleLinkAge, newDiscoveryDelay;
         try {
             String s = get(properties, PROP_ENABLED);
@@ -312,6 +316,9 @@
             s = get(properties, PROP_DISCOVERY_DELAY);
             newDiscoveryDelay = isNullOrEmpty(s) ? maxDiscoveryDelayMs : Integer.parseInt(s.trim());
 
+            s = get(properties, PROP_USE_STALE_LINK_AGE);
+            newUseStaleLinkAge = isNullOrEmpty(s) || Boolean.parseBoolean(s.trim());
+
         } catch (NumberFormatException e) {
             log.warn("Component configuration had invalid values", e);
             newEnabled = enabled;
@@ -319,6 +326,7 @@
             newProbeRate = probeRate;
             newStaleLinkAge = staleLinkAge;
             newDiscoveryDelay = maxDiscoveryDelayMs;
+            newUseStaleLinkAge = useStaleLinkAge;
         }
 
         boolean wasEnabled = enabled;
@@ -328,6 +336,7 @@
         probeRate = newProbeRate;
         staleLinkAge = newStaleLinkAge;
         maxDiscoveryDelayMs = newDiscoveryDelay;
+        useStaleLinkAge = newUseStaleLinkAge;
 
         if (!wasEnabled && enabled) {
             enable();
@@ -340,7 +349,7 @@
             }
         }
 
-        log.info(FORMAT, enabled, useBddp, probeRate, staleLinkAge, maxDiscoveryDelayMs);
+        log.info(FORMAT, enabled, useBddp, probeRate, staleLinkAge, maxDiscoveryDelayMs, useStaleLinkAge);
     }
 
     /**
@@ -730,10 +739,16 @@
                         return true;
                     }
                     if (isStale(e.getValue())) {
-                        providerService.linkVanished(new DefaultLinkDescription(e.getKey().src(),
+                        if (useStaleLinkAge) {
+                            providerService.linkVanished(new DefaultLinkDescription(e.getKey().src(),
+
                                                                                 e.getKey().dst(),
                                                                                 DIRECT));
-                        return true;
+                            return true;
+                        }
+                        log.warn("VanishStaleLinkAge feature is disabled, " +
+                                "not bringing down link src {} dst {} with expired StaleLinkAge",
+                                e.getKey().src(), e.getKey().dst());
                     }
                     return false;
                 }).clear();
diff --git a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/OsgiPropertyConstants.java b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/OsgiPropertyConstants.java
index 51bcd39..224ac7e 100644
--- a/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/OsgiPropertyConstants.java
+++ b/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/OsgiPropertyConstants.java
@@ -38,4 +38,7 @@
     public static final String PROP_DISCOVERY_DELAY = "maxDiscoveryDelayMs";
     public static final int DISCOVERY_DELAY_DEFAULT = 1000;
 
+    public static final String PROP_USE_STALE_LINK_AGE = "useStaleLinkAge";
+    public static final boolean USE_STALE_LINK_AGE_DEFAULT = true;
+
 }
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/LinksWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/LinksWebResource.java
index 3c74d94..cb4f0a4 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/LinksWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/LinksWebResource.java
@@ -23,7 +23,9 @@
 import org.onosproject.rest.AbstractWebResource;
 
 import javax.ws.rs.GET;
+import javax.ws.rs.POST;
 import javax.ws.rs.Path;
+import javax.ws.rs.Consumes;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
@@ -31,6 +33,13 @@
 
 import static org.onosproject.net.DeviceId.deviceId;
 import static org.onosproject.net.PortNumber.portNumber;
+import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.cfg.ConfigProperty;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.io.IOException;
+import java.io.InputStream;
+
 
 /**
  * Manage inventory of infrastructure links.
@@ -97,4 +106,56 @@
         }
     }
 
+    /**
+     * Get useStaleLinkAge active status.
+     * Returns current status of the VanishedStaleLink.
+     *
+     * @onos.rsModel VanishedLink
+     * @return 200 ok with the VanishedStaleLink status.
+     */
+    @GET
+    @Path("{usestalelinkage}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getVanishStaleLink() {
+        ObjectNode root = mapper().createObjectNode();
+        ComponentConfigService useStaleLink = get(ComponentConfigService.class);
+
+        for (ConfigProperty prop : useStaleLink.getProperties("org.onosproject.provider.lldp.impl.LldpLinkProvider")) {
+            if (prop.name().equals("useStaleLinkAge")) {
+                root.put("active", Boolean.valueOf(prop.value()));
+                break;
+            }
+        }
+        return ok(root).build();
+    }
+
+    /**
+     * Set useStaleLinkAge status.
+     *
+     * @onos.rsModel VanishedLink
+     * @param stream input JSON
+     * @return 200 ok.
+     * BAD_REQUEST if the JSON is invalid
+     */
+    @POST
+    @Path("{usestalelinkage}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response setVanishStaleLink(InputStream stream) {
+        try {
+            // Parse the input stream
+            ObjectNode root = (ObjectNode) mapper().readTree(stream);
+            if (root.has("active")) {
+                ComponentConfigService useStaleLink = get(ComponentConfigService.class);
+                useStaleLink.setProperty("org.onosproject.provider.lldp.impl.LldpLinkProvider",
+                   "useStaleLinkAge", String.valueOf(root.get("active")));
+            }
+        } catch (IOException ex) {
+            throw new IllegalArgumentException(ex);
+        }
+        return Response
+                .ok()
+                .build();
+    }
+
 }
diff --git a/web/api/src/main/resources/definitions/VanishedLink.json b/web/api/src/main/resources/definitions/VanishedLink.json
new file mode 100644
index 0000000..7bee04b
--- /dev/null
+++ b/web/api/src/main/resources/definitions/VanishedLink.json
@@ -0,0 +1,12 @@
+{
+    "type" : "object",
+    "required": [
+        "active"
+    ],
+    "properties": {
+        "active": {
+            "type": "boolean",
+            "example": true
+        }
+    }
+}