Added isLinkLocal predicate to MacAddress and used it in ReactiveForwarding.
diff --git a/apps/fwd/src/main/java/org/onlab/onos/fwd/ReactiveForwarding.java b/apps/fwd/src/main/java/org/onlab/onos/fwd/ReactiveForwarding.java
index 74e9b14..3578715 100644
--- a/apps/fwd/src/main/java/org/onlab/onos/fwd/ReactiveForwarding.java
+++ b/apps/fwd/src/main/java/org/onlab/onos/fwd/ReactiveForwarding.java
@@ -137,6 +137,11 @@
 
             HostId id = HostId.hostId(ethPkt.getDestinationMAC());
 
+            // Do not process link-local addresses in any way.
+            if (id.mac().isLinkLocal()) {
+                return;
+            }
+
             // Do we know who this is for? If not, flood and bail.
             Host dst = hostService.getHost(id);
             if (dst == null) {
diff --git a/providers/lldp/src/main/java/org/onlab/onos/provider/lldp/impl/LinkDiscovery.java b/providers/lldp/src/main/java/org/onlab/onos/provider/lldp/impl/LinkDiscovery.java
index 8a060c7..1bb81f1 100644
--- a/providers/lldp/src/main/java/org/onlab/onos/provider/lldp/impl/LinkDiscovery.java
+++ b/providers/lldp/src/main/java/org/onlab/onos/provider/lldp/impl/LinkDiscovery.java
@@ -18,20 +18,6 @@
  */
 package org.onlab.onos.provider.lldp.impl;
 
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.nio.ByteBuffer;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-
 import org.jboss.netty.util.Timeout;
 import org.jboss.netty.util.TimerTask;
 import org.onlab.onos.mastership.MastershipService;
@@ -39,10 +25,8 @@
 import org.onlab.onos.net.Device;
 import org.onlab.onos.net.DeviceId;
 import org.onlab.onos.net.Link.Type;
-import org.onlab.onos.net.MastershipRole;
 import org.onlab.onos.net.Port;
 import org.onlab.onos.net.PortNumber;
-import org.onlab.onos.net.flow.DefaultTrafficTreatment;
 import org.onlab.onos.net.link.DefaultLinkDescription;
 import org.onlab.onos.net.link.LinkDescription;
 import org.onlab.onos.net.link.LinkProviderService;
@@ -55,7 +39,21 @@
 import org.onlab.util.Timer;
 import org.slf4j.Logger;
 
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static org.onlab.onos.net.MastershipRole.MASTER;
+import static org.onlab.onos.net.PortNumber.portNumber;
+import static org.onlab.onos.net.flow.DefaultTrafficTreatment.builder;
+import static org.slf4j.LoggerFactory.getLogger;
 
 /**
  * Run discovery process from a physical switch. Ports are initially labeled as
@@ -63,7 +61,7 @@
  * fast. Every probeRate milliseconds, loop over all fast ports and send an
  * LLDP, send an LLDP for a single slow port. Based on FlowVisor topology
  * discovery implementation.
- *
+ * <p/>
  * TODO: add 'fast discovery' mode: drop LLDPs in destination switch but listen
  * for flow_removed messages
  */
@@ -93,13 +91,14 @@
      * Instantiates discovery manager for the given physical switch. Creates a
      * generic LLDP packet that will be customized for the port it is sent out on.
      * Starts the the timer for the discovery process.
-     * @param device the physical switch
-     * @param masterService
-     * @param useBDDP flag to also use BDDP for discovery
+     *
+     * @param device        the physical switch
+     * @param masterService mastership service
+     * @param useBDDP       flag to also use BDDP for discovery
      */
     public LinkDiscovery(Device device, PacketService pktService,
-                         MastershipService masterService, LinkProviderService providerService, Boolean... useBDDP) {
-
+                         MastershipService masterService,
+                         LinkProviderService providerService, Boolean... useBDDP) {
         this.device = device;
         this.probeRate = 3000;
         this.linkProvider = providerService;
@@ -142,16 +141,12 @@
      * @param port the port
      */
     public void addPort(final Port port) {
-        this.log.debug("sending init probe to port {}@{}",
-                           port.number().toLong(), device.id());
-
+        this.log.debug("Sending init probe to port {}@{}",
+                       port.number().toLong(), device.id());
         sendProbes(port.number().toLong());
-
         synchronized (this) {
             this.slowPorts.add(port.number().toLong());
         }
-
-
     }
 
     /**
@@ -172,9 +167,8 @@
                 this.portProbeCount.remove(portnum);
                 // no iterator to update
             } else {
-                this.log.warn(
-                        "tried to dynamically remove non-existing port {}",
-                        portnum);
+                this.log.warn("Tried to dynamically remove non-existing port {}",
+                              portnum);
             }
         }
     }
@@ -187,21 +181,17 @@
      * @param portNumber the port
      */
     public void ackProbe(final Long portNumber) {
-
         synchronized (this) {
             if (this.slowPorts.contains(portNumber)) {
                 this.log.debug("Setting slow port to fast: {}:{}",
-                        this.device.id(), portNumber);
+                               this.device.id(), portNumber);
                 this.slowPorts.remove(portNumber);
                 this.fastPorts.add(portNumber);
                 this.portProbeCount.put(portNumber, new AtomicInteger(0));
             } else if (this.fastPorts.contains(portNumber)) {
-                    this.portProbeCount.get(portNumber).set(0);
+                this.portProbeCount.get(portNumber).set(0);
             } else {
-                    this.log.debug(
-                            "Got ackProbe for non-existing port: {}",
-                            portNumber);
-
+                this.log.debug("Got ackProbe for non-existing port: {}", portNumber);
             }
         }
     }
@@ -217,7 +207,7 @@
         if (onoslldp != null) {
             final PortNumber dstPort =
                     context.inPacket().receivedFrom().port();
-            final PortNumber srcPort = PortNumber.portNumber(onoslldp.getPort());
+            final PortNumber srcPort = portNumber(onoslldp.getPort());
             final DeviceId srcDeviceId = DeviceId.deviceId(onoslldp.getDeviceString());
             final DeviceId dstDeviceId = context.inPacket().receivedFrom().deviceId();
             this.ackProbe(dstPort.toLong());
@@ -237,61 +227,48 @@
     }
 
 
-
     /**
      * Execute this method every t milliseconds. Loops over all ports
      * labeled as fast and sends out an LLDP. Send out an LLDP on a single slow
      * port.
      *
      * @param t timeout
-     * @throws Exception
      */
     @Override
     public void run(final Timeout t) {
-        this.log.trace("sending probes from {}", device.id());
+        this.log.trace("Sending probes from {}", device.id());
         synchronized (this) {
             final Iterator<Long> fastIterator = this.fastPorts.iterator();
-            Long portNumber;
-            Integer probeCount;
             while (fastIterator.hasNext()) {
-                portNumber = fastIterator.next();
-                probeCount = this.portProbeCount.get(portNumber)
-                        .getAndIncrement();
+                long portNumber = fastIterator.next();
+                int probeCount = portProbeCount.get(portNumber).getAndIncrement();
 
                 if (probeCount < LinkDiscovery.MAX_PROBE_COUNT) {
-                    this.log.trace("sending fast probe to port {}", portNumber);
+                    this.log.trace("Sending fast probe to port {}", portNumber);
                     sendProbes(portNumber);
+
                 } else {
                     // Update fast and slow ports
                     fastIterator.remove();
                     this.slowPorts.add(portNumber);
                     this.portProbeCount.remove(portNumber);
 
-
-                    ConnectPoint cp = new ConnectPoint(
-                            device.id(),
-                            PortNumber.portNumber(portNumber));
+                    ConnectPoint cp = new ConnectPoint(device.id(),
+                                                       portNumber(portNumber));
                     log.debug("Link down -> {}", cp);
                     linkProvider.linksVanished(cp);
                 }
             }
 
             // send a probe for the next slow port
-            if (!this.slowPorts.isEmpty()) {
-                Iterator<Long> slowIterator = this.slowPorts.iterator();
-                while (slowIterator.hasNext()) {
-                    portNumber = slowIterator.next();
-                    this.log.trace("sending slow probe to port {}", portNumber);
-
-                    sendProbes(portNumber);
-
-                }
+            for (long portNumber : slowPorts) {
+                this.log.trace("Sending slow probe to port {}", portNumber);
+                sendProbes(portNumber);
             }
         }
 
         // reschedule timer
-        timeout = Timer.getTimer().newTimeout(this, this.probeRate,
-                TimeUnit.MILLISECONDS);
+        timeout = Timer.getTimer().newTimeout(this, this.probeRate, MILLISECONDS);
     }
 
     public void stop() {
@@ -300,8 +277,7 @@
     }
 
     public void start() {
-        timeout = Timer.getTimer().newTimeout(this, 0,
-                                              TimeUnit.MILLISECONDS);
+        timeout = Timer.getTimer().newTimeout(this, 0, MILLISECONDS);
         isStopped = false;
     }
 
@@ -319,12 +295,9 @@
         this.ethPacket.setSourceMACAddress("DE:AD:BE:EF:BA:11");
 
         final byte[] lldp = this.ethPacket.serialize();
-        OutboundPacket outboundPacket = new DefaultOutboundPacket(
-                this.device.id(),
-                DefaultTrafficTreatment.builder().setOutput(
-                        PortNumber.portNumber(port)).build(),
-                ByteBuffer.wrap(lldp));
-        return outboundPacket;
+        return new DefaultOutboundPacket(this.device.id(),
+                                         builder().setOutput(portNumber(port)).build(),
+                                         ByteBuffer.wrap(lldp));
     }
 
     /**
@@ -341,39 +314,26 @@
         this.bddpEth.setSourceMACAddress("DE:AD:BE:EF:BA:11");
 
         final byte[] bddp = this.bddpEth.serialize();
-        OutboundPacket outboundPacket = new DefaultOutboundPacket(
-                this.device.id(),
-                DefaultTrafficTreatment.builder()
-                        .setOutput(PortNumber.portNumber(port)).build(),
-                ByteBuffer.wrap(bddp));
-        return outboundPacket;
+        return new DefaultOutboundPacket(this.device.id(),
+                                         builder().setOutput(portNumber(port)).build(),
+                                         ByteBuffer.wrap(bddp));
     }
 
     private void sendProbes(Long portNumber) {
-       if (device == null) {
-           log.warn("CRAZY SHIT");
-       }
-       if (mastershipService == null) {
-           log.warn("INSANE");
-       }
-       if (device.type() != Device.Type.ROADM &&
-               mastershipService.getLocalRole(this.device.id()) ==
-               MastershipRole.MASTER) {
-           log.debug("sending probes out to {}@{}", portNumber, device.id());
-           OutboundPacket pkt = this.createOutBoundLLDP(portNumber);
-           pktService.emit(pkt);
-           if (useBDDP) {
-               OutboundPacket bpkt = this.createOutBoundBDDP(portNumber);
-               pktService.emit(bpkt);
-           }
-       }
+        boolean isMaster = mastershipService.getLocalRole(device.id()) == MASTER;
+        if (isMaster && device.type() != Device.Type.ROADM) {
+            log.debug("Sending probes out to {}@{}", portNumber, device.id());
+            OutboundPacket pkt = this.createOutBoundLLDP(portNumber);
+            pktService.emit(pkt);
+            if (useBDDP) {
+                OutboundPacket bpkt = this.createOutBoundBDDP(portNumber);
+                pktService.emit(bpkt);
+            }
+        }
     }
 
     public boolean containsPort(Long portNumber) {
-        if (slowPorts.contains(portNumber) || fastPorts.contains(portNumber)) {
-            return true;
-        }
-        return false;
+        return slowPorts.contains(portNumber) || fastPorts.contains(portNumber);
     }
 
     public boolean isStopped() {
diff --git a/utils/misc/src/main/java/org/onlab/packet/MacAddress.java b/utils/misc/src/main/java/org/onlab/packet/MacAddress.java
index 05e0f7b..78114cc 100644
--- a/utils/misc/src/main/java/org/onlab/packet/MacAddress.java
+++ b/utils/misc/src/main/java/org/onlab/packet/MacAddress.java
@@ -22,7 +22,6 @@
 
 /**
  * The class representing MAC address.
- *
  */
 public class MacAddress {
 
@@ -32,6 +31,11 @@
     public static final byte[] ZERO_MAC_ADDRESS = ZERO.getAddress();
     public static final byte[] BROADCAST_MAC = BROADCAST.getAddress();
 
+    private static final byte[] LL = new byte[]{
+            0x01, (byte) 0x80, (byte) 0xc2, 0x00, 0x00,
+            0x00, 0x0e, 0x03
+    };
+
     public static final int MAC_ADDRESS_LENGTH = 6;
     private byte[] address = new byte[MacAddress.MAC_ADDRESS_LENGTH];
 
@@ -43,12 +47,10 @@
      * Returns a MAC address instance representing the value of the specified
      * {@code String}.
      *
-     * @param address
-     *            the String representation of the MAC Address to be parsed.
+     * @param address the String representation of the MAC Address to be parsed.
      * @return a MAC Address instance representing the value of the specified
-     *         {@code String}.
-     * @throws IllegalArgumentException
-     *             if the string cannot be parsed as a MAC address.
+     * {@code String}.
+     * @throws IllegalArgumentException if the string cannot be parsed as a MAC address.
      */
     public static MacAddress valueOf(final String address) {
         final String[] elements = address.split(":");
@@ -71,17 +73,15 @@
      * Returns a MAC address instance representing the specified {@code byte}
      * array.
      *
-     * @param address
-     *            the byte array to be parsed.
+     * @param address the byte array to be parsed.
      * @return a MAC address instance representing the specified {@code byte}
-     *         array.
-     * @throws IllegalArgumentException
-     *             if the byte array cannot be parsed as a MAC address.
+     * array.
+     * @throws IllegalArgumentException if the byte array cannot be parsed as a MAC address.
      */
     public static MacAddress valueOf(final byte[] address) {
         if (address.length != MacAddress.MAC_ADDRESS_LENGTH) {
             throw new IllegalArgumentException("the length is not "
-                    + MacAddress.MAC_ADDRESS_LENGTH);
+                                                       + MacAddress.MAC_ADDRESS_LENGTH);
         }
 
         return new MacAddress(address);
@@ -92,19 +92,17 @@
      * value. The lower 48 bits of the long value are used to parse as a MAC
      * address.
      *
-     * @param address
-     *            the long value to be parsed. The lower 48 bits are used for a
-     *            MAC address.
+     * @param address the long value to be parsed. The lower 48 bits are used for a
+     *                MAC address.
      * @return a MAC address instance representing the specified {@code long}
-     *         value.
-     * @throws IllegalArgumentException
-     *             if the long value cannot be parsed as a MAC address.
+     * value.
+     * @throws IllegalArgumentException if the long value cannot be parsed as a MAC address.
      */
     public static MacAddress valueOf(final long address) {
-        final byte[] addressInBytes = new byte[] {
+        final byte[] addressInBytes = new byte[]{
                 (byte) (address >> 40 & 0xff), (byte) (address >> 32 & 0xff),
                 (byte) (address >> 24 & 0xff), (byte) (address >> 16 & 0xff),
-                (byte) (address >> 8 & 0xff), (byte) (address >> 0 & 0xff) };
+                (byte) (address >> 8 & 0xff), (byte) (address >> 0 & 0xff)};
 
         return new MacAddress(addressInBytes);
     }
@@ -122,7 +120,7 @@
      * Returns the value of the {@code MACAddress} as a {@code byte} array.
      *
      * @return the numeric value represented by this object after conversion to
-     *         type {@code byte} array.
+     * type {@code byte} array.
      */
     public byte[] toBytes() {
         return Arrays.copyOf(this.address, this.address.length);
@@ -132,7 +130,7 @@
      * Returns the value of the {@code MACAddress} as a {@code long}.
      *
      * @return the numeric value represented by this object after conversion to
-     *         type {@code long}.
+     * type {@code long}.
      */
     public long toLong() {
         long mac = 0;
@@ -169,6 +167,17 @@
         return (this.address[0] & 0x01) != 0;
     }
 
+    /**
+     * Returns true if this MAC address is link local.
+     *
+     * @return true if link local
+     */
+    public boolean isLinkLocal() {
+        return LL[0] == address[0] && LL[1] == address[1] && LL[2] == address[2] &&
+                LL[3] == address[3] && LL[4] == address[4] &&
+                (LL[5] == address[5] || LL[6] == address[5] || LL[7] == address[5]);
+    }
+
     @Override
     public boolean equals(final Object o) {
         if (o == this) {
@@ -202,7 +211,7 @@
 
     /**
      * @return MAC address in string representation without colons (useful for
-     *         radix tree storage)
+     * radix tree storage)
      */
     public String toStringNoColon() {
         final StringBuilder builder = new StringBuilder();