diff --git a/src/main/java/net/floodlightcontroller/core/internal/Controller.java b/src/main/java/net/floodlightcontroller/core/internal/Controller.java index 93fb9364b761b769c8743f70a81b2740a0df2734..4aacb7f10b3f839308300bf2e373f7f31dee2cb6 100644 --- a/src/main/java/net/floodlightcontroller/core/internal/Controller.java +++ b/src/main/java/net/floodlightcontroller/core/internal/Controller.java @@ -342,7 +342,9 @@ public class Controller processOFMessage((OFMessage)e.getMessage()); } } catch (Exception ex) { - Channels.fireExceptionCaught(ctx, ex); + // We are the last handler in the stream, so run the exception + // through the channel again by passing in ctx.getChannel(). + Channels.fireExceptionCaught(ctx.getChannel(), ex); } } @@ -572,8 +574,6 @@ public class Controller handleMessage(sw, m, null); break; } - } catch (Exception e) { - log.warn("Exeption in handling OF message {}", e); } finally { sw.processMessageLock().unlock(); @@ -1221,8 +1221,6 @@ public class Controller } } switchResultSet.save(); - } catch (Exception e) { - log.error("Error updating switch info {}", e); } finally { if (switchResultSet != null) @@ -1458,7 +1456,8 @@ public class Controller // call this explicitly because it does setup this.setStorageSource(storageSource); - HashSet<ITopologyAware> topologyAware = new HashSet<ITopologyAware>(); + + ArrayList<ITopologyAware> topologyAware = new ArrayList<ITopologyAware>(); topologyAware.add(deviceManager); topologyAware.add(routingEngine); topology.setTopologyAware(topologyAware); diff --git a/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java b/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java index 8c59a3407170a016a27ac2379d77a9b4f6f4ca35..8ea10996543a0bdf1490383a58755c94aff07fe3 100644 --- a/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java +++ b/src/main/java/net/floodlightcontroller/core/web/SwitchResourceBase.java @@ -120,7 +120,7 @@ public class SwitchResourceBase extends ServerResource { } return values; } - + protected List<OFStatistics> getSwitchStatistics(String switchId, OFStatisticsType statType) { return getSwitchStatistics(HexString.toLong(switchId), statType); } diff --git a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java index 2253d868c24f2a44b880cf5ec68fed94eb9446c4..3ef2adb16118080258299807f83c227b865bfe56 100755 --- a/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java +++ b/src/main/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImpl.java @@ -32,6 +32,8 @@ import net.floodlightcontroller.devicemanager.IEntityClass; import net.floodlightcontroller.storage.IStorageSourceListener; import net.floodlightcontroller.topology.ITopologyAware; import org.openflow.protocol.OFMessage; +import org.openflow.protocol.OFPacketIn; +import org.openflow.protocol.OFPortStatus; import org.openflow.protocol.OFType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -146,15 +148,13 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener, public void removedLink(IOFSwitch srcSw, short srcPort, IOFSwitch dstSw, short dstPort) { // TODO Auto-generated method stub - } @Override public void clusterMerged() { // TODO Auto-generated method stub - } - + // ***************** // IOFSwitchListener // ***************** @@ -162,7 +162,6 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener, @Override public void updatedSwitch(IOFSwitch sw) { // TODO Auto-generated method stub - } @@ -175,7 +174,6 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener, @Override public void removedSwitch(IOFSwitch sw) { // TODO Auto-generated method stub - } // **************** @@ -183,7 +181,207 @@ public class DeviceManagerImpl implements IDeviceManager, IOFMessageListener, // **************** public Command processPortStatusMessage(IOFSwitch sw, OFPortStatus ps) { + return null; } + + /** + * This method is called for every packet-in and should be optimized for + * performance. + * @param sw + * @param pi + * @param cntx + * @return + */ + public Command processPacketInMessage(IOFSwitch sw, OFPacketIn pi, + FloodlightContext cntx) { + return null; + /* + Command ret = Command.CONTINUE; + OFMatch match = new OFMatch(); + match.loadFromPacket(pi.getPacketData(), pi.getInPort(), sw.getId()); + // Add this packet-in to event history + evHistPktIn(match); + + // Create attachment point/update network address if required + SwitchPortTuple switchPort = new SwitchPortTuple(sw, pi.getInPort()); + // Don't learn from internal port or invalid port + if (topology.isInternal(switchPort) || + !isValidInputPort(switchPort.getPort())) { + processUpdates(); + return Command.CONTINUE; + } + + // Packet arrive at a port from where we can learn the device + // if the source is multicast/broadcast ignore it + if ((match.getDataLayerSource()[0] & 0x1) != 0) { + return Command.CONTINUE; + } + + Long dlAddr = Ethernet.toLong(match.getDataLayerSource()); + Short vlan = match.getDataLayerVirtualLan(); + if (vlan < 0) vlan = null; + Ethernet eth = IFloodlightProvider.bcStore.get( + cntx, IFloodlightProvider.CONTEXT_PI_PAYLOAD); + int nwSrc = getSrcNwAddr(eth, dlAddr); + Device device = devMgrMaps.getDeviceByDataLayerAddr(dlAddr); + Date currentDate = new Date(); // TODO, + if (device != null) { + // Write lock is expensive, check if we have an update first + boolean newAttachmentPoint = false; + boolean newNetworkAddress = false; + boolean updateAttachmentPointLastSeen = false; + boolean updateNetworkAddressLastSeen = false; + boolean updateNeworkAddressMap = false; + boolean updateDeviceVlan = false; + boolean clearAttachmentPoints = false; + boolean updateDevice = false; + + DeviceAttachmentPoint attachmentPoint = null; + DeviceNetworkAddress networkAddress = null; + + // Copy-replace of device would be too expensive here + device.setLastSeen(currentDate); + updateDevice = device.shouldWriteLastSeenToStorage(); + attachmentPoint = device.getAttachmentPoint(switchPort); + + if (isGratArp(eth)) { + clearAttachmentPoints = true; + } + + if (attachmentPoint != null) { + updateAttachmentPointLastSeen = true; + } else { + newAttachmentPoint = true; + } + + if (nwSrc != 0) { + networkAddress = device.getNetworkAddress(nwSrc); + if (networkAddress != null) { + updateNetworkAddressLastSeen = true; + } else if (eth != null && (eth.getPayload() instanceof ARP)) { + networkAddress = new DeviceNetworkAddress(nwSrc, + currentDate); + newNetworkAddress = true; + } + + // Also, if this address is currently mapped to a different + // device, fix it. This should be rare, so it is OK to do update + // the storage from here. + // + // NOTE: the mapping is observed, and the decision is made based + // on that, outside a lock. So the state may change by the time + // we get to do the map update. But that is OK since the mapping + // will eventually get consistent. + Device deviceByNwaddr = this.getDeviceByIPv4Address(nwSrc); + if ((deviceByNwaddr != null) && + (deviceByNwaddr.getDataLayerAddressAsLong() != + device.getDataLayerAddressAsLong())) { + updateNeworkAddressMap = true; + Device dCopy = new Device(deviceByNwaddr); + DeviceNetworkAddress naOld = dCopy.getNetworkAddress(nwSrc); + Map<Integer, DeviceNetworkAddress> namap = + dCopy.getNetworkAddressesMap(); + if (namap.containsKey(nwSrc)) namap.remove(nwSrc); + dCopy.setNetworkAddresses(namap.values()); + this.devMgrMaps.updateMaps(dCopy); + if (naOld !=null) + removeNetworkAddressFromStorage(dCopy, naOld); + log.info( + "Network address {} moved from {} to {} due to packet {}", + new Object[] {networkAddress, + deviceByNwaddr.getDataLayerAddress(), + device.getDataLayerAddress(), + eth}); + } + + } + if ((vlan == null && device.getVlanId() != null) || + (vlan != null && !vlan.equals(device.getVlanId()))) { + updateDeviceVlan = true; + } + + if (newAttachmentPoint || newNetworkAddress || updateDeviceVlan || + updateNeworkAddressMap) { + + Device nd = new Device(device); + + try { + // Check if we have seen this attachmentPoint recently, + // An exception is thrown if the attachmentPoint is blocked. + if (newAttachmentPoint) { + attachmentPoint = getNewAttachmentPoint(nd, switchPort); + nd.addAttachmentPoint(attachmentPoint); + evHistAttachmtPt(nd, attachmentPoint.getSwitchPort(), + EvAction.ADDED, "New AP from pkt-in"); + } + + if (clearAttachmentPoints) { + nd.clearAttachmentPoints(); + evHistAttachmtPt(nd, 0L, (short)(-1), + EvAction.CLEARED, "Grat. ARP from pkt-in"); + } + + if (newNetworkAddress) { + // add the address + nd.addNetworkAddress(networkAddress); + log.debug("Device {} added IP {}", + nd, IPv4.fromIPv4Address(nwSrc)); + } + + if (updateDeviceVlan) { + nd.setVlanId(vlan); + writeDeviceToStorage(nd, currentDate); + } + + } catch (APBlockedException e) { + assert(attachmentPoint == null); + ret = Command.STOP; + // install drop flow to avoid overloading the controller + // set hard timeout to 5 seconds to avoid blocking host + // forever + ForwardingBase.blockHost(floodlightProvider, switchPort, + dlAddr, ForwardingBase.FLOWMOD_DEFAULT_HARD_TIMEOUT); + } + // Update the maps + devMgrMaps.updateMaps(nd); + // publish the update after devMgrMaps is updated. + if (newNetworkAddress) { + updateAddress(nd, networkAddress, true); + } + if (updateDeviceVlan) { + updateVlan(nd); + } + device = nd; + } + + if (updateAttachmentPointLastSeen) { + attachmentPoint.setLastSeen(currentDate); + if (attachmentPoint.shouldWriteLastSeenToStorage()) + writeAttachmentPointToStorage( + device, attachmentPoint, currentDate); + } + + if (updateNetworkAddressLastSeen || newNetworkAddress) { + if (updateNetworkAddressLastSeen) + networkAddress.setLastSeen(currentDate); + if (newNetworkAddress || + networkAddress.shouldWriteLastSeenToStorage()) + writeNetworkAddressToStorage( + device, networkAddress, currentDate); + } + + if (updateDevice) { + writeDeviceToStorage(device, currentDate); + } + + } else { // device is null + handleNewDevice(match.getDataLayerSource(), currentDate, + switchPort, nwSrc, vlan); + } + processUpdates(); + return ret; + */ + } } diff --git a/src/main/java/net/floodlightcontroller/perfmon/PktinProcessingTime.java b/src/main/java/net/floodlightcontroller/perfmon/PktinProcessingTime.java index 55a91ccb13517688959095e971eb88708c31ecc1..c0e7dfa03c7c02355d5a9370f465c4d2863bca4c 100644 --- a/src/main/java/net/floodlightcontroller/perfmon/PktinProcessingTime.java +++ b/src/main/java/net/floodlightcontroller/perfmon/PktinProcessingTime.java @@ -40,7 +40,7 @@ public class PktinProcessingTime { */ protected static Logger logger = - LoggerFactory.getLogger(PktinProcessingTime.class); + LoggerFactory.getLogger(PktinProcessingTime.class); /*** * procTimeMonitoringState: true if monitoring is on, default is false @@ -92,7 +92,8 @@ public class PktinProcessingTime { // Time bucket created once and reused as needed public CumulativeTimeBucket ctb; // Current time bucket being filled public CircularTimeBucketSet ctbs; // Set of all time buckets - private int numComponents; + private int numComponents; // Numbert of components being monitored + private int numBuckets; // number of time buckets, each 10s long public Long getLastPktTime_ns() { @@ -132,25 +133,33 @@ public class PktinProcessingTime { this.numComponents = numComponents; } + public int getNumBuckets() { + return numBuckets; + } + public void setNumBuckets(int numBuckets) { + this.numBuckets = numBuckets; + } + // Constructor public PktinProcessingTime() { FlListenerID.populateCompNames(); setNumComponents(BB_LAST_LISTENER_ID + 1); perfMonCfgs = new PerfMonConfigs(); - ctbs = new CircularTimeBucketSet(getNumComponents()); + numBuckets = BUCKET_SET_SIZE; + ctbs = new CircularTimeBucketSet(getNumComponents(), numBuckets); ctb = ctbs.timeBucketSet[ctbs.curBucketIdx]; ctb.startTime_ms = System.currentTimeMillis(); ctb.startTime_ns = System.nanoTime(); } /*** - * 30 buckets each holding 10s of processing time data, a total + * BUCKET_SET_SIZE buckets each holding 10s of processing time data, a total * of 30*10s = 5mins of processing time data is maintained */ protected static final long ONE_BUCKET_DURATION_SECONDS_LONG = 10;// seconds protected static final int ONE_BUCKET_DURATION_SECONDS_INT = 10;// seconds protected static final long ONE_BUCKET_DURATION_NANOSECONDS = ONE_BUCKET_DURATION_SECONDS_LONG * 1000000000; - protected static final int BUCKET_SET_SIZE = 30; + protected static final int BUCKET_SET_SIZE = 360; // 1hr (=1*60*60/10) protected static final int TOT_PROC_TIME_WARN_THRESHOLD_US = 5000; // ms protected static final int TOT_PROC_TIME_ALERT_THRESHOLD_US = 10000; // ms, TBD, alert not in logger @@ -317,9 +326,9 @@ public class PktinProcessingTime { return (int) Math.sqrt((double)temp); } - public CircularTimeBucketSet(int numComps) { - timeBucketSet = new CumulativeTimeBucket[BUCKET_SET_SIZE]; - for (int idx= 0; idx < BUCKET_SET_SIZE; idx++) { + public CircularTimeBucketSet(int numComps, int numBuckets) { + timeBucketSet = new CumulativeTimeBucket[numBuckets]; + for (int idx= 0; idx < numBuckets; idx++) { timeBucketSet[idx] = new CumulativeTimeBucket(numComps); timeBucketSet[idx].setBucketNo(idx); } @@ -354,7 +363,7 @@ public class PktinProcessingTime { ctb.duration_s = ONE_BUCKET_DURATION_SECONDS_INT; // Move to the new bucket - if (curBucketIdx >= BUCKET_SET_SIZE-1) { + if (curBucketIdx >= numBuckets-1) { curBucketIdx = 0; allBucketsValid = true; } else { diff --git a/src/main/java/net/floodlightcontroller/routing/dijkstra/RoutingImpl.java b/src/main/java/net/floodlightcontroller/routing/dijkstra/RoutingImpl.java index d1a34212d3aa1be9e0dd5b35d24ca0016a90c140..8e37806004a34f5031c5dd0fe117389aa46b2458 100644 --- a/src/main/java/net/floodlightcontroller/routing/dijkstra/RoutingImpl.java +++ b/src/main/java/net/floodlightcontroller/routing/dijkstra/RoutingImpl.java @@ -203,8 +203,8 @@ public class RoutingImpl implements IRoutingEngine, ITopologyAware { network_updated = true; } + Link srcLink = new Link(srcPort, dstPort, dstId); if (added) { - Link srcLink = new Link(srcPort, dstPort, dstId); if (src.containsKey(srcPort)) { log.debug("update: unexpected link add request - srcPort in use src, link: {}, {}", srcId, src.get(srcPort)); } @@ -214,9 +214,9 @@ public class RoutingImpl implements IRoutingEngine, ITopologyAware { } else { // Only remove if that link actually exists. - if (src.containsKey(srcPort) && src.get(srcPort).getDst().equals(dstId)) { + if (src.containsKey(srcLink)) { log.debug("update: removed link: {}, {}", srcId, srcPort); - src.remove(srcPort); + src.remove(srcLink); network_updated = true; } else { diff --git a/src/main/java/net/floodlightcontroller/topology/internal/TopologyImpl.java b/src/main/java/net/floodlightcontroller/topology/internal/TopologyImpl.java index ed931f4c3c944a873b1b3b91b046e94be818306b..e079b1e94f89957fcb1c5d1b16f3a2e378f91c78 100644 --- a/src/main/java/net/floodlightcontroller/topology/internal/TopologyImpl.java +++ b/src/main/java/net/floodlightcontroller/topology/internal/TopologyImpl.java @@ -162,7 +162,9 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, * Map from switch id to a set of all links with it as an endpoint */ protected Map<IOFSwitch, Set<LinkTuple>> switchLinks; - protected Set<ITopologyAware> topologyAware; + /* topology aware components are called in the order they were added to the + * the array */ + protected ArrayList<ITopologyAware> topologyAware; protected BlockingQueue<Update> updates; protected Thread updatesThread; @@ -261,7 +263,7 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, do { Update update = updates.take(); if (topologyAware != null) { - for (ITopologyAware ta : topologyAware) { + for (ITopologyAware ta : topologyAware) { // order maintained if (log.isDebugEnabled()) { log.debug("Dispatching topology update {} {} {} {} {}", new Object[]{update.operation, @@ -665,7 +667,7 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, if (eth.isMulticast()) { if (log.isTraceEnabled()) log.trace("Received a multicast LLDP packet from a different controller, allowing the packet to follow normal processing chain."); - return Command.CONTINUE; + return Command.STOP; } if (log.isTraceEnabled()) { log.trace("Received a unicast LLDP packet from a different controller, stop processing the packet here."); @@ -1675,7 +1677,7 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, /** * @param topologyAware the topologyAware to set */ - public void setTopologyAware(Set<ITopologyAware> topologyAware) { + public void setTopologyAware(ArrayList<ITopologyAware> topologyAware) { // TODO make this a copy on write set or lock it somehow this.topologyAware = topologyAware; } @@ -1717,7 +1719,7 @@ public class TopologyImpl implements IOFMessageListener, IOFSwitchListener, } /** - * @param storageSource the storage source to use for persisting link info + * @param routingEngine the storage source to use for persisting link info */ public void setRoutingEngine(IRoutingEngine routingEngine) { this.routingEngine = routingEngine; diff --git a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java index 508cb7435a0978e523cb25ffad0ac6b71b824df2..c9274ae08968b254d4c7ad47df3a322282880d8f 100644 --- a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java +++ b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java @@ -19,6 +19,7 @@ package net.floodlightcontroller.devicemanager.internal; import java.util.Date; import java.util.HashMap; +import java.util.Map; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.createNiceMock; @@ -34,6 +35,7 @@ import net.floodlightcontroller.packet.ARP; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPacket; import net.floodlightcontroller.packet.IPv4; +import net.floodlightcontroller.storage.IStorageSource; import net.floodlightcontroller.storage.memory.MemoryStorageSource; import net.floodlightcontroller.test.FloodlightTestCase; import net.floodlightcontroller.topology.ITopology; @@ -44,6 +46,7 @@ import org.junit.Test; import org.openflow.protocol.OFPacketIn; import org.openflow.protocol.OFType; import org.openflow.protocol.OFPacketIn.OFPacketInReason; +import org.openflow.protocol.OFPhysicalPort; /** * @@ -58,6 +61,7 @@ public class DeviceManagerImplTest extends FloodlightTestCase { private OFPacketIn thirdPacketIn; MockFloodlightProvider mockFloodlightProvider; DeviceManagerImpl deviceManager; + IStorageSource storageSource; @Before public void setUp() { @@ -65,8 +69,9 @@ public class DeviceManagerImplTest extends FloodlightTestCase { mockFloodlightProvider = getMockFloodlightProvider(); deviceManager = new DeviceManagerImpl(); + storageSource = new MemoryStorageSource(); deviceManager.setFloodlightProvider(mockFloodlightProvider); - deviceManager.setStorageSource(new MemoryStorageSource()); + deviceManager.setStorageSource(storageSource); deviceManager.startUp(); // Build our test packet @@ -351,6 +356,10 @@ public class DeviceManagerImplTest extends FloodlightTestCase { @Test public void testAttachmentPointFlapping() throws Exception { + OFPhysicalPort port1 = new OFPhysicalPort(); + OFPhysicalPort port2 = new OFPhysicalPort(); + port1.setName("port1"); + port2.setName("port2"); byte[] dataLayerSource = ((Ethernet)this.testPacket).getSourceMACAddress(); @@ -359,6 +368,8 @@ public class DeviceManagerImplTest extends FloodlightTestCase { expect(mockSwitch.getId()).andReturn(1L).anyTimes(); expect(mockSwitch.getStringId()).andReturn("00:00:00:00:00:00:00:01").anyTimes(); ITopology mockTopology = createMock(ITopology.class); + expect(mockSwitch.getPort((short)1)).andReturn(port1).anyTimes(); + expect(mockSwitch.getPort((short)2)).andReturn(port2).anyTimes(); expect(mockTopology.isInternal(new SwitchPortTuple(mockSwitch, 1))) .andReturn(false).atLeastOnce(); expect(mockTopology.isInternal(new SwitchPortTuple(mockSwitch, 2))) @@ -391,4 +402,93 @@ public class DeviceManagerImplTest extends FloodlightTestCase { // Reset the device cache deviceManager.clearAllDeviceStateFromMemory(); } + + private static final Map<String, Object> pcPort1; + static { + pcPort1 = new HashMap<String, Object>(); + pcPort1.put(DeviceManagerImpl.PORT_CHANNEL_COLUMN_NAME, "channel"); + pcPort1.put(DeviceManagerImpl.PC_PORT_COLUMN_NAME, "port1"); + pcPort1.put(DeviceManagerImpl.PC_SWITCH_COLUMN_NAME, "00:00:00:00:00:00:00:01"); + pcPort1.put(DeviceManagerImpl.PC_ID_COLUMN_NAME, "00:00:00:00:00:00:00:01|port1"); + } + + private static final Map<String, Object> pcPort2; + static { + pcPort2 = new HashMap<String, Object>(); + pcPort2.put(DeviceManagerImpl.PORT_CHANNEL_COLUMN_NAME, "channel"); + pcPort2.put(DeviceManagerImpl.PC_PORT_COLUMN_NAME, "port2"); + pcPort2.put(DeviceManagerImpl.PC_SWITCH_COLUMN_NAME, "00:00:00:00:00:00:00:01"); + pcPort2.put(DeviceManagerImpl.PC_ID_COLUMN_NAME, "00:00:00:00:00:00:00:01|port2"); + } + + private void setupPortChannel() { + + storageSource.insertRow(DeviceManagerImpl.PORT_CHANNEL_TABLE_NAME, pcPort1); + storageSource.insertRow(DeviceManagerImpl.PORT_CHANNEL_TABLE_NAME, pcPort2); + deviceManager.readPortChannelConfigFromStorage(); + } + + private void teardownPortChannel() { + storageSource.deleteRow(DeviceManagerImpl.PORT_CHANNEL_TABLE_NAME, + pcPort1.get(DeviceManagerImpl.PC_ID_COLUMN_NAME)); + storageSource.deleteRow(DeviceManagerImpl.PORT_CHANNEL_TABLE_NAME, + pcPort2.get(DeviceManagerImpl.PC_ID_COLUMN_NAME)); + deviceManager.readPortChannelConfigFromStorage(); + } + + /** + * The same test as testAttachmentPointFlapping except for port-channel + * @throws Exception + */ + @Test + public void testPortChannel() throws Exception { + OFPhysicalPort port1 = new OFPhysicalPort(); + OFPhysicalPort port2 = new OFPhysicalPort(); + port1.setName("port1"); + port2.setName("port2"); + + setupPortChannel(); + byte[] dataLayerSource = ((Ethernet)this.testPacket).getSourceMACAddress(); + + // Mock up our expected behavior + IOFSwitch mockSwitch = createMock(IOFSwitch.class); + expect(mockSwitch.getPort((short)1)).andReturn(port1).anyTimes(); + expect(mockSwitch.getPort((short)2)).andReturn(port2).anyTimes(); + expect(mockSwitch.getId()).andReturn(1L).anyTimes(); + expect(mockSwitch.getStringId()).andReturn("00:00:00:00:00:00:00:01").anyTimes(); + ITopology mockTopology = createMock(ITopology.class); + expect(mockTopology.isInternal(new SwitchPortTuple(mockSwitch, 1))) + .andReturn(false).atLeastOnce(); + expect(mockTopology.isInternal(new SwitchPortTuple(mockSwitch, 2))) + .andReturn(false).atLeastOnce(); + deviceManager.setTopology(mockTopology); + + // Start recording the replay on the mocks + replay(mockSwitch, mockTopology); + + // Get the listener and trigger the packet in + mockFloodlightProvider.dispatchMessage(mockSwitch, this.packetIn); + mockFloodlightProvider.dispatchMessage(mockSwitch, this.packetIn.setInPort((short)2)); + mockFloodlightProvider.dispatchMessage(mockSwitch, this.packetIn.setInPort((short)1)); + mockFloodlightProvider.dispatchMessage(mockSwitch, this.packetIn.setInPort((short)2)); + mockFloodlightProvider.dispatchMessage(mockSwitch, this.packetIn.setInPort((short)1)); + mockFloodlightProvider.dispatchMessage(mockSwitch, this.packetIn.setInPort((short)2)); + + Device device = deviceManager.getDeviceByDataLayerAddress(dataLayerSource); + + // Verify the replay matched our expectations + verify(mockSwitch, mockTopology); + + // Verify the device + assertEquals(device.getAttachmentPoints().size(), 1); + assertEquals(device.getOldAttachmentPoints().size(), 1); + for (DeviceAttachmentPoint ap : device.getOldAttachmentPoints()) { + assertFalse(ap.isBlocked()); + } + + // Reset the device cache + deviceManager.clearAllDeviceStateFromMemory(); + + teardownPortChannel(); + } } diff --git a/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusherTest.java b/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusherTest.java index d1316f47d757b5f1e1486efab3624a42da649ee3..fbd700e28ddaf385f36fc07cf0dbfbd5e836962e 100644 --- a/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusherTest.java +++ b/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusherTest.java @@ -87,7 +87,7 @@ public class StaticFlowEntryPusherTest extends FloodlightTestCase { staticFlowEntryPusher.addEntry(flowMod2); // Verify that the switch has gotten some flow_mods - assertEquals(true, writeCapture.getValues().size() == 2); + assertEquals(writeCapture.getValues().size(), 2); int count = 5; while (count >= 0) { diff --git a/src/test/java/net/floodlightcontroller/topology/internal/TopologyImplTest.java b/src/test/java/net/floodlightcontroller/topology/internal/TopologyImplTest.java index a796a083c7fb0ef374145a28e996dba0c6e756cb..ad7247005d4b3c95639a25fcb005d132f7903117 100644 --- a/src/test/java/net/floodlightcontroller/topology/internal/TopologyImplTest.java +++ b/src/test/java/net/floodlightcontroller/topology/internal/TopologyImplTest.java @@ -67,7 +67,7 @@ public class TopologyImplTest extends FloodlightTestCase { topology.setStorageSource(new MemoryStorageSource()); RoutingImpl routingEngine = new RoutingImpl(); topology.setRoutingEngine(routingEngine); - HashSet<ITopologyAware> topologyAware = new HashSet<ITopologyAware>(); + ArrayList<ITopologyAware> topologyAware = new ArrayList<ITopologyAware>(); topologyAware.add(routingEngine); topology.setTopologyAware(topologyAware); topology.startUp();