Refactor MacAddress and ONOSLLDP class

- Implement unit tests for MacAddress
- Implement new method to get OUI
- Rename isLinkLocal to isLldp to describe this method more precisely
- Remove ON.Lab specific names in the code

Change-Id: I01ef9ed94f7bd7e3930a4746627257ef9667c7a3
diff --git a/apps/fwd/src/main/java/org/onosproject/fwd/ReactiveForwarding.java b/apps/fwd/src/main/java/org/onosproject/fwd/ReactiveForwarding.java
index a8ffed2..4b7ce67 100644
--- a/apps/fwd/src/main/java/org/onosproject/fwd/ReactiveForwarding.java
+++ b/apps/fwd/src/main/java/org/onosproject/fwd/ReactiveForwarding.java
@@ -468,8 +468,8 @@
 
             HostId id = HostId.hostId(ethPkt.getDestinationMAC());
 
-            // Do not process link-local addresses in any way.
-            if (id.mac().isLinkLocal()) {
+            // Do not process LLDP MAC address in any way.
+            if (id.mac().isLldp()) {
                 droppedPacket(macMetrics);
                 return;
             }
diff --git a/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LldpLinkProviderTest.java b/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LldpLinkProviderTest.java
index 811baac..9cdf90e 100644
--- a/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LldpLinkProviderTest.java
+++ b/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LldpLinkProviderTest.java
@@ -29,6 +29,7 @@
 import org.junit.Test;
 import org.onlab.packet.ChassisId;
 import org.onlab.packet.Ethernet;
+import org.onlab.packet.MacAddress;
 import org.onlab.packet.ONOSLLDP;
 import org.onosproject.cfg.ComponentConfigAdapter;
 import org.onosproject.cluster.ClusterMetadataServiceAdapter;
@@ -658,7 +659,7 @@
 
             Ethernet ethPacket = new Ethernet();
             ethPacket.setEtherType(Ethernet.TYPE_LLDP);
-            ethPacket.setDestinationMACAddress(ONOSLLDP.LLDP_ONLAB);
+            ethPacket.setDestinationMACAddress(MacAddress.ONOS_LLDP);
             ethPacket.setPayload(lldp);
             ethPacket.setPad(true);
 
diff --git a/providers/lldpcommon/src/main/java/org/onosproject/provider/lldpcommon/LinkDiscovery.java b/providers/lldpcommon/src/main/java/org/onosproject/provider/lldpcommon/LinkDiscovery.java
index b012d28..f4e2231 100644
--- a/providers/lldpcommon/src/main/java/org/onosproject/provider/lldpcommon/LinkDiscovery.java
+++ b/providers/lldpcommon/src/main/java/org/onosproject/provider/lldpcommon/LinkDiscovery.java
@@ -20,6 +20,7 @@
 import org.jboss.netty.util.Timeout;
 import org.jboss.netty.util.TimerTask;
 import org.onlab.packet.Ethernet;
+import org.onlab.packet.MacAddress;
 import org.onlab.packet.ONOSLLDP;
 import org.onlab.util.Timer;
 import org.onosproject.net.ConnectPoint;
@@ -82,12 +83,12 @@
 
         ethPacket = new Ethernet();
         ethPacket.setEtherType(Ethernet.TYPE_LLDP);
-        ethPacket.setDestinationMACAddress(ONOSLLDP.LLDP_ONLAB);
+        ethPacket.setDestinationMACAddress(MacAddress.ONOS_LLDP);
         ethPacket.setPad(true);
 
         bddpEth = new Ethernet();
         bddpEth.setEtherType(Ethernet.TYPE_BSN);
-        bddpEth.setDestinationMACAddress(ONOSLLDP.BDDP_MULTICAST);
+        bddpEth.setDestinationMACAddress(MacAddress.BROADCAST);
         bddpEth.setPad(true);
 
         isStopped = true;
diff --git a/providers/netcfglinks/src/test/java/org/onosproject/provider/netcfglinks/NetworkConfigLinksProviderTest.java b/providers/netcfglinks/src/test/java/org/onosproject/provider/netcfglinks/NetworkConfigLinksProviderTest.java
index ce33f22..c98c481 100644
--- a/providers/netcfglinks/src/test/java/org/onosproject/provider/netcfglinks/NetworkConfigLinksProviderTest.java
+++ b/providers/netcfglinks/src/test/java/org/onosproject/provider/netcfglinks/NetworkConfigLinksProviderTest.java
@@ -21,6 +21,7 @@
 import org.junit.Test;
 import org.onlab.packet.ChassisId;
 import org.onlab.packet.Ethernet;
+import org.onlab.packet.MacAddress;
 import org.onlab.packet.ONOSLLDP;
 import org.onosproject.cluster.ClusterMetadataServiceAdapter;
 import org.onosproject.core.CoreServiceAdapter;
@@ -152,7 +153,7 @@
 
             Ethernet ethPacket = new Ethernet();
             ethPacket.setEtherType(Ethernet.TYPE_LLDP);
-            ethPacket.setDestinationMACAddress(ONOSLLDP.LLDP_ONLAB);
+            ethPacket.setDestinationMACAddress(MacAddress.ONOS_LLDP);
             ethPacket.setPayload(lldp);
             ethPacket.setPad(true);
 
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 0fe46ab..a040b69 100644
--- a/utils/misc/src/main/java/org/onlab/packet/MacAddress.java
+++ b/utils/misc/src/main/java/org/onlab/packet/MacAddress.java
@@ -15,7 +15,10 @@
  */
 package org.onlab.packet;
 
+import com.google.common.collect.Sets;
+
 import java.util.Arrays;
+import java.util.Set;
 
 /**
  * The class representing MAC address.
@@ -24,8 +27,17 @@
 
     /**
      * Dummy MAC address.
+     * We use the first MAC address in ONOS OUI range as a dummy MAC address.
      */
-    public static final MacAddress NONE = valueOf("a4:23:05:00:00:00");
+    public static final MacAddress NONE = MacAddress.ONOS;
+    /**
+     * First MAC address in ONOS OUI range.
+     */
+    public static final MacAddress ONOS = valueOf("a4:23:05:00:00:00");
+    /**
+     * ONOS LLDP MAC address with multicast bit set.
+     */
+    public static final MacAddress ONOS_LLDP = valueOf("a5:23:05:00:00:01");
     /**
      * All-zero MAC address.
      */
@@ -42,11 +54,13 @@
      * IPv4 multicast MAC mask.
      */
     public static final MacAddress IPV4_MULTICAST_MASK = valueOf("ff:ff:ff:80:00:00");
-
-    private static final byte[] LL = new byte[]{
-            0x01, (byte) 0x80, (byte) 0xc2, 0x00, 0x00,
-            0x00, 0x0e, 0x03
-    };
+    /**
+     * A set of LLDP MAC addresses.
+     */
+    public static final Set<MacAddress> LLDP = Sets.newHashSet(
+            MacAddress.valueOf("01:80:c2:00:00:00"),
+            MacAddress.valueOf("01:80:c2:00:00:03"),
+            MacAddress.valueOf("01:80:c2:00:00:0e"));
 
     public static final int MAC_ADDRESS_LENGTH = 6;
     private byte[] address = new byte[MacAddress.MAC_ADDRESS_LENGTH];
@@ -183,11 +197,40 @@
      * Returns true if this MAC address is link local.
      *
      * @return true if link local
+     * @deprecated in Kingfisher release. Link local is not a correct description for
+     *             this MAC address. Replaced with {@link #isLldp()}
      */
+    @Deprecated
     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]);
+        return isLldp();
+    }
+
+    /**
+     * Returns true if this MAC address is used by link layer discovery protocol.
+     *
+     * @return true if this MAC is LLDP MAC.
+     */
+    public boolean isLldp() {
+        return LLDP.contains(this);
+    }
+
+    /**
+     * Returns true if the Organizationally Unique Identifier (OUI) of this MAC
+     * address matches ONOS OUI.
+     *
+     * @return true if the OUI of this MAC address matches ONOS OUI.
+     */
+    public boolean isOnos() {
+        return Arrays.equals(this.oui(), ONOS.oui());
+    }
+
+    /**
+     * Returns the Organizationally Unique Identifier (OUI) of this MAC address.
+     *
+     * @return the OUI of this MAC address.
+     */
+    public byte[] oui() {
+        return Arrays.copyOfRange(this.address, 0, 3);
     }
 
     @Override
diff --git a/utils/misc/src/main/java/org/onlab/packet/ONOSLLDP.java b/utils/misc/src/main/java/org/onlab/packet/ONOSLLDP.java
index 40e99d4..d94a7ba 100644
--- a/utils/misc/src/main/java/org/onlab/packet/ONOSLLDP.java
+++ b/utils/misc/src/main/java/org/onlab/packet/ONOSLLDP.java
@@ -30,13 +30,31 @@
  *  ONOS LLDP containing organizational TLV for ONOS device discovery.
  */
 public class ONOSLLDP extends LLDP {
-
+    /**
+     * ONOS OUI.
+     *
+     * @deprecated in Kingfisher. Use MacAddress.ONOS.oui() instead.
+     */
+    @Deprecated
     public static final byte[] ONLAB_OUI = {(byte) 0xa4, 0x23, 0x05};
+
     public static final String DEFAULT_DEVICE = "INVALID";
     public static final String DEFAULT_NAME = "ONOS Discovery";
 
-    // ON.Lab OUI (a42305) with multicast bit set
+    /**
+     * ONOS LLDP multicast MAC address.
+     *
+     * @deprecated in Kingfisher. Use MacAddress.ONOS_LLDP instead.
+     */
+    @Deprecated
     public static final byte[] LLDP_ONLAB = {(byte) 0xa5, 0x23, 0x05, 0x00, 0x00, 0x01};
+
+    /**
+     * ONOS BDDP broadcast MAC address.
+     *
+     * @deprecated in Kingfisher. Use MacAddress.BROADCASAT instead.
+     */
+    @Deprecated
     public static final byte[] BDDP_MULTICAST = {(byte) 0xff, (byte) 0xff,
             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
 
@@ -95,7 +113,7 @@
         nametlv.setLength((short) (name.length() + NAME_LENGTH));
         nametlv.setInfoString(name);
         nametlv.setSubType(NAME_SUBTYPE);
-        nametlv.setOUI(ONLAB_OUI);
+        nametlv.setOUI(MacAddress.ONOS.oui());
     }
 
     public void setDevice(String device) {
@@ -103,7 +121,7 @@
         devicetlv.setInfoString(device);
         devicetlv.setLength((short) (device.length() + DEVICE_LENGTH));
         devicetlv.setSubType(DEVICE_SUBTYPE);
-        devicetlv.setOUI(ONLAB_OUI);
+        devicetlv.setOUI(MacAddress.ONOS.oui());
     }
 
     public void setDomainInfo(String domainId) {
@@ -115,7 +133,7 @@
         domaintlv.setInfoString(domainId);
         domaintlv.setLength((short) (domainId.length() + DOMAIN_LENGTH));
         domaintlv.setSubType(DOMAIN_SUBTYPE);
-        domaintlv.setOUI(ONLAB_OUI);
+        domaintlv.setOUI(MacAddress.ONOS.oui());
     }
 
     public void setChassisId(final ChassisId chassisId) {
diff --git a/utils/misc/src/test/java/org/onlab/packet/MacAddressTest.java b/utils/misc/src/test/java/org/onlab/packet/MacAddressTest.java
new file mode 100644
index 0000000..38a3b43
--- /dev/null
+++ b/utils/misc/src/test/java/org/onlab/packet/MacAddressTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2017-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onlab.packet;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests for class {@link MacAddress}.
+ */
+public class MacAddressTest {
+    private static final MacAddress MAC_NORMAL = MacAddress.valueOf("00:00:00:00:00:01");
+    private static final MacAddress MAC_BCAST = MacAddress.valueOf("ff:ff:ff:ff:ff:ff");
+    private static final MacAddress MAC_MCAST = MacAddress.valueOf("01:00:5e:00:00:00");
+    private static final MacAddress MAC_MCAST_2 = MacAddress.valueOf("01:00:0c:cc:cc:cc");
+    private static final MacAddress MAC_LLDP = MacAddress.valueOf("01:80:c2:00:00:00");
+    private static final MacAddress MAC_LLDP_2 = MacAddress.valueOf("01:80:c2:00:00:03");
+    private static final MacAddress MAC_LLDP_3 = MacAddress.valueOf("01:80:c2:00:00:0e");
+    private static final MacAddress MAC_ONOS = MacAddress.valueOf("a4:23:05:01:02:03");
+    private static final MacAddress MAC_ONOS_EQUAL = MacAddress.valueOf("a4:23:05:01:02:03");
+
+    private static final byte[] OUI_ONOS = {(byte) 0xa4, (byte) 0x23, (byte) 0x05};
+    private static final byte[] MAC_ONOS_BYTE = {
+            (byte) 0xa4, (byte) 0x23, (byte) 0x05, (byte) 0x01, (byte) 0x02, (byte) 0x03
+    };
+    private static final long MAC_ONOS_LONG = 180470314762755L;
+    private static final String MAC_ONOS_STR = "A4:23:05:01:02:03";
+    private static final String MAC_ONOS_STR_NO_COLON = "A42305010203";
+
+    private static final int LENGTH = 6;
+
+    private static final String INVALID_STR = "invalid";
+    private static final byte[] INVALID_BYTE = {(byte) 0xaa};
+
+    @Test
+    public void testValueOfString() throws Exception {
+        assertArrayEquals(MAC_ONOS_BYTE, MacAddress.valueOf(MAC_ONOS_STR).toBytes());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testValueOfInvalidString() throws Exception {
+        MacAddress.valueOf(INVALID_STR);
+    }
+
+    @Test
+    public void testValueOfByte() throws Exception {
+        assertArrayEquals(MAC_ONOS_BYTE, MacAddress.valueOf(MAC_ONOS_BYTE).toBytes());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testValueOfInvalidByte() throws Exception {
+        MacAddress.valueOf(INVALID_BYTE);
+    }
+
+    @Test
+    public void testValueOfLong() throws Exception {
+        assertArrayEquals(MAC_ONOS_BYTE, MacAddress.valueOf(MAC_ONOS_LONG).toBytes());
+    }
+
+    @Test
+    public void testLength() throws Exception {
+        assertEquals(LENGTH, MAC_NORMAL.length());
+    }
+
+    @Test
+    public void testToBytes() throws Exception {
+        assertArrayEquals(MAC_ONOS_BYTE, MAC_ONOS.toBytes());
+    }
+
+    @Test
+    public void testToLong() throws Exception {
+        assertEquals(MAC_ONOS_LONG, MAC_ONOS.toLong());
+    }
+
+    @Test
+    public void testIsBroadcast() throws Exception {
+        assertFalse(MAC_NORMAL.isBroadcast());
+        assertTrue(MAC_BCAST.isBroadcast());
+        assertFalse(MAC_MCAST.isBroadcast());
+        assertFalse(MAC_MCAST_2.isBroadcast());
+        assertFalse(MAC_LLDP.isBroadcast());
+        assertFalse(MAC_LLDP_2.isBroadcast());
+        assertFalse(MAC_LLDP_3.isBroadcast());
+        assertFalse(MAC_ONOS.isBroadcast());
+    }
+
+    @Test
+    public void testIsMulticast() throws Exception {
+        // Note: LLDP MACs are also a multicast MACs
+        assertFalse(MAC_NORMAL.isMulticast());
+        assertFalse(MAC_BCAST.isMulticast());
+        assertTrue(MAC_MCAST.isMulticast());
+        assertTrue(MAC_MCAST_2.isMulticast());
+        assertTrue(MAC_LLDP.isMulticast());
+        assertTrue(MAC_LLDP_2.isMulticast());
+        assertTrue(MAC_LLDP_3.isMulticast());
+        assertFalse(MAC_ONOS.isMulticast());
+    }
+
+    @Test
+    @Deprecated
+    public void testIsLinkLocal() throws Exception {
+        assertFalse(MAC_NORMAL.isLinkLocal());
+        assertFalse(MAC_BCAST.isLinkLocal());
+        assertFalse(MAC_MCAST.isLinkLocal());
+        assertFalse(MAC_MCAST_2.isLinkLocal());
+        assertTrue(MAC_LLDP.isLinkLocal());
+        assertTrue(MAC_LLDP_2.isLinkLocal());
+        assertTrue(MAC_LLDP_3.isLinkLocal());
+        assertFalse(MAC_ONOS.isLinkLocal());
+    }
+
+
+    @Test
+    public void testIsLldp() throws Exception {
+        assertFalse(MAC_NORMAL.isLldp());
+        assertFalse(MAC_BCAST.isLldp());
+        assertFalse(MAC_MCAST.isLldp());
+        assertFalse(MAC_MCAST_2.isLldp());
+        assertTrue(MAC_LLDP.isLldp());
+        assertTrue(MAC_LLDP_2.isLldp());
+        assertTrue(MAC_LLDP_3.isLldp());
+        assertFalse(MAC_ONOS.isLldp());
+    }
+
+    @Test
+    public void testIsOnos() throws Exception {
+        assertFalse(MAC_NORMAL.isOnos());
+        assertFalse(MAC_BCAST.isOnos());
+        assertFalse(MAC_MCAST.isOnos());
+        assertFalse(MAC_MCAST_2.isOnos());
+        assertFalse(MAC_LLDP.isOnos());
+        assertFalse(MAC_LLDP_2.isOnos());
+        assertFalse(MAC_LLDP_3.isOnos());
+        assertTrue(MAC_ONOS.isOnos());
+    }
+
+    @Test
+    public void testOui() throws Exception {
+        assertArrayEquals(MAC_ONOS.oui(), OUI_ONOS);
+    }
+
+    @Test
+    public void testEquals() throws Exception {
+        assertTrue(MAC_ONOS.equals(MAC_ONOS));
+        assertFalse(MAC_ONOS.equals(MAC_ONOS_STR));
+        assertTrue(MAC_ONOS.equals(MAC_ONOS_EQUAL));
+        assertFalse(MAC_ONOS.equals(MAC_NORMAL));
+        assertFalse(MAC_ONOS.equals(MAC_BCAST));
+        assertFalse(MAC_ONOS.equals(MAC_MCAST));
+        assertFalse(MAC_ONOS.equals(MAC_MCAST_2));
+        assertFalse(MAC_ONOS.equals(MAC_LLDP));
+        assertFalse(MAC_ONOS.equals(MAC_LLDP_2));
+        assertFalse(MAC_ONOS.equals(MAC_LLDP_3));
+    }
+
+    @Test
+    public void testHashCode() throws Exception {
+        assertEquals(Long.hashCode(MAC_ONOS_LONG), MAC_ONOS.hashCode());
+    }
+
+    @Test
+    public void testToString() throws Exception {
+        assertEquals(MAC_ONOS_STR, MAC_ONOS.toString());
+    }
+
+    @Test
+    public void testToStringNoColon() throws Exception {
+        assertEquals(MAC_ONOS_STR_NO_COLON, MAC_ONOS.toStringNoColon());
+    }
+
+}
\ No newline at end of file