From 4c2b615fc0d33467d22602ec22c09faf1f9f0534 Mon Sep 17 00:00:00 2001 From: Rob Adams <rob.adams@bigswitch.com> Date: Fri, 27 Apr 2012 13:48:02 -0700 Subject: [PATCH] Port broadcast domain logic from old device manager --- .../devicemanager/internal/Device.java | 2 +- .../internal/DeviceManagerImpl.java | 104 ++++++++++++------ .../internal/DeviceManagerImplTest.java | 52 +++++++++ 3 files changed, 124 insertions(+), 34 deletions(-) diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java index f8bbbe578..1a31036aa 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/Device.java @@ -237,7 +237,7 @@ public class Device implements IDevice { // XXX - TODO suppress flapping // XXX - TODO handle suppressing switching to a broadcast domain Entity[] clentities = Arrays.<Entity>copyOf(entities, entities.length); - Arrays.sort(clentities, deviceManager.clusterIdComparator); + Arrays.sort(clentities, deviceManager.apComparator); ITopologyService topology = deviceManager.topology; long prevCluster = 0; diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java index b2ac5a5fd..dcc1b4783 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java @@ -101,6 +101,14 @@ public class DeviceManagerImpl implements */ protected static final int ENTITY_CLEANUP_INTERVAL = 60*60; + /** + * Attachment points on a broadcast domain will have lower priority + * than attachment points in openflow domains. This is the timeout + * for switching from a non-broadcast domain to a broadcast domain + * attachment point. + */ + protected static long NBD_TO_BD_TIMEDIFF_MS = 300000; // 5 minutes + /** * This is the master device map that maps device IDs to {@link Device} * objects. @@ -219,10 +227,71 @@ public class DeviceManagerImpl implements } } + /** + * Comparator for finding the correct attachment point to use based on + * the set of entities + */ + protected class AttachmentPointComparator + implements Comparator<Entity> { + + + public AttachmentPointComparator() { + super(); + } + + @Override + public int compare(Entity e1, Entity e2) { + int r = 0; + + Long swdpid1 = e1.getSwitchDPID(); + Long swdpid2 = e2.getSwitchDPID(); + if (swdpid1 == null) + r = swdpid2 == null ? 0 : -1; + else if (swdpid2 == null) + r = 1; + else { + Long d1ClusterId = + topology.getSwitchClusterId(swdpid1); + Long d2ClusterId = + topology.getSwitchClusterId(swdpid2); + r = d1ClusterId.compareTo(d2ClusterId); + } + if (r != 0) return r; + + Date e1t = e1.getLastSeenTimestamp(); + Date e2t = e2.getLastSeenTimestamp(); + if (e1t == null) + r = e2t == null ? 0 : -1; + else if (e2t == null) + r = 1; + else { + long e1ts = e1t.getTime(); + long e2ts = e2t.getTime(); + if (topology. + isBroadcastDomainPort(e1.getSwitchDPID(), + e1.getSwitchPort(). + shortValue())) { + e1ts -= NBD_TO_BD_TIMEDIFF_MS; + } + if (topology. + isBroadcastDomainPort(e2.getSwitchDPID(), + e2.getSwitchPort(). + shortValue())) { + e2ts -= NBD_TO_BD_TIMEDIFF_MS; + } + + r = Long.valueOf(e1ts).compareTo(e2ts); + } + + return r; + } + + } + /** * Comparator for sorting by cluster ID */ - public Comparator<Entity> clusterIdComparator; + public Comparator<Entity> apComparator; /** * Periodic task to clean up expired entities @@ -520,38 +589,7 @@ public class DeviceManagerImpl implements deviceMap = new ConcurrentHashMap<Long, Device>(); classStateMap = new ConcurrentHashMap<IEntityClass, ClassState>(); - clusterIdComparator = new Comparator<Entity>() { - @Override - public int compare(Entity e1, Entity e2) { - int r = 0; - - Long swdpid1 = e1.getSwitchDPID(); - Long swdpid2 = e2.getSwitchDPID(); - if (swdpid1 == null) - r = swdpid2 == null ? 0 : -1; - else if (swdpid2 == null) - r = 1; - else { - Long d1ClusterId = - topology.getSwitchClusterId(swdpid1); - Long d2ClusterId = - topology.getSwitchClusterId(swdpid2); - r = d1ClusterId.compareTo(d2ClusterId); - } - if (r != 0) return r; - - Date e1t = e1.getLastSeenTimestamp(); - Date e2t = e2.getLastSeenTimestamp(); - if (e1t == null) - r = e2t == null ? 0 : -1; - else if (e2t == null) - r = 1; - else - r = e1t.compareTo(e2t); - - return r; - } - }; + apComparator = new AttachmentPointComparator(); floodlightProvider.addOFMessageListener(OFType.PACKET_IN, this); diff --git a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java index cfa01fc69..587b76b16 100644 --- a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java +++ b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java @@ -248,6 +248,9 @@ public class DeviceManagerImplTest extends FloodlightTestCase { ITopologyService mockTopology = createMock(ITopologyService.class); expect(mockTopology.getSwitchClusterId(anyLong())). andReturn(1L).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(anyLong(), anyShort())). + andReturn(false).anyTimes(); + expect(mockTopology.isInternal(anyLong(), anyShort())).andReturn(false).anyTimes(); deviceManager.topology = mockTopology; @@ -359,6 +362,8 @@ public class DeviceManagerImplTest extends FloodlightTestCase { andReturn(10L).anyTimes(); expect(mockTopology.getSwitchClusterId(50L)). andReturn(10L).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(anyLong(), anyShort())). + andReturn(false).anyTimes(); expect(mockTopology.isInternal(anyLong(), anyShort())).andReturn(false).anyTimes(); @@ -430,6 +435,53 @@ public class DeviceManagerImplTest extends FloodlightTestCase { verify(mockListener); } + @Test + public void testBDAttachmentPointLearning() throws Exception { + ITopologyService mockTopology = createMock(ITopologyService.class); + expect(mockTopology.getSwitchClusterId(anyLong())). + andReturn(1L).anyTimes(); + expect(mockTopology.isInternal(anyLong(), anyShort())). + andReturn(false).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(1L, (short)1)). + andReturn(false).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(1L, (short)2)). + andReturn(true).anyTimes(); + + replay(mockTopology); + + deviceManager.topology = mockTopology; + + Calendar c = Calendar.getInstance(); + Entity entity1 = new Entity(1L, null, 1, 1L, 1, c.getTime()); + c.add(Calendar.MILLISECOND, + (int)DeviceManagerImpl.NBD_TO_BD_TIMEDIFF_MS / 2); + Entity entity2 = new Entity(1L, null, null, 1L, 2, c.getTime()); + c.add(Calendar.MILLISECOND, + (int)DeviceManagerImpl.NBD_TO_BD_TIMEDIFF_MS / 2 + 1); + Entity entity3 = new Entity(1L, null, null, 1L, 2, c.getTime()); + + IDevice d; + SwitchPort[] aps; + + d = deviceManager.learnDeviceByEntity(entity1); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps); + + // this timestamp is too soon; don't switch + d = deviceManager.learnDeviceByEntity(entity2); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps); + + // it should switch when we learn with a timestamp after the + // timeout + d = deviceManager.learnDeviceByEntity(entity3); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 2) }, aps); + } + @Test public void testPacketIn() throws Exception { byte[] dataLayerSource = -- GitLab