@Override public synchronized void notifyPortChanged(IOFSwitchBackend sw, OFPortDesc port, PortChangeType changeType) { Preconditions.checkNotNull(sw, "switch must not be null"); Preconditions.checkNotNull(port, "port must not be null"); Preconditions.checkNotNull(changeType, "changeType must not be null"); if (role != OFControllerRole.ROLE_MASTER) { counters.invalidPortsChanged.increment(); return; } if (!this.switches.containsKey(sw.getId())) { counters.invalidPortsChanged.increment(); return; } if(sw.getStatus().isVisible()) { // no need to count here. SwitchUpdate.dispatch will count // the portchanged SwitchUpdate update = new SwitchUpdate(sw.getId(), SwitchUpdateType.PORTCHANGED, port, changeType); addUpdateToQueue(update); } }
/** * Test switchActivated for a new switch while in slave: disconnect the switch */ @Test public void testNewSwitchActivatedWhileSlave() throws Exception { doSetUp(HARole.STANDBY); IOFSwitchBackend sw = createMock(IOFSwitchBackend.class); IOFSwitchListener listener = createMock(IOFSwitchListener.class); switchManager.addOFSwitchListener(listener); expect(sw.getId()).andReturn(DATAPATH_ID_0).anyTimes(); expect(sw.getStatus()).andReturn(SwitchStatus.MASTER).anyTimes(); sw.disconnect(); expectLastCall().once(); expect(sw.getOFFactory()).andReturn(factory).once(); replay(sw, listener); // nothing recorded switchManager.switchAdded(sw); switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER); verify(sw); controller.processUpdateQueueForTesting(); verify(listener); }
/** * Create and activate a switch, either completely new or reconnected * The mocked switch instance will be returned. It will be reset. */ private IOFSwitchBackend doActivateSwitchInt(DatapathId datapathId, SwitchDescription description, OFFeaturesReply featuresReply, boolean clearFlows) throws Exception { IOFSwitchBackend sw = createMock(IOFSwitchBackend.class); if (featuresReply == null) { featuresReply = createOFFeaturesReply(datapathId); } if (description == null) { description = createSwitchDescription(); } setupSwitchForAddSwitch(sw, datapathId, description, featuresReply); replay(sw); switchManager.switchAdded(sw); switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER); verify(sw); assertEquals(sw, switchManager.getSwitch(datapathId)); // drain updates and ignore controller.processUpdateQueueForTesting(); reset(sw); return sw; }
/** * Try to remove a switch that's different from what's in the active * switch map. Should be ignored */ @Test public void testSwitchDisconnectedOther() throws Exception { IOFSwitch origSw = doActivateNewSwitch(DATAPATH_ID_1, null, null); // create a new mock switch IOFSwitchBackend sw = createMock(IOFSwitchBackend.class); expect(sw.getId()).andReturn(DATAPATH_ID_1).anyTimes(); IOFSwitchListener listener = createMock(IOFSwitchListener.class); switchManager.addOFSwitchListener(listener); replay(sw, listener); switchManager.switchDisconnected(sw); controller.processUpdateQueueForTesting(); verify(sw, listener); expect(origSw.getStatus()).andReturn(SwitchStatus.MASTER).anyTimes(); replay(origSw); assertSame(origSw, switchManager.getSwitch(DATAPATH_ID_1)); }
/** * Tests that you can't remove a switch from the map returned by * getSwitches() (because getSwitches should return an unmodifiable * map) */ @Test public void testRemoveActiveSwitch() { IOFSwitchBackend sw = createNiceMock(IOFSwitchBackend.class); setupSwitchForAddSwitch(sw, DATAPATH_ID_1, null, null); replay(sw); switchManager.switchAdded(sw); switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER); assertEquals(sw, switchManager.getSwitch(DATAPATH_ID_1)); try { switchManager.getAllSwitchMap().remove(DATAPATH_ID_1); fail("Expected: UnsupportedOperationException"); } catch(UnsupportedOperationException e) { // expected } // we don't care for updates. drain queue. controller.processUpdateQueueForTesting(); }
/** * Tests that the switch manager should only return a switch to a getActiveSwitch * call when the switch is visible/active. */ @Test public void testGetActiveSwitch() { MockOFConnection connection = new MockOFConnection(DATAPATH_ID_1, OFAuxId.MAIN); IOFSwitchBackend sw = new MockOFSwitchImpl(connection); sw.setStatus(SwitchStatus.HANDSHAKE); assertNull(switchManager.getActiveSwitch(DATAPATH_ID_1)); switchManager.switchAdded(sw); assertNull(switchManager.getActiveSwitch(DATAPATH_ID_1)); sw.setStatus(SwitchStatus.MASTER); assertEquals(sw, switchManager.getActiveSwitch(DATAPATH_ID_1)); sw.setStatus(SwitchStatus.QUARANTINED); assertNull(switchManager.getActiveSwitch(DATAPATH_ID_1)); sw.setStatus(SwitchStatus.SLAVE); assertEquals(sw, switchManager.getActiveSwitch(DATAPATH_ID_1)); sw.setStatus(SwitchStatus.DISCONNECTED); assertNull(switchManager.getActiveSwitch(DATAPATH_ID_1)); // we don't care for updates. drain queue. controller.processUpdateQueueForTesting(); }
@Override @Test public void moveToWaitInitialRole() throws Exception { moveToWaitAppHandshakeState(); assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(WaitAppHandshakeState.class)); reset(sw); expect(sw.getAttribute(IOFSwitchBackend.SWITCH_SUPPORTS_NX_ROLE)).andReturn(true).anyTimes(); replay(sw); reset(roleManager); expect(roleManager.getOFControllerRole()).andReturn(OFControllerRole.ROLE_MASTER).anyTimes(); roleManager.notifyControllerConnectionUpdate(); expectLastCall().once(); replay(roleManager); WaitAppHandshakeState state = (WaitAppHandshakeState) switchHandler.getStateForTesting(); state.enterNextPlugin(); // Expect wait initial role's enterState message to be written OFMessage msg = connection.retrieveMessage(); assertThat(msg, CoreMatchers.instanceOf(OFRoleRequest.class)); verifyUniqueXids(msg); assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class)); }
@Override @Test public void moveToWaitInitialRole() throws Exception { moveToWaitAppHandshakeState(); assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(WaitAppHandshakeState.class)); reset(sw); expect(sw.getAttribute(IOFSwitchBackend.SWITCH_SUPPORTS_NX_ROLE)).andReturn(true).anyTimes(); replay(sw); reset(roleManager); expect(roleManager.getOFControllerRole()).andReturn(OFControllerRole.ROLE_MASTER).anyTimes(); replay(roleManager); WaitAppHandshakeState state = (WaitAppHandshakeState) switchHandler.getStateForTesting(); PluginResult result = new PluginResult(PluginResultType.CONTINUE); state.exitPlugin(result); assertThat(connection.retrieveMessage(), instanceOf(getRoleRequestClass())); assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class)); }
/** * Test switchActivated for a new switch while in slave: disconnect the switch */ @Test public void testNewSwitchActivatedWhileSlave() throws Exception { doSetUp(HARole.STANDBY); IOFSwitchBackend sw = createMock(IOFSwitchBackend.class); IOFSwitchListener listener = createMock(IOFSwitchListener.class); switchManager.addOFSwitchListener(listener); expect(sw.getId()).andReturn(DATAPATH_ID_0).anyTimes(); expect(sw.getStatus()).andReturn(SwitchStatus.MASTER).anyTimes(); sw.disconnect(); expectLastCall().once(); replay(sw, listener); // nothing recorded switchManager.switchAdded(sw); switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.MASTER); verify(sw); controller.processUpdateQueueForTesting(); verify(listener); }
@Before public void setUp() throws Exception { switchManager = createMock(IOFSwitchManager.class); roleManager = createMock(RoleManager.class); sw = createMock(IOFSwitchBackend.class); timer = createMock(Timer.class); expect(timer.newTimeout(anyObject(TimerTask.class), anyLong(), anyObject(TimeUnit.class))).andReturn(EasyMock.createNiceMock(Timeout.class)); replay(timer); seenXids = null; // TODO: should mock IDebugCounterService and make sure // the expected counters are updated. debugCounterService = new DebugCounterServiceImpl(); SwitchManagerCounters counters = new SwitchManagerCounters(debugCounterService); expect(switchManager.getCounters()).andReturn(counters).anyTimes(); replay(switchManager); connection = new MockOFConnection(featuresReply.getDatapathId(), OFAuxId.MAIN); switchHandler = new OFSwitchHandshakeHandler(connection, featuresReply, switchManager, roleManager, timer); // replay sw. Reset it if you need more specific behavior replay(sw); }
@Override public IOFSwitchBackend getOFSwitchInstance(IOFConnectionBackend connection, SwitchDescription description, OFFactory factory, DatapathId datapathId) { return null; }
@Override public void switchStatusChanged(IOFSwitchBackend sw, SwitchStatus oldStatus, SwitchStatus newStatus) { // do nothing }
/** * Iterates over all the switches and checks to see if they have controller * connections that points towards another master controller. * @return */ private boolean switchesHaveAnotherMaster() { IOFSwitchService switchService = controller.getSwitchService(); for(Entry<DatapathId, IOFSwitch> switchMap : switchService.getAllSwitchMap().entrySet()){ IOFSwitchBackend sw = (IOFSwitchBackend) switchMap.getValue(); if(sw.hasAnotherMaster()){ return true; } } return false; }
@Override public synchronized void switchAdded(IOFSwitchBackend sw) { DatapathId dpid = sw.getId(); IOFSwitchBackend oldSw = this.switches.put(dpid, sw); // Update event history evSwitch.newEventWithFlush(new SwitchEvent(dpid, "connected")); if (oldSw == sw) { // Note == for object equality, not .equals for value counters.errorActivatedSwitchNotPresent.increment(); log.error("Switch {} added twice?", sw); return; } else if (oldSw != null) { // This happens either when we have switches with duplicate // DPIDs or when a switch reconnects before we saw the // disconnect counters.switchWithSameDpidActivated.increment(); log.warn("New switch added {} for already-added switch {}", sw, oldSw); // We need to disconnect and remove the old switch // TODO: we notify switch listeners that the switch has been // removed and then we notify them that the new one has been // added. One could argue that a switchChanged notification // might be more appropriate in this case.... oldSw.cancelAllPendingRequests(); addUpdateToQueue(new SwitchUpdate(dpid, SwitchUpdateType.REMOVED)); oldSw.disconnect(); } /* * Set some other config options for this switch. */ if (sw.getOFFactory().getVersion().compareTo(OFVersion.OF_13) >= 0) { if (forwardToControllerFlowsUpToTableByDpid.containsKey(sw.getId())) { sw.setMaxTableForTableMissFlow(forwardToControllerFlowsUpToTableByDpid.get(sw.getId())); } else { sw.setMaxTableForTableMissFlow(forwardToControllerFlowsUpToTable); } } }
@Override public synchronized void switchDisconnected(IOFSwitchBackend sw) { DatapathId dpid = sw.getId(); IOFSwitchBackend presentSw = this.switches.get(dpid); if (presentSw != sw) { // Note == for object equality, not .equals for value counters.errorActivatedSwitchNotPresent.increment(); log.warn("Switch {} disconnect but not present in sync manager", sw); return; } counters.switchDisconnected.increment(); this.switches.remove(dpid); }
@Override public IOFSwitch getActiveSwitch(DatapathId dpid) { IOFSwitchBackend sw = this.switches.get(dpid); if(sw != null && sw.getStatus().isVisible()) return sw; else return null; }
@Override public IOFSwitchBackend getOFSwitchInstance(IOFConnectionBackend connection, SwitchDescription description, OFFactory factory, DatapathId datapathId) { return this.driverRegistry.getOFSwitchInstance(connection, description, factory, datapathId); }