DeviceManagerImpl implements
IDeviceService, IOFMessageListener, ITopologyListener,
IFloodlightModule, IEntityClassListener,
IFlowReconcileListener, IInfoProvider, IHAListener { protected Device learnDeviceByEntity(Entity entity) { ArrayList<Long> deleteQueue = null; LinkedList<DeviceUpdate> deviceUpdates = null; Device device = null; while (true) { deviceUpdates = null; Long deviceKey = primaryIndex.findByEntity(entity); IEntityClass entityClass = null; if (deviceKey == null) { entityClass = entityClassifier.classifyEntity(entity); if (entityClass == null) { return null; } ClassState classState = getClassState(entityClass); if (classState.classIndex != null) { deviceKey = classState.classIndex.findByEntity(entity); } } if (deviceKey != null) { device = deviceMap.get(deviceKey); if (device == null) throw new IllegalStateException("Corrupted device index"); } else { if (!isEntityAllowed(entity, entityClass)) { logger.info("PacketIn is not allowed {} {}", entityClass.getName(), entity); return null; } synchronized (deviceKeyLock) { deviceKey = Long.valueOf(deviceKeyCounter++); } device = allocateDevice(deviceKey, entity, entityClass); if (logger.isDebugEnabled()) { logger.debug("New device created: {} deviceKey={}, entity={}", new Object[]{device, deviceKey, entity}); } deviceMap.put(deviceKey, device); if (!updateIndices(device, deviceKey)) { if (deleteQueue == null) deleteQueue = new ArrayList<Long>(); deleteQueue.add(deviceKey); continue; } updateSecondaryIndices(entity, entityClass, deviceKey); deviceUpdates = updateUpdates(deviceUpdates, new DeviceUpdate(device, ADD, null)); break; } if (!isEntityAllowed(entity, device.getEntityClass())) { logger.info("PacketIn is not allowed {} {}", device.getEntityClass().getName(), entity); return null; } int entityindex = -1; if ((entityindex = device.entityIndex(entity)) >= 0) { Date lastSeen = entity.getLastSeenTimestamp(); if (lastSeen == null) lastSeen = new Date(); device.entities[entityindex].setLastSeenTimestamp(lastSeen); if (device.entities[entityindex].getSwitchDPID() != null && device.entities[entityindex].getSwitchPort() != null) { long sw = device.entities[entityindex].getSwitchDPID(); short port = device.entities[entityindex].getSwitchPort().shortValue(); boolean moved = device.updateAttachmentPoint(sw, port, lastSeen.getTime()); if (moved) { sendDeviceMovedNotification(device); if (logger.isTraceEnabled()) { logger.trace("Device moved: attachment points {}," + "entities {}", device.attachmentPoints, device.entities); } } else { if (logger.isTraceEnabled()) { logger.trace("Device attachment point NOT updated: " + "attachment points {}," + "entities {}", device.attachmentPoints, device.entities); } } } break; } else { boolean moved = false; Device newDevice = allocateDevice(device, entity); if (entity.getSwitchDPID() != null && entity.getSwitchPort() != null) { moved = newDevice.updateAttachmentPoint(entity.getSwitchDPID(), entity.getSwitchPort().shortValue(), entity.getLastSeenTimestamp().getTime()); } EnumSet<DeviceField> changedFields = findChangedFields(device, entity); if (changedFields.size() > 0) deviceUpdates = updateUpdates(deviceUpdates, new DeviceUpdate(newDevice, CHANGE, changedFields)); boolean res = deviceMap.replace(deviceKey, device, newDevice); if (!res) continue; device = newDevice; if (!updateIndices(device, deviceKey)) { continue; } updateSecondaryIndices(entity, device.getEntityClass(), deviceKey); if (moved) { sendDeviceMovedNotification(device); if (logger.isDebugEnabled()) { logger.debug("Device moved: attachment points {}," + "entities {}", device.attachmentPoints, device.entities); } } else { if (logger.isDebugEnabled()) { logger.debug("Device attachment point updated: " + "attachment points {}," + "entities {}", device.attachmentPoints, device.entities); } } break; } } if (deleteQueue != null) { for (Long l : deleteQueue) { Device dev = deviceMap.get(l); this.deleteDevice(dev); deviceUpdates = updateUpdates(deviceUpdates, new DeviceUpdate(dev, DELETE, null)); } } processUpdates(deviceUpdates); return device; }  @Override IDevice getDevice(Long deviceKey); @Override IDevice findDevice(long macAddress, Short vlan,
                              Integer ipv4Address, Long switchDPID,
                              Integer switchPort); @Override IDevice findDestDevice(IDevice source, long macAddress,
                                  Short vlan, Integer ipv4Address); @Override Collection<? extends IDevice> getAllDevices(); @Override void addIndex(boolean perClass,
                         EnumSet<DeviceField> keyFields); @Override Iterator<? extends IDevice> queryDevices(Long macAddress,
                                                    Short vlan,
                                                    Integer ipv4Address,
                                                    Long switchDPID,
                                                    Integer switchPort); @Override Iterator<? extends IDevice> queryClassDevices(IDevice reference,
                                                         Long macAddress,
                                                         Short vlan,
                                                         Integer ipv4Address,
                                                         Long switchDPID,
                                                         Integer switchPort); @Override void addListener(IDeviceListener listener); @Override Map<String, Object> getInfo(String type); @Override String getName(); @Override boolean isCallbackOrderingPrereq(OFType type, String name); @Override boolean isCallbackOrderingPostreq(OFType type, String name); @Override Command receive(IOFSwitch sw, OFMessage msg,
                           FloodlightContext cntx); @Override Command reconcileFlows(ArrayList<OFMatchReconcile> ofmRcList); @Override Collection<Class<? extends IFloodlightService>> getModuleServices(); @Override Map<Class<? extends IFloodlightService>, IFloodlightService> getServiceImpls(); @Override Collection<Class<? extends IFloodlightService>> getModuleDependencies(); @Override void init(FloodlightModuleContext fmc); @Override void startUp(FloodlightModuleContext fmc); @Override void roleChanged(Role oldRole, Role newRole); @Override void controllerNodeIPsChanged(
                                         Map<String, String> curControllerNodeIPs,
                                         Map<String, String> addedControllerNodeIPs,
                                         Map<String, String> removedControllerNodeIPs); boolean isValidAttachmentPoint(long switchDPID,
                                             int switchPort); @Override void entityClassChanged(Set<String> entityClassNames); @Override void addSuppressAPs(long swId, short port); @Override void removeSuppressAPs(long swId, short port); @Override void topologyChanged(); public AttachmentPointComparator apComparator; public SingletonTask entityCleanupTask; }
@Test public void testAttachmentPointFlapping() throws Exception { Calendar c = Calendar.getInstance(); ITopologyService mockTopology = createMock(ITopologyService.class); expect(mockTopology.isAttachmentPointPort(anyLong(), anyShort())).andReturn(true).anyTimes(); expect(mockTopology.isBroadcastDomainPort(anyLong(), anyShort())). andReturn(false).anyTimes(); expect(mockTopology.isInSameBroadcastDomain(anyLong(), anyShort(), anyLong(), anyShort())).andReturn(false).anyTimes(); expect(mockTopology.getL2DomainId(anyLong())). andReturn(1L).anyTimes(); expect(mockTopology.isConsistent(1L, (short)1, 1L, (short)1)). andReturn(true).anyTimes(); expect(mockTopology.isConsistent(1L, (short)1, 5L, (short)1)). andReturn(false).anyTimes(); expect(mockTopology.isConsistent(1L, (short)1, 10L, (short)1)). andReturn(false).anyTimes(); expect(mockTopology.isConsistent(5L, (short)1, 10L, (short)1)). andReturn(false).anyTimes(); expect(mockTopology.isConsistent(10L, (short)1, 1L, (short)1)). andReturn(false).anyTimes(); expect(mockTopology.isConsistent(5L, (short)1, 1L, (short)1)). andReturn(false).anyTimes(); expect(mockTopology.isConsistent(10L, (short)1, 5L, (short)1)). andReturn(false).anyTimes(); Date topologyUpdateTime = new Date(); expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). anyTimes(); replay(mockTopology); deviceManager.topology = mockTopology; Entity entity1 = new Entity(1L, null, null, 1L, 1, c.getTime()); Entity entity1a = new Entity(1L, null, 1, 1L, 1, c.getTime()); Entity entity2 = new Entity(1L, null, null, 5L, 1, c.getTime()); Entity entity3 = new Entity(1L, null, null, 10L, 1, c.getTime()); entity1.setLastSeenTimestamp(c.getTime()); c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT/2); entity1a.setLastSeenTimestamp(c.getTime()); c.add(Calendar.MILLISECOND, 1); entity2.setLastSeenTimestamp(c.getTime()); c.add(Calendar.MILLISECOND, 1); entity3.setLastSeenTimestamp(c.getTime()); IDevice d; d = deviceManager.learnDeviceByEntity(entity1); d = deviceManager.learnDeviceByEntity(entity1a); d = deviceManager.learnDeviceByEntity(entity2); d = deviceManager.learnDeviceByEntity(entity3); assertArrayEquals(new SwitchPort[] { new SwitchPort(10L, 1) }, d.getAttachmentPoints()); assertArrayEquals(new SwitchPort[] { new SwitchPort(10L, 1),}, d.getAttachmentPoints(true)); c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT/4); entity1.setLastSeenTimestamp(c.getTime()); d = deviceManager.learnDeviceByEntity(entity1); assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, d.getAttachmentPoints()); assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), new SwitchPort(5L, 1, ErrorStatus.DUPLICATE_DEVICE), new SwitchPort(10L, 1, ErrorStatus.DUPLICATE_DEVICE) }, d.getAttachmentPoints(true)); c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT+2000); entity1.setLastSeenTimestamp(c.getTime()); d = deviceManager.learnDeviceByEntity(entity1); assertEquals(entity1.getActiveSince(), entity1.getLastSeenTimestamp()); assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, d.getAttachmentPoints()); assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, d.getAttachmentPoints(true)); }
@Test public void testAttachmentPointFlappingTwoCluster() throws Exception { Calendar c = Calendar.getInstance(); ITopologyService mockTopology = createMock(ITopologyService.class); expect(mockTopology.isAttachmentPointPort(anyLong(), anyShort())).andReturn(true).anyTimes(); expect(mockTopology.isBroadcastDomainPort(anyLong(), anyShort())). andReturn(false).anyTimes(); expect(mockTopology.isInSameBroadcastDomain(anyLong(), anyShort(), anyLong(), anyShort())).andReturn(false).anyTimes(); expect(mockTopology.getL2DomainId(1L)). andReturn(1L).anyTimes(); expect(mockTopology.getL2DomainId(5L)). andReturn(5L).anyTimes(); expect(mockTopology.isConsistent(1L, (short)1, 1L, (short)2)). andReturn(false).anyTimes(); expect(mockTopology.isConsistent(1L, (short)2, 5L, (short)1)). andReturn(false).anyTimes(); expect(mockTopology.isConsistent(5L, (short)1, 5L, (short)2)). andReturn(false).anyTimes(); expect(mockTopology.isConsistent(1L, (short)2, 1L, (short)1)). andReturn(false).anyTimes(); expect(mockTopology.isConsistent(1L, (short)1, 5L, (short)1)). andReturn(false).anyTimes(); expect(mockTopology.isConsistent(1L, (short)1, 5L, (short)2)). andReturn(false).anyTimes(); expect(mockTopology.isConsistent(5L, (short)2, 5L, (short)1)). andReturn(false).anyTimes(); Date topologyUpdateTime = new Date(); expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). anyTimes(); replay(mockTopology); deviceManager.topology = mockTopology; Entity entity1 = new Entity(1L, null, null, 1L, 1, c.getTime()); Entity entity2 = new Entity(1L, null, null, 1L, 2, c.getTime()); Entity entity3 = new Entity(1L, null, null, 5L, 1, c.getTime()); Entity entity4 = new Entity(1L, null, null, 5L, 2, c.getTime()); entity1.setLastSeenTimestamp(c.getTime()); c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT/2); c.add(Calendar.MILLISECOND, 1); entity2.setLastSeenTimestamp(c.getTime()); c.add(Calendar.MILLISECOND, 1); entity3.setLastSeenTimestamp(c.getTime()); c.add(Calendar.MILLISECOND, 1); entity4.setLastSeenTimestamp(c.getTime()); deviceManager.learnDeviceByEntity(entity1); deviceManager.learnDeviceByEntity(entity2); deviceManager.learnDeviceByEntity(entity3); IDevice d = deviceManager.learnDeviceByEntity(entity4); assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 2), new SwitchPort(5L, 2) }, d.getAttachmentPoints()); assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 2), new SwitchPort(5L, 2)}, d.getAttachmentPoints(true)); c.add(Calendar.MILLISECOND, 1); entity1.setLastSeenTimestamp(c.getTime()); d = deviceManager.learnDeviceByEntity(entity1); assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), new SwitchPort(5L, 2) }, d.getAttachmentPoints()); assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), new SwitchPort(5L, 2), new SwitchPort(1L, 2, ErrorStatus.DUPLICATE_DEVICE)}, d.getAttachmentPoints(true)); c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT+1); entity1.setLastSeenTimestamp(c.getTime()); d = deviceManager.learnDeviceByEntity(entity1); assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), new SwitchPort(5L, 2) }, d.getAttachmentPoints()); assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), new SwitchPort(5L, 2)}, d.getAttachmentPoints(true)); entity3.setLastSeenTimestamp(c.getTime()); d = deviceManager.learnDeviceByEntity(entity3); assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), new SwitchPort(5L, 1) }, d.getAttachmentPoints()); assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), new SwitchPort(5L, 1) }, d.getAttachmentPoints(true)); }
@Test public void testGetIPv4Addresses() { ITopologyService mockTopology = createMock(ITopologyService.class); deviceManager.topology = mockTopology; expect(mockTopology.isAttachmentPointPort(anyLong(), anyShort())). andReturn(true).anyTimes(); expect(mockTopology.getL2DomainId(anyLong())).andReturn(1L).anyTimes(); expect(mockTopology.isConsistent(EasyMock.anyLong(), EasyMock.anyShort(), EasyMock.anyLong(), EasyMock.anyShort())) .andReturn(false) .anyTimes(); expect(mockTopology.isBroadcastDomainPort(EasyMock.anyLong(), EasyMock.anyShort())) .andReturn(false) .anyTimes(); expect(mockTopology.isInSameBroadcastDomain(EasyMock.anyLong(), EasyMock.anyShort(), EasyMock.anyLong(), EasyMock.anyShort())). andReturn(false).anyTimes(); replay(mockTopology); Entity e1 = new Entity(1L, (short)1, null, null, null, new Date(2000)); Device d1 = deviceManager.learnDeviceByEntity(e1); assertArrayEquals(new Integer[0], d1.getIPv4Addresses()); Entity e2 = new Entity(2L, (short)2, 2, null, null, new Date(2000)); Device d2 = deviceManager.learnDeviceByEntity(e2); d2 = deviceManager.learnDeviceByEntity(e2); assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); Entity e2b = new Entity(2L, (short)2, null, 2L, 2, new Date(3000)); d2 = deviceManager.learnDeviceByEntity(e2b); assertEquals(2, d2.entities.length); assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); Entity e2c = new Entity(2L, (short)2, 2, 2L, 3, new Date(3000)); d2 = deviceManager.learnDeviceByEntity(e2c); assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); assertEquals(3, d2.entities.length); Entity e3 = new Entity(3L, (short)3, 3, null, null, new Date(4000)); Entity e3b = new Entity(3L, (short)3, 3, 3L, 3, new Date(4400)); Device d3 = deviceManager.learnDeviceByEntity(e3); d3 = deviceManager.learnDeviceByEntity(e3b); assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); assertArrayEquals(new Integer[] { 3 }, d3.getIPv4Addresses()); Entity e3c = new Entity(3L, (short)3, 33, 3L, 3, new Date(4400)); d3 = deviceManager.learnDeviceByEntity(e3c); Integer[] ips = d3.getIPv4Addresses(); Arrays.sort(ips); assertArrayEquals(new Integer[] { 3, 33 }, ips); Entity e4 = new Entity(4L, (short)4, 2, null, null, new Date(1000)); Entity e4b = new Entity(4L, (short)4, null, 4L, 4, new Date(1000)); Device d4 = deviceManager.learnDeviceByEntity(e4); assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); assertArrayEquals(new Integer[0], d4.getIPv4Addresses()); d4 = deviceManager.learnDeviceByEntity(e4b); assertArrayEquals(new Integer[0], d4.getIPv4Addresses()); Entity e4c = new Entity(4L, (short)4, 2, null, null, new Date(5000)); Entity e4d = new Entity(4L, (short)4, null, 4L, 5, new Date(5000)); d4 = deviceManager.learnDeviceByEntity(e4c); d4 = deviceManager.learnDeviceByEntity(e4d); assertArrayEquals(new Integer[0], d2.getIPv4Addresses()); assertArrayEquals(new Integer[] { 2 }, d4.getIPv4Addresses()); Entity e2d = new Entity(2L, (short)2, 22, 4L, 6, new Date(6000)); d2 = deviceManager.learnDeviceByEntity(e2d); assertArrayEquals(new Integer[] { 22 }, d2.getIPv4Addresses()); assertArrayEquals(new Integer[] { 2 }, d4.getIPv4Addresses()); Entity e2e = new Entity(2L, (short)2, 42, 2L, 4, new Date(7000)); d2 = deviceManager.learnDeviceByEntity(e2e); ips= d2.getIPv4Addresses(); Arrays.sort(ips); assertArrayEquals(new Integer[] { 22, 42 }, ips); Entity e4e = new Entity(4L, (short)4, 42, 4L, 7, new Date(7000)); d4 = deviceManager.learnDeviceByEntity(e4e); ips= d4.getIPv4Addresses(); Arrays.sort(ips); assertArrayEquals(new Integer[] { 2, 42 }, ips); Entity e2f = new Entity(2L, (short)2, 4242, 2L, 5, new Date(8000)); d2 = deviceManager.learnDeviceByEntity(e2f); ips= d2.getIPv4Addresses(); Arrays.sort(ips); assertArrayEquals(new Integer[] { 22, 42, 4242 }, ips); Entity e4f = new Entity(4L, (short)4, 4242, 4L, 8, new Date(9000)); d4 = deviceManager.learnDeviceByEntity(e4f); ips= d4.getIPv4Addresses(); Arrays.sort(ips); assertArrayEquals(new Integer[] { 2, 42, 4242 }, ips); }