/**
* Copyright 2013, Big Switch Networks, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
**/
package net.floodlightcontroller.core.internal;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import net.floodlightcontroller.core.FloodlightContext;
import net.floodlightcontroller.core.IFloodlightProviderService;
import net.floodlightcontroller.core.IOFSwitch;
import net.floodlightcontroller.core.SwitchDriverSubHandshakeAlreadyStarted;
import net.floodlightcontroller.core.SwitchDriverSubHandshakeCompleted;
import net.floodlightcontroller.core.SwitchDriverSubHandshakeNotStarted;
import net.floodlightcontroller.core.IOFSwitch.PortChangeEvent;
import net.floodlightcontroller.core.IOFSwitch.PortChangeType;
import net.floodlightcontroller.core.ImmutablePort;
import net.floodlightcontroller.core.OFSwitchBase;
import net.floodlightcontroller.debugcounter.DebugCounter;
import net.floodlightcontroller.debugcounter.IDebugCounterService;
import net.floodlightcontroller.packet.ARP;
import net.floodlightcontroller.packet.Ethernet;
import net.floodlightcontroller.packet.IPacket;
import net.floodlightcontroller.packet.IPv4;
import org.junit.Before;
import org.junit.Test;
import org.openflow.protocol.OFFlowMod;
import org.openflow.protocol.OFMatch;
import org.openflow.protocol.OFMessage;
import org.openflow.protocol.OFPacketIn;
import org.openflow.protocol.OFPortStatus;
import org.openflow.protocol.OFType;
import org.openflow.protocol.OFPacketIn.OFPacketInReason;
import org.openflow.protocol.OFPhysicalPort.OFPortConfig;
import org.openflow.protocol.OFPhysicalPort.OFPortFeatures;
import org.openflow.protocol.OFPortStatus.OFPortReason;
import org.openflow.protocol.factory.BasicFactory;
import org.openflow.protocol.statistics.OFDescriptionStatistics;
import org.openflow.util.HexString;
public class OFSwitchBaseTest {
private static final String srcMac = "00:44:33:22:11:00";
IFloodlightProviderService floodlightProvider;
Map<Long, IOFSwitch> switches;
private OFMessage blockMessage;
private OFPacketIn pi;
private IPacket testPacket;
private byte[] testPacketSerialized;
private class OFSwitchTest extends OFSwitchBase {
public OFSwitchTest(IFloodlightProviderService fp) {
super();
stringId = "whatever";
datapathId = 1L;
floodlightProvider = fp;
}
@Override
public void setSwitchProperties(OFDescriptionStatistics description) {
// TODO Auto-generated method stub
}
@Override
public OFPortType getPortType(short port_num) {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean isFastPort(short port_num) {
// TODO Auto-generated method stub
return false;
}
@Override
public void write(OFMessage msg, FloodlightContext cntx) {
blockMessage = msg;
}
public void setThresholds(int high, int low, int host, int port) {
sw.setInputThrottleThresholds(high, low, host, port);
}
public boolean inputThrottleEnabled() {
return packetInThrottleEnabled;
}
@Override
public String toString() {
return "OFSwitchTest";
}
}
private OFSwitchTest sw;
private ImmutablePort p1a;
private ImmutablePort p1b;
private ImmutablePort p2a;
private ImmutablePort p2b;
private ImmutablePort p3;
private final ImmutablePort portFoo1 = ImmutablePort.create("foo", (short)11);
private final ImmutablePort portFoo2 = ImmutablePort.create("foo", (short)12);
private final ImmutablePort portBar1 = ImmutablePort.create("bar", (short)11);
private final ImmutablePort portBar2 = ImmutablePort.create("bar", (short)12);
private final PortChangeEvent portFoo1Add =
new PortChangeEvent(portFoo1, PortChangeType.ADD);
private final PortChangeEvent portFoo2Add =
new PortChangeEvent(portFoo2, PortChangeType.ADD);
private final PortChangeEvent portBar1Add =
new PortChangeEvent(portBar1, PortChangeType.ADD);
private final PortChangeEvent portBar2Add =
new PortChangeEvent(portBar2, PortChangeType.ADD);
private final PortChangeEvent portFoo1Del =
new PortChangeEvent(portFoo1, PortChangeType.DELETE);
private final PortChangeEvent portFoo2Del =
new PortChangeEvent(portFoo2, PortChangeType.DELETE);
private final PortChangeEvent portBar1Del =
new PortChangeEvent(portBar1, PortChangeType.DELETE);
private final PortChangeEvent portBar2Del =
new PortChangeEvent(portBar2, PortChangeType.DELETE);
@Before
public void setUp() throws Exception {
blockMessage = null;
// Build our test packet
testPacket = new Ethernet()
.setSourceMACAddress(srcMac)
.setDestinationMACAddress("00:11:22:33:44:55")
.setEtherType(Ethernet.TYPE_ARP)
.setPayload(
new ARP()
.setHardwareType(ARP.HW_TYPE_ETHERNET)
.setProtocolType(ARP.PROTO_TYPE_IP)
.setHardwareAddressLength((byte) 6)
.setProtocolAddressLength((byte) 4)
.setOpCode(ARP.OP_REPLY)
.setSenderHardwareAddress(Ethernet.toMACAddress("00:44:33:22:11:00"))
.setSenderProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.1"))
.setTargetHardwareAddress(Ethernet.toMACAddress("00:11:22:33:44:55"))
.setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2")));
testPacketSerialized = testPacket.serialize();
pi = ((OFPacketIn) BasicFactory.getInstance().getMessage(OFType.PACKET_IN))
.setBufferId(-1)
.setInPort((short) 1)
.setPacketData(testPacketSerialized)
.setReason(OFPacketInReason.NO_MATCH)
.setTotalLength((short) testPacketSerialized.length);
floodlightProvider = createMock(IFloodlightProviderService.class);
sw = new OFSwitchTest(floodlightProvider);
IDebugCounterService debugCounter = new DebugCounter();
sw.setDebugCounterService(debugCounter);
switches = new ConcurrentHashMap<Long, IOFSwitch>();
switches.put(sw.getId(), sw);
expect(floodlightProvider.getSwitch(sw.getId())).andReturn(sw).anyTimes();
expect(floodlightProvider.getOFMessageFactory())
.andReturn(BasicFactory.getInstance()).anyTimes();
}
@Before
public void setUpPorts() {
ImmutablePort.Builder bld = new ImmutablePort.Builder();
// p1a is disabled
p1a = bld.setName("port1")
.setPortNumber((short)1)
.setPortStateLinkDown(true)
.build();
assertFalse("Sanity check portEnabled", p1a.isEnabled());
// p1b is enabled
// p1b has different feature from p1a
p1b = bld.addCurrentFeature(OFPortFeatures.OFPPF_1GB_FD)
.setPortStateLinkDown(false)
.build();
assertTrue("Sanity check portEnabled", p1b.isEnabled());
// p2 is disabled
// p2 has mixed case
bld = new ImmutablePort.Builder();
p2a = bld.setName("Port2")
.setPortNumber((short)2)
.setPortStateLinkDown(false)
.addConfig(OFPortConfig.OFPPC_PORT_DOWN)
.build();
// p2b only differs in PortFeatures
p2b = bld.addCurrentFeature(OFPortFeatures.OFPPF_100MB_HD)
.build();
assertFalse("Sanity check portEnabled", p2a.isEnabled());
// p3 is enabled
// p3 has mixed case
bld = new ImmutablePort.Builder();
p3 = bld.setName("porT3")
.setPortNumber((short)3)
.setPortStateLinkDown(false)
.build();
assertTrue("Sanity check portEnabled", p3.isEnabled());
}
/**
* By default, high threshold is infinite
*/
@Test
public void testNoPacketInThrottle() {
replay(floodlightProvider);
/* disable input throttle */
sw.setThresholds(Integer.MAX_VALUE, 1, 0, 0);
for (int i = 0; i < 200; i++) {
assertFalse(sw.inputThrottled(pi));
}
assertTrue(blockMessage == null);
assertFalse(sw.inputThrottleEnabled());
}
/**
* The test sends packet in at infinite rate (< 1ms),
* so throttling should be enabled on 100th packet, when the first
* rate measurement is done.
*/
@Test
public void testPacketInStartThrottle() {
floodlightProvider.addSwitchEvent(anyLong(),
(String)anyObject(), anyBoolean());
replay(floodlightProvider);
int high = 500;
sw.setThresholds(high, 10, 50, 200);
// We measure time lapse every 1000 packets
for (int i = 0; i < 1000; i++) {
assertFalse(sw.inputThrottleEnabled());
assertFalse(sw.inputThrottled(pi));
}
assertTrue(sw.inputThrottleEnabled());
assertTrue(sw.inputThrottled(pi));
assertTrue(sw.inputThrottled(pi));
assertTrue(blockMessage == null);
}
/**
* With throttling enabled, raise the low water mark threshold,
* verify throttling stops.
* @throws InterruptedException
*/
@Test
public void testPacketInStopThrottle() throws InterruptedException {
floodlightProvider.addSwitchEvent(anyLong(),
(String)anyObject(), anyBoolean());
expectLastCall().times(2);
replay(floodlightProvider);
sw.setThresholds(100, 10, 50, 200);
// First, enable throttling
for (int i = 0; i < 1000; i++) {
assertFalse(sw.inputThrottleEnabled());
assertFalse(sw.inputThrottled(pi));
}
assertTrue(sw.inputThrottleEnabled());
sw.setThresholds(Integer.MAX_VALUE, 100000, 50, 200);
for (int i = 0; i < 999; i++) {
assertTrue(sw.inputThrottled(pi));
assertTrue(sw.inputThrottleEnabled());
}
// Sleep for 2 msec, next packet should disable throttling
Thread.sleep(2);
assertFalse(sw.inputThrottled(pi));
assertFalse(sw.inputThrottleEnabled());
}
/**
* With throttling enabled, if rate of unique flows from a host
* exceeds set threshold, a flow mod should be emitted to block host
*/
@Test
public void testPacketInBlockHost() {
floodlightProvider.addSwitchEvent(anyLong(),
(String)anyObject(), anyBoolean());
expectLastCall().times(2);
replay(floodlightProvider);
int high = 500;
int perMac = 50;
sw.setThresholds(high, 10, perMac, 200);
// First, enable throttling
for (int i = 0; i < 1000; i++) {
assertFalse(sw.inputThrottleEnabled());
assertFalse(sw.inputThrottled(pi));
}
assertTrue(sw.inputThrottleEnabled());
assertTrue(blockMessage == null);
// Build unique flows with the same source mac
for (int j = 0; j < perMac - 1; j++) {
testPacketSerialized[5]++;
pi.setPacketData(testPacketSerialized);
assertFalse(sw.inputThrottled(pi));
}
assertTrue(blockMessage == null);
testPacketSerialized[5]++;
pi.setPacketData(testPacketSerialized);
assertFalse(sw.inputThrottled(pi));
// Verify the message is a flowmod with a hard timeout and srcMac
assertTrue(blockMessage != null);
assertTrue(blockMessage instanceof OFFlowMod);
OFFlowMod fm = (OFFlowMod) blockMessage;
assertTrue(fm.getHardTimeout() == 5);
OFMatch match = fm.getMatch();
assertTrue((match.getWildcards() & OFMatch.OFPFW_DL_SRC) == 0);
assertTrue(Arrays.equals(match.getDataLayerSource(),
HexString.fromHexString(srcMac)));
// Verify non-unique OFMatches are throttled
assertTrue(sw.inputThrottled(pi));
}
/**
* With throttling enabled, if rate of unique flows from a port
* exceeds set threshold, a flow mod should be emitted to block port
*/
@Test
public void testPacketInBlockPort() {
floodlightProvider.addSwitchEvent(anyLong(),
(String)anyObject(), anyBoolean());
expectLastCall().times(2);
replay(floodlightProvider);
int high = 500;
int perPort = 200;
sw.setThresholds(high, 10, 50, perPort);
// First, enable throttling
for (int i = 0; i < 1000; i++) {
assertFalse(sw.inputThrottleEnabled());
assertFalse(sw.inputThrottled(pi));
}
assertTrue(sw.inputThrottleEnabled());
assertTrue(blockMessage == null);
// Build unique flows with different source mac
for (int j = 0; j < perPort - 1; j++) {
testPacketSerialized[11]++;
pi.setPacketData(testPacketSerialized);
assertFalse(sw.inputThrottled(pi));
}
assertTrue(blockMessage == null);
testPacketSerialized[11]++;
pi.setPacketData(testPacketSerialized);
assertFalse(sw.inputThrottled(pi));
// Verify the message is a flowmod with a hard timeout and per port
assertTrue(blockMessage != null);
assertTrue(blockMessage instanceof OFFlowMod);
OFFlowMod fm = (OFFlowMod) blockMessage;
assertTrue(fm.getHardTimeout() == 5);
OFMatch match = fm.getMatch();
assertTrue((match.getWildcards() & OFMatch.OFPFW_DL_SRC) != 0);
assertTrue((match.getWildcards() & OFMatch.OFPFW_IN_PORT) == 0);
assertTrue(match.getInputPort() == 1);
// Verify non-unique OFMatches are throttled
assertTrue(sw.inputThrottled(pi));
}
/**
* Test whether two collections contains the same elements, regardless
* of the order in which the elements appear in the collections
* @param expected
* @param actual
*/
private static <T> void assertCollectionEqualsNoOrder(Collection<T> expected,
Collection<T> actual) {
String msg = String.format("expected=%s, actual=%s",
expected, actual);
assertEquals(msg, expected.size(), actual.size());
for(T e: expected) {
if (!actual.contains(e)) {
msg = String.format("Expected element %s not found in " +
"actual. expected=%s, actual=%s",
e, expected, actual);
fail(msg);
}
}
}
/**
* Test "normal" setPorts() and comparePorts() methods. No name<->number
* conflicts or exception testing.
*/
@Test
public void testBasicSetPortOperations() {
Collection<ImmutablePort> oldPorts = Collections.emptyList();
Collection<ImmutablePort> oldEnabledPorts = Collections.emptyList();
Collection<Short> oldEnabledPortNumbers = Collections.emptyList();
List<ImmutablePort> ports = new ArrayList<ImmutablePort>();
Collection<PortChangeEvent> expectedChanges =
new ArrayList<IOFSwitch.PortChangeEvent>();
Collection<PortChangeEvent> actualChanges = sw.comparePorts(ports);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertEquals(0, sw.getPorts().size());
assertEquals(0, sw.getEnabledPorts().size());
assertEquals(0, sw.getEnabledPortNumbers().size());
actualChanges = sw.setPorts(ports);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertEquals(0, sw.getPorts().size());
assertEquals(0, sw.getEnabledPorts().size());
assertEquals(0, sw.getEnabledPortNumbers().size());
//---------------------------------------------
// Add port p1a and p2a
ports.add(p1a);
ports.add(p2a);
PortChangeEvent evP1aAdded =
new PortChangeEvent(p1a, PortChangeType.ADD);
PortChangeEvent evP2aAdded =
new PortChangeEvent(p2a, PortChangeType.ADD);
expectedChanges.clear();
expectedChanges.add(evP1aAdded);
expectedChanges.add(evP2aAdded);
actualChanges = sw.comparePorts(ports);
assertEquals(0, sw.getPorts().size());
assertEquals(0, sw.getEnabledPorts().size());
assertEquals(0, sw.getEnabledPortNumbers().size());
assertEquals(2, actualChanges.size());
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
actualChanges = sw.setPorts(ports);
assertEquals(2, actualChanges.size());
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
assertTrue("enabled ports should be empty",
sw.getEnabledPortNumbers().isEmpty());
assertTrue("enabled ports should be empty",
sw.getEnabledPorts().isEmpty());
assertEquals(p1a, sw.getPort((short)1));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2a, sw.getPort((short)2));
assertEquals(p2a, sw.getPort("port2"));
assertEquals(p2a, sw.getPort("PoRt2")); // case insensitive get
assertEquals(null, sw.getPort((short)3));
assertEquals(null, sw.getPort("port3"));
assertEquals(null, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// Set the same ports again. No changes
oldPorts = sw.getPorts();
oldEnabledPorts = sw.getEnabledPorts();
oldEnabledPortNumbers = sw.getEnabledPortNumbers();
expectedChanges.clear();
actualChanges = sw.comparePorts(ports);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertEquals(oldPorts, sw.getPorts());
assertEquals(oldEnabledPorts, sw.getEnabledPorts());
assertEquals(oldEnabledPortNumbers, sw.getEnabledPortNumbers());
actualChanges = sw.setPorts(ports);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertEquals(oldPorts, sw.getPorts());
assertEquals(oldEnabledPorts, sw.getEnabledPorts());
assertEquals(oldEnabledPortNumbers, sw.getEnabledPortNumbers());
assertCollectionEqualsNoOrder(ports, sw.getPorts());
assertTrue("enabled ports should be empty",
sw.getEnabledPortNumbers().isEmpty());
assertTrue("enabled ports should be empty",
sw.getEnabledPorts().isEmpty());
assertEquals(p1a, sw.getPort((short)1));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2a, sw.getPort((short)2));
assertEquals(p2a, sw.getPort("port2"));
assertEquals(p2a, sw.getPort("PoRt2")); // case insensitive get
assertEquals(null, sw.getPort((short)3));
assertEquals(null, sw.getPort("port3"));
assertEquals(null, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// Remove p1a, add p1b. Should receive a port up
oldPorts = sw.getPorts();
oldEnabledPorts = sw.getEnabledPorts();
oldEnabledPortNumbers = sw.getEnabledPortNumbers();
ports.clear();
ports.add(p2a);
ports.add(p1b);
// comparePorts
PortChangeEvent evP1bUp = new PortChangeEvent(p1b, PortChangeType.UP);
actualChanges = sw.comparePorts(ports);
assertEquals(oldPorts, sw.getPorts());
assertEquals(oldEnabledPorts, sw.getEnabledPorts());
assertEquals(oldEnabledPortNumbers, sw.getEnabledPortNumbers());
assertEquals(1, actualChanges.size());
assertTrue("No UP event for port1", actualChanges.contains(evP1bUp));
// setPorts
actualChanges = sw.setPorts(ports);
assertEquals(1, actualChanges.size());
assertTrue("No UP event for port1", actualChanges.contains(evP1bUp));
assertCollectionEqualsNoOrder(ports, sw.getPorts());
List<ImmutablePort> enabledPorts = new ArrayList<ImmutablePort>();
enabledPorts.add(p1b);
List<Short> enabledPortNumbers = new ArrayList<Short>();
enabledPortNumbers.add((short)1);
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1b, sw.getPort((short)1));
assertEquals(p1b, sw.getPort("port1"));
assertEquals(p1b, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2a, sw.getPort((short)2));
assertEquals(p2a, sw.getPort("port2"));
assertEquals(p2a, sw.getPort("PoRt2")); // case insensitive get
assertEquals(null, sw.getPort((short)3));
assertEquals(null, sw.getPort("port3"));
assertEquals(null, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// Remove p2a, add p2b. Should receive a port modify
oldPorts = sw.getPorts();
oldEnabledPorts = sw.getEnabledPorts();
oldEnabledPortNumbers = sw.getEnabledPortNumbers();
ports.clear();
ports.add(p2b);
ports.add(p1b);
PortChangeEvent evP2bModified =
new PortChangeEvent(p2b, PortChangeType.OTHER_UPDATE);
// comparePorts
actualChanges = sw.comparePorts(ports);
assertEquals(oldPorts, sw.getPorts());
assertEquals(oldEnabledPorts, sw.getEnabledPorts());
assertEquals(oldEnabledPortNumbers, sw.getEnabledPortNumbers());
assertEquals(1, actualChanges.size());
assertTrue("No OTHER_CHANGE event for port2",
actualChanges.contains(evP2bModified));
// setPorts
actualChanges = sw.setPorts(ports);
assertEquals(1, actualChanges.size());
assertTrue("No OTHER_CHANGE event for port2",
actualChanges.contains(evP2bModified));
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts = new ArrayList<ImmutablePort>();
enabledPorts.add(p1b);
enabledPortNumbers = new ArrayList<Short>();
enabledPortNumbers.add((short)1);
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1b, sw.getPort((short)1));
assertEquals(p1b, sw.getPort("port1"));
assertEquals(p1b, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2b, sw.getPort((short)2));
assertEquals(p2b, sw.getPort("port2"));
assertEquals(p2b, sw.getPort("PoRt2")); // case insensitive get
assertEquals(null, sw.getPort((short)3));
assertEquals(null, sw.getPort("port3"));
assertEquals(null, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// Remove p1b, add p1a. Should receive a port DOWN
// Remove p2b, add p2a. Should receive a port modify
// Add p3, should receive an add
oldPorts = sw.getPorts();
oldEnabledPorts = sw.getEnabledPorts();
oldEnabledPortNumbers = sw.getEnabledPortNumbers();
ports.clear();
ports.add(p2a);
ports.add(p1a);
ports.add(p3);
PortChangeEvent evP1aDown =
new PortChangeEvent(p1a, PortChangeType.DOWN);
PortChangeEvent evP2aModified =
new PortChangeEvent(p2a, PortChangeType.OTHER_UPDATE);
PortChangeEvent evP3Add =
new PortChangeEvent(p3, PortChangeType.ADD);
expectedChanges.clear();
expectedChanges.add(evP1aDown);
expectedChanges.add(evP2aModified);
expectedChanges.add(evP3Add);
// comparePorts
actualChanges = sw.comparePorts(ports);
assertEquals(oldPorts, sw.getPorts());
assertEquals(oldEnabledPorts, sw.getEnabledPorts());
assertEquals(oldEnabledPortNumbers, sw.getEnabledPortNumbers());
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
// setPorts
actualChanges = sw.setPorts(ports);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPorts.add(p3);
enabledPortNumbers.clear();
enabledPortNumbers.add((short)3);
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1a, sw.getPort((short)1));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2a, sw.getPort((short)2));
assertEquals(p2a, sw.getPort("port2"));
assertEquals(p2a, sw.getPort("PoRt2")); // case insensitive get
assertEquals(p3, sw.getPort((short)3));
assertEquals(p3, sw.getPort("port3"));
assertEquals(p3, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// Remove p1b Should receive a port DELETE
// Remove p2b Should receive a port DELETE
oldPorts = sw.getPorts();
oldEnabledPorts = sw.getEnabledPorts();
oldEnabledPortNumbers = sw.getEnabledPortNumbers();
ports.clear();
ports.add(p3);
PortChangeEvent evP1aDel =
new PortChangeEvent(p1a, PortChangeType.DELETE);
PortChangeEvent evP2aDel =
new PortChangeEvent(p2a, PortChangeType.DELETE);
expectedChanges.clear();
expectedChanges.add(evP1aDel);
expectedChanges.add(evP2aDel);
// comparePorts
actualChanges = sw.comparePorts(ports);
assertEquals(oldPorts, sw.getPorts());
assertEquals(oldEnabledPorts, sw.getEnabledPorts());
assertEquals(oldEnabledPortNumbers, sw.getEnabledPortNumbers());
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
// setPorts
actualChanges = sw.setPorts(ports);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPorts.add(p3);
enabledPortNumbers.clear();
enabledPortNumbers.add((short)3);
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p3, sw.getPort((short)3));
assertEquals(p3, sw.getPort("port3"));
assertEquals(p3, sw.getPort("PoRt3")); // case insensitive get
}
/**
* Test "normal" OFPortStatus handling. No name<->number
* conflicts or exception testing.
*/
@Test
public void testBasicPortStatusOperation() {
OFPortStatus ps = (OFPortStatus)
BasicFactory.getInstance().getMessage(OFType.PORT_STATUS);
List<ImmutablePort> ports = new ArrayList<ImmutablePort>();
ports.add(p1a);
ports.add(p2a);
// Set p1a and p2a as baseline
PortChangeEvent evP1aAdded =
new PortChangeEvent(p1a, PortChangeType.ADD);
PortChangeEvent evP2aAdded =
new PortChangeEvent(p2a, PortChangeType.ADD);
Collection<PortChangeEvent> expectedChanges =
new ArrayList<IOFSwitch.PortChangeEvent>();
expectedChanges.add(evP1aAdded);
expectedChanges.add(evP2aAdded);
Collection<PortChangeEvent> actualChanges = sw.comparePorts(ports);
assertEquals(0, sw.getPorts().size());
assertEquals(0, sw.getEnabledPorts().size());
assertEquals(0, sw.getEnabledPortNumbers().size());
assertEquals(2, actualChanges.size());
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
actualChanges = sw.setPorts(ports);
assertEquals(2, actualChanges.size());
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
assertTrue("enabled ports should be empty",
sw.getEnabledPortNumbers().isEmpty());
assertTrue("enabled ports should be empty",
sw.getEnabledPorts().isEmpty());
assertEquals(p1a, sw.getPort((short)1));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2a, sw.getPort((short)2));
assertEquals(p2a, sw.getPort("port2"));
assertEquals(p2a, sw.getPort("PoRt2")); // case insensitive get
//----------------------------------------------------
// P1a -> p1b. Should receive a port up
ports.clear();
ports.add(p2a);
ports.add(p1b);
ps.setReason(OFPortReason.OFPPR_MODIFY.getReasonCode());
ps.setDesc(p1b.toOFPhysicalPort());
PortChangeEvent evP1bUp = new PortChangeEvent(p1b, PortChangeType.UP);
actualChanges = sw.processOFPortStatus(ps);
expectedChanges.clear();
expectedChanges.add(evP1bUp);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
List<ImmutablePort> enabledPorts = new ArrayList<ImmutablePort>();
enabledPorts.add(p1b);
List<Short> enabledPortNumbers = new ArrayList<Short>();
enabledPortNumbers.add((short)1);
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1b, sw.getPort((short)1));
assertEquals(p1b, sw.getPort("port1"));
assertEquals(p1b, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2a, sw.getPort((short)2));
assertEquals(p2a, sw.getPort("port2"));
assertEquals(p2a, sw.getPort("PoRt2")); // case insensitive get
//----------------------------------------------------
// p2a -> p2b. Should receive a port modify
ports.clear();
ports.add(p2b);
ports.add(p1b);
PortChangeEvent evP2bModified =
new PortChangeEvent(p2b, PortChangeType.OTHER_UPDATE);
ps.setReason(OFPortReason.OFPPR_MODIFY.getReasonCode());
ps.setDesc(p2b.toOFPhysicalPort());
actualChanges = sw.processOFPortStatus(ps);
expectedChanges.clear();
expectedChanges.add(evP2bModified);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts = new ArrayList<ImmutablePort>();
enabledPorts.add(p1b);
enabledPortNumbers = new ArrayList<Short>();
enabledPortNumbers.add((short)1);
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1b, sw.getPort((short)1));
assertEquals(p1b, sw.getPort("port1"));
assertEquals(p1b, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2b, sw.getPort((short)2));
assertEquals(p2b, sw.getPort("port2"));
assertEquals(p2b, sw.getPort("PoRt2")); // case insensitive get
assertEquals(null, sw.getPort((short)3));
assertEquals(null, sw.getPort("port3"));
assertEquals(null, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// p1b -> p1a. Via an OFPPR_ADD, Should receive a port DOWN
ports.clear();
ports.add(p2b);
ports.add(p1a);
// we use an ADD here. We treat ADD and MODIFY the same way
ps.setReason(OFPortReason.OFPPR_ADD.getReasonCode());
ps.setDesc(p1a.toOFPhysicalPort());
PortChangeEvent evP1aDown =
new PortChangeEvent(p1a, PortChangeType.DOWN);
actualChanges = sw.processOFPortStatus(ps);
expectedChanges.clear();
expectedChanges.add(evP1aDown);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPortNumbers.clear();
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1a, sw.getPort((short)1));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2b, sw.getPort((short)2));
assertEquals(p2b, sw.getPort("port2"));
assertEquals(p2b, sw.getPort("PoRt2")); // case insensitive get
//----------------------------------------------------
// p2b -> p2a. Via an OFPPR_ADD, Should receive a port MODIFY
ports.clear();
ports.add(p2a);
ports.add(p1a);
// we use an ADD here. We treat ADD and MODIFY the same way
ps.setReason(OFPortReason.OFPPR_ADD.getReasonCode());
ps.setDesc(p2a.toOFPhysicalPort());
PortChangeEvent evP2aModify =
new PortChangeEvent(p2a, PortChangeType.OTHER_UPDATE);
actualChanges = sw.processOFPortStatus(ps);
expectedChanges.clear();
expectedChanges.add(evP2aModify);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPortNumbers.clear();
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1a, sw.getPort((short)1));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(p2a, sw.getPort((short)2));
assertEquals(p2a, sw.getPort("port2"));
assertEquals(p2a, sw.getPort("PoRt2")); // case insensitive get
//----------------------------------------------------
// Remove p2a
ports.clear();
ports.add(p1a);
ps.setReason(OFPortReason.OFPPR_DELETE.getReasonCode());
ps.setDesc(p2a.toOFPhysicalPort());
PortChangeEvent evP2aDel =
new PortChangeEvent(p2a, PortChangeType.DELETE);
actualChanges = sw.processOFPortStatus(ps);
expectedChanges.clear();
expectedChanges.add(evP2aDel);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPortNumbers.clear();
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1a, sw.getPort((short)1));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(null, sw.getPort((short)2));
assertEquals(null, sw.getPort("port2"));
assertEquals(null, sw.getPort("PoRt2")); // case insensitive get
//----------------------------------------------------
// Remove p2a again. Nothing should happen.
ports.clear();
ports.add(p1a);
ps.setReason(OFPortReason.OFPPR_DELETE.getReasonCode());
ps.setDesc(p2a.toOFPhysicalPort());
actualChanges = sw.processOFPortStatus(ps);
expectedChanges.clear();
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPortNumbers.clear();
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1a, sw.getPort((short)1));
assertEquals(p1a, sw.getPort("port1"));
assertEquals(p1a, sw.getPort("PoRt1")); // case insensitive get
assertEquals(null, sw.getPort((short)2));
assertEquals(null, sw.getPort("port2"));
assertEquals(null, sw.getPort("PoRt2")); // case insensitive get
//----------------------------------------------------
// Remove p1a
ports.clear();
ps.setReason(OFPortReason.OFPPR_DELETE.getReasonCode());
ps.setDesc(p1a.toOFPhysicalPort());
PortChangeEvent evP1aDel =
new PortChangeEvent(p1a, PortChangeType.DELETE);
actualChanges = sw.processOFPortStatus(ps);
expectedChanges.clear();
expectedChanges.add(evP1aDel);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPortNumbers.clear();
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(null, sw.getPort((short)1));
assertEquals(null, sw.getPort("port1"));
assertEquals(null, sw.getPort("PoRt1")); // case insensitive get
assertEquals(null, sw.getPort((short)2));
assertEquals(null, sw.getPort("port2"));
assertEquals(null, sw.getPort("PoRt2")); // case insensitive get
//----------------------------------------------------
// Add p3, should receive an add
ports.clear();
ports.add(p3);
PortChangeEvent evP3Add =
new PortChangeEvent(p3, PortChangeType.ADD);
expectedChanges.clear();
expectedChanges.add(evP3Add);
ps.setReason(OFPortReason.OFPPR_ADD.getReasonCode());
ps.setDesc(p3.toOFPhysicalPort());
actualChanges = sw.processOFPortStatus(ps);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPorts.add(p3);
enabledPortNumbers.clear();
enabledPortNumbers.add((short)3);
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(null, sw.getPort((short)1));
assertEquals(null, sw.getPort("port1"));
assertEquals(null, sw.getPort("PoRt1")); // case insensitive get
assertEquals(null, sw.getPort((short)2));
assertEquals(null, sw.getPort("port2"));
assertEquals(null, sw.getPort("PoRt2")); // case insensitive get
assertEquals(p3, sw.getPort((short)3));
assertEquals(p3, sw.getPort("port3"));
assertEquals(p3, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// Add p1b, back should receive an add
ports.clear();
ports.add(p1b);
ports.add(p3);
PortChangeEvent evP1bAdd =
new PortChangeEvent(p1b, PortChangeType.ADD);
expectedChanges.clear();
expectedChanges.add(evP1bAdd);
// use a modify to add the port
ps.setReason(OFPortReason.OFPPR_MODIFY.getReasonCode());
ps.setDesc(p1b.toOFPhysicalPort());
actualChanges = sw.processOFPortStatus(ps);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPorts.add(p3);
enabledPorts.add(p1b);
enabledPortNumbers.clear();
enabledPortNumbers.add((short)3);
enabledPortNumbers.add((short)1);
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1b, sw.getPort((short)1));
assertEquals(p1b, sw.getPort("port1"));
assertEquals(p1b, sw.getPort("PoRt1")); // case insensitive get
assertEquals(null, sw.getPort((short)2));
assertEquals(null, sw.getPort("port2"));
assertEquals(null, sw.getPort("PoRt2")); // case insensitive get
assertEquals(p3, sw.getPort((short)3));
assertEquals(p3, sw.getPort("port3"));
assertEquals(p3, sw.getPort("PoRt3")); // case insensitive get
//----------------------------------------------------
// Modify, but nothing really changed
ports.clear();
ports.add(p1b);
ports.add(p3);
expectedChanges.clear();
// use a modify to add the port
ps.setReason(OFPortReason.OFPPR_MODIFY.getReasonCode());
ps.setDesc(p1b.toOFPhysicalPort());
actualChanges = sw.processOFPortStatus(ps);
assertCollectionEqualsNoOrder(expectedChanges, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
enabledPorts.clear();
enabledPorts.add(p3);
enabledPorts.add(p1b);
enabledPortNumbers.clear();
enabledPortNumbers.add((short)3);
enabledPortNumbers.add((short)1);
assertCollectionEqualsNoOrder(enabledPorts, sw.getEnabledPorts());
assertCollectionEqualsNoOrder(enabledPortNumbers,
sw.getEnabledPortNumbers());
assertEquals(p1b, sw.getPort((short)1));
assertEquals(p1b, sw.getPort("port1"));
assertEquals(p1b, sw.getPort("PoRt1")); // case insensitive get
assertEquals(null, sw.getPort((short)2));
assertEquals(null, sw.getPort("port2"));
assertEquals(null, sw.getPort("PoRt2")); // case insensitive get
assertEquals(p3, sw.getPort((short)3));
assertEquals(p3, sw.getPort("port3"));
assertEquals(p3, sw.getPort("PoRt3")); // case insensitive get
}
/**
* Test exception handling for setPorts() and comparePorts()
*/
@Test
public void testSetPortExceptions() {
try {
sw.setPorts(null);
fail("Excpeted exception not thrown");
} catch (NullPointerException e) { };
// two ports with same name
List<ImmutablePort> ports = new ArrayList<ImmutablePort>();
ports.add(ImmutablePort.create("port1", (short)1));
ports.add(ImmutablePort.create("port1", (short)2));
try {
sw.setPorts(ports);
fail("Excpeted exception not thrown");
} catch (IllegalArgumentException e) { };
// two ports with same number
ports.clear();
ports.add(ImmutablePort.create("port1", (short)1));
ports.add(ImmutablePort.create("port2", (short)1));
try {
sw.setPorts(ports);
fail("Excpeted exception not thrown");
} catch (IllegalArgumentException e) { };
// null port in list
ports.clear();
ports.add(ImmutablePort.create("port1", (short)1));
ports.add(null);
try {
sw.setPorts(ports);
fail("Excpeted exception not thrown");
} catch (NullPointerException e) { };
// try getPort(null)
try {
sw.getPort(null);
fail("Excpeted exception not thrown");
} catch (NullPointerException e) { };
//--------------------------
// comparePorts()
try {
sw.comparePorts(null);
fail("Excpeted exception not thrown");
} catch (NullPointerException e) { };
// two ports with same name
ports = new ArrayList<ImmutablePort>();
ports.add(ImmutablePort.create("port1", (short)1));
ports.add(ImmutablePort.create("port1", (short)2));
try {
sw.comparePorts(ports);
fail("Excpeted exception not thrown");
} catch (IllegalArgumentException e) { };
// two ports with same number
ports.clear();
ports.add(ImmutablePort.create("port1", (short)1));
ports.add(ImmutablePort.create("port2", (short)1));
try {
sw.comparePorts(ports);
fail("Excpeted exception not thrown");
} catch (IllegalArgumentException e) { };
// null port in list
ports.clear();
ports.add(ImmutablePort.create("port1", (short)1));
ports.add(null);
try {
sw.comparePorts(ports);
fail("Excpeted exception not thrown");
} catch (NullPointerException e) { };
// try getPort(null)
try {
sw.getPort(null);
fail("Excpeted exception not thrown");
} catch (NullPointerException e) { };
}
@Test
public void testPortStatusExceptions() {
OFPortStatus ps = (OFPortStatus)
BasicFactory.getInstance().getMessage(OFType.PORT_STATUS);
try {
sw.processOFPortStatus(null);
fail("Expected exception not thrown");
} catch (NullPointerException e) { }
// illegal reason code
ps.setReason((byte)0x42);
ps.setDesc(ImmutablePort.create("p1", (short)1).toOFPhysicalPort());
try {
sw.processOFPortStatus(ps);
fail("Expected exception not thrown");
} catch (IllegalArgumentException e) { }
// null port
ps.setReason(OFPortReason.OFPPR_ADD.getReasonCode());
ps.setDesc(null);
try {
sw.processOFPortStatus(ps);
fail("Expected exception not thrown");
} catch (NullPointerException e) { }
}
/**
* Assert that the expected PortChangeEvents have been recevied, asserting
* the expected ordering.
*
* All events in earlyEvents have to appear in actualEvents before any
* event in lateEvent appears. Events in anytimeEvents can appear at any
* given time. earlyEvents, lateEvents, and anytimeEvents must be mutually
* exclusive (their intersection must be none) and their union must
* contain all elements from actualEvents
* @param earlyEvents
* @param lateEvents
* @param anytimeEvents
* @param actualEvents
*/
private static void assertChangeEvents(Collection<PortChangeEvent> earlyEvents,
Collection<PortChangeEvent> lateEvents,
Collection<PortChangeEvent> anytimeEvents,
Collection<PortChangeEvent> actualEvents) {
String inputDesc = String.format("earlyEvents=%s, lateEvents=%s, " +
"anytimeEvents=%s, actualEvents=%s",
earlyEvents, lateEvents, anytimeEvents, actualEvents);
// Make copies of expected lists, so we can modify them
Collection<PortChangeEvent> early =
new ArrayList<PortChangeEvent>(earlyEvents);
Collection<PortChangeEvent> late =
new ArrayList<PortChangeEvent>(lateEvents);
Collection<PortChangeEvent> any =
new ArrayList<PortChangeEvent>(anytimeEvents);
// Sanity check: no overlap between early, late, and anytime events
for (PortChangeEvent ev: early) {
assertFalse("Test setup error. Early and late overlap",
late.contains(ev));
assertFalse("Test setup error. Early and anytime overlap",
any.contains(ev));
}
for (PortChangeEvent ev: late) {
assertFalse("Test setup error. Late and early overlap",
early.contains(ev));
assertFalse("Test setup error. Late and any overlap",
any.contains(ev));
}
for (PortChangeEvent ev: any) {
assertFalse("Test setup error. Anytime and early overlap",
early.contains(ev));
assertFalse("Test setup error. Anytime and late overlap",
late.contains(ev));
}
for (PortChangeEvent a: actualEvents) {
if (early.remove(a)) {
continue;
}
if (any.remove(a)) {
continue;
}
if (late.remove(a)) {
if (!early.isEmpty()) {
fail(a + " is in late list, but haven't seen all required " +
"early events. " + inputDesc);
} else {
continue;
}
}
fail(a + " was not expected. " + inputDesc);
}
if (!early.isEmpty())
fail("Elements left in early: " + early + ". " + inputDesc);
if (!late.isEmpty())
fail("Elements left in late: " + late + ". " + inputDesc);
if (!any.isEmpty())
fail("Elements left in any: " + any + ". " + inputDesc);
}
/**
* Test setPort() with changing name / number mappings
* We don't test comparePorts() here. We assume setPorts() and
* comparePorts() use the same underlying implementation
*/
@Test
public void testSetPortNameNumberMappingChange() {
List<ImmutablePort> ports = new ArrayList<ImmutablePort>();
Collection<PortChangeEvent> early = new ArrayList<PortChangeEvent>();
Collection<PortChangeEvent> late = new ArrayList<PortChangeEvent>();
Collection<PortChangeEvent> anytime = new ArrayList<PortChangeEvent>();
Collection<PortChangeEvent> actualChanges = null;
ports.add(portFoo1);
ports.add(p1a);
sw.setPorts(ports);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Add portFoo2: name collision
ports.clear();
ports.add(portFoo2);
ports.add(p1a);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.setPorts(ports);
early.add(portFoo1Del);
late.add(portFoo2Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Add portBar2: number collision
ports.clear();
ports.add(portBar2);
ports.add(p1a);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.setPorts(ports);
early.add(portFoo2Del);
late.add(portBar2Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Set to portFoo1, portBar2. No collisions in this step
ports.clear();
ports.add(portFoo1);
ports.add(portBar2);
ports.add(p1a);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.setPorts(ports);
anytime.add(portFoo1Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Add portFoo2: name and number collision
ports.clear();
ports.add(portFoo2);
ports.add(p1a);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.setPorts(ports);
early.add(portFoo1Del);
early.add(portBar2Del);
late.add(portFoo2Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Set to portFoo2, portBar1. No collisions in this step
ports.clear();
ports.add(portFoo2);
ports.add(portBar1);
ports.add(p1a);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.setPorts(ports);
anytime.add(portBar1Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Add portFoo1, portBar2 name and number collision
// Also change p1a -> p1b: expect modify for it
// Also add p3: expect add for it
PortChangeEvent p1bUp = new PortChangeEvent(p1b, PortChangeType.UP);
PortChangeEvent p3Add = new PortChangeEvent(p3, PortChangeType.ADD);
ports.clear();
ports.add(portFoo1);
ports.add(portBar2);
ports.add(p1b);
ports.add(p3);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.setPorts(ports);
early.add(portFoo2Del);
early.add(portBar1Del);
late.add(portFoo1Add);
late.add(portBar2Add);
anytime.add(p1bUp);
anytime.add(p3Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
}
@Test
public void testPortStatusNameNumberMappingChange() {
List<ImmutablePort> ports = new ArrayList<ImmutablePort>();
Collection<PortChangeEvent> early = new ArrayList<PortChangeEvent>();
Collection<PortChangeEvent> late = new ArrayList<PortChangeEvent>();
Collection<PortChangeEvent> anytime = new ArrayList<PortChangeEvent>();
Collection<PortChangeEvent> actualChanges = null;
// init: add portFoo1, p1a
ports.add(portFoo1);
ports.add(p1a);
sw.setPorts(ports);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
OFPortStatus ps = (OFPortStatus)
BasicFactory.getInstance().getMessage(OFType.PORT_STATUS);
// portFoo1 -> portFoo2 via MODIFY : name collision
ps.setReason(OFPortReason.OFPPR_MODIFY.getReasonCode());
ps.setDesc(portFoo2.toOFPhysicalPort());
ports.clear();
ports.add(portFoo2);
ports.add(p1a);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.processOFPortStatus(ps);
early.add(portFoo1Del);
late.add(portFoo2Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// portFoo2 -> portBar2 via ADD number collision
ps.setReason(OFPortReason.OFPPR_ADD.getReasonCode());
ps.setDesc(portBar2.toOFPhysicalPort());
ports.clear();
ports.add(portBar2);
ports.add(p1a);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.processOFPortStatus(ps);
early.add(portFoo2Del);
late.add(portBar2Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Set to portFoo1, portBar2
ports.clear();
ports.add(portFoo1);
ports.add(portBar2);
sw.setPorts(ports);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// portFoo1 + portBar2 -> portFoo2: name and number collision
ps.setReason(OFPortReason.OFPPR_MODIFY.getReasonCode());
ps.setDesc(portFoo2.toOFPhysicalPort());
ports.clear();
ports.add(portFoo2);
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.processOFPortStatus(ps);
early.add(portFoo1Del);
early.add(portBar2Del);
late.add(portFoo2Add);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
//----------------------
// Test DELETEs
// del portFoo1: name exists (portFoo2), but number doesn't.
ps.setReason(OFPortReason.OFPPR_DELETE.getReasonCode());
ps.setDesc(portFoo1.toOFPhysicalPort());
ports.clear();
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.processOFPortStatus(ps);
anytime.add(portFoo2Del);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Set to portFoo1
ports.clear();
ports.add(portFoo1);
sw.setPorts(ports);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// del portBar1: number exists (portFoo1), but name doesn't.
ps.setReason(OFPortReason.OFPPR_DELETE.getReasonCode());
ps.setDesc(portBar1.toOFPhysicalPort());
ports.clear();
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.processOFPortStatus(ps);
anytime.add(portFoo1Del);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// Set to portFoo1, portBar2
ports.clear();
ports.add(portFoo1);
ports.add(portBar2);
sw.setPorts(ports);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
// del portFoo2: name and number exists
ps.setReason(OFPortReason.OFPPR_DELETE.getReasonCode());
ps.setDesc(portFoo2.toOFPhysicalPort());
ports.clear();
early.clear();
late.clear();
anytime.clear();
actualChanges = sw.processOFPortStatus(ps);
anytime.add(portFoo1Del);
anytime.add(portBar2Del);
assertChangeEvents(early, late, anytime, actualChanges);
assertCollectionEqualsNoOrder(ports, sw.getPorts());
}
@Test
public void testSubHandshake() {
OFMessage m = BasicFactory.getInstance().getMessage(OFType.VENDOR);
// test execptions before handshake is started
try {
sw.processDriverHandshakeMessage(m);
fail("expected exception not thrown");
} catch (SwitchDriverSubHandshakeNotStarted e) { /* expected */ }
try {
sw.isDriverHandshakeComplete();
fail("expected exception not thrown");
} catch (SwitchDriverSubHandshakeNotStarted e) { /* expected */ }
// start the handshake -- it should immediately complete
sw.startDriverHandshake();
assertTrue("Handshake should be complete",
sw.isDriverHandshakeComplete());
// test exceptions after handshake is completed
try {
sw.processDriverHandshakeMessage(m);
fail("expected exception not thrown");
} catch (SwitchDriverSubHandshakeCompleted e) { /* expected */ }
try {
sw.startDriverHandshake();
fail("Expected exception not thrown");
} catch (SwitchDriverSubHandshakeAlreadyStarted e) { /* expected */ }
}
}