/** * Extract the role information from an OF1.3 Role Reply Message. * * @param rrmsg the role message * @return RoleReplyInfo object * @throws SwitchStateException if the role information could not be extracted. */ @Override public RoleReplyInfo extractOFRoleReply(OFRoleReply rrmsg) throws SwitchStateException { OFControllerRole cr = rrmsg.getRole(); RoleState role = null; switch (cr) { case ROLE_EQUAL: role = RoleState.EQUAL; break; case ROLE_MASTER: role = RoleState.MASTER; break; case ROLE_SLAVE: role = RoleState.SLAVE; break; case ROLE_NOCHANGE: // switch should send current role default: String msg = String.format("Unknown controller role %s " + "received from switch %s", cr, sw); throw new SwitchStateException(msg); } return new RoleReplyInfo(role, rrmsg.getGenerationId(), rrmsg.getXid()); }
@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)); }
/** * Send a role request for the given role only if no other role * request is currently pending. * @param role The role to send to the switch. * @throws IOException */ synchronized void sendRoleRequestIfNotPending(OFControllerRole role, long xid) throws IOException { long now = System.nanoTime(); if (now - lastAssertTimeNs < assertTimeIntervalNs) { return; } lastAssertTimeNs = now; if (assertTimeIntervalNs < MAX_ASSERT_TIME_INTERVAL_NS) { // 2 minutes max assertTimeIntervalNs <<= 1; } else if (role == OFControllerRole.ROLE_MASTER){ log.warn("Reasserting master role on switch {}, " + "likely a switch config error with multiple masters", role, sw); } if (!requestPending) sendRoleRequest(role, xid); else switchManagerCounters.roleNotResentBecauseRolePending.increment(); }
/** * Send a role request with the given role to the switch. * * Send a role request with the given role to the switch and update * the pending request and timestamp. * * @param role * @throws IOException */ synchronized void sendRoleRequest(OFControllerRole role, long xid) throws IOException { /* * There are three cases to consider for SUPPORTS_NX_ROLE: * * 1) unset. We have neither received a role reply from the * switch nor has a request timed out. Send a request. * 2) TRUE: We've already send a request earlier and received * a reply. The switch supports role and we should send one. * 3) FALSE: We have already send a role and received an error. * The switch does not support roles. Don't send a role request, * set the switch's role directly. */ Boolean supportsNxRole = (Boolean) sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE); if ((supportsNxRole != null) && !supportsNxRole) { setSwitchRole(role, RoleRecvStatus.UNSUPPORTED); } else { pendingXid = sendNiciraRoleRequest(role, xid); pendingRole = role; this.roleSubmitTimeNs = System.nanoTime(); requestPending = true; } }
/** * Set the role for this switch / channel. * * If the status indicates that we received a reply we set the role. * If the status indicates otherwise we disconnect the switch if * the role is SLAVE. * * "Setting a role" means setting the appropriate ChannelState, * setting the flags on the switch and * notifying Controller.java about new role of the switch * * @param role The role to set. * @param status How we derived at the decision to set this status. */ synchronized private void setSwitchRole(OFControllerRole role, RoleRecvStatus status) { requestPending = false; if (status == RoleRecvStatus.RECEIVED_REPLY) sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true); else sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false); sw.setControllerRole(role); if (role != OFControllerRole.ROLE_SLAVE) { OFSwitchHandshakeHandler.this.setState(new MasterState()); } else { if (status != RoleRecvStatus.RECEIVED_REPLY) { if (log.isDebugEnabled()) { log.debug("Disconnecting switch {}. Doesn't support role" + "({}) request and controller is now SLAVE", getSwitchInfoString(), status); } // the disconnect will trigger a switch removed to // controller so no need to signal anything else sw.disconnect(); } else { OFSwitchHandshakeHandler.this.setState(new SlaveState()); } } }
@Override void enterState() { if (OFSwitchManager.clearTablesOnEachTransitionToMaster) { log.info("Clearing flow tables of {} on upcoming transition to MASTER.", sw.getId().toString()); clearAllTables(); } else if (OFSwitchManager.clearTablesOnInitialConnectAsMaster && initialRole == null) { /* don't do it if we were slave first */ initialRole = OFControllerRole.ROLE_MASTER; log.info("Clearing flow tables of {} on upcoming initial role as MASTER.", sw.getId().toString()); clearAllTables(); } sendBarrier(); /* Need to make sure the tables are clear before adding default flows */ addDefaultFlows(); /* * We also need a barrier between adding flows and notifying modules of the * transition to master. Some modules might modify the flow tables and expect * the clear/default flow operations above to have completed. */ sendBarrier(); setSwitchStatus(SwitchStatus.MASTER); }
@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); } }
/** * This test ensures that the switch accurately determined if another master * exists in the cluster by examining the controller connections it has. */ @Test public void testHasAnotherMaster() { URI cokeUri = URIUtil.createURI("1.2.3.4", 6653); InetSocketAddress address = (InetSocketAddress) sw.getConnection(OFAuxId.MAIN).getLocalInetAddress(); URI pepsiUri = URIUtil.createURI(address.getHostName(), address.getPort()); updateControllerConnections(sw, OFControllerRole.ROLE_SLAVE, OFBsnControllerConnectionState.BSN_CONTROLLER_CONNECTION_STATE_CONNECTED, cokeUri.toString(), OFControllerRole.ROLE_MASTER, OFBsnControllerConnectionState.BSN_CONTROLLER_CONNECTION_STATE_CONNECTED, pepsiUri.toString()); // From the perspective of pepsi, the cluster currently does NOT have another master controller assertFalse(sw.hasAnotherMaster()); // Switch the controller connections so that pepsi is no longer master updateControllerConnections(sw, OFControllerRole.ROLE_MASTER, OFBsnControllerConnectionState.BSN_CONTROLLER_CONNECTION_STATE_CONNECTED, cokeUri.toString(), OFControllerRole.ROLE_SLAVE, OFBsnControllerConnectionState.BSN_CONTROLLER_CONNECTION_STATE_CONNECTED, pepsiUri.toString()); // From the perspective of pepsi, the cluster currently has another master controller assertTrue(sw.hasAnotherMaster()); }
/** * Setup the mock switch and write capture for a role request, set the * role and verify mocks. * @param supportsNxRole whether the switch supports role request messages * to setup the attribute. This must be null (don't yet know if roles * supported: send to check) or true. * @param role The role to send * @throws IOException */ private long setupSwitchSendRoleRequestAndVerify(Boolean supportsNxRole, OFControllerRole role) throws IOException { assertTrue("This internal test helper method most not be called " + "with supportsNxRole==false. Test setup broken", supportsNxRole == null || supportsNxRole == true); reset(sw); expect(sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE)) .andReturn(supportsNxRole).atLeastOnce(); replay(sw); switchHandler.sendRoleRequest(role); OFMessage msg = connection.retrieveMessage(); verifyRoleRequest(msg, role); verify(sw); return msg.getXid(); }
@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)); }
private static OFControllerRole parseRole(String role) { if (role == null || role.isEmpty()) { return OFControllerRole.ROLE_NOCHANGE; } role = role.toUpperCase(); if (role.contains(STR_ROLE_MASTER)) { return OFControllerRole.ROLE_MASTER; } else if (role.contains(STR_ROLE_SLAVE)) { return OFControllerRole.ROLE_SLAVE; } else if (role.contains(STR_ROLE_EQUAL) || role.contains(STR_ROLE_OTHER)) { return OFControllerRole.ROLE_EQUAL; } else { return OFControllerRole.ROLE_NOCHANGE; } }
/** * Test interaction with OFChannelHandler when the current role is * master. */ @Test public void testChannelHandlerMaster() { OFSwitchHandshakeHandler h = createMock(OFSwitchHandshakeHandler.class); // Reassert the role. reset(h); h.sendRoleRequestIfNotPending(OFControllerRole.ROLE_MASTER); replay(h); controller.reassertRole(h, HARole.ACTIVE); verify(h); // reassert a different role: no-op reset(h); replay(h); controller.reassertRole(h, HARole.STANDBY); verify(h); }
@Override @LogMessageDoc(level="WARN", message="Received PacketIn from switch {} while" + "being slave. Reasserting slave role.", explanation="The switch has receive a PacketIn despite being " + "in slave role indicating inconsistent controller roles", recommendation="This situation can occurs transiently during role" + " changes. If, however, the condition persists or happens" + " frequently this indicates a role inconsistency. " + LogMessageDoc.CHECK_CONTROLLER ) void processOFPacketIn(OFPacketIn m) { // we don't expect packetIn while slave, reassert we are slave switchManagerCounters.packetInWhileSwitchIsSlave.increment(); log.warn("Received PacketIn from switch {} while" + "being slave. Reasserting slave role.", sw); reassertRole(OFControllerRole.ROLE_SLAVE); }
private int sendOF13RoleRequest(RoleState role) throws IOException { // Convert the role enum to the appropriate role to send OFControllerRole roleToSend = OFControllerRole.ROLE_NOCHANGE; switch (role) { case EQUAL: roleToSend = OFControllerRole.ROLE_EQUAL; break; case MASTER: roleToSend = OFControllerRole.ROLE_MASTER; break; case SLAVE: roleToSend = OFControllerRole.ROLE_SLAVE; break; default: log.warn("Sending default role.noChange to switch {}." + " Should only be used for queries.", sw); } int xid = sw.getNextTransactionId(); OFRoleRequest rrm = OFFactories.getFactory(OFVersion.OF_13) .buildRoleRequest() .setRole(roleToSend) .setXid(xid) //FIXME fix below when we actually use generation ids .setGenerationId(U64.ZERO) .build(); sw.sendRoleRequest(rrm); return xid; }
@Override protected OFMessage getRoleReply(long xid, OFControllerRole role) { OFRoleReply roleReply = factory.buildRoleReply() .setXid(xid) .setRole(role) .build(); return roleReply; }
/** Move the channel from scratch to SLAVE state * Builds on doMoveToWaitInitialRole() * adds testing for WAIT_INITAL_ROLE state * * This method tests only the simple case that the switch supports roles * and transitions to SLAVE */ @Test public void testInitialMoveToSlaveWithRole() throws Exception { // first, move us to WAIT_INITIAL_ROLE_STATE moveToWaitInitialRole(); assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class)); // Set the role long xid = setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_SLAVE); assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class)); // prepare mocks and inject the role reply message reset(sw); sw.setAttribute(IOFSwitchBackend.SWITCH_SUPPORTS_NX_ROLE, true); expectLastCall().once(); sw.setControllerRole(OFControllerRole.ROLE_SLAVE); expectLastCall().once(); expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE).once(); sw.setStatus(SwitchStatus.SLAVE); expectLastCall().once(); replay(sw); reset(switchManager); switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, SwitchStatus.SLAVE); expectLastCall().once(); replay(switchManager); OFMessage reply = getRoleReply(xid, OFControllerRole.ROLE_SLAVE); // sendMessageToHandler will verify and rest controller mock switchHandler.processOFMessage(reply); assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.SlaveState.class)); }
public void serializeHarole(OFControllerRole role, JsonGenerator jGen) throws IOException, JsonProcessingException { if ( null == role ) jGen.writeStringField("harole","null"); else jGen.writeStringField("harole",HARole.ofOFRole(role).toString()); }
/** Move channel from scratch to WAIT_INITIAL_STATE, then MASTER, * then SLAVE for cases where the switch does not support roles. * I.e., the final SLAVE transition should disconnect the switch. */ @Test public void testNoRoleInitialToMasterToSlave() throws Exception { int xid = 46; // First, lets move the state to MASTER without role support testInitialMoveToMasterNoRole(); assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.MasterState.class)); assertThat("Unexpected messages have been captured", connection.getMessages(), Matchers.empty()); // try to set master role again. should be a no-op setupSwitchRoleChangeUnsupported(xid, OFControllerRole.ROLE_MASTER); assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.MasterState.class)); assertThat("Unexpected messages have been captured", connection.getMessages(), Matchers.empty()); setupSwitchRoleChangeUnsupported(xid, OFControllerRole.ROLE_SLAVE); assertThat(connection.isConnected(), equalTo(false)); assertThat("Unexpected messages have been captured", connection.getMessages(), Matchers.empty()); }
/** * Deliver a received role reply and set SWITCH_SUPPORTS_NX_ROLE. * * Check if a request is pending and if the received reply matches the * the expected pending reply (we check both role and xid) we set * the role for the switch/channel. * * If a request is pending but doesn't match the reply we ignore it. * * If no request is pending we disconnect. * * @param xid * @param role * @throws SwitchStateException if no request is pending */ synchronized void deliverRoleReply(long xid, OFControllerRole role) { log.debug("DELIVERING ROLE REPLY {}", role.toString()); if (!requestPending) { // Maybe don't disconnect if the role reply we received is // for the same role we are already in. String msg = String.format("Switch: [%s], State: [%s], " + "received unexpected RoleReply[%s]. " + "No roles are pending", OFSwitchHandshakeHandler.this.getSwitchInfoString(), OFSwitchHandshakeHandler.this.state.toString(), role); throw new SwitchStateException(msg); } if (pendingXid == xid && pendingRole == role) { log.debug("[{}] Received role reply message setting role to {}", getDpid(), role); switchManagerCounters.roleReplyReceived.increment(); setSwitchRole(role, RoleRecvStatus.RECEIVED_REPLY); } else { log.debug("[{}] Received stale or unexpected role reply " + "{}, xid={}. Ignoring. " + "Waiting for {}, xid={}", new Object[] { getDpid(), role, xid, pendingRole, pendingXid }); } }
@Override void processOFExperimenter(OFExperimenter m) { OFControllerRole role = extractNiciraRoleReply(m); // If role == null it means the message wasn't really a // Nicira role reply. We ignore just dispatch it to the // OFMessage listenersa in this case. if (role != null) { roleChanger.deliverRoleReply(m.getXid(), role); } else { dispatchMessage(m); } }
@Override void processOFNiciraControllerRoleRequest(OFNiciraControllerRoleRequest m) { OFControllerRole role; switch (m.getRole()) { case ROLE_MASTER: role = OFControllerRole.ROLE_MASTER; break; case ROLE_SLAVE: role = OFControllerRole.ROLE_SLAVE; break; case ROLE_OTHER: role = OFControllerRole.ROLE_EQUAL; break; default: log.error("Attempted to change to invalid Nicira role {}.", m.getRole().toString()); return; } /* * This will get converted back to the correct factory of the switch later. * We will use OFRoleRequest though to simplify the API between OF versions. */ sendRoleRequest(OFFactories.getFactory(OFVersion.OF_13).buildRoleRequest() .setGenerationId(U64.ZERO) .setXid(m.getXid()) .setRole(role) .build()); }
@Override void enterState() { setSwitchStatus(SwitchStatus.SLAVE); if (initialRole == null) { initialRole = OFControllerRole.ROLE_SLAVE; } }
@Override void processOFExperimenter(OFExperimenter m) { OFControllerRole role = extractNiciraRoleReply(m); // If role == null it means the message wasn't really a // Nicira role reply. We ignore it. if (role != null) { roleChanger.deliverRoleReply(m.getXid(), role); } else { unhandledMessageReceived(m); } }
@Override void processOFPacketIn(OFPacketIn m) { // we don't expect packetIn while slave, reassert we are slave switchManagerCounters.packetInWhileSwitchIsSlave.increment(); log.warn("Received PacketIn from switch {} while" + "being slave. Reasserting slave role.", sw); reassertRole(OFControllerRole.ROLE_SLAVE); }
/** * Forwards to RoleChanger. See there. * @param role */ void sendRoleRequestIfNotPending(OFControllerRole role) { try { roleChanger.sendRoleRequestIfNotPending(role, 0); } catch (IOException e) { log.error("Disconnecting switch {} due to IO Error: {}", getSwitchInfoString(), e.getMessage()); mainConnection.disconnect(); } }
/** * Forwards to RoleChanger. See there. * @param role */ void sendRoleRequest(OFControllerRole role) { try { roleChanger.sendRoleRequest(role, 0); } catch (IOException e) { log.error("Disconnecting switch {} due to IO Error: {}", getSwitchInfoString(), e.getMessage()); mainConnection.disconnect(); } }
public static OFControllerRole niciraToOFRole(OFNiciraControllerRoleReply roleReply) { switch(roleReply.getRole()) { case ROLE_MASTER: return OFControllerRole.ROLE_MASTER; case ROLE_OTHER: return OFControllerRole.ROLE_EQUAL; case ROLE_SLAVE: return OFControllerRole.ROLE_SLAVE; default: throw new IllegalArgumentException("unknown Nicira role value: " + roleReply.getRole()); } }
/** Move the channel to SLAVE state * Expects that the channel is in MASTER or SLAVE state. * */ public void changeRoleToSlaveWithRequest() throws Exception { assertTrue("This method can only be called when handler is in " + "MASTER or SLAVE role", switchHandler.isHandshakeComplete()); // Set the role long xid = setupSwitchSendRoleRequestAndVerify(true, OFControllerRole.ROLE_SLAVE); // prepare mocks and inject the role reply message reset(sw); sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true); expectLastCall().once(); sw.setControllerRole(OFControllerRole.ROLE_SLAVE); expectLastCall().once(); expect(sw.getStatus()).andReturn(SwitchStatus.MASTER).once(); sw.setStatus(SwitchStatus.SLAVE); expectLastCall().once(); replay(sw); reset(switchManager); switchManager.switchStatusChanged(sw, SwitchStatus.MASTER, SwitchStatus.SLAVE); expectLastCall().once(); replay(switchManager); OFMessage reply = getRoleReply(xid, OFControllerRole.ROLE_SLAVE); connection.getListener().messageReceived(connection, reply); assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.SlaveState.class)); }
/** * Setup the mock switch for a role change request where the switch * does not support roles. * * Needs to verify and reset the controller since we need to set * an expectation */ @SuppressWarnings("unchecked") private void setupSwitchRoleChangeUnsupported(int xid, OFControllerRole role) { SwitchStatus newStatus = role != OFControllerRole.ROLE_SLAVE ? SwitchStatus.MASTER : SwitchStatus.SLAVE; boolean supportsNxRole = false; verify(switchManager); reset(sw, switchManager); expect(sw.getAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE)) .andReturn(supportsNxRole).atLeastOnce(); // TODO: hmmm. While it's not incorrect that we set the attribute // again it looks odd. Maybe change expect(sw.getOFFactory()).andReturn(factory).anyTimes(); sw.write(anyObject(OFMessage.class)); expectLastCall().anyTimes(); sw.write(anyObject(Iterable.class)); expectLastCall().anyTimes(); expect(sw.getTables()).andStubReturn((short)0); sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, supportsNxRole); expectLastCall().anyTimes(); sw.setControllerRole(role); expectLastCall().once(); if (role == OFControllerRole.ROLE_SLAVE) { sw.disconnect(); expectLastCall().once(); } else { expect(sw.getStatus()).andReturn(SwitchStatus.HANDSHAKE).once(); sw.setStatus(newStatus); expectLastCall().once(); switchManager.switchStatusChanged(sw, SwitchStatus.HANDSHAKE, newStatus); } replay(sw, switchManager); switchHandler.sendRoleRequest(role); verify(sw, switchManager); }
@Test public void testMasterSlaveWrites() { OFFactory factory = OFFactories.getFactory(OFVersion.OF_13); OFFlowAdd fa = factory.buildFlowAdd().build(); OFFlowStatsRequest fsr = factory.buildFlowStatsRequest().build(); List<OFMessage> msgList = new ArrayList<OFMessage>(); msgList.add(fa); msgList.add(fsr); reset(switchManager); expect(switchManager.isCategoryRegistered(LogicalOFMessageCategory.MAIN)).andReturn(true).times(6); switchManager.handleOutgoingMessage(sw, fa); expectLastCall().times(2); switchManager.handleOutgoingMessage(sw, fsr); expectLastCall().times(4); replay(switchManager); /* test master -- both messages should be written */ sw.setControllerRole(OFControllerRole.ROLE_MASTER); assertTrue(sw.write(fa)); assertTrue(sw.write(fsr)); assertEquals(Collections.<OFMessage>emptyList(), sw.write(msgList)); /* test slave -- flow-add (mod op) should fail each time; flow stats (read op) should pass */ sw.setControllerRole(OFControllerRole.ROLE_SLAVE); assertFalse(sw.write(fa)); /* flow-add should be stopped (mod op) */ assertTrue(sw.write(fsr)); /* stats request makes it (read op) */ assertEquals(Collections.<OFMessage>singletonList(fa), sw.write(msgList)); /* return bad flow-add */ }
/** Move the channel from scratch to SLAVE state * Builds on doMoveToWaitInitialRole() * adds testing for WAIT_INITAL_ROLE state * * We let the initial role request time out. The switch should be * disconnected */ @Test public void testInitialMoveToSlaveTimeout() throws Exception { int timeout = 50; switchHandler.useRoleChangerWithOtherTimeoutForTesting(timeout); // first, move us to WAIT_INITIAL_ROLE_STATE moveToWaitInitialRole(); assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class)); // Set the role setupSwitchSendRoleRequestAndVerify(null, OFControllerRole.ROLE_SLAVE); assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitInitialRoleState.class)); // prepare mocks and inject the role reply message reset(sw); sw.setAttribute(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, false); expectLastCall().once(); sw.setControllerRole(OFControllerRole.ROLE_SLAVE); expectLastCall().once(); sw.disconnect(); // Make sure we disconnect expectLastCall().once(); replay(sw); // Apparently this can be any type of message for this test?! OFMessage m = factory.buildBarrierReply().build(); Thread.sleep(timeout+5); switchHandler.processOFMessage(m); }
/** * Start as SLAVE then set role to MASTER * Tests normal role change transition. Check that connected channels * receive a setRole request */ @Test public void testSetRole() throws Exception { doSetUp(HARole.STANDBY); RoleInfo info = controller.getRoleInfo(); assertEquals(HARole.STANDBY, info.getRole()); assertEquals(HARole.STANDBY, controller.getRole()); OFSwitchHandshakeHandler h = createMock(OFSwitchHandshakeHandler.class); // Reassert the role. reset(h); h.sendRoleRequestIfNotPending(OFControllerRole.ROLE_SLAVE); replay(h); controller.reassertRole(h, HARole.STANDBY); verify(h); // reassert a different role: no-op reset(h); replay(h); controller.reassertRole(h, HARole.ACTIVE); verify(h); IHAListener listener = createMock(IHAListener.class); expect(listener.getName()).andReturn("foo").anyTimes(); setupListenerOrdering(listener); listener.transitionToActive(); expectLastCall().once(); replay(listener); controller.addHAListener(listener); controller.setRole(HARole.ACTIVE, "FooBar"); controller.processUpdateQueueForTesting(); verify(listener); info = controller.getRoleInfo(); assertEquals(HARole.ACTIVE, info.getRole()); assertEquals("FooBar", info.getRoleChangeDescription()); assertEquals(HARole.ACTIVE, controller.getRole()); }
/** write a request which triggers an OFErrorMsg response */ @Test(timeout = 5000) public void testWriteRequestOFErrorMsg() throws InterruptedException, ExecutionException { Capture<List<OFMessage>> cMsgList = prepareChannelForWriteList(); OFRoleRequest roleRequest = factory.buildRoleRequest().setRole(OFControllerRole.ROLE_MASTER).build(); ListenableFuture<OFRoleReply> future = conn.writeRequest(roleRequest); assertThat("Connection should have 1 pending request", conn.getPendingRequestIds().size(), equalTo(1)); eventLoop.runTasks(); assertThat("Should have captured MsgList", cMsgList.getValue(), Matchers.<OFMessage> contains(roleRequest)); assertThat("Future should not be complete yet", future.isDone(), equalTo(false)); OFRoleRequestFailedErrorMsg roleError = factory.errorMsgs().buildRoleRequestFailedErrorMsg() .setXid(roleRequest.getXid()) .setCode(OFRoleRequestFailedCode.STALE) .build(); assertThat("Connection should have accepted the response", conn.deliverResponse(roleError), equalTo(true)); OFErrorMsgException e = FutureTestUtils.assertFutureFailedWithException(future, OFErrorMsgException.class); assertThat(e.getErrorMessage(), CoreMatchers.<OFErrorMsg>equalTo(roleError)); }
@Test public void testSetHARoleReply() { sw.setControllerRole(OFControllerRole.ROLE_MASTER); assertEquals(OFControllerRole.ROLE_MASTER, sw.getControllerRole()); sw.setControllerRole(OFControllerRole.ROLE_EQUAL); assertEquals(OFControllerRole.ROLE_EQUAL, sw.getControllerRole()); sw.setControllerRole(OFControllerRole.ROLE_SLAVE); assertEquals(OFControllerRole.ROLE_SLAVE, sw.getControllerRole()); }
/** * Helper to load controller connection messages into a switch for testing. * @param sw the switch to insert the message on * @param role the role for the controller connection message * @param state the state for the controller connection message * @param uri the URI for the controller connection message */ public void updateControllerConnections(IOFSwitchBackend sw, OFControllerRole role1, OFBsnControllerConnectionState state1, String uri1 , OFControllerRole role2, OFBsnControllerConnectionState state2, String uri2) { OFBsnControllerConnection connection1 = factory.buildBsnControllerConnection() .setAuxiliaryId(OFAuxId.MAIN) .setRole(role1) .setState(state1) .setUri(uri1) .build(); OFBsnControllerConnection connection2 = factory.buildBsnControllerConnection() .setAuxiliaryId(OFAuxId.MAIN) .setRole(role2) .setState(state2) .setUri(uri2) .build(); List<OFBsnControllerConnection> connections = new ArrayList<OFBsnControllerConnection>(); connections.add(connection1); connections.add(connection2); OFBsnControllerConnectionsReply reply = factory.buildBsnControllerConnectionsReply() .setConnections(connections) .build(); sw.updateControllerConnections(reply); }