diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
index a3f11a0a3f436f4a76f65656e4609a11f3cc28b0..cb5c0fcb25c22be4fbd76d03ac26a1a922cd3d5a 100755
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java
@@ -909,6 +909,7 @@ public class DeviceManagerImpl implements IDeviceService, IOFMessageListener, IT
 		this.perClassIndices =
 				new HashSet<EnumSet<DeviceField>>();
 		addIndex(true, EnumSet.of(DeviceField.IPv4));
+		addIndex(true, EnumSet.of(DeviceField.IPv6));
 
 		this.deviceListeners = new ListenerDispatcher<String, IDeviceListener>();
 		this.suppressAPs = Collections.newSetFromMap(
diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceUniqueIndex.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceUniqueIndex.java
index 40ae3c91ec4ae1564c9e6ae60b9040fb1d09f24f..3917f493b0788f409babae395de503cba71f0e6a 100644
--- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceUniqueIndex.java
+++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceUniqueIndex.java
@@ -113,5 +113,4 @@ public class DeviceUniqueIndex extends DeviceIndex {
             return null;
         return deviceKey;
     }
-
-}
+}
\ No newline at end of file
diff --git a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
index e8722b42d917eefcd7881066a4df59989b5cfed2..748516618cc16b45ed2feddfe99642668ca6a7b7 100644
--- a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
+++ b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java
@@ -79,6 +79,7 @@ import net.floodlightcontroller.packet.Data;
 import net.floodlightcontroller.packet.Ethernet;
 import net.floodlightcontroller.packet.IPacket;
 import net.floodlightcontroller.packet.IPv4;
+import net.floodlightcontroller.packet.IPv6;
 import net.floodlightcontroller.packet.UDP;
 import net.floodlightcontroller.restserver.IRestApiService;
 import net.floodlightcontroller.restserver.RestApiServer;
@@ -119,8 +120,12 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
 
 	protected OFPacketIn testARPReplyPacketIn_1, testARPReplyPacketIn_2;
 	protected OFPacketIn testUDPPacketIn;
+	protected OFPacketIn testUDPIPv6PacketIn;
+	protected OFPacketIn testUDPIPv6RevPacketIn;
 	protected IPacket testARPReplyPacket_1, testARPReplyPacket_2;
 	protected Ethernet testUDPPacket;
+	protected Ethernet testUDPIPv6Packet;
+	protected Ethernet testUDPIPv6RevPacket;
 	protected byte[] testARPReplyPacket_1_Srld, testARPReplyPacket_2_Srld;
 	protected byte[] testUDPPacketSrld;
 	private MockSyncService syncService;
@@ -287,7 +292,37 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
 				.setPayload(new Data(new byte[] {0x01}))));
 		updateUDPPacketIn();
 
-		//TODO test UDP IPv6 packet
+		// This packet is used to test forming an entity from an IPv6 packet
+		this.testUDPIPv6Packet = (Ethernet) new Ethernet()
+		.setSourceMACAddress("00:11:22:33:44:55")
+		.setDestinationMACAddress("00:44:33:22:11:01")
+		.setEtherType(EthType.IPv6)
+		.setVlanID((short)5)
+		.setPayload(
+				new IPv6()
+				.setHopLimit((byte) 128)
+				.setSourceAddress(IPv6Address.of(1,1))
+				.setDestinationAddress(IPv6Address.of(2,2))
+				.setPayload(new UDP()
+				.setSourcePort((short) 5000)
+				.setDestinationPort((short) 5001)
+				.setPayload(new Data(new byte[] {0x01}))));
+
+		// This packet reverses the above
+		this.testUDPIPv6RevPacket = (Ethernet) new Ethernet()
+		.setSourceMACAddress("00:44:33:22:11:01")
+		.setDestinationMACAddress("00:11:22:33:44:55")
+		.setEtherType(EthType.IPv6)
+		.setVlanID((short)5)
+		.setPayload(
+				new IPv6()
+				.setHopLimit((byte) 128)
+				.setSourceAddress(IPv6Address.of(2,2))
+				.setDestinationAddress(IPv6Address.of(1,1))
+				.setPayload(new UDP()
+				.setSourcePort((short) 5001)
+				.setDestinationPort((short) 5000)
+				.setPayload(new Data(new byte[] {0x01}))));
 
 		// Build the PacketIn
 		this.testARPReplyPacketIn_1 = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn()
@@ -304,6 +339,20 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
 				.setData(this.testARPReplyPacket_2_Srld)
 				.setReason(OFPacketInReason.NO_MATCH)
 				.build();
+
+		this.testUDPIPv6PacketIn = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn()
+				.setBufferId(OFBufferId.NO_BUFFER)
+				.setMatch(OFFactories.getFactory(OFVersion.OF_13).buildMatch().setExact(MatchField.IN_PORT, OFPort.of(1)).build())
+				.setData(this.testUDPIPv6Packet.serialize())
+				.setReason(OFPacketInReason.NO_MATCH)
+				.build();
+		
+		this.testUDPIPv6RevPacketIn = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn()
+				.setBufferId(OFBufferId.NO_BUFFER)
+				.setMatch(OFFactories.getFactory(OFVersion.OF_13).buildMatch().setExact(MatchField.IN_PORT, OFPort.of(1)).build())
+				.setData(this.testUDPIPv6RevPacket.serialize())
+				.setReason(OFPacketInReason.NO_MATCH)
+				.build();
 	}
 
 	/**
@@ -380,7 +429,6 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
 
 		deviceManager.topology = mockTopology;
 
-		//TODO add entities for IPv6
 		Entity entity1 = new Entity(MacAddress.of(1L), VlanVid.ZERO, IPv4Address.NONE, IPv6Address.NONE, DatapathId.of(1L), OFPort.of(1), new Date());
 		Entity entity2 = new Entity(MacAddress.of(1L), VlanVid.ZERO, IPv4Address.NONE, IPv6Address.NONE, DatapathId.of(10L), OFPort.of(1), new Date());
 		Entity entity3 = new Entity(MacAddress.of(1L), VlanVid.ZERO, IPv4Address.of(1), IPv6Address.NONE, DatapathId.of(10L), OFPort.of(1), new Date());
@@ -514,6 +562,175 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
 		verify(mockListener);
 	}
 
+	@Test
+	public void testEntityLearningIPv6() throws Exception {
+		IDeviceListener mockListener =
+				createMock(IDeviceListener.class);
+		expect(mockListener.getName()).andReturn("mockListener").atLeastOnce();
+		expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject()))
+		.andReturn(false).atLeastOnce();
+		expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject()))
+		.andReturn(false).atLeastOnce();
+
+		replay(mockListener);
+		deviceManager.addListener(mockListener);
+		verify(mockListener);
+		reset(mockListener);
+		deviceManager.entityClassifier= new MockEntityClassifier();
+		deviceManager.startUp(null);
+
+		ITopologyService mockTopology = createMock(ITopologyService.class);
+		expect(mockTopology.getL2DomainId(DatapathId.of(anyLong()))).
+		andReturn(DatapathId.of(1L)).anyTimes();
+		expect(mockTopology.isBroadcastDomainPort(DatapathId.of(anyLong()), OFPort.of(anyShort()))).
+		andReturn(false).anyTimes();
+
+		expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()),
+				OFPort.of(anyShort()))).andReturn(true).anyTimes();
+		expect(mockTopology.isConsistent(DatapathId.of(10L), OFPort.of(1), DatapathId.of(10L), OFPort.of(1))).
+		andReturn(true).anyTimes();
+		expect(mockTopology.isConsistent(DatapathId.of(1L), OFPort.of(1), DatapathId.of(1L), OFPort.of(1))).
+		andReturn(true).anyTimes();
+		expect(mockTopology.isConsistent(DatapathId.of(50L), OFPort.of(3), DatapathId.of(50L), OFPort.of(3))).
+		andReturn(true).anyTimes();
+
+		Date topologyUpdateTime = new Date();
+		expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime).
+		anyTimes();
+
+		deviceManager.topology = mockTopology;
+
+		Entity entity1 = new Entity(MacAddress.of(1L), VlanVid.ZERO, IPv4Address.NONE, IPv6Address.NONE, DatapathId.of(1L), OFPort.of(1), new Date());
+		Entity entity2 = new Entity(MacAddress.of(1L), VlanVid.ZERO, IPv4Address.NONE, IPv6Address.NONE, DatapathId.of(10L), OFPort.of(1), new Date());
+		Entity entity3 = new Entity(MacAddress.of(1L), VlanVid.ZERO, IPv4Address.NONE, IPv6Address.of(1, 1), DatapathId.of(10L), OFPort.of(1), new Date());
+		Entity entity4 = new Entity(MacAddress.of(1L), VlanVid.ZERO, IPv4Address.NONE, IPv6Address.of(1, 1), DatapathId.of(1L), OFPort.of(1), new Date());
+		Entity entity5 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(4), IPv4Address.NONE, IPv6Address.of(1, 1), DatapathId.of(5L), OFPort.of(2), new Date());
+		Entity entity6 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(4), IPv4Address.NONE, IPv6Address.of(1, 1), DatapathId.of(50L), OFPort.of(3), new Date());
+		Entity entity7 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(4), IPv4Address.NONE, IPv6Address.of(2, 2), DatapathId.of(50L), OFPort.of(3), new Date());
+
+		mockListener.deviceAdded(isA(IDevice.class));
+		replay(mockListener, mockTopology);
+
+		Device d1 = deviceManager.learnDeviceByEntity(entity1);
+		assertSame(d1, deviceManager.learnDeviceByEntity(entity1));
+		assertSame(d1, deviceManager.findDeviceByEntity(entity1));
+		assertEquals(DefaultEntityClassifier.entityClass ,
+				d1.getEntityClass());
+		assertArrayEquals(new VlanVid[] { VlanVid.ZERO }, d1.getVlanId());
+		assertArrayEquals(new IPv6Address[] { }, d1.getIPv6Addresses());
+
+		assertEquals(1, deviceManager.getAllDevices().size());
+		verify(mockListener);
+
+		reset(mockListener);
+		mockListener.deviceAdded(isA(IDevice.class));
+		replay(mockListener);
+
+		Device d2 = deviceManager.learnDeviceByEntity(entity2);
+		assertFalse(d1.equals(d2));
+		assertNotSame(d1, d2);
+		assertNotSame(d1.getDeviceKey(), d2.getDeviceKey());
+		assertEquals(MockEntityClassifier.testEC, d2.getEntityClass());
+		assertArrayEquals(new VlanVid[] { VlanVid.ZERO }, d2.getVlanId());
+		assertArrayEquals(new IPv6Address[] { }, d2.getIPv6Addresses());
+
+		assertEquals(2, deviceManager.getAllDevices().size());
+		verify(mockListener);
+
+		reset(mockListener);
+		mockListener.deviceIPV6AddrChanged(isA(IDevice.class));
+		replay(mockListener);
+
+		Device d3 = deviceManager.learnDeviceByEntity(entity3);
+		assertNotSame(d2, d3);
+		assertEquals(d2.getDeviceKey(), d3.getDeviceKey());
+		assertEquals(MockEntityClassifier.testEC, d3.getEntityClass());
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(1, 1) },
+				d3.getIPv6Addresses());
+		assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(10L), OFPort.of(1)) },
+				d3.getAttachmentPoints());
+		assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(10L), OFPort.of(1)) },
+				d3.getAttachmentPoints(true));
+		assertArrayEquals(new VlanVid[] { VlanVid.ZERO },
+				d3.getVlanId());
+
+		assertEquals(2, deviceManager.getAllDevices().size());
+		verify(mockListener);
+
+		reset(mockListener);
+		mockListener.deviceIPV6AddrChanged(isA(IDevice.class));
+		replay(mockListener);
+
+		Device d4 = deviceManager.learnDeviceByEntity(entity4);
+		assertNotSame(d1, d4);
+		assertEquals(d1.getDeviceKey(), d4.getDeviceKey());
+		assertEquals(DefaultEntityClassifier.entityClass, d4.getEntityClass());
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(1, 1) },
+				d4.getIPv6Addresses());
+		assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)) },
+				d4.getAttachmentPoints());
+		assertArrayEquals(new VlanVid[] { VlanVid.ZERO },
+				d4.getVlanId());
+
+		assertEquals(2, deviceManager.getAllDevices().size());
+		verify(mockListener);
+
+		reset(mockListener);
+		mockListener.deviceAdded((isA(IDevice.class)));
+		replay(mockListener);
+
+		Device d5 = deviceManager.learnDeviceByEntity(entity5);
+		assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(5L), OFPort.of(2)) },
+				d5.getAttachmentPoints());
+		assertArrayEquals(new VlanVid[] { VlanVid.ofVlan(4) },
+				d5.getVlanId());
+		assertEquals(MacAddress.of(2L), d5.getMACAddress());
+		assertEquals("00:00:00:00:00:02", d5.getMACAddressString());
+		verify(mockListener);
+
+		reset(mockListener);
+		mockListener.deviceAdded(isA(IDevice.class));
+		replay(mockListener);
+
+		Device d6 = deviceManager.learnDeviceByEntity(entity6);
+		assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(50L), OFPort.of(3)) },
+				d6.getAttachmentPoints());
+		assertArrayEquals(new VlanVid[] { VlanVid.ofVlan(4) },
+				d6.getVlanId());
+
+		assertEquals(4, deviceManager.getAllDevices().size());
+		verify(mockListener);
+
+		reset(mockListener);
+		mockListener.deviceIPV6AddrChanged(isA(IDevice.class));
+		replay(mockListener);
+
+		Device d7 = deviceManager.learnDeviceByEntity(entity7);
+		assertNotSame(d6, d7);
+		assertEquals(d6.getDeviceKey(), d7.getDeviceKey());
+		assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(50L), OFPort.of(3)) },
+				d7.getAttachmentPoints());
+		assertArrayEquals(new VlanVid[] { VlanVid.ofVlan(4) },
+				d7.getVlanId());
+
+		assertEquals(4, deviceManager.getAllDevices().size());
+		verify(mockListener);
+
+		reset(mockListener);
+		replay(mockListener);
+
+		reset(deviceManager.topology);
+		deviceManager.topology.addListener(deviceManager);
+		expectLastCall().times(1);
+		replay(deviceManager.topology);
+
+		deviceManager.entityClassifier = new MockEntityClassifierMac();
+		deviceManager.startUp(null);
+		Entity entityNoClass = new Entity(MacAddress.of(5L), VlanVid.ofVlan(1), IPv4Address.NONE, IPv6Address.of(5, 5), DatapathId.of(-1L), OFPort.of(1), new Date());
+		assertEquals(null, deviceManager.learnDeviceByEntity(entityNoClass));
+
+		verify(mockListener);
+	}
 
 	private void doTestEntityOrdering(boolean computeInsertionPoint) throws Exception {
 		Entity e = new Entity(MacAddress.of(10L), VlanVid.ZERO, IPv4Address.NONE, IPv6Address.NONE, DatapathId.NONE, OFPort.ZERO, Entity.NO_DATE);
@@ -866,11 +1083,6 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
 		mockListener.deviceIPV4AddrChanged((isA(IDevice.class)));
 		replay(mockListener);
 
-		// TODO: we currently do learn entities on suppressed APs
-		// // cannot learn device on suppressed AP
-		// d = deviceManager.learnDeviceByEntity(entity1);
-		// assertNull(d);
-
 		/* Device is learned w/o attachment point */
 		deviceManager.learnDeviceByEntity(entity0);
 		/* Device is "seen" with a suppressed AP now, so we shouldn't learn the AP but still keep the entity */
@@ -1211,6 +1423,109 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
 		assertEquals(2, deviceManager.getAllDevices().size());
 	}
 
+	@Test
+	public void testPacketInBasicIPv6() throws Exception {
+		MacAddress deviceMac =
+				((Ethernet)this.testUDPIPv6Packet).getSourceMACAddress();
+		OFPacketIn packetIn = testUDPIPv6PacketIn;
+		IPv6Address ipaddr = IPv6Address.of(1, 1);
+
+		// Mock up our expected behavior
+		ITopologyService mockTopology = createMock(ITopologyService.class);
+		deviceManager.topology = mockTopology;
+		mockTopologyForPacketInTests(mockTopology);
+		replay(mockTopology);
+
+		FloodlightContext cntx = new FloodlightContext();
+		Command cmd = dispatchPacketIn(1L, packetIn, cntx);
+		verify(mockTopology);
+		assertEquals(Command.CONTINUE, cmd);
+		// Verify the device
+		Device rdevice = (Device)
+				deviceManager.findDevice(deviceMac,
+						VlanVid.ofVlan(5), IPv4Address.NONE, IPv6Address.NONE, DatapathId.NONE, OFPort.ZERO);
+		verifyDevice(rdevice, deviceMac, VlanVid.ofVlan(5), IPv4Address.NONE, ipaddr, DatapathId.of(1), OFPort.of(1));
+		IDevice cntxSrcDev = IDeviceService.fcStore.get(cntx,
+				IDeviceService.CONTEXT_SRC_DEVICE);
+		assertEquals(rdevice, cntxSrcDev);
+		IDevice cntxDstDev = IDeviceService.fcStore.get(cntx,
+				IDeviceService.CONTEXT_DST_DEVICE);
+		assertNull(cntxDstDev);
+
+		Device result = null;
+		Iterator<? extends IDevice> dstiter =
+				deviceManager.queryDevices(MacAddress.NONE, null /* any VLAN here */, IPv4Address.NONE,
+						ipaddr, DatapathId.NONE, OFPort.ZERO);
+		if (dstiter.hasNext()) {
+			result = (Device)dstiter.next();
+		}
+		assertFalse("There shouldn't be more than 1 device", dstiter.hasNext());
+		assertEquals(rdevice, result);
+
+
+		//-----------------
+		// Test packetIn again with a different source port. Should be
+		// the same device
+		reset(mockTopology);
+		mockTopologyForPacketInTests(mockTopology);
+		replay(mockTopology);
+
+		// trigger the packet in
+		cntx = new FloodlightContext();
+		packetIn = packetIn.createBuilder().setMatch(OFFactories.getFactory(OFVersion.OF_13).buildMatch().setExact(MatchField.IN_PORT, OFPort.of(2)).build()).build();
+		cmd = dispatchPacketIn(5L, packetIn, cntx);
+		verify(mockTopology);
+		// Verify the replay matched our expectations
+		assertEquals(Command.CONTINUE, cmd);
+
+		// Verify the device
+		rdevice = (Device)
+				deviceManager.findDevice(deviceMac,
+						VlanVid.ofVlan(5), IPv4Address.NONE, IPv6Address.NONE, DatapathId.NONE, OFPort.ZERO);
+		verifyDevice(rdevice, deviceMac, VlanVid.ofVlan(5), IPv4Address.NONE, ipaddr, DatapathId.of(5), OFPort.of(2));
+		cntxSrcDev = IDeviceService.fcStore.get(cntx,
+				IDeviceService.CONTEXT_SRC_DEVICE);
+		assertEquals(rdevice, cntxSrcDev);
+		cntxDstDev = IDeviceService.fcStore.get(cntx,
+				IDeviceService.CONTEXT_DST_DEVICE);
+		assertNull(cntxDstDev);
+		// There can be only one device
+		assertEquals(1, deviceManager.getAllDevices().size());
+
+		//----------------------------
+		// Test packetIn with a different packet going the reverse direction.
+		// We should now get source and dest device in the context
+		//==> The destination device in this step has been learned just before
+		MacAddress srcMac = testUDPIPv6RevPacket.getSourceMACAddress();
+		MacAddress dstMac = deviceMac;
+		reset(mockTopology);
+		mockTopologyForPacketInTests(mockTopology);
+		replay(mockTopology);
+		// trigger the packet in
+		cntx = new FloodlightContext();
+		cmd = dispatchPacketIn(1L, testUDPIPv6RevPacketIn, cntx);
+		verify(mockTopology);
+
+		assertEquals(Command.CONTINUE, cmd);
+		IDevice srcDev =
+				deviceManager.findDevice(srcMac, VlanVid.ofVlan(5), IPv4Address.NONE, IPv6Address.NONE, DatapathId.NONE, OFPort.ZERO);
+		verifyDevice(srcDev, srcMac, VlanVid.ofVlan(5), IPv4Address.NONE, IPv6Address.NONE, DatapathId.of(1), testUDPIPv6PacketIn.getMatch().get(MatchField.IN_PORT));
+
+		IDevice dstDev =
+				deviceManager.findDevice(dstMac, VlanVid.ofVlan(5), IPv4Address.NONE, IPv6Address.NONE, DatapathId.NONE, OFPort.ZERO);
+		verifyDevice(dstDev, dstMac, VlanVid.ofVlan(5), IPv4Address.NONE, ipaddr, DatapathId.of(5), OFPort.of(2));
+
+		cntxSrcDev = IDeviceService.fcStore.get(cntx,
+				IDeviceService.CONTEXT_SRC_DEVICE);
+		assertEquals(srcDev, cntxSrcDev);
+
+		cntxDstDev = IDeviceService.fcStore.get(cntx,
+				IDeviceService.CONTEXT_DST_DEVICE);
+		assertEquals(dstDev, cntxDstDev);
+
+		assertEquals(2, deviceManager.getAllDevices().size());
+	}
+
 	/**
 	 * This test ensures the device manager learns the source device
 	 * corresponding to the senderHardwareAddress and senderProtocolAddress
@@ -2251,7 +2566,6 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
 		d4 = deviceManager.learnDeviceByEntity(e4c);
 		d4 = deviceManager.learnDeviceByEntity(e4d);
 		assertArrayEquals(new IPv4Address[0], d2.getIPv4Addresses());
-		// FIXME: d4 should not return IP4
 		assertArrayEquals(new IPv4Address[] { IPv4Address.of(2) }, d4.getIPv4Addresses());
 
 		// Add another newer entity to d2 but with different IP
@@ -2284,9 +2598,117 @@ public class DeviceManagerImplTest extends FloodlightTestCase {
 		Arrays.sort(ips);
 		assertArrayEquals(new IPv4Address[] { IPv4Address.of(2), IPv4Address.of(42), IPv4Address.of(4242) }, ips);
 	}
+	
+	@Test
+	public void testGetIPv6Addresses() {
+		// Looks like Date is only 1s granularity
+
+		ITopologyService mockTopology = createMock(ITopologyService.class);
+		deviceManager.topology = mockTopology;
+		expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()),
+				OFPort.of(anyShort()))).
+				andReturn(true).anyTimes();
+		expect(mockTopology.getL2DomainId(DatapathId.of(anyLong()))).andReturn(DatapathId.of(1L)).anyTimes();
+		expect(mockTopology.isConsistent(DatapathId.of(EasyMock.anyLong()),
+				OFPort.of(EasyMock.anyShort()),
+				DatapathId.of(EasyMock.anyLong()),
+				OFPort.of(EasyMock.anyShort())))
+				.andReturn(false)
+				.anyTimes();
+		expect(mockTopology.isBroadcastDomainPort(DatapathId.of(EasyMock.anyLong()),
+				OFPort.of(EasyMock.anyShort())))
+				.andReturn(false)
+				.anyTimes();
+		expect(mockTopology.isInSameBroadcastDomain(DatapathId.of(EasyMock.anyLong()),
+				OFPort.of(EasyMock.anyShort()),
+				DatapathId.of(EasyMock.anyLong()),
+				OFPort.of(EasyMock.anyShort()))).
+				andReturn(false).anyTimes();
+		replay(mockTopology);
+
+		Entity e1 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(1), IPv4Address.NONE, IPv6Address.NONE, DatapathId.NONE, OFPort.ZERO, new Date(2000));
+		Device d1 = deviceManager.learnDeviceByEntity(e1);
+		assertArrayEquals(new IPv6Address[0], d1.getIPv6Addresses());
+
+		Entity e2 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.NONE, IPv6Address.of(2, 2), DatapathId.NONE, OFPort.ZERO, new Date(2000));
+		Device d2 = deviceManager.learnDeviceByEntity(e2);
+		d2 = deviceManager.learnDeviceByEntity(e2);
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(2, 2) }, d2.getIPv6Addresses());
+		// More than one entity
+		Entity e2b = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.NONE, IPv6Address.NONE, DatapathId.of(2L), OFPort.of(2), new Date(3000));
+		d2 = deviceManager.learnDeviceByEntity(e2b);
+		assertEquals(2, d2.entities.length);
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(2, 2) }, d2.getIPv6Addresses());
+		// and now add an entity with an IP
+		Entity e2c = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.NONE, IPv6Address.of(2, 2), DatapathId.of(2L), OFPort.of(3), new Date(3000));
+		d2 = deviceManager.learnDeviceByEntity(e2c);
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(2, 2) }, d2.getIPv6Addresses());
+		assertEquals(3, d2.entities.length);
+
+		// Other devices with different IPs shouldn't interfere
+		Entity e3 = new Entity(MacAddress.of(3L), VlanVid.ofVlan(3), IPv4Address.NONE, IPv6Address.of(3, 3), DatapathId.NONE, OFPort.ZERO, new Date(4000));
+		Entity e3b = new Entity(MacAddress.of(3L), VlanVid.ofVlan(3), IPv4Address.NONE, IPv6Address.of(3, 3), DatapathId.of(3L), OFPort.of(3), new Date(4400));
+		Device d3 = deviceManager.learnDeviceByEntity(e3);
+		d3 = deviceManager.learnDeviceByEntity(e3b);
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(2, 2) }, d2.getIPv6Addresses());
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(3, 3) }, d3.getIPv6Addresses());
+
+		// Add another IP to d3
+		Entity e3c = new Entity(MacAddress.of(3L), VlanVid.ofVlan(3), IPv4Address.NONE, IPv6Address.of(33, 33), DatapathId.of(3L), OFPort.of(3), new Date(4400));
+		d3 = deviceManager.learnDeviceByEntity(e3c);
+		IPv6Address[] ips = d3.getIPv6Addresses();
+		Arrays.sort(ips);
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(3, 3), IPv6Address.of(33, 33) }, ips);
+
+		// Add another device that also claims IP2 but is older than e2
+		Entity e4 = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), IPv4Address.NONE, IPv6Address.of(2, 2), DatapathId.NONE, OFPort.ZERO, new Date(1000));
+		Entity e4b = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), IPv4Address.NONE, IPv6Address.NONE, DatapathId.of(4L), OFPort.of(4), new Date(1000));
+		Device d4 = deviceManager.learnDeviceByEntity(e4);
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(2, 2) }, d2.getIPv6Addresses());
+		assertArrayEquals(new IPv6Address[0],  d4.getIPv6Addresses());
+		// add another entity to d4
+		d4 = deviceManager.learnDeviceByEntity(e4b);
+		assertArrayEquals(new IPv6Address[0], d4.getIPv6Addresses());
+
+		// Make e4 and e4a newer
+		Entity e4c = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), IPv4Address.NONE, IPv6Address.of(2, 2), DatapathId.NONE, OFPort.ZERO, new Date(5000));
+		Entity e4d = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), IPv4Address.NONE, IPv6Address.NONE, DatapathId.of(4L), OFPort.of(5), new Date(5000));
+		d4 = deviceManager.learnDeviceByEntity(e4c);
+		d4 = deviceManager.learnDeviceByEntity(e4d);
+		assertArrayEquals(new IPv6Address[0], d2.getIPv6Addresses());
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(2, 2) }, d4.getIPv6Addresses());
+
+		// Add another newer entity to d2 but with different IP
+		Entity e2d = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.NONE, IPv6Address.of(22, 22), DatapathId.of(4L), OFPort.of(6), new Date(6000));
+		d2 = deviceManager.learnDeviceByEntity(e2d);
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(22, 22) }, d2.getIPv6Addresses());
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(2, 2) }, d4.getIPv6Addresses());
+
+		// new IP for d2,d4 but with same timestamp. Both devices get the IP
+		Entity e2e = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.NONE, IPv6Address.of(42, 42), DatapathId.of(2L), OFPort.of(4), new Date(7000));
+		d2 = deviceManager.learnDeviceByEntity(e2e);
+		ips= d2.getIPv6Addresses();
+		Arrays.sort(ips);
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(22, 22), IPv6Address.of(42, 42) }, ips);
+		Entity e4e = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), IPv4Address.NONE, IPv6Address.of(42, 42), DatapathId.of(4L), OFPort.of(7), new Date(7000));
+		d4 = deviceManager.learnDeviceByEntity(e4e);
+		ips= d4.getIPv6Addresses();
+		Arrays.sort(ips);
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(2, 2), IPv6Address.of(42, 42) }, ips);
+
+		// add a couple more IPs
+		Entity e2f = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.NONE, IPv6Address.of(4242, 4242), DatapathId.of(2L), OFPort.of(5), new Date(8000));
+		d2 = deviceManager.learnDeviceByEntity(e2f);
+		ips= d2.getIPv6Addresses();
+		Arrays.sort(ips);
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(22, 22), IPv6Address.of(42, 42), IPv6Address.of(4242, 4242) }, ips);
+		Entity e4f = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), IPv4Address.NONE, IPv6Address.of(4242, 4242), DatapathId.of(4L), OFPort.of(8), new Date(9000));
+		d4 = deviceManager.learnDeviceByEntity(e4f);
+		ips= d4.getIPv6Addresses();
+		Arrays.sort(ips);
+		assertArrayEquals(new IPv6Address[] { IPv6Address.of(2, 2), IPv6Address.of(42, 42), IPv6Address.of(4242, 4242) }, ips);
+	}
 
-	// TODO: this test should really go into a separate class that collects
-	// unit tests for Device
 	@Test
 	public void testGetSwitchPortVlanId() {
 		Entity entity1 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(1), IPv4Address.NONE, IPv6Address.NONE, DatapathId.of(10L), OFPort.of(1), new Date());