Secure LLDP-based Topology Detection

Current LLDP/BDDP-based Topology Detection is vulnerable to the
creation of fake links via forged, modified, or replayed LLDP packets.
This patch fixes this vulnerability by authenticating LLDP/BDDP packets
using a Message Authentication Code and adding a timestamp to prevent
replay. We use HMAC with SHA-256 has our Messge Authentication Code and
derive the key from the config/cluster.json file via the
ClusterMetadata class.

Change-Id: I01dd6edc5cffd6dfe274bcdb97189f2661a6c4f1
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 87ca7d7..3ea56af 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
@@ -101,7 +101,7 @@
 
     private static final String FORMAT =
             "Settings: enabled={}, useBDDP={}, probeRate={}, " +
-                    "staleLinkAge={}";
+                    "staleLinkAge={}, maxLLDPage={}";
 
     // When a Device/Port has this annotation, do not send out LLDP/BDDP
     public static final String NO_LLDP = "no-lldp";
@@ -174,6 +174,12 @@
             label = "Number of millis beyond which links will be considered stale")
     private int staleLinkAge = DEFAULT_STALE_LINK_AGE;
 
+    private static final String PROP_DISCOVERY_DELAY = "maxLLDPAge";
+    private static final int DEFAULT_DISCOVERY_DELAY = 1000;
+    @Property(name = PROP_DISCOVERY_DELAY, intValue = DEFAULT_DISCOVERY_DELAY,
+            label = "Number of millis beyond which an LLDP packet will not be accepted")
+    private int maxDiscoveryDelayMs = DEFAULT_DISCOVERY_DELAY;
+
     private final LinkDiscoveryContext context = new InternalDiscoveryContext();
     private final InternalRoleListener roleListener = new InternalRoleListener();
     private final InternalDeviceListener deviceListener = new InternalDeviceListener();
@@ -297,7 +303,7 @@
         Dictionary<?, ?> properties = context != null ? context.getProperties() : new Properties();
 
         boolean newEnabled, newUseBddp;
-        int newProbeRate, newStaleLinkAge;
+        int newProbeRate, newStaleLinkAge, newDiscoveryDelay;
         try {
             String s = get(properties, PROP_ENABLED);
             newEnabled = isNullOrEmpty(s) || Boolean.parseBoolean(s.trim());
@@ -311,12 +317,16 @@
             s = get(properties, PROP_STALE_LINK_AGE);
             newStaleLinkAge = isNullOrEmpty(s) ? staleLinkAge : Integer.parseInt(s.trim());
 
+            s = get(properties, PROP_DISCOVERY_DELAY);
+            newDiscoveryDelay = isNullOrEmpty(s) ? maxDiscoveryDelayMs : Integer.parseInt(s.trim());
+
         } catch (NumberFormatException e) {
             log.warn("Component configuration had invalid values", e);
             newEnabled = enabled;
             newUseBddp = useBddp;
             newProbeRate = probeRate;
             newStaleLinkAge = staleLinkAge;
+            newDiscoveryDelay = maxDiscoveryDelayMs;
         }
 
         boolean wasEnabled = enabled;
@@ -325,6 +335,7 @@
         useBddp = newUseBddp;
         probeRate = newProbeRate;
         staleLinkAge = newStaleLinkAge;
+        maxDiscoveryDelayMs = newDiscoveryDelay;
 
         if (!wasEnabled && enabled) {
             enable();
@@ -337,7 +348,7 @@
             }
         }
 
-        log.info(FORMAT, enabled, useBddp, probeRate, staleLinkAge);
+        log.info(FORMAT, enabled, useBddp, probeRate, staleLinkAge, maxDiscoveryDelayMs);
     }
 
     /**
@@ -795,6 +806,16 @@
         public String fingerprint() {
             return buildSrcMac();
         }
+
+        @Override
+        public String lldpSecret() {
+            return clusterMetadataService.getClusterMetadata().getClusterSecret();
+        }
+
+        @Override
+        public long maxDiscoveryDelay() {
+            return maxDiscoveryDelayMs;
+        }
     }
 
     static final EnumSet<NetworkConfigEvent.Type> CONFIG_CHANGED