/** * Create a switch sync representation and add it to the store and * notify the store listener. * If the description and/or features reply are null, we'll allocate * the default one */ public void doAddSwitchToStore(long dpid, OFDescriptionStatistics desc, OFFeaturesReply featuresReply) throws Exception { if (featuresReply == null) { featuresReply = createOFFeaturesReply(); featuresReply.setDatapathId(dpid); } if (desc == null) { desc = createOFDescriptionStatistics(); } SwitchSyncRepresentation ssr = new SwitchSyncRepresentation(featuresReply, desc); storeClient.put(dpid, ssr); Iterator<Long> keysToNotify = Collections.singletonList(dpid).iterator(); controller.getStoreListener().keysModified(keysToNotify, UpdateType.REMOTE); }
@Override public void keysModified(Iterator<DatapathId> keys, UpdateType type) { if (type == UpdateType.LOCAL) { // We only care for remote updates return; } while(keys.hasNext()) { DatapathId key = keys.next(); Versioned<SwitchSyncRepresentation> versionedSwitch = null; try { versionedSwitch = storeClient.get(key); } catch (SyncException e) { log.error("Exception while retrieving switch " + key.toString() + " from sync store. Skipping", e); continue; } if (log.isTraceEnabled()) { log.trace("Reveiced switch store notification: key={}, " + "entry={}", key, versionedSwitch.getValue()); } // versionedSwtich won't be null. storeClient.get() always // returns a non-null or throws an exception if (versionedSwitch.getValue() == null) { switchRemovedFromStore(key); continue; } SwitchSyncRepresentation storedSwitch = versionedSwitch.getValue(); IOFSwitch sw = getSwitch(storedSwitch.getDpid()); //TODO @Ryan need to get IOFSwitchBackend setFeaturesReply(storedSwitch.getFeaturesReply(sw.getOFFactory())); if (!key.equals(storedSwitch.getFeaturesReply(sw.getOFFactory()).getDatapathId())) { log.error("Inconsistent DPIDs from switch sync store: " + "key is {} but sw.getId() says {}. Ignoring", key.toString(), sw.getId()); continue; } switchAddedToStore(sw); } }
@Test /** * Test switchActivated for a new switch, i.e., a switch that was not * previously known to the controller cluser. We expect that all * flow mods are cleared and we expect a switchAdded */ public void testNewSwitchActivated() throws Exception { // We set AlwaysClearFlowsOnSwActivate to false but we still // expect a clearAllFlowMods() because the AlwaysClearFlowsOnSwActivate // is only relevant if a switch that was previously known is activated!! controller.setAlwaysClearFlowsOnSwActivate(false); IOFSwitch sw = createMock(IOFSwitch.class); setupSwitchForAddSwitch(sw, 0L, null, null); sw.clearAllFlowMods(); expectLastCall().once(); // strict mock. Order of events matters! IOFSwitchListener listener = createStrictMock(IOFSwitchListener.class); listener.switchAdded(0L); expectLastCall().once(); listener.switchActivated(0L); expectLastCall().once(); replay(listener); controller.addOFSwitchListener(listener); replay(sw); controller.switchActivated(sw); verify(sw); assertEquals(sw, controller.getSwitch(0L)); controller.processUpdateQueueForTesting(); verify(listener); SwitchSyncRepresentation storedSwitch = storeClient.getValue(0L); assertEquals(createOFFeaturesReply(), storedSwitch.getFeaturesReply()); assertEquals(createOFDescriptionStatistics(), storedSwitch.getDescription()); }
/** * Create and activate a switch, either completely new or reconnected * The mocked switch instance will be returned. It wil be reset. */ private IOFSwitch doActivateSwitchInt(long dpid, OFDescriptionStatistics desc, OFFeaturesReply featuresReply, boolean clearFlows) throws Exception { controller.setAlwaysClearFlowsOnSwActivate(true); IOFSwitch sw = createMock(IOFSwitch.class); if (featuresReply == null) { featuresReply = createOFFeaturesReply(); featuresReply.setDatapathId(dpid); } if (desc == null) { desc = createOFDescriptionStatistics(); } setupSwitchForAddSwitch(sw, dpid, desc, featuresReply); if (clearFlows) { sw.clearAllFlowMods(); expectLastCall().once(); } replay(sw); controller.switchActivated(sw); verify(sw); assertEquals(sw, controller.getSwitch(dpid)); // drain updates and ignore controller.processUpdateQueueForTesting(); SwitchSyncRepresentation storedSwitch = storeClient.getValue(dpid); assertEquals(featuresReply, storedSwitch.getFeaturesReply()); assertEquals(desc, storedSwitch.getDescription()); reset(sw); return sw; }
/** Add switch to store with inconsistent DPID * @throws Exception */ @Test public void testInconsistentStoreDpid() throws Exception { doSetUp(Role.SLAVE); IOFSwitchListener listener = createMock(IOFSwitchListener.class); controller.addOFSwitchListener(listener); replay(listener); OFFeaturesReply featuresReply = createOFFeaturesReply(); featuresReply.setDatapathId(42L); OFDescriptionStatistics desc = createOFDescriptionStatistics(); SwitchSyncRepresentation ssr = new SwitchSyncRepresentation(featuresReply, desc); storeClient.put(1L, ssr); Iterator<Long> keysToNotify = Collections.singletonList(1L).iterator(); controller.getStoreListener().keysModified(keysToNotify, UpdateType.REMOTE); controller.processUpdateQueueForTesting(); verify(listener); assertNull("Switch should not have been added", controller.getSwitch(1L)); assertNull("Switch should not have been added", controller.getSwitch(42L)); }
@Override public void keysModified(Iterator<Long> keys, UpdateType type) { if (type == UpdateType.LOCAL) { // We only care for remote updates return; } counters.remoteStoreNotification.updateCounterWithFlush(); while(keys.hasNext()) { Long key = keys.next(); Versioned<SwitchSyncRepresentation> versionedSwitch = null; try { versionedSwitch = storeClient.get(key); } catch (SyncException e) { counters.storeSyncError.updateCounterWithFlush(); log.error("Exception while retrieving switch " + HexString.toHexString(key) + " from sync store. Skipping", e); continue; } if (log.isTraceEnabled()) { log.trace("Reveiced switch store notification: key={}, " + "entry={}", key, versionedSwitch.getValue()); } // versionedSwtich won't be null. storeClient.get() always // returns a non-null or throws an exception if (versionedSwitch.getValue() == null) { switchRemovedFromStore(key); continue; } SwitchSyncRepresentation storedSwitch = versionedSwitch.getValue(); IOFSwitch sw = getOFSwitchInstance(storedSwitch.getDescription()); sw.setFeaturesReply(storedSwitch.getFeaturesReply()); if (!key.equals(storedSwitch.getFeaturesReply().getDatapathId())) { counters.storeSyncError.updateCounterWithFlush(); log.error("Inconsistent DPIDs from switch sync store: " + "key is {} but sw.getId() says {}. Ignoring", HexString.toHexString(key), sw.getStringId()); continue; } switchAddedToStore(sw); } }
/** * Test that notifyPortChanged() results in an IOFSwitchListener * update and that its arguments are passed through to * the listener call */ @Test public void testNotifySwitchPoArtChanged() throws Exception { long dpid = 42L; OFFeaturesReply fr1 = createOFFeaturesReply(); fr1.setDatapathId(dpid); OFPhysicalPort p1 = createOFPhysicalPort("Port1", 1); fr1.setPorts(Collections.singletonList(p1)); OFFeaturesReply fr2 = createOFFeaturesReply(); fr1.setDatapathId(dpid); OFPhysicalPort p2 = createOFPhysicalPort("Port1", 1); p2.setAdvertisedFeatures(0x2); // just some bogus values fr2.setPorts(Collections.singletonList(p2)); OFDescriptionStatistics desc = createOFDescriptionStatistics(); // activate switch IOFSwitch sw = doActivateNewSwitch(dpid, desc, fr1); // check the store SwitchSyncRepresentation ssr = storeClient.getValue(dpid); assertNotNull(ssr); assertEquals(dpid, ssr.getDpid()); assertEquals(1, ssr.getPorts().size()); assertEquals(p1, ssr.getPorts().get(0).toOFPhysicalPort()); IOFSwitchListener listener = createMock(IOFSwitchListener.class); controller.addOFSwitchListener(listener); // setup switch with the new, second features reply (and thus ports) setupSwitchForAddSwitch(sw, dpid, desc, fr2); listener.switchPortChanged(dpid, ImmutablePort.fromOFPhysicalPort(p2), PortChangeType.OTHER_UPDATE); expectLastCall().once(); replay(listener); replay(sw); controller.notifyPortChanged(sw, ImmutablePort.fromOFPhysicalPort(p2), PortChangeType.OTHER_UPDATE); controller.processUpdateQueueForTesting(); verify(listener); verify(sw); // check the store ssr = storeClient.getValue(dpid); assertNotNull(ssr); assertEquals(dpid, ssr.getDpid()); assertEquals(1, ssr.getPorts().size()); assertEquals(p2, ssr.getPorts().get(0).toOFPhysicalPort()); }