package net.floodlightcontroller.core.internal;
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import java.util.EnumSet;
import java.util.List;
import org.hamcrest.CoreMatchers;
import org.hamcrest.Matchers;
import org.junit.Test;
import net.floodlightcontroller.core.IOFSwitchBackend;
import net.floodlightcontroller.core.SwitchDescription;
import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.WaitAppHandshakeState;
import net.floodlightcontroller.core.internal.OFSwitchHandshakeHandler.WaitTableFeaturesReplyState;
import org.projectfloodlight.openflow.protocol.OFCapabilities;
import org.projectfloodlight.openflow.protocol.OFControllerRole;
import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
import org.projectfloodlight.openflow.protocol.OFPortDescStatsRequest;
import org.projectfloodlight.openflow.protocol.OFRoleReply;
import org.projectfloodlight.openflow.protocol.OFRoleRequest;
import org.projectfloodlight.openflow.protocol.OFTableFeaturesStatsReply;
import org.projectfloodlight.openflow.protocol.OFTableFeaturesStatsRequest;
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.types.DatapathId;
import org.projectfloodlight.openflow.types.OFAuxId;
import org.projectfloodlight.openflow.types.OFPort;
import com.google.common.collect.ImmutableList;
public class OFSwitchHandshakeHandlerVer13Test extends OFSwitchHandlerTestBase {
@Override
public OFFactory getFactory() {
return OFFactories.getFactory(OFVersion.OF_13);
}
@Override
OFFeaturesReply getFeaturesReply() {
return factory.buildFeaturesReply()
.setDatapathId(dpid)
.setNBuffers(1)
.setNTables((short)1)
.setCapabilities(EnumSet.<OFCapabilities>of(OFCapabilities.FLOW_STATS, OFCapabilities.TABLE_STATS))
.setAuxiliaryId(OFAuxId.MAIN)
.build();
}
OFPortDescStatsReply getPortDescStatsReply() {
OFPortDesc portDesc = factory.buildPortDesc()
.setName("Eth1")
.setPortNo(OFPort.of(1))
.build();
return factory.buildPortDescStatsReply()
.setEntries(ImmutableList.<OFPortDesc>of(portDesc))
.build();
}
/** Move the channel from scratch to WAIT_CONFIG_REPLY state
* Builds on moveToWaitFeaturesReply
* adds testing for WAIT_FEATURES_REPLY state
*/
@Test
public void moveToWaitPortDescStatsReply() throws Exception {
testInitState();
switchHandler.beginHandshake();
OFMessage msg = connection.retrieveMessage();
assertThat(msg, CoreMatchers.instanceOf(OFPortDescStatsRequest.class));
verifyUniqueXids(msg);
assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitPortDescStatsReplyState.class));
}
@Override
void moveToPreConfigReply() throws Exception {
moveToWaitPortDescStatsReply();
switchHandler.processOFMessage(getPortDescStatsReply());
}
public void handleDescStatsAndCreateSwitch() throws Exception {
// build the stats reply
OFDescStatsReply sr = createDescriptionStatsReply();
reset(sw);
SwitchDescription switchDescription = new SwitchDescription(sr);
setupSwitchForInstantiationWithReset();
sw.setPortDescStats(anyObject(OFPortDescStatsReply.class));
expectLastCall().once();
expect(sw.getOFFactory()).andReturn(factory).anyTimes();
replay(sw);
reset(switchManager);
expect(switchManager.getHandshakePlugins()).andReturn(plugins).anyTimes();
expect(
switchManager.getOFSwitchInstance(anyObject(OFConnection.class),
eq(switchDescription),
anyObject(OFFactory.class),
anyObject(DatapathId.class))).andReturn(sw).once();
expect(switchManager.getNumRequiredConnections()).andReturn(1).anyTimes();
switchManager.switchAdded(sw);
expectLastCall().once();
replay(switchManager);
// send the description stats reply
switchHandler.processOFMessage(sr);
OFMessage msg = connection.retrieveMessage();
assertThat(msg, CoreMatchers.instanceOf(OFTableFeaturesStatsRequest.class));
verifyUniqueXids(msg);
verify(sw, switchManager);
}
@SuppressWarnings("unchecked")
public void handleTableFeatures(boolean subHandShakeComplete) throws Exception {
// build the table features stats reply
OFTableFeaturesStatsReply tf = createTableFeaturesStatsReply();
reset(sw);
sw.startDriverHandshake();
expectLastCall().once();
expect(sw.isDriverHandshakeComplete()).andReturn(subHandShakeComplete).once();
sw.processOFTableFeatures(anyObject(List.class));
expectLastCall().once();
expect(sw.getOFFactory()).andReturn(factory).anyTimes();
replay(sw);
switchHandler.processOFMessage(tf);
}
@Test
public void moveToWaitTableFeaturesReplyState() throws Exception {
moveToWaitDescriptionStatReply();
handleDescStatsAndCreateSwitch();
assertThat(switchHandler.getStateForTesting(),
CoreMatchers.instanceOf(WaitTableFeaturesReplyState.class));
}
@Test
@Override
public void moveToWaitAppHandshakeState() throws Exception {
moveToWaitTableFeaturesReplyState();
handleTableFeatures(true);
assertThat(switchHandler.getStateForTesting(),
CoreMatchers.instanceOf(WaitAppHandshakeState.class));
}
@Override
Class<?> getRoleRequestClass() {
return OFRoleRequest.class;
}
@Override
public void verifyRoleRequest(OFMessage m, OFControllerRole expectedRole) {
assertThat(m, CoreMatchers.instanceOf(OFRoleRequest.class));
OFRoleRequest roleRequest = (OFRoleRequest) m;
assertThat(roleRequest.getRole(), equalTo(expectedRole));
}
@Override
protected OFMessage getRoleReply(long xid, OFControllerRole role) {
OFRoleReply roleReply = factory.buildRoleReply()
.setXid(xid)
.setRole(role)
.build();
return roleReply;
}
@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 moveToWaitSwitchDriverSubHandshake() throws Exception {
moveToWaitTableFeaturesReplyState();
handleTableFeatures(false); //TODO
assertThat(switchHandler.getStateForTesting(), CoreMatchers.instanceOf(OFSwitchHandshakeHandler.WaitSwitchDriverSubHandshakeState.class));
assertThat("Unexpected message captured", connection.getMessages(), Matchers.empty());
verify(sw);
}
}