diff --git a/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java b/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java index 578a15e60d15cc41294155e052082b107b9562b2..8578fc07aa92cda233d1b9bce486f939ba8dc383 100644 --- a/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java +++ b/src/main/java/net/floodlightcontroller/flowcache/FlowReconcileManager.java @@ -46,8 +46,6 @@ import org.projectfloodlight.openflow.protocol.OFType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.sun.j3d.utils.scenegraph.io.retained.Controller; - public class FlowReconcileManager implements IFloodlightModule, IFlowReconcileService { /** The logger. */ private static Logger logger = LoggerFactory.getLogger(FlowReconcileManager.class); diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java index 97d71ba236e28526a06b2ed4cf9b6453a86431e6..07b9fd9e019d03d30b8149f2d3fd902aa847e4a3 100644 --- a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java +++ b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntries.java @@ -193,7 +193,6 @@ public class StaticFlowEntries { Match match = fm.getMatch(); // it's a shame we can't use the MatchUtils for this. It's kind of the same thing but storing in a different place. - boolean setTOS = false; Iterator<MatchField<?>> itr = match.getMatchFields().iterator(); // only get exact or masked fields (not fully wildcarded) while(itr.hasNext()) { @SuppressWarnings("rawtypes") // this is okay here @@ -217,25 +216,11 @@ public class StaticFlowEntries { case ETH_TYPE: entry.put(StaticFlowEntryPusher.COLUMN_DL_TYPE, match.get(MatchField.ETH_TYPE).getValue()); break; - case IP_ECN: // TOS = [DSCP bits 0-5] + [ECN bits 6-7] --> bitwise OR to get TOS byte - if (setTOS) { //TODO @Ryan need to break TOS into ECN and DSCP columns - entry.put(StaticFlowEntryPusher.COLUMN_NW_TOS, - Byte.toString((byte) (match.get(MatchField.IP_ECN).getEcnValue() - | (Byte.parseByte(entry.get(StaticFlowEntryPusher.COLUMN_NW_TOS).toString()))))); - } else { - entry.put(StaticFlowEntryPusher.COLUMN_NW_TOS, Byte.toString((byte) (match.get(MatchField.IP_ECN).getEcnValue()))); - } - setTOS = true; - break; - case IP_DSCP: - if (setTOS) { - entry.put(StaticFlowEntryPusher.COLUMN_NW_TOS, - Byte.toString((byte) (match.get(MatchField.IP_DSCP).getDscpValue() - | (Byte.parseByte(entry.get(StaticFlowEntryPusher.COLUMN_NW_TOS).toString()))))); - } else { - entry.put(StaticFlowEntryPusher.COLUMN_NW_TOS, Byte.toString((byte) (match.get(MatchField.IP_ECN).getEcnValue()))); - } - setTOS = true; + case IP_ECN: // TOS = [DSCP bits 0-5] + [ECN bits 6-7] --> bitwise OR to get TOS byte (have separate columns now though) + entry.put(StaticFlowEntryPusher.COLUMN_NW_ECN, Byte.toString(match.get(MatchField.IP_ECN).getEcnValue())); + break; + case IP_DSCP: // Even for OF1.0, loxi will break ECN and DSCP up from the API's POV. This method is only invoked by a SFP service push from another module + entry.put(StaticFlowEntryPusher.COLUMN_NW_DSCP, Byte.toString((byte) (match.get(MatchField.IP_DSCP).getDscpValue()))); break; case IP_PROTO: entry.put(StaticFlowEntryPusher.COLUMN_NW_PROTO, Short.toString(match.get(MatchField.IP_PROTO).getIpProtocolNumber())); @@ -402,9 +387,15 @@ public class StaticFlowEntries { case StaticFlowEntryPusher.COLUMN_DL_TYPE: entry.put(StaticFlowEntryPusher.COLUMN_DL_TYPE, jp.getText()); break; - case StaticFlowEntryPusher.COLUMN_NW_TOS: + case StaticFlowEntryPusher.COLUMN_NW_TOS: // only valid for OF1.0; all other should specify specifics (ECN and/or DSCP bits) entry.put(StaticFlowEntryPusher.COLUMN_NW_TOS, jp.getText()); break; + case StaticFlowEntryPusher.COLUMN_NW_ECN: + entry.put(StaticFlowEntryPusher.COLUMN_NW_ECN, jp.getText()); + break; + case StaticFlowEntryPusher.COLUMN_NW_DSCP: + entry.put(StaticFlowEntryPusher.COLUMN_NW_DSCP, jp.getText()); + break; case StaticFlowEntryPusher.COLUMN_NW_PROTO: entry.put(StaticFlowEntryPusher.COLUMN_NW_PROTO, jp.getText()); ipProto = jp.getText(); diff --git a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java index 00540929f2e1ac22746af481001a9ec864631d78..7154396b37dbd56b3ac4c10769ae0793302c8543 100644 --- a/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java +++ b/src/main/java/net/floodlightcontroller/staticflowentry/StaticFlowEntryPusher.java @@ -107,6 +107,8 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService, public static final String COLUMN_DL_TYPE = MatchUtils.STR_DL_TYPE; public static final String COLUMN_NW_TOS = MatchUtils.STR_NW_TOS; + public static final String COLUMN_NW_ECN = MatchUtils.STR_NW_ECN; + public static final String COLUMN_NW_DSCP = MatchUtils.STR_NW_DSCP; public static final String COLUMN_NW_PROTO = MatchUtils.STR_NW_PROTO; public static final String COLUMN_NW_SRC = MatchUtils.STR_NW_SRC; // includes CIDR-style netmask, e.g. "128.8.128.0/24" public static final String COLUMN_NW_DST = MatchUtils.STR_NW_DST; @@ -340,7 +342,7 @@ implements IOFSwitchListener, IFloodlightModule, IStaticFlowEntryPusherService, } // get the correct builder for the OF version supported by the switch - // TODO @Ryan this should arguably be a FlowAdd, not a FlowModify + // TODO @Ryan this should arguably be a FlowAdd, not a FlowModify, but it really doesn't matter fmb = OFFactories.getFactory(switchService.getSwitch(DatapathId.of(switchName)).getOFFactory().getVersion()).buildFlowModify(); StaticFlowEntries.initDefaultFlowMod(fmb, entryName); diff --git a/src/main/java/net/floodlightcontroller/storage/AbstractStorageSource.java b/src/main/java/net/floodlightcontroller/storage/AbstractStorageSource.java index 911c1a12dcc31d06bced558ffbcc87b694eb6474..22c7656f93cf57f4f993d9dd52d30de1b35d62fc 100644 --- a/src/main/java/net/floodlightcontroller/storage/AbstractStorageSource.java +++ b/src/main/java/net/floodlightcontroller/storage/AbstractStorageSource.java @@ -36,7 +36,6 @@ import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.module.FloodlightModuleException; import net.floodlightcontroller.core.module.IFloodlightModule; import net.floodlightcontroller.core.module.IFloodlightService; -import net.floodlightcontroller.debugcounter.IDebugCounter; import net.floodlightcontroller.debugcounter.IDebugCounterService; import net.floodlightcontroller.restserver.IRestApiService; import net.floodlightcontroller.storage.web.StorageWebRoutable; diff --git a/src/main/java/net/floodlightcontroller/testmodule/TestModule.java b/src/main/java/net/floodlightcontroller/testmodule/TestModule.java index 5344ee9a78ad1f4c8e9328023653cc814577bf2c..2b3d7ec51c020b4717168104229f7b112b9c5984 100644 --- a/src/main/java/net/floodlightcontroller/testmodule/TestModule.java +++ b/src/main/java/net/floodlightcontroller/testmodule/TestModule.java @@ -9,6 +9,10 @@ import java.util.Map; import org.projectfloodlight.openflow.protocol.OFFactories; import org.projectfloodlight.openflow.protocol.OFFactory; import org.projectfloodlight.openflow.protocol.OFFlowAdd; +import org.projectfloodlight.openflow.protocol.OFMeterBandStats; +import org.projectfloodlight.openflow.protocol.OFMeterBandType; +import org.projectfloodlight.openflow.protocol.OFMeterMod; +import org.projectfloodlight.openflow.protocol.OFMeterModCommand; import org.projectfloodlight.openflow.protocol.OFOxmClass; import org.projectfloodlight.openflow.protocol.OFPortDesc; import org.projectfloodlight.openflow.protocol.OFSetConfig; @@ -17,8 +21,17 @@ import org.projectfloodlight.openflow.protocol.action.OFAction; import org.projectfloodlight.openflow.protocol.action.OFActionOutput; import org.projectfloodlight.openflow.protocol.action.OFActionSetField; import org.projectfloodlight.openflow.protocol.action.OFActionSetNwSrc; +import org.projectfloodlight.openflow.protocol.instruction.OFInstruction; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionApplyActions; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionClearActions; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionExperimenter; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionGotoTable; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionMeter; +import org.projectfloodlight.openflow.protocol.instruction.OFInstructionWriteActions; import org.projectfloodlight.openflow.protocol.match.Match; import org.projectfloodlight.openflow.protocol.match.MatchField; +import org.projectfloodlight.openflow.protocol.meterband.OFMeterBand; +import org.projectfloodlight.openflow.protocol.meterband.OFMeterBandDrop; import org.projectfloodlight.openflow.protocol.oxm.OFOxm; import org.projectfloodlight.openflow.protocol.oxm.OFOxmEthSrc; import org.projectfloodlight.openflow.types.ArpOpcode; @@ -39,6 +52,7 @@ import org.projectfloodlight.openflow.types.OFVlanVidMatch; import org.projectfloodlight.openflow.types.TableId; import org.projectfloodlight.openflow.types.TransportPort; import org.projectfloodlight.openflow.types.U32; +import org.projectfloodlight.openflow.types.U64; import org.projectfloodlight.openflow.types.U8; import org.projectfloodlight.openflow.types.VlanPcp; import org.projectfloodlight.openflow.types.VlanVid; @@ -103,6 +117,18 @@ public class TestModule implements IFloodlightModule, IOFSwitchListener { OFFlowAdd.Builder fmb = factory.buildFlowAdd(); List<OFAction> actions = new ArrayList<OFAction>(); Match.Builder mb = factory.buildMatch(); + List<OFInstruction> instructions = new ArrayList<OFInstruction>(); + OFInstructionApplyActions.Builder applyActInstBldr = factory.instructions().buildApplyActions(); + OFInstructionWriteActions.Builder writeActInstBldr = factory.instructions().buildWriteActions(); + OFInstructionMeter.Builder mtrBldr = factory.instructions().buildMeter(); + OFInstructionClearActions clrAct = factory.instructions().clearActions(); // no builder available (there's nothing to set anyway) + OFInstructionGotoTable.Builder gotoTblBldr = factory.instructions().buildGotoTable(); + /*OFMeterBandDrop dropMeter = factory.meterBands().buildDrop().setBurstSize(100).setRate(200).build(); + List<OFMeterBand> meterBandEntries = new ArrayList<OFMeterBand>(); + OFMeterBandStats meterBandStats = factory.buildMeterBandStats().setPacketBandCount(U64.of(64)).setByteBandCount(U64.of(1024)).build(); + meterBandEntries.add(meterBandStats); + OFMeterMod meterMod = factory.buildMeterMod().setCommand(OFMeterModCommand.ADD.ordinal()).setMeters(meterBandEntries).setMeterId(10).build(); + factory.buildmeter*/ /*try { Thread.sleep(3000); @@ -158,6 +184,9 @@ public class TestModule implements IFloodlightModule, IOFSwitchListener { actions.add(factory.actions().setField(factory.oxms().ipv4Dst(IPv4Address.of("128.0.3.4")))); actions.add(factory.actions().setField(factory.oxms().sctpSrc(TransportPort.of(22)))); actions.add(factory.actions().setField(factory.oxms().sctpDst(TransportPort.of(80)))); + actions.add(factory.actions().setField((factory.oxms().ipDscp(IpDscp.DSCP_11)))); + actions.add(factory.actions().setField((factory.oxms().ipEcn(IpEcn.ECN_10)))); + fmb.setTableId(TableId.of(7)); // these test non-set-field actions //actions.add(factory.actions().copyTtlOut()); @@ -174,8 +203,12 @@ public class TestModule implements IFloodlightModule, IOFSwitchListener { /* METADATA TEST mb.setExact(MatchField.METADATA, OFMetadata.ofRaw(1)); */ - - fmb.setActions(actions); + //fmb.setActions(actions); // this will automatically create the apply actions instruction + applyActInstBldr.setActions(actions); + //mtrBldr.setMeterId(1); + instructions.add(applyActInstBldr.build()); + //instructions.add(mtrBldr.build()); + fmb.setInstructions(instructions); fmb.setMatch(mb.build()); sfps.addFlow("test-flow", fmb.build(), switchId); diff --git a/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java b/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java index 2e336c3b8ef270b105bdc5f40a580721b25896ea..758e50a9242cdd17df6cdc24075e532908fa5068 100644 --- a/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java +++ b/src/main/java/net/floodlightcontroller/topology/NodePortTuple.java @@ -17,7 +17,6 @@ package net.floodlightcontroller.topology; import net.floodlightcontroller.core.web.serializers.DPIDSerializer; -import net.floodlightcontroller.core.web.serializers.UShortSerializer; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonSerialize; diff --git a/src/main/java/net/floodlightcontroller/ui/web/StaticWebRoutable.java b/src/main/java/net/floodlightcontroller/ui/web/StaticWebRoutable.java index aab21fb643a6634b9d7693d642e59e14945e7f3e..6470c904562639647960962221a6ad0e6c016db7 100644 --- a/src/main/java/net/floodlightcontroller/ui/web/StaticWebRoutable.java +++ b/src/main/java/net/floodlightcontroller/ui/web/StaticWebRoutable.java @@ -67,7 +67,6 @@ public class StaticWebRoutable implements RestletRoutable, IFloodlightModule { public void startUp(FloodlightModuleContext context) { // Add our REST API restApi.addRestletRoutable(this); - } @Override diff --git a/src/main/java/net/floodlightcontroller/util/ActionUtils.java b/src/main/java/net/floodlightcontroller/util/ActionUtils.java index 3b0553d49a81910ed71db764beea2a8263cb932c..28d9a206f09cc2aae84f4fed2f6d1e3860124ed1 100644 --- a/src/main/java/net/floodlightcontroller/util/ActionUtils.java +++ b/src/main/java/net/floodlightcontroller/util/ActionUtils.java @@ -67,6 +67,7 @@ import org.projectfloodlight.openflow.types.EthType; import org.projectfloodlight.openflow.types.ICMPv4Code; import org.projectfloodlight.openflow.types.ICMPv4Type; import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.IpDscp; import org.projectfloodlight.openflow.types.IpEcn; import org.projectfloodlight.openflow.types.IpProtocol; import org.projectfloodlight.openflow.types.MacAddress; @@ -278,9 +279,9 @@ public class ActionUtils { } else if (((OFActionSetField)a).getField() instanceof OFOxmIpv4Dst) { sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_NW_DST + MatchUtils.SET_FIELD_DELIM + ((OFOxmIpv4Dst) ((OFActionSetField) a).getField()).getValue().toString()); } else if (((OFActionSetField)a).getField() instanceof OFOxmIpEcn) { //TODO @Ryan ECN and DSCP need to have their own columns for OF1.3.... - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_NW_TOS + MatchUtils.SET_FIELD_DELIM + Byte.toString(((OFOxmIpEcn) ((OFActionSetField) a).getField()).getValue().getEcnValue())); + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_NW_ECN + MatchUtils.SET_FIELD_DELIM + Byte.toString(((OFOxmIpEcn) ((OFActionSetField) a).getField()).getValue().getEcnValue())); } else if (((OFActionSetField)a).getField() instanceof OFOxmIpDscp) { - sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_NW_TOS + MatchUtils.SET_FIELD_DELIM + Byte.toString(((OFOxmIpDscp) ((OFActionSetField) a).getField()).getValue().getDscpValue())); + sb.append(STR_FIELD_SET + "=" + MatchUtils.STR_NW_DSCP + MatchUtils.SET_FIELD_DELIM + Byte.toString(((OFOxmIpDscp) ((OFActionSetField) a).getField()).getValue().getDscpValue())); } /* TRANSPORT LAYER, TCP, UDP, and SCTP */ else if (((OFActionSetField)a).getField() instanceof OFOxmTcpSrc) { @@ -375,7 +376,7 @@ public class ActionUtils { case STR_EXPERIMENTER: //no-op. Not implemented break; - case STR_FIELD_SET: + case STR_FIELD_SET: /* ONLY OF1.1+ should get in here. These should only be header fields valid within a set-field. */ String[] actionData = pair.split(MatchUtils.SET_FIELD_DELIM); if (actionData.length != 2) { throw new IllegalArgumentException("[Action, Data] " + keyPair + " does not have form 'action=data' parsing " + actionData); @@ -456,9 +457,15 @@ public class ActionUtils { .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIpv4Dst().setValue(IPv4Address.of(actionData[1])).build()) .build(); break; - case MatchUtils.STR_NW_TOS: - //TODO @Ryan need to break this up into ECN and DSCP - + case MatchUtils.STR_NW_ECN: + a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() + .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIpEcn().setValue(IpEcn.of(Byte.parseByte(actionData[1]))).build()) + .build(); + break; + case MatchUtils.STR_NW_DSCP: + a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() + .setField(OFFactories.getFactory(fmb.getVersion()).oxms().buildIpDscp().setValue(IpDscp.of(Byte.parseByte(actionData[1]))).build()) + .build(); break; case MatchUtils.STR_SCTP_SRC: a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetField() @@ -544,7 +551,7 @@ public class ActionUtils { .build(); break; case STR_NW_TOS_SET: - a = decode_set_tos_bits(pair, fmb.getVersion(), log); + a = decode_set_tos_bits(pair, fmb.getVersion(), log); // should only be used by OF1.0 break; case STR_NW_SRC_SET: a = decode_set_src_ip(pair, fmb.getVersion(), log); @@ -552,7 +559,7 @@ public class ActionUtils { case STR_NW_DST_SET: a = decode_set_dst_ip(pair, fmb.getVersion(), log); break; - case STR_NW_ECN_SET: + case STR_NW_ECN_SET: // loxi does not support DSCP set for OF1.3 a = OFFactories.getFactory(fmb.getVersion()).actions().buildSetNwEcn() .setNwEcn(IpEcn.of(Byte.parseByte(pair))) .build(); diff --git a/src/main/java/net/floodlightcontroller/util/MatchUtils.java b/src/main/java/net/floodlightcontroller/util/MatchUtils.java index f830ebc913338fa94579d6559bf21e614c59d99b..449055aeacbb4365071d5f8348f5f12595271650 100644 --- a/src/main/java/net/floodlightcontroller/util/MatchUtils.java +++ b/src/main/java/net/floodlightcontroller/util/MatchUtils.java @@ -59,6 +59,8 @@ public class MatchUtils { public static final String STR_NW_SRC = "nw_src"; public static final String STR_NW_PROTO = "nw_proto"; public static final String STR_NW_TOS = "nw_tos"; + public static final String STR_NW_ECN = "nw_ecn"; + public static final String STR_NW_DSCP = "nw_dscp"; public static final String STR_SCTP_DST = "sctp_dst"; public static final String STR_SCTP_SRC = "sctp_src"; @@ -383,6 +385,12 @@ public class MatchUtils { mb.setExact(MatchField.IP_ECN, IpEcn.of(U8.t(Short.valueOf(key_value[1])))); mb.setExact(MatchField.IP_DSCP, IpDscp.of(U8.t(Short.valueOf(key_value[1])))); break; + case STR_NW_ECN: + mb.setExact(MatchField.IP_ECN, IpEcn.of(U8.t(Short.valueOf(key_value[1])))); + break; + case STR_NW_DSCP: + mb.setExact(MatchField.IP_DSCP, IpDscp.of(U8.t(Short.valueOf(key_value[1])))); + break; case STR_SCTP_DST: // for transport ports, if we don't know the transport protocol yet, postpone parsing this [key, value] pair until we know. Put it at the back of the queue. if (mb.get(MatchField.IP_PROTO) == null) { llValues.add(key_value); // place it back if we can't proceed yet diff --git a/src/main/resources/floodlightdefault.properties b/src/main/resources/floodlightdefault.properties index 3dbacb7bae8f06c048021048013811e26471de85..2aaab9fdaba5ce189f597a519d3c3066e5c84374 100644 --- a/src/main/resources/floodlightdefault.properties +++ b/src/main/resources/floodlightdefault.properties @@ -10,8 +10,9 @@ net.floodlightcontroller.debugevent.DebugEventService,\ net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher,\ net.floodlightcontroller.restserver.RestApiServer,\ net.floodlightcontroller.topology.TopologyManager,\ -net.floodlightcontroller.forwarding.Forwarding,\ +net.floodlightcontroller.testmodule.TestModule,\ net.floodlightcontroller.linkdiscovery.internal.LinkDiscoveryManager,\ +net.floodlightcontroller.ui.web.StaticWebRoutable,\ net.floodlightcontroller.devicemanager.internal.DeviceManagerImpl org.sdnplatform.sync.internal.SyncManager.authScheme=CHALLENGE_RESPONSE org.sdnplatform.sync.internal.SyncManager.keyStorePath=/etc/floodlight/auth_credentials.jceks diff --git a/src/main/resources/logback-test.xml b/src/main/resources/logback-test.xml index 7f61e32e22bac17b1f72ccd1562370afe70d2673..c80889cac1cf1411fe6db835c25a1011e7364ad0 100644 --- a/src/main/resources/logback-test.xml +++ b/src/main/resources/logback-test.xml @@ -6,12 +6,12 @@ </appender> <appender name="EV_WARN_ERR" class="net.floodlightcontroller.debugevent.DebugEventAppender"> </appender> - <root level="DEBUG"> + <root level="TRACE"> <appender-ref ref="STDOUT" /> <appender-ref ref="EV_WARN_ERR" /> </root> - <logger name="org" level="DEBUG"/> - <logger name="LogService" level="DEBUG"/> <!-- Restlet access logging --> + <logger name="org" level="TRACE"/> + <logger name="LogService" level="TRACE"></logger> <!-- Restlet access logging --> <logger name="net.floodlightcontroller" level="DEBUG"/> <logger name="org.sdnplatform" level="INFO"></logger> <logger name="net.floodlightcontroller.devicemanager" level="TRACE"></logger> diff --git a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandlerVer13Test.java b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandlerVer13Test.java index 06b3a3bbeceea5a29c80a7f673f0bec31a8b63dd..2fc31311dbee3a36393b277a1f4abfe6ae6b9672 100644 --- a/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandlerVer13Test.java +++ b/src/test/java/net/floodlightcontroller/core/internal/OFSwitchHandshakeHandlerVer13Test.java @@ -1,7 +1,6 @@ package net.floodlightcontroller.core.internal; import static org.easymock.EasyMock.anyObject; -import static org.easymock.EasyMock.capture; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expectLastCall; @@ -15,7 +14,6 @@ import java.util.ArrayList; import java.util.EnumSet; import java.util.List; -import org.easymock.Capture; import org.hamcrest.CoreMatchers; import org.hamcrest.Matchers; import org.junit.Test; @@ -29,10 +27,7 @@ import org.projectfloodlight.openflow.protocol.OFBsnControllerConnection; import org.projectfloodlight.openflow.protocol.OFBsnControllerConnectionState; import org.projectfloodlight.openflow.protocol.OFBsnControllerConnectionsReply; import org.projectfloodlight.openflow.protocol.OFBsnControllerConnectionsRequest; -import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsReply; -import org.projectfloodlight.openflow.protocol.OFBsnGentableDescStatsRequest; import org.projectfloodlight.openflow.protocol.OFBsnSetAuxCxnsReply; -import org.projectfloodlight.openflow.protocol.OFBsnSetAuxCxnsRequest; import org.projectfloodlight.openflow.protocol.OFCapabilities; import org.projectfloodlight.openflow.protocol.OFControllerRole; import org.projectfloodlight.openflow.protocol.OFDescStatsReply; @@ -47,7 +42,6 @@ import org.projectfloodlight.openflow.protocol.OFRoleReply; import org.projectfloodlight.openflow.protocol.OFRoleRequest; import org.projectfloodlight.openflow.protocol.OFVersion; import org.projectfloodlight.openflow.types.DatapathId; -import org.projectfloodlight.openflow.types.GenTableId; import org.projectfloodlight.openflow.types.OFAuxId; import org.projectfloodlight.openflow.types.OFPort; diff --git a/src/test/java/net/floodlightcontroller/debugevent/CircularBufferTest.java b/src/test/java/net/floodlightcontroller/debugevent/CircularBufferTest.java deleted file mode 100644 index 5c99aae3c972735485382105b085f50a7ae62fa4..0000000000000000000000000000000000000000 --- a/src/test/java/net/floodlightcontroller/debugevent/CircularBufferTest.java +++ /dev/null @@ -1,83 +0,0 @@ -package net.floodlightcontroller.debugevent; - -import java.util.ArrayList; - -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import net.floodlightcontroller.test.FloodlightTestCase; - -public class CircularBufferTest extends FloodlightTestCase { - /*CircularBuffer<String> cb; - protected static Logger log = LoggerFactory.getLogger(CircularBufferTest.class); - - @Test - public void testCircularNature() { - cb = new CircularBuffer<String>(2); - cb.add("String 1"); - assertEquals(1, cb.size()); - cb.add("String 2"); - assertEquals(2, cb.size()); - cb.add("String 3"); - assertEquals(2, cb.size()); - - for (String s : cb) { - assertEquals(false, s.contains("1")); - } - } - - class Elems { - String str; - Boolean boo; - - public Elems(String s,boolean b) { - this.str = s; - this.boo = b; - } - } - - @Test - public void testAdd() { - CircularBuffer<Elems> eb = new CircularBuffer<Elems>(2); - Elems theone = new Elems("String 1", false); - Elems ret1 = eb.add(theone); - assertEquals(null, ret1); - Elems ret2 = eb.add(new Elems("String 2", true)); - assertEquals(null, ret2); - Elems ret3 = eb.add(new Elems("String 3", true)); - // We want to see if what is returned is a reference to the original object - // 'theone'. So we use '==' to compare the references - assertEquals(true, ret3 == theone); - log.info("{} {}", ret3, theone); - } - - @Test - public void testAddAll() { - CircularBuffer<Elems> eb = new CircularBuffer<Elems>(2); - Elems one = new Elems("String 1", false); - eb.add(one); - ArrayList<Elems> elist = new ArrayList<Elems>(); - Elems two = new Elems("String 2", true); - elist.add(two); - Elems three = new Elems("String 3", true); - elist.add(three); - Elems four = new Elems("String 4", true); - elist.add(four); - - ArrayList<Elems> retlist = eb.addAll(elist, 2); - assertEquals(null, retlist.get(0)); - assertEquals(true, retlist.get(1) == one); - assertEquals(true, retlist.get(2) == four); - - ArrayList<Elems> retlist2 = eb.addAll(retlist, 3); - assertEquals(null, retlist2.get(0)); - assertEquals(true, retlist2.get(1) == two); - assertEquals(true, retlist2.get(2) == three); - - ArrayList<Elems> retlist3 = eb.addAll(retlist2, 4); - assertEquals(retlist3, retlist2); - - } -*/ -} diff --git a/src/test/java/net/floodlightcontroller/debugevent/DebugEventTest.java b/src/test/java/net/floodlightcontroller/debugevent/DebugEventTest.java index 80d06bd5e15d68f132c7d8bbd5d3d3f5fd8d6ce6..0c296ef4bc60253961c084e37a14ff439d69be3a 100644 --- a/src/test/java/net/floodlightcontroller/debugevent/DebugEventTest.java +++ b/src/test/java/net/floodlightcontroller/debugevent/DebugEventTest.java @@ -11,13 +11,13 @@ import net.floodlightcontroller.debugevent.IDebugEventService.EventType; import net.floodlightcontroller.test.FloodlightTestCase; public class DebugEventTest extends FloodlightTestCase { - /* DebugEvent debugEvent; + Event debugEvent; protected static Logger log = LoggerFactory.getLogger(DebugEventTest.class); @Override @Before public void setUp() throws Exception { - debugEvent = new DebugEvent(); + debugEvent = new Event(System.currentTimeMillis(), 0, "test", null, 0); } @@ -25,8 +25,8 @@ public class DebugEventTest extends FloodlightTestCase { @Test public void testRegisterAndUpdateEvent() throws Exception { assertEquals(0, debugEvent.currentEvents.size()); - IEventUpdater<SwitchyEvent> event1 = null; - IEventUpdater<PacketyEvent> event2 = null; + IEventCategory<SwitchyEvent> event1 = null; + IEventCategory<PacketyEvent> event2 = null; event1 = debugEvent.registerEvent("dbgevtest", "switchevent", "switchtest", EventType.ALWAYS_LOG, SwitchyEvent.class, 100); @@ -97,5 +97,5 @@ public class DebugEventTest extends FloodlightTestCase { this.dpid = dpid; this.mac = mac; } - } */ + } } diff --git a/src/test/java/net/floodlightcontroller/debugevent/EventTest.java b/src/test/java/net/floodlightcontroller/debugevent/EventTest.java index f3bbc52089476511e098943e397ea8ab011e7524..8ee0661cf3d4e115c0c508411d941f29673aef5e 100644 --- a/src/test/java/net/floodlightcontroller/debugevent/EventTest.java +++ b/src/test/java/net/floodlightcontroller/debugevent/EventTest.java @@ -14,14 +14,13 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class EventTest { - /* protected static Logger log = LoggerFactory.getLogger(EventTest.class); + protected static Logger log = LoggerFactory.getLogger(EventTest.class); @Test public void testFormat() { River r = new River("ganges", 42); - Event e = new Event(1L, 32, "test", - new RiverEvent(1L, (short)10, true, "big river", 5, 4L, r)); + Event e = new Event(1, 32, "test", new RiverEvent(1L, (short)10, true, "big river", 5, 4L, r), 0); Map<String, String> expected = new HashMap<String, String>(); expected.put("dpid", "00:00:00:00:00:00:00:01"); @@ -38,10 +37,6 @@ public class EventTest { e.getFormattedEvent(RiverEvent.class, "test").get(elem.getKey())); // ensure timestamp comes in ISO8601 time - assertEquals("1969-12-31T16:00:00.001-0800", - e.getFormattedEvent(RiverEvent.class, "test2").get("Timestamp")); //1L - // change the timestamp - the call should return cached value - e.setTimestamp(2L); assertEquals("1969-12-31T16:00:00.001-0800", e.getFormattedEvent(RiverEvent.class, "test2").get("Timestamp")); //1L @@ -56,19 +51,6 @@ public class EventTest { e.getFormattedEvent(null, "test").get("Error")); } - @Test - public void testIncorrectAnnotation() { - Event e = new Event(1L, 32, "test", - new LakeEvent(199)); // dpid cannot be int - assertEquals("java.lang.Integer cannot be cast to java.lang.Long", - e.getFormattedEvent(LakeEvent.class, "test").get("Error")); - - Event e2 = new Event(1L, 32, "test", - new LakeEvent2(199)); // mac cannot be int - assertEquals("java.lang.Integer cannot be cast to java.lang.Long", - e2.getFormattedEvent(LakeEvent2.class, "test").get("Error")); - } - class RiverEvent { @EventColumn(name = "dpid", description = EventFieldType.DPID) long dpid; @@ -145,5 +127,5 @@ public class EventTest { public LakeEvent2(int mac) { this.mac = mac; } - } */ + } } diff --git a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java index 03479e44954f0f14aa9d4cb8022f001e253c8fa0..df61c28e34730ca935489e5f1d7ce5e7d251969f 100644 --- a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java +++ b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceManagerImplTest.java @@ -53,7 +53,6 @@ import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IListener.Command; import net.floodlightcontroller.core.IOFSwitch; -import net.floodlightcontroller.core.internal.RoleManager; import net.floodlightcontroller.core.HARole; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.module.FloodlightModuleException; @@ -90,12 +89,15 @@ import net.floodlightcontroller.topology.ITopologyService; import org.easymock.EasyMock; import org.junit.Before; import org.junit.Test; +import org.projectfloodlight.openflow.protocol.OFFactories; import org.projectfloodlight.openflow.protocol.OFPacketIn; -import org.projectfloodlight.openflow.protocol.OFPacketInReason; -import org.projectfloodlight.openflow.protocol.OFPortDesc; +import org.projectfloodlight.openflow.protocol.OFPacketInReason;import org.projectfloodlight.openflow.protocol.OFVersion; import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFBufferId; import org.projectfloodlight.openflow.types.OFPort; -import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.types.VlanVid; import org.sdnplatform.sync.IClosableIterator; import org.sdnplatform.sync.IStoreClient; import org.sdnplatform.sync.ISyncService; @@ -106,2933 +108,2925 @@ import org.slf4j.LoggerFactory; public class DeviceManagerImplTest extends FloodlightTestCase { - protected static Logger logger = - LoggerFactory.getLogger(DeviceManagerImplTest.class); - - protected OFPacketIn testARPReplyPacketIn_1, testARPReplyPacketIn_2; - protected OFPacketIn testUDPPacketIn; - protected IPacket testARPReplyPacket_1, testARPReplyPacket_2; - protected Ethernet testUDPPacket; - protected byte[] testARPReplyPacket_1_Srld, testARPReplyPacket_2_Srld; - protected byte[] testUDPPacketSrld; - private MockSyncService syncService; - private IStoreClient<String, DeviceSyncRepresentation> storeClient; - - DeviceManagerImpl deviceManager; - MemoryStorageSource storageSource; - FlowReconcileManager flowReconcileMgr; - - private IOFSwitch makeSwitchMock(DatapathId id) { - IOFSwitch mockSwitch = createMock(IOFSwitch.class); - OFPort port = OFPort.of(1); - expect(mockSwitch.getId()).andReturn(id).anyTimes(); - expect(mockSwitch.getId().toString()).andReturn(id.toString()).anyTimes(); - expect(mockSwitch.getPort(OFPort.of(anyShort())).getPortNo()).andReturn(port).anyTimes(); - return mockSwitch; - } - - /* - * return an EasyMock ITopologyService that's setup so that it will - * answer all questions a device or device manager will ask - * (isAttachmentPointPort, etc.) in a way so that every port is a - * non-BD, attachment point port. - * The returned mock is still in record mode - */ - private ITopologyService makeMockTopologyAllPortsAp() { - ITopologyService mockTopology = createMock(ITopologyService.class); - mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), OFPort.of(anyShort())); - expectLastCall().andReturn(true).anyTimes(); - mockTopology.getL2DomainId(DatapathId.of(anyLong())); - expectLastCall().andReturn(1L).anyTimes(); - mockTopology.isBroadcastDomainPort(DatapathId.of(anyLong()), OFPort.of(anyShort())); - expectLastCall().andReturn(false).anyTimes(); - mockTopology.isConsistent(DatapathId.of(anyLong()), OFPort.of(anyShort()), DatapathId.of(anyLong()), OFPort.of(anyShort())); - expectLastCall().andReturn(false).anyTimes(); - mockTopology.isInSameBroadcastDomain(DatapathId.of(anyLong()), OFPort.of(anyShort()), DatapathId.of(anyLong()), OFPort.of(anyShort())); - expectLastCall().andReturn(false).anyTimes(); - return mockTopology; - } - - @Override - @Before - public void setUp() throws Exception { - doSetUp(HARole.ACTIVE); - } - - public void doSetUp(HARole initialRole) throws Exception { - super.setUp(); - - this.syncService = new MockSyncService(); - - FloodlightModuleContext fmc = new FloodlightModuleContext(); - RestApiServer restApi = new RestApiServer(); - MockThreadPoolService tp = new MockThreadPoolService(); - ITopologyService topology = createMock(ITopologyService.class); - fmc.addService(IThreadPoolService.class, tp); - mockFloodlightProvider = getMockFloodlightProvider(); - mockFloodlightProvider.setRole(initialRole, ""); - - - deviceManager = new DeviceManagerImpl(); - flowReconcileMgr = new FlowReconcileManager(); - DefaultEntityClassifier entityClassifier = new DefaultEntityClassifier(); - fmc.addService(IDeviceService.class, deviceManager); - storageSource = new MemoryStorageSource(); - fmc.addService(IStorageSourceService.class, storageSource); - fmc.addService(IFloodlightProviderService.class, mockFloodlightProvider); - fmc.addService(IRestApiService.class, restApi); - fmc.addService(IFlowReconcileService.class, flowReconcileMgr); - fmc.addService(IEntityClassifierService.class, entityClassifier); - fmc.addService(ITopologyService.class, topology); - fmc.addService(ISyncService.class, syncService); - tp.init(fmc); - restApi.init(fmc); - storageSource.init(fmc); - deviceManager.init(fmc); - flowReconcileMgr.init(fmc); - entityClassifier.init(fmc); - syncService.init(fmc); - storageSource.startUp(fmc); - deviceManager.startUp(fmc); - flowReconcileMgr.startUp(fmc); - tp.startUp(fmc); - entityClassifier.startUp(fmc); - syncService.startUp(fmc); - - this.storeClient = - this.syncService.getStoreClient(DeviceManagerImpl.DEVICE_SYNC_STORE_NAME, - String.class, DeviceSyncRepresentation.class); - - reset(topology); - topology.addListener(deviceManager); - expectLastCall().anyTimes(); - replay(topology); - - IOFSwitch mockSwitch1 = makeSwitchMock(DatapathId.of(1L)); - IOFSwitch mockSwitch10 = makeSwitchMock(DatapathId.of(10L)); - IOFSwitch mockSwitch5 = makeSwitchMock(DatapathId.of(5L)); - IOFSwitch mockSwitch50 = makeSwitchMock(DatapathId.of(50L)); - Map<DatapathId, IOFSwitch> switches = new HashMap<DatapathId, IOFSwitch>(); - switches.put(DatapathId.of(1L), mockSwitch1); - switches.put(DatapathId.of(10L), mockSwitch10); - switches.put(DatapathId.of(5L), mockSwitch5); - switches.put(DatapathId.of(50L), mockSwitch50); - mockFloodlightProvider.setSwitches(switches); - - replay(mockSwitch1, mockSwitch5, mockSwitch10, mockSwitch50); - - // Build our test packet - this.testARPReplyPacket_1 = new Ethernet() - .setSourceMACAddress("00:44:33:22:11:01") - .setDestinationMACAddress("00:11:22:33:44:55") - .setEtherType(Ethernet.TYPE_ARP) - .setVlanID((short)5) - .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:01")) - .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.1")) - .setTargetHardwareAddress(Ethernet.toMACAddress("00:11:22:33:44:55")) - .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2"))); - this.testARPReplyPacket_1_Srld = testARPReplyPacket_1.serialize(); - - // Another test packet with the same ARP payload as packet 1 but with - // a different source MAC. (i.e., sender MAC and source MAC differ) - this.testARPReplyPacket_2 = new Ethernet() - .setSourceMACAddress("00:99:88:77:66:55") - .setDestinationMACAddress("00:11:22:33:44:55") - .setEtherType(Ethernet.TYPE_ARP) - .setVlanID((short)5) - .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:01")) - .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.1")) - .setTargetHardwareAddress(Ethernet.toMACAddress("00:11:22:33:44:55")) - .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2"))); - this.testARPReplyPacket_2_Srld = testARPReplyPacket_2.serialize(); - - // This packet reverses the MACs and IP from testARPReplyPacket_1 - this.testUDPPacket = (Ethernet) new Ethernet() - .setSourceMACAddress("00:11:22:33:44:55") - .setDestinationMACAddress("00:44:33:22:11:01") - .setEtherType(Ethernet.TYPE_IPv4) - .setVlanID((short)5) - .setPayload( - new IPv4() - .setTtl((byte) 128) - .setSourceAddress("192.168.1.2") - .setDestinationAddress("192.168.1.1") - .setPayload(new UDP() - .setSourcePort((short) 5000) - .setDestinationPort((short) 5001) - .setPayload(new Data(new byte[] {0x01})))); - updateUDPPacketIn(); - - // Build the PacketIn - this.testARPReplyPacketIn_1 = ((OFPacketIn) mockFloodlightProvider. - getOFMessageFactory().getMessage(OFType.PACKET_IN)) - .setBufferId(-1) - .setInPort((short) 1) - .setPacketData(this.testARPReplyPacket_1_Srld) - .setReason(OFPacketInReason.NO_MATCH) - .setTotalLength((short) this.testARPReplyPacket_1_Srld.length); - - // Build the PacketIn - this.testARPReplyPacketIn_2 = ((OFPacketIn) mockFloodlightProvider. - getOFMessageFactory().getMessage(OFType.PACKET_IN)) - .setBufferId(-1) - .setInPort((short) 1) - .setPacketData(this.testARPReplyPacket_2_Srld) - .setReason(OFPacketInReason.NO_MATCH) - .setTotalLength((short) this.testARPReplyPacket_2_Srld.length); - - - } - - /** - * Updates testUDPPacketIn and testUDPPacketSrld from testUDPPacket - * To be called after testUDPPacket has been mangled. - */ - private void updateUDPPacketIn() { - this.testUDPPacketSrld = this.testUDPPacket.serialize(); - // Build the PacketIn - this.testUDPPacketIn = ((OFPacketIn) mockFloodlightProvider. - getOFMessageFactory().getMessage(OFType.PACKET_IN)) - .setBufferId(-1) - .setInPort((short) 3) - .setPacketData(this.testUDPPacketSrld) - .setReason(OFPacketInReason.NO_MATCH) - .setTotalLength((short) this.testUDPPacketSrld.length); - } - - @Test - public void testLastSeen() throws Exception { - Calendar c = Calendar.getInstance(); - Date d1 = c.getTime(); - Entity entity1 = new Entity(1L, null, null, null, null, d1); - c.add(Calendar.SECOND, 1); - Entity entity2 = new Entity(1L, null, 1, null, null, c.getTime()); - - IDevice d = deviceManager.learnDeviceByEntity(entity2); - assertEquals(c.getTime(), d.getLastSeen()); - d = deviceManager.learnDeviceByEntity(entity1); - assertEquals(c.getTime(), d.getLastSeen()); - - deviceManager.startUp(null); - d = deviceManager.learnDeviceByEntity(entity1); - assertEquals(d1, d.getLastSeen()); - d = deviceManager.learnDeviceByEntity(entity2); - assertEquals(c.getTime(), d.getLastSeen()); - } - - - @Test - public void testEntityLearning() throws Exception { - IDeviceListener mockListener = - createMock(IDeviceListener.class); - expect(mockListener.getName()).andReturn("mockListener").atLeastOnce(); - expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) - .andReturn(false).atLeastOnce(); - expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) - .andReturn(false).atLeastOnce(); - - replay(mockListener); - deviceManager.addListener(mockListener); - verify(mockListener); - reset(mockListener); - deviceManager.entityClassifier= new MockEntityClassifier(); - deviceManager.startUp(null); - - ITopologyService mockTopology = createMock(ITopologyService.class); - expect(mockTopology.getL2DomainId(anyLong())). - andReturn(1L).anyTimes(); - expect(mockTopology.isBroadcastDomainPort(anyLong(), anyShort())). - andReturn(false).anyTimes(); - - expect(mockTopology.isAttachmentPointPort(anyLong(), - anyShort())).andReturn(true).anyTimes(); - expect(mockTopology.isConsistent(10L, (short)1, 10L, (short)1)). - andReturn(true).anyTimes(); - expect(mockTopology.isConsistent(1L, (short)1, 1L, (short)1)). - andReturn(true).anyTimes(); - expect(mockTopology.isConsistent(50L, (short)3, 50L, (short)3)). - andReturn(true).anyTimes(); - - Date topologyUpdateTime = new Date(); - expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). - anyTimes(); - - deviceManager.topology = mockTopology; - - Entity entity1 = new Entity(1L, null, null, 1L, 1, new Date()); - Entity entity2 = new Entity(1L, null, null, 10L, 1, new Date()); - Entity entity3 = new Entity(1L, null, 1, 10L, 1, new Date()); - Entity entity4 = new Entity(1L, null, 1, 1L, 1, new Date()); - Entity entity5 = new Entity(2L, (short)4, 1, 5L, 2, new Date()); - Entity entity6 = new Entity(2L, (short)4, 1, 50L, 3, new Date()); - Entity entity7 = new Entity(2L, (short)4, 2, 50L, 3, new Date()); - - mockListener.deviceAdded(isA(IDevice.class)); - replay(mockListener, mockTopology); - - Device d1 = deviceManager.learnDeviceByEntity(entity1); - assertSame(d1, deviceManager.learnDeviceByEntity(entity1)); - assertSame(d1, deviceManager.findDeviceByEntity(entity1)); - assertEquals(DefaultEntityClassifier.entityClass , - d1.getEntityClass()); - assertArrayEquals(new Short[] { -1 }, d1.getVlanId()); - assertArrayEquals(new Integer[] { }, d1.getIPv4Addresses()); - - assertEquals(1, deviceManager.getAllDevices().size()); - verify(mockListener); - - reset(mockListener); - mockListener.deviceAdded(isA(IDevice.class)); - replay(mockListener); - - Device d2 = deviceManager.learnDeviceByEntity(entity2); - assertFalse(d1.equals(d2)); - assertNotSame(d1, d2); - assertNotSame(d1.getDeviceKey(), d2.getDeviceKey()); - assertEquals(MockEntityClassifier.testEC, d2.getEntityClass()); - assertArrayEquals(new Short[] { -1 }, d2.getVlanId()); - assertArrayEquals(new Integer[] { }, d2.getIPv4Addresses()); - - assertEquals(2, deviceManager.getAllDevices().size()); - verify(mockListener); - - reset(mockListener); - mockListener.deviceIPV4AddrChanged(isA(IDevice.class)); - replay(mockListener); - - Device d3 = deviceManager.learnDeviceByEntity(entity3); - assertNotSame(d2, d3); - assertEquals(d2.getDeviceKey(), d3.getDeviceKey()); - assertEquals(MockEntityClassifier.testEC, d3.getEntityClass()); - assertArrayEquals(new Integer[] { 1 }, - d3.getIPv4Addresses()); - assertArrayEquals(new SwitchPort[] { new SwitchPort(10L, 1) }, - d3.getAttachmentPoints()); - assertArrayEquals(new SwitchPort[] { new SwitchPort(10L, 1) }, - d3.getAttachmentPoints(true)); - assertArrayEquals(new Short[] { -1 }, - d3.getVlanId()); - - assertEquals(2, deviceManager.getAllDevices().size()); - verify(mockListener); - - reset(mockListener); - mockListener.deviceIPV4AddrChanged(isA(IDevice.class)); - replay(mockListener); - - Device d4 = deviceManager.learnDeviceByEntity(entity4); - assertNotSame(d1, d4); - assertEquals(d1.getDeviceKey(), d4.getDeviceKey()); - assertEquals(DefaultEntityClassifier.entityClass, d4.getEntityClass()); - assertArrayEquals(new Integer[] { 1 }, - d4.getIPv4Addresses()); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, - d4.getAttachmentPoints()); - assertArrayEquals(new Short[] { -1 }, - d4.getVlanId()); - - assertEquals(2, deviceManager.getAllDevices().size()); - verify(mockListener); - - reset(mockListener); - mockListener.deviceAdded((isA(IDevice.class))); - replay(mockListener); - - Device d5 = deviceManager.learnDeviceByEntity(entity5); - assertArrayEquals(new SwitchPort[] { new SwitchPort(5L, 2) }, - d5.getAttachmentPoints()); - assertArrayEquals(new Short[] { (short) 4 }, - d5.getVlanId()); - assertEquals(2L, d5.getMACAddress()); - assertEquals("00:00:00:00:00:02", d5.getMACAddressString()); - verify(mockListener); - - reset(mockListener); - mockListener.deviceAdded(isA(IDevice.class)); - replay(mockListener); - - Device d6 = deviceManager.learnDeviceByEntity(entity6); - assertArrayEquals(new SwitchPort[] { new SwitchPort(50L, 3) }, - d6.getAttachmentPoints()); - assertArrayEquals(new Short[] { (short) 4 }, - d6.getVlanId()); - - assertEquals(4, deviceManager.getAllDevices().size()); - verify(mockListener); - - reset(mockListener); - mockListener.deviceIPV4AddrChanged(isA(IDevice.class)); - replay(mockListener); - - Device d7 = deviceManager.learnDeviceByEntity(entity7); - assertNotSame(d6, d7); - assertEquals(d6.getDeviceKey(), d7.getDeviceKey()); - assertArrayEquals(new SwitchPort[] { new SwitchPort(50L, 3) }, - d7.getAttachmentPoints()); - assertArrayEquals(new Short[] { (short) 4 }, - d7.getVlanId()); - - assertEquals(4, deviceManager.getAllDevices().size()); - verify(mockListener); - - - reset(mockListener); - replay(mockListener); - - reset(deviceManager.topology); - deviceManager.topology.addListener(deviceManager); - expectLastCall().times(1); - replay(deviceManager.topology); - - deviceManager.entityClassifier = new MockEntityClassifierMac(); - deviceManager.startUp(null); - Entity entityNoClass = new Entity(5L, (short)1, 5, -1L, 1, new Date()); - assertEquals(null, deviceManager.learnDeviceByEntity(entityNoClass)); - - verify(mockListener); - } - - - private void doTestEntityOrdering(boolean computeInsertionPoint) throws Exception { - Entity e = new Entity(10L, null, null, null, null, null); - IEntityClass ec = createNiceMock(IEntityClass.class); - Device d = new Device(deviceManager, 1L, e, ec); - - int expectedLength = 1; - Long[] macs = new Long[] { 5L, // new first element - 15L, // new last element - 7L, // insert in middle - 12L, // insert in middle - 6L, // insert at idx 1 - 14L, // insert at idx length-2 - 1L, - 20L - }; - - for (Long mac: macs) { - e = new Entity(mac, null, null, null, null, null); - int insertionPoint; - if (computeInsertionPoint) { - insertionPoint = -(Arrays.binarySearch(d.entities, e)+1); - } else { - insertionPoint = -1; - } - d = deviceManager.allocateDevice(d, e, insertionPoint); - expectedLength++; - assertEquals(expectedLength, d.entities.length); - for (int i = 0; i < d.entities.length-1; i++) - assertEquals(-1, d.entities[i].compareTo(d.entities[i+1])); - } - } - - @Test - public void testEntityOrderingExternal() throws Exception { - doTestEntityOrdering(true); - } - - @Test - public void testEntityOrderingInternal() throws Exception { - doTestEntityOrdering(false); - } - - @Test - public void testAttachmentPointLearning() throws Exception { - IDeviceListener mockListener = - createMock(IDeviceListener.class); - expect(mockListener.getName()).andReturn("mockListener").atLeastOnce(); - expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) - .andReturn(false).atLeastOnce(); - expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) - .andReturn(false).atLeastOnce(); - - replay(mockListener); - deviceManager.addListener(mockListener); - verify(mockListener); - reset(mockListener); - - ITopologyService mockTopology = createMock(ITopologyService.class); - expect(mockTopology.getL2DomainId(1L)). - andReturn(1L).anyTimes(); - expect(mockTopology.getL2DomainId(5L)). - andReturn(1L).anyTimes(); - expect(mockTopology.getL2DomainId(10L)). - andReturn(10L).anyTimes(); - expect(mockTopology.getL2DomainId(50L)). - andReturn(10L).anyTimes(); - expect(mockTopology.isBroadcastDomainPort(anyLong(), anyShort())). - andReturn(false).anyTimes(); - expect(mockTopology.isInSameBroadcastDomain(anyLong(), anyShort(), - anyLong(), anyShort())).andReturn(false).anyTimes(); - - expect(mockTopology.isAttachmentPointPort(anyLong(), - anyShort())).andReturn(true).anyTimes(); - expect(mockTopology.isConsistent(1L, (short)1, 5L, (short)1)). - andReturn(false).anyTimes(); - expect(mockTopology.isConsistent(5L, (short)1, 10L, (short)1)). - andReturn(false).anyTimes(); - expect(mockTopology.isConsistent(10L, (short)1, 50L, (short)1)). - andReturn(false).anyTimes(); - - Date topologyUpdateTime = new Date(); - expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). - anyTimes(); - - replay(mockTopology); - - deviceManager.topology = mockTopology; - - Calendar c = Calendar.getInstance(); - Entity entity1 = new Entity(1L, null, 1, 1L, 1, c.getTime()); - Entity entity0 = new Entity(1L, null, null, null, null, c.getTime()); - c.add(Calendar.SECOND, 1); - Entity entity2 = new Entity(1L, null, null, 5L, 1, c.getTime()); - c.add(Calendar.SECOND, 1); - Entity entity3 = new Entity(1L, null, null, 10L, 1, c.getTime()); - c.add(Calendar.SECOND, 1); - Entity entity4 = new Entity(1L, null, null, 50L, 1, c.getTime()); - - IDevice d; - SwitchPort[] aps; - Integer[] ips; - - mockListener.deviceAdded(isA(IDevice.class)); - replay(mockListener); - - deviceManager.learnDeviceByEntity(entity1); - d = deviceManager.learnDeviceByEntity(entity0); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps); - ips = d.getIPv4Addresses(); - assertArrayEquals(new Integer[] { 1 }, ips); - verify(mockListener); - - reset(mockListener); - mockListener.deviceMoved((isA(IDevice.class))); - replay(mockListener); - - d = deviceManager.learnDeviceByEntity(entity2); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - - assertArrayEquals(new SwitchPort[] { new SwitchPort(5L, 1) }, aps); - ips = d.getIPv4Addresses(); - assertArrayEquals(new Integer[] { 1 }, ips); - verify(mockListener); - - reset(mockListener); - mockListener.deviceMoved((isA(IDevice.class))); - replay(mockListener); - - d = deviceManager.learnDeviceByEntity(entity3); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] {new SwitchPort(5L, 1), new SwitchPort(10L, 1)}, aps); - ips = d.getIPv4Addresses(); - assertArrayEquals(new Integer[] { 1 }, ips); - verify(mockListener); - - reset(mockListener); - mockListener.deviceMoved((isA(IDevice.class))); - replay(mockListener); - - d = deviceManager.learnDeviceByEntity(entity4); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(5L, 1), - new SwitchPort(50L, 1) }, aps); - ips = d.getIPv4Addresses(); - assertArrayEquals(new Integer[] { 1 }, ips); - verify(mockListener); - } - - /** - * In this test, a device is moved from attachment point (1,1) to (5,1) - * and then moved back to (1,1) within 30 seconds. Both the moves should - * generate device moved notification. - * @throws Exception - */ - @Test - public void testAttachmentPointMovingBack() throws Exception { - IDeviceListener mockListener = - createMock(IDeviceListener.class); - expect(mockListener.getName()).andReturn("mockListener").atLeastOnce(); - expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) - .andReturn(false).atLeastOnce(); - expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) - .andReturn(false).atLeastOnce(); - - replay(mockListener); - deviceManager.addListener(mockListener); - verify(mockListener); - reset(mockListener); - - ITopologyService mockTopology = createMock(ITopologyService.class); - expect(mockTopology.getL2DomainId(1L)). - andReturn(1L).anyTimes(); - expect(mockTopology.getL2DomainId(5L)). - andReturn(1L).anyTimes(); - expect(mockTopology.isBroadcastDomainPort(anyLong(), anyShort())). - andReturn(false).anyTimes(); - expect(mockTopology.isInSameBroadcastDomain(anyLong(), anyShort(), - anyLong(), anyShort())) - .andReturn(false).anyTimes(); - - expect(mockTopology.isAttachmentPointPort(anyLong(), - anyShort())).andReturn(true).anyTimes(); - expect(mockTopology.isConsistent(1L, (short)1, 5L, (short)1)). - andReturn(false).anyTimes(); - - Date topologyUpdateTime = new Date(); - expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). - anyTimes(); - - replay(mockTopology); - - deviceManager.topology = mockTopology; - - Calendar c = Calendar.getInstance(); - Entity entity1 = new Entity(1L, null, null, 1L, 1, c.getTime()); - c.add(Calendar.SECOND, 1); - Entity entity2 = new Entity(1L, null, null, 5L, 1, c.getTime()); - c.add(Calendar.SECOND, 1); - Entity entity3 = new Entity(1L, null, null, 1L, 1, c.getTime()); - c.add(Calendar.SECOND, 1); - Entity entity4 = new Entity(1L, null, null, 5L, 1, c.getTime()); - - IDevice d; - SwitchPort[] aps; - - mockListener.deviceAdded(isA(IDevice.class)); - replay(mockListener); - - d = deviceManager.learnDeviceByEntity(entity1); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps); - verify(mockListener); - - reset(mockListener); - mockListener.deviceMoved((isA(IDevice.class))); - replay(mockListener); - - d = deviceManager.learnDeviceByEntity(entity2); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - - assertArrayEquals(new SwitchPort[] { new SwitchPort(5L, 1) }, aps); - verify(mockListener); - - reset(mockListener); - mockListener.deviceMoved((isA(IDevice.class))); - replay(mockListener); - - d = deviceManager.learnDeviceByEntity(entity3); - assertEquals(1, deviceManager.getAllDevices().size()); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), - new SwitchPort(5L, 1, ErrorStatus.DUPLICATE_DEVICE)}, - d.getAttachmentPoints(true)); - verify(mockListener); - - // Generate a packet-in again from 5,1 and ensure that it doesn't - // create a device moved event. - reset(mockListener); - replay(mockListener); - d = deviceManager.learnDeviceByEntity(entity4); - assertEquals(1, deviceManager.getAllDevices().size()); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), - new SwitchPort(5L, 1, ErrorStatus.DUPLICATE_DEVICE)}, - d.getAttachmentPoints(true)); - verify(mockListener); - } - - private void verifyEntityArray(Entity[] expected, Device d) { - Arrays.sort(expected); - assertArrayEquals(expected, d.entities); - } - - @Test - public void testNoLearningOnInternalPorts() throws Exception { - IDeviceListener mockListener = - createMock(IDeviceListener.class); - - expect(mockListener.getName()).andReturn("mockListener").anyTimes(); - expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) - .andReturn(false).atLeastOnce(); - expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) - .andReturn(false).atLeastOnce(); - - replay(mockListener); - deviceManager.addListener(mockListener); - verify(mockListener); - reset(mockListener); - - ITopologyService mockTopology = createMock(ITopologyService.class); - expect(mockTopology.getL2DomainId(1L)). - andReturn(1L).anyTimes(); - expect(mockTopology.getL2DomainId(2L)). - andReturn(1L).anyTimes(); - expect(mockTopology.getL2DomainId(3L)). - andReturn(1L).anyTimes(); - expect(mockTopology.getL2DomainId(4L)). - andReturn(1L).anyTimes(); - expect(mockTopology.isBroadcastDomainPort(anyLong(), anyShort())) - .andReturn(false).anyTimes(); - expect(mockTopology.isInSameBroadcastDomain(anyLong(), anyShort(), - anyLong(), anyShort())) - .andReturn(false).anyTimes(); - - expect(mockTopology.isAttachmentPointPort(or(eq(1L), eq(3L)), anyShort())) - .andReturn(true).anyTimes(); - // Switches 2 and 4 have only internal ports - expect(mockTopology.isAttachmentPointPort(or(eq(2L), eq(4L)), anyShort())) - .andReturn(false).anyTimes(); - - expect(mockTopology.isConsistent(1L, (short)1, 3L, (short)1)) - .andReturn(false).once(); - - Date topologyUpdateTime = new Date(); - expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). - anyTimes(); - - replay(mockTopology); - - deviceManager.topology = mockTopology; - - Calendar c = Calendar.getInstance(); - Entity entity1 = new Entity(1L, null, 1, 1L, 1, c.getTime()); - c.add(Calendar.SECOND, 1); - Entity entity2 = new Entity(1L, null, 2, 2L, 1, c.getTime()); - c.add(Calendar.SECOND, 1); - Entity entity3 = new Entity(1L, null, 3, 3L, 1, c.getTime()); - c.add(Calendar.SECOND, 1); - Entity entity4 = new Entity(1L, null, 4, 4L, 1, c.getTime()); - - IDevice d; - SwitchPort[] aps; - Integer[] ips; - - mockListener.deviceAdded(isA(IDevice.class)); - expectLastCall().once(); - replay(mockListener); - - // cannot learn device internal ports - d = deviceManager.learnDeviceByEntity(entity2); - assertNull(d); - d = deviceManager.learnDeviceByEntity(entity4); - assertNull(d); - - d = deviceManager.learnDeviceByEntity(entity1); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps); - verifyEntityArray(new Entity[] { entity1 } , (Device)d); - ips = d.getIPv4Addresses(); - assertArrayEquals(new Integer[] { 1 }, ips); - verify(mockListener); - - reset(mockListener); - replay(mockListener); - - // don't learn - d = deviceManager.learnDeviceByEntity(entity2); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps); - verifyEntityArray(new Entity[] { entity1 } , (Device)d); - ips = d.getIPv4Addresses(); - assertArrayEquals(new Integer[] { 1 }, ips); - verify(mockListener); - - reset(mockListener); - mockListener.deviceMoved(isA(IDevice.class)); - mockListener.deviceIPV4AddrChanged(isA(IDevice.class)); - replay(mockListener); - - // learn - d = deviceManager.learnDeviceByEntity(entity3); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(3L, 1) }, aps); - verifyEntityArray(new Entity[] { entity1, entity3 } , (Device)d); - ips = d.getIPv4Addresses(); - Arrays.sort(ips); - assertArrayEquals(new Integer[] { 1, 3 }, ips); - verify(mockListener); - - reset(mockListener); - replay(mockListener); - - // don't learn - d = deviceManager.learnDeviceByEntity(entity4); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(3L, 1) }, aps); - verifyEntityArray(new Entity[] { entity1, entity3 } , (Device)d); - ips = d.getIPv4Addresses(); - Arrays.sort(ips); - assertArrayEquals(new Integer[] { 1, 3 }, ips); - verify(mockListener); - } - - @Test - public void testAttachmentPointSuppression() throws Exception { - IDeviceListener mockListener = - createMock(IDeviceListener.class); - - expect(mockListener.getName()).andReturn("mockListener").anyTimes(); - expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) - .andReturn(false).atLeastOnce(); - expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) - .andReturn(false).atLeastOnce(); - - replay(mockListener); - deviceManager.addListener(mockListener); - verify(mockListener); - reset(mockListener); - - ITopologyService mockTopology = createMock(ITopologyService.class); - expect(mockTopology.getL2DomainId(1L)). - andReturn(1L).anyTimes(); - expect(mockTopology.getL2DomainId(5L)). - andReturn(1L).anyTimes(); - expect(mockTopology.getL2DomainId(10L)). - andReturn(10L).anyTimes(); - expect(mockTopology.getL2DomainId(50L)). - andReturn(10L).anyTimes(); - expect(mockTopology.isBroadcastDomainPort(anyLong(), anyShort())) - .andReturn(false).anyTimes(); - expect(mockTopology.isInSameBroadcastDomain(anyLong(), anyShort(), - anyLong(), anyShort())) - .andReturn(false).anyTimes(); - - expect(mockTopology.isAttachmentPointPort(anyLong(), anyShort())) - .andReturn(true).anyTimes(); - expect(mockTopology.isConsistent(5L, (short)1, 50L, (short)1)) - .andReturn(false).anyTimes(); - - Date topologyUpdateTime = new Date(); - expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). - anyTimes(); - - replay(mockTopology); - - deviceManager.topology = mockTopology; - // suppress (1L, 1) and (10L, 1) - deviceManager.addSuppressAPs(1L, (short)1); - deviceManager.addSuppressAPs(10L, (short)1); - - Calendar c = Calendar.getInstance(); - Entity entity0 = new Entity(1L, null, null, null, null, c.getTime()); - // No attachment point should be learnt on 1L, 1 - Entity entity1 = new Entity(1L, null, 1, 1L, 1, c.getTime()); - c.add(Calendar.SECOND, 1); - Entity entity2 = new Entity(1L, null, 1, 5L, 1, c.getTime()); - c.add(Calendar.SECOND, 1); - Entity entity3 = new Entity(1L, null, null, 10L, 1, c.getTime()); - c.add(Calendar.SECOND, 1); - Entity entity4 = new Entity(1L, null, null, 50L, 1, c.getTime()); - - IDevice d; - SwitchPort[] aps; - Integer[] ips; - - mockListener.deviceAdded(isA(IDevice.class)); - mockListener.deviceIPV4AddrChanged((isA(IDevice.class))); - replay(mockListener); - - // TODO: we currently do learn entities on suppressed APs - // // cannot learn device on suppressed AP - // d = deviceManager.learnDeviceByEntity(entity1); - // assertNull(d); - - deviceManager.learnDeviceByEntity(entity0); - d = deviceManager.learnDeviceByEntity(entity1); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertEquals(aps.length, 0); - verifyEntityArray(new Entity[] { entity0, entity1} , (Device)d); - ips = d.getIPv4Addresses(); - assertArrayEquals(new Integer[] { 1 }, ips); - verify(mockListener); - - reset(mockListener); - mockListener.deviceMoved((isA(IDevice.class))); - //mockListener.deviceIPV4AddrChanged((isA(IDevice.class))); - replay(mockListener); - d = deviceManager.learnDeviceByEntity(entity2); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(5L, 1) }, aps); - verifyEntityArray(new Entity[] { entity0, entity1, entity2 } , (Device)d); - ips = d.getIPv4Addresses(); - assertArrayEquals(new Integer[] { 1 }, ips); - verify(mockListener); - - reset(mockListener); - replay(mockListener); - - d = deviceManager.learnDeviceByEntity(entity3); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(5L, 1) }, aps); - verifyEntityArray(new Entity[] { entity0, entity1, entity2, entity3 } , (Device)d); - ips = d.getIPv4Addresses(); - assertArrayEquals(new Integer[] { 1 }, ips); - verify(mockListener); - - reset(mockListener); - mockListener.deviceMoved((isA(IDevice.class))); - replay(mockListener); - - d = deviceManager.learnDeviceByEntity(entity4); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(5L, 1), - new SwitchPort(50L, 1) }, aps); - verifyEntityArray(new Entity[] { entity0, entity1, entity2, entity3, entity4} , (Device)d); - ips = d.getIPv4Addresses(); - assertArrayEquals(new Integer[] { 1 }, ips); - verify(mockListener); - } - - @Test - public void testBDAttachmentPointLearning() throws Exception { - ITopologyService mockTopology = createMock(ITopologyService.class); - expect(mockTopology.getL2DomainId(anyLong())). - andReturn(1L).anyTimes(); - expect(mockTopology.isAttachmentPointPort(anyLong(), anyShort())). - andReturn(true).anyTimes(); - expect(mockTopology.isBroadcastDomainPort(1L, (short)1)). - andReturn(false).anyTimes(); - expect(mockTopology.isBroadcastDomainPort(1L, (short)2)). - andReturn(true).anyTimes(); - expect(mockTopology.isInSameBroadcastDomain(1L, (short)1, - 1L, (short)2)).andReturn(true).anyTimes(); - expect(mockTopology.isInSameBroadcastDomain(1L, (short)2, - 1L, (short)1)).andReturn(true).anyTimes(); - expect(mockTopology.isConsistent(anyLong(), anyShort(), anyLong(), anyShort())).andReturn(false).anyTimes(); - - Date topologyUpdateTime = new Date(); - expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). - anyTimes(); - - replay(mockTopology); - - deviceManager.topology = mockTopology; - - Calendar c = Calendar.getInstance(); - Entity entity1 = new Entity(1L, null, 1, 1L, 1, c.getTime()); - c.add(Calendar.MILLISECOND, - (int)AttachmentPoint.OPENFLOW_TO_EXTERNAL_TIMEOUT/ 2); - Entity entity2 = new Entity(1L, null, null, 1L, 2, c.getTime()); - c.add(Calendar.MILLISECOND, - (int)AttachmentPoint.OPENFLOW_TO_EXTERNAL_TIMEOUT / 2 + 1); - Entity entity3 = new Entity(1L, null, null, 1L, 2, c.getTime()); - - IDevice d; - SwitchPort[] aps; - - d = deviceManager.learnDeviceByEntity(entity1); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps); - - // this timestamp is too soon; don't switch - d = deviceManager.learnDeviceByEntity(entity2); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps); - - // it should switch when we learn with a timestamp after the - // timeout - d = deviceManager.learnDeviceByEntity(entity3); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 2) }, aps); - } - - /** - * This test verifies that the learning behavior on OFPP_LOCAL ports. - * Once a host is learned on OFPP_LOCAL, it is allowed to move only from - * one OFPP_LOCAL to another OFPP_LOCAL port. - * @throws Exception - */ - @Test - public void testLOCALAttachmentPointLearning() throws Exception { - ITopologyService mockTopology = createMock(ITopologyService.class); - expect(mockTopology.getL2DomainId(anyLong())). - andReturn(1L).anyTimes(); - expect(mockTopology.isAttachmentPointPort(anyLong(), anyShort())). - andReturn(true).anyTimes(); - expect(mockTopology.isBroadcastDomainPort(1L, (short)1)). - andReturn(false).anyTimes(); - expect(mockTopology.isBroadcastDomainPort(1L, OFPort.OFPP_LOCAL.getValue())). - andReturn(false).anyTimes(); - expect(mockTopology.isBroadcastDomainPort(1L, (short)2)). - andReturn(true).anyTimes(); - expect(mockTopology.isInSameBroadcastDomain(1L, (short)1, - 1L, OFPort.OFPP_LOCAL.getValue())).andReturn(true).anyTimes(); - expect(mockTopology.isInSameBroadcastDomain(1L, OFPort.OFPP_LOCAL.getValue(), - 1L, (short)2)).andReturn(true).anyTimes(); - expect(mockTopology.isInSameBroadcastDomain(1L, (short)2, - 1L, OFPort.OFPP_LOCAL.getValue())).andReturn(true).anyTimes(); - expect(mockTopology.isConsistent(anyLong(), anyShort(), anyLong(), anyShort())).andReturn(false).anyTimes(); - - Date topologyUpdateTime = new Date(); - expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). - anyTimes(); - - replay(mockTopology); - - deviceManager.topology = mockTopology; - - Calendar c = Calendar.getInstance(); - Entity entity1 = new Entity(1L, null, 1, 1L, 1, c.getTime()); - c.add(Calendar.MILLISECOND, - (int)AttachmentPoint.OPENFLOW_TO_EXTERNAL_TIMEOUT/ 2); - Entity entity2 = new Entity(1L, null, null, 1L, (int)OFPort.OFPP_LOCAL.getValue(), c.getTime()); - c.add(Calendar.MILLISECOND, - (int)AttachmentPoint.OPENFLOW_TO_EXTERNAL_TIMEOUT + 1); - Entity entity3 = new Entity(1L, null, null, 1L, 2, c.getTime()); - - IDevice d; - SwitchPort[] aps; - - d = deviceManager.learnDeviceByEntity(entity1); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, aps); - - // Ensure that the attachment point changes to OFPP_LOCAL - d = deviceManager.learnDeviceByEntity(entity2); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, OFPort.OFPP_LOCAL.getValue()) }, aps); - - // Even though the new attachment point is consistent with old - // and the time has elapsed, OFPP_LOCAL attachment point should - // be maintained. - d = deviceManager.learnDeviceByEntity(entity3); - assertEquals(1, deviceManager.getAllDevices().size()); - aps = d.getAttachmentPoints(); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, OFPort.OFPP_LOCAL.getValue()) }, aps); - } - - private static void - mockTopologyForPacketInTests(ITopologyService mockTopology) { - expect(mockTopology.isAttachmentPointPort(anyLong(), - anyShort())). - andReturn(true). - anyTimes(); - expect(mockTopology.isConsistent(EasyMock.anyLong(), - EasyMock.anyShort(), - EasyMock.anyLong(), - EasyMock.anyShort())).andReturn(false). - anyTimes(); - expect(mockTopology.isBroadcastDomainPort(EasyMock.anyLong(), - EasyMock.anyShort())) - .andReturn(false) - .anyTimes(); - expect(mockTopology.getL2DomainId(anyLong())).andReturn(1L).anyTimes(); - expect(mockTopology.isInSameBroadcastDomain(anyLong(), - anyShort(), - anyLong(), - anyShort())) - .andReturn(false).anyTimes(); - - } - - private Command dispatchPacketIn(long swId, OFPacketIn pi, - FloodlightContext cntx) { - IOFSwitch sw = mockFloodlightProvider.getSwitch(swId); - Ethernet eth = new Ethernet(); - eth.deserialize(pi.getPacketData(), 0, pi.getPacketData().length); - IFloodlightProviderService.bcStore.put(cntx, - IFloodlightProviderService.CONTEXT_PI_PAYLOAD, - eth); - return deviceManager.receive(sw, pi, cntx); - } - - /** - * Verify that the given device exactly matches the given fields. E.g., - * if ip is not null we expect the device to have exactly one IP address. - * swId and port are the attachment point port. - * Vlan and ip are optional all other fields must be specified. - * @return - */ - private static void verifyDevice(IDevice d, long mac, Short vlan, Integer ip, - long swId, int port) { - assertNotNull(d); - assertEquals(mac, d.getMACAddress()); - if (vlan == null) - assertArrayEquals(new Short[0], d.getVlanId()); - else - assertArrayEquals(new Short[] { vlan }, d.getVlanId()); - - if (ip == null) - assertArrayEquals(new Integer[0], d.getIPv4Addresses()); - else - assertArrayEquals(new Integer[] { ip }, d.getIPv4Addresses()); - - SwitchPort expectedAp = new SwitchPort(swId, port); - assertArrayEquals(new SwitchPort[] { expectedAp }, - d.getAttachmentPoints()); - } - - - @Test - public void testPacketInBasic() throws Exception { - byte[] deviceMac = - ((Ethernet)this.testARPReplyPacket_1).getSourceMACAddress(); - OFPacketIn packetIn = testARPReplyPacketIn_1; - Integer ipaddr = IPv4.toIPv4Address("192.168.1.1"); - - // Mock up our expected behavior - ITopologyService mockTopology = createMock(ITopologyService.class); - deviceManager.topology = mockTopology; - mockTopologyForPacketInTests(mockTopology); - replay(mockTopology); - - FloodlightContext cntx = new FloodlightContext(); - Command cmd = dispatchPacketIn(1L, packetIn, cntx); - verify(mockTopology); - assertEquals(Command.CONTINUE, cmd); - // Verify the device - Device rdevice = (Device) - deviceManager.findDevice(Ethernet.toLong(deviceMac), - (short)5, null, null, null); - verifyDevice(rdevice, Ethernet.toLong(deviceMac), - (short)5, ipaddr, 1L, 1); - IDevice cntxSrcDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_SRC_DEVICE); - assertEquals(rdevice, cntxSrcDev); - IDevice cntxDstDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_DST_DEVICE); - assertNull(cntxDstDev); - - Device result = null; - Iterator<? extends IDevice> dstiter = - deviceManager.queryDevices(null, null, ipaddr, - null, null); - if (dstiter.hasNext()) { - result = (Device)dstiter.next(); - } - assertFalse("There shouldn't be more than 1 device", dstiter.hasNext()); - assertEquals(rdevice, result); - - - //----------------- - // Test packetIn again with a different source port. Should be - // the same device - reset(mockTopology); - mockTopologyForPacketInTests(mockTopology); - replay(mockTopology); - - // trigger the packet in - cntx = new FloodlightContext(); - packetIn.setInPort((short)2); - cmd = dispatchPacketIn(5L, packetIn, cntx); - verify(mockTopology); - // Verify the replay matched our expectations - assertEquals(Command.CONTINUE, cmd); - - // Verify the device - rdevice = (Device) - deviceManager.findDevice(Ethernet.toLong(deviceMac), - (short)5, null, null, null); - verifyDevice(rdevice, Ethernet.toLong(deviceMac), - (short)5, ipaddr, 5L, 2); - cntxSrcDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_SRC_DEVICE); - assertEquals(rdevice, cntxSrcDev); - cntxDstDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_DST_DEVICE); - assertNull(cntxDstDev); - // There can be only one device - assertEquals(1, deviceManager.getAllDevices().size()); - - //---------------------------- - // Test packetIn with a different packet going the reverse direction. - // We should now get source and dest device in the context - //==> The destination device in this step has been learned just before - long srcMac = Ethernet.toLong(testUDPPacket.getSourceMACAddress()); - long dstMac = Ethernet.toLong(deviceMac); - reset(mockTopology); - mockTopologyForPacketInTests(mockTopology); - replay(mockTopology); - // trigger the packet in - cntx = new FloodlightContext(); - cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); - verify(mockTopology); - - assertEquals(Command.CONTINUE, cmd); - IDevice srcDev = - deviceManager.findDevice(srcMac, (short)5, null, null, null); - verifyDevice(srcDev, srcMac, (short)5, null, - 1L, testUDPPacketIn.getInPort()); - - IDevice dstDev = - deviceManager.findDevice(dstMac, (short)5, null, null, null); - verifyDevice(dstDev, dstMac, (short)5, ipaddr, 5L, 2); - - cntxSrcDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_SRC_DEVICE); - assertEquals(srcDev, cntxSrcDev); - - cntxDstDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_DST_DEVICE); - assertEquals(dstDev, cntxDstDev); - - assertEquals(2, deviceManager.getAllDevices().size()); - } - - /** - * This test ensures the device manager learns the source device - * corresponding to the senderHardwareAddress and senderProtocolAddress - * in an ARP response whenever the senderHardwareAddress is different - * from the source MAC address of the Ethernet frame. - * - * @throws Exception - */ - @Test - public void testDeviceLearningFromArpResponseData() throws Exception { - ARP arp = (ARP)((Ethernet)this.testARPReplyPacket_2).getPayload(); - long senderMac = Ethernet.toLong(arp.getSenderHardwareAddress()); - long sourceMac = - Ethernet.toLong(((Ethernet)this.testARPReplyPacket_2) - .getSourceMACAddress()); - Integer ipaddr = IPv4.toIPv4Address("192.168.1.1"); - OFPacketIn packetIn = testARPReplyPacketIn_2; - - // Mock up our expected behavior - ITopologyService mockTopology = createMock(ITopologyService.class); - deviceManager.topology = mockTopology; - mockTopologyForPacketInTests(mockTopology); - replay(mockTopology); - - - FloodlightContext cntx = new FloodlightContext(); - Command cmd = dispatchPacketIn(1L, packetIn, cntx); - verify(mockTopology); - assertEquals(Command.CONTINUE, cmd); - // Verify the device for the sender HW address - Device senderDev = (Device) - deviceManager.findDevice(senderMac, (short)5, null, null, null); - verifyDevice(senderDev, senderMac, (short)5, ipaddr, 1L, 1); - - Device result = null; - Iterator<? extends IDevice> dstiter = - deviceManager.queryDevices(null, null, ipaddr, - null, null); - if (dstiter.hasNext()) { - result = (Device)dstiter.next(); - } - assertFalse("There shouldn't be more than 1 device", dstiter.hasNext()); - assertEquals(senderDev, result); - - - - // Verify the device for the source MAC - Device srcDev = (Device) - deviceManager.findDevice(sourceMac, (short)5, null, null, null); - // must NOT learn IP on this device - verifyDevice(srcDev, sourceMac, (short)5, null, 1L, 1); - assertFalse("Device must differ", srcDev.equals(senderDev)); - // Context is annotated with this device, not the device associated - // with ARP sender address - IDevice cntxSrcDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_SRC_DEVICE); - assertEquals(srcDev, cntxSrcDev); - - assertEquals(2, deviceManager.getAllDevices().size()); - } - - - @Test - public void testPacketInInvalidSrcMac() throws Exception { - // Mock up our expected behavior - ITopologyService mockTopology = createMock(ITopologyService.class); - deviceManager.topology = mockTopology; - mockTopologyForPacketInTests(mockTopology); - replay(mockTopology); - FloodlightContext cntx = new FloodlightContext(); - - testUDPPacket.setSourceMACAddress(Ethernet.toByteArray(0L)); - updateUDPPacketIn(); - Command cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); - assertEquals(Command.STOP, cmd); - IDevice cntxSrcDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_SRC_DEVICE); - assertNull(cntxSrcDev); - IDevice cntxDstDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_DST_DEVICE); - assertNull(cntxDstDev); - - testUDPPacket.setSourceMACAddress(Ethernet.toByteArray(-1L)); - updateUDPPacketIn(); - cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); - assertEquals(Command.STOP, cmd); - cntxSrcDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_SRC_DEVICE); - assertNull(cntxSrcDev); - cntxDstDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_DST_DEVICE); - assertNull(cntxDstDev); - - // MAC with only the multicast bit set - testUDPPacket.setSourceMACAddress(new byte[] { 1, 0, 0, 0, 0, 0 }); - updateUDPPacketIn(); - cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); - assertEquals(Command.STOP, cmd); - cntxSrcDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_SRC_DEVICE); - assertNull(cntxSrcDev); - cntxDstDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_DST_DEVICE); - assertNull(cntxDstDev); - - // Now use a real MAC. We should get a src device - testUDPPacket.setSourceMACAddress(Ethernet.toByteArray(1L)); - updateUDPPacketIn(); - cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); - assertEquals(Command.CONTINUE, cmd); - cntxSrcDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_SRC_DEVICE); - verifyDevice(cntxSrcDev, 1L, (short)5, null, - 1L, testUDPPacketIn.getInPort()); - - cntxDstDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_DST_DEVICE); - assertNull(cntxDstDev); - verify(mockTopology); - } - - - @Test - public void testPacketInInvalidDstMac() throws Exception { - // Mock up our expected behavior - ITopologyService mockTopology = createMock(ITopologyService.class); - deviceManager.topology = mockTopology; - mockTopologyForPacketInTests(mockTopology); - replay(mockTopology); - FloodlightContext cntx = new FloodlightContext(); - - long srcMac = Ethernet.toLong(testUDPPacket.getSourceMACAddress()); - long dstMac = Ethernet.toLong(testUDPPacket.getDestinationMACAddress()); - - // Prime device manager with the source device - Command cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); - assertEquals(Command.CONTINUE, cmd); - IDevice cntxSrcDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_SRC_DEVICE); - verifyDevice(cntxSrcDev, srcMac, (short)5, null, - 1L, testUDPPacketIn.getInPort()); - IDevice cntxDstDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_DST_DEVICE); - assertNull(cntxDstDev); - IDevice expectedSrcDev = cntxSrcDev; - - // Create a device for the destination. We can use testARPPacketIn_1 - // for that. - cntx = new FloodlightContext(); - // Prime device manager with the source device - cmd = dispatchPacketIn(1L, testARPReplyPacketIn_1, cntx); - assertEquals(Command.CONTINUE, cmd); - cntxSrcDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_SRC_DEVICE); - // yes: we check that cntxSrcDev matched dstMAC because we are - // just adding the dest device - int ip = IPv4.toIPv4Address("192.168.1.1"); - verifyDevice(cntxSrcDev, dstMac, (short)5, ip, - 1L, testARPReplyPacketIn_1.getInPort()); - // yes: we set the expected dst device to the current srcDev - IDevice expectedDstDev = cntxSrcDev; - - //------------------------------- - // Let the real tests begin - - cntx = new FloodlightContext(); - testUDPPacket.setDestinationMACAddress(Ethernet.toByteArray(0L)); - updateUDPPacketIn(); - cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); - assertEquals(Command.STOP, cmd); - cntxDstDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_DST_DEVICE); - assertNull(cntxDstDev); - - // use a real dest mac - cntx = new FloodlightContext(); - testUDPPacket.setDestinationMACAddress(Ethernet.toByteArray(dstMac)); - updateUDPPacketIn(); - cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); - assertEquals(Command.CONTINUE, cmd); - cntxSrcDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_SRC_DEVICE); - assertEquals(expectedSrcDev, cntxSrcDev); - cntxDstDev = IDeviceService.fcStore.get(cntx, - IDeviceService.CONTEXT_DST_DEVICE); - assertEquals(expectedDstDev, cntxDstDev); - - verify(mockTopology); - } - - /** - * Note: Entity expiration does not result in device moved notification. - * @throws Exception - */ - public void doTestEntityExpiration() throws Exception { - IDeviceListener mockListener = - createMock(IDeviceListener.class); - expect(mockListener.getName()).andReturn("mockListener").anyTimes(); - expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) - .andReturn(false).atLeastOnce(); - expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) - .andReturn(false).atLeastOnce(); - - ITopologyService mockTopology = createMock(ITopologyService.class); - expect(mockTopology.isAttachmentPointPort(anyLong(), - anyShort())). - andReturn(true).anyTimes(); - - expect(mockTopology.isBroadcastDomainPort(1L, (short)1)).andReturn(false).anyTimes(); - expect(mockTopology.isBroadcastDomainPort(5L, (short)1)).andReturn(false).anyTimes(); - expect(mockTopology.getL2DomainId(1L)).andReturn(1L).anyTimes(); - expect(mockTopology.getL2DomainId(5L)).andReturn(5L).anyTimes(); - expect(mockTopology.isConsistent(1L, (short)1, 5L, (short)1)). - andReturn(false).anyTimes(); - - Date topologyUpdateTime = new Date(); - expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). - anyTimes(); - - replay(mockTopology); - deviceManager.topology = mockTopology; - - Calendar c = Calendar.getInstance(); - Entity entity1 = new Entity(1L, null, 2, 1L, 1, c.getTime()); - c.add(Calendar.MILLISECOND, -DeviceManagerImpl.ENTITY_TIMEOUT-1); - Entity entity2 = new Entity(1L, null, 1, 5L, 1, c.getTime()); - - deviceManager.learnDeviceByEntity(entity1); - IDevice d = deviceManager.learnDeviceByEntity(entity2); - assertArrayEquals(new Integer[] { 1, 2 }, d.getIPv4Addresses()); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), - new SwitchPort(5L, 1)}, - d.getAttachmentPoints()); - Iterator<? extends IDevice> diter = - deviceManager.queryClassDevices(d.getEntityClass(), - null, null, 1, null, null); - assertTrue(diter.hasNext()); - assertEquals(d.getDeviceKey(), diter.next().getDeviceKey()); - diter = deviceManager.queryClassDevices(d.getEntityClass(), - null, null, 2, null, null); - assertTrue(diter.hasNext()); - assertEquals(d.getDeviceKey(), diter.next().getDeviceKey()); - - replay(mockListener); - deviceManager.addListener(mockListener); - verify(mockListener); - reset(mockListener); - - mockListener.deviceIPV4AddrChanged(isA(IDevice.class)); - replay(mockListener); - deviceManager.entityCleanupTask.reschedule(0, null); - - d = deviceManager.getDevice(d.getDeviceKey()); - assertArrayEquals(new Integer[] { 2 }, d.getIPv4Addresses()); - - // Attachment points are not removed, previous ones are still valid. - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), - new SwitchPort(5L, 1) }, - d.getAttachmentPoints()); - diter = deviceManager.queryClassDevices(d.getEntityClass(), - null, null, 2, null, null); - assertTrue(diter.hasNext()); - assertEquals(d.getDeviceKey(), diter.next().getDeviceKey()); - diter = deviceManager.queryClassDevices(d.getEntityClass(), - null, null, 1, null, null); - assertFalse(diter.hasNext()); - - d = deviceManager.findDevice(1L, null, null, null, null); - assertArrayEquals(new Integer[] { 2 }, d.getIPv4Addresses()); - - // Attachment points are not removed, previous ones are still valid. - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), - new SwitchPort(5L, 1) }, - d.getAttachmentPoints()); - - verify(mockListener); - } - - public void doTestDeviceExpiration() throws Exception { - IDeviceListener mockListener = - createMock(IDeviceListener.class); - expect(mockListener.getName()).andReturn("mockListener").anyTimes(); - expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) - .andReturn(false).atLeastOnce(); - expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) - .andReturn(false).atLeastOnce(); - - Calendar c = Calendar.getInstance(); - c.add(Calendar.MILLISECOND, -DeviceManagerImpl.ENTITY_TIMEOUT-1); - Entity entity1 = new Entity(1L, null, 1, 1L, 1, c.getTime()); - Entity entity2 = new Entity(1L, null, 2, 5L, 1, c.getTime()); - - ITopologyService mockTopology = createMock(ITopologyService.class); - deviceManager.topology = mockTopology; - - expect(mockTopology.isAttachmentPointPort(EasyMock.anyLong(), - EasyMock.anyShort())). - andReturn(true). - anyTimes(); - expect(mockTopology.getL2DomainId(1L)).andReturn(1L).anyTimes(); - expect(mockTopology.getL2DomainId(5L)).andReturn(1L).anyTimes(); - expect(mockTopology.isConsistent(EasyMock.anyLong(), - EasyMock.anyShort(), - EasyMock.anyLong(), - EasyMock.anyShort())).andReturn(false). - anyTimes(); - expect(mockTopology.isBroadcastDomainPort(EasyMock.anyLong(), - EasyMock.anyShort())). - andReturn(false).anyTimes(); - replay(mockTopology); - - IDevice d = deviceManager.learnDeviceByEntity(entity2); - d = deviceManager.learnDeviceByEntity(entity1); - assertArrayEquals(new Integer[] { 1, 2 }, d.getIPv4Addresses()); - - replay(mockListener); - deviceManager.addListener(mockListener); - verify(mockListener); - reset(mockListener); - - mockListener.deviceRemoved(isA(IDevice.class)); - replay(mockListener); - deviceManager.entityCleanupTask.reschedule(0, null); - - IDevice r = deviceManager.getDevice(d.getDeviceKey()); - assertNull(r); - Iterator<? extends IDevice> diter = - deviceManager.queryClassDevices(d.getEntityClass(), - null, null, 1, null, null); - assertFalse(diter.hasNext()); - - r = deviceManager.findDevice(1L, null, null, null, null); - assertNull(r); - - verify(mockListener); - } - - /* - * A ConcurrentHashMap for devices (deviceMap) that can be used to test - * code that specially handles concurrent modification situations. In - * particular, we overwrite values() and will replace / remove all the - * elements returned by values. - * - * The remove flag in the constructor specifies if devices returned by - * values() should be removed or replaced. - */ - protected static class ConcurrentlyModifiedDeviceMap - extends ConcurrentHashMap<Long, Device> { - private static final long serialVersionUID = 7784938535441180562L; - protected boolean remove; - public ConcurrentlyModifiedDeviceMap(boolean remove) { - super(); - this.remove = remove; - } - - @Override - public Collection<Device> values() { - // Get the values from the real map and copy them since - // the collection returned by values can reflect changed - Collection<Device> devs = new ArrayList<Device>(super.values()); - for (Device d: devs) { - if (remove) { - // We remove the device from the underlying map - super.remove(d.getDeviceKey()); - } else { - super.remove(d.getDeviceKey()); - // We add a different Device instance with the same - // key to the map. We'll do some hackery so the device - // is different enough to compare differently in equals - // but otherwise looks the same. - // It's ugly but it works. - // clone entities - Device newDevice = d; - for (Entity e: d.getEntities()) { - Entity newEntity = new Entity (e.macAddress, - e.vlan, - e.ipv4Address, - e.switchDPID, - e.switchPort, - e.lastSeenTimestamp); - if (e.vlan == null) - newEntity.vlan = (short)1; - else - newEntity.vlan = (short)((e.vlan + 1 % 4095)+1); - newDevice = new Device(newDevice, newEntity, -1); - } - assertEquals(false, newDevice.equals(d)); - super.put(newDevice.getDeviceKey(), newDevice); - } - } - return devs; - } - } - - @Test - public void testEntityExpiration() throws Exception { - doTestEntityExpiration(); - } - - @Test - public void testDeviceExpiration() throws Exception { - doTestDeviceExpiration(); - } - - /* Test correct entity cleanup behavior when a concurrent modification - * occurs. - */ - @Test - public void testEntityExpirationConcurrentModification() throws Exception { - deviceManager.deviceMap = new ConcurrentlyModifiedDeviceMap(false); - doTestEntityExpiration(); - } - - /* Test correct entity cleanup behavior when a concurrent remove - * occurs. - */ - @Test - public void testDeviceExpirationConcurrentRemove() throws Exception { - deviceManager.deviceMap = new ConcurrentlyModifiedDeviceMap(true); - doTestDeviceExpiration(); - } - - /* Test correct entity cleanup behavior when a concurrent modification - * occurs. - */ - @Test - public void testDeviceExpirationConcurrentModification() throws Exception { - deviceManager.deviceMap = new ConcurrentlyModifiedDeviceMap(false); - doTestDeviceExpiration(); - } - - - @Test - public void testAttachmentPointFlapping() throws Exception { - Calendar c = Calendar.getInstance(); - - ITopologyService mockTopology = createMock(ITopologyService.class); - expect(mockTopology.isAttachmentPointPort(anyLong(), - anyShort())).andReturn(true).anyTimes(); - expect(mockTopology.isBroadcastDomainPort(anyLong(), - anyShort())). - andReturn(false).anyTimes(); - expect(mockTopology.isInSameBroadcastDomain(anyLong(), anyShort(), - anyLong(), anyShort())).andReturn(false).anyTimes(); - expect(mockTopology.getL2DomainId(anyLong())). - andReturn(1L).anyTimes(); - expect(mockTopology.isConsistent(1L, (short)1, 1L, (short)1)). - andReturn(true).anyTimes(); - expect(mockTopology.isConsistent(1L, (short)1, 5L, (short)1)). - andReturn(false).anyTimes(); - expect(mockTopology.isConsistent(1L, (short)1, 10L, (short)1)). - andReturn(false).anyTimes(); - expect(mockTopology.isConsistent(5L, (short)1, 10L, (short)1)). - andReturn(false).anyTimes(); - expect(mockTopology.isConsistent(10L, (short)1, 1L, (short)1)). - andReturn(false).anyTimes(); - expect(mockTopology.isConsistent(5L, (short)1, 1L, (short)1)). - andReturn(false).anyTimes(); - expect(mockTopology.isConsistent(10L, (short)1, 5L, (short)1)). - andReturn(false).anyTimes(); - - Date topologyUpdateTime = new Date(); - expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). - anyTimes(); - - - replay(mockTopology); - deviceManager.topology = mockTopology; - - Entity entity1 = new Entity(1L, null, null, 1L, 1, c.getTime()); - Entity entity1a = new Entity(1L, null, 1, 1L, 1, c.getTime()); - Entity entity2 = new Entity(1L, null, null, 5L, 1, c.getTime()); - Entity entity3 = new Entity(1L, null, null, 10L, 1, c.getTime()); - entity1.setLastSeenTimestamp(c.getTime()); - c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT/2); - entity1a.setLastSeenTimestamp(c.getTime()); - c.add(Calendar.MILLISECOND, 1); - entity2.setLastSeenTimestamp(c.getTime()); - c.add(Calendar.MILLISECOND, 1); - entity3.setLastSeenTimestamp(c.getTime()); - - - - IDevice d; - d = deviceManager.learnDeviceByEntity(entity1); - d = deviceManager.learnDeviceByEntity(entity1a); - d = deviceManager.learnDeviceByEntity(entity2); - d = deviceManager.learnDeviceByEntity(entity3); - - // all entities are active, so entity3 should win - assertArrayEquals(new SwitchPort[] { new SwitchPort(10L, 1) }, - d.getAttachmentPoints()); - - assertArrayEquals(new SwitchPort[] { new SwitchPort(10L, 1),}, - d.getAttachmentPoints(true)); - - c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT/4); - entity1.setLastSeenTimestamp(c.getTime()); - d = deviceManager.learnDeviceByEntity(entity1); - - // all are still active; entity3 should still win - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, - d.getAttachmentPoints()); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), - new SwitchPort(5L, 1, - ErrorStatus.DUPLICATE_DEVICE), - new SwitchPort(10L, 1, - ErrorStatus.DUPLICATE_DEVICE) }, - d.getAttachmentPoints(true)); - - c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT+2000); - entity1.setLastSeenTimestamp(c.getTime()); - d = deviceManager.learnDeviceByEntity(entity1); - - assertEquals(entity1.getActiveSince(), entity1.getLastSeenTimestamp()); - // entity1 should now be the only active entity - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, - d.getAttachmentPoints()); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1) }, - d.getAttachmentPoints(true)); - } - - - @Test - public void testAttachmentPointFlappingTwoCluster() throws Exception { - Calendar c = Calendar.getInstance(); - - ITopologyService mockTopology = createMock(ITopologyService.class); - expect(mockTopology.isAttachmentPointPort(anyLong(), - anyShort())).andReturn(true).anyTimes(); - expect(mockTopology.isBroadcastDomainPort(anyLong(), - anyShort())). - andReturn(false).anyTimes(); - expect(mockTopology.isInSameBroadcastDomain(anyLong(), anyShort(), - anyLong(), anyShort())).andReturn(false).anyTimes(); - expect(mockTopology.getL2DomainId(1L)). - andReturn(1L).anyTimes(); - expect(mockTopology.getL2DomainId(5L)). - andReturn(5L).anyTimes(); - expect(mockTopology.isConsistent(1L, (short)1, 1L, (short)2)). - andReturn(false).anyTimes(); - expect(mockTopology.isConsistent(1L, (short)2, 5L, (short)1)). - andReturn(false).anyTimes(); - expect(mockTopology.isConsistent(5L, (short)1, 5L, (short)2)). - andReturn(false).anyTimes(); - expect(mockTopology.isConsistent(1L, (short)2, 1L, (short)1)). - andReturn(false).anyTimes(); - expect(mockTopology.isConsistent(1L, (short)1, 5L, (short)1)). - andReturn(false).anyTimes(); - expect(mockTopology.isConsistent(1L, (short)1, 5L, (short)2)). - andReturn(false).anyTimes(); - expect(mockTopology.isConsistent(5L, (short)2, 5L, (short)1)). - andReturn(false).anyTimes(); - - Date topologyUpdateTime = new Date(); - expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). - anyTimes(); - - replay(mockTopology); - deviceManager.topology = mockTopology; - - Entity entity1 = new Entity(1L, null, null, 1L, 1, c.getTime()); - Entity entity2 = new Entity(1L, null, null, 1L, 2, c.getTime()); - Entity entity3 = new Entity(1L, null, null, 5L, 1, c.getTime()); - Entity entity4 = new Entity(1L, null, null, 5L, 2, c.getTime()); - entity1.setLastSeenTimestamp(c.getTime()); - c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT/2); - c.add(Calendar.MILLISECOND, 1); - entity2.setLastSeenTimestamp(c.getTime()); - c.add(Calendar.MILLISECOND, 1); - entity3.setLastSeenTimestamp(c.getTime()); - c.add(Calendar.MILLISECOND, 1); - entity4.setLastSeenTimestamp(c.getTime()); - - deviceManager.learnDeviceByEntity(entity1); - deviceManager.learnDeviceByEntity(entity2); - deviceManager.learnDeviceByEntity(entity3); - IDevice d = deviceManager.learnDeviceByEntity(entity4); - - // all entities are active, so entities 2,4 should win - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 2), - new SwitchPort(5L, 2) }, - d.getAttachmentPoints()); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 2), - new SwitchPort(5L, 2)}, - d.getAttachmentPoints(true)); - - c.add(Calendar.MILLISECOND, 1); - entity1.setLastSeenTimestamp(c.getTime()); - d = deviceManager.learnDeviceByEntity(entity1); - - // all entities are active, so entities 2,4 should win - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), - new SwitchPort(5L, 2) }, - d.getAttachmentPoints()); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), - new SwitchPort(5L, 2), - new SwitchPort(1L, 2, ErrorStatus.DUPLICATE_DEVICE)}, - d.getAttachmentPoints(true)); - - c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT+1); - entity1.setLastSeenTimestamp(c.getTime()); - d = deviceManager.learnDeviceByEntity(entity1); - - // entities 3,4 are still in conflict, but 1 should be resolved - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), - new SwitchPort(5L, 2) }, - d.getAttachmentPoints()); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), - new SwitchPort(5L, 2)}, - d.getAttachmentPoints(true)); - - entity3.setLastSeenTimestamp(c.getTime()); - d = deviceManager.learnDeviceByEntity(entity3); - - // no conflicts, 1 and 3 will win - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), - new SwitchPort(5L, 1) }, - d.getAttachmentPoints()); - assertArrayEquals(new SwitchPort[] { new SwitchPort(1L, 1), - new SwitchPort(5L, 1) }, - d.getAttachmentPoints(true)); - - } - - protected void doTestDeviceQuery() throws Exception { - Entity entity1 = new Entity(1L, (short)1, 1, 1L, 1, new Date()); - Entity entity2 = new Entity(2L, (short)2, 2, 1L, 2, new Date()); - Entity entity3 = new Entity(3L, (short)3, 3, 5L, 1, new Date()); - Entity entity4 = new Entity(4L, (short)4, 3, 5L, 2, new Date()); - Entity entity5 = new Entity(1L, (short)4, 3, 5L, 2, new Date()); - - Device d1 = deviceManager.learnDeviceByEntity(entity1); - deviceManager.learnDeviceByEntity(entity2); - Device d3 = deviceManager.learnDeviceByEntity(entity3); - Device d4 = deviceManager.learnDeviceByEntity(entity4); - - IDevice d; - - Iterator<? extends IDevice> iter = - deviceManager.queryDevices(null, (short)1, 1, null, null); - int count = 0; - while (iter.hasNext()) { - count += 1; - d = iter.next(); - assertEquals(d1.getDeviceKey(), d.getDeviceKey()); - } - assertEquals(1, count); - - iter = deviceManager.queryDevices(null, (short)3, 3, null, null); - count = 0; - while (iter.hasNext()) { - count += 1; - d = iter.next(); - assertEquals(d3.getDeviceKey(), d.getDeviceKey()); - } - assertEquals(1, count); - - iter = deviceManager.queryDevices(null, (short)1, 3, null, null); - count = 0; - while (iter.hasNext()) { - count += 1; - iter.next(); - } - assertEquals(0, count); - - Device d5 = deviceManager.learnDeviceByEntity(entity5); - iter = deviceManager.queryDevices(null, (short)4, 3, null, null); - count = 0; - Set<Long> deviceKeysFromIterator = new HashSet<Long>(); - while (iter.hasNext()) { - count += 1; - d = iter.next(); - deviceKeysFromIterator.add(d.getDeviceKey()); - } - Set<Long> expectedDeviceKeys = new HashSet<Long>(); - expectedDeviceKeys.add(d4.getDeviceKey()); - expectedDeviceKeys.add(d5.getDeviceKey()); - assertEquals(expectedDeviceKeys, deviceKeysFromIterator); - assertEquals(2, count); - - - iter = deviceManager.queryDevices(1L, null, null, null, null); - count = 0; - deviceKeysFromIterator = new HashSet<Long>(); - while (iter.hasNext()) { - count += 1; - d = iter.next(); - deviceKeysFromIterator.add(d.getDeviceKey()); - } - expectedDeviceKeys = new HashSet<Long>(); - expectedDeviceKeys.add(d1.getDeviceKey()); - expectedDeviceKeys.add(d5.getDeviceKey()); - assertEquals(expectedDeviceKeys, deviceKeysFromIterator); - assertEquals(2, count); - } - - @Test - public void testDeviceIndex() throws Exception { - EnumSet<IDeviceService.DeviceField> indexFields = - EnumSet.noneOf(IDeviceService.DeviceField.class); - indexFields.add(IDeviceService.DeviceField.IPV4); - indexFields.add(IDeviceService.DeviceField.VLAN); - deviceManager.addIndex(false, indexFields); - - indexFields = EnumSet.noneOf(IDeviceService.DeviceField.class); - deviceManager.addIndex(false, indexFields); - - ITopologyService mockTopology = createMock(ITopologyService.class); - deviceManager.topology = mockTopology; - expect(mockTopology.isAttachmentPointPort(anyLong(), - anyShort())). - andReturn(true).anyTimes(); - expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes(); - replay(mockTopology); - doTestDeviceQuery(); - } - - @Test - public void testDeviceQuery() throws Exception { - ITopologyService mockTopology = createMock(ITopologyService.class); - deviceManager.topology = mockTopology; - expect(mockTopology.isAttachmentPointPort(anyLong(), - anyShort())). - andReturn(true).anyTimes(); - expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes(); - replay(mockTopology); - - doTestDeviceQuery(); - } - - protected void doTestDeviceClassQuery() throws Exception { - Entity entity1 = new Entity(1L, (short)1, 1, 1L, 1, new Date()); - Entity entity2 = new Entity(2L, (short)2, 2, 1L, 2, new Date()); - Entity entity3 = new Entity(3L, (short)3, 3, 5L, 1, new Date()); - Entity entity4 = new Entity(4L, (short)4, 3, 5L, 2, new Date()); - Entity entity5 = new Entity(1L, (short)4, 3, 5L, 2, new Date()); - - IDevice d1 = deviceManager.learnDeviceByEntity(entity1); - IDevice d2 = deviceManager.learnDeviceByEntity(entity2); - IDevice d3 = deviceManager.learnDeviceByEntity(entity3); - IDevice d4 = deviceManager.learnDeviceByEntity(entity4); - assertEquals(d1.getEntityClass(), d2.getEntityClass()); - assertEquals(d1.getEntityClass(), d3.getEntityClass()); - assertEquals(d1.getEntityClass(), d4.getEntityClass()); - - IDevice d; - - Iterator<? extends IDevice> iter = - deviceManager.queryClassDevices(d1.getEntityClass(), null, - (short)1, 1, null, null); - int count = 0; - while (iter.hasNext()) { - count += 1; - d = iter.next(); - assertEquals(d1.getDeviceKey(), d.getDeviceKey()); - } - assertEquals(1, count); - - iter = deviceManager.queryClassDevices(d1.getEntityClass(), null, - (short)3, 3, null, null); - count = 0; - while (iter.hasNext()) { - count += 1; - d = iter.next(); - assertEquals(d3.getDeviceKey(), d.getDeviceKey()); - - } - assertEquals(1, count); - - iter = deviceManager.queryClassDevices(d1.getEntityClass(), null, - (short)1, 3, null, null); - count = 0; - while (iter.hasNext()) { - count += 1; - iter.next(); - } - assertEquals(0, count); - - IDevice d5 = deviceManager.learnDeviceByEntity(entity5); - assertEquals(d1.getEntityClass(), d5.getEntityClass()); - iter = deviceManager.queryClassDevices(d1.getEntityClass(), null, - (short)4, 3, null, null); - count = 0; - Set<Long> deviceKeysFromIterator = new HashSet<Long>(); - while (iter.hasNext()) { - count += 1; - d = iter.next(); - deviceKeysFromIterator.add(d.getDeviceKey()); - } - Set<Long> expectedDeviceKeys = new HashSet<Long>(); - expectedDeviceKeys.add(d4.getDeviceKey()); - expectedDeviceKeys.add(d5.getDeviceKey()); - assertEquals(expectedDeviceKeys, deviceKeysFromIterator); - assertEquals(2, count); - } - - @Test - public void testDeviceClassIndex() throws Exception { - EnumSet<IDeviceService.DeviceField> indexFields = - EnumSet.noneOf(IDeviceService.DeviceField.class); - indexFields.add(IDeviceService.DeviceField.IPV4); - indexFields.add(IDeviceService.DeviceField.VLAN); - deviceManager.addIndex(true, indexFields); - - ITopologyService mockTopology = createMock(ITopologyService.class); - deviceManager.topology = mockTopology; - expect(mockTopology.isAttachmentPointPort(anyLong(), - anyShort())). - andReturn(true).anyTimes(); - expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes(); - replay(mockTopology); - - doTestDeviceClassQuery(); - } - - @Test - public void testDeviceClassQuery() throws Exception { - ITopologyService mockTopology = createMock(ITopologyService.class); - deviceManager.topology = mockTopology; - expect(mockTopology.isAttachmentPointPort(anyLong(), - anyShort())). - andReturn(true).anyTimes(); - expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes(); - replay(mockTopology); - - doTestDeviceClassQuery(); - } - - @Test - public void testFindDevice() throws FloodlightModuleException { - boolean exceptionCaught; - deviceManager.entityClassifier= new MockEntityClassifierMac(); - deviceManager.startUp(null); - - ITopologyService mockTopology = createMock(ITopologyService.class); - deviceManager.topology = mockTopology; - expect(mockTopology.isAttachmentPointPort(anyLong(), - anyShort())). - andReturn(true).anyTimes(); - expect(mockTopology.getL2DomainId(EasyMock.anyLong())).andReturn(1L).anyTimes(); - replay(mockTopology); - - Entity entity1 = new Entity(1L, (short)1, 1, 1L, 1, new Date()); - Entity entity2 = new Entity(2L, (short)2, 2, 1L, 2, new Date()); - Entity entity2b = new Entity(22L, (short)2, 2, 1L, 2, new Date()); - - Entity entity3 = new Entity(3L, (short)1, 3, 2L, 1, new Date()); - Entity entity4 = new Entity(4L, (short)2, 4, 2L, 2, new Date()); - - Entity entity5 = new Entity(5L, (short)1, 5, 3L, 1, new Date()); - - - IDevice d1 = deviceManager.learnDeviceByEntity(entity1); - IDevice d2 = deviceManager.learnDeviceByEntity(entity2); - IDevice d3 = deviceManager.learnDeviceByEntity(entity3); - IDevice d4 = deviceManager.learnDeviceByEntity(entity4); - IDevice d5 = deviceManager.learnDeviceByEntity(entity5); - - // Make sure the entity classifier worked as expected - assertEquals(MockEntityClassifierMac.testECMac1, d1.getEntityClass()); - assertEquals(MockEntityClassifierMac.testECMac1, d2.getEntityClass()); - assertEquals(MockEntityClassifierMac.testECMac2, d3.getEntityClass()); - assertEquals(MockEntityClassifierMac.testECMac2, d4.getEntityClass()); - assertEquals(DefaultEntityClassifier.entityClass, - d5.getEntityClass()); - - // Look up the device using findDevice() which uses only the primary - // index - assertEquals(d1, deviceManager.findDevice(entity1.getMacAddress(), - entity1.getVlan(), - entity1.getIpv4Address(), - entity1.getSwitchDPID(), - entity1.getSwitchPort())); - // port changed. Device will be found through class index - assertEquals(d1, deviceManager.findDevice(entity1.getMacAddress(), - entity1.getVlan(), - entity1.getIpv4Address(), - entity1.getSwitchDPID(), - entity1.getSwitchPort()+1)); - // VLAN changed. No device matches - assertEquals(null, deviceManager.findDevice(entity1.getMacAddress(), - (short)42, - entity1.getIpv4Address(), - entity1.getSwitchDPID(), - entity1.getSwitchPort())); - assertEquals(null, deviceManager.findDevice(entity1.getMacAddress(), - null, - entity1.getIpv4Address(), - entity1.getSwitchDPID(), - entity1.getSwitchPort())); - assertEquals(d2, deviceManager.findDeviceByEntity(entity2)); - assertEquals(null, deviceManager.findDeviceByEntity(entity2b)); - assertEquals(d3, deviceManager.findDevice(entity3.getMacAddress(), - entity3.getVlan(), - entity3.getIpv4Address(), - entity3.getSwitchDPID(), - entity3.getSwitchPort())); - // switch and port not set. throws exception - exceptionCaught = false; - try { - assertEquals(null, deviceManager.findDevice(entity3.getMacAddress(), - entity3.getVlan(), - entity3.getIpv4Address(), - null, - null)); - } - catch (IllegalArgumentException e) { - exceptionCaught = true; - } - if (!exceptionCaught) - fail("findDevice() did not throw IllegalArgumentException"); - assertEquals(d4, deviceManager.findDeviceByEntity(entity4)); - assertEquals(d5, deviceManager.findDevice(entity5.getMacAddress(), - entity5.getVlan(), - entity5.getIpv4Address(), - entity5.getSwitchDPID(), - entity5.getSwitchPort())); - // switch and port not set. throws exception (swith/port are key - // fields of IEntityClassifier but not d5.entityClass - exceptionCaught = false; - try { - assertEquals(d5, deviceManager.findDevice(entity5.getMacAddress(), - entity5.getVlan(), - entity5.getIpv4Address(), - null, - null)); - } - catch (IllegalArgumentException e) { - exceptionCaught = true; - } - if (!exceptionCaught) - fail("findDevice() did not throw IllegalArgumentException"); - - - Entity entityNoClass = new Entity(5L, (short)1, 5, -1L, 1, new Date()); - assertEquals(null, deviceManager.findDeviceByEntity(entityNoClass)); - - - // Now look up destination devices - assertEquals(d1, deviceManager.findClassDevice(d2.getEntityClass(), - entity1.getMacAddress(), - entity1.getVlan(), - entity1.getIpv4Address())); - assertEquals(d1, deviceManager.findClassDevice(d2.getEntityClass(), - entity1.getMacAddress(), - entity1.getVlan(), - null)); - assertEquals(null, deviceManager.findClassDevice(d2.getEntityClass(), - entity1.getMacAddress(), - (short) -1, - 0)); - } - - - - @Test - public void testGetIPv4Addresses() { - // Looks like Date is only 1s granularity - - ITopologyService mockTopology = createMock(ITopologyService.class); - deviceManager.topology = mockTopology; - expect(mockTopology.isAttachmentPointPort(anyLong(), - anyShort())). - andReturn(true).anyTimes(); - expect(mockTopology.getL2DomainId(anyLong())).andReturn(1L).anyTimes(); - expect(mockTopology.isConsistent(EasyMock.anyLong(), - EasyMock.anyShort(), - EasyMock.anyLong(), - EasyMock.anyShort())) - .andReturn(false) - .anyTimes(); - expect(mockTopology.isBroadcastDomainPort(EasyMock.anyLong(), - EasyMock.anyShort())) - .andReturn(false) - .anyTimes(); - expect(mockTopology.isInSameBroadcastDomain(EasyMock.anyLong(), - EasyMock.anyShort(), - EasyMock.anyLong(), - EasyMock.anyShort())). - andReturn(false).anyTimes(); - replay(mockTopology); - - Entity e1 = new Entity(1L, (short)1, null, null, null, new Date(2000)); - Device d1 = deviceManager.learnDeviceByEntity(e1); - assertArrayEquals(new Integer[0], d1.getIPv4Addresses()); - - - Entity e2 = new Entity(2L, (short)2, 2, null, null, new Date(2000)); - Device d2 = deviceManager.learnDeviceByEntity(e2); - d2 = deviceManager.learnDeviceByEntity(e2); - assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); - // More than one entity - Entity e2b = new Entity(2L, (short)2, null, 2L, 2, new Date(3000)); - d2 = deviceManager.learnDeviceByEntity(e2b); - assertEquals(2, d2.entities.length); - assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); - // and now add an entity with an IP - Entity e2c = new Entity(2L, (short)2, 2, 2L, 3, new Date(3000)); - d2 = deviceManager.learnDeviceByEntity(e2c); - assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); - assertEquals(3, d2.entities.length); - - // Other devices with different IPs shouldn't interfere - Entity e3 = new Entity(3L, (short)3, 3, null, null, new Date(4000)); - Entity e3b = new Entity(3L, (short)3, 3, 3L, 3, new Date(4400)); - Device d3 = deviceManager.learnDeviceByEntity(e3); - d3 = deviceManager.learnDeviceByEntity(e3b); - assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); - assertArrayEquals(new Integer[] { 3 }, d3.getIPv4Addresses()); - - // Add another IP to d3 - Entity e3c = new Entity(3L, (short)3, 33, 3L, 3, new Date(4400)); - d3 = deviceManager.learnDeviceByEntity(e3c); - Integer[] ips = d3.getIPv4Addresses(); - Arrays.sort(ips); - assertArrayEquals(new Integer[] { 3, 33 }, ips); - - // Add another device that also claims IP2 but is older than e2 - Entity e4 = new Entity(4L, (short)4, 2, null, null, new Date(1000)); - Entity e4b = new Entity(4L, (short)4, null, 4L, 4, new Date(1000)); - Device d4 = deviceManager.learnDeviceByEntity(e4); - assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); - assertArrayEquals(new Integer[0], d4.getIPv4Addresses()); - // add another entity to d4 - d4 = deviceManager.learnDeviceByEntity(e4b); - assertArrayEquals(new Integer[0], d4.getIPv4Addresses()); - - // Make e4 and e4a newer - Entity e4c = new Entity(4L, (short)4, 2, null, null, new Date(5000)); - Entity e4d = new Entity(4L, (short)4, null, 4L, 5, new Date(5000)); - d4 = deviceManager.learnDeviceByEntity(e4c); - d4 = deviceManager.learnDeviceByEntity(e4d); - assertArrayEquals(new Integer[0], d2.getIPv4Addresses()); - // FIXME: d4 should not return IP4 - assertArrayEquals(new Integer[] { 2 }, d4.getIPv4Addresses()); - - // Add another newer entity to d2 but with different IP - Entity e2d = new Entity(2L, (short)2, 22, 4L, 6, new Date(6000)); - d2 = deviceManager.learnDeviceByEntity(e2d); - assertArrayEquals(new Integer[] { 22 }, d2.getIPv4Addresses()); - assertArrayEquals(new Integer[] { 2 }, d4.getIPv4Addresses()); - - // new IP for d2,d4 but with same timestamp. Both devices get the IP - Entity e2e = new Entity(2L, (short)2, 42, 2L, 4, new Date(7000)); - d2 = deviceManager.learnDeviceByEntity(e2e); - ips= d2.getIPv4Addresses(); - Arrays.sort(ips); - assertArrayEquals(new Integer[] { 22, 42 }, ips); - Entity e4e = new Entity(4L, (short)4, 42, 4L, 7, new Date(7000)); - d4 = deviceManager.learnDeviceByEntity(e4e); - ips= d4.getIPv4Addresses(); - Arrays.sort(ips); - assertArrayEquals(new Integer[] { 2, 42 }, ips); - - // add a couple more IPs - Entity e2f = new Entity(2L, (short)2, 4242, 2L, 5, new Date(8000)); - d2 = deviceManager.learnDeviceByEntity(e2f); - ips= d2.getIPv4Addresses(); - Arrays.sort(ips); - assertArrayEquals(new Integer[] { 22, 42, 4242 }, ips); - Entity e4f = new Entity(4L, (short)4, 4242, 4L, 8, new Date(9000)); - d4 = deviceManager.learnDeviceByEntity(e4f); - ips= d4.getIPv4Addresses(); - Arrays.sort(ips); - assertArrayEquals(new Integer[] { 2, 42, 4242 }, ips); - } - - // TODO: this test should really go into a separate class that collects - // unit tests for Device - @Test - public void testGetSwitchPortVlanId() { - Entity entity1 = new Entity(1L, (short)1, null, 10L, 1, new Date()); - Entity entity2 = new Entity(1L, null, null, 10L, 1, new Date()); - Entity entity3 = new Entity(1L, (short)3, null, 1L, 1, new Date()); - Entity entity4 = new Entity(1L, (short)42, null, 1L, 1, new Date()); - Entity[] entities = new Entity[] { entity1, entity2, - entity3, entity4 - }; - Device d = new Device(null,1L, null, null, null, - Arrays.asList(entities), null); - SwitchPort swp1x1 = new SwitchPort(1L, 1); - SwitchPort swp1x2 = new SwitchPort(1L, 2); - SwitchPort swp2x1 = new SwitchPort(2L, 1); - SwitchPort swp10x1 = new SwitchPort(10L, 1); - assertArrayEquals(new Short[] { -1, 1}, - d.getSwitchPortVlanIds(swp10x1)); - assertArrayEquals(new Short[] { 3, 42}, - d.getSwitchPortVlanIds(swp1x1)); - assertArrayEquals(new Short[0], - d.getSwitchPortVlanIds(swp1x2)); - assertArrayEquals(new Short[0], - d.getSwitchPortVlanIds(swp2x1)); - } - - @Test - public void testReclassifyDevice() throws FloodlightModuleException { - MockFlexEntityClassifier flexClassifier = - new MockFlexEntityClassifier(); - deviceManager.entityClassifier= flexClassifier; - deviceManager.startUp(null); - - ITopologyService mockTopology = createMock(ITopologyService.class); - deviceManager.topology = mockTopology; - expect(mockTopology.isAttachmentPointPort(anyLong(), - anyShort())). - andReturn(true).anyTimes(); - expect(mockTopology.getL2DomainId(anyLong())).andReturn(1L).anyTimes(); - expect(mockTopology.isConsistent(EasyMock.anyLong(), - EasyMock.anyShort(), - EasyMock.anyLong(), - EasyMock.anyShort())) - .andReturn(false) - .anyTimes(); - expect(mockTopology.isBroadcastDomainPort(EasyMock.anyLong(), - EasyMock.anyShort())) - .andReturn(false) - .anyTimes(); - replay(mockTopology); - - //flexClassifier.createTestEntityClass("Class1"); - - Entity entity1 = new Entity(1L, (short)1, 1, 1L, 1, new Date()); - Entity entity1b = new Entity(1L, (short)2, 1, 1L, 1, new Date()); - Entity entity2 = new Entity(2L, (short)1, 2, 2L, 2, new Date()); - Entity entity2b = new Entity(2L, (short)2, 2, 2L, 2, new Date()); - - - Device d1 = deviceManager.learnDeviceByEntity(entity1); - Device d2 = deviceManager.learnDeviceByEntity(entity2); - Device d1b = deviceManager.learnDeviceByEntity(entity1b); - Device d2b = deviceManager.learnDeviceByEntity(entity2b); - - d1 = deviceManager.getDeviceIteratorForQuery(entity1.getMacAddress(), - entity1.getVlan(), entity1.getIpv4Address(), - entity1.getSwitchDPID(), entity1.getSwitchPort()) - .next(); - d1b = deviceManager.getDeviceIteratorForQuery(entity1b.getMacAddress(), - entity1b.getVlan(), entity1b.getIpv4Address(), - entity1b.getSwitchDPID(), entity1b.getSwitchPort()).next(); - - assertEquals(d1, d1b); - - d2 = deviceManager.getDeviceIteratorForQuery(entity2.getMacAddress(), - entity2.getVlan(), entity2.getIpv4Address(), - entity2.getSwitchDPID(), entity2.getSwitchPort()).next(); - d2b = deviceManager.getDeviceIteratorForQuery(entity2b.getMacAddress(), - entity2b.getVlan(), entity2b.getIpv4Address(), - entity2b.getSwitchDPID(), entity2b.getSwitchPort()).next(); - assertEquals(d2, d2b); - - IEntityClass eC1 = flexClassifier.createTestEntityClass("C1"); - IEntityClass eC2 = flexClassifier.createTestEntityClass("C2"); - - flexClassifier.addVlanEntities((short)1, eC1); - flexClassifier.addVlanEntities((short)2, eC1); - - deviceManager.reclassifyDevice(d1); - deviceManager.reclassifyDevice(d2); - - d1 = deviceManager.deviceMap.get( - deviceManager.primaryIndex.findByEntity(entity1)); - d1b = deviceManager.deviceMap.get( - deviceManager.primaryIndex.findByEntity(entity1b)); - - assertEquals(d1, d1b); - - d2 = deviceManager.deviceMap.get( - deviceManager.primaryIndex.findByEntity(entity2)); - d2b = deviceManager.deviceMap.get( - deviceManager.primaryIndex.findByEntity(entity2b)); - - assertEquals(d2, d2b); - - flexClassifier.addVlanEntities((short)1, eC2); - - deviceManager.reclassifyDevice(d1); - deviceManager.reclassifyDevice(d2); - d1 = deviceManager.deviceMap.get( - deviceManager.primaryIndex.findByEntity(entity1)); - d1b = deviceManager.deviceMap.get( - deviceManager.primaryIndex.findByEntity(entity1b)); - d2 = deviceManager.deviceMap.get( - deviceManager.primaryIndex.findByEntity(entity2)); - d2b = deviceManager.deviceMap.get( - deviceManager.primaryIndex.findByEntity(entity2b)); - - assertNotSame(d1, d1b); - - assertNotSame(d2, d2b); - - flexClassifier.addVlanEntities((short)1, eC1); - deviceManager.reclassifyDevice(d1); - deviceManager.reclassifyDevice(d2); - ClassState classState = deviceManager.classStateMap.get(eC1.getName()); - - Long deviceKey1 = null; - Long deviceKey1b = null; - Long deviceKey2 = null; - Long deviceKey2b = null; - - deviceKey1 = - classState.classIndex.findByEntity(entity1); - deviceKey1b = - classState.classIndex.findByEntity(entity1b); - deviceKey2 = - classState.classIndex.findByEntity(entity2); - deviceKey2b = - classState.classIndex.findByEntity(entity2b); - - assertEquals(deviceKey1, deviceKey1b); - - assertEquals(deviceKey2, deviceKey2b); - } - - @Test - public void testSyncEntity() { - Date d1 = new Date(); - Date d2 = new Date(0); - Entity e1 = new Entity(1L, (short)2, 3, 4L, 5, d1); - e1.setActiveSince(d2); - SyncEntity se1 = new SyncEntity(e1); - assertEntityEquals(e1, se1); - assertEquals(1L, se1.macAddress); - assertEquals(Short.valueOf((short)2), se1.vlan); - assertEquals(Integer.valueOf(3), se1.ipv4Address); - assertEquals(Long.valueOf(4L), se1.switchDPID); - assertEquals(Integer.valueOf(5), se1.switchPort); - assertEquals(d1, se1.lastSeenTimestamp); - assertEquals(d2, se1.activeSince); - assertNotSame(d1, se1.lastSeenTimestamp); - assertNotSame(d2, se1.activeSince); - - Entity e2 = new Entity(42L, null, null, null, null, null); - SyncEntity se2 = new SyncEntity(e2); - assertEntityEquals(e2, se2); - - SyncEntity se3 = new SyncEntity(); - SyncEntity se4 = new SyncEntity(); - se3.lastSeenTimestamp = new Date(1000); - se4.lastSeenTimestamp = new Date(2000); - assertTrue("", se3.compareTo(se4) < 0); - assertTrue("", se4.compareTo(se3) > 0); - se4.lastSeenTimestamp = new Date(1000); - assertTrue("", se3.compareTo(se4) == 0); - assertTrue("", se4.compareTo(se3) == 0); - se4.lastSeenTimestamp = new Date(500); - assertTrue("", se3.compareTo(se4) > 0); - assertTrue("", se4.compareTo(se3) < 0); - } - - /* Test basic DeviceSyncRepresentation behavior */ - @Test - public void testDeviceSyncRepresentationBasics() { - DeviceSyncRepresentation dsr = new DeviceSyncRepresentation(); - assertNull(dsr.getKey()); - assertNull(dsr.getEntities()); - dsr.setKey("MyKey"); - assertEquals("MyKey", dsr.getKey()); - assertEquals("MyKey", dsr.toString()); - - List<SyncEntity> entities = new ArrayList<SyncEntity>(); - Entity e1a = new Entity(1L, (short)2, 3, 4L, 5, new Date(1000)); - Entity e1b = new Entity(1L, (short)2, null, 4L, 5, new Date(0)); - entities.add(new SyncEntity(e1a)); - entities.add(new SyncEntity(e1b)); - // e1b comes before e1 (lastSeen) but we add it after it to test - // sorting - dsr.setEntities(entities); - - assertEquals(2, dsr.getEntities().size()); - // e1b has earlier time - assertEquals(e1b, dsr.getEntities().get(0).asEntity()); - assertEquals(e1a, dsr.getEntities().get(1).asEntity()); - - dsr.setKey(null); - dsr.setEntities(null); - assertNull(dsr.getKey()); - assertNull(dsr.getEntities()); - } - - @Test - public void testDeviceSyncRepresentationFromDevice() { - ITopologyService mockTopology = makeMockTopologyAllPortsAp(); - replay(mockTopology); - deviceManager.topology = mockTopology; - - deviceManager.entityClassifier = new MockEntityClassifier(); - - //************************************** - // Test 1: a single entity - Entity e1 = new Entity(1L, (short)2, 3, 4L, 5, new Date(1000)); - Device d1 = deviceManager.learnDeviceByEntity(e1); - assertEquals("Sanity check failed. Device doesn't have the expected " + - "entity class. Something with the test setup is strange", - "DefaultEntityClass", d1.getEntityClass().getName()); - assertEquals("Sanity check failed. Device doesn't have the expected " + - "entity class. Something with the test setup is strange", - EnumSet.of(DeviceField.MAC, DeviceField.VLAN), - d1.getEntityClass().getKeyFields()); - - Long deviceKey = d1.getDeviceKey(); - DeviceSyncRepresentation dsr1 = new DeviceSyncRepresentation(d1); - assertEquals("DefaultEntityClass::00:00:00:00:00:01::[2]::", - dsr1.getKey()); - assertEquals(1, dsr1.getEntities().size()); - assertEquals(e1, dsr1.getEntities().get(0).asEntity()); - - //************************************** - // Test 1b: same device, now with a second entity (no IP). - // this second entity has a lastSeen time that is earlier than the - // first entity - Entity e1b = new Entity(1L, (short)2, null, 4L, 5, new Date(0)); - d1 = deviceManager.learnDeviceByEntity(e1b); - assertEquals("Sanity check failed. Should still be same device but " + - "deviceKeys differs", deviceKey, d1.getDeviceKey()); - dsr1 = new DeviceSyncRepresentation(d1); - assertEquals("DefaultEntityClass::00:00:00:00:00:01::[2]::", - dsr1.getKey()); - assertEquals(2, dsr1.getEntities().size()); - // Entities are ordered by their lastSeen time. e1b should come - // before e1. - assertEquals(e1, dsr1.getEntities().get(1).asEntity()); - assertEquals(e1b, dsr1.getEntities().get(0).asEntity()); - - //************************************** - // Test 1c: same device with a third entity that does not have a - // switch port. It should be added to the DeviceSyncRepresentation - Entity e1c = new Entity(1L, (short)2, 33, null, null, new Date(2000)); - d1 = deviceManager.learnDeviceByEntity(e1c); - assertEquals("Sanity check failed. Should still be same device but " + - "deviceKeys differs", deviceKey, d1.getDeviceKey()); - dsr1 = new DeviceSyncRepresentation(d1); - assertEquals("DefaultEntityClass::00:00:00:00:00:01::[2]::", - dsr1.getKey()); - assertEquals(3, dsr1.getEntities().size()); - // Entities are ordered by their lastSeen time - assertEquals(e1c, dsr1.getEntities().get(2).asEntity()); - assertEquals(e1, dsr1.getEntities().get(1).asEntity()); - assertEquals(e1b, dsr1.getEntities().get(0).asEntity()); - - //************************************** - // Test 1d: same device with a fourth entity that has a different - // attachment point and that is newer. Device should move and - // non-attachment point entities should be removed (e1b). Although - // e1 is non-attachment point it will remain because it has an IP - Entity e1d = new Entity(1L, (short)2, 33, 4L, 6, new Date(3000)); - d1 = deviceManager.learnDeviceByEntity(e1d); - assertEquals("Sanity check failed. Should still be same device but " + - "deviceKeys differs", deviceKey, d1.getDeviceKey()); - dsr1 = new DeviceSyncRepresentation(d1); - assertEquals("DefaultEntityClass::00:00:00:00:00:01::[2]::", - dsr1.getKey()); - assertEquals(3, dsr1.getEntities().size()); - assertEquals(e1, dsr1.getEntities().get(0).asEntity()); - assertEquals(e1c, dsr1.getEntities().get(1).asEntity()); - assertEquals(e1d, dsr1.getEntities().get(2).asEntity()); - - d1 = null; - - - //************************************** - // Test 2: a second device with a different entity class. The - // mock entity classifier will return an entity class where all - // fields are keys if the DPID is > 10L - Entity e2 = new Entity(2L, (short)23, 24, 11L, 1, new Date(0)); - Device d2 = deviceManager.learnDeviceByEntity(e2); - DeviceSyncRepresentation dsr2 = new DeviceSyncRepresentation(d2); - assertEquals("Sanity check failed. Device doesn't have the expected " + - "entity class. Something with the test setup is strange", - "TestEntityClass", d2.getEntityClass().getName()); - assertEquals("Sanity check failed. Device doesn't have the expected " + - "entity class. Something with the test setup is strange", - EnumSet.of(DeviceField.MAC, DeviceField.VLAN, - DeviceField.SWITCH, DeviceField.PORT), - d2.getEntityClass().getKeyFields()); - SwitchPort swp = new SwitchPort(11L, 1, null); - assertEquals("TestEntityClass::00:00:00:00:00:02::[23]::[" + - swp.toString() + "]::", - dsr2.getKey()); - } - - /* interate through all entries in the sync store and return them as - * list. We don't return the key from the store however, we assert - * that the key from the store matches the key in the representation. - * If we have a null value (tombstone) we simply add the null value to - * the list to return. - */ - private List<DeviceSyncRepresentation> getEntriesFromStore() - throws Exception { - List<DeviceSyncRepresentation> entries = - new ArrayList<DeviceSyncRepresentation>(); - IClosableIterator<Entry<String, Versioned<DeviceSyncRepresentation>>> iter = - storeClient.entries(); - try { - while(iter.hasNext()) { - Entry<String, Versioned<DeviceSyncRepresentation>> entry = - iter.next(); - DeviceSyncRepresentation dsr = entry.getValue().getValue(); - if (dsr != null) - assertEquals(entry.getKey(), dsr.getKey()); - entries.add(dsr); - } - } finally { - if (iter != null) - iter.close(); - } - return entries; - } - - /* - * assert whether the given Entity expected is equals to the given - * SyncEntity actual. This method also compares the times (lastSeen, - * activeSince). Entity.equals will not do that! - */ - private static void assertEntityEquals(Entity expected, SyncEntity actual) { - assertNotNull(actual); - assertNotNull(expected); - Entity actualEntity = actual.asEntity(); - assertEquals("entityFields", expected, actualEntity); - assertEquals("lastSeenTimestamp", - expected.getLastSeenTimestamp(), - actualEntity.getLastSeenTimestamp()); - assertEquals("activeSince", - expected.getActiveSince(), actualEntity.getActiveSince()); - } - - /* This test tests the normal operation as master when we write to the sync - * store or delete from the store. - */ - @Test - public void testWriteToSyncStore() throws Exception { - int syncStoreIntervalMs = 50; - ITopologyService mockTopology = makeMockTopologyAllPortsAp(); - replay(mockTopology); - deviceManager.topology = mockTopology; - deviceManager.setSyncStoreWriteInterval(syncStoreIntervalMs); - - Entity e1a = new Entity(1L, (short)2, 3, 4L, 5, new Date(1000)); - e1a.setActiveSince(new Date(0)); - deviceManager.learnDeviceByEntity(e1a); - - //storeClient.put("FooBar", new DeviceSyncRepresentation()); - - List<DeviceSyncRepresentation> entries = getEntriesFromStore(); - assertEquals(1, entries.size()); - DeviceSyncRepresentation dsr1 = entries.get(0); - assertEquals(1, dsr1.getEntities().size()); - assertEntityEquals(e1a, dsr1.getEntities().get(0)); - - // Same entity but newer timestamp. Since the device hasn't changed, - // only the timestamp is updated and the write should be throttled. - Entity e1b = new Entity(1L, (short)2, 3, 4L, 5, new Date(2000)); - e1b.setActiveSince(new Date(0)); - deviceManager.learnDeviceByEntity(e1a); - entries = getEntriesFromStore(); - assertEquals(1, entries.size()); - dsr1 = entries.get(0); - assertEquals(1, dsr1.getEntities().size()); - assertEntityEquals(e1a, dsr1.getEntities().get(0)); //e1a not e1b !!! - - // Wait for the write interval to expire then write again. - Thread.sleep(syncStoreIntervalMs+5); - Entity e1c = new Entity(1L, (short)2, 3, 4L, 5, new Date(3000)); - e1c.setActiveSince(new Date(0)); - deviceManager.learnDeviceByEntity(e1c); - entries = getEntriesFromStore(); - assertEquals(1, entries.size()); - dsr1 = entries.get(0); - assertEquals(1, dsr1.getEntities().size()); - assertEntityEquals(e1c, dsr1.getEntities().get(0)); // e1c !! - - // Entity for same device but with different IP. should be added - // immediately - Entity e1d = new Entity(1L, (short)2, 33, 4L, 5, new Date(4000)); - e1d.setActiveSince(new Date(0)); - deviceManager.learnDeviceByEntity(e1d); - entries = getEntriesFromStore(); - assertEquals(1, entries.size()); - dsr1 = entries.get(0); - assertEquals(2, dsr1.getEntities().size()); - assertEntityEquals(e1c, dsr1.getEntities().get(0)); // e1c !! - assertEntityEquals(e1d, dsr1.getEntities().get(1)); // e1d !! - - // Entity for same device with new switch port ==> moved ==> write - // update immediately without throttle. - // Note: the previous entities will still be there because they have - // IPs (even though they aren't for the current attachment point) - Entity e1e = new Entity(1L, (short)2, 33, 4L, 6, new Date(5000)); - e1e.setActiveSince(new Date(0)); - deviceManager.learnDeviceByEntity(e1e); - entries = getEntriesFromStore(); - assertEquals(1, entries.size()); - dsr1 = entries.get(0); - assertEquals(3, dsr1.getEntities().size()); - assertEntityEquals(e1c, dsr1.getEntities().get(0)); - assertEntityEquals(e1d, dsr1.getEntities().get(1)); - assertEntityEquals(e1e, dsr1.getEntities().get(2)); - - // Add a second device - Entity e2 = new Entity(2L, null, null, 5L, 5, new Date()); - deviceManager.learnDeviceByEntity(e2); - entries = getEntriesFromStore(); - assertEquals(2, entries.size()); - for (DeviceSyncRepresentation dsr: entries) { - // This is a kinda ugly way to ensure we have the two - // devices we need..... but it will work for now - if (dsr.getKey().contains("::00:00:00:00:00:01::")) { - assertEquals(3, dsr.getEntities().size()); - assertEntityEquals(e1c, dsr.getEntities().get(0)); - assertEntityEquals(e1d, dsr.getEntities().get(1)); - assertEntityEquals(e1e, dsr.getEntities().get(2)); - } else if (dsr.getKey().contains("::00:00:00:00:00:02::")) { - assertEquals(1, dsr.getEntities().size()); - assertEntityEquals(e2, dsr.getEntities().get(0)); - } else { - fail("Unknown entry in store: " + dsr); - } - } - - - // Run entity cleanup. Since we've used phony time stamps for - // device 1 its entities should be cleared and the device should be - // removed from the store. Device 2 should remain in the store. - deviceManager.cleanupEntities(); - entries = getEntriesFromStore(); - assertEquals(2, entries.size()); - for (DeviceSyncRepresentation dsr: entries) { - if (dsr == null) { - // pass - } else if (dsr.getKey().contains("::00:00:00:00:00:02::")) { - assertEquals(1, dsr.getEntities().size()); - assertEntityEquals(e2, dsr.getEntities().get(0)); - } else { - fail("Unknown entry in store: " + dsr); - } - } - } - - - private void assertDeviceIps(Integer[] expected, IDevice d) { - List<Integer> expectedList = Arrays.asList(expected); - Collections.sort(expectedList); - List<Integer> actualList = Arrays.asList(d.getIPv4Addresses()); - Collections.sort(actualList); - assertEquals(expectedList, actualList); - } - - private IDevice getSingleDeviceFromDeviceManager(long mac) { - Iterator<? extends IDevice> diter = - deviceManager.queryDevices(mac, null, null, null, null); - assertTrue("Query didn't return a device", diter.hasNext()); - IDevice d = diter.next(); - assertFalse("Query returned more than one device", diter.hasNext()); - return d; - } - - @Test - public void testToMaster() throws Exception { - int syncStoreWriteIntervalMs = 0; - int initialSyncStoreConsolidateIntervalMs = 50; - ITopologyService mockTopology = makeMockTopologyAllPortsAp(); - replay(mockTopology); - deviceManager.topology = mockTopology; - // We want an EntityClassifier that has switch/port as key fields - deviceManager.entityClassifier = new MockEntityClassifier(); - deviceManager.setSyncStoreWriteInterval(syncStoreWriteIntervalMs); - deviceManager.setInitialSyncStoreConsolidateMs(initialSyncStoreConsolidateIntervalMs); - - // Add Device1 with two entities with two different IPs - Entity e1a = new Entity(1L, null, 3, 4L, 5, new Date(1000)); - Entity e1b = new Entity(1L, null, 33, 4L, 5, new Date(2000)); - Device d1 = deviceManager.allocateDevice(1L, e1a, - DefaultEntityClassifier.entityClass); - d1 = deviceManager.allocateDevice(d1, e1b, -1); - DeviceSyncRepresentation dsr = new DeviceSyncRepresentation(d1); - storeClient.put(dsr.getKey(), dsr); - - // Add Device2 with different switch-ports. Only the most recent - // one should be the attachment point - Entity e2a = new Entity(2L, null, null, 4L, 4, new Date(1000)); - Entity e2b = new Entity(2L, null, null, 4L, 5, new Date(2000)); - Device d2 = deviceManager.allocateDevice(2L, e2a, - DefaultEntityClassifier.entityClass); - d2 = deviceManager.allocateDevice(d2, e2b, -1); - d2.updateAttachmentPoint(4L, (short)5, - e2b.getLastSeenTimestamp().getTime()); - SwitchPort swp = new SwitchPort(4L, 5); - SwitchPort[] aps = d2.getAttachmentPoints(); - // sanity check - assertArrayEquals("Sanity check: should only have AP(4L,5)", - new SwitchPort[] {swp}, aps); - dsr = new DeviceSyncRepresentation(d2); - storeClient.put(dsr.getKey(), dsr); - - // Add a tombstone entry to the store to make sure we don't trip a - // NPE - dsr = null; - Versioned<DeviceSyncRepresentation> versionedDsr = - storeClient.get("FooBar"); - storeClient.put("FooBar", versionedDsr); - - deviceManager.getHAListener().transitionToMaster(); - - // Query for the Device1. Make sure we have the two IPs we stored. - IDevice d = getSingleDeviceFromDeviceManager(1L); - assertDeviceIps(new Integer[] {3, 33}, d); - assertArrayEquals(new Short[] { Ethernet.VLAN_UNTAGGED }, d.getVlanId()); - swp = new SwitchPort(4L, 5); - assertArrayEquals(new SwitchPort[] { swp }, d.getAttachmentPoints()); - - // Query for Device2. Make sure we only have the more recent AP - // Query for the Device1. Make sure we have the two IPs we stored. - d = getSingleDeviceFromDeviceManager(2L); - assertArrayEquals(new Integer[0], d.getIPv4Addresses()); - assertArrayEquals(new Short[] { Ethernet.VLAN_UNTAGGED }, d.getVlanId()); - swp = new SwitchPort(4L, 5); - assertArrayEquals(new SwitchPort[] { swp }, d.getAttachmentPoints()); - - //---------------------------- - // add another entry device to the store. since device manager is - // already master we won't read this device and it should be - // removed from the store by the consolidate task - Entity e3 = new Entity(3L, null, null, 1L, 1, null); - dsr = new DeviceSyncRepresentation(); - dsr.setKey("Device3"); - dsr.setEntities(Collections.singletonList(new SyncEntity(e3))); - storeClient.put(dsr.getKey(), dsr); - - // make sure it's in the store - List<DeviceSyncRepresentation> entries = getEntriesFromStore(); - boolean found = false; - for (DeviceSyncRepresentation entry: entries) { - if (entry!=null && entry.getKey().equals("Device3")) - found = true; - } - assertTrue("Device3 not in store. Entries in store: " + entries, found); - // make sure it's not in DevManager - Iterator<? extends IDevice> diter = - deviceManager.queryDevices(3L, null, null, null, null); - assertFalse("Device3 found in DeviceManager. Should be there", - diter.hasNext()); - - // Wait for consolidate - Thread.sleep(initialSyncStoreConsolidateIntervalMs + 5); - // make sure it's in NOT the store - entries = getEntriesFromStore(); - found = false; - for (DeviceSyncRepresentation entry: entries) { - if (entry!=null && entry.getKey().equals("Device3")) - found = true; - } - assertFalse("Device3 not is still in the store. Entries in store: " - + entries, found); - // make sure it's not in DevManager - diter = deviceManager.queryDevices(3L, null, null, null, null); - assertFalse("Device3 found in DeviceManager. Should be there", - diter.hasNext()); - } - - - @Test - public void testConsolitateStore() throws Exception { - int syncStoreInternalMs = 0; - ITopologyService mockTopology = makeMockTopologyAllPortsAp(); - replay(mockTopology); - deviceManager.topology = mockTopology; - // We want an EntityClassifier that has switch/port as key fields - deviceManager.entityClassifier = new MockEntityClassifier(); - deviceManager.setSyncStoreWriteInterval(syncStoreInternalMs); - - // Add Device1 with two entities to store and let device manager - // learn - Entity e1a = new Entity(1L, null, null, 4L, 5, new Date(1000)); - Entity e1b = new Entity(1L, null, 3, 4L, 5, new Date(2000)); - Device d1 = deviceManager.learnDeviceByEntity(e1a); - deviceManager.learnDeviceByEntity(e1b); - String dev1Key = DeviceSyncRepresentation.computeKey(d1); - - - // Add a second device to the store but do NOT add to device manager - Entity e2 = new Entity(2L, null, null, 5L, 5, new Date()); - Device d2 = deviceManager.allocateDevice(42L, e2, - DefaultEntityClassifier.entityClass); - DeviceSyncRepresentation dsr = new DeviceSyncRepresentation(d2); - storeClient.put(dsr.getKey(), dsr); - String dev2Key = DeviceSyncRepresentation.computeKey(d2); - - // Make sure we have two devices in the store - List<DeviceSyncRepresentation> entries = getEntriesFromStore(); - assertEquals(2, entries.size()); - - deviceManager.scheduleConsolidateStoreNow(); - Thread.sleep(25); // give the scheduler time to run the task - - // We should still have two entries, however one of them will be a - // tombstone - entries = getEntriesFromStore(); - assertEquals(2, entries.size()); - - // Device 1 should still be in store - Versioned<DeviceSyncRepresentation> versioned = - storeClient.get(dev1Key); - dsr = versioned.getValue(); - assertNotNull(dsr); - assertEquals(2, dsr.getEntities().size()); - assertEntityEquals(e1a, dsr.getEntities().get(0)); - assertEntityEquals(e1b, dsr.getEntities().get(1)); - - // Device2 should be gone - versioned = storeClient.get(dev2Key); - assertNull(versioned.getValue()); - - // Run consolitate again. This time we check that tombstones in - // the store are handled correctly - deviceManager.scheduleConsolidateStoreNow(); - Thread.sleep(25); // give the scheduler time to run the task - - // Now write a device to the store that doesn't have any switch-port - // it should be removed - Entity e3 = new Entity(3L, null, null, null, null, null); - dsr.setKey("Device3"); - dsr.setEntities(Collections.singletonList(new SyncEntity(e3))); - storeClient.put(dsr.getKey(), dsr); - - // Run consolitate again. This time we check that tombstones in - // the store are handled correctly - deviceManager.scheduleConsolidateStoreNow(); - Thread.sleep(25); // give the scheduler time to run the task - versioned = storeClient.get("Device3"); - assertNull(versioned.getValue()); - - } + protected static Logger logger = + LoggerFactory.getLogger(DeviceManagerImplTest.class); + + protected OFPacketIn testARPReplyPacketIn_1, testARPReplyPacketIn_2; + protected OFPacketIn testUDPPacketIn; + protected IPacket testARPReplyPacket_1, testARPReplyPacket_2; + protected Ethernet testUDPPacket; + protected byte[] testARPReplyPacket_1_Srld, testARPReplyPacket_2_Srld; + protected byte[] testUDPPacketSrld; + private MockSyncService syncService; + private IStoreClient<String, DeviceSyncRepresentation> storeClient; + + DeviceManagerImpl deviceManager; + MemoryStorageSource storageSource; + FlowReconcileManager flowReconcileMgr; + + private IOFSwitch makeSwitchMock(DatapathId id) { + IOFSwitch mockSwitch = createMock(IOFSwitch.class); + OFPort port = OFPort.of(1); + expect(mockSwitch.getId()).andReturn(id).anyTimes(); + expect(mockSwitch.getId().toString()).andReturn(id.toString()).anyTimes(); + expect(mockSwitch.getPort(OFPort.of(anyShort())).getPortNo()).andReturn(port).anyTimes(); + return mockSwitch; + } + + /* + * return an EasyMock ITopologyService that's setup so that it will + * answer all questions a device or device manager will ask + * (isAttachmentPointPort, etc.) in a way so that every port is a + * non-BD, attachment point port. + * The returned mock is still in record mode + */ + private ITopologyService makeMockTopologyAllPortsAp() { + ITopologyService mockTopology = createMock(ITopologyService.class); + mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), OFPort.of(anyShort())); + expectLastCall().andReturn(true).anyTimes(); + mockTopology.getL2DomainId(DatapathId.of(anyLong())); + expectLastCall().andReturn(1L).anyTimes(); + mockTopology.isBroadcastDomainPort(DatapathId.of(anyLong()), OFPort.of(anyShort())); + expectLastCall().andReturn(false).anyTimes(); + mockTopology.isConsistent(DatapathId.of(anyLong()), OFPort.of(anyShort()), DatapathId.of(anyLong()), OFPort.of(anyShort())); + expectLastCall().andReturn(false).anyTimes(); + mockTopology.isInSameBroadcastDomain(DatapathId.of(anyLong()), OFPort.of(anyShort()), DatapathId.of(anyLong()), OFPort.of(anyShort())); + expectLastCall().andReturn(false).anyTimes(); + return mockTopology; + } + + @Override + @Before + public void setUp() throws Exception { + doSetUp(HARole.ACTIVE); + } + + public void doSetUp(HARole initialRole) throws Exception { + super.setUp(); + + this.syncService = new MockSyncService(); + + FloodlightModuleContext fmc = new FloodlightModuleContext(); + RestApiServer restApi = new RestApiServer(); + MockThreadPoolService tp = new MockThreadPoolService(); + ITopologyService topology = createMock(ITopologyService.class); + fmc.addService(IThreadPoolService.class, tp); + mockFloodlightProvider = getMockFloodlightProvider(); + mockFloodlightProvider.setRole(initialRole, ""); + + + deviceManager = new DeviceManagerImpl(); + flowReconcileMgr = new FlowReconcileManager(); + DefaultEntityClassifier entityClassifier = new DefaultEntityClassifier(); + fmc.addService(IDeviceService.class, deviceManager); + storageSource = new MemoryStorageSource(); + fmc.addService(IStorageSourceService.class, storageSource); + fmc.addService(IFloodlightProviderService.class, mockFloodlightProvider); + fmc.addService(IRestApiService.class, restApi); + fmc.addService(IFlowReconcileService.class, flowReconcileMgr); + fmc.addService(IEntityClassifierService.class, entityClassifier); + fmc.addService(ITopologyService.class, topology); + fmc.addService(ISyncService.class, syncService); + tp.init(fmc); + restApi.init(fmc); + storageSource.init(fmc); + deviceManager.init(fmc); + flowReconcileMgr.init(fmc); + entityClassifier.init(fmc); + syncService.init(fmc); + storageSource.startUp(fmc); + deviceManager.startUp(fmc); + flowReconcileMgr.startUp(fmc); + tp.startUp(fmc); + entityClassifier.startUp(fmc); + syncService.startUp(fmc); + + this.storeClient = + this.syncService.getStoreClient(DeviceManagerImpl.DEVICE_SYNC_STORE_NAME, + String.class, DeviceSyncRepresentation.class); + + reset(topology); + topology.addListener(deviceManager); + expectLastCall().anyTimes(); + replay(topology); + + IOFSwitch mockSwitch1 = makeSwitchMock(DatapathId.of(1L)); + IOFSwitch mockSwitch10 = makeSwitchMock(DatapathId.of(10L)); + IOFSwitch mockSwitch5 = makeSwitchMock(DatapathId.of(5L)); + IOFSwitch mockSwitch50 = makeSwitchMock(DatapathId.of(50L)); + Map<DatapathId, IOFSwitch> switches = new HashMap<DatapathId, IOFSwitch>(); + switches.put(DatapathId.of(1L), mockSwitch1); + switches.put(DatapathId.of(10L), mockSwitch10); + switches.put(DatapathId.of(5L), mockSwitch5); + switches.put(DatapathId.of(50L), mockSwitch50); + getMockSwitchService().setSwitches(switches); + + replay(mockSwitch1, mockSwitch5, mockSwitch10, mockSwitch50); + + // Build our test packet + this.testARPReplyPacket_1 = new Ethernet() + .setSourceMACAddress("00:44:33:22:11:01") + .setDestinationMACAddress("00:11:22:33:44:55") + .setEtherType(Ethernet.TYPE_ARP) + .setVlanID((short)5) + .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:01")) + .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.1")) + .setTargetHardwareAddress(Ethernet.toMACAddress("00:11:22:33:44:55")) + .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2"))); + this.testARPReplyPacket_1_Srld = testARPReplyPacket_1.serialize(); + + // Another test packet with the same ARP payload as packet 1 but with + // a different source MAC. (i.e., sender MAC and source MAC differ) + this.testARPReplyPacket_2 = new Ethernet() + .setSourceMACAddress("00:99:88:77:66:55") + .setDestinationMACAddress("00:11:22:33:44:55") + .setEtherType(Ethernet.TYPE_ARP) + .setVlanID((short)5) + .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:01")) + .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.1")) + .setTargetHardwareAddress(Ethernet.toMACAddress("00:11:22:33:44:55")) + .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2"))); + this.testARPReplyPacket_2_Srld = testARPReplyPacket_2.serialize(); + + // This packet reverses the MACs and IP from testARPReplyPacket_1 + this.testUDPPacket = (Ethernet) new Ethernet() + .setSourceMACAddress("00:11:22:33:44:55") + .setDestinationMACAddress("00:44:33:22:11:01") + .setEtherType(Ethernet.TYPE_IPv4) + .setVlanID((short)5) + .setPayload( + new IPv4() + .setTtl((byte) 128) + .setSourceAddress("192.168.1.2") + .setDestinationAddress("192.168.1.1") + .setPayload(new UDP() + .setSourcePort((short) 5000) + .setDestinationPort((short) 5001) + .setPayload(new Data(new byte[] {0x01})))); + updateUDPPacketIn(); + + // Build the PacketIn + this.testARPReplyPacketIn_1 = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn() + .setBufferId(OFBufferId.NO_BUFFER) + .setInPort(OFPort.of(1)) + .setData(this.testARPReplyPacket_1_Srld) + .setReason(OFPacketInReason.NO_MATCH) + .build(); + + // Build the PacketIn + this.testARPReplyPacketIn_2 = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn() + .setBufferId(OFBufferId.NO_BUFFER) + .setInPort(OFPort.of(1)) + .setData(this.testARPReplyPacket_2_Srld) + .setReason(OFPacketInReason.NO_MATCH) + .build(); + } + + /** + * Updates testUDPPacketIn and testUDPPacketSrld from testUDPPacket + * To be called after testUDPPacket has been mangled. + */ + private void updateUDPPacketIn() { + this.testUDPPacketSrld = this.testUDPPacket.serialize(); + // Build the PacketIn + this.testUDPPacketIn = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn() + .setBufferId(OFBufferId.NO_BUFFER) + .setInPort(OFPort.of(3)) + .setData(this.testUDPPacketSrld) + .setReason(OFPacketInReason.NO_MATCH) + .build(); + } + + @Test + public void testLastSeen() throws Exception { + Calendar c = Calendar.getInstance(); + Date d1 = c.getTime(); + Entity entity1 = new Entity(MacAddress.of(1L), null, null, null, null, d1); + c.add(Calendar.SECOND, 1); + Entity entity2 = new Entity(MacAddress.of(1L), null, IPv4Address.of(1), null, null, c.getTime()); + + IDevice d = deviceManager.learnDeviceByEntity(entity2); + assertEquals(c.getTime(), d.getLastSeen()); + d = deviceManager.learnDeviceByEntity(entity1); + assertEquals(c.getTime(), d.getLastSeen()); + + deviceManager.startUp(null); + d = deviceManager.learnDeviceByEntity(entity1); + assertEquals(d1, d.getLastSeen()); + d = deviceManager.learnDeviceByEntity(entity2); + assertEquals(c.getTime(), d.getLastSeen()); + } + + + @Test + public void testEntityLearning() throws Exception { + IDeviceListener mockListener = + createMock(IDeviceListener.class); + expect(mockListener.getName()).andReturn("mockListener").atLeastOnce(); + expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) + .andReturn(false).atLeastOnce(); + expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) + .andReturn(false).atLeastOnce(); + + replay(mockListener); + deviceManager.addListener(mockListener); + verify(mockListener); + reset(mockListener); + deviceManager.entityClassifier= new MockEntityClassifier(); + deviceManager.startUp(null); + + ITopologyService mockTopology = createMock(ITopologyService.class); + expect(mockTopology.getL2DomainId(DatapathId.of(anyLong()))). + andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(anyLong()), OFPort.of(anyShort()))). + andReturn(false).anyTimes(); + + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))).andReturn(true).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(10L), OFPort.of(1), DatapathId.of(10L), OFPort.of(1))). + andReturn(true).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(1L), OFPort.of(1), DatapathId.of(1L), OFPort.of(1))). + andReturn(true).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(50L), OFPort.of(3), DatapathId.of(50L), OFPort.of(3))). + andReturn(true).anyTimes(); + + Date topologyUpdateTime = new Date(); + expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). + anyTimes(); + + deviceManager.topology = mockTopology; + + Entity entity1 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(1L), OFPort.of(1), new Date()); + Entity entity2 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(10L), OFPort.of(1), new Date()); + Entity entity3 = new Entity(MacAddress.of(1L), null, IPv4Address.of(1), DatapathId.of(10L), OFPort.of(1), new Date()); + Entity entity4 = new Entity(MacAddress.of(1L), null, IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), new Date()); + Entity entity5 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(4), IPv4Address.of(1), DatapathId.of(5L), OFPort.of(2), new Date()); + Entity entity6 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(4), IPv4Address.of(1), DatapathId.of(50L), OFPort.of(3), new Date()); + Entity entity7 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(4), IPv4Address.of(2), DatapathId.of(50L), OFPort.of(3), new Date()); + + mockListener.deviceAdded(isA(IDevice.class)); + replay(mockListener, mockTopology); + + Device d1 = deviceManager.learnDeviceByEntity(entity1); + assertSame(d1, deviceManager.learnDeviceByEntity(entity1)); + assertSame(d1, deviceManager.findDeviceByEntity(entity1)); + assertEquals(DefaultEntityClassifier.entityClass , + d1.getEntityClass()); + assertArrayEquals(new Short[] { -1 }, d1.getVlanId()); + assertArrayEquals(new Integer[] { }, d1.getIPv4Addresses()); + + assertEquals(1, deviceManager.getAllDevices().size()); + verify(mockListener); + + reset(mockListener); + mockListener.deviceAdded(isA(IDevice.class)); + replay(mockListener); + + Device d2 = deviceManager.learnDeviceByEntity(entity2); + assertFalse(d1.equals(d2)); + assertNotSame(d1, d2); + assertNotSame(d1.getDeviceKey(), d2.getDeviceKey()); + assertEquals(MockEntityClassifier.testEC, d2.getEntityClass()); + assertArrayEquals(new Short[] { -1 }, d2.getVlanId()); + assertArrayEquals(new Integer[] { }, d2.getIPv4Addresses()); + + assertEquals(2, deviceManager.getAllDevices().size()); + verify(mockListener); + + reset(mockListener); + mockListener.deviceIPV4AddrChanged(isA(IDevice.class)); + replay(mockListener); + + Device d3 = deviceManager.learnDeviceByEntity(entity3); + assertNotSame(d2, d3); + assertEquals(d2.getDeviceKey(), d3.getDeviceKey()); + assertEquals(MockEntityClassifier.testEC, d3.getEntityClass()); + assertArrayEquals(new Integer[] { 1 }, + d3.getIPv4Addresses()); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(10L), OFPort.of(1)) }, + d3.getAttachmentPoints()); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(10L), OFPort.of(1)) }, + d3.getAttachmentPoints(true)); + assertArrayEquals(new Short[] { -1 }, + d3.getVlanId()); + + assertEquals(2, deviceManager.getAllDevices().size()); + verify(mockListener); + + reset(mockListener); + mockListener.deviceIPV4AddrChanged(isA(IDevice.class)); + replay(mockListener); + + Device d4 = deviceManager.learnDeviceByEntity(entity4); + assertNotSame(d1, d4); + assertEquals(d1.getDeviceKey(), d4.getDeviceKey()); + assertEquals(DefaultEntityClassifier.entityClass, d4.getEntityClass()); + assertArrayEquals(new Integer[] { 1 }, + d4.getIPv4Addresses()); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)) }, + d4.getAttachmentPoints()); + assertArrayEquals(new Short[] { -1 }, + d4.getVlanId()); + + assertEquals(2, deviceManager.getAllDevices().size()); + verify(mockListener); + + reset(mockListener); + mockListener.deviceAdded((isA(IDevice.class))); + replay(mockListener); + + Device d5 = deviceManager.learnDeviceByEntity(entity5); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(5L), OFPort.of(2)) }, + d5.getAttachmentPoints()); + assertArrayEquals(new Short[] { (short) 4 }, + d5.getVlanId()); + assertEquals(2L, d5.getMACAddress()); + assertEquals("00:00:00:00:00:02", d5.getMACAddressString()); + verify(mockListener); + + reset(mockListener); + mockListener.deviceAdded(isA(IDevice.class)); + replay(mockListener); + + Device d6 = deviceManager.learnDeviceByEntity(entity6); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(50L), OFPort.of(3)) }, + d6.getAttachmentPoints()); + assertArrayEquals(new Short[] { (short) 4 }, + d6.getVlanId()); + + assertEquals(4, deviceManager.getAllDevices().size()); + verify(mockListener); + + reset(mockListener); + mockListener.deviceIPV4AddrChanged(isA(IDevice.class)); + replay(mockListener); + + Device d7 = deviceManager.learnDeviceByEntity(entity7); + assertNotSame(d6, d7); + assertEquals(d6.getDeviceKey(), d7.getDeviceKey()); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(50L), OFPort.of(3)) }, + d7.getAttachmentPoints()); + assertArrayEquals(new Short[] { (short) 4 }, + d7.getVlanId()); + + assertEquals(4, deviceManager.getAllDevices().size()); + verify(mockListener); + + + reset(mockListener); + replay(mockListener); + + reset(deviceManager.topology); + deviceManager.topology.addListener(deviceManager); + expectLastCall().times(1); + replay(deviceManager.topology); + + deviceManager.entityClassifier = new MockEntityClassifierMac(); + deviceManager.startUp(null); + Entity entityNoClass = new Entity(MacAddress.of(5L), VlanVid.ofVlan(1), IPv4Address.of(5), DatapathId.of(-1L), OFPort.of(1), new Date()); + assertEquals(null, deviceManager.learnDeviceByEntity(entityNoClass)); + + verify(mockListener); + } + + + private void doTestEntityOrdering(boolean computeInsertionPoint) throws Exception { + Entity e = new Entity(MacAddress.of(10L), null, null, null, null, null); + IEntityClass ec = createNiceMock(IEntityClass.class); + Device d = new Device(deviceManager, 1L, e, ec); + + int expectedLength = 1; + Long[] macs = new Long[] { 5L, // new first element + 15L, // new last element + 7L, // insert in middle + 12L, // insert in middle + 6L, // insert at idx 1 + 14L, // insert at idx length-2 + 1L, + 20L + }; + + for (Long mac: macs) { + e = new Entity(MacAddress.of(mac), null, null, null, null, null); + int insertionPoint; + if (computeInsertionPoint) { + insertionPoint = -(Arrays.binarySearch(d.entities, e)+1); + } else { + insertionPoint = -1; + } + d = deviceManager.allocateDevice(d, e, insertionPoint); + expectedLength++; + assertEquals(expectedLength, d.entities.length); + for (int i = 0; i < d.entities.length-1; i++) + assertEquals(-1, d.entities[i].compareTo(d.entities[i+1])); + } + } + + @Test + public void testEntityOrderingExternal() throws Exception { + doTestEntityOrdering(true); + } + + @Test + public void testEntityOrderingInternal() throws Exception { + doTestEntityOrdering(false); + } + + @Test + public void testAttachmentPointLearning() throws Exception { + IDeviceListener mockListener = + createMock(IDeviceListener.class); + expect(mockListener.getName()).andReturn("mockListener").atLeastOnce(); + expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) + .andReturn(false).atLeastOnce(); + expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) + .andReturn(false).atLeastOnce(); + + replay(mockListener); + deviceManager.addListener(mockListener); + verify(mockListener); + reset(mockListener); + + ITopologyService mockTopology = createMock(ITopologyService.class); + expect(mockTopology.getL2DomainId(DatapathId.of(1L))). + andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(5L))). + andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(10L))). + andReturn(DatapathId.of(10L)).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(50L))). + andReturn(DatapathId.of(10L)).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(anyLong()), OFPort.of(anyShort()))). + andReturn(false).anyTimes(); + expect(mockTopology.isInSameBroadcastDomain(DatapathId.of(anyLong()), OFPort.of(anyShort()), + DatapathId.of(anyLong()), OFPort.of(anyShort()))).andReturn(false).anyTimes(); + + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))).andReturn(true).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(1L), OFPort.of(1), DatapathId.of(5L), OFPort.of(1))). + andReturn(false).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(5L), OFPort.of(1), DatapathId.of(10L), OFPort.of(1))). + andReturn(false).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(10L), OFPort.of(1), DatapathId.of(50L), OFPort.of(1))). + andReturn(false).anyTimes(); + + Date topologyUpdateTime = new Date(); + expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). + anyTimes(); + + replay(mockTopology); + + deviceManager.topology = mockTopology; + + Calendar c = Calendar.getInstance(); + Entity entity1 = new Entity(MacAddress.of(1L), null, IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), c.getTime()); + Entity entity0 = new Entity(MacAddress.of(1L), null, null, null, null, c.getTime()); + c.add(Calendar.SECOND, 1); + Entity entity2 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(5L), OFPort.of(1), c.getTime()); + c.add(Calendar.SECOND, 1); + Entity entity3 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(10L), OFPort.of(1), c.getTime()); + c.add(Calendar.SECOND, 1); + Entity entity4 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(50L), OFPort.of(1), c.getTime()); + + IDevice d; + SwitchPort[] aps; + IPv4Address[] ips; + + mockListener.deviceAdded(isA(IDevice.class)); + replay(mockListener); + + deviceManager.learnDeviceByEntity(entity1); + d = deviceManager.learnDeviceByEntity(entity0); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)) }, aps); + ips = d.getIPv4Addresses(); + assertArrayEquals(new Integer[] { 1 }, ips); + verify(mockListener); + + reset(mockListener); + mockListener.deviceMoved((isA(IDevice.class))); + replay(mockListener); + + d = deviceManager.learnDeviceByEntity(entity2); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(5L), OFPort.of(1)) }, aps); + ips = d.getIPv4Addresses(); + assertArrayEquals(new Integer[] { 1 }, ips); + verify(mockListener); + + reset(mockListener); + mockListener.deviceMoved((isA(IDevice.class))); + replay(mockListener); + + d = deviceManager.learnDeviceByEntity(entity3); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] {new SwitchPort(DatapathId.of(5L), OFPort.of(1)), new SwitchPort(DatapathId.of(10L), OFPort.of(1))}, aps); + ips = d.getIPv4Addresses(); + assertArrayEquals(new Integer[] { 1 }, ips); + verify(mockListener); + + reset(mockListener); + mockListener.deviceMoved((isA(IDevice.class))); + replay(mockListener); + + d = deviceManager.learnDeviceByEntity(entity4); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(5L), OFPort.of(1)), + new SwitchPort(DatapathId.of(50L), OFPort.of(1)) }, aps); + ips = d.getIPv4Addresses(); + assertArrayEquals(new Integer[] { 1 }, ips); + verify(mockListener); + } + + /** + * In this test, a device is moved from attachment point (1,1) to (5,1) + * and then moved back to (1,1) within 30 seconds. Both the moves should + * generate device moved notification. + * @throws Exception + */ + @Test + public void testAttachmentPointMovingBack() throws Exception { + IDeviceListener mockListener = + createMock(IDeviceListener.class); + expect(mockListener.getName()).andReturn("mockListener").atLeastOnce(); + expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) + .andReturn(false).atLeastOnce(); + expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) + .andReturn(false).atLeastOnce(); + + replay(mockListener); + deviceManager.addListener(mockListener); + verify(mockListener); + reset(mockListener); + + ITopologyService mockTopology = createMock(ITopologyService.class); + expect(mockTopology.getL2DomainId(DatapathId.of(1L))). + andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(5L))). + andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(anyLong()), OFPort.of(anyShort()))). + andReturn(false).anyTimes(); + expect(mockTopology.isInSameBroadcastDomain(DatapathId.of(anyLong()), OFPort.of(anyShort()), + DatapathId.of(anyLong()), OFPort.of(anyShort()))) + .andReturn(false).anyTimes(); + + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))).andReturn(true).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(1L), OFPort.of(1), DatapathId.of(5L), OFPort.of(1))). + andReturn(false).anyTimes(); + + Date topologyUpdateTime = new Date(); + expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). + anyTimes(); + + replay(mockTopology); + + deviceManager.topology = mockTopology; + + Calendar c = Calendar.getInstance(); + Entity entity1 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(1L), OFPort.of(1), c.getTime()); + c.add(Calendar.SECOND, 1); + Entity entity2 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(5L), OFPort.of(1), c.getTime()); + c.add(Calendar.SECOND, 1); + Entity entity3 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(1L), OFPort.of(1), c.getTime()); + c.add(Calendar.SECOND, 1); + Entity entity4 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(5L), OFPort.of(1), c.getTime()); + + IDevice d; + SwitchPort[] aps; + + mockListener.deviceAdded(isA(IDevice.class)); + replay(mockListener); + + d = deviceManager.learnDeviceByEntity(entity1); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)) }, aps); + verify(mockListener); + + reset(mockListener); + mockListener.deviceMoved((isA(IDevice.class))); + replay(mockListener); + + d = deviceManager.learnDeviceByEntity(entity2); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(5L), OFPort.of(1)) }, aps); + verify(mockListener); + + reset(mockListener); + mockListener.deviceMoved((isA(IDevice.class))); + replay(mockListener); + + d = deviceManager.learnDeviceByEntity(entity3); + assertEquals(1, deviceManager.getAllDevices().size()); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)), + new SwitchPort(DatapathId.of(5L), OFPort.of(1), ErrorStatus.DUPLICATE_DEVICE)}, + d.getAttachmentPoints(true)); + verify(mockListener); + + // Generate a packet-in again from 5,1 and ensure that it doesn't + // create a device moved event. + reset(mockListener); + replay(mockListener); + d = deviceManager.learnDeviceByEntity(entity4); + assertEquals(1, deviceManager.getAllDevices().size()); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)), + new SwitchPort(DatapathId.of(5L), OFPort.of(1), ErrorStatus.DUPLICATE_DEVICE)}, + d.getAttachmentPoints(true)); + verify(mockListener); + } + + private void verifyEntityArray(Entity[] expected, Device d) { + Arrays.sort(expected); + assertArrayEquals(expected, d.entities); + } + + @Test + public void testNoLearningOnInternalPorts() throws Exception { + IDeviceListener mockListener = + createMock(IDeviceListener.class); + + expect(mockListener.getName()).andReturn("mockListener").anyTimes(); + expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) + .andReturn(false).atLeastOnce(); + expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) + .andReturn(false).atLeastOnce(); + + replay(mockListener); + deviceManager.addListener(mockListener); + verify(mockListener); + reset(mockListener); + + ITopologyService mockTopology = createMock(ITopologyService.class); + expect(mockTopology.getL2DomainId(DatapathId.of(1L))). + andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(2L))). + andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(3L))). + andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(4L))). + andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(anyLong()), OFPort.of(anyShort()))) + .andReturn(false).anyTimes(); + expect(mockTopology.isInSameBroadcastDomain(DatapathId.of(anyLong()), OFPort.of(anyShort()), + DatapathId.of(anyLong()), OFPort.of(anyShort()))) + .andReturn(false).anyTimes(); + + expect(mockTopology.isAttachmentPointPort(or(eq(DatapathId.of(1L)), eq(DatapathId.of(3L))), OFPort.of(anyShort()))) + .andReturn(true).anyTimes(); + // Switches 2 and 4 have only internal ports + expect(mockTopology.isAttachmentPointPort(or(eq(DatapathId.of(2L)), eq(DatapathId.of(4L))), OFPort.of(anyShort()))) + .andReturn(false).anyTimes(); + + expect(mockTopology.isConsistent(DatapathId.of(1L), OFPort.of(1), DatapathId.of(3L), OFPort.of(1))) + .andReturn(false).once(); + + Date topologyUpdateTime = new Date(); + expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). + anyTimes(); + + replay(mockTopology); + + deviceManager.topology = mockTopology; + + Calendar c = Calendar.getInstance(); + Entity entity1 = new Entity(MacAddress.of(1L), null, IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), c.getTime()); + c.add(Calendar.SECOND, 1); + Entity entity2 = new Entity(MacAddress.of(1L), null, IPv4Address.of(2), DatapathId.of(2L), OFPort.of(1), c.getTime()); + c.add(Calendar.SECOND, 1); + Entity entity3 = new Entity(MacAddress.of(1L), null, IPv4Address.of(3), DatapathId.of(3L), OFPort.of(1), c.getTime()); + c.add(Calendar.SECOND, 1); + Entity entity4 = new Entity(MacAddress.of(1L), null, IPv4Address.of(4), DatapathId.of(4L), OFPort.of(1), c.getTime()); + + IDevice d; + SwitchPort[] aps; + IPv4Address[] ips; + + mockListener.deviceAdded(isA(IDevice.class)); + expectLastCall().once(); + replay(mockListener); + + // cannot learn device internal ports + d = deviceManager.learnDeviceByEntity(entity2); + assertNull(d); + d = deviceManager.learnDeviceByEntity(entity4); + assertNull(d); + + d = deviceManager.learnDeviceByEntity(entity1); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)) }, aps); + verifyEntityArray(new Entity[] { entity1 } , (Device)d); + ips = d.getIPv4Addresses(); + assertArrayEquals(new Integer[] { 1 }, ips); + verify(mockListener); + + reset(mockListener); + replay(mockListener); + + // don't learn + d = deviceManager.learnDeviceByEntity(entity2); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)) }, aps); + verifyEntityArray(new Entity[] { entity1 } , (Device)d); + ips = d.getIPv4Addresses(); + assertArrayEquals(new Integer[] { 1 }, ips); + verify(mockListener); + + reset(mockListener); + mockListener.deviceMoved(isA(IDevice.class)); + mockListener.deviceIPV4AddrChanged(isA(IDevice.class)); + replay(mockListener); + + // learn + d = deviceManager.learnDeviceByEntity(entity3); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(3L), OFPort.of(1)) }, aps); + verifyEntityArray(new Entity[] { entity1, entity3 } , (Device)d); + ips = d.getIPv4Addresses(); + Arrays.sort(ips); + assertArrayEquals(new Integer[] { 1, 3 }, ips); + verify(mockListener); + + reset(mockListener); + replay(mockListener); + + // don't learn + d = deviceManager.learnDeviceByEntity(entity4); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(3L), OFPort.of(1)) }, aps); + verifyEntityArray(new Entity[] { entity1, entity3 } , (Device)d); + ips = d.getIPv4Addresses(); + Arrays.sort(ips); + assertArrayEquals(new Integer[] { 1, 3 }, ips); + verify(mockListener); + } + + @Test + public void testAttachmentPointSuppression() throws Exception { + IDeviceListener mockListener = + createMock(IDeviceListener.class); + + expect(mockListener.getName()).andReturn("mockListener").anyTimes(); + expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) + .andReturn(false).atLeastOnce(); + expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) + .andReturn(false).atLeastOnce(); + + replay(mockListener); + deviceManager.addListener(mockListener); + verify(mockListener); + reset(mockListener); + + ITopologyService mockTopology = createMock(ITopologyService.class); + expect(mockTopology.getL2DomainId(DatapathId.of(1L))). + andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(5L))). + andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(10L))). + andReturn(DatapathId.of(10L)).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(50L))). + andReturn(DatapathId.of(10L)).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(anyLong()), OFPort.of(anyShort()))) + .andReturn(false).anyTimes(); + expect(mockTopology.isInSameBroadcastDomain(DatapathId.of(anyLong()), OFPort.of(anyShort()), + DatapathId.of(anyLong()), OFPort.of(anyShort()))) + .andReturn(false).anyTimes(); + + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), OFPort.of(anyShort()))) + .andReturn(true).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(5L), OFPort.of(1), DatapathId.of(50L), OFPort.of(1))) + .andReturn(false).anyTimes(); + + Date topologyUpdateTime = new Date(); + expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). + anyTimes(); + + replay(mockTopology); + + deviceManager.topology = mockTopology; + // suppress (1L, 1) and (10L, 1) + deviceManager.addSuppressAPs(DatapathId.of(1L), OFPort.of(1)); + deviceManager.addSuppressAPs(DatapathId.of(10L), OFPort.of(1)); + + Calendar c = Calendar.getInstance(); + Entity entity0 = new Entity(MacAddress.of(1L), null, null, null, null, c.getTime()); + // No attachment point should be learnt on 1L, 1 + Entity entity1 = new Entity(MacAddress.of(1L), null, IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), c.getTime()); + c.add(Calendar.SECOND, 1); + Entity entity2 = new Entity(MacAddress.of(1L), null, IPv4Address.of(1), DatapathId.of(5L), OFPort.of(1), c.getTime()); + c.add(Calendar.SECOND, 1); + Entity entity3 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(10L), OFPort.of(1), c.getTime()); + c.add(Calendar.SECOND, 1); + Entity entity4 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(50L), OFPort.of(1), c.getTime()); + + IDevice d; + SwitchPort[] aps; + IPv4Address[] ips; + + mockListener.deviceAdded(isA(IDevice.class)); + mockListener.deviceIPV4AddrChanged((isA(IDevice.class))); + replay(mockListener); + + // TODO: we currently do learn entities on suppressed APs + // // cannot learn device on suppressed AP + // d = deviceManager.learnDeviceByEntity(entity1); + // assertNull(d); + + deviceManager.learnDeviceByEntity(entity0); + d = deviceManager.learnDeviceByEntity(entity1); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertEquals(aps.length, 0); + verifyEntityArray(new Entity[] { entity0, entity1} , (Device)d); + ips = d.getIPv4Addresses(); + assertArrayEquals(new Integer[] { 1 }, ips); + verify(mockListener); + + reset(mockListener); + mockListener.deviceMoved((isA(IDevice.class))); + //mockListener.deviceIPV4AddrChanged((isA(IDevice.class))); + replay(mockListener); + d = deviceManager.learnDeviceByEntity(entity2); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(5L), OFPort.of(1)) }, aps); + verifyEntityArray(new Entity[] { entity0, entity1, entity2 } , (Device)d); + ips = d.getIPv4Addresses(); + assertArrayEquals(new Integer[] { 1 }, ips); + verify(mockListener); + + reset(mockListener); + replay(mockListener); + + d = deviceManager.learnDeviceByEntity(entity3); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(5L), OFPort.of(1)) }, aps); + verifyEntityArray(new Entity[] { entity0, entity1, entity2, entity3 } , (Device)d); + ips = d.getIPv4Addresses(); + assertArrayEquals(new Integer[] { 1 }, ips); + verify(mockListener); + + reset(mockListener); + mockListener.deviceMoved((isA(IDevice.class))); + replay(mockListener); + + d = deviceManager.learnDeviceByEntity(entity4); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(5L), OFPort.of(1)), + new SwitchPort(DatapathId.of(50L), OFPort.of(1)) }, aps); + verifyEntityArray(new Entity[] { entity0, entity1, entity2, entity3, entity4} , (Device)d); + ips = d.getIPv4Addresses(); + assertArrayEquals(new Integer[] { 1 }, ips); + verify(mockListener); + } + + @Test + public void testBDAttachmentPointLearning() throws Exception { + ITopologyService mockTopology = createMock(ITopologyService.class); + expect(mockTopology.getL2DomainId(DatapathId.of(anyLong()))).andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), OFPort.of(anyShort()))). + andReturn(true).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(1L), OFPort.of(1))). + andReturn(false).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(1L), OFPort.of(2))). + andReturn(true).anyTimes(); + expect(mockTopology.isInSameBroadcastDomain(DatapathId.of(1L), OFPort.of(1), + DatapathId.of(1L), OFPort.of(2))).andReturn(true).anyTimes(); + expect(mockTopology.isInSameBroadcastDomain(DatapathId.of(1L), OFPort.of(2), + DatapathId.of(1L), OFPort.of(1))).andReturn(true).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(anyLong()), OFPort.of(anyShort()), DatapathId.of(anyLong()), OFPort.of(anyShort()))).andReturn(false).anyTimes(); + + Date topologyUpdateTime = new Date(); + expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). + anyTimes(); + + replay(mockTopology); + + deviceManager.topology = mockTopology; + + Calendar c = Calendar.getInstance(); + Entity entity1 = new Entity(MacAddress.of(1L), null, IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), c.getTime()); + c.add(Calendar.MILLISECOND, + (int)AttachmentPoint.OPENFLOW_TO_EXTERNAL_TIMEOUT/ 2); + Entity entity2 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(1L), OFPort.of(2), c.getTime()); + c.add(Calendar.MILLISECOND, + (int)AttachmentPoint.OPENFLOW_TO_EXTERNAL_TIMEOUT / 2 + 1); + Entity entity3 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(1L), OFPort.of(2), c.getTime()); + + IDevice d; + SwitchPort[] aps; + + d = deviceManager.learnDeviceByEntity(entity1); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)) }, aps); + + // this timestamp is too soon; don't switch + d = deviceManager.learnDeviceByEntity(entity2); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)) }, aps); + + // it should switch when we learn with a timestamp after the + // timeout + d = deviceManager.learnDeviceByEntity(entity3); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(2)) }, aps); + } + + /** + * This test verifies that the learning behavior on OFPP_LOCAL ports. + * Once a host is learned on OFPP_LOCAL, it is allowed to move only from + * one OFPP_LOCAL to another OFPP_LOCAL port. + * @throws Exception + */ + @Test + public void testLOCALAttachmentPointLearning() throws Exception { + ITopologyService mockTopology = createMock(ITopologyService.class); + expect(mockTopology.getL2DomainId(DatapathId.of(anyLong()))). + andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), OFPort.of(anyShort()))). + andReturn(true).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(1L), OFPort.of(1))). + andReturn(false).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(1L), OFPort.LOCAL)). + andReturn(false).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(1L), OFPort.of(2))). + andReturn(true).anyTimes(); + expect(mockTopology.isInSameBroadcastDomain(DatapathId.of(1L), OFPort.of(1), + DatapathId.of(1L), OFPort.LOCAL)).andReturn(true).anyTimes(); + expect(mockTopology.isInSameBroadcastDomain(DatapathId.of(1L), OFPort.LOCAL, + DatapathId.of(1L), OFPort.of(2))).andReturn(true).anyTimes(); + expect(mockTopology.isInSameBroadcastDomain(DatapathId.of(1L), OFPort.of(2), + DatapathId.of(1L), OFPort.LOCAL)).andReturn(true).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(anyLong()), OFPort.of(anyShort()), DatapathId.of(anyLong()), OFPort.of(anyShort()))).andReturn(false).anyTimes(); + + Date topologyUpdateTime = new Date(); + expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). + anyTimes(); + + replay(mockTopology); + + deviceManager.topology = mockTopology; + + Calendar c = Calendar.getInstance(); + Entity entity1 = new Entity(MacAddress.of(1L), null, IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), c.getTime()); + c.add(Calendar.MILLISECOND, + (int)AttachmentPoint.OPENFLOW_TO_EXTERNAL_TIMEOUT/ 2); + Entity entity2 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(1L), OFPort.LOCAL, c.getTime()); + c.add(Calendar.MILLISECOND, + (int)AttachmentPoint.OPENFLOW_TO_EXTERNAL_TIMEOUT + 1); + Entity entity3 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(1L), OFPort.of(2), c.getTime()); + + IDevice d; + SwitchPort[] aps; + + d = deviceManager.learnDeviceByEntity(entity1); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)) }, aps); + + // Ensure that the attachment point changes to OFPP_LOCAL + d = deviceManager.learnDeviceByEntity(entity2); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.LOCAL) }, aps); + + // Even though the new attachment point is consistent with old + // and the time has elapsed, OFPP_LOCAL attachment point should + // be maintained. + d = deviceManager.learnDeviceByEntity(entity3); + assertEquals(1, deviceManager.getAllDevices().size()); + aps = d.getAttachmentPoints(); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.LOCAL) }, aps); + } + + private static void + mockTopologyForPacketInTests(ITopologyService mockTopology) { + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))). + andReturn(true). + anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(EasyMock.anyLong()), + OFPort.of(EasyMock.anyShort()), + DatapathId.of(EasyMock.anyLong()), + OFPort.of(EasyMock.anyShort()))).andReturn(false). + anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(EasyMock.anyLong()), + OFPort.of(EasyMock.anyShort()))) + .andReturn(false) + .anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(anyLong()))).andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.isInSameBroadcastDomain(DatapathId.of(anyLong()), + OFPort.of(anyShort()), + DatapathId.of(anyLong()), + OFPort.of(anyShort()))) + .andReturn(false).anyTimes(); + + } + + private Command dispatchPacketIn(long swId, OFPacketIn pi, + FloodlightContext cntx) { + IOFSwitch sw = getMockSwitchService().getSwitch(DatapathId.of(swId)); + Ethernet eth = new Ethernet(); + eth.deserialize(pi.getData(), 0, pi.getData().length); + IFloodlightProviderService.bcStore.put(cntx, + IFloodlightProviderService.CONTEXT_PI_PAYLOAD, + eth); + return deviceManager.receive(sw, pi, cntx); + } + + /** + * Verify that the given device exactly matches the given fields. E.g., + * if ip is not null we expect the device to have exactly one IP address. + * swId and port are the attachment point port. + * Vlan and ip are optional all other fields must be specified. + * @return + */ + private static void verifyDevice(IDevice d, long mac, Short vlan, Integer ip, + long swId, int port) { + assertNotNull(d); + assertEquals(mac, d.getMACAddress()); + if (vlan == null) + assertArrayEquals(new Short[0], d.getVlanId()); + else + assertArrayEquals(new Short[] { vlan }, d.getVlanId()); + + if (ip == null) + assertArrayEquals(new Integer[0], d.getIPv4Addresses()); + else + assertArrayEquals(new Integer[] { ip }, d.getIPv4Addresses()); + + SwitchPort expectedAp = new SwitchPort(DatapathId.of(swId), OFPort.of(port)); + assertArrayEquals(new SwitchPort[] { expectedAp }, + d.getAttachmentPoints()); + } + + + @Test + public void testPacketInBasic() throws Exception { + MacAddress deviceMac = + ((Ethernet)this.testARPReplyPacket_1).getSourceMACAddress(); + OFPacketIn packetIn = testARPReplyPacketIn_1; + Integer ipaddr = IPv4.toIPv4Address("192.168.1.1"); + + // Mock up our expected behavior + ITopologyService mockTopology = createMock(ITopologyService.class); + deviceManager.topology = mockTopology; + mockTopologyForPacketInTests(mockTopology); + replay(mockTopology); + + FloodlightContext cntx = new FloodlightContext(); + Command cmd = dispatchPacketIn(1L, packetIn, cntx); + verify(mockTopology); + assertEquals(Command.CONTINUE, cmd); + // Verify the device + Device rdevice = (Device) + deviceManager.findDevice(deviceMac, + VlanVid.ofVlan(5), null, null, null); + verifyDevice(rdevice, deviceMac.getLong(), + (short) 5, ipaddr, 1L, 1); + IDevice cntxSrcDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_SRC_DEVICE); + assertEquals(rdevice, cntxSrcDev); + IDevice cntxDstDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_DST_DEVICE); + assertNull(cntxDstDev); + + Device result = null; + Iterator<? extends IDevice> dstiter = + deviceManager.queryDevices(null, null, IPv4Address.of(ipaddr), + null, null); + if (dstiter.hasNext()) { + result = (Device)dstiter.next(); + } + assertFalse("There shouldn't be more than 1 device", dstiter.hasNext()); + assertEquals(rdevice, result); + + + //----------------- + // Test packetIn again with a different source port. Should be + // the same device + reset(mockTopology); + mockTopologyForPacketInTests(mockTopology); + replay(mockTopology); + + // trigger the packet in + cntx = new FloodlightContext(); + packetIn = packetIn.createBuilder().setInPort(OFPort.of(2)).build(); + cmd = dispatchPacketIn(5L, packetIn, cntx); + verify(mockTopology); + // Verify the replay matched our expectations + assertEquals(Command.CONTINUE, cmd); + + // Verify the device + rdevice = (Device) + deviceManager.findDevice(deviceMac, + VlanVid.ofVlan(5), null, null, null); + verifyDevice(rdevice, deviceMac.getLong(), + (short)5, ipaddr, 5L, 2); + cntxSrcDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_SRC_DEVICE); + assertEquals(rdevice, cntxSrcDev); + cntxDstDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_DST_DEVICE); + assertNull(cntxDstDev); + // There can be only one device + assertEquals(1, deviceManager.getAllDevices().size()); + + //---------------------------- + // Test packetIn with a different packet going the reverse direction. + // We should now get source and dest device in the context + //==> The destination device in this step has been learned just before + MacAddress srcMac = testUDPPacket.getSourceMACAddress(); + MacAddress dstMac = deviceMac; + reset(mockTopology); + mockTopologyForPacketInTests(mockTopology); + replay(mockTopology); + // trigger the packet in + cntx = new FloodlightContext(); + cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); + verify(mockTopology); + + assertEquals(Command.CONTINUE, cmd); + IDevice srcDev = + deviceManager.findDevice(srcMac, VlanVid.ofVlan(5), null, null, null); + verifyDevice(srcDev, srcMac.getLong(), (short)5, null, + 1L, testUDPPacketIn.getInPort().getShortPortNumber()); + + IDevice dstDev = + deviceManager.findDevice(dstMac, VlanVid.ofVlan(5), null, null, null); + verifyDevice(dstDev, dstMac.getLong(), (short)5, ipaddr, 5L, 2); + + cntxSrcDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_SRC_DEVICE); + assertEquals(srcDev, cntxSrcDev); + + cntxDstDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_DST_DEVICE); + assertEquals(dstDev, cntxDstDev); + + assertEquals(2, deviceManager.getAllDevices().size()); + } + + /** + * This test ensures the device manager learns the source device + * corresponding to the senderHardwareAddress and senderProtocolAddress + * in an ARP response whenever the senderHardwareAddress is different + * from the source MAC address of the Ethernet frame. + * + * @throws Exception + */ + @Test + public void testDeviceLearningFromArpResponseData() throws Exception { + ARP arp = (ARP)((Ethernet)this.testARPReplyPacket_2).getPayload(); + MacAddress senderMac = MacAddress.of(arp.getSenderHardwareAddress()); + MacAddress sourceMac = + ((Ethernet)this.testARPReplyPacket_2) + .getSourceMACAddress(); + Integer ipaddr = IPv4.toIPv4Address("192.168.1.1"); + OFPacketIn packetIn = testARPReplyPacketIn_2; + + // Mock up our expected behavior + ITopologyService mockTopology = createMock(ITopologyService.class); + deviceManager.topology = mockTopology; + mockTopologyForPacketInTests(mockTopology); + replay(mockTopology); + + + FloodlightContext cntx = new FloodlightContext(); + Command cmd = dispatchPacketIn(1L, packetIn, cntx); + verify(mockTopology); + assertEquals(Command.CONTINUE, cmd); + // Verify the device for the sender HW address + Device senderDev = (Device) + deviceManager.findDevice(senderMac, VlanVid.ofVlan(5), null, null, null); + verifyDevice(senderDev, senderMac.getLong(), (short)5, ipaddr, 1L, 1); + + Device result = null; + Iterator<? extends IDevice> dstiter = + deviceManager.queryDevices(null, null, IPv4Address.of(ipaddr), + null, null); + if (dstiter.hasNext()) { + result = (Device)dstiter.next(); + } + assertFalse("There shouldn't be more than 1 device", dstiter.hasNext()); + assertEquals(senderDev, result); + + + + // Verify the device for the source MAC + Device srcDev = (Device) + deviceManager.findDevice(sourceMac, VlanVid.ofVlan(5), null, null, null); + // must NOT learn IP on this device + verifyDevice(srcDev, sourceMac.getLong(), (short)5, null, 1L, 1); + assertFalse("Device must differ", srcDev.equals(senderDev)); + // Context is annotated with this device, not the device associated + // with ARP sender address + IDevice cntxSrcDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_SRC_DEVICE); + assertEquals(srcDev, cntxSrcDev); + + assertEquals(2, deviceManager.getAllDevices().size()); + } + + + @Test + public void testPacketInInvalidSrcMac() throws Exception { + // Mock up our expected behavior + ITopologyService mockTopology = createMock(ITopologyService.class); + deviceManager.topology = mockTopology; + mockTopologyForPacketInTests(mockTopology); + replay(mockTopology); + FloodlightContext cntx = new FloodlightContext(); + + testUDPPacket.setSourceMACAddress(Ethernet.toByteArray(0L)); + updateUDPPacketIn(); + Command cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); + assertEquals(Command.STOP, cmd); + IDevice cntxSrcDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_SRC_DEVICE); + assertNull(cntxSrcDev); + IDevice cntxDstDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_DST_DEVICE); + assertNull(cntxDstDev); + + testUDPPacket.setSourceMACAddress(Ethernet.toByteArray(-1L)); + updateUDPPacketIn(); + cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); + assertEquals(Command.STOP, cmd); + cntxSrcDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_SRC_DEVICE); + assertNull(cntxSrcDev); + cntxDstDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_DST_DEVICE); + assertNull(cntxDstDev); + + // MAC with only the multicast bit set + testUDPPacket.setSourceMACAddress(new byte[] { 1, 0, 0, 0, 0, 0 }); + updateUDPPacketIn(); + cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); + assertEquals(Command.STOP, cmd); + cntxSrcDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_SRC_DEVICE); + assertNull(cntxSrcDev); + cntxDstDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_DST_DEVICE); + assertNull(cntxDstDev); + + // Now use a real MAC. We should get a src device + testUDPPacket.setSourceMACAddress(Ethernet.toByteArray(1L)); + updateUDPPacketIn(); + cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); + assertEquals(Command.CONTINUE, cmd); + cntxSrcDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_SRC_DEVICE); + verifyDevice(cntxSrcDev, 1L, (short)5, null, + 1L, testUDPPacketIn.getInPort().getShortPortNumber()); + + cntxDstDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_DST_DEVICE); + assertNull(cntxDstDev); + verify(mockTopology); + } + + + @Test + public void testPacketInInvalidDstMac() throws Exception { + // Mock up our expected behavior + ITopologyService mockTopology = createMock(ITopologyService.class); + deviceManager.topology = mockTopology; + mockTopologyForPacketInTests(mockTopology); + replay(mockTopology); + FloodlightContext cntx = new FloodlightContext(); + + MacAddress srcMac = testUDPPacket.getSourceMACAddress(); + MacAddress dstMac = testUDPPacket.getDestinationMACAddress(); + + // Prime device manager with the source device + Command cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); + assertEquals(Command.CONTINUE, cmd); + IDevice cntxSrcDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_SRC_DEVICE); + verifyDevice(cntxSrcDev, srcMac.getLong(), (short)5, null, + 1L, testUDPPacketIn.getInPort().getShortPortNumber()); + IDevice cntxDstDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_DST_DEVICE); + assertNull(cntxDstDev); + IDevice expectedSrcDev = cntxSrcDev; + + // Create a device for the destination. We can use testARPPacketIn_1 + // for that. + cntx = new FloodlightContext(); + // Prime device manager with the source device + cmd = dispatchPacketIn(1L, testARPReplyPacketIn_1, cntx); + assertEquals(Command.CONTINUE, cmd); + cntxSrcDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_SRC_DEVICE); + // yes: we check that cntxSrcDev matched dstMAC because we are + // just adding the dest device + int ip = IPv4.toIPv4Address("192.168.1.1"); + verifyDevice(cntxSrcDev, dstMac.getLong(), (short)5, ip, + 1L, testARPReplyPacketIn_1.getInPort().getShortPortNumber()); + // yes: we set the expected dst device to the current srcDev + IDevice expectedDstDev = cntxSrcDev; + + //------------------------------- + // Let the real tests begin + + cntx = new FloodlightContext(); + testUDPPacket.setDestinationMACAddress(Ethernet.toByteArray(0L)); + updateUDPPacketIn(); + cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); + assertEquals(Command.STOP, cmd); + cntxDstDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_DST_DEVICE); + assertNull(cntxDstDev); + + // use a real dest mac + cntx = new FloodlightContext(); + testUDPPacket.setDestinationMACAddress(dstMac); + updateUDPPacketIn(); + cmd = dispatchPacketIn(1L, testUDPPacketIn, cntx); + assertEquals(Command.CONTINUE, cmd); + cntxSrcDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_SRC_DEVICE); + assertEquals(expectedSrcDev, cntxSrcDev); + cntxDstDev = IDeviceService.fcStore.get(cntx, + IDeviceService.CONTEXT_DST_DEVICE); + assertEquals(expectedDstDev, cntxDstDev); + + verify(mockTopology); + } + + /** + * Note: Entity expiration does not result in device moved notification. + * @throws Exception + */ + public void doTestEntityExpiration() throws Exception { + IDeviceListener mockListener = + createMock(IDeviceListener.class); + expect(mockListener.getName()).andReturn("mockListener").anyTimes(); + expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) + .andReturn(false).atLeastOnce(); + expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) + .andReturn(false).atLeastOnce(); + + ITopologyService mockTopology = createMock(ITopologyService.class); + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))).andReturn(true).anyTimes(); + + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(1L), OFPort.of(1))).andReturn(false).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(5L), OFPort.of(1))).andReturn(false).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(1L))).andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(5L))).andReturn(DatapathId.of(5L)).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(1L), OFPort.of(1), DatapathId.of(5L), OFPort.of(1))). + andReturn(false).anyTimes(); + + Date topologyUpdateTime = new Date(); + expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). + anyTimes(); + + replay(mockTopology); + deviceManager.topology = mockTopology; + + Calendar c = Calendar.getInstance(); + Entity entity1 = new Entity(MacAddress.of(1L), null, IPv4Address.of(2), DatapathId.of(1L), OFPort.of(1), c.getTime()); + c.add(Calendar.MILLISECOND, -DeviceManagerImpl.ENTITY_TIMEOUT-1); + Entity entity2 = new Entity(MacAddress.of(1L), null, IPv4Address.of(1), DatapathId.of(5L), OFPort.of(1), c.getTime()); + + deviceManager.learnDeviceByEntity(entity1); + IDevice d = deviceManager.learnDeviceByEntity(entity2); + assertArrayEquals(new Integer[] { 1, 2 }, d.getIPv4Addresses()); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)), + new SwitchPort(DatapathId.of(5L), OFPort.of(1))}, + d.getAttachmentPoints()); + Iterator<? extends IDevice> diter = + deviceManager.queryClassDevices(d.getEntityClass(), + null, null, IPv4Address.of(1), null, null); + assertTrue(diter.hasNext()); + assertEquals(d.getDeviceKey(), diter.next().getDeviceKey()); + diter = deviceManager.queryClassDevices(d.getEntityClass(), + null, null, IPv4Address.of(2), null, null); + assertTrue(diter.hasNext()); + assertEquals(d.getDeviceKey(), diter.next().getDeviceKey()); + + replay(mockListener); + deviceManager.addListener(mockListener); + verify(mockListener); + reset(mockListener); + + mockListener.deviceIPV4AddrChanged(isA(IDevice.class)); + replay(mockListener); + deviceManager.entityCleanupTask.reschedule(0, null); + + d = deviceManager.getDevice(d.getDeviceKey()); + assertArrayEquals(new Integer[] { 2 }, d.getIPv4Addresses()); + + // Attachment points are not removed, previous ones are still valid. + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)), + new SwitchPort(DatapathId.of(5L), OFPort.of(1)) }, + d.getAttachmentPoints()); + diter = deviceManager.queryClassDevices(d.getEntityClass(), + null, null, IPv4Address.of(2), null, null); + assertTrue(diter.hasNext()); + assertEquals(d.getDeviceKey(), diter.next().getDeviceKey()); + diter = deviceManager.queryClassDevices(d.getEntityClass(), + null, null, IPv4Address.of(1), null, null); + assertFalse(diter.hasNext()); + + d = deviceManager.findDevice(MacAddress.of(1L), null, null, null, null); + assertArrayEquals(new Integer[] { 2 }, d.getIPv4Addresses()); + + // Attachment points are not removed, previous ones are still valid. + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)), + new SwitchPort(DatapathId.of(5L), OFPort.of(1)) }, + d.getAttachmentPoints()); + + verify(mockListener); + } + + public void doTestDeviceExpiration() throws Exception { + IDeviceListener mockListener = + createMock(IDeviceListener.class); + expect(mockListener.getName()).andReturn("mockListener").anyTimes(); + expect(mockListener.isCallbackOrderingPostreq((String)anyObject(), (String)anyObject())) + .andReturn(false).atLeastOnce(); + expect(mockListener.isCallbackOrderingPrereq((String)anyObject(), (String)anyObject())) + .andReturn(false).atLeastOnce(); + + Calendar c = Calendar.getInstance(); + c.add(Calendar.MILLISECOND, -DeviceManagerImpl.ENTITY_TIMEOUT-1); + Entity entity1 = new Entity(MacAddress.of(1L), null, IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), c.getTime()); + Entity entity2 = new Entity(MacAddress.of(1L), null, IPv4Address.of(2), DatapathId.of(5L), OFPort.of(1), c.getTime()); + + ITopologyService mockTopology = createMock(ITopologyService.class); + deviceManager.topology = mockTopology; + + expect(mockTopology.isAttachmentPointPort(DatapathId.of(EasyMock.anyLong()), + OFPort.of(EasyMock.anyShort()))). + andReturn(true). + anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(1L))).andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(5L))).andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(EasyMock.anyLong()), + OFPort.of(EasyMock.anyShort()), + DatapathId.of(EasyMock.anyLong()), + OFPort.of(EasyMock.anyShort()))).andReturn(false). + anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(EasyMock.anyLong()), + OFPort.of(EasyMock.anyShort()))). + andReturn(false).anyTimes(); + replay(mockTopology); + + IDevice d = deviceManager.learnDeviceByEntity(entity2); + d = deviceManager.learnDeviceByEntity(entity1); + assertArrayEquals(new Integer[] { 1, 2 }, d.getIPv4Addresses()); + + replay(mockListener); + deviceManager.addListener(mockListener); + verify(mockListener); + reset(mockListener); + + mockListener.deviceRemoved(isA(IDevice.class)); + replay(mockListener); + deviceManager.entityCleanupTask.reschedule(0, null); + + IDevice r = deviceManager.getDevice(d.getDeviceKey()); + assertNull(r); + Iterator<? extends IDevice> diter = + deviceManager.queryClassDevices(d.getEntityClass(), + null, null, IPv4Address.of(1), null, null); + assertFalse(diter.hasNext()); + + r = deviceManager.findDevice(MacAddress.of(1L), null, null, null, null); + assertNull(r); + + verify(mockListener); + } + + /* + * A ConcurrentHashMap for devices (deviceMap) that can be used to test + * code that specially handles concurrent modification situations. In + * particular, we overwrite values() and will replace / remove all the + * elements returned by values. + * + * The remove flag in the constructor specifies if devices returned by + * values() should be removed or replaced. + */ + protected static class ConcurrentlyModifiedDeviceMap + extends ConcurrentHashMap<Long, Device> { + private static final long serialVersionUID = 7784938535441180562L; + protected boolean remove; + public ConcurrentlyModifiedDeviceMap(boolean remove) { + super(); + this.remove = remove; + } + + @Override + public Collection<Device> values() { + // Get the values from the real map and copy them since + // the collection returned by values can reflect changed + Collection<Device> devs = new ArrayList<Device>(super.values()); + for (Device d: devs) { + if (remove) { + // We remove the device from the underlying map + super.remove(d.getDeviceKey()); + } else { + super.remove(d.getDeviceKey()); + // We add a different Device instance with the same + // key to the map. We'll do some hackery so the device + // is different enough to compare differently in equals + // but otherwise looks the same. + // It's ugly but it works. + // clone entities + Device newDevice = d; + for (Entity e: d.getEntities()) { + Entity newEntity = new Entity (e.macAddress, + e.vlan, + e.ipv4Address, + e.switchDPID, + e.switchPort, + e.lastSeenTimestamp); + if (e.vlan == null) + newEntity.vlan = VlanVid.ofVlan(1); + else + newEntity.vlan = VlanVid.ofVlan(((e.vlan.getVlan() + 1 % 4095)+1)); + newDevice = new Device(newDevice, newEntity, -1); + } + assertEquals(false, newDevice.equals(d)); + super.put(newDevice.getDeviceKey(), newDevice); + } + } + return devs; + } + } + + @Test + public void testEntityExpiration() throws Exception { + doTestEntityExpiration(); + } + + @Test + public void testDeviceExpiration() throws Exception { + doTestDeviceExpiration(); + } + + /* Test correct entity cleanup behavior when a concurrent modification + * occurs. + */ + @Test + public void testEntityExpirationConcurrentModification() throws Exception { + deviceManager.deviceMap = new ConcurrentlyModifiedDeviceMap(false); + doTestEntityExpiration(); + } + + /* Test correct entity cleanup behavior when a concurrent remove + * occurs. + */ + @Test + public void testDeviceExpirationConcurrentRemove() throws Exception { + deviceManager.deviceMap = new ConcurrentlyModifiedDeviceMap(true); + doTestDeviceExpiration(); + } + + /* Test correct entity cleanup behavior when a concurrent modification + * occurs. + */ + @Test + public void testDeviceExpirationConcurrentModification() throws Exception { + deviceManager.deviceMap = new ConcurrentlyModifiedDeviceMap(false); + doTestDeviceExpiration(); + } + + + @Test + public void testAttachmentPointFlapping() throws Exception { + Calendar c = Calendar.getInstance(); + + ITopologyService mockTopology = createMock(ITopologyService.class); + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))).andReturn(true).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))). + andReturn(false).anyTimes(); + expect(mockTopology.isInSameBroadcastDomain(DatapathId.of(anyLong()), OFPort.of(anyShort()), + DatapathId.of(anyLong()), OFPort.of(anyShort()))).andReturn(false).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(anyLong()))). + andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(1L), OFPort.of(1), DatapathId.of(1L), OFPort.of(1))). + andReturn(true).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(1L), OFPort.of(1), DatapathId.of(5L), OFPort.of(1))). + andReturn(false).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(1L), OFPort.of(1), DatapathId.of(10L), OFPort.of(1))). + andReturn(false).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(5L), OFPort.of(1), DatapathId.of(10L), OFPort.of(1))). + andReturn(false).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(10L), OFPort.of(1), DatapathId.of(1L), OFPort.of(1))). + andReturn(false).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(5L), OFPort.of(1), DatapathId.of(1L), OFPort.of(1))). + andReturn(false).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(10L), OFPort.of(1), DatapathId.of(5L), OFPort.of(1))). + andReturn(false).anyTimes(); + + Date topologyUpdateTime = new Date(); + expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). + anyTimes(); + + + replay(mockTopology); + deviceManager.topology = mockTopology; + + Entity entity1 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(1L), OFPort.of(1), c.getTime()); + Entity entity1a = new Entity(MacAddress.of(1L), null, IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), c.getTime()); + Entity entity2 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(5L), OFPort.of(1), c.getTime()); + Entity entity3 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(10L), OFPort.of(1), c.getTime()); + entity1.setLastSeenTimestamp(c.getTime()); + c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT/2); + entity1a.setLastSeenTimestamp(c.getTime()); + c.add(Calendar.MILLISECOND, 1); + entity2.setLastSeenTimestamp(c.getTime()); + c.add(Calendar.MILLISECOND, 1); + entity3.setLastSeenTimestamp(c.getTime()); + + + + IDevice d; + d = deviceManager.learnDeviceByEntity(entity1); + d = deviceManager.learnDeviceByEntity(entity1a); + d = deviceManager.learnDeviceByEntity(entity2); + d = deviceManager.learnDeviceByEntity(entity3); + + // all entities are active, so entity3 should win + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(10L), OFPort.of(1)) }, + d.getAttachmentPoints()); + + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(10L), OFPort.of(1)),}, + d.getAttachmentPoints(true)); + + c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT/4); + entity1.setLastSeenTimestamp(c.getTime()); + d = deviceManager.learnDeviceByEntity(entity1); + + // all are still active; entity3 should still win + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)) }, + d.getAttachmentPoints()); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)), + new SwitchPort(DatapathId.of(5L), OFPort.of(1), + ErrorStatus.DUPLICATE_DEVICE), + new SwitchPort(DatapathId.of(10L), OFPort.of(1), + ErrorStatus.DUPLICATE_DEVICE) }, + d.getAttachmentPoints(true)); + + c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT+2000); + entity1.setLastSeenTimestamp(c.getTime()); + d = deviceManager.learnDeviceByEntity(entity1); + + assertEquals(entity1.getActiveSince(), entity1.getLastSeenTimestamp()); + // entity1 should now be the only active entity + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)) }, + d.getAttachmentPoints()); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)) }, + d.getAttachmentPoints(true)); + } + + + @Test + public void testAttachmentPointFlappingTwoCluster() throws Exception { + Calendar c = Calendar.getInstance(); + + ITopologyService mockTopology = createMock(ITopologyService.class); + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))).andReturn(true).anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))). + andReturn(false).anyTimes(); + expect(mockTopology.isInSameBroadcastDomain(DatapathId.of(anyLong()), OFPort.of(anyShort()), + DatapathId.of(anyLong()), OFPort.of(anyShort()))).andReturn(false).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(1L))). + andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(5L))). + andReturn(DatapathId.of(5L)).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(1L), OFPort.of(1), DatapathId.of(1L), OFPort.of(2))). + andReturn(false).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(1L), OFPort.of(2), DatapathId.of(5L), OFPort.of(1))). + andReturn(false).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(5L), OFPort.of(1), DatapathId.of(5L), OFPort.of(2))). + andReturn(false).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(1L), OFPort.of(2), DatapathId.of(1L), OFPort.of(1))). + andReturn(false).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(1L), OFPort.of(1), DatapathId.of(5L), OFPort.of(1))). + andReturn(false).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(1L), OFPort.of(1), DatapathId.of(5L), OFPort.of(2))). + andReturn(false).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(5L), OFPort.of(2), DatapathId.of(5L), OFPort.of(1))). + andReturn(false).anyTimes(); + + Date topologyUpdateTime = new Date(); + expect(mockTopology.getLastUpdateTime()).andReturn(topologyUpdateTime). + anyTimes(); + + replay(mockTopology); + deviceManager.topology = mockTopology; + + Entity entity1 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(1L), OFPort.of(1), c.getTime()); + Entity entity2 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(1L), OFPort.of(2), c.getTime()); + Entity entity3 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(5L), OFPort.of(1), c.getTime()); + Entity entity4 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(5L), OFPort.of(2), c.getTime()); + entity1.setLastSeenTimestamp(c.getTime()); + c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT/2); + c.add(Calendar.MILLISECOND, 1); + entity2.setLastSeenTimestamp(c.getTime()); + c.add(Calendar.MILLISECOND, 1); + entity3.setLastSeenTimestamp(c.getTime()); + c.add(Calendar.MILLISECOND, 1); + entity4.setLastSeenTimestamp(c.getTime()); + + deviceManager.learnDeviceByEntity(entity1); + deviceManager.learnDeviceByEntity(entity2); + deviceManager.learnDeviceByEntity(entity3); + IDevice d = deviceManager.learnDeviceByEntity(entity4); + + // all entities are active, so entities 2,4 should win + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(2)), + new SwitchPort(DatapathId.of(5L), OFPort.of(2)) }, + d.getAttachmentPoints()); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(2)), + new SwitchPort(DatapathId.of(5L), OFPort.of(2))}, + d.getAttachmentPoints(true)); + + c.add(Calendar.MILLISECOND, 1); + entity1.setLastSeenTimestamp(c.getTime()); + d = deviceManager.learnDeviceByEntity(entity1); + + // all entities are active, so entities 2,4 should win + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)), + new SwitchPort(DatapathId.of(5L), OFPort.of(2)) }, + d.getAttachmentPoints()); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)), + new SwitchPort(DatapathId.of(5L), OFPort.of(2)), + new SwitchPort(DatapathId.of(1L), OFPort.of(2), ErrorStatus.DUPLICATE_DEVICE)}, + d.getAttachmentPoints(true)); + + c.add(Calendar.MILLISECOND, Entity.ACTIVITY_TIMEOUT+1); + entity1.setLastSeenTimestamp(c.getTime()); + d = deviceManager.learnDeviceByEntity(entity1); + + // entities 3,4 are still in conflict, but 1 should be resolved + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)), + new SwitchPort(DatapathId.of(5L), OFPort.of(2)) }, + d.getAttachmentPoints()); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)), + new SwitchPort(DatapathId.of(5L), OFPort.of(2))}, + d.getAttachmentPoints(true)); + + entity3.setLastSeenTimestamp(c.getTime()); + d = deviceManager.learnDeviceByEntity(entity3); + + // no conflicts, 1 and 3 will win + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)), + new SwitchPort(DatapathId.of(5L), OFPort.of(1)) }, + d.getAttachmentPoints()); + assertArrayEquals(new SwitchPort[] { new SwitchPort(DatapathId.of(1L), OFPort.of(1)), + new SwitchPort(DatapathId.of(5L), OFPort.of(1)) }, + d.getAttachmentPoints(true)); + + } + + protected void doTestDeviceQuery() throws Exception { + Entity entity1 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(1), IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), new Date()); + Entity entity2 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.of(2), DatapathId.of(1L), OFPort.of(2), new Date()); + Entity entity3 = new Entity(MacAddress.of(3L), VlanVid.ofVlan(3), IPv4Address.of(3), DatapathId.of(5L), OFPort.of(1), new Date()); + Entity entity4 = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), IPv4Address.of(3), DatapathId.of(5L), OFPort.of(2), new Date()); + Entity entity5 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(4), IPv4Address.of(3), DatapathId.of(5L), OFPort.of(2), new Date()); + + Device d1 = deviceManager.learnDeviceByEntity(entity1); + deviceManager.learnDeviceByEntity(entity2); + Device d3 = deviceManager.learnDeviceByEntity(entity3); + Device d4 = deviceManager.learnDeviceByEntity(entity4); + + IDevice d; + + Iterator<? extends IDevice> iter = + deviceManager.queryDevices(null, VlanVid.ofVlan(1), IPv4Address.of(1), null, null); + int count = 0; + while (iter.hasNext()) { + count += 1; + d = iter.next(); + assertEquals(d1.getDeviceKey(), d.getDeviceKey()); + } + assertEquals(1, count); + + iter = deviceManager.queryDevices(null, VlanVid.ofVlan(3), IPv4Address.of(3), null, null); + count = 0; + while (iter.hasNext()) { + count += 1; + d = iter.next(); + assertEquals(d3.getDeviceKey(), d.getDeviceKey()); + } + assertEquals(1, count); + + iter = deviceManager.queryDevices(null, VlanVid.ofVlan(1), IPv4Address.of(3), null, null); + count = 0; + while (iter.hasNext()) { + count += 1; + iter.next(); + } + assertEquals(0, count); + + Device d5 = deviceManager.learnDeviceByEntity(entity5); + iter = deviceManager.queryDevices(null, VlanVid.ofVlan(4), IPv4Address.of(3), null, null); + count = 0; + Set<Long> deviceKeysFromIterator = new HashSet<Long>(); + while (iter.hasNext()) { + count += 1; + d = iter.next(); + deviceKeysFromIterator.add(d.getDeviceKey()); + } + Set<Long> expectedDeviceKeys = new HashSet<Long>(); + expectedDeviceKeys.add(d4.getDeviceKey()); + expectedDeviceKeys.add(d5.getDeviceKey()); + assertEquals(expectedDeviceKeys, deviceKeysFromIterator); + assertEquals(2, count); + + + iter = deviceManager.queryDevices(MacAddress.of(1L), null, null, null, null); + count = 0; + deviceKeysFromIterator = new HashSet<Long>(); + while (iter.hasNext()) { + count += 1; + d = iter.next(); + deviceKeysFromIterator.add(d.getDeviceKey()); + } + expectedDeviceKeys = new HashSet<Long>(); + expectedDeviceKeys.add(d1.getDeviceKey()); + expectedDeviceKeys.add(d5.getDeviceKey()); + assertEquals(expectedDeviceKeys, deviceKeysFromIterator); + assertEquals(2, count); + } + + @Test + public void testDeviceIndex() throws Exception { + EnumSet<IDeviceService.DeviceField> indexFields = + EnumSet.noneOf(IDeviceService.DeviceField.class); + indexFields.add(IDeviceService.DeviceField.IPV4); + indexFields.add(IDeviceService.DeviceField.VLAN); + deviceManager.addIndex(false, indexFields); + + indexFields = EnumSet.noneOf(IDeviceService.DeviceField.class); + deviceManager.addIndex(false, indexFields); + + ITopologyService mockTopology = createMock(ITopologyService.class); + deviceManager.topology = mockTopology; + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))). + andReturn(true).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(EasyMock.anyLong()))).andReturn(DatapathId.of(1L)).anyTimes(); + replay(mockTopology); + doTestDeviceQuery(); + } + + @Test + public void testDeviceQuery() throws Exception { + ITopologyService mockTopology = createMock(ITopologyService.class); + deviceManager.topology = mockTopology; + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))). + andReturn(true).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(EasyMock.anyLong()))).andReturn(DatapathId.of(1L)).anyTimes(); + replay(mockTopology); + + doTestDeviceQuery(); + } + + protected void doTestDeviceClassQuery() throws Exception { + Entity entity1 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(1), IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), new Date()); + Entity entity2 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.of(2), DatapathId.of(1L), OFPort.of(2), new Date()); + Entity entity3 = new Entity(MacAddress.of(3L), VlanVid.ofVlan(3), IPv4Address.of(3), DatapathId.of(5L), OFPort.of(1), new Date()); + Entity entity4 = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), IPv4Address.of(3), DatapathId.of(5L), OFPort.of(2), new Date()); + Entity entity5 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(4), IPv4Address.of(3), DatapathId.of(5L), OFPort.of(2), new Date()); + + IDevice d1 = deviceManager.learnDeviceByEntity(entity1); + IDevice d2 = deviceManager.learnDeviceByEntity(entity2); + IDevice d3 = deviceManager.learnDeviceByEntity(entity3); + IDevice d4 = deviceManager.learnDeviceByEntity(entity4); + assertEquals(d1.getEntityClass(), d2.getEntityClass()); + assertEquals(d1.getEntityClass(), d3.getEntityClass()); + assertEquals(d1.getEntityClass(), d4.getEntityClass()); + + IDevice d; + + Iterator<? extends IDevice> iter = + deviceManager.queryClassDevices(d1.getEntityClass(), null, + VlanVid.ofVlan(1), IPv4Address.of(1), null, null); + int count = 0; + while (iter.hasNext()) { + count += 1; + d = iter.next(); + assertEquals(d1.getDeviceKey(), d.getDeviceKey()); + } + assertEquals(1, count); + + iter = deviceManager.queryClassDevices(d1.getEntityClass(), null, + VlanVid.ofVlan(3), IPv4Address.of(3), null, null); + count = 0; + while (iter.hasNext()) { + count += 1; + d = iter.next(); + assertEquals(d3.getDeviceKey(), d.getDeviceKey()); + + } + assertEquals(1, count); + + iter = deviceManager.queryClassDevices(d1.getEntityClass(), null, + VlanVid.ofVlan(1), IPv4Address.of(3), null, null); + count = 0; + while (iter.hasNext()) { + count += 1; + iter.next(); + } + assertEquals(0, count); + + IDevice d5 = deviceManager.learnDeviceByEntity(entity5); + assertEquals(d1.getEntityClass(), d5.getEntityClass()); + iter = deviceManager.queryClassDevices(d1.getEntityClass(), null, + VlanVid.ofVlan(4), IPv4Address.of(3), null, null); + count = 0; + Set<Long> deviceKeysFromIterator = new HashSet<Long>(); + while (iter.hasNext()) { + count += 1; + d = iter.next(); + deviceKeysFromIterator.add(d.getDeviceKey()); + } + Set<Long> expectedDeviceKeys = new HashSet<Long>(); + expectedDeviceKeys.add(d4.getDeviceKey()); + expectedDeviceKeys.add(d5.getDeviceKey()); + assertEquals(expectedDeviceKeys, deviceKeysFromIterator); + assertEquals(2, count); + } + + @Test + public void testDeviceClassIndex() throws Exception { + EnumSet<IDeviceService.DeviceField> indexFields = + EnumSet.noneOf(IDeviceService.DeviceField.class); + indexFields.add(IDeviceService.DeviceField.IPV4); + indexFields.add(IDeviceService.DeviceField.VLAN); + deviceManager.addIndex(true, indexFields); + + ITopologyService mockTopology = createMock(ITopologyService.class); + deviceManager.topology = mockTopology; + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))). + andReturn(true).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(EasyMock.anyLong()))).andReturn(DatapathId.of(1L)).anyTimes(); + replay(mockTopology); + + doTestDeviceClassQuery(); + } + + @Test + public void testDeviceClassQuery() throws Exception { + ITopologyService mockTopology = createMock(ITopologyService.class); + deviceManager.topology = mockTopology; + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))).andReturn(true).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(EasyMock.anyLong()))).andReturn(DatapathId.of(1L)).anyTimes(); + replay(mockTopology); + + doTestDeviceClassQuery(); + } + + @Test + public void testFindDevice() throws FloodlightModuleException { + boolean exceptionCaught; + deviceManager.entityClassifier= new MockEntityClassifierMac(); + deviceManager.startUp(null); + + ITopologyService mockTopology = createMock(ITopologyService.class); + deviceManager.topology = mockTopology; + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))). + andReturn(true).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(EasyMock.anyLong()))).andReturn(DatapathId.of(1L)).anyTimes(); + replay(mockTopology); + + Entity entity1 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(1), IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), new Date()); + Entity entity2 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.of(2), DatapathId.of(1L), OFPort.of(2), new Date()); + Entity entity2b = new Entity(MacAddress.of(22L), VlanVid.ofVlan(2), IPv4Address.of(2), DatapathId.of(1L), OFPort.of(2), new Date()); + + Entity entity3 = new Entity(MacAddress.of(3L), VlanVid.ofVlan(1), IPv4Address.of(3), DatapathId.of(2L), OFPort.of(1), new Date()); + Entity entity4 = new Entity(MacAddress.of(4L), VlanVid.ofVlan(2), IPv4Address.of(4), DatapathId.of(2L), OFPort.of(2), new Date()); + + Entity entity5 = new Entity(MacAddress.of(5L), VlanVid.ofVlan(1), IPv4Address.of(5), DatapathId.of(3L), OFPort.of(1), new Date()); + + + IDevice d1 = deviceManager.learnDeviceByEntity(entity1); + IDevice d2 = deviceManager.learnDeviceByEntity(entity2); + IDevice d3 = deviceManager.learnDeviceByEntity(entity3); + IDevice d4 = deviceManager.learnDeviceByEntity(entity4); + IDevice d5 = deviceManager.learnDeviceByEntity(entity5); + + // Make sure the entity classifier worked as expected + assertEquals(MockEntityClassifierMac.testECMac1, d1.getEntityClass()); + assertEquals(MockEntityClassifierMac.testECMac1, d2.getEntityClass()); + assertEquals(MockEntityClassifierMac.testECMac2, d3.getEntityClass()); + assertEquals(MockEntityClassifierMac.testECMac2, d4.getEntityClass()); + assertEquals(DefaultEntityClassifier.entityClass, + d5.getEntityClass()); + + // Look up the device using findDevice() which uses only the primary + // index + assertEquals(d1, deviceManager.findDevice(entity1.getMacAddress(), + entity1.getVlan(), + entity1.getIpv4Address(), + entity1.getSwitchDPID(), + entity1.getSwitchPort())); + // port changed. Device will be found through class index + assertEquals(d1, deviceManager.findDevice(entity1.getMacAddress(), + entity1.getVlan(), + entity1.getIpv4Address(), + entity1.getSwitchDPID(), + OFPort.of(entity1.getSwitchPort().getPortNumber()+1))); + // VLAN changed. No device matches + assertEquals(null, deviceManager.findDevice(entity1.getMacAddress(), + VlanVid.ofVlan(42), + entity1.getIpv4Address(), + entity1.getSwitchDPID(), + entity1.getSwitchPort())); + assertEquals(null, deviceManager.findDevice(entity1.getMacAddress(), + null, + entity1.getIpv4Address(), + entity1.getSwitchDPID(), + entity1.getSwitchPort())); + assertEquals(d2, deviceManager.findDeviceByEntity(entity2)); + assertEquals(null, deviceManager.findDeviceByEntity(entity2b)); + assertEquals(d3, deviceManager.findDevice(entity3.getMacAddress(), + entity3.getVlan(), + entity3.getIpv4Address(), + entity3.getSwitchDPID(), + entity3.getSwitchPort())); + // switch and port not set. throws exception + exceptionCaught = false; + try { + assertEquals(null, deviceManager.findDevice(entity3.getMacAddress(), + entity3.getVlan(), + entity3.getIpv4Address(), + null, + null)); + } + catch (IllegalArgumentException e) { + exceptionCaught = true; + } + if (!exceptionCaught) + fail("findDevice() did not throw IllegalArgumentException"); + assertEquals(d4, deviceManager.findDeviceByEntity(entity4)); + assertEquals(d5, deviceManager.findDevice(entity5.getMacAddress(), + entity5.getVlan(), + entity5.getIpv4Address(), + entity5.getSwitchDPID(), + entity5.getSwitchPort())); + // switch and port not set. throws exception (swith/port are key + // fields of IEntityClassifier but not d5.entityClass + exceptionCaught = false; + try { + assertEquals(d5, deviceManager.findDevice(entity5.getMacAddress(), + entity5.getVlan(), + entity5.getIpv4Address(), + null, + null)); + } + catch (IllegalArgumentException e) { + exceptionCaught = true; + } + if (!exceptionCaught) + fail("findDevice() did not throw IllegalArgumentException"); + + + Entity entityNoClass = new Entity(MacAddress.of(5L), VlanVid.ofVlan(1), IPv4Address.of(5), DatapathId.of(-1L), OFPort.of(1), new Date()); + assertEquals(null, deviceManager.findDeviceByEntity(entityNoClass)); + + + // Now look up destination devices + assertEquals(d1, deviceManager.findClassDevice(d2.getEntityClass(), + entity1.getMacAddress(), + entity1.getVlan(), + entity1.getIpv4Address())); + assertEquals(d1, deviceManager.findClassDevice(d2.getEntityClass(), + entity1.getMacAddress(), + entity1.getVlan(), + null)); + assertEquals(null, deviceManager.findClassDevice(d2.getEntityClass(), + entity1.getMacAddress(), + VlanVid.ofVlan(-1), + IPv4Address.of(0))); + } + + + + @Test + public void testGetIPv4Addresses() { + // Looks like Date is only 1s granularity + + ITopologyService mockTopology = createMock(ITopologyService.class); + deviceManager.topology = mockTopology; + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))). + andReturn(true).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(anyLong()))).andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(EasyMock.anyLong()), + OFPort.of(EasyMock.anyShort()), + DatapathId.of(EasyMock.anyLong()), + OFPort.of(EasyMock.anyShort()))) + .andReturn(false) + .anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(EasyMock.anyLong()), + OFPort.of(EasyMock.anyShort()))) + .andReturn(false) + .anyTimes(); + expect(mockTopology.isInSameBroadcastDomain(DatapathId.of(EasyMock.anyLong()), + OFPort.of(EasyMock.anyShort()), + DatapathId.of(EasyMock.anyLong()), + OFPort.of(EasyMock.anyShort()))). + andReturn(false).anyTimes(); + replay(mockTopology); + + Entity e1 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(1), null, null, null, new Date(2000)); + Device d1 = deviceManager.learnDeviceByEntity(e1); + assertArrayEquals(new Integer[0], d1.getIPv4Addresses()); + + + Entity e2 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.of(2), null, null, new Date(2000)); + Device d2 = deviceManager.learnDeviceByEntity(e2); + d2 = deviceManager.learnDeviceByEntity(e2); + assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); + // More than one entity + Entity e2b = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), null, DatapathId.of(2L), OFPort.of(2), new Date(3000)); + d2 = deviceManager.learnDeviceByEntity(e2b); + assertEquals(2, d2.entities.length); + assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); + // and now add an entity with an IP + Entity e2c = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.of(2), DatapathId.of(2L), OFPort.of(3), new Date(3000)); + d2 = deviceManager.learnDeviceByEntity(e2c); + assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); + assertEquals(3, d2.entities.length); + + // Other devices with different IPs shouldn't interfere + Entity e3 = new Entity(MacAddress.of(3L), VlanVid.ofVlan(3), IPv4Address.of(3), null, null, new Date(4000)); + Entity e3b = new Entity(MacAddress.of(3L), VlanVid.ofVlan(3), IPv4Address.of(3), DatapathId.of(3L), OFPort.of(3), new Date(4400)); + Device d3 = deviceManager.learnDeviceByEntity(e3); + d3 = deviceManager.learnDeviceByEntity(e3b); + assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); + assertArrayEquals(new Integer[] { 3 }, d3.getIPv4Addresses()); + + // Add another IP to d3 + Entity e3c = new Entity(MacAddress.of(3L), VlanVid.ofVlan(3), IPv4Address.of(33), DatapathId.of(3L), OFPort.of(3), new Date(4400)); + d3 = deviceManager.learnDeviceByEntity(e3c); + IPv4Address[] ips = d3.getIPv4Addresses(); + Arrays.sort(ips); + assertArrayEquals(new Integer[] { 3, 33 }, ips); + + // Add another device that also claims IP2 but is older than e2 + Entity e4 = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), IPv4Address.of(2), null, null, new Date(1000)); + Entity e4b = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), null, DatapathId.of(4L), OFPort.of(4), new Date(1000)); + Device d4 = deviceManager.learnDeviceByEntity(e4); + assertArrayEquals(new Integer[] { 2 }, d2.getIPv4Addresses()); + assertArrayEquals(new Integer[0], d4.getIPv4Addresses()); + // add another entity to d4 + d4 = deviceManager.learnDeviceByEntity(e4b); + assertArrayEquals(new Integer[0], d4.getIPv4Addresses()); + + // Make e4 and e4a newer + Entity e4c = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), IPv4Address.of(2), null, null, new Date(5000)); + Entity e4d = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), null, DatapathId.of(4L), OFPort.of(5), new Date(5000)); + d4 = deviceManager.learnDeviceByEntity(e4c); + d4 = deviceManager.learnDeviceByEntity(e4d); + assertArrayEquals(new Integer[0], d2.getIPv4Addresses()); + // FIXME: d4 should not return IP4 + assertArrayEquals(new Integer[] { 2 }, d4.getIPv4Addresses()); + + // Add another newer entity to d2 but with different IP + Entity e2d = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.of(22), DatapathId.of(4L), OFPort.of(6), new Date(6000)); + d2 = deviceManager.learnDeviceByEntity(e2d); + assertArrayEquals(new Integer[] { 22 }, d2.getIPv4Addresses()); + assertArrayEquals(new Integer[] { 2 }, d4.getIPv4Addresses()); + + // new IP for d2,d4 but with same timestamp. Both devices get the IP + Entity e2e = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.of(42), DatapathId.of(2L), OFPort.of(4), new Date(7000)); + d2 = deviceManager.learnDeviceByEntity(e2e); + ips= d2.getIPv4Addresses(); + Arrays.sort(ips); + assertArrayEquals(new Integer[] { 22, 42 }, ips); + Entity e4e = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), IPv4Address.of(42), DatapathId.of(4L), OFPort.of(7), new Date(7000)); + d4 = deviceManager.learnDeviceByEntity(e4e); + ips= d4.getIPv4Addresses(); + Arrays.sort(ips); + assertArrayEquals(new Integer[] { 2, 42 }, ips); + + // add a couple more IPs + Entity e2f = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.of(4242), DatapathId.of(2L), OFPort.of(5), new Date(8000)); + d2 = deviceManager.learnDeviceByEntity(e2f); + ips= d2.getIPv4Addresses(); + Arrays.sort(ips); + assertArrayEquals(new Integer[] { 22, 42, 4242 }, ips); + Entity e4f = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), IPv4Address.of(4242), DatapathId.of(4L), OFPort.of(8), new Date(9000)); + d4 = deviceManager.learnDeviceByEntity(e4f); + ips= d4.getIPv4Addresses(); + Arrays.sort(ips); + assertArrayEquals(new Integer[] { 2, 42, 4242 }, ips); + } + + // TODO: this test should really go into a separate class that collects + // unit tests for Device + @Test + public void testGetSwitchPortVlanId() { + Entity entity1 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(1), null, DatapathId.of(10L), OFPort.of(1), new Date()); + Entity entity2 = new Entity(MacAddress.of(1L), null, null, DatapathId.of(10L), OFPort.of(1), new Date()); + Entity entity3 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(3), null, DatapathId.of(1L), OFPort.of(1), new Date()); + Entity entity4 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(42), null, DatapathId.of(1L), OFPort.of(1), new Date()); + Entity[] entities = new Entity[] { entity1, entity2, + entity3, entity4 + }; + Device d = new Device(null,1L, null, null, null, + Arrays.asList(entities), null); + SwitchPort swp1x1 = new SwitchPort(DatapathId.of(1L), OFPort.of(1)); + SwitchPort swp1x2 = new SwitchPort(DatapathId.of(1L), OFPort.of(2)); + SwitchPort swp2x1 = new SwitchPort(DatapathId.of(2L), OFPort.of(1)); + SwitchPort swp10x1 = new SwitchPort(DatapathId.of(10L), OFPort.of(1)); + assertArrayEquals(new Short[] { -1, 1}, + d.getSwitchPortVlanIds(swp10x1)); + assertArrayEquals(new Short[] { 3, 42}, + d.getSwitchPortVlanIds(swp1x1)); + assertArrayEquals(new Short[0], + d.getSwitchPortVlanIds(swp1x2)); + assertArrayEquals(new Short[0], + d.getSwitchPortVlanIds(swp2x1)); + } + + @Test + public void testReclassifyDevice() throws FloodlightModuleException { + MockFlexEntityClassifier flexClassifier = + new MockFlexEntityClassifier(); + deviceManager.entityClassifier= flexClassifier; + deviceManager.startUp(null); + + ITopologyService mockTopology = createMock(ITopologyService.class); + deviceManager.topology = mockTopology; + expect(mockTopology.isAttachmentPointPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))). + andReturn(true).anyTimes(); + expect(mockTopology.getL2DomainId(DatapathId.of(anyLong()))).andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockTopology.isConsistent(DatapathId.of(EasyMock.anyLong()), + OFPort.of(EasyMock.anyShort()), + DatapathId.of(EasyMock.anyLong()), + OFPort.of(EasyMock.anyShort()))) + .andReturn(false) + .anyTimes(); + expect(mockTopology.isBroadcastDomainPort(DatapathId.of(EasyMock.anyLong()), + OFPort.of(EasyMock.anyShort()))) + .andReturn(false) + .anyTimes(); + replay(mockTopology); + + //flexClassifier.createTestEntityClass("Class1"); + + Entity entity1 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(1), IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), new Date()); + Entity entity1b = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), new Date()); + Entity entity2 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(1), IPv4Address.of(2), DatapathId.of(2L), OFPort.of(2), new Date()); + Entity entity2b = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.of(2), DatapathId.of(2L), OFPort.of(2), new Date()); + + + Device d1 = deviceManager.learnDeviceByEntity(entity1); + Device d2 = deviceManager.learnDeviceByEntity(entity2); + Device d1b = deviceManager.learnDeviceByEntity(entity1b); + Device d2b = deviceManager.learnDeviceByEntity(entity2b); + + d1 = deviceManager.getDeviceIteratorForQuery(entity1.getMacAddress(), + entity1.getVlan(), entity1.getIpv4Address(), + entity1.getSwitchDPID(), entity1.getSwitchPort()) + .next(); + d1b = deviceManager.getDeviceIteratorForQuery(entity1b.getMacAddress(), + entity1b.getVlan(), entity1b.getIpv4Address(), + entity1b.getSwitchDPID(), entity1b.getSwitchPort()).next(); + + assertEquals(d1, d1b); + + d2 = deviceManager.getDeviceIteratorForQuery(entity2.getMacAddress(), + entity2.getVlan(), entity2.getIpv4Address(), + entity2.getSwitchDPID(), entity2.getSwitchPort()).next(); + d2b = deviceManager.getDeviceIteratorForQuery(entity2b.getMacAddress(), + entity2b.getVlan(), entity2b.getIpv4Address(), + entity2b.getSwitchDPID(), entity2b.getSwitchPort()).next(); + assertEquals(d2, d2b); + + IEntityClass eC1 = flexClassifier.createTestEntityClass("C1"); + IEntityClass eC2 = flexClassifier.createTestEntityClass("C2"); + + flexClassifier.addVlanEntities((short)1, eC1); + flexClassifier.addVlanEntities((short)2, eC1); + + deviceManager.reclassifyDevice(d1); + deviceManager.reclassifyDevice(d2); + + d1 = deviceManager.deviceMap.get( + deviceManager.primaryIndex.findByEntity(entity1)); + d1b = deviceManager.deviceMap.get( + deviceManager.primaryIndex.findByEntity(entity1b)); + + assertEquals(d1, d1b); + + d2 = deviceManager.deviceMap.get( + deviceManager.primaryIndex.findByEntity(entity2)); + d2b = deviceManager.deviceMap.get( + deviceManager.primaryIndex.findByEntity(entity2b)); + + assertEquals(d2, d2b); + + flexClassifier.addVlanEntities((short)1, eC2); + + deviceManager.reclassifyDevice(d1); + deviceManager.reclassifyDevice(d2); + d1 = deviceManager.deviceMap.get( + deviceManager.primaryIndex.findByEntity(entity1)); + d1b = deviceManager.deviceMap.get( + deviceManager.primaryIndex.findByEntity(entity1b)); + d2 = deviceManager.deviceMap.get( + deviceManager.primaryIndex.findByEntity(entity2)); + d2b = deviceManager.deviceMap.get( + deviceManager.primaryIndex.findByEntity(entity2b)); + + assertNotSame(d1, d1b); + + assertNotSame(d2, d2b); + + flexClassifier.addVlanEntities((short)1, eC1); + deviceManager.reclassifyDevice(d1); + deviceManager.reclassifyDevice(d2); + ClassState classState = deviceManager.classStateMap.get(eC1.getName()); + + Long deviceKey1 = null; + Long deviceKey1b = null; + Long deviceKey2 = null; + Long deviceKey2b = null; + + deviceKey1 = + classState.classIndex.findByEntity(entity1); + deviceKey1b = + classState.classIndex.findByEntity(entity1b); + deviceKey2 = + classState.classIndex.findByEntity(entity2); + deviceKey2b = + classState.classIndex.findByEntity(entity2b); + + assertEquals(deviceKey1, deviceKey1b); + + assertEquals(deviceKey2, deviceKey2b); + } + + @Test + public void testSyncEntity() { + Date d1 = new Date(); + Date d2 = new Date(0); + Entity e1 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(3), DatapathId.of(4L), OFPort.of(5), d1); + e1.setActiveSince(d2); + SyncEntity se1 = new SyncEntity(e1); + assertEntityEquals(e1, se1); + assertEquals(1L, se1.macAddress); + assertEquals(Short.valueOf((short)2), se1.vlan); + assertEquals(Integer.valueOf(3), se1.ipv4Address); + assertEquals(Long.valueOf(4L), se1.switchDPID); + assertEquals(Integer.valueOf(5), se1.switchPort); + assertEquals(d1, se1.lastSeenTimestamp); + assertEquals(d2, se1.activeSince); + assertNotSame(d1, se1.lastSeenTimestamp); + assertNotSame(d2, se1.activeSince); + + Entity e2 = new Entity(MacAddress.of(42L), null, null, null, null, null); + SyncEntity se2 = new SyncEntity(e2); + assertEntityEquals(e2, se2); + + SyncEntity se3 = new SyncEntity(); + SyncEntity se4 = new SyncEntity(); + se3.lastSeenTimestamp = new Date(1000); + se4.lastSeenTimestamp = new Date(2000); + assertTrue("", se3.compareTo(se4) < 0); + assertTrue("", se4.compareTo(se3) > 0); + se4.lastSeenTimestamp = new Date(1000); + assertTrue("", se3.compareTo(se4) == 0); + assertTrue("", se4.compareTo(se3) == 0); + se4.lastSeenTimestamp = new Date(500); + assertTrue("", se3.compareTo(se4) > 0); + assertTrue("", se4.compareTo(se3) < 0); + } + + /* Test basic DeviceSyncRepresentation behavior */ + @Test + public void testDeviceSyncRepresentationBasics() { + DeviceSyncRepresentation dsr = new DeviceSyncRepresentation(); + assertNull(dsr.getKey()); + assertNull(dsr.getEntities()); + dsr.setKey("MyKey"); + assertEquals("MyKey", dsr.getKey()); + assertEquals("MyKey", dsr.toString()); + + List<SyncEntity> entities = new ArrayList<SyncEntity>(); + Entity e1a = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(3), DatapathId.of(4L), OFPort.of(5), new Date(1000)); + Entity e1b = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), null, DatapathId.of(4L), OFPort.of(5), new Date(0)); + entities.add(new SyncEntity(e1a)); + entities.add(new SyncEntity(e1b)); + // e1b comes before e1 (lastSeen) but we add it after it to test + // sorting + dsr.setEntities(entities); + + assertEquals(2, dsr.getEntities().size()); + // e1b has earlier time + assertEquals(e1b, dsr.getEntities().get(0).asEntity()); + assertEquals(e1a, dsr.getEntities().get(1).asEntity()); + + dsr.setKey(null); + dsr.setEntities(null); + assertNull(dsr.getKey()); + assertNull(dsr.getEntities()); + } + + @Test + public void testDeviceSyncRepresentationFromDevice() { + ITopologyService mockTopology = makeMockTopologyAllPortsAp(); + replay(mockTopology); + deviceManager.topology = mockTopology; + + deviceManager.entityClassifier = new MockEntityClassifier(); + + //************************************** + // Test 1: a single entity + Entity e1 = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(3), DatapathId.of(4L), OFPort.of(5), new Date(1000)); + Device d1 = deviceManager.learnDeviceByEntity(e1); + assertEquals("Sanity check failed. Device doesn't have the expected " + + "entity class. Something with the test setup is strange", + "DefaultEntityClass", d1.getEntityClass().getName()); + assertEquals("Sanity check failed. Device doesn't have the expected " + + "entity class. Something with the test setup is strange", + EnumSet.of(DeviceField.MAC, DeviceField.VLAN), + d1.getEntityClass().getKeyFields()); + + Long deviceKey = d1.getDeviceKey(); + DeviceSyncRepresentation dsr1 = new DeviceSyncRepresentation(d1); + assertEquals("DefaultEntityClass::00:00:00:00:00:01::[2]::", + dsr1.getKey()); + assertEquals(1, dsr1.getEntities().size()); + assertEquals(e1, dsr1.getEntities().get(0).asEntity()); + + //************************************** + // Test 1b: same device, now with a second entity (no IP). + // this second entity has a lastSeen time that is earlier than the + // first entity + Entity e1b = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), null, DatapathId.of(4L), OFPort.of(5), new Date(0)); + d1 = deviceManager.learnDeviceByEntity(e1b); + assertEquals("Sanity check failed. Should still be same device but " + + "deviceKeys differs", deviceKey, d1.getDeviceKey()); + dsr1 = new DeviceSyncRepresentation(d1); + assertEquals("DefaultEntityClass::00:00:00:00:00:01::[2]::", + dsr1.getKey()); + assertEquals(2, dsr1.getEntities().size()); + // Entities are ordered by their lastSeen time. e1b should come + // before e1. + assertEquals(e1, dsr1.getEntities().get(1).asEntity()); + assertEquals(e1b, dsr1.getEntities().get(0).asEntity()); + + //************************************** + // Test 1c: same device with a third entity that does not have a + // switch port. It should be added to the DeviceSyncRepresentation + Entity e1c = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(33), null, null, new Date(2000)); + d1 = deviceManager.learnDeviceByEntity(e1c); + assertEquals("Sanity check failed. Should still be same device but " + + "deviceKeys differs", deviceKey, d1.getDeviceKey()); + dsr1 = new DeviceSyncRepresentation(d1); + assertEquals("DefaultEntityClass::00:00:00:00:00:01::[2]::", + dsr1.getKey()); + assertEquals(3, dsr1.getEntities().size()); + // Entities are ordered by their lastSeen time + assertEquals(e1c, dsr1.getEntities().get(2).asEntity()); + assertEquals(e1, dsr1.getEntities().get(1).asEntity()); + assertEquals(e1b, dsr1.getEntities().get(0).asEntity()); + + //************************************** + // Test 1d: same device with a fourth entity that has a different + // attachment point and that is newer. Device should move and + // non-attachment point entities should be removed (e1b). Although + // e1 is non-attachment point it will remain because it has an IP + Entity e1d = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(33), DatapathId.of(4L), OFPort.of(6), new Date(3000)); + d1 = deviceManager.learnDeviceByEntity(e1d); + assertEquals("Sanity check failed. Should still be same device but " + + "deviceKeys differs", deviceKey, d1.getDeviceKey()); + dsr1 = new DeviceSyncRepresentation(d1); + assertEquals("DefaultEntityClass::00:00:00:00:00:01::[2]::", + dsr1.getKey()); + assertEquals(3, dsr1.getEntities().size()); + assertEquals(e1, dsr1.getEntities().get(0).asEntity()); + assertEquals(e1c, dsr1.getEntities().get(1).asEntity()); + assertEquals(e1d, dsr1.getEntities().get(2).asEntity()); + + d1 = null; + + + //************************************** + // Test 2: a second device with a different entity class. The + // mock entity classifier will return an entity class where all + // fields are keys if the DPID is > 10L + Entity e2 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(23), IPv4Address.of(24), DatapathId.of(11L), OFPort.of(1), new Date(0)); + Device d2 = deviceManager.learnDeviceByEntity(e2); + DeviceSyncRepresentation dsr2 = new DeviceSyncRepresentation(d2); + assertEquals("Sanity check failed. Device doesn't have the expected " + + "entity class. Something with the test setup is strange", + "TestEntityClass", d2.getEntityClass().getName()); + assertEquals("Sanity check failed. Device doesn't have the expected " + + "entity class. Something with the test setup is strange", + EnumSet.of(DeviceField.MAC, DeviceField.VLAN, + DeviceField.SWITCH, DeviceField.PORT), + d2.getEntityClass().getKeyFields()); + SwitchPort swp = new SwitchPort(DatapathId.of(11L), OFPort.of(1), null); + assertEquals("TestEntityClass::00:00:00:00:00:02::[23]::[" + + swp.toString() + "]::", + dsr2.getKey()); + } + + /* interate through all entries in the sync store and return them as + * list. We don't return the key from the store however, we assert + * that the key from the store matches the key in the representation. + * If we have a null value (tombstone) we simply add the null value to + * the list to return. + */ + private List<DeviceSyncRepresentation> getEntriesFromStore() + throws Exception { + List<DeviceSyncRepresentation> entries = + new ArrayList<DeviceSyncRepresentation>(); + IClosableIterator<Entry<String, Versioned<DeviceSyncRepresentation>>> iter = + storeClient.entries(); + try { + while(iter.hasNext()) { + Entry<String, Versioned<DeviceSyncRepresentation>> entry = + iter.next(); + DeviceSyncRepresentation dsr = entry.getValue().getValue(); + if (dsr != null) + assertEquals(entry.getKey(), dsr.getKey()); + entries.add(dsr); + } + } finally { + if (iter != null) + iter.close(); + } + return entries; + } + + /* + * assert whether the given Entity expected is equals to the given + * SyncEntity actual. This method also compares the times (lastSeen, + * activeSince). Entity.equals will not do that! + */ + private static void assertEntityEquals(Entity expected, SyncEntity actual) { + assertNotNull(actual); + assertNotNull(expected); + Entity actualEntity = actual.asEntity(); + assertEquals("entityFields", expected, actualEntity); + assertEquals("lastSeenTimestamp", + expected.getLastSeenTimestamp(), + actualEntity.getLastSeenTimestamp()); + assertEquals("activeSince", + expected.getActiveSince(), actualEntity.getActiveSince()); + } + + /* This test tests the normal operation as master when we write to the sync + * store or delete from the store. + */ + @Test + public void testWriteToSyncStore() throws Exception { + int syncStoreIntervalMs = 50; + ITopologyService mockTopology = makeMockTopologyAllPortsAp(); + replay(mockTopology); + deviceManager.topology = mockTopology; + deviceManager.setSyncStoreWriteInterval(syncStoreIntervalMs); + + Entity e1a = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(3), DatapathId.of(4L), OFPort.of(5), new Date(1000)); + e1a.setActiveSince(new Date(0)); + deviceManager.learnDeviceByEntity(e1a); + + //storeClient.put("FooBar", new DeviceSyncRepresentation()); + + List<DeviceSyncRepresentation> entries = getEntriesFromStore(); + assertEquals(1, entries.size()); + DeviceSyncRepresentation dsr1 = entries.get(0); + assertEquals(1, dsr1.getEntities().size()); + assertEntityEquals(e1a, dsr1.getEntities().get(0)); + + // Same entity but newer timestamp. Since the device hasn't changed, + // only the timestamp is updated and the write should be throttled. + Entity e1b = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(3), DatapathId.of(4L), OFPort.of(5), new Date(2000)); + e1b.setActiveSince(new Date(0)); + deviceManager.learnDeviceByEntity(e1a); + entries = getEntriesFromStore(); + assertEquals(1, entries.size()); + dsr1 = entries.get(0); + assertEquals(1, dsr1.getEntities().size()); + assertEntityEquals(e1a, dsr1.getEntities().get(0)); //e1a not e1b !!! + + // Wait for the write interval to expire then write again. + Thread.sleep(syncStoreIntervalMs+5); + Entity e1c = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(3), DatapathId.of(4L), OFPort.of(5), new Date(3000)); + e1c.setActiveSince(new Date(0)); + deviceManager.learnDeviceByEntity(e1c); + entries = getEntriesFromStore(); + assertEquals(1, entries.size()); + dsr1 = entries.get(0); + assertEquals(1, dsr1.getEntities().size()); + assertEntityEquals(e1c, dsr1.getEntities().get(0)); // e1c !! + + // Entity for same device but with different IP. should be added + // immediately + Entity e1d = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(33), DatapathId.of(4L), OFPort.of(5), new Date(4000)); + e1d.setActiveSince(new Date(0)); + deviceManager.learnDeviceByEntity(e1d); + entries = getEntriesFromStore(); + assertEquals(1, entries.size()); + dsr1 = entries.get(0); + assertEquals(2, dsr1.getEntities().size()); + assertEntityEquals(e1c, dsr1.getEntities().get(0)); // e1c !! + assertEntityEquals(e1d, dsr1.getEntities().get(1)); // e1d !! + + // Entity for same device with new switch port ==> moved ==> write + // update immediately without throttle. + // Note: the previous entities will still be there because they have + // IPs (even though they aren't for the current attachment point) + Entity e1e = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(33), DatapathId.of(4L), OFPort.of(6), new Date(5000)); + e1e.setActiveSince(new Date(0)); + deviceManager.learnDeviceByEntity(e1e); + entries = getEntriesFromStore(); + assertEquals(1, entries.size()); + dsr1 = entries.get(0); + assertEquals(3, dsr1.getEntities().size()); + assertEntityEquals(e1c, dsr1.getEntities().get(0)); + assertEntityEquals(e1d, dsr1.getEntities().get(1)); + assertEntityEquals(e1e, dsr1.getEntities().get(2)); + + // Add a second device + Entity e2 = new Entity(MacAddress.of(2L), null, null, DatapathId.of(5L), OFPort.of(5), new Date()); + deviceManager.learnDeviceByEntity(e2); + entries = getEntriesFromStore(); + assertEquals(2, entries.size()); + for (DeviceSyncRepresentation dsr: entries) { + // This is a kinda ugly way to ensure we have the two + // devices we need..... but it will work for now + if (dsr.getKey().contains("::00:00:00:00:00:01::")) { + assertEquals(3, dsr.getEntities().size()); + assertEntityEquals(e1c, dsr.getEntities().get(0)); + assertEntityEquals(e1d, dsr.getEntities().get(1)); + assertEntityEquals(e1e, dsr.getEntities().get(2)); + } else if (dsr.getKey().contains("::00:00:00:00:00:02::")) { + assertEquals(1, dsr.getEntities().size()); + assertEntityEquals(e2, dsr.getEntities().get(0)); + } else { + fail("Unknown entry in store: " + dsr); + } + } + + + // Run entity cleanup. Since we've used phony time stamps for + // device 1 its entities should be cleared and the device should be + // removed from the store. Device 2 should remain in the store. + deviceManager.cleanupEntities(); + entries = getEntriesFromStore(); + assertEquals(2, entries.size()); + for (DeviceSyncRepresentation dsr: entries) { + if (dsr == null) { + // pass + } else if (dsr.getKey().contains("::00:00:00:00:00:02::")) { + assertEquals(1, dsr.getEntities().size()); + assertEntityEquals(e2, dsr.getEntities().get(0)); + } else { + fail("Unknown entry in store: " + dsr); + } + } + } + + + private void assertDeviceIps(Integer[] expected, IDevice d) { + List<Integer> expectedList = Arrays.asList(expected); + Collections.sort(expectedList); + List<IPv4Address> actualList = Arrays.asList(d.getIPv4Addresses()); + Collections.sort(actualList); + assertEquals(expectedList, actualList); + } + + private IDevice getSingleDeviceFromDeviceManager(long mac) { + Iterator<? extends IDevice> diter = + deviceManager.queryDevices(MacAddress.of(mac), null, null, null, null); + assertTrue("Query didn't return a device", diter.hasNext()); + IDevice d = diter.next(); + assertFalse("Query returned more than one device", diter.hasNext()); + return d; + } + + @Test + public void testToMaster() throws Exception { + int syncStoreWriteIntervalMs = 0; + int initialSyncStoreConsolidateIntervalMs = 50; + ITopologyService mockTopology = makeMockTopologyAllPortsAp(); + replay(mockTopology); + deviceManager.topology = mockTopology; + // We want an EntityClassifier that has switch/port as key fields + deviceManager.entityClassifier = new MockEntityClassifier(); + deviceManager.setSyncStoreWriteInterval(syncStoreWriteIntervalMs); + deviceManager.setInitialSyncStoreConsolidateMs(initialSyncStoreConsolidateIntervalMs); + + // Add Device1 with two entities with two different IPs + Entity e1a = new Entity(MacAddress.of(1L), null, IPv4Address.of(3), DatapathId.of(4L), OFPort.of(5), new Date(1000)); + Entity e1b = new Entity(MacAddress.of(1L), null, IPv4Address.of(33), DatapathId.of(4L), OFPort.of(5), new Date(2000)); + Device d1 = deviceManager.allocateDevice(1L, e1a, + DefaultEntityClassifier.entityClass); + d1 = deviceManager.allocateDevice(d1, e1b, -1); + DeviceSyncRepresentation dsr = new DeviceSyncRepresentation(d1); + storeClient.put(dsr.getKey(), dsr); + + // Add Device2 with different switch-ports. Only the most recent + // one should be the attachment point + Entity e2a = new Entity(MacAddress.of(2L), null, null, DatapathId.of(4L), OFPort.of(4), new Date(1000)); + Entity e2b = new Entity(MacAddress.of(2L), null, null, DatapathId.of(4L), OFPort.of(5), new Date(2000)); + Device d2 = deviceManager.allocateDevice(2L, e2a, + DefaultEntityClassifier.entityClass); + d2 = deviceManager.allocateDevice(d2, e2b, -1); + d2.updateAttachmentPoint(DatapathId.of(4L), OFPort.of(5), + e2b.getLastSeenTimestamp()); + SwitchPort swp = new SwitchPort(DatapathId.of(4L), OFPort.of(5)); + SwitchPort[] aps = d2.getAttachmentPoints(); + // sanity check + assertArrayEquals("Sanity check: should only have AP(4L,5)", + new SwitchPort[] {swp}, aps); + dsr = new DeviceSyncRepresentation(d2); + storeClient.put(dsr.getKey(), dsr); + + // Add a tombstone entry to the store to make sure we don't trip a + // NPE + dsr = null; + Versioned<DeviceSyncRepresentation> versionedDsr = + storeClient.get("FooBar"); + storeClient.put("FooBar", versionedDsr); + + deviceManager.getHAListener().transitionToActive(); + + // Query for the Device1. Make sure we have the two IPs we stored. + IDevice d = getSingleDeviceFromDeviceManager(1L); + assertDeviceIps(new Integer[] {3, 33}, d); + assertArrayEquals(new Short[] { Ethernet.VLAN_UNTAGGED }, d.getVlanId()); + swp = new SwitchPort(DatapathId.of(4L), OFPort.of(5)); + assertArrayEquals(new SwitchPort[] { swp }, d.getAttachmentPoints()); + + // Query for Device2. Make sure we only have the more recent AP + // Query for the Device1. Make sure we have the two IPs we stored. + d = getSingleDeviceFromDeviceManager(2L); + assertArrayEquals(new Integer[0], d.getIPv4Addresses()); + assertArrayEquals(new Short[] { Ethernet.VLAN_UNTAGGED }, d.getVlanId()); + swp = new SwitchPort(DatapathId.of(4L), OFPort.of(5)); + assertArrayEquals(new SwitchPort[] { swp }, d.getAttachmentPoints()); + + //---------------------------- + // add another entry device to the store. since device manager is + // already master we won't read this device and it should be + // removed from the store by the consolidate task + Entity e3 = new Entity(MacAddress.of(3L), null, null, DatapathId.of(1L), OFPort.of(1), null); + dsr = new DeviceSyncRepresentation(); + dsr.setKey("Device3"); + dsr.setEntities(Collections.singletonList(new SyncEntity(e3))); + storeClient.put(dsr.getKey(), dsr); + + // make sure it's in the store + List<DeviceSyncRepresentation> entries = getEntriesFromStore(); + boolean found = false; + for (DeviceSyncRepresentation entry: entries) { + if (entry!=null && entry.getKey().equals("Device3")) + found = true; + } + assertTrue("Device3 not in store. Entries in store: " + entries, found); + // make sure it's not in DevManager + Iterator<? extends IDevice> diter = + deviceManager.queryDevices(MacAddress.of(3L), null, null, null, null); + assertFalse("Device3 found in DeviceManager. Should be there", + diter.hasNext()); + + // Wait for consolidate + Thread.sleep(initialSyncStoreConsolidateIntervalMs + 5); + // make sure it's in NOT the store + entries = getEntriesFromStore(); + found = false; + for (DeviceSyncRepresentation entry: entries) { + if (entry!=null && entry.getKey().equals("Device3")) + found = true; + } + assertFalse("Device3 not is still in the store. Entries in store: " + + entries, found); + // make sure it's not in DevManager + diter = deviceManager.queryDevices(MacAddress.of(3L), null, null, null, null); + assertFalse("Device3 found in DeviceManager. Should be there", + diter.hasNext()); + } + + + @Test + public void testConsolitateStore() throws Exception { + int syncStoreInternalMs = 0; + ITopologyService mockTopology = makeMockTopologyAllPortsAp(); + replay(mockTopology); + deviceManager.topology = mockTopology; + // We want an EntityClassifier that has switch/port as key fields + deviceManager.entityClassifier = new MockEntityClassifier(); + deviceManager.setSyncStoreWriteInterval(syncStoreInternalMs); + + // Add Device1 with two entities to store and let device manager + // learn + Entity e1a = new Entity(MacAddress.of(1L), null, null, DatapathId.of(4L), OFPort.of(5), new Date(1000)); + Entity e1b = new Entity(MacAddress.of(1L), null, IPv4Address.of(3), DatapathId.of(4L), OFPort.of(5), new Date(2000)); + Device d1 = deviceManager.learnDeviceByEntity(e1a); + deviceManager.learnDeviceByEntity(e1b); + String dev1Key = DeviceSyncRepresentation.computeKey(d1); + + + // Add a second device to the store but do NOT add to device manager + Entity e2 = new Entity(MacAddress.of(2L), null, null, DatapathId.of(5L), OFPort.of(5), new Date()); + Device d2 = deviceManager.allocateDevice(42L, e2, + DefaultEntityClassifier.entityClass); + DeviceSyncRepresentation dsr = new DeviceSyncRepresentation(d2); + storeClient.put(dsr.getKey(), dsr); + String dev2Key = DeviceSyncRepresentation.computeKey(d2); + + // Make sure we have two devices in the store + List<DeviceSyncRepresentation> entries = getEntriesFromStore(); + assertEquals(2, entries.size()); + + deviceManager.scheduleConsolidateStoreNow(); + Thread.sleep(25); // give the scheduler time to run the task + + // We should still have two entries, however one of them will be a + // tombstone + entries = getEntriesFromStore(); + assertEquals(2, entries.size()); + + // Device 1 should still be in store + Versioned<DeviceSyncRepresentation> versioned = + storeClient.get(dev1Key); + dsr = versioned.getValue(); + assertNotNull(dsr); + assertEquals(2, dsr.getEntities().size()); + assertEntityEquals(e1a, dsr.getEntities().get(0)); + assertEntityEquals(e1b, dsr.getEntities().get(1)); + + // Device2 should be gone + versioned = storeClient.get(dev2Key); + assertNull(versioned.getValue()); + + // Run consolitate again. This time we check that tombstones in + // the store are handled correctly + deviceManager.scheduleConsolidateStoreNow(); + Thread.sleep(25); // give the scheduler time to run the task + + // Now write a device to the store that doesn't have any switch-port + // it should be removed + Entity e3 = new Entity(MacAddress.of(3L), null, null, null, null, null); + dsr.setKey("Device3"); + dsr.setEntities(Collections.singletonList(new SyncEntity(e3))); + storeClient.put(dsr.getKey(), dsr); + + // Run consolitate again. This time we check that tombstones in + // the store are handled correctly + deviceManager.scheduleConsolidateStoreNow(); + Thread.sleep(25); // give the scheduler time to run the task + versioned = storeClient.get("Device3"); + assertNull(versioned.getValue()); + + } } diff --git a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceUniqueIndexTest.java b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceUniqueIndexTest.java index 1ac1f1c35d5a13601df137c7e4669bf605c76d8b..e820f9e082e1ce9aa4c0686f7b87f05c34d88897 100644 --- a/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceUniqueIndexTest.java +++ b/src/test/java/net/floodlightcontroller/devicemanager/internal/DeviceUniqueIndexTest.java @@ -26,6 +26,12 @@ import java.util.Set; import java.util.Iterator; import org.junit.Test; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.VlanVid; + import net.floodlightcontroller.devicemanager.IDeviceService.DeviceField; import junit.framework.TestCase; @@ -46,8 +52,8 @@ public class DeviceUniqueIndexTest extends TestCase { @Override protected void setUp() throws Exception { super.setUp(); - e1a = new Entity(1L, (short)1, 1, 1L, 1, new Date()); - e1b = new Entity(1L, (short)2, 1, 1L, 1, new Date()); + e1a = new Entity(MacAddress.of(1L), VlanVid.ofVlan(1), IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), new Date()); + e1b = new Entity(MacAddress.of(1L), VlanVid.ofVlan(2), IPv4Address.of(1), DatapathId.of(1L), OFPort.of(1), new Date()); List<Entity> d1Entities = new ArrayList<Entity>(2); d1Entities.add(e1a); d1Entities.add(e1b); @@ -55,14 +61,14 @@ public class DeviceUniqueIndexTest extends TestCase { d1Entities, null); // e2 and e2 alt match in MAC and VLAN - e2 = new Entity(2L, (short)2, 2, 2L, 2, new Date()); - e2alt = new Entity(2, (short)2, null, null, null, null); + e2 = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), IPv4Address.of(2), DatapathId.of(2L), OFPort.of(2), new Date()); + e2alt = new Entity(MacAddress.of(2L), VlanVid.ofVlan(2), null, null, null, null); // IP is null - e3 = new Entity(3L, (short)3, null, 3L, 3, new Date()); + e3 = new Entity(MacAddress.of(3L), VlanVid.ofVlan(3), null, DatapathId.of(3L), OFPort.of(3), new Date()); // IP and switch and port are null - e4 = new Entity(4L, (short)4, null, null, null, new Date()); + e4 = new Entity(MacAddress.of(4L), VlanVid.ofVlan(4), null, null, null, new Date()); } /* @@ -141,7 +147,7 @@ public class DeviceUniqueIndexTest extends TestCase { // only one key field is null idx2.updateIndex(e3, 3L); assertEquals(Long.valueOf(3L), idx2.findByEntity(e3)); - e3.ipv4Address = 3; + e3.ipv4Address = IPv4Address.of(3); assertEquals(null, idx2.findByEntity(e3)); // all key fields are null idx2.updateIndex(e4, 4L); diff --git a/src/test/java/net/floodlightcontroller/devicemanager/test/MockDevice.java b/src/test/java/net/floodlightcontroller/devicemanager/test/MockDevice.java index 5657cc515792d534179e5d66116f362a232c2098..f8c0bc3f082159a81fd6cdbfb0761ebf57182a00 100644 --- a/src/test/java/net/floodlightcontroller/devicemanager/test/MockDevice.java +++ b/src/test/java/net/floodlightcontroller/devicemanager/test/MockDevice.java @@ -23,6 +23,8 @@ import java.util.Collection; import java.util.List; import java.util.TreeSet; +import org.projectfloodlight.openflow.types.IPv4Address; + import net.floodlightcontroller.devicemanager.IEntityClass; import net.floodlightcontroller.devicemanager.SwitchPort; import net.floodlightcontroller.devicemanager.internal.AttachmentPoint; @@ -57,14 +59,14 @@ public class MockDevice extends Device { } @Override - public Integer[] getIPv4Addresses() { - TreeSet<Integer> vals = new TreeSet<Integer>(); + public IPv4Address[] getIPv4Addresses() { + TreeSet<IPv4Address> vals = new TreeSet<IPv4Address>(); for (Entity e : entities) { if (e.getIpv4Address() == null) continue; vals.add(e.getIpv4Address()); } - return vals.toArray(new Integer[vals.size()]); + return vals.toArray(new IPv4Address[vals.size()]); } @Override diff --git a/src/test/java/net/floodlightcontroller/devicemanager/test/MockDeviceManager.java b/src/test/java/net/floodlightcontroller/devicemanager/test/MockDeviceManager.java index f15061ad0a1397cf7564124e26dd071a148fe997..29059e340ea2a4ad13aaff7cd8d785ba4429dec9 100644 --- a/src/test/java/net/floodlightcontroller/devicemanager/test/MockDeviceManager.java +++ b/src/test/java/net/floodlightcontroller/devicemanager/test/MockDeviceManager.java @@ -20,6 +20,11 @@ import java.util.Collection; import java.util.Date; import java.util.List; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.VlanVid; import org.sdnplatform.sync.test.MockSyncService; import net.floodlightcontroller.core.module.FloodlightModuleContext; @@ -38,106 +43,106 @@ import net.floodlightcontroller.devicemanager.internal.Entity; * @author readams */ public class MockDeviceManager extends DeviceManagerImpl { - /** - * Set a new IEntityClassifier - * Use this as a quick way to use a particular entity classifier in a - * single test without having to setup the full FloodlightModuleContext - * again. - * @param ecs - */ - public void setEntityClassifier(IEntityClassifierService ecs) { - this.entityClassifier = ecs; - try { - this.startUp(null); - } catch (FloodlightModuleException e) { - throw new RuntimeException(e); - } - } + /** + * Set a new IEntityClassifier + * Use this as a quick way to use a particular entity classifier in a + * single test without having to setup the full FloodlightModuleContext + * again. + * @param ecs + */ + public void setEntityClassifier(IEntityClassifierService ecs) { + this.entityClassifier = ecs; + try { + this.startUp(null); + } catch (FloodlightModuleException e) { + throw new RuntimeException(e); + } + } - /** - * Learn a device using the given characteristics. - * @param macAddress the MAC - * @param vlan the VLAN (can be null) - * @param ipv4Address the IP (can be null) - * @param switchDPID the attachment point switch DPID (can be null) - * @param switchPort the attachment point switch port (can be null) - * @param processUpdates if false, will not send updates. Note that this - * method is not thread safe if this is false - * @return the device, either new or not - */ - public IDevice learnEntity(long macAddress, Short vlan, - Integer ipv4Address, Long switchDPID, - Integer switchPort, - boolean processUpdates) { - List<IDeviceListener> listeners = deviceListeners.getOrderedListeners(); - if (!processUpdates) { - deviceListeners.clearListeners(); - } + /** + * Learn a device using the given characteristics. + * @param macAddress the MAC + * @param vlan the VLAN (can be null) + * @param ipv4Address the IP (can be null) + * @param switchDPID the attachment point switch DPID (can be null) + * @param switchPort the attachment point switch port (can be null) + * @param processUpdates if false, will not send updates. Note that this + * method is not thread safe if this is false + * @return the device, either new or not + */ + public IDevice learnEntity(long macAddress, Short vlan, + Integer ipv4Address, Long switchDPID, + Integer switchPort, + boolean processUpdates) { + List<IDeviceListener> listeners = deviceListeners.getOrderedListeners(); + if (!processUpdates) { + deviceListeners.clearListeners(); + } - if (vlan != null && vlan.shortValue() <= 0) - vlan = null; - if (ipv4Address != null && ipv4Address == 0) - ipv4Address = null; - IDevice res = learnDeviceByEntity(new Entity(macAddress, vlan, - ipv4Address, switchDPID, - switchPort, new Date())); - // Restore listeners - if (listeners != null) { - for (IDeviceListener listener : listeners) { - deviceListeners.addListener("device", listener); - } - } - return res; - } + if (vlan != null && vlan.shortValue() <= 0) + vlan = null; + if (ipv4Address != null && ipv4Address == 0) + ipv4Address = null; + IDevice res = learnDeviceByEntity(new Entity(MacAddress.of(macAddress), VlanVid.ofVlan(vlan), + IPv4Address.of(ipv4Address), DatapathId.of(switchDPID), + OFPort.of(switchPort), new Date())); + // Restore listeners + if (listeners != null) { + for (IDeviceListener listener : listeners) { + deviceListeners.addListener("device", listener); + } + } + return res; + } - @Override - public void deleteDevice(Device device) { - super.deleteDevice(device); - } + @Override + public void deleteDevice(Device device) { + super.deleteDevice(device); + } - /** - * Learn a device using the given characteristics. - * @param macAddress the MAC - * @param vlan the VLAN (can be null) - * @param ipv4Address the IP (can be null) - * @param switchDPID the attachment point switch DPID (can be null) - * @param switchPort the attachment point switch port (can be null) - * @return the device, either new or not - */ - public IDevice learnEntity(long macAddress, Short vlan, - Integer ipv4Address, Long switchDPID, - Integer switchPort) { - return learnEntity(macAddress, vlan, ipv4Address, - switchDPID, switchPort, true); - } + /** + * Learn a device using the given characteristics. + * @param macAddress the MAC + * @param vlan the VLAN (can be null) + * @param ipv4Address the IP (can be null) + * @param switchDPID the attachment point switch DPID (can be null) + * @param switchPort the attachment point switch port (can be null) + * @return the device, either new or not + */ + public IDevice learnEntity(long macAddress, Short vlan, + Integer ipv4Address, Long switchDPID, + Integer switchPort) { + return learnEntity(macAddress, vlan, ipv4Address, + switchDPID, switchPort, true); + } - @Override - protected Device allocateDevice(Long deviceKey, - Entity entity, - IEntityClass entityClass) { - return new MockDevice(this, deviceKey, entity, entityClass); - } + @Override + protected Device allocateDevice(Long deviceKey, + Entity entity, + IEntityClass entityClass) { + return new MockDevice(this, deviceKey, entity, entityClass); + } - @Override - protected Device allocateDevice(Long deviceKey, - String dhcpClientName, - List<AttachmentPoint> aps, - List<AttachmentPoint> trueAPs, - Collection<Entity> entities, - IEntityClass entityClass) { - return new MockDevice(this, deviceKey, aps, trueAPs, entities, entityClass); - } + @Override + protected Device allocateDevice(Long deviceKey, + String dhcpClientName, + List<AttachmentPoint> aps, + List<AttachmentPoint> trueAPs, + Collection<Entity> entities, + IEntityClass entityClass) { + return new MockDevice(this, deviceKey, aps, trueAPs, entities, entityClass); + } - @Override - protected Device allocateDevice(Device device, - Entity entity, - int insertionpoint) { - return new MockDevice(device, entity, insertionpoint); - } + @Override + protected Device allocateDevice(Device device, + Entity entity, + int insertionpoint) { + return new MockDevice(device, entity, insertionpoint); + } - @Override - public void init(FloodlightModuleContext fmc) throws FloodlightModuleException { - super.init(fmc); - setSyncServiceIfNotSet(new MockSyncService()); - } + @Override + public void init(FloodlightModuleContext fmc) throws FloodlightModuleException { + super.init(fmc); + setSyncServiceIfNotSet(new MockSyncService()); + } } diff --git a/src/test/java/net/floodlightcontroller/devicemanager/test/MockEntityClassifier.java b/src/test/java/net/floodlightcontroller/devicemanager/test/MockEntityClassifier.java index 7a35049a94f79d4a5b0701b28cd682fc95bc7299..2d92357f453f21c2bf8cc5a8543168a65dd695e0 100644 --- a/src/test/java/net/floodlightcontroller/devicemanager/test/MockEntityClassifier.java +++ b/src/test/java/net/floodlightcontroller/devicemanager/test/MockEntityClassifier.java @@ -49,7 +49,7 @@ public class MockEntityClassifier extends DefaultEntityClassifier { @Override public IEntityClass classifyEntity(Entity entity) { - if (entity.getSwitchDPID() >= 10L) { + if (entity.getSwitchDPID().getLong() >= 10L) { return testEC; } return DefaultEntityClassifier.entityClass; diff --git a/src/test/java/net/floodlightcontroller/devicemanager/test/MockEntityClassifierMac.java b/src/test/java/net/floodlightcontroller/devicemanager/test/MockEntityClassifierMac.java index 521b9b7929833dcca5114a6062e7f0475be4738a..a953d5c14dfc0b69c9a899810e37c453d087d636 100644 --- a/src/test/java/net/floodlightcontroller/devicemanager/test/MockEntityClassifierMac.java +++ b/src/test/java/net/floodlightcontroller/devicemanager/test/MockEntityClassifierMac.java @@ -59,11 +59,11 @@ public class MockEntityClassifierMac extends DefaultEntityClassifier { if (entity.getSwitchDPID() == null) { throw new IllegalArgumentException("Not all key fields specified." + " Required fields: " + getKeyFields()); - } else if (entity.getSwitchDPID() == 1L) { + } else if (entity.getSwitchDPID().getLong() == 1L) { return testECMac1; - } else if (entity.getSwitchDPID() == 2L) { + } else if (entity.getSwitchDPID().getLong() == 2L) { return testECMac2; - } else if (entity.getSwitchDPID() == -1L) { + } else if (entity.getSwitchDPID().getLong() == -1L) { return null; } return DefaultEntityClassifier.entityClass; diff --git a/src/test/java/net/floodlightcontroller/firewall/FirewallTest.java b/src/test/java/net/floodlightcontroller/firewall/FirewallTest.java index ea9aafb93968fc9af5dc248fe38461fb410cdb32..6e5f4a57bb819012687c80a6ea19fcb8b6d7345d 100644 --- a/src/test/java/net/floodlightcontroller/firewall/FirewallTest.java +++ b/src/test/java/net/floodlightcontroller/firewall/FirewallTest.java @@ -47,18 +47,18 @@ import net.floodlightcontroller.test.FloodlightTestCase; import org.easymock.EasyMock; import org.junit.Before; import org.junit.Test; +import org.projectfloodlight.openflow.protocol.OFFactories; import org.projectfloodlight.openflow.protocol.OFPacketIn; import org.projectfloodlight.openflow.protocol.OFPacketInReason; -import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.OFVersion; import org.projectfloodlight.openflow.types.DatapathId; import org.projectfloodlight.openflow.types.EthType; -import org.projectfloodlight.openflow.types.IPv4Address; import org.projectfloodlight.openflow.types.IPv4AddressWithMask; import org.projectfloodlight.openflow.types.IpProtocol; import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFBufferId; import org.projectfloodlight.openflow.types.OFPort; import org.projectfloodlight.openflow.types.TransportPort; -import org.projectfloodlight.openflow.util.HexString; /** * Unit test for stateless firewall implemented as a Google Summer of Code project. @@ -84,6 +84,7 @@ public class FirewallTest extends FloodlightTestCase { super.setUp(); cntx = new FloodlightContext(); mockFloodlightProvider = getMockFloodlightProvider(); + mockSwitchManager = getMockSwitchService(); firewall = new Firewall(); IStorageSourceService storageService = new MemoryStorageSource(); RestApiServer restApi = new RestApiServer(); @@ -95,9 +96,9 @@ public class FirewallTest extends FloodlightTestCase { expect(sw.getId().toString()).andReturn(TestSwitch1DPID).anyTimes(); replay(sw); // Load the switch map - Map<Long, IOFSwitch> switches = new HashMap<Long, IOFSwitch>(); + Map<DatapathId, IOFSwitch> switches = new HashMap<DatapathId, IOFSwitch>(); switches.put(dpid, sw); - mockFloodlightProvider.setSwitches(switches); + mockSwitchManager.setSwitches(switches); FloodlightModuleContext fmc = new FloodlightModuleContext(); fmc.addService(IFloodlightProviderService.class, @@ -216,13 +217,12 @@ public class FirewallTest extends FloodlightTestCase { protected void setPacketIn(IPacket packet) { byte[] serializedPacket = packet.serialize(); // Build the PacketIn - /*this.packetIn = ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_IN)) - .setBufferId(-1) - .setInPort((short) 1) - .setPacketData(serializedPacket) + this.packetIn = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn() + .setBufferId(OFBufferId.NO_BUFFER) + .setInPort(OFPort.of(1)) + .setData(serializedPacket) .setReason(OFPacketInReason.NO_MATCH) - .setTotalLength((short) serializedPacket.length); - */ + .build(); // Add the packet to the context store IFloodlightProviderService.bcStore. put(cntx, diff --git a/src/test/java/net/floodlightcontroller/flowcache/FlowReconcileMgrTest.java b/src/test/java/net/floodlightcontroller/flowcache/FlowReconcileMgrTest.java index 62ccecdf69fefab4db37686abb7c273d4420075f..cda16ee4dd8d6c6c54cfc574d93a3b8676014567 100644 --- a/src/test/java/net/floodlightcontroller/flowcache/FlowReconcileMgrTest.java +++ b/src/test/java/net/floodlightcontroller/flowcache/FlowReconcileMgrTest.java @@ -17,6 +17,7 @@ package net.floodlightcontroller.flowcache; import static org.easymock.EasyMock.*; +import static org.junit.Assert.*; import java.util.ArrayList; import java.util.Date; @@ -25,29 +26,26 @@ import java.util.ListIterator; import net.floodlightcontroller.core.IListener.Command; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.test.MockThreadPoolService; -import net.floodlightcontroller.counter.ICounterStoreService; -import net.floodlightcontroller.counter.SimpleCounter; -import net.floodlightcontroller.counter.CounterValue.CounterType; import net.floodlightcontroller.flowcache.IFlowReconcileListener; import net.floodlightcontroller.flowcache.OFMatchReconcile; import net.floodlightcontroller.flowcache.PriorityPendingQueue.EventPriority; import net.floodlightcontroller.test.FloodlightTestCase; import net.floodlightcontroller.threadpool.IThreadPoolService; + import org.easymock.EasyMock; import org.easymock.IAnswer; import org.junit.Before; import org.junit.Test; -import org.openflow.protocol.OFStatisticsRequest; -import org.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.OFStatsRequest; +import org.projectfloodlight.openflow.protocol.OFType; public class FlowReconcileMgrTest extends FloodlightTestCase { protected FlowReconcileManager flowReconcileMgr; protected MockThreadPoolService threadPool; - protected ICounterStoreService counterStore; protected FloodlightModuleContext fmc; - OFStatisticsRequest ofStatsRequest; + OFStatsRequest ofStatsRequest; protected int NUM_FLOWS_PER_THREAD = 100; protected int NUM_THREADS = 20; @@ -59,9 +57,7 @@ public class FlowReconcileMgrTest extends FloodlightTestCase { fmc = new FloodlightModuleContext(); flowReconcileMgr = new FlowReconcileManager(); threadPool = new MockThreadPoolService(); - counterStore = createMock(ICounterStoreService.class); - fmc.addService(ICounterStoreService.class, counterStore); fmc.addService(IThreadPoolService.class, threadPool); threadPool.init(fmc); @@ -115,16 +111,6 @@ public class FlowReconcileMgrTest extends FloodlightTestCase { andThrow(new RuntimeException("This is NOT an error! " + "We are testing exception catching.")); - SimpleCounter cnt = (SimpleCounter)SimpleCounter.createCounter( - new Date(), - CounterType.LONG); - cnt.increment(); - expect(counterStore.getCounter( - flowReconcileMgr.controllerPktInCounterName)) - .andReturn(cnt) - .anyTimes(); - - replay(r1, r2, r3, counterStore); flowReconcileMgr.clearFlowReconcileListeners(); flowReconcileMgr.addFlowReconcileListener(r1); flowReconcileMgr.addFlowReconcileListener(r2); @@ -256,8 +242,7 @@ public class FlowReconcileMgrTest extends FloodlightTestCase { @Test public void testGetPktInRate() { - internalTestGetPktInRate(CounterType.LONG); - internalTestGetPktInRate(CounterType.DOUBLE); + } protected void internalTestGetPktInRate(CounterType type) { diff --git a/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java b/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java index 1209cb1842c2d2373d20dcc510543e6149df7be4..9dec8e67163830432e2da62cc3980b22a8699a2c 100644 --- a/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java +++ b/src/test/java/net/floodlightcontroller/forwarding/ForwardingTest.java @@ -18,6 +18,7 @@ package net.floodlightcontroller.forwarding; import static org.easymock.EasyMock.*; +import static org.junit.Assert.*; import java.util.ArrayList; import java.util.Date; @@ -32,8 +33,6 @@ import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.test.MockThreadPoolService; import net.floodlightcontroller.devicemanager.internal.DefaultEntityClassifier; import net.floodlightcontroller.devicemanager.test.MockDeviceManager; -import net.floodlightcontroller.counter.CounterStore; -import net.floodlightcontroller.counter.ICounterStoreService; import net.floodlightcontroller.devicemanager.IDevice; import net.floodlightcontroller.devicemanager.IDeviceService; import net.floodlightcontroller.devicemanager.IEntityClassifierService; @@ -57,18 +56,24 @@ import org.easymock.Capture; import org.easymock.CaptureType; import org.easymock.EasyMock; import org.junit.Test; -import org.openflow.protocol.OFFeaturesReply; -import org.openflow.protocol.OFFlowMod; -import org.openflow.protocol.OFMatch; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPacketIn; -import org.openflow.protocol.OFPacketOut; -import org.openflow.protocol.OFPort; -import org.openflow.protocol.OFType; -import org.openflow.protocol.OFPacketIn.OFPacketInReason; -import org.openflow.protocol.action.OFAction; -import org.openflow.protocol.action.OFActionOutput; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.protocol.OFFeaturesReply; +import org.projectfloodlight.openflow.protocol.OFFlowMod; +import org.projectfloodlight.openflow.protocol.match.Match; +import org.projectfloodlight.openflow.protocol.OFFactories; +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFPacketOut; +import org.projectfloodlight.openflow.protocol.OFVersion; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFBufferId; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.U64; +import org.projectfloodlight.openflow.protocol.OFPacketInReason; +import org.projectfloodlight.openflow.protocol.action.OFAction; +import org.projectfloodlight.openflow.protocol.action.OFActionOutput; import org.sdnplatform.sync.ISyncService; import org.sdnplatform.sync.test.MockSyncService; @@ -91,6 +96,8 @@ public class ForwardingTest extends FloodlightTestCase { protected int expected_wildcards; protected Date currentDate; private MockSyncService mockSyncService; + private OFFactory factory = OFFactories.getFactory(OFVersion.OF_13); + @Override public void setUp() throws Exception { @@ -135,7 +142,6 @@ public class ForwardingTest extends FloodlightTestCase { fmc.addService(IThreadPoolService.class, threadPool); fmc.addService(ITopologyService.class, topology); fmc.addService(IRoutingService.class, routingEngine); - fmc.addService(ICounterStoreService.class, new CounterStore()); fmc.addService(IDeviceService.class, deviceManager); fmc.addService(IFlowReconcileService.class, flowReconcileMgr); fmc.addService(IEntityClassifierService.class, entityClassifier); @@ -159,42 +165,29 @@ public class ForwardingTest extends FloodlightTestCase { entityClassifier.startUp(fmc); verify(topology); - swFeatures = new OFFeaturesReply(); - swFeatures.setBuffers(1000); + swFeatures = factory.buildFeaturesReply().setNBuffers(1000).build(); // Mock switches sw1 = EasyMock.createMock(IOFSwitch.class); - expect(sw1.getId()).andReturn(1L).anyTimes(); - expect(sw1.getBuffers()).andReturn(swFeatures.getBuffers()).anyTimes(); - expect(sw1.getStringId()) - .andReturn(HexString.toHexString(1L)).anyTimes(); + expect(sw1.getId()).andReturn(DatapathId.of(1L)).anyTimes(); + expect(sw1.getBuffers()).andReturn(swFeatures.getNBuffers()).anyTimes(); + expect(sw1.getId().toString()) + .andReturn(DatapathId.of(1L).toString()).anyTimes(); sw2 = EasyMock.createMock(IOFSwitch.class); - expect(sw2.getId()).andReturn(2L).anyTimes(); - expect(sw2.getBuffers()).andReturn(swFeatures.getBuffers()).anyTimes(); - expect(sw2.getStringId()) - .andReturn(HexString.toHexString(2L)).anyTimes(); - - //fastWilcards mocked as this constant - int fastWildcards = - OFMatch.OFPFW_IN_PORT | - OFMatch.OFPFW_NW_PROTO | - OFMatch.OFPFW_TP_SRC | - OFMatch.OFPFW_TP_DST | - OFMatch.OFPFW_NW_SRC_ALL | - OFMatch.OFPFW_NW_DST_ALL | - OFMatch.OFPFW_NW_TOS; - - expect(sw1.getAttribute(IOFSwitch.PROP_FASTWILDCARDS)).andReturn(fastWildcards).anyTimes(); + expect(sw2.getId()).andReturn(DatapathId.of(2L)).anyTimes(); + expect(sw2.getBuffers()).andReturn(swFeatures.getNBuffers()).anyTimes(); + expect(sw2.getId().toString()) + .andReturn(DatapathId.of(2L).toString()).anyTimes(); + expect(sw1.hasAttribute(IOFSwitch.PROP_SUPPORTS_OFPP_TABLE)).andReturn(true).anyTimes(); - expect(sw2.getAttribute(IOFSwitch.PROP_FASTWILDCARDS)).andReturn(fastWildcards).anyTimes(); expect(sw2.hasAttribute(IOFSwitch.PROP_SUPPORTS_OFPP_TABLE)).andReturn(true).anyTimes(); // Load the switch map - Map<Long, IOFSwitch> switches = new HashMap<Long, IOFSwitch>(); - switches.put(1L, sw1); - switches.put(2L, sw2); - mockFloodlightProvider.setSwitches(switches); + Map<DatapathId, IOFSwitch> switches = new HashMap<DatapathId, IOFSwitch>(); + switches.put(DatapathId.of(1L), sw1); + switches.put(DatapathId.of(2L), sw2); + getMockSwitchService().setSwitches(switches); // Build test packet testPacket = new Ethernet() @@ -217,54 +210,33 @@ public class ForwardingTest extends FloodlightTestCase { // Mock Packet-in testPacketSerialized = testPacket.serialize(); - packetIn = - ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory(). - getMessage(OFType.PACKET_IN)) - .setBufferId(-1) - .setInPort((short) 1) - .setPacketData(testPacketSerialized) + packetIn = factory.buildPacketIn() + .setBufferId(OFBufferId.NO_BUFFER) + .setInPort(OFPort.of(1)) + .setData(testPacketSerialized) .setReason(OFPacketInReason.NO_MATCH) - .setTotalLength((short) testPacketSerialized.length); + .build(); // Mock Packet-out - packetOut = - (OFPacketOut) mockFloodlightProvider.getOFMessageFactory(). - getMessage(OFType.PACKET_OUT); - packetOut.setBufferId(this.packetIn.getBufferId()) - .setInPort(this.packetIn.getInPort()); List<OFAction> poactions = new ArrayList<OFAction>(); - poactions.add(new OFActionOutput((short) 3, (short) 0xffff)); - packetOut.setActions(poactions) - .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH) - .setPacketData(testPacketSerialized) - .setLengthU(OFPacketOut.MINIMUM_LENGTH+ - packetOut.getActionsLength()+ - testPacketSerialized.length); + poactions.add(factory.actions().output(OFPort.of(3), Integer.MAX_VALUE)); + packetOut = factory.buildPacketOut() + .setBufferId(this.packetIn.getBufferId()) + .setInPort(this.packetIn.getInPort()) + .setActions(poactions) + .setData(testPacketSerialized) + .build(); // Mock Packet-out with OFPP_FLOOD action - packetOutFlooded = - (OFPacketOut) mockFloodlightProvider.getOFMessageFactory(). - getMessage(OFType.PACKET_OUT); - packetOutFlooded.setBufferId(this.packetIn.getBufferId()) - .setInPort(this.packetIn.getInPort()); poactions = new ArrayList<OFAction>(); - poactions.add(new OFActionOutput(OFPort.OFPP_FLOOD.getValue(), - (short) 0xffff)); - packetOutFlooded.setActions(poactions) - .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH) - .setPacketData(testPacketSerialized) - .setLengthU(OFPacketOut.MINIMUM_LENGTH+ - packetOutFlooded.getActionsLength()+ - testPacketSerialized.length); - - expected_wildcards = fastWildcards; - expected_wildcards &= ~OFMatch.OFPFW_IN_PORT & - ~OFMatch.OFPFW_DL_VLAN & - ~OFMatch.OFPFW_DL_SRC & - ~OFMatch.OFPFW_DL_DST; - expected_wildcards &= ~OFMatch.OFPFW_NW_SRC_MASK & - ~OFMatch.OFPFW_NW_DST_MASK; - + poactions.add(factory.actions().output(OFPort.FLOOD, Integer.MAX_VALUE)); + packetOutFlooded = factory.buildPacketOut() + .setBufferId(this.packetIn.getBufferId()) + .setInPort(this.packetIn.getInPort()) + .setActions(poactions) + .setData(testPacketSerialized) + .build(); + IFloodlightProviderService.bcStore. put(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD, @@ -274,39 +246,39 @@ public class ForwardingTest extends FloodlightTestCase { enum DestDeviceToLearn { NONE, DEVICE1 ,DEVICE2 }; public void learnDevices(DestDeviceToLearn destDeviceToLearn) { // Build src and dest devices - byte[] dataLayerSource = ((Ethernet)testPacket).getSourceMACAddress(); - byte[] dataLayerDest = + MacAddress dataLayerSource = ((Ethernet)testPacket).getSourceMACAddress(); + MacAddress dataLayerDest = ((Ethernet)testPacket).getDestinationMACAddress(); - int networkSource = + IPv4Address networkSource = ((IPv4)((Ethernet)testPacket).getPayload()). getSourceAddress(); - int networkDest = + IPv4Address networkDest = ((IPv4)((Ethernet)testPacket).getPayload()). getDestinationAddress(); reset(topology); - expect(topology.isAttachmentPointPort(1L, (short)1)) + expect(topology.isAttachmentPointPort(DatapathId.of(1L), OFPort.of(1))) .andReturn(true) .anyTimes(); - expect(topology.isAttachmentPointPort(2L, (short)3)) + expect(topology.isAttachmentPointPort(DatapathId.of(2L), OFPort.of(3))) .andReturn(true) .anyTimes(); - expect(topology.isAttachmentPointPort(1L, (short)3)) + expect(topology.isAttachmentPointPort(DatapathId.of(1L), OFPort.of(3))) .andReturn(true) .anyTimes(); replay(topology); srcDevice = - deviceManager.learnEntity(Ethernet.toLong(dataLayerSource), - null, networkSource, + deviceManager.learnEntity(dataLayerSource.getLong(), + null, networkSource.getInt(), 1L, 1); IDeviceService.fcStore. put(cntx, IDeviceService.CONTEXT_SRC_DEVICE, srcDevice); if (destDeviceToLearn == DestDeviceToLearn.DEVICE1) { dstDevice1 = - deviceManager.learnEntity(Ethernet.toLong(dataLayerDest), - null, networkDest, + deviceManager.learnEntity(dataLayerDest.getLong(), + null, networkDest.getInt(), 2L, 3); IDeviceService.fcStore.put(cntx, IDeviceService.CONTEXT_DST_DEVICE, @@ -314,8 +286,8 @@ public class ForwardingTest extends FloodlightTestCase { } if (destDeviceToLearn == DestDeviceToLearn.DEVICE2) { dstDevice2 = - deviceManager.learnEntity(Ethernet.toLong(dataLayerDest), - null, networkDest, + deviceManager.learnEntity(dataLayerDest.getLong(), + null, networkDest.getInt(), 1L, 3); IDeviceService.fcStore.put(cntx, IDeviceService.CONTEXT_DST_DEVICE, @@ -330,52 +302,42 @@ public class ForwardingTest extends FloodlightTestCase { Capture<OFMessage> wc1 = new Capture<OFMessage>(CaptureType.ALL); Capture<OFMessage> wc2 = new Capture<OFMessage>(CaptureType.ALL); - Capture<FloodlightContext> bc1 = - new Capture<FloodlightContext>(CaptureType.ALL); - Capture<FloodlightContext> bc2 = - new Capture<FloodlightContext>(CaptureType.ALL); - - Route route = new Route(1L, 2L); + Route route = new Route(DatapathId.of(1L), DatapathId.of(2L)); List<NodePortTuple> nptList = new ArrayList<NodePortTuple>(); - nptList.add(new NodePortTuple(1L, (short)1)); - nptList.add(new NodePortTuple(1L, (short)3)); - nptList.add(new NodePortTuple(2L, (short)1)); - nptList.add(new NodePortTuple(2L, (short)3)); + nptList.add(new NodePortTuple(DatapathId.of(1L), OFPort.of(1))); + nptList.add(new NodePortTuple(DatapathId.of(1L), OFPort.of(3))); + nptList.add(new NodePortTuple(DatapathId.of(2L), OFPort.of(1))); + nptList.add(new NodePortTuple(DatapathId.of(2L), OFPort.of(3))); route.setPath(nptList); - expect(routingEngine.getRoute(1L, (short)1, 2L, (short)3, 0)).andReturn(route).atLeastOnce(); + expect(routingEngine.getRoute(DatapathId.of(1L), OFPort.of(1), DatapathId.of(2L), OFPort.of(3), U64.ZERO)).andReturn(route).atLeastOnce(); // Expected Flow-mods - OFMatch match = new OFMatch(); - match.loadFromPacket(testPacketSerialized, (short) 1); - OFActionOutput action = new OFActionOutput((short)3, (short)0xffff); + Match match = ((OFPacketIn)testPacket).getMatch(); + OFActionOutput action = factory.actions().output(OFPort.of(3), Integer.MAX_VALUE); List<OFAction> actions = new ArrayList<OFAction>(); actions.add(action); - OFFlowMod fm1 = - (OFFlowMod) mockFloodlightProvider.getOFMessageFactory(). - getMessage(OFType.FLOW_MOD); - fm1.setIdleTimeout((short)5) - .setMatch(match.clone() - .setWildcards(expected_wildcards)) - .setActions(actions) - .setBufferId(OFPacketOut.BUFFER_ID_NONE) - .setCookie(2L << 52) - .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH); - OFFlowMod fm2 = fm1.clone(); - ((OFActionOutput)fm2.getActions().get(0)).setPort((short) 3); + OFFlowMod fm1 = factory.buildFlowAdd() + .setIdleTimeout((short)5) + .setMatch(match) + .setActions(actions) + .setBufferId(OFBufferId.NO_BUFFER) + .setCookie(U64.of(2L << 52)) + .build(); + OFFlowMod fm2 = fm1.createBuilder().build(); - sw1.writeThrottled(capture(wc1), capture(bc1)); + sw1.write(capture(wc1)); expectLastCall().anyTimes(); - sw2.writeThrottled(capture(wc2), capture(bc2)); + sw2.write(capture(wc2)); expectLastCall().anyTimes(); reset(topology); - expect(topology.getL2DomainId(1L)).andReturn(1L).anyTimes(); - expect(topology.getL2DomainId(2L)).andReturn(1L).anyTimes(); - expect(topology.isAttachmentPointPort(1L, (short)1)).andReturn(true).anyTimes(); - expect(topology.isAttachmentPointPort(2L, (short)3)).andReturn(true).anyTimes(); - expect(topology.isIncomingBroadcastAllowed(anyLong(), anyShort())).andReturn(true).anyTimes(); + expect(topology.getL2DomainId(DatapathId.of(1L))).andReturn(DatapathId.of(1L)).anyTimes(); + expect(topology.getL2DomainId(DatapathId.of(2L))).andReturn(DatapathId.of(1L)).anyTimes(); + expect(topology.isAttachmentPointPort(DatapathId.of(1L), OFPort.of(1))).andReturn(true).anyTimes(); + expect(topology.isAttachmentPointPort(DatapathId.of(2L), OFPort.of(3))).andReturn(true).anyTimes(); + expect(topology.isIncomingBroadcastAllowed(DatapathId.of(anyLong()), OFPort.of(anyShort()))).andReturn(true).anyTimes(); // Reset mocks, trigger the packet in, and validate results replay(sw1, sw2, routingEngine, topology); @@ -403,39 +365,34 @@ public class ForwardingTest extends FloodlightTestCase { public void testForwardSingleSwitchPath() throws Exception { learnDevices(DestDeviceToLearn.DEVICE2); - Route route = new Route(1L, 1L); - route.getPath().add(new NodePortTuple(1L, (short)1)); - route.getPath().add(new NodePortTuple(1L, (short)3)); - expect(routingEngine.getRoute(1L, (short)1, 1L, (short)3, 0)).andReturn(route).atLeastOnce(); + Route route = new Route(DatapathId.of(1L), DatapathId.of(1L)); + route.getPath().add(new NodePortTuple(DatapathId.of(1L), OFPort.of(1))); + route.getPath().add(new NodePortTuple(DatapathId.of(1L), OFPort.of(3))); + expect(routingEngine.getRoute(DatapathId.of(1L), OFPort.of(1), DatapathId.of(1L), OFPort.of(3), U64.ZERO)).andReturn(route).atLeastOnce(); // Expected Flow-mods - OFMatch match = new OFMatch(); - match.loadFromPacket(testPacketSerialized, (short) 1); - OFActionOutput action = new OFActionOutput((short)3, (short)0xffff); + Match match = ((OFPacketIn) testPacket).getMatch(); + OFActionOutput action = factory.actions().output(OFPort.of(3), Integer.MAX_VALUE); List<OFAction> actions = new ArrayList<OFAction>(); actions.add(action); - OFFlowMod fm1 = - (OFFlowMod) mockFloodlightProvider.getOFMessageFactory(). - getMessage(OFType.FLOW_MOD); - fm1.setIdleTimeout((short)5) - .setMatch(match.clone() - .setWildcards(expected_wildcards)) + OFFlowMod fm1 = factory.buildFlowAdd() + .setIdleTimeout((short)5) + .setMatch(match) .setActions(actions) - .setBufferId(OFPacketOut.BUFFER_ID_NONE) - .setCookie(2L << 52) - .setLengthU(OFFlowMod.MINIMUM_LENGTH + - OFActionOutput.MINIMUM_LENGTH); + .setBufferId(OFBufferId.NO_BUFFER) + .setCookie(U64.of(2L<< 52)) + .build(); // Record expected packet-outs/flow-mods - sw1.writeThrottled(fm1, cntx); - sw1.writeThrottled(packetOut, cntx); + sw1.write(fm1); + sw1.write(packetOut); reset(topology); - expect(topology.isIncomingBroadcastAllowed(anyLong(), anyShort())).andReturn(true).anyTimes(); - expect(topology.getL2DomainId(1L)).andReturn(1L).anyTimes(); - expect(topology.isAttachmentPointPort(1L, (short)1)).andReturn(true).anyTimes(); - expect(topology.isAttachmentPointPort(1L, (short)3)).andReturn(true).anyTimes(); + expect(topology.isIncomingBroadcastAllowed(DatapathId.of(anyLong()), OFPort.of(anyShort()))).andReturn(true).anyTimes(); + expect(topology.getL2DomainId(DatapathId.of(1L))).andReturn(DatapathId.of(1L)).anyTimes(); + expect(topology.isAttachmentPointPort(DatapathId.of(1L), OFPort.of(1))).andReturn(true).anyTimes(); + expect(topology.isAttachmentPointPort(DatapathId.of(1L), OFPort.of(3))).andReturn(true).anyTimes(); // Reset mocks, trigger the packet in, and validate results replay(sw1, sw2, routingEngine, topology); @@ -448,49 +405,44 @@ public class ForwardingTest extends FloodlightTestCase { learnDevices(DestDeviceToLearn.DEVICE2); reset(topology); - expect(topology.isAttachmentPointPort(EasyMock.anyLong(), EasyMock.anyShort())) + expect(topology.isAttachmentPointPort(DatapathId.of(anyLong()), OFPort.of(anyShort()))) .andReturn(true).anyTimes(); - expect(topology.getL2DomainId(1L)).andReturn(1L).anyTimes(); + expect(topology.getL2DomainId(DatapathId.of(1L))).andReturn(DatapathId.of(1L)).anyTimes(); replay(topology); - Route route = new Route(1L, 1L); - route.getPath().add(new NodePortTuple(1L, (short)1)); - route.getPath().add(new NodePortTuple(1L, (short)3)); - expect(routingEngine.getRoute(1L, (short)1, 1L, (short)3, 0)).andReturn(route).atLeastOnce(); + Route route = new Route(DatapathId.of(1L), DatapathId.of(1L)); + route.getPath().add(new NodePortTuple(DatapathId.of(1L), OFPort.of(1))); + route.getPath().add(new NodePortTuple(DatapathId.of(1L), OFPort.of(3))); + expect(routingEngine.getRoute(DatapathId.of(1L), OFPort.of(1), DatapathId.of(1L), OFPort.of(3), U64.ZERO)).andReturn(route).atLeastOnce(); // Expected Flow-mods - OFMatch match = new OFMatch(); - match.loadFromPacket(testPacketSerialized, (short) 1); - OFActionOutput action = new OFActionOutput((short)3, (short)0xffff); + Match match = ((OFPacketIn) testPacket).getMatch(); + OFActionOutput action = factory.actions().output(OFPort.of(3), Integer.MAX_VALUE); List<OFAction> actions = new ArrayList<OFAction>(); actions.add(action); - OFFlowMod fm1 = - (OFFlowMod) mockFloodlightProvider.getOFMessageFactory(). - getMessage(OFType.FLOW_MOD); - fm1.setIdleTimeout((short)5) - .setMatch(match.clone() - .setWildcards(expected_wildcards)) - .setActions(actions) - .setBufferId(OFPacketOut.BUFFER_ID_NONE) - .setCookie(2L << 52) - .setLengthU(OFFlowMod.MINIMUM_LENGTH + - OFActionOutput.MINIMUM_LENGTH); + OFFlowMod fm1 = factory.buildFlowAdd() + .setIdleTimeout((short)5) + .setMatch(match) + .setActions(actions) + .setBufferId(OFBufferId.NO_BUFFER) + .setCookie(U64.of(2L << 52)) + .build(); // Record expected packet-outs/flow-mods // We will inject the packet_in 3 times and expect 1 flow mod and // 3 packet outs due to flow mod dampening - sw1.writeThrottled(fm1, cntx); + sw1.write(fm1); expectLastCall().once(); - sw1.writeThrottled(packetOut, cntx); + sw1.write(packetOut); expectLastCall().times(3); reset(topology); - expect(topology.isIncomingBroadcastAllowed(anyLong(), anyShort())).andReturn(true).anyTimes(); - expect(topology.getL2DomainId(1L)).andReturn(1L).anyTimes(); - expect(topology.isAttachmentPointPort(1L, (short)1)).andReturn(true).anyTimes(); - expect(topology.isAttachmentPointPort(1L, (short)3)).andReturn(true).anyTimes(); + expect(topology.isIncomingBroadcastAllowed(DatapathId.of(anyLong()), OFPort.of(anyShort()))).andReturn(true).anyTimes(); + expect(topology.getL2DomainId(DatapathId.of(1L))).andReturn(DatapathId.of(1L)).anyTimes(); + expect(topology.isAttachmentPointPort(DatapathId.of(1L), OFPort.of(1))).andReturn(true).anyTimes(); + expect(topology.isAttachmentPointPort(DatapathId.of(1L), OFPort.of(3))).andReturn(true).anyTimes(); // Reset mocks, trigger the packet in, and validate results replay(sw1, routingEngine, topology); @@ -509,14 +461,14 @@ public class ForwardingTest extends FloodlightTestCase { // Reset mocks, trigger the packet in, and validate results reset(topology); - expect(topology.isIncomingBroadcastAllowed(1L, (short)1)).andReturn(true).anyTimes(); - expect(topology.isAttachmentPointPort(EasyMock.anyLong(), - EasyMock.anyShort())) + expect(topology.isIncomingBroadcastAllowed(DatapathId.of(1L), OFPort.of(1))).andReturn(true).anyTimes(); + expect(topology.isAttachmentPointPort(DatapathId.of(anyLong()), + OFPort.of(anyShort()))) .andReturn(true) .anyTimes(); expect(sw1.hasAttribute(IOFSwitch.PROP_SUPPORTS_OFPP_FLOOD)) .andReturn(true).anyTimes(); - sw1.writeThrottled(packetOutFlooded, cntx); + sw1.write(packetOutFlooded); expectLastCall().once(); replay(sw1, sw2, routingEngine, topology); forwarding.receive(sw1, this.packetIn, cntx); diff --git a/src/test/java/net/floodlightcontroller/learningswitch/LearningSwitchTest.java b/src/test/java/net/floodlightcontroller/learningswitch/LearningSwitchTest.java index d8da84ff89bea099c40af6792b7c0ad632a99514..f0bf807fd0da056edeb369f2f6fd211b6388fd84 100644 --- a/src/test/java/net/floodlightcontroller/learningswitch/LearningSwitchTest.java +++ b/src/test/java/net/floodlightcontroller/learningswitch/LearningSwitchTest.java @@ -21,15 +21,12 @@ import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; +import static org.junit.Assert.*; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; + import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; -import net.floodlightcontroller.core.module.FloodlightTestModuleLoader; -import net.floodlightcontroller.core.module.IFloodlightModule; -import net.floodlightcontroller.core.test.MockFloodlightProvider; import net.floodlightcontroller.packet.Data; import net.floodlightcontroller.packet.Ethernet; import net.floodlightcontroller.packet.IPacket; @@ -39,17 +36,22 @@ import net.floodlightcontroller.test.FloodlightTestCase; 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.OFPacketIn.OFPacketInReason; -import org.openflow.protocol.OFPacketOut; -import org.openflow.protocol.OFPort; -import org.openflow.protocol.OFType; -import org.openflow.protocol.action.OFAction; -import org.openflow.protocol.action.OFActionOutput; -import org.openflow.protocol.action.OFActionType; +import org.projectfloodlight.openflow.protocol.OFFactories; +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFPacketInReason; +import org.projectfloodlight.openflow.protocol.OFPacketOut; +import org.projectfloodlight.openflow.protocol.OFVersion; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFBufferId; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.U64; +import org.projectfloodlight.openflow.types.VlanVid; +import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.action.OFAction; +import org.projectfloodlight.openflow.protocol.action.OFActionOutput; /** * @@ -64,21 +66,12 @@ public class LearningSwitchTest extends FloodlightTestCase { protected IPacket testPacketReply; protected byte[] testPacketReplySerialized; private LearningSwitch learningSwitch; + private OFFactory factory = OFFactories.getFactory(OFVersion.OF_13); @Override @Before public void setUp() throws Exception { super.setUp(); - FloodlightTestModuleLoader fml = new FloodlightTestModuleLoader(); - Collection<Class<? extends IFloodlightModule>> mods - = new ArrayList<Class<? extends IFloodlightModule>>(); - mods.add(LearningSwitch.class); - - fml.setupModules(mods, null); - learningSwitch = (LearningSwitch) fml.getModuleByName(LearningSwitch.class); - mockFloodlightProvider = - (MockFloodlightProvider) fml.getModuleByName(MockFloodlightProvider.class); - // Build our test packet this.testPacket = new Ethernet() .setDestinationMACAddress("00:11:22:33:44:55") @@ -129,29 +122,27 @@ public class LearningSwitchTest extends FloodlightTestCase { this.testPacketReplySerialized = testPacketReply.serialize(); // Build the PacketIn - this.packetIn = ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.PACKET_IN)) - .setBufferId(OFPacketOut.BUFFER_ID_NONE) - .setInPort((short) 1) - .setPacketData(this.testPacketSerialized) + this.packetIn = factory.buildPacketIn() + .setBufferId(OFBufferId.NO_BUFFER) + .setInPort(OFPort.of(1)) + .setData(this.testPacketSerialized) .setReason(OFPacketInReason.NO_MATCH) - .setTotalLength((short) this.testPacketSerialized.length); + .build(); } @Test public void testFlood() throws Exception { // build our expected flooded packetOut - OFPacketOut po = new OFPacketOut() - .setActions(Arrays.asList(new OFAction[] {new OFActionOutput().setPort(OFPort.OFPP_FLOOD.getValue())})) - .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH) - .setBufferId(-1) - .setInPort((short)1) - .setPacketData(this.testPacketSerialized); - po.setLengthU(OFPacketOut.MINIMUM_LENGTH + po.getActionsLengthU() - + this.testPacketSerialized.length); + OFPacketOut po = factory.buildPacketOut() + .setActions(Arrays.asList((OFAction)factory.actions().output(OFPort.FLOOD, Integer.MAX_VALUE))) + .setBufferId(OFBufferId.NO_BUFFER) + .setInPort(OFPort.of(1)) + .setData(this.testPacketSerialized) + .build(); // Mock up our expected behavior IOFSwitch mockSwitch = createMock(IOFSwitch.class); - expect(mockSwitch.getStringId()).andReturn("00:11:22:33:44:55:66:77").anyTimes(); + expect(mockSwitch.getId().toString()).andReturn("00:11:22:33:44:55:66:77").anyTimes(); mockSwitch.write(po, null); // Start recording the replay on the mocks @@ -163,7 +154,7 @@ public class LearningSwitchTest extends FloodlightTestCase { listener.receive(mockSwitch, this.packetIn, parseAndAnnotate(this.packetIn)); // Verify the replay matched our expectations - short result = learningSwitch.getFromPortMap(mockSwitch, Ethernet.toLong(Ethernet.toMACAddress("00:44:33:22:11:00")), (short) 42).shortValue(); + OFPort result = learningSwitch.getFromPortMap(mockSwitch, MacAddress.of("00:44:33:22:11:00"), VlanVid.ofVlan(42)); verify(mockSwitch); // Verify the MAC table inside the switch @@ -173,62 +164,40 @@ public class LearningSwitchTest extends FloodlightTestCase { @Test public void testFlowMod() throws Exception { // tweak the test packet in since we need a bufferId - this.packetIn.setBufferId(50); + this.packetIn = packetIn.createBuilder().setBufferId(OFBufferId.of(50)).build(); // build expected flow mods - OFMessage fm1 = ((OFFlowMod) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.FLOW_MOD)) - .setActions(Arrays.asList(new OFAction[] { - new OFActionOutput().setPort((short) 2).setMaxLength((short) -1)})) - .setBufferId(OFPacketOut.BUFFER_ID_NONE) - .setCommand(OFFlowMod.OFPFC_ADD) + OFMessage fm1 = factory.buildFlowAdd() + .setActions(Arrays.asList((OFAction)factory.actions().output(OFPort.FLOOD, -1))) + .setBufferId(OFBufferId.NO_BUFFER) .setIdleTimeout((short) 5) - .setMatch(new OFMatch() - .loadFromPacket(testPacketSerialized, (short) 1) - .setWildcards(OFMatch.OFPFW_NW_PROTO | OFMatch.OFPFW_TP_SRC | OFMatch.OFPFW_TP_DST - | OFMatch.OFPFW_NW_TOS)) - .setOutPort(OFPort.OFPP_NONE.getValue()) - .setCookie(1L << 52) + .setMatch(((OFPacketIn) testPacket).getMatch()) + .setOutPort(OFPort.ANY) + .setCookie(U64.of(1L << 52)) .setPriority((short) 100) - .setFlags((short)(1 << 0)) - .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH); - OFMessage fm2 = ((OFFlowMod) mockFloodlightProvider.getOFMessageFactory().getMessage(OFType.FLOW_MOD)) - .setActions(Arrays.asList(new OFAction[] { - new OFActionOutput().setPort((short) 1).setMaxLength((short) -1)})) - .setBufferId(-1) - .setCommand(OFFlowMod.OFPFC_ADD) + .build(); + OFMessage fm2 = factory.buildFlowAdd() + .setActions(Arrays.asList((OFAction)factory.actions().output(OFPort.of(1), -1))) + .setBufferId(OFBufferId.NO_BUFFER) .setIdleTimeout((short) 5) - .setMatch(new OFMatch() - .loadFromPacket(testPacketReplySerialized, (short) 2) - .setWildcards(OFMatch.OFPFW_NW_PROTO | OFMatch.OFPFW_TP_SRC | OFMatch.OFPFW_TP_DST - | OFMatch.OFPFW_NW_TOS)) - .setOutPort(OFPort.OFPP_NONE.getValue()) - .setCookie(1L << 52) + .setMatch(((OFPacketIn) testPacketReply).getMatch()) + .setOutPort(OFPort.ANY) + .setCookie(U64.of(1L << 52)) .setPriority((short) 100) - .setFlags((short)(1 << 0)) - .setLengthU(OFFlowMod.MINIMUM_LENGTH+OFActionOutput.MINIMUM_LENGTH); - - OFActionOutput ofAcOut = new OFActionOutput(); - ofAcOut.setMaxLength((short) -1); - ofAcOut.setPort((short)2); - ofAcOut.setLength((short) 8); - ofAcOut.setType(OFActionType.OUTPUT); - - OFPacketOut packetOut = new OFPacketOut(); - packetOut.setActions(Arrays.asList(new OFAction[] {ofAcOut})) - .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH) - .setBufferId(50) - .setInPort((short)1) - .setPacketData(null) - .setLength((short) (OFPacketOut.MINIMUM_LENGTH + OFActionOutput.MINIMUM_LENGTH)); - packetOut.setActionFactory(mockFloodlightProvider.getOFMessageFactory()); + .build(); + + OFActionOutput ofAcOut = factory.actions().output(OFPort.of(2), -1); + + OFPacketOut packetOut = factory.buildPacketOut() + .setActions(Arrays.asList((OFAction)ofAcOut)) + .setBufferId(OFBufferId.of(50)) + .setInPort(OFPort.of(1)) + .build(); // Mock up our expected behavior IOFSwitch mockSwitch = createMock(IOFSwitch.class); - expect(mockSwitch.getId()).andReturn(1L).anyTimes(); - expect(mockSwitch.getAttribute(IOFSwitch.PROP_FASTWILDCARDS)).andReturn((OFMatch.OFPFW_IN_PORT | OFMatch.OFPFW_NW_PROTO - | OFMatch.OFPFW_TP_SRC | OFMatch.OFPFW_TP_DST | OFMatch.OFPFW_NW_SRC_ALL - | OFMatch.OFPFW_NW_DST_ALL | OFMatch.OFPFW_NW_TOS)); - expect(mockSwitch.getBuffers()).andReturn(100).anyTimes(); + expect(mockSwitch.getId()).andReturn(DatapathId.of(1L)).anyTimes(); + expect(mockSwitch.getBuffers()).andReturn((long)100).anyTimes(); mockSwitch.write(packetOut, null); mockSwitch.write(fm1, null); mockSwitch.write(fm2, null); @@ -238,7 +207,7 @@ public class LearningSwitchTest extends FloodlightTestCase { // Populate the MAC table learningSwitch.addToPortMap(mockSwitch, - Ethernet.toLong(Ethernet.toMACAddress("00:11:22:33:44:55")), (short) 42, (short) 2); + MacAddress.of("00:11:22:33:44:55"), VlanVid.ofVlan(42), OFPort.of(2)); // Get the listener and trigger the packet in IOFMessageListener listener = mockFloodlightProvider.getListeners().get( @@ -246,7 +215,7 @@ public class LearningSwitchTest extends FloodlightTestCase { listener.receive(mockSwitch, this.packetIn, parseAndAnnotate(this.packetIn)); // Verify the replay matched our expectations - short result = learningSwitch.getFromPortMap(mockSwitch, Ethernet.toLong(Ethernet.toMACAddress("00:44:33:22:11:00")), (short) 42).shortValue(); + OFPort result = learningSwitch.getFromPortMap(mockSwitch, MacAddress.of("00:44:33:22:11:00"), VlanVid.ofVlan(42)); verify(mockSwitch); // Verify the MAC table inside the switch diff --git a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java b/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java index 940bd076ed4e4cecf46dd502c8466bbe4647596e..b2ba0f446582e7a69d6c22cd012a194539d2cf96 100644 --- a/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java +++ b/src/test/java/net/floodlightcontroller/linkdiscovery/internal/LinkDiscoveryManagerTest.java @@ -24,9 +24,11 @@ import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expectLastCall; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; +import static org.junit.Assert.*; import java.util.ArrayList; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -36,7 +38,6 @@ import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IListener.Command; import net.floodlightcontroller.core.IOFSwitch; -import net.floodlightcontroller.core.ImmutablePort; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.test.MockThreadPoolService; import net.floodlightcontroller.linkdiscovery.ILinkDiscoveryListener; @@ -64,13 +65,16 @@ import org.easymock.CaptureType; import org.easymock.EasyMock; import org.junit.Before; import org.junit.Test; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPacketIn; -import org.openflow.protocol.OFPacketIn.OFPacketInReason; -import org.openflow.protocol.OFPhysicalPort; -import org.openflow.protocol.OFType; -import org.openflow.protocol.factory.BasicFactory; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.protocol.OFFactories; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFPacketInReason; +import org.projectfloodlight.openflow.protocol.OFPortDesc; +import org.projectfloodlight.openflow.protocol.OFVersion; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFBufferId; +import org.projectfloodlight.openflow.types.OFPort; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -111,7 +115,7 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { private IOFSwitch createMockSwitch(Long id) { IOFSwitch mockSwitch = createNiceMock(IOFSwitch.class); - expect(mockSwitch.getId()).andReturn(id).anyTimes(); + expect(mockSwitch.getId()).andReturn(DatapathId.of(id)).anyTimes(); return mockSwitch; } @@ -143,10 +147,10 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { IOFSwitch sw1 = createMockSwitch(1L); IOFSwitch sw2 = createMockSwitch(2L); - Map<Long, IOFSwitch> switches = new HashMap<Long, IOFSwitch>(); - switches.put(1L, sw1); - switches.put(2L, sw2); - getMockFloodlightProvider().setSwitches(switches); + Map<DatapathId, IOFSwitch> switches = new HashMap<DatapathId, IOFSwitch>(); + switches.put(DatapathId.of(1L), sw1); + switches.put(DatapathId.of(2L), sw2); + getMockSwitchService().setSwitches(switches); replay(sw1, sw2); } @@ -154,14 +158,14 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { public void testAddOrUpdateLink() throws Exception { LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager(); - Link lt = new Link(1L, 2, 2L, 1); - LinkInfo info = new LinkInfo(System.currentTimeMillis(), - System.currentTimeMillis(), null); + Link lt = new Link(DatapathId.of(1L), OFPort.of(2), DatapathId.of(2L), OFPort.of(1)); + LinkInfo info = new LinkInfo(new Date(), + new Date(), null); linkDiscovery.addOrUpdateLink(lt, info); - NodePortTuple srcNpt = new NodePortTuple(1L, 2); - NodePortTuple dstNpt = new NodePortTuple(2L, 1); + NodePortTuple srcNpt = new NodePortTuple(DatapathId.of(1L), OFPort.of(2)); + NodePortTuple dstNpt = new NodePortTuple(DatapathId.of(2L), OFPort.of(1)); // check invariants hold assertNotNull(linkDiscovery.switchLinks.get(lt.getSrc())); @@ -177,9 +181,9 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { public void testDeleteLink() throws Exception { LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager(); - Link lt = new Link(1L, 2, 2L, 1); - LinkInfo info = new LinkInfo(System.currentTimeMillis(), - System.currentTimeMillis(), null); + Link lt = new Link(DatapathId.of(1L), OFPort.of(2), DatapathId.of(2L), OFPort.of(1)); + LinkInfo info = new LinkInfo(new Date(), + new Date(), null); linkDiscovery.addOrUpdateLink(lt, info); linkDiscovery.deleteLinks(Collections.singletonList(lt), "Test"); @@ -195,12 +199,12 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { public void testAddOrUpdateLinkToSelf() throws Exception { LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager(); - Link lt = new Link(1L, 2, 2L, 3); - NodePortTuple srcNpt = new NodePortTuple(1L, 2); - NodePortTuple dstNpt = new NodePortTuple(2L, 3); + Link lt = new Link(DatapathId.of(1L), OFPort.of(2), DatapathId.of(2L), OFPort.of(3)); + NodePortTuple srcNpt = new NodePortTuple(DatapathId.of(1L), OFPort.of(2)); + NodePortTuple dstNpt = new NodePortTuple(DatapathId.of(2L), OFPort.of(3)); - LinkInfo info = new LinkInfo(System.currentTimeMillis(), - System.currentTimeMillis(), null); + LinkInfo info = new LinkInfo(new Date(), + new Date(), null); linkDiscovery.addOrUpdateLink(lt, info); // check invariants hold @@ -217,12 +221,12 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { public void testDeleteLinkToSelf() throws Exception { LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager(); - Link lt = new Link(1L, 2, 1L, 3); - NodePortTuple srcNpt = new NodePortTuple(1L, 2); - NodePortTuple dstNpt = new NodePortTuple(2L, 3); + Link lt = new Link(DatapathId.of(1L), OFPort.of(2), DatapathId.of(1L), OFPort.of(3)); + NodePortTuple srcNpt = new NodePortTuple(DatapathId.of(1L), OFPort.of(2)); + NodePortTuple dstNpt = new NodePortTuple(DatapathId.of(2L), OFPort.of(3)); - LinkInfo info = new LinkInfo(System.currentTimeMillis(), - System.currentTimeMillis(), null); + LinkInfo info = new LinkInfo(new Date(), + new Date(), null); linkDiscovery.addOrUpdateLink(lt, info); linkDiscovery.deleteLinks(Collections.singletonList(lt), "Test to self"); @@ -238,15 +242,15 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { public void testRemovedSwitch() { LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager(); - Link lt = new Link(1L, 2, 2L, 1); - NodePortTuple srcNpt = new NodePortTuple(1L, 2); - NodePortTuple dstNpt = new NodePortTuple(2L, 1); - LinkInfo info = new LinkInfo(System.currentTimeMillis(), - System.currentTimeMillis(), null); + Link lt = new Link(DatapathId.of(1L), OFPort.of(2), DatapathId.of(2L), OFPort.of(1)); + NodePortTuple srcNpt = new NodePortTuple(DatapathId.of(1L), OFPort.of(2)); + NodePortTuple dstNpt = new NodePortTuple(DatapathId.of(2L), OFPort.of(1)); + LinkInfo info = new LinkInfo(new Date(), + new Date(), null); linkDiscovery.addOrUpdateLink(lt, info); - IOFSwitch sw1 = getMockFloodlightProvider().getSwitch(1L); - IOFSwitch sw2 = getMockFloodlightProvider().getSwitch(2L); + IOFSwitch sw1 = getMockSwitchService().getSwitch(DatapathId.of(1L)); + IOFSwitch sw2 = getMockSwitchService().getSwitch(DatapathId.of(2L)); // Mock up our expected behavior linkDiscovery.switchRemoved(sw1.getId()); verify(sw1, sw2); @@ -264,9 +268,9 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager(); IOFSwitch sw1 = createMockSwitch(1L); replay(sw1); - Link lt = new Link(1L, 2, 1L, 3); - LinkInfo info = new LinkInfo(System.currentTimeMillis(), - System.currentTimeMillis(), null); + Link lt = new Link(DatapathId.of(1L), OFPort.of(2), DatapathId.of(1L), OFPort.of(3)); + LinkInfo info = new LinkInfo(new Date(), + new Date(), null); linkDiscovery.addOrUpdateLink(lt, info); // Mock up our expected behavior @@ -284,14 +288,14 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { public void testAddUpdateLinks() throws Exception { LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager(); - Link lt = new Link(1L, 1, 2L, 1); - NodePortTuple srcNpt = new NodePortTuple(1L, 1); - NodePortTuple dstNpt = new NodePortTuple(2L, 1); + Link lt = new Link(DatapathId.of(1L), OFPort.of(1), DatapathId.of(2L), OFPort.of(1)); + NodePortTuple srcNpt = new NodePortTuple(DatapathId.of(1L), OFPort.of(1)); + NodePortTuple dstNpt = new NodePortTuple(DatapathId.of(2L), OFPort.of(2)); LinkInfo info; - info = new LinkInfo(System.currentTimeMillis() - 40000, - System.currentTimeMillis() - 40000, null); + info = new LinkInfo(new Date(System.currentTimeMillis() - 40000), + new Date(System.currentTimeMillis() - 40000), null); linkDiscovery.addOrUpdateLink(lt, info); // check invariants hold @@ -306,9 +310,9 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { linkDiscovery.timeoutLinks(); - info = new LinkInfo(System.currentTimeMillis(),/* firstseen */ + info = new LinkInfo(new Date(),/* firstseen */ null,/* unicast */ - System.currentTimeMillis()); + new Date()); linkDiscovery.addOrUpdateLink(lt, info); assertTrue(linkDiscovery.links.get(lt).getUnicastValidTime() == null); assertTrue(linkDiscovery.links.get(lt).getMulticastValidTime() != null); @@ -319,8 +323,8 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { // this to test timeout after this test. Although the info is initialized // with LT_OPENFLOW_LINK, the link property should be changed to LT_NON_OPENFLOW // by the addOrUpdateLink method. - info = new LinkInfo(System.currentTimeMillis() - 40000, - System.currentTimeMillis() - 40000, null); + info = new LinkInfo(new Date(System.currentTimeMillis() - 40000), + new Date(System.currentTimeMillis() - 40000), null); linkDiscovery.addOrUpdateLink(lt, info); // Expect to timeout the unicast Valid Time, but not the multicast Valid time @@ -330,15 +334,15 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { assertTrue(linkDiscovery.links.get(lt).getMulticastValidTime() != null); // Set the multicastValidTime to be old and see if that also times out. - info = new LinkInfo(System.currentTimeMillis() - 40000, - null, System.currentTimeMillis() - 40000); + info = new LinkInfo(new Date(System.currentTimeMillis() - 40000), + null, new Date(System.currentTimeMillis() - 40000)); linkDiscovery.addOrUpdateLink(lt, info); linkDiscovery.timeoutLinks(); assertTrue(linkDiscovery.links.get(lt) == null); // Test again only with multicast LLDP - info = new LinkInfo(System.currentTimeMillis() - 40000, - null, System.currentTimeMillis() - 40000); + info = new LinkInfo(new Date(System.currentTimeMillis() - 40000), + null, new Date(System.currentTimeMillis() - 40000)); linkDiscovery.addOrUpdateLink(lt, info); assertTrue(linkDiscovery.links.get(lt).getUnicastValidTime() == null); assertTrue(linkDiscovery.links.get(lt).getMulticastValidTime() != null); @@ -348,36 +352,36 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { assertTrue(linkDiscovery.links.get(lt) == null); // Start clean and see if loops are also added. - lt = new Link(1L, 1, 1L, 2); - srcNpt = new NodePortTuple(1L, 1); - dstNpt = new NodePortTuple(1L, 2); - info = new LinkInfo(System.currentTimeMillis() - 40000, - null, System.currentTimeMillis() - 40000); + lt = new Link(DatapathId.of(1L), OFPort.of(1), DatapathId.of(1L), OFPort.of(2)); + srcNpt = new NodePortTuple(DatapathId.of(1L), OFPort.of(1)); + dstNpt = new NodePortTuple(DatapathId.of(1L), OFPort.of(2)); + info = new LinkInfo(new Date(System.currentTimeMillis() - 40000), + null, new Date(System.currentTimeMillis() - 40000)); linkDiscovery.addOrUpdateLink(lt, info); // Start clean and see if loops are also added. - lt = new Link(1L, 1, 1L, 3); - srcNpt = new NodePortTuple(1L, 1); - dstNpt = new NodePortTuple(1L, 3); - info = new LinkInfo(System.currentTimeMillis() - 40000, - null, System.currentTimeMillis() - 40000); + lt = new Link(DatapathId.of(1L), OFPort.of(1), DatapathId.of(1L), OFPort.of(3)); + srcNpt = new NodePortTuple(DatapathId.of(1L), OFPort.of(1)); + dstNpt = new NodePortTuple(DatapathId.of(1L), OFPort.of(3)); + info = new LinkInfo(new Date(System.currentTimeMillis() - 40000), + null, new Date(System.currentTimeMillis() - 40000)); linkDiscovery.addOrUpdateLink(lt, info); // Start clean and see if loops are also added. - lt = new Link(1L, 4, 1L, 5); - srcNpt = new NodePortTuple(1L, 4); - dstNpt = new NodePortTuple(1L, 5); - info = new LinkInfo(System.currentTimeMillis() - 40000, - null, System.currentTimeMillis() - 40000); + lt = new Link(DatapathId.of(1L), OFPort.of(4), DatapathId.of(1L), OFPort.of(5)); + srcNpt = new NodePortTuple(DatapathId.of(1L), OFPort.of(4)); + dstNpt = new NodePortTuple(DatapathId.of(1L), OFPort.of(5)); + info = new LinkInfo(new Date(System.currentTimeMillis() - 40000), + null, new Date(System.currentTimeMillis() - 40000)); linkDiscovery.addOrUpdateLink(lt, info); // Start clean and see if loops are also added. - lt = new Link(1L, 3, 1L, 5); - srcNpt = new NodePortTuple(1L, 3); - dstNpt = new NodePortTuple(1L, 5); - info = new LinkInfo(System.currentTimeMillis() - 40000, - null, System.currentTimeMillis() - 40000); + lt = new Link(DatapathId.of(1L), OFPort.of(3), DatapathId.of(1L), OFPort.of(5)); + srcNpt = new NodePortTuple(DatapathId.of(1L), OFPort.of(3)); + dstNpt = new NodePortTuple(DatapathId.of(1L), OFPort.of(5)); + info = new LinkInfo(new Date(System.currentTimeMillis() - 40000), + null, new Date(System.currentTimeMillis() - 40000)); linkDiscovery.addOrUpdateLink(lt, info); } @@ -387,11 +391,11 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { IOFSwitch sw1 = createMockSwitch(1L); IOFSwitch sw2 = createMockSwitch(2L); replay(sw1, sw2); - Link lt = new Link(1L, 2, 2L, 1); - NodePortTuple srcNpt = new NodePortTuple(1L, 2); - NodePortTuple dstNpt = new NodePortTuple(2L, 1); - LinkInfo info = new LinkInfo(System.currentTimeMillis(), - System.currentTimeMillis(), null); + Link lt = new Link(DatapathId.of(1L), OFPort.of(2), DatapathId.of(2L), OFPort.of(1)); + NodePortTuple srcNpt = new NodePortTuple(DatapathId.of(1L), OFPort.of(2)); + NodePortTuple dstNpt = new NodePortTuple(DatapathId.of(2L), OFPort.of(1)); + LinkInfo info = new LinkInfo(new Date(), + new Date(), null); linkDiscovery.addOrUpdateLink(lt, info); // check invariants hold @@ -419,35 +423,34 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { public void testSwitchAdded() throws Exception { LinkDiscoveryManager linkDiscovery = getLinkDiscoveryManager(); Capture<OFMessage> wc; - Capture<FloodlightContext> fc; - Set<Short> qPorts; - OFPhysicalPort ofpp = new OFPhysicalPort(); - ofpp.setName("eth4242"); - ofpp.setPortNumber((short)4242); - ofpp.setHardwareAddress(HexString.fromHexString("5c:16:c7:00:00:01")); - ofpp.setCurrentFeatures(0); - ImmutablePort p1 = ImmutablePort.fromOFPhysicalPort(ofpp); + Set<OFPort> qPorts; + OFPortDesc ofpp = OFFactories.getFactory(OFVersion.OF_13).buildPortDesc() + .setName("eth4242") + .setPortNo(OFPort.of(4242)) + .setHwAddr(MacAddress.of("5c:16:c7:00:00:01")) + .setCurr(null) + .build(); + OFPort p1 = ofpp.getPortNo(); IOFSwitch sw1 = createMockSwitch(1L); // Set switch map in floodlightProvider. - Map<Long, IOFSwitch> switches = new HashMap<Long, IOFSwitch>(); - switches.put(1L, sw1); - getMockFloodlightProvider().setSwitches(switches); + Map<DatapathId, IOFSwitch> switches = new HashMap<DatapathId, IOFSwitch>(); + switches.put(DatapathId.of(1L), sw1); + getMockSwitchService().setSwitches(switches); // Create the set of ports - List<Short> ports = new ArrayList<Short>(); + List<OFPort> ports = new ArrayList<OFPort>(); for(short p=1; p<=20; ++p) { - ports.add(p); + ports.add(OFPort.of(p)); } // Set the captures. wc = new Capture<OFMessage>(CaptureType.ALL); - fc = new Capture<FloodlightContext>(CaptureType.ALL); // Expect switch to return those ports. expect(sw1.getEnabledPortNumbers()).andReturn(ports).anyTimes(); - expect(sw1.getPort(EasyMock.anyShort())).andReturn(p1).anyTimes(); - sw1.write(capture(wc), capture(fc)); + expect(sw1.getPort(OFPort.of(EasyMock.anyShort())).getPortNo()).andReturn(p1).anyTimes(); + sw1.write(capture(wc)); expectLastCall().anyTimes(); replay(sw1); @@ -494,12 +497,12 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { byte[] testPacketSerialized = testPacket.serialize(); OFPacketIn pi; // build out input packet - pi = ((OFPacketIn) BasicFactory.getInstance().getMessage(OFType.PACKET_IN)) - .setBufferId(-1) - .setInPort((short) 1) - .setPacketData(testPacketSerialized) + pi = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn() + .setBufferId(OFBufferId.NO_BUFFER) + .setInPort(OFPort.of(1)) + .setData(testPacketSerialized) .setReason(OFPacketInReason.NO_MATCH) - .setTotalLength((short) testPacketSerialized.length); + .build(); return pi; } @@ -513,7 +516,7 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { short vlan = 42; IOFSwitch mockSwitch = createMock(IOFSwitch.class); - expect(mockSwitch.getId()).andReturn(1L).anyTimes(); + expect(mockSwitch.getId()).andReturn(DatapathId.of(1L)).anyTimes(); replay(mockSwitch); /* TEST1: See basic packet flow */ @@ -521,7 +524,7 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { pi = createPacketIn(mac1, mac2, srcIp, dstIp, vlan); FloodlightContext cntx = new FloodlightContext(); Ethernet eth = new Ethernet(); - eth.deserialize(pi.getPacketData(), 0, pi.getPacketData().length); + eth.deserialize(pi.getData(), 0, pi.getData().length); IFloodlightProviderService.bcStore.put(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD, eth); @@ -532,14 +535,14 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { /* TEST2: Add mac1 to the ignore MAC list and see that the packet is * dropped */ - ldm.addMACToIgnoreList(HexString.toLong(mac1), 0); + ldm.addMACToIgnoreList(MacAddress.of(mac1), 0); ret = ldm.receive(mockSwitch, pi, cntx); assertEquals(Command.STOP, ret); /* Verify that if we send a packet with another MAC it still works */ pi = createPacketIn(mac2, mac3, srcIp, dstIp, vlan); cntx = new FloodlightContext(); eth = new Ethernet(); - eth.deserialize(pi.getPacketData(), 0, pi.getPacketData().length); + eth.deserialize(pi.getData(), 0, pi.getData().length); IFloodlightProviderService.bcStore.put(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD, eth); @@ -547,7 +550,7 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { assertEquals(Command.CONTINUE, ret); /* TEST3: Add a MAC range and see if that is ignored */ - ldm.addMACToIgnoreList(HexString.toLong(mac2), 8); + ldm.addMACToIgnoreList(MacAddress.of(mac2), 8); ret = ldm.receive(mockSwitch, pi, cntx); assertEquals(Command.STOP, ret); /* Send a packet with source MAC as mac3 and see that that is ignored @@ -556,7 +559,7 @@ public class LinkDiscoveryManagerTest extends FloodlightTestCase { pi = createPacketIn(mac3, mac1, srcIp, dstIp, vlan); cntx = new FloodlightContext(); eth = new Ethernet(); - eth.deserialize(pi.getPacketData(), 0, pi.getPacketData().length); + eth.deserialize(pi.getData(), 0, pi.getData().length); IFloodlightProviderService.bcStore.put(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD, eth); diff --git a/src/test/java/net/floodlightcontroller/loadbalancer/LoadBalancerTest.java b/src/test/java/net/floodlightcontroller/loadbalancer/LoadBalancerTest.java index b1f6b0253a4c0be0cec494d0767c18c58212119e..a78460f5d00c09f62fa3ace90d7f426a8713a9f3 100644 --- a/src/test/java/net/floodlightcontroller/loadbalancer/LoadBalancerTest.java +++ b/src/test/java/net/floodlightcontroller/loadbalancer/LoadBalancerTest.java @@ -25,6 +25,7 @@ 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.junit.Assert.*; import java.io.IOException; import java.util.ArrayList; @@ -36,17 +37,22 @@ import org.easymock.CaptureType; import org.easymock.EasyMock; 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.OFPacketOut; -import org.openflow.protocol.OFPort; -import org.openflow.protocol.OFType; -import org.openflow.protocol.OFPacketIn.OFPacketInReason; -import org.openflow.protocol.action.OFAction; -import org.openflow.protocol.action.OFActionOutput; -import org.openflow.util.HexString; +import org.projectfloodlight.openflow.protocol.OFFlowMod; +import org.projectfloodlight.openflow.protocol.OFFactories; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFPacketOut; +import org.projectfloodlight.openflow.protocol.OFVersion; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.IpProtocol; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFBufferId; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.types.U64; +import org.projectfloodlight.openflow.protocol.OFPacketInReason; +import org.projectfloodlight.openflow.protocol.action.OFAction; +import org.projectfloodlight.openflow.util.HexString; +import org.projectfloodlight.openflow.types.DatapathId; import org.sdnplatform.sync.ISyncService; import org.sdnplatform.sync.test.MockSyncService; @@ -55,8 +61,6 @@ import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.test.MockThreadPoolService; -import net.floodlightcontroller.counter.CounterStore; -import net.floodlightcontroller.counter.ICounterStoreService; import net.floodlightcontroller.devicemanager.IDeviceService; import net.floodlightcontroller.devicemanager.IEntityClassifierService; import net.floodlightcontroller.devicemanager.internal.DefaultEntityClassifier; @@ -82,618 +86,592 @@ import net.floodlightcontroller.topology.ITopologyService; import net.floodlightcontroller.topology.NodePortTuple; public class LoadBalancerTest extends FloodlightTestCase { - protected LoadBalancer lb; - - protected FloodlightContext cntx; - protected FloodlightModuleContext fmc; - protected MockDeviceManager deviceManager; - protected MockThreadPoolService tps; - protected FlowReconcileManager frm; - protected DefaultEntityClassifier entityClassifier; - protected IRoutingService routingEngine; - protected ITopologyService topology; - protected StaticFlowEntryPusher sfp; - protected MemoryStorageSource storage; - protected RestApiServer restApi; - protected VipsResource vipsResource; - protected PoolsResource poolsResource; - protected MembersResource membersResource; - private MockSyncService mockSyncService; - - protected LBVip vip1, vip2; - protected LBPool pool1, pool2, pool3; - protected LBMember member1, member2, member3, member4; - - @Override - @Before - public void setUp() throws Exception { - super.setUp(); - - lb = new LoadBalancer(); - - cntx = new FloodlightContext(); - fmc = new FloodlightModuleContext(); - entityClassifier = new DefaultEntityClassifier(); // dependency for device manager - frm = new FlowReconcileManager(); //dependency for device manager - tps = new MockThreadPoolService(); //dependency for device manager - deviceManager = new MockDeviceManager(); - topology = createMock(ITopologyService.class); - routingEngine = createMock(IRoutingService.class); - restApi = new RestApiServer(); - sfp = new StaticFlowEntryPusher(); - storage = new MemoryStorageSource(); //dependency for sfp - mockSyncService = new MockSyncService(); - - fmc.addService(IRestApiService.class, restApi); - fmc.addService(IFloodlightProviderService.class, getMockFloodlightProvider()); - fmc.addService(IEntityClassifierService.class, entityClassifier); - fmc.addService(IFlowReconcileService.class, frm); - fmc.addService(IThreadPoolService.class, tps); - fmc.addService(IDeviceService.class, deviceManager); - fmc.addService(ITopologyService.class, topology); - fmc.addService(IRoutingService.class, routingEngine); - fmc.addService(ICounterStoreService.class, new CounterStore()); - fmc.addService(IStaticFlowEntryPusherService.class, sfp); - fmc.addService(ILoadBalancerService.class, lb); - fmc.addService(IStorageSourceService.class, storage); - fmc.addService(ISyncService.class, mockSyncService); - - lb.init(fmc); - getMockFloodlightProvider().init(fmc); - entityClassifier.init(fmc); - frm.init(fmc); - tps.init(fmc); - mockSyncService.init(fmc); - deviceManager.init(fmc); - restApi.init(fmc); - sfp.init(fmc); - storage.init(fmc); - - topology.addListener(deviceManager); - expectLastCall().times(1); - replay(topology); - - lb.startUp(fmc); - getMockFloodlightProvider().startUp(fmc); - entityClassifier.startUp(fmc); - frm.startUp(fmc); - tps.startUp(fmc); - mockSyncService.startUp(fmc); - deviceManager.startUp(fmc); - restApi.startUp(fmc); - sfp.startUp(fmc); - storage.startUp(fmc); - - verify(topology); - - vipsResource = new VipsResource(); - poolsResource = new PoolsResource(); - membersResource = new MembersResource(); - - vip1=null; - vip2=null; - - pool1=null; - pool2=null; - pool3=null; - - member1=null; - member2=null; - member3=null; - member4=null; - } - - @Test - public void testCreateVip() { - String postData1, postData2; - IOException error = null; - - postData1 = "{\"id\":\"1\",\"name\":\"vip1\",\"protocol\":\"icmp\",\"address\":\"10.0.0.100\",\"port\":\"8\"}"; - postData2 = "{\"id\":\"2\",\"name\":\"vip2\",\"protocol\":\"tcp\",\"address\":\"10.0.0.200\",\"port\":\"100\"}"; - - try { - vip1 = vipsResource.jsonToVip(postData1); - } catch (IOException e) { - error = e; - } - try { - vip2 = vipsResource.jsonToVip(postData2); - } catch (IOException e) { - error = e; - } - - // verify correct parsing - assertFalse(vip1==null); - assertFalse(vip2==null); - assertTrue(error==null); - - lb.createVip(vip1); - lb.createVip(vip2); - - // verify correct creation - assertTrue(lb.vips.containsKey(vip1.id)); - assertTrue(lb.vips.containsKey(vip2.id)); - } - - @Test - public void testRemoveVip() { - - testCreateVip(); - - // verify correct initial condition - assertFalse(vip1==null); - assertFalse(vip2==null); - - lb.removeVip(vip1.id); - lb.removeVip(vip2.id); - - // verify correct removal - assertFalse(lb.vips.containsKey(vip1.id)); - assertFalse(lb.vips.containsKey(vip2.id)); - - } - - @Test - public void testCreatePool() { - String postData1, postData2, postData3; - IOException error = null; - - testCreateVip(); - - postData1 = "{\"id\":\"1\",\"name\":\"pool1\",\"protocol\":\"icmp\",\"vip_id\":\"1\"}"; - postData2 = "{\"id\":\"2\",\"name\":\"pool2\",\"protocol\":\"tcp\",\"vip_id\":\"2\"}"; - postData3 = "{\"id\":\"3\",\"name\":\"pool3\",\"protocol\":\"udp\",\"vip_id\":\"3\"}"; - - try { - pool1 = poolsResource.jsonToPool(postData1); - } catch (IOException e) { - error = e; - } - try { - pool2 = poolsResource.jsonToPool(postData2); - } catch (IOException e) { - error = e; - } - try { - pool3 = poolsResource.jsonToPool(postData3); - } catch (IOException e) { - error = e; - } - - // verify correct parsing - assertFalse(pool1==null); - assertFalse(pool2==null); - assertFalse(pool3==null); - assertTrue(error==null); - - lb.createPool(pool1); - lb.createPool(pool2); - lb.createPool(pool3); - - // verify successful creates; two registered with vips and one not - assertTrue(lb.pools.containsKey(pool1.id)); - assertTrue(lb.vips.get(pool1.vipId).pools.contains(pool1.id)); - assertTrue(lb.pools.containsKey(pool2.id)); - assertTrue(lb.vips.get(pool2.vipId).pools.contains(pool2.id)); - assertTrue(lb.pools.containsKey(pool3.id)); - assertFalse(lb.vips.containsKey(pool3.vipId)); - - } - - @Test - public void testRemovePool() { - testCreateVip(); - testCreatePool(); - - // verify correct initial condition - assertFalse(vip1==null); - assertFalse(vip2==null); - assertFalse(pool1==null); - assertFalse(pool2==null); - assertFalse(pool3==null); - - lb.removePool(pool1.id); - lb.removePool(pool2.id); - lb.removePool(pool3.id); - - // verify correct removal - assertFalse(lb.pools.containsKey(pool1.id)); - assertFalse(lb.pools.containsKey(pool2.id)); - assertFalse(lb.pools.containsKey(pool3.id)); - - //verify pool cleanup from vip - assertFalse(lb.vips.get(pool1.vipId).pools.contains(pool1.id)); - assertFalse(lb.vips.get(pool2.vipId).pools.contains(pool2.id)); - } - - @Test - public void testCreateMember() { - String postData1, postData2, postData3, postData4; - IOException error = null; - - testCreateVip(); - testCreatePool(); - - postData1 = "{\"id\":\"1\",\"address\":\"10.0.0.3\",\"port\":\"8\",\"pool_id\":\"1\"}"; - postData2 = "{\"id\":\"2\",\"address\":\"10.0.0.4\",\"port\":\"8\",\"pool_id\":\"1\"}"; - postData3 = "{\"id\":\"3\",\"address\":\"10.0.0.5\",\"port\":\"100\",\"pool_id\":\"2\"}"; - postData4 = "{\"id\":\"4\",\"address\":\"10.0.0.6\",\"port\":\"100\",\"pool_id\":\"2\"}"; - - try { - member1 = membersResource.jsonToMember(postData1); - } catch (IOException e) { - error = e; - } - try { - member2 = membersResource.jsonToMember(postData2); - } catch (IOException e) { - error = e; - } - try { - member3 = membersResource.jsonToMember(postData3); - } catch (IOException e) { - error = e; - } - try { - member4 = membersResource.jsonToMember(postData4); - } catch (IOException e) { - error = e; - } - - // verify correct parsing - assertFalse(member1==null); - assertFalse(member2==null); - assertFalse(member3==null); - assertFalse(member4==null); - assertTrue(error==null); - - lb.createMember(member1); - lb.createMember(member2); - lb.createMember(member3); - lb.createMember(member4); - - // add the same server a second time - lb.createMember(member1); - - // verify successful creates - assertTrue(lb.members.containsKey(member1.id)); - assertTrue(lb.members.containsKey(member2.id)); - assertTrue(lb.members.containsKey(member3.id)); - assertTrue(lb.members.containsKey(member4.id)); - - assertTrue(lb.pools.get(member1.poolId).members.size()==2); - assertTrue(lb.pools.get(member3.poolId).members.size()==2); - - // member1 should inherit valid vipId from pool - assertTrue(lb.vips.get(member1.vipId)!=null); - } - - @Test - public void testRemoveMember() { - testCreateVip(); - testCreatePool(); - testCreateMember(); - - // verify correct initial condition - assertFalse(vip1==null); - assertFalse(vip2==null); - assertFalse(pool1==null); - assertFalse(pool2==null); - assertFalse(pool3==null); - assertFalse(member1==null); - assertFalse(member2==null); - assertFalse(member3==null); - assertFalse(member4==null); - - lb.removeMember(member1.id); - lb.removeMember(member2.id); - lb.removeMember(member3.id); - lb.removeMember(member4.id); - - // verify correct removal - assertFalse(lb.members.containsKey(member1.id)); - assertFalse(lb.members.containsKey(member2.id)); - assertFalse(lb.members.containsKey(member3.id)); - assertFalse(lb.members.containsKey(member4.id)); - - //verify member cleanup from pool - assertFalse(lb.pools.get(member1.poolId).members.contains(member1.id)); - assertFalse(lb.pools.get(member2.poolId).members.contains(member2.id)); - assertFalse(lb.pools.get(member3.poolId).members.contains(member3.id)); - assertFalse(lb.pools.get(member4.poolId).members.contains(member4.id)); - - } - - @Test - public void testTwoSubsequentIcmpRequests() throws Exception { - testCreateVip(); - testCreatePool(); - testCreateMember(); - - IOFSwitch sw1; - - IPacket arpRequest1, arpReply1, icmpPacket1, icmpPacket2; - - byte[] arpRequest1Serialized; - byte[] arpReply1Serialized; - byte[] icmpPacket1Serialized, icmpPacket2Serialized; - - OFPacketIn arpRequestPacketIn1; - OFPacketIn icmpPacketIn1, icmpPacketIn2; - - OFPacketOut arpReplyPacketOut1; - - Capture<OFMessage> wc1 = new Capture<OFMessage>(CaptureType.ALL); - Capture<FloodlightContext> bc1 = - new Capture<FloodlightContext>(CaptureType.ALL); - - int fastWildcards = - OFMatch.OFPFW_IN_PORT | - OFMatch.OFPFW_NW_PROTO | - OFMatch.OFPFW_TP_SRC | - OFMatch.OFPFW_TP_DST | - OFMatch.OFPFW_NW_SRC_ALL | - OFMatch.OFPFW_NW_DST_ALL | - OFMatch.OFPFW_NW_TOS; - - sw1 = EasyMock.createNiceMock(IOFSwitch.class); - expect(sw1.getId()).andReturn(1L).anyTimes(); - expect(sw1.getStringId()).andReturn("00:00:00:00:00:01").anyTimes(); - expect(sw1.getAttribute(IOFSwitch.PROP_FASTWILDCARDS)).andReturn(fastWildcards).anyTimes(); - expect(sw1.hasAttribute(IOFSwitch.PROP_SUPPORTS_OFPP_TABLE)).andReturn(true).anyTimes(); - sw1.writeThrottled(capture(wc1), capture(bc1)); - expectLastCall().anyTimes(); - sw1.flush(); - expectLastCall().anyTimes(); - - replay(sw1); - sfp.switchAdded(1L); - verify(sw1); - - /* Test plan: - * - two clients and two servers on sw1 port 1, 2, 3, 4 - * - mock arp request received towards vip1 from (1L, 1) - * - proxy arp got pushed out to (1L, 1)- check sw1 getting the packetout - * - mock icmp request received towards vip1 from (1L, 1) - * - device manager list of devices queried to identify source and dest devices - * - routing engine queried to get inbound and outbound routes - * - check getRoute calls and responses - * - sfp called to install flows - * - check sfp calls - */ - - // Build topology - reset(topology); - expect(topology.isIncomingBroadcastAllowed(anyLong(), anyShort())).andReturn(true).anyTimes(); - expect(topology.getL2DomainId(1L)).andReturn(1L).anyTimes(); - expect(topology.isAttachmentPointPort(1L, (short)1)).andReturn(true).anyTimes(); - expect(topology.isAttachmentPointPort(1L, (short)2)).andReturn(true).anyTimes(); - expect(topology.isAttachmentPointPort(1L, (short)3)).andReturn(true).anyTimes(); - expect(topology.isAttachmentPointPort(1L, (short)4)).andReturn(true).anyTimes(); - replay(topology); - - - - // Build arp packets - arpRequest1 = new Ethernet() - .setSourceMACAddress("00:00:00:00:00:01") - .setDestinationMACAddress("ff:ff:ff:ff:ff:ff") - .setEtherType(Ethernet.TYPE_ARP) - .setVlanID((short) 0) - .setPriorityCode((byte) 0) - .setPayload( - new ARP() - .setHardwareType(ARP.HW_TYPE_ETHERNET) - .setProtocolType(ARP.PROTO_TYPE_IP) - .setHardwareAddressLength((byte) 6) - .setProtocolAddressLength((byte) 4) - .setOpCode(ARP.OP_REQUEST) - .setSenderHardwareAddress(HexString.fromHexString("00:00:00:00:00:01")) - .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("10.0.0.1")) - .setTargetHardwareAddress(HexString.fromHexString("00:00:00:00:00:00")) - .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("10.0.0.100"))); - - arpRequest1Serialized = arpRequest1.serialize(); - - arpRequestPacketIn1 = - ((OFPacketIn) getMockFloodlightProvider().getOFMessageFactory(). - getMessage(OFType.PACKET_IN)) - .setBufferId(-1) - .setInPort((short) 1) - .setPacketData(arpRequest1Serialized) - .setReason(OFPacketInReason.NO_MATCH) - .setTotalLength((short) arpRequest1Serialized.length); - - IFloodlightProviderService.bcStore.put(cntx, - IFloodlightProviderService.CONTEXT_PI_PAYLOAD, - (Ethernet) arpRequest1); - - // Mock proxy arp packet-out - arpReply1 = new Ethernet() - .setSourceMACAddress(LBVip.LB_PROXY_MAC) - .setDestinationMACAddress(HexString.fromHexString("00:00:00:00:00:01")) - .setEtherType(Ethernet.TYPE_ARP) - .setVlanID((short) 0) - .setPriorityCode((byte) 0) - .setPayload( - new ARP() - .setHardwareType(ARP.HW_TYPE_ETHERNET) - .setProtocolType(ARP.PROTO_TYPE_IP) - .setHardwareAddressLength((byte) 6) - .setProtocolAddressLength((byte) 4) - .setOpCode(ARP.OP_REPLY) - .setSenderHardwareAddress(HexString.fromHexString(LBVip.LB_PROXY_MAC)) - .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("10.0.0.100")) - .setTargetHardwareAddress(HexString.fromHexString("00:00:00:00:00:01")) - .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("10.0.0.1"))); - - arpReply1Serialized = arpReply1.serialize(); - - arpReplyPacketOut1 = - (OFPacketOut) getMockFloodlightProvider().getOFMessageFactory(). - getMessage(OFType.PACKET_OUT); - arpReplyPacketOut1.setBufferId(OFPacketOut.BUFFER_ID_NONE) - .setInPort(OFPort.OFPP_NONE.getValue()); - List<OFAction> poactions = new ArrayList<OFAction>(); - poactions.add(new OFActionOutput(arpRequestPacketIn1.getInPort(), (short) 0xffff)); - arpReplyPacketOut1.setActions(poactions) - .setActionsLength((short) OFActionOutput.MINIMUM_LENGTH) - .setPacketData(arpReply1Serialized) - .setLengthU(OFPacketOut.MINIMUM_LENGTH+ - arpReplyPacketOut1.getActionsLength()+ - arpReply1Serialized.length); - - lb.receive(sw1, arpRequestPacketIn1, cntx); - verify(sw1, topology); - - assertTrue(wc1.hasCaptured()); // wc1 should get packetout - - List<OFMessage> msglist1 = wc1.getValues(); - - for (OFMessage m: msglist1) { - if (m instanceof OFPacketOut) - assertEquals(arpReplyPacketOut1, m); - else - assertTrue(false); // unexpected message - } - - // - // Skip arpRequest2 test - in reality this will happen, but for unit test the same logic - // is already validated with arpRequest1 test above - // - - // Build icmp packets - icmpPacket1 = new Ethernet() - .setSourceMACAddress("00:00:00:00:00:01") - .setDestinationMACAddress(LBVip.LB_PROXY_MAC) - .setEtherType(Ethernet.TYPE_IPv4) - .setVlanID((short) 0) - .setPriorityCode((byte) 0) - .setPayload( - new IPv4() - .setSourceAddress("10.0.0.1") - .setDestinationAddress("10.0.0.100") - .setProtocol(IPv4.PROTOCOL_ICMP) - .setPayload(new ICMP() - .setIcmpCode((byte) 0) - .setIcmpType((byte) 0))); - - icmpPacket1Serialized = icmpPacket1.serialize(); - - icmpPacketIn1 = - ((OFPacketIn) getMockFloodlightProvider().getOFMessageFactory(). - getMessage(OFType.PACKET_IN)) - .setBufferId(-1) - .setInPort((short) 1) - .setPacketData(icmpPacket1Serialized) - .setReason(OFPacketInReason.NO_MATCH) - .setTotalLength((short) icmpPacket1Serialized.length); - - icmpPacket2 = new Ethernet() - .setSourceMACAddress("00:00:00:00:00:02") - .setDestinationMACAddress(LBVip.LB_PROXY_MAC) - .setEtherType(Ethernet.TYPE_IPv4) - .setVlanID((short) 0) - .setPriorityCode((byte) 0) - .setPayload( - new IPv4() - .setSourceAddress("10.0.0.2") - .setDestinationAddress("10.0.0.100") - .setProtocol(IPv4.PROTOCOL_ICMP) - .setPayload(new ICMP() - .setIcmpCode((byte) 0) - .setIcmpType((byte) 0))); - - icmpPacket2Serialized = icmpPacket2.serialize(); - - icmpPacketIn2 = - ((OFPacketIn) getMockFloodlightProvider().getOFMessageFactory(). - getMessage(OFType.PACKET_IN)) - .setBufferId(-1) - .setInPort((short) 2) - .setPacketData(icmpPacket2Serialized) - .setReason(OFPacketInReason.NO_MATCH) - .setTotalLength((short) icmpPacket2Serialized.length); - - byte[] dataLayerSource1 = ((Ethernet)icmpPacket1).getSourceMACAddress(); - int networkSource1 = ((IPv4)((Ethernet)icmpPacket1).getPayload()).getSourceAddress(); - byte[] dataLayerDest1 = HexString.fromHexString("00:00:00:00:00:03"); - int networkDest1 = IPv4.toIPv4Address("10.0.0.3"); - byte[] dataLayerSource2 = ((Ethernet)icmpPacket2).getSourceMACAddress(); - int networkSource2 = ((IPv4)((Ethernet)icmpPacket2).getPayload()).getSourceAddress(); - byte[] dataLayerDest2 = HexString.fromHexString("00:00:00:00:00:04"); - int networkDest2 = IPv4.toIPv4Address("10.0.0.4"); - - deviceManager.learnEntity(Ethernet.toLong(dataLayerSource1), - null, networkSource1, - 1L, 1); - deviceManager.learnEntity(Ethernet.toLong(dataLayerSource2), - null, networkSource2, - 1L, 2); - deviceManager.learnEntity(Ethernet.toLong(dataLayerDest1), - null, networkDest1, - 1L, 3); - deviceManager.learnEntity(Ethernet.toLong(dataLayerDest2), - null, networkDest2, - 1L, 4); - - // in bound #1 - Route route1 = new Route(1L, 1L); - List<NodePortTuple> nptList1 = new ArrayList<NodePortTuple>(); - nptList1.add(new NodePortTuple(1L, (short)1)); - nptList1.add(new NodePortTuple(1L, (short)3)); - route1.setPath(nptList1); - expect(routingEngine.getRoute(1L, (short)1, 1L, (short)3, 0)).andReturn(route1).atLeastOnce(); - - // outbound #1 - Route route2 = new Route(1L, 1L); - List<NodePortTuple> nptList2 = new ArrayList<NodePortTuple>(); - nptList2.add(new NodePortTuple(1L, (short)3)); - nptList2.add(new NodePortTuple(1L, (short)1)); - route2.setPath(nptList2); - expect(routingEngine.getRoute(1L, (short)3, 1L, (short)1, 0)).andReturn(route2).atLeastOnce(); - - // inbound #2 - Route route3 = new Route(1L, 1L); - List<NodePortTuple> nptList3 = new ArrayList<NodePortTuple>(); - nptList3.add(new NodePortTuple(1L, (short)2)); - nptList3.add(new NodePortTuple(1L, (short)4)); - route3.setPath(nptList3); - expect(routingEngine.getRoute(1L, (short)2, 1L, (short)4, 0)).andReturn(route3).atLeastOnce(); - - // outbound #2 - Route route4 = new Route(1L, 1L); - List<NodePortTuple> nptList4 = new ArrayList<NodePortTuple>(); - nptList4.add(new NodePortTuple(1L, (short)4)); - nptList4.add(new NodePortTuple(1L, (short)2)); - route4.setPath(nptList3); - expect(routingEngine.getRoute(1L, (short)4, 1L, (short)2, 0)).andReturn(route4).atLeastOnce(); - - replay(routingEngine); - - wc1.reset(); - - IFloodlightProviderService.bcStore.put(cntx, - IFloodlightProviderService.CONTEXT_PI_PAYLOAD, - (Ethernet) icmpPacket1); - lb.receive(sw1, icmpPacketIn1, cntx); - - IFloodlightProviderService.bcStore.put(cntx, - IFloodlightProviderService.CONTEXT_PI_PAYLOAD, - (Ethernet) icmpPacket2); - lb.receive(sw1, icmpPacketIn2, cntx); - - assertTrue(wc1.hasCaptured()); // wc1 should get packetout - - List<OFMessage> msglist2 = wc1.getValues(); - - assertTrue(msglist2.size()==2); // has inbound and outbound packetouts - // TODO: not seeing flowmods yet ... - - Map<String, OFFlowMod> map = sfp.getFlows("00:00:00:00:00:00:00:01"); - - assertTrue(map.size()==4); - } + protected LoadBalancer lb; + + protected FloodlightContext cntx; + protected FloodlightModuleContext fmc; + protected MockDeviceManager deviceManager; + protected MockThreadPoolService tps; + protected FlowReconcileManager frm; + protected DefaultEntityClassifier entityClassifier; + protected IRoutingService routingEngine; + protected ITopologyService topology; + protected StaticFlowEntryPusher sfp; + protected MemoryStorageSource storage; + protected RestApiServer restApi; + protected VipsResource vipsResource; + protected PoolsResource poolsResource; + protected MembersResource membersResource; + private MockSyncService mockSyncService; + + protected LBVip vip1, vip2; + protected LBPool pool1, pool2, pool3; + protected LBMember member1, member2, member3, member4; + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + + lb = new LoadBalancer(); + + cntx = new FloodlightContext(); + fmc = new FloodlightModuleContext(); + entityClassifier = new DefaultEntityClassifier(); // dependency for device manager + frm = new FlowReconcileManager(); //dependency for device manager + tps = new MockThreadPoolService(); //dependency for device manager + deviceManager = new MockDeviceManager(); + topology = createMock(ITopologyService.class); + routingEngine = createMock(IRoutingService.class); + restApi = new RestApiServer(); + sfp = new StaticFlowEntryPusher(); + storage = new MemoryStorageSource(); //dependency for sfp + mockSyncService = new MockSyncService(); + + fmc.addService(IRestApiService.class, restApi); + fmc.addService(IFloodlightProviderService.class, getMockFloodlightProvider()); + fmc.addService(IEntityClassifierService.class, entityClassifier); + fmc.addService(IFlowReconcileService.class, frm); + fmc.addService(IThreadPoolService.class, tps); + fmc.addService(IDeviceService.class, deviceManager); + fmc.addService(ITopologyService.class, topology); + fmc.addService(IRoutingService.class, routingEngine); + fmc.addService(IStaticFlowEntryPusherService.class, sfp); + fmc.addService(ILoadBalancerService.class, lb); + fmc.addService(IStorageSourceService.class, storage); + fmc.addService(ISyncService.class, mockSyncService); + + lb.init(fmc); + getMockFloodlightProvider().init(fmc); + entityClassifier.init(fmc); + frm.init(fmc); + tps.init(fmc); + mockSyncService.init(fmc); + deviceManager.init(fmc); + restApi.init(fmc); + sfp.init(fmc); + storage.init(fmc); + + topology.addListener(deviceManager); + expectLastCall().times(1); + replay(topology); + + lb.startUp(fmc); + getMockFloodlightProvider().startUp(fmc); + entityClassifier.startUp(fmc); + frm.startUp(fmc); + tps.startUp(fmc); + mockSyncService.startUp(fmc); + deviceManager.startUp(fmc); + restApi.startUp(fmc); + sfp.startUp(fmc); + storage.startUp(fmc); + + verify(topology); + + vipsResource = new VipsResource(); + poolsResource = new PoolsResource(); + membersResource = new MembersResource(); + + vip1=null; + vip2=null; + + pool1=null; + pool2=null; + pool3=null; + + member1=null; + member2=null; + member3=null; + member4=null; + } + + @Test + public void testCreateVip() { + String postData1, postData2; + IOException error = null; + + postData1 = "{\"id\":\"1\",\"name\":\"vip1\",\"protocol\":\"icmp\",\"address\":\"10.0.0.100\",\"port\":\"8\"}"; + postData2 = "{\"id\":\"2\",\"name\":\"vip2\",\"protocol\":\"tcp\",\"address\":\"10.0.0.200\",\"port\":\"100\"}"; + + try { + vip1 = vipsResource.jsonToVip(postData1); + } catch (IOException e) { + error = e; + } + try { + vip2 = vipsResource.jsonToVip(postData2); + } catch (IOException e) { + error = e; + } + + // verify correct parsing + assertFalse(vip1==null); + assertFalse(vip2==null); + assertTrue(error==null); + + lb.createVip(vip1); + lb.createVip(vip2); + + // verify correct creation + assertTrue(lb.vips.containsKey(vip1.id)); + assertTrue(lb.vips.containsKey(vip2.id)); + } + + @Test + public void testRemoveVip() { + + testCreateVip(); + + // verify correct initial condition + assertFalse(vip1==null); + assertFalse(vip2==null); + + lb.removeVip(vip1.id); + lb.removeVip(vip2.id); + + // verify correct removal + assertFalse(lb.vips.containsKey(vip1.id)); + assertFalse(lb.vips.containsKey(vip2.id)); + + } + + @Test + public void testCreatePool() { + String postData1, postData2, postData3; + IOException error = null; + + testCreateVip(); + + postData1 = "{\"id\":\"1\",\"name\":\"pool1\",\"protocol\":\"icmp\",\"vip_id\":\"1\"}"; + postData2 = "{\"id\":\"2\",\"name\":\"pool2\",\"protocol\":\"tcp\",\"vip_id\":\"2\"}"; + postData3 = "{\"id\":\"3\",\"name\":\"pool3\",\"protocol\":\"udp\",\"vip_id\":\"3\"}"; + + try { + pool1 = poolsResource.jsonToPool(postData1); + } catch (IOException e) { + error = e; + } + try { + pool2 = poolsResource.jsonToPool(postData2); + } catch (IOException e) { + error = e; + } + try { + pool3 = poolsResource.jsonToPool(postData3); + } catch (IOException e) { + error = e; + } + + // verify correct parsing + assertFalse(pool1==null); + assertFalse(pool2==null); + assertFalse(pool3==null); + assertTrue(error==null); + + lb.createPool(pool1); + lb.createPool(pool2); + lb.createPool(pool3); + + // verify successful creates; two registered with vips and one not + assertTrue(lb.pools.containsKey(pool1.id)); + assertTrue(lb.vips.get(pool1.vipId).pools.contains(pool1.id)); + assertTrue(lb.pools.containsKey(pool2.id)); + assertTrue(lb.vips.get(pool2.vipId).pools.contains(pool2.id)); + assertTrue(lb.pools.containsKey(pool3.id)); + assertFalse(lb.vips.containsKey(pool3.vipId)); + + } + + @Test + public void testRemovePool() { + testCreateVip(); + testCreatePool(); + + // verify correct initial condition + assertFalse(vip1==null); + assertFalse(vip2==null); + assertFalse(pool1==null); + assertFalse(pool2==null); + assertFalse(pool3==null); + + lb.removePool(pool1.id); + lb.removePool(pool2.id); + lb.removePool(pool3.id); + + // verify correct removal + assertFalse(lb.pools.containsKey(pool1.id)); + assertFalse(lb.pools.containsKey(pool2.id)); + assertFalse(lb.pools.containsKey(pool3.id)); + + //verify pool cleanup from vip + assertFalse(lb.vips.get(pool1.vipId).pools.contains(pool1.id)); + assertFalse(lb.vips.get(pool2.vipId).pools.contains(pool2.id)); + } + + @Test + public void testCreateMember() { + String postData1, postData2, postData3, postData4; + IOException error = null; + + testCreateVip(); + testCreatePool(); + + postData1 = "{\"id\":\"1\",\"address\":\"10.0.0.3\",\"port\":\"8\",\"pool_id\":\"1\"}"; + postData2 = "{\"id\":\"2\",\"address\":\"10.0.0.4\",\"port\":\"8\",\"pool_id\":\"1\"}"; + postData3 = "{\"id\":\"3\",\"address\":\"10.0.0.5\",\"port\":\"100\",\"pool_id\":\"2\"}"; + postData4 = "{\"id\":\"4\",\"address\":\"10.0.0.6\",\"port\":\"100\",\"pool_id\":\"2\"}"; + + try { + member1 = membersResource.jsonToMember(postData1); + } catch (IOException e) { + error = e; + } + try { + member2 = membersResource.jsonToMember(postData2); + } catch (IOException e) { + error = e; + } + try { + member3 = membersResource.jsonToMember(postData3); + } catch (IOException e) { + error = e; + } + try { + member4 = membersResource.jsonToMember(postData4); + } catch (IOException e) { + error = e; + } + + // verify correct parsing + assertFalse(member1==null); + assertFalse(member2==null); + assertFalse(member3==null); + assertFalse(member4==null); + assertTrue(error==null); + + lb.createMember(member1); + lb.createMember(member2); + lb.createMember(member3); + lb.createMember(member4); + + // add the same server a second time + lb.createMember(member1); + + // verify successful creates + assertTrue(lb.members.containsKey(member1.id)); + assertTrue(lb.members.containsKey(member2.id)); + assertTrue(lb.members.containsKey(member3.id)); + assertTrue(lb.members.containsKey(member4.id)); + + assertTrue(lb.pools.get(member1.poolId).members.size()==2); + assertTrue(lb.pools.get(member3.poolId).members.size()==2); + + // member1 should inherit valid vipId from pool + assertTrue(lb.vips.get(member1.vipId)!=null); + } + + @Test + public void testRemoveMember() { + testCreateVip(); + testCreatePool(); + testCreateMember(); + + // verify correct initial condition + assertFalse(vip1==null); + assertFalse(vip2==null); + assertFalse(pool1==null); + assertFalse(pool2==null); + assertFalse(pool3==null); + assertFalse(member1==null); + assertFalse(member2==null); + assertFalse(member3==null); + assertFalse(member4==null); + + lb.removeMember(member1.id); + lb.removeMember(member2.id); + lb.removeMember(member3.id); + lb.removeMember(member4.id); + + // verify correct removal + assertFalse(lb.members.containsKey(member1.id)); + assertFalse(lb.members.containsKey(member2.id)); + assertFalse(lb.members.containsKey(member3.id)); + assertFalse(lb.members.containsKey(member4.id)); + + //verify member cleanup from pool + assertFalse(lb.pools.get(member1.poolId).members.contains(member1.id)); + assertFalse(lb.pools.get(member2.poolId).members.contains(member2.id)); + assertFalse(lb.pools.get(member3.poolId).members.contains(member3.id)); + assertFalse(lb.pools.get(member4.poolId).members.contains(member4.id)); + + } + + @Test + public void testTwoSubsequentIcmpRequests() throws Exception { + testCreateVip(); + testCreatePool(); + testCreateMember(); + + IOFSwitch sw1; + + IPacket arpRequest1, arpReply1, icmpPacket1, icmpPacket2; + + byte[] arpRequest1Serialized; + byte[] arpReply1Serialized; + byte[] icmpPacket1Serialized, icmpPacket2Serialized; + + OFPacketIn arpRequestPacketIn1; + OFPacketIn icmpPacketIn1, icmpPacketIn2; + + OFPacketOut arpReplyPacketOut1; + + Capture<OFMessage> wc1 = new Capture<OFMessage>(CaptureType.ALL); + + sw1 = EasyMock.createNiceMock(IOFSwitch.class); + expect(sw1.getId()).andReturn(DatapathId.of(1L)).anyTimes(); + expect(sw1.getId().toString()).andReturn("00:00:00:00:00:01").anyTimes(); + expect(sw1.hasAttribute(IOFSwitch.PROP_SUPPORTS_OFPP_TABLE)).andReturn(true).anyTimes(); + sw1.write(capture(wc1)); + expectLastCall().anyTimes(); + sw1.flush(); + expectLastCall().anyTimes(); + + replay(sw1); + sfp.switchAdded(DatapathId.of(1L)); + verify(sw1); + + /* Test plan: + * - two clients and two servers on sw1 port 1, 2, 3, 4 + * - mock arp request received towards vip1 from (1L, 1) + * - proxy arp got pushed out to (1L, 1)- check sw1 getting the packetout + * - mock icmp request received towards vip1 from (1L, 1) + * - device manager list of devices queried to identify source and dest devices + * - routing engine queried to get inbound and outbound routes + * - check getRoute calls and responses + * - sfp called to install flows + * - check sfp calls + */ + + // Build topology + reset(topology); + expect(topology.isIncomingBroadcastAllowed(DatapathId.of(anyLong()), OFPort.of(anyShort()))).andReturn(true).anyTimes(); + expect(topology.getL2DomainId(DatapathId.of(1L))).andReturn(DatapathId.of(1L)).anyTimes(); + expect(topology.isAttachmentPointPort(DatapathId.of(1L), OFPort.of(1))).andReturn(true).anyTimes(); + expect(topology.isAttachmentPointPort(DatapathId.of(1L), OFPort.of(2))).andReturn(true).anyTimes(); + expect(topology.isAttachmentPointPort(DatapathId.of(1L), OFPort.of(3))).andReturn(true).anyTimes(); + expect(topology.isAttachmentPointPort(DatapathId.of(1L), OFPort.of(4))).andReturn(true).anyTimes(); + replay(topology); + + + + // Build arp packets + arpRequest1 = new Ethernet() + .setSourceMACAddress("00:00:00:00:00:01") + .setDestinationMACAddress("ff:ff:ff:ff:ff:ff") + .setEtherType(Ethernet.TYPE_ARP) + .setVlanID((short) 0) + .setPriorityCode((byte) 0) + .setPayload( + new ARP() + .setHardwareType(ARP.HW_TYPE_ETHERNET) + .setProtocolType(ARP.PROTO_TYPE_IP) + .setHardwareAddressLength((byte) 6) + .setProtocolAddressLength((byte) 4) + .setOpCode(ARP.OP_REQUEST) + .setSenderHardwareAddress(HexString.fromHexString("00:00:00:00:00:01")) + .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("10.0.0.1")) + .setTargetHardwareAddress(HexString.fromHexString("00:00:00:00:00:00")) + .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("10.0.0.100"))); + + arpRequest1Serialized = arpRequest1.serialize(); + + arpRequestPacketIn1 = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn() + .setBufferId(OFBufferId.NO_BUFFER) + .setInPort(OFPort.of(1)) + .setData(arpRequest1Serialized) + .setReason(OFPacketInReason.NO_MATCH) + .build(); + + IFloodlightProviderService.bcStore.put(cntx, + IFloodlightProviderService.CONTEXT_PI_PAYLOAD, + (Ethernet) arpRequest1); + + // Mock proxy arp packet-out + arpReply1 = new Ethernet() + .setSourceMACAddress(LBVip.LB_PROXY_MAC) + .setDestinationMACAddress(HexString.fromHexString("00:00:00:00:00:01")) + .setEtherType(Ethernet.TYPE_ARP) + .setVlanID((short) 0) + .setPriorityCode((byte) 0) + .setPayload( + new ARP() + .setHardwareType(ARP.HW_TYPE_ETHERNET) + .setProtocolType(ARP.PROTO_TYPE_IP) + .setHardwareAddressLength((byte) 6) + .setProtocolAddressLength((byte) 4) + .setOpCode(ARP.OP_REPLY) + .setSenderHardwareAddress(HexString.fromHexString(LBVip.LB_PROXY_MAC)) + .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("10.0.0.100")) + .setTargetHardwareAddress(HexString.fromHexString("00:00:00:00:00:01")) + .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("10.0.0.1"))); + + arpReply1Serialized = arpReply1.serialize(); + + List<OFAction> poactions = new ArrayList<OFAction>(); + poactions.add(OFFactories.getFactory(OFVersion.OF_13).actions().output(arpRequestPacketIn1.getInPort(), (short) 0xffff)); + arpReplyPacketOut1 = OFFactories.getFactory(OFVersion.OF_13).buildPacketOut() + .setBufferId(OFBufferId.NO_BUFFER) + .setInPort(OFPort.ANY) + .setActions(poactions) + .setData(arpReply1Serialized) + .build(); + + lb.receive(sw1, arpRequestPacketIn1, cntx); + verify(sw1, topology); + + assertTrue(wc1.hasCaptured()); // wc1 should get packetout + + List<OFMessage> msglist1 = wc1.getValues(); + + for (OFMessage m: msglist1) { + if (m instanceof OFPacketOut) + assertEquals(arpReplyPacketOut1, m); + else + assertTrue(false); // unexpected message + } + + // + // Skip arpRequest2 test - in reality this will happen, but for unit test the same logic + // is already validated with arpRequest1 test above + // + + // Build icmp packets + icmpPacket1 = new Ethernet() + .setSourceMACAddress("00:00:00:00:00:01") + .setDestinationMACAddress(LBVip.LB_PROXY_MAC) + .setEtherType(Ethernet.TYPE_IPv4) + .setVlanID((short) 0) + .setPriorityCode((byte) 0) + .setPayload( + new IPv4() + .setSourceAddress("10.0.0.1") + .setDestinationAddress("10.0.0.100") + .setProtocol(IpProtocol.ICMP) + .setPayload(new ICMP() + .setIcmpCode((byte) 0) + .setIcmpType((byte) 0))); + + icmpPacket1Serialized = icmpPacket1.serialize(); + + icmpPacketIn1 = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn() + .setBufferId(OFBufferId.NO_BUFFER) + .setInPort(OFPort.of(1)) + .setData(icmpPacket1Serialized) + .setReason(OFPacketInReason.NO_MATCH) + .build(); + icmpPacket2 = new Ethernet() + .setSourceMACAddress("00:00:00:00:00:02") + .setDestinationMACAddress(LBVip.LB_PROXY_MAC) + .setEtherType(Ethernet.TYPE_IPv4) + .setVlanID((short) 0) + .setPriorityCode((byte) 0) + .setPayload( + new IPv4() + .setSourceAddress("10.0.0.2") + .setDestinationAddress("10.0.0.100") + .setProtocol(IpProtocol.ICMP) + .setPayload(new ICMP() + .setIcmpCode((byte) 0) + .setIcmpType((byte) 0))); + + icmpPacket2Serialized = icmpPacket2.serialize(); + + icmpPacketIn2 = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn() + .setBufferId(OFBufferId.NO_BUFFER) + .setInPort(OFPort.of(2)) + .setData(icmpPacket2Serialized) + .setReason(OFPacketInReason.NO_MATCH) + .build(); + MacAddress dataLayerSource1 = ((Ethernet)icmpPacket1).getSourceMACAddress(); + IPv4Address networkSource1 = ((IPv4)((Ethernet)icmpPacket1).getPayload()).getSourceAddress(); + MacAddress dataLayerDest1 = MacAddress.of("00:00:00:00:00:03"); + IPv4Address networkDest1 = IPv4Address.of("10.0.0.3"); + MacAddress dataLayerSource2 = ((Ethernet)icmpPacket2).getSourceMACAddress(); + IPv4Address networkSource2 = ((IPv4)((Ethernet)icmpPacket2).getPayload()).getSourceAddress(); + MacAddress dataLayerDest2 = MacAddress.of("00:00:00:00:00:04"); + IPv4Address networkDest2 = IPv4Address.of("10.0.0.4"); + + deviceManager.learnEntity(dataLayerSource1.getLong(), + null, networkSource1.getInt(), + 1L, 1); + deviceManager.learnEntity(dataLayerSource2.getLong(), + null, networkSource2.getInt(), + 1L, 2); + deviceManager.learnEntity(dataLayerDest1.getLong(), + null, networkDest1.getInt(), + 1L, 3); + deviceManager.learnEntity(dataLayerDest2.getLong(), + null, networkDest2.getInt(), + 1L, 4); + + // in bound #1 + Route route1 = new Route(DatapathId.of(1L), DatapathId.of(1L)); + List<NodePortTuple> nptList1 = new ArrayList<NodePortTuple>(); + nptList1.add(new NodePortTuple(DatapathId.of(1L), OFPort.of(1))); + nptList1.add(new NodePortTuple(DatapathId.of(1L), OFPort.of(3))); + route1.setPath(nptList1); + expect(routingEngine.getRoute(DatapathId.of(1L), OFPort.of(1), DatapathId.of(1L), OFPort.of(3), U64.of(0))).andReturn(route1).atLeastOnce(); + + // outbound #1 + Route route2 = new Route(DatapathId.of(1L), DatapathId.of(1L)); + List<NodePortTuple> nptList2 = new ArrayList<NodePortTuple>(); + nptList2.add(new NodePortTuple(DatapathId.of(1L), OFPort.of(3))); + nptList2.add(new NodePortTuple(DatapathId.of(1L), OFPort.of(1))); + route2.setPath(nptList2); + expect(routingEngine.getRoute(DatapathId.of(1L), OFPort.of(3), DatapathId.of(1L), OFPort.of(1), U64.of(0))).andReturn(route2).atLeastOnce(); + + // inbound #2 + Route route3 = new Route(DatapathId.of(1L), DatapathId.of(1L)); + List<NodePortTuple> nptList3 = new ArrayList<NodePortTuple>(); + nptList3.add(new NodePortTuple(DatapathId.of(1L), OFPort.of(2))); + nptList3.add(new NodePortTuple(DatapathId.of(1L), OFPort.of(4))); + route3.setPath(nptList3); + expect(routingEngine.getRoute(DatapathId.of(1L), OFPort.of(2), DatapathId.of(1L), OFPort.of(4), U64.of(0))).andReturn(route3).atLeastOnce(); + + // outbound #2 + Route route4 = new Route(DatapathId.of(1L), DatapathId.of(1L)); + List<NodePortTuple> nptList4 = new ArrayList<NodePortTuple>(); + nptList4.add(new NodePortTuple(DatapathId.of(1L), OFPort.of(4))); + nptList4.add(new NodePortTuple(DatapathId.of(1L), OFPort.of(2))); + route4.setPath(nptList3); + expect(routingEngine.getRoute(DatapathId.of(1L), OFPort.of(4), DatapathId.of(1L), OFPort.of(2), U64.of(0))).andReturn(route4).atLeastOnce(); + + replay(routingEngine); + + wc1.reset(); + + IFloodlightProviderService.bcStore.put(cntx, + IFloodlightProviderService.CONTEXT_PI_PAYLOAD, + (Ethernet) icmpPacket1); + lb.receive(sw1, icmpPacketIn1, cntx); + + IFloodlightProviderService.bcStore.put(cntx, + IFloodlightProviderService.CONTEXT_PI_PAYLOAD, + (Ethernet) icmpPacket2); + lb.receive(sw1, icmpPacketIn2, cntx); + + assertTrue(wc1.hasCaptured()); // wc1 should get packetout + + List<OFMessage> msglist2 = wc1.getValues(); + + assertTrue(msglist2.size()==2); // has inbound and outbound packetouts + // TODO: not seeing flowmods yet ... + + Map<String, OFFlowMod> map = sfp.getFlows(DatapathId.of(1L)); + + assertTrue(map.size()==4); + } } diff --git a/src/test/java/net/floodlightcontroller/packet/IPv4Test.java b/src/test/java/net/floodlightcontroller/packet/IPv4Test.java index 9aa9e3d1093e197d4536f2cc08a475da7ed70ad2..c69de687700b402f653fc4a67e4b7b613e22a25a 100644 --- a/src/test/java/net/floodlightcontroller/packet/IPv4Test.java +++ b/src/test/java/net/floodlightcontroller/packet/IPv4Test.java @@ -27,6 +27,7 @@ import java.util.Arrays; import org.junit.Assert; import org.junit.Test; +import org.projectfloodlight.openflow.types.IpProtocol; /** * @author David Erickson (daviderickson@cs.stanford.edu) @@ -62,7 +63,7 @@ public class IPv4Test { IPv4 packet = new IPv4() .setIdentification((short) 24142) .setTtl((byte) 63) - .setProtocol((byte) 0x06) + .setProtocol(IpProtocol.of((byte) 0x06)) .setSourceAddress("172.24.74.223") .setDestinationAddress("171.64.74.48"); byte[] actual = packet.serialize(); diff --git a/src/test/java/net/floodlightcontroller/packet/PacketTest.java b/src/test/java/net/floodlightcontroller/packet/PacketTest.java index c5a1bb2274b51e48a1ce5801e439d73a10b86232..609feb0f0efb6df5725d4ba19cccef49959310b4 100644 --- a/src/test/java/net/floodlightcontroller/packet/PacketTest.java +++ b/src/test/java/net/floodlightcontroller/packet/PacketTest.java @@ -116,8 +116,8 @@ public class PacketTest { Ethernet eth = (Ethernet)pkt; Ethernet newEth = (Ethernet)newPkt; newEth.setDestinationMACAddress(new byte[] { 1,2,3,4,5,6}); - assertEquals(false, newEth.getDestinationMAC() - .equals(eth.getDestinationMAC())); + assertEquals(false, newEth.getDestinationMACAddress() + .equals(eth.getDestinationMACAddress())); assertEquals(false, newPkt.equals(pkt)); } if (pkt instanceof ARP) { diff --git a/src/test/java/net/floodlightcontroller/routing/RouteTest.java b/src/test/java/net/floodlightcontroller/routing/RouteTest.java index 3bd0398980078d54d8275f721eb6ace1912045e2..40b32e3d4dd903481a37d62c1559556afe451495 100644 --- a/src/test/java/net/floodlightcontroller/routing/RouteTest.java +++ b/src/test/java/net/floodlightcontroller/routing/RouteTest.java @@ -17,7 +17,11 @@ package net.floodlightcontroller.routing; +import static org.junit.Assert.*; + import org.junit.Test; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFPort; import net.floodlightcontroller.routing.Route; import net.floodlightcontroller.test.FloodlightTestCase; @@ -30,22 +34,22 @@ import net.floodlightcontroller.topology.NodePortTuple; public class RouteTest extends FloodlightTestCase { @Test public void testCloneable() throws Exception { - Route r1 = new Route(1L, 2L); - Route r2 = new Route(1L, 3L); + Route r1 = new Route(DatapathId.of(1L), DatapathId.of(2L)); + Route r2 = new Route(DatapathId.of(1L), DatapathId.of(3L)); assertNotSame(r1, r2); assertNotSame(r1.getId(), r2.getId()); - r1 = new Route(1L, 3L); - r1.getPath().add(new NodePortTuple(1L, (short)1)); - r1.getPath().add(new NodePortTuple(2L, (short)1)); - r1.getPath().add(new NodePortTuple(2L, (short)2)); - r1.getPath().add(new NodePortTuple(3L, (short)1)); + r1 = new Route(DatapathId.of(1L), DatapathId.of(3L)); + r1.getPath().add(new NodePortTuple(DatapathId.of(1L), OFPort.of((short)1))); + r1.getPath().add(new NodePortTuple(DatapathId.of(2L), OFPort.of((short)1))); + r1.getPath().add(new NodePortTuple(DatapathId.of(2L), OFPort.of((short)2))); + r1.getPath().add(new NodePortTuple(DatapathId.of(3L), OFPort.of((short)1))); - r2.getPath().add(new NodePortTuple(1L, (short)1)); - r2.getPath().add(new NodePortTuple(2L, (short)1)); - r2.getPath().add(new NodePortTuple(2L, (short)2)); - r2.getPath().add(new NodePortTuple(3L, (short)1)); + r2.getPath().add(new NodePortTuple(DatapathId.of(1L), OFPort.of((short)1))); + r2.getPath().add(new NodePortTuple(DatapathId.of(2L), OFPort.of((short)1))); + r2.getPath().add(new NodePortTuple(DatapathId.of(2L), OFPort.of((short)2))); + r2.getPath().add(new NodePortTuple(DatapathId.of(3L), OFPort.of((short)1))); assertEquals(r1, r2); @@ -56,7 +60,7 @@ public class RouteTest extends FloodlightTestCase { assertEquals(r1, r2); r2.getPath().remove(1); - temp = new NodePortTuple(2L, (short)5); + temp = new NodePortTuple(DatapathId.of(2L), OFPort.of((short)5)); r2.getPath().add(1, temp); assertNotSame(r1, r2); } diff --git a/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowTests.java b/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowTests.java index a1e33539ebcb2b7099740fd62d1116fd7364b782..cf73d87a60e9415ee71f8175333d57ac8c758ef6 100644 --- a/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowTests.java +++ b/src/test/java/net/floodlightcontroller/staticflowentry/StaticFlowTests.java @@ -24,19 +24,20 @@ import java.util.List; import java.util.Map; import java.util.Set; - import org.easymock.Capture; import org.easymock.CaptureType; import org.junit.Test; -import org.openflow.protocol.OFFlowMod; -import org.openflow.protocol.OFMatch; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFPort; -import org.openflow.protocol.action.OFAction; -import org.openflow.protocol.action.OFActionOutput; -import org.openflow.protocol.action.OFActionStripVirtualLan; -import org.openflow.util.HexString; - +import org.projectfloodlight.openflow.protocol.OFFactories; +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.protocol.OFFlowMod; +import org.projectfloodlight.openflow.protocol.OFVersion; +import org.projectfloodlight.openflow.protocol.match.Match; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFBufferId; +import org.projectfloodlight.openflow.types.OFPort; +import org.projectfloodlight.openflow.protocol.action.OFAction; +import org.projectfloodlight.openflow.util.HexString; import net.floodlightcontroller.core.FloodlightContext; import net.floodlightcontroller.core.IFloodlightProviderService; @@ -44,6 +45,8 @@ import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.test.MockFloodlightProvider; import net.floodlightcontroller.test.FloodlightTestCase; +import net.floodlightcontroller.util.FlowModUtils; +import net.floodlightcontroller.util.MatchUtils; import net.floodlightcontroller.restserver.IRestApiService; import net.floodlightcontroller.restserver.RestApiServer; import net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher; @@ -51,11 +54,14 @@ import net.floodlightcontroller.storage.IStorageSourceService; import net.floodlightcontroller.storage.memory.MemoryStorageSource; import static net.floodlightcontroller.staticflowentry.StaticFlowEntryPusher.*; import static org.easymock.EasyMock.*; +import static org.junit.Assert.*; public class StaticFlowTests extends FloodlightTestCase { static String TestSwitch1DPID = "00:00:00:00:00:00:00:01"; static int TotalTestRules = 3; + + static OFFactory factory = OFFactories.getFactory(OFVersion.OF_13); /*** * Create TestRuleXXX and the corresponding FlowModXXX @@ -64,51 +70,50 @@ public class StaticFlowTests extends FloodlightTestCase { static Map<String,Object> TestRule1; static OFFlowMod FlowMod1; static { - FlowMod1 = new OFFlowMod(); + FlowMod1 = factory.buildFlowModify().build(); TestRule1 = new HashMap<String,Object>(); TestRule1.put(COLUMN_NAME, "TestRule1"); TestRule1.put(COLUMN_SWITCH, TestSwitch1DPID); // setup match - OFMatch match = new OFMatch(); + Match match; TestRule1.put(COLUMN_DL_DST, "00:20:30:40:50:60"); - match.fromString("dl_dst=00:20:30:40:50:60"); + match = MatchUtils.fromString("dl_dst=00:20:30:40:50:60", factory.getVersion()); // setup actions List<OFAction> actions = new LinkedList<OFAction>(); TestRule1.put(COLUMN_ACTIONS, "output=1"); - actions.add(new OFActionOutput((short)1, Short.MAX_VALUE)); + actions.add(factory.actions().output(OFPort.of(1), Integer.MAX_VALUE)); // done - FlowMod1.setMatch(match); - FlowMod1.setActions(actions); - FlowMod1.setBufferId(-1); - FlowMod1.setOutPort(OFPort.OFPP_NONE.getValue()); - FlowMod1.setPriority(Short.MAX_VALUE); - FlowMod1.setLengthU(OFFlowMod.MINIMUM_LENGTH + 8); // 8 bytes of actions + FlowMod1 = FlowMod1.createBuilder().setMatch(match) + .setActions(actions) + .setBufferId(OFBufferId.NO_BUFFER) + .setOutPort(OFPort.ANY) + .setPriority(Short.MAX_VALUE) + .build(); } static Map<String,Object> TestRule2; static OFFlowMod FlowMod2; static { - FlowMod2 = new OFFlowMod(); + FlowMod2 = factory.buildFlowModify().build(); TestRule2 = new HashMap<String,Object>(); TestRule2.put(COLUMN_NAME, "TestRule2"); TestRule2.put(COLUMN_SWITCH, TestSwitch1DPID); // setup match - OFMatch match = new OFMatch(); + Match match; TestRule2.put(COLUMN_NW_DST, "192.168.1.0/24"); - match.fromString("nw_dst=192.168.1.0/24"); + match = MatchUtils.fromString("nw_dst=192.168.1.0/24", factory.getVersion()); // setup actions List<OFAction> actions = new LinkedList<OFAction>(); TestRule2.put(COLUMN_ACTIONS, "output=1"); - actions.add(new OFActionOutput((short)1, Short.MAX_VALUE)); + actions.add(factory.actions().output(OFPort.of(1), Integer.MAX_VALUE)); // done - FlowMod2.setMatch(match); - FlowMod2.setActions(actions); - FlowMod2.setBufferId(-1); - FlowMod2.setOutPort(OFPort.OFPP_NONE.getValue()); - FlowMod2.setPriority(Short.MAX_VALUE); - FlowMod2.setLengthU(OFFlowMod.MINIMUM_LENGTH + 8); // 8 bytes of actions - + FlowMod2 = FlowMod2.createBuilder().setMatch(match) + .setActions(actions) + .setBufferId(OFBufferId.NO_BUFFER) + .setOutPort(OFPort.ANY) + .setPriority(Short.MAX_VALUE) + .build(); } @@ -122,35 +127,33 @@ public class StaticFlowTests extends FloodlightTestCase { private long dpid; private IStorageSourceService storage; static { - FlowMod3 = new OFFlowMod(); + FlowMod3 = factory.buildFlowModify().build(); TestRule3 = new HashMap<String,Object>(); TestRule3.put(COLUMN_NAME, "TestRule3"); TestRule3.put(COLUMN_SWITCH, TestSwitch1DPID); // setup match - OFMatch match = new OFMatch(); + Match match; TestRule3.put(COLUMN_DL_DST, "00:20:30:40:50:60"); TestRule3.put(COLUMN_DL_VLAN, 4096); - match.fromString("dl_dst=00:20:30:40:50:60,dl_vlan=4096"); + match = MatchUtils.fromString("dl_dst=00:20:30:40:50:60,dl_vlan=4096", factory.getVersion()); // setup actions TestRule3.put(COLUMN_ACTIONS, "output=controller"); List<OFAction> actions = new LinkedList<OFAction>(); - actions.add(new OFActionOutput(OFPort.OFPP_CONTROLLER.getValue(), Short.MAX_VALUE)); + actions.add(factory.actions().output(OFPort.CONTROLLER, Integer.MAX_VALUE)); // done - FlowMod3.setMatch(match); - FlowMod3.setActions(actions); - FlowMod3.setBufferId(-1); - FlowMod3.setOutPort(OFPort.OFPP_NONE.getValue()); - FlowMod3.setPriority(Short.MAX_VALUE); - FlowMod3.setLengthU(OFFlowMod.MINIMUM_LENGTH + 8); // 8 bytes of actions - + FlowMod3 = FlowMod3.createBuilder().setMatch(match) + .setActions(actions) + .setBufferId(OFBufferId.NO_BUFFER) + .setOutPort(OFPort.ANY) + .setPriority(Short.MAX_VALUE) + .build(); } - private void verifyFlowMod(OFFlowMod testFlowMod, - OFFlowMod goodFlowMod) { + private void verifyFlowMod(OFFlowMod testFlowMod, OFFlowMod goodFlowMod) { verifyMatch(testFlowMod, goodFlowMod); verifyActions(testFlowMod, goodFlowMod); // dont' bother testing the cookie; just copy it over - goodFlowMod.setCookie(testFlowMod.getCookie()); + goodFlowMod = goodFlowMod.createBuilder().setCookie(testFlowMod.getCookie()).build(); // .. so we can continue to use .equals() assertEquals(goodFlowMod, testFlowMod); } @@ -184,13 +187,12 @@ public class StaticFlowTests extends FloodlightTestCase { mockSwitch = createNiceMock(IOFSwitch.class); writeCapture = new Capture<OFMessage>(CaptureType.ALL); - contextCapture = new Capture<FloodlightContext>(CaptureType.ALL); writeCaptureList = new Capture<List<OFMessage>>(CaptureType.ALL); //OFMessageSafeOutStream mockOutStream = createNiceMock(OFMessageSafeOutStream.class); - mockSwitch.write(capture(writeCapture), capture(contextCapture)); + mockSwitch.write(capture(writeCapture)); expectLastCall().anyTimes(); - mockSwitch.write(capture(writeCaptureList), capture(contextCapture)); + mockSwitch.write(capture(writeCaptureList)); expectLastCall().anyTimes(); mockSwitch.flush(); expectLastCall().anyTimes(); @@ -200,10 +202,10 @@ public class StaticFlowTests extends FloodlightTestCase { fmc.addService(IStorageSourceService.class, storage); MockFloodlightProvider mockFloodlightProvider = getMockFloodlightProvider(); - Map<Long, IOFSwitch> switchMap = new HashMap<Long, IOFSwitch>(); - switchMap.put(dpid, mockSwitch); + Map<DatapathId, IOFSwitch> switchMap = new HashMap<DatapathId, IOFSwitch>(); + switchMap.put(DatapathId.of(dpid), mockSwitch); // NO ! expect(mockFloodlightProvider.getSwitches()).andReturn(switchMap).anyTimes(); - mockFloodlightProvider.setSwitches(switchMap); + getMockSwitchService().setSwitches(switchMap); fmc.addService(IFloodlightProviderService.class, mockFloodlightProvider); RestApiServer restApi = new RestApiServer(); fmc.addService(IRestApiService.class, restApi); @@ -222,12 +224,12 @@ public class StaticFlowTests extends FloodlightTestCase { //expect(mockSwitch.getOutputStream()).andReturn(mockOutStream).anyTimes(); // if someone calls getId(), return this dpid instead - expect(mockSwitch.getId()).andReturn(dpid).anyTimes(); - expect(mockSwitch.getStringId()).andReturn(TestSwitch1DPID).anyTimes(); + expect(mockSwitch.getId()).andReturn(DatapathId.of(dpid)).anyTimes(); + expect(mockSwitch.getId()).andReturn(DatapathId.of(TestSwitch1DPID)).anyTimes(); replay(mockSwitch); // hook the static pusher up to the fake switch - staticFlowEntryPusher.switchAdded(dpid); + staticFlowEntryPusher.switchAdded(DatapathId.of(dpid)); verify(mockSwitch); @@ -257,16 +259,16 @@ public class StaticFlowTests extends FloodlightTestCase { assertEquals(2, writeCapture.getValues().size()); OFFlowMod firstDelete = (OFFlowMod) writeCapture.getValues().get(0); - FlowMod1.setCommand(OFFlowMod.OFPFC_DELETE_STRICT); + FlowMod1 = FlowModUtils.toFlowDeleteStrict(FlowMod1); verifyFlowMod(firstDelete, FlowMod1); OFFlowMod secondDelete = (OFFlowMod) writeCapture.getValues().get(1); - FlowMod2.setCommand(OFFlowMod.OFPFC_DELETE_STRICT); + FlowMod2 = FlowModUtils.toFlowDeleteStrict(FlowMod2); verifyFlowMod(secondDelete, FlowMod2); // add rules back to make sure that staticFlowPusher.rowsInserted() works writeCapture.reset(); - FlowMod2.setCommand(OFFlowMod.OFPFC_ADD); + FlowMod2= FlowModUtils.toFlowAdd(FlowMod1); storage.insertRow(StaticFlowEntryPusher.TABLE_NAME, TestRule2); assertEquals(2, staticFlowEntryPusher.countEntries()); assertEquals(1, writeCaptureList.getValues().size()); @@ -288,10 +290,10 @@ public class StaticFlowTests extends FloodlightTestCase { outList = writeCaptureList.getValues().get(0); assertEquals(2, outList.size()); OFFlowMod removeFlowMod = (OFFlowMod) outList.get(0); - FlowMod3.setCommand(OFFlowMod.OFPFC_DELETE_STRICT); + FlowMod3 = FlowModUtils.toFlowDeleteStrict(FlowMod3); verifyFlowMod(removeFlowMod, FlowMod3); - FlowMod3.setCommand(OFFlowMod.OFPFC_ADD); - FlowMod3.getMatch().fromString("dl_dst=00:20:30:40:50:60,dl_vlan=333"); + FlowMod3 = FlowModUtils.toFlowAdd(FlowMod3); + FlowMod3 = FlowMod3.createBuilder().setMatch(MatchUtils.fromString("dl_dst=00:20:30:40:50:60,dl_vlan=333", factory.getVersion())).build(); OFFlowMod updateFlowMod = (OFFlowMod) outList.get(1); verifyFlowMod(updateFlowMod, FlowMod3); writeCaptureList.reset(); @@ -305,13 +307,11 @@ public class StaticFlowTests extends FloodlightTestCase { outList = writeCaptureList.getValues().get(0); assertEquals(1, outList.size()); OFFlowMod modifyFlowMod = (OFFlowMod) outList.get(0); - FlowMod3.setCommand(OFFlowMod.OFPFC_MODIFY_STRICT); + FlowMod3 = FlowModUtils.toFlowModifyStrict(FlowMod3); List<OFAction> modifiedActions = FlowMod3.getActions(); - modifiedActions.add(new OFActionStripVirtualLan()); // add the new action to what we should expect - FlowMod3.setActions(modifiedActions); - FlowMod3.setLengthU(OFFlowMod.MINIMUM_LENGTH + 16); // accommodate the addition of new actions + modifiedActions.add(factory.actions().stripVlan()); // add the new action to what we should expect + FlowMod3 = FlowMod3.createBuilder().setActions(modifiedActions).build(); verifyFlowMod(modifyFlowMod, FlowMod3); - } diff --git a/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java b/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java index 58d76fe4dc5bc7079a6e9ebce2f637931632dbb2..d05013cbc848f7056fd3542c776f51074570d94b 100644 --- a/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java +++ b/src/test/java/net/floodlightcontroller/topology/TopologyInstanceTest.java @@ -21,8 +21,8 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; -import static org.junit.Assert.*; +import static org.junit.Assert.*; import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.test.MockFloodlightProvider; @@ -37,6 +37,8 @@ import net.floodlightcontroller.topology.TopologyManager; import org.easymock.EasyMock; import org.junit.Before; import org.junit.Test; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFPort; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -71,7 +73,7 @@ public class TopologyInstanceTest { } protected void verifyClusters(int[][] clusters, boolean tunnelsEnabled) { - List<Long> verifiedSwitches = new ArrayList<Long>(); + List<DatapathId> verifiedSwitches = new ArrayList<DatapathId>(); // Make sure the expected cluster arrays are sorted so we can // use binarySearch to test for membership @@ -80,24 +82,24 @@ public class TopologyInstanceTest { TopologyInstance ti = topologyManager.getCurrentInstance(tunnelsEnabled); - Set<Long> switches = ti.getSwitches(); + Set<DatapathId> switches = ti.getSwitches(); - for (long sw: switches) { + for (DatapathId sw: switches) { if (!verifiedSwitches.contains(sw)) { int[] expectedCluster = null; for (int j = 0; j < clusters.length; j++) { - if (Arrays.binarySearch(clusters[j], (int) sw) >= 0) { + if (Arrays.binarySearch(clusters[j], (int)sw.getLong()) >= 0) { expectedCluster = clusters[j]; break; } } if (expectedCluster != null) { - Set<Long> cluster = ti.getSwitchesInOpenflowDomain(sw); + Set<DatapathId> cluster = ti.getSwitchesInOpenflowDomain(sw); assertEquals(expectedCluster.length, cluster.size()); - for (long sw2: cluster) { - assertTrue(Arrays.binarySearch(expectedCluster, (int)sw2) >= 0); + for (DatapathId sw2: cluster) { + assertTrue(Arrays.binarySearch(expectedCluster, (int)sw2.getLong()) >= 0); verifiedSwitches.add(sw2); } } @@ -119,7 +121,7 @@ public class TopologyInstanceTest { int [][] nptList = ebp[i]; expected.clear(); for(int j=0; j<nptList.length; ++j) { - npt = new NodePortTuple((long)nptList[j][0], (short)nptList[j][1]); + npt = new NodePortTuple(DatapathId.of(nptList[j][0]), OFPort.of(nptList[j][1])); expected.add(npt); } TopologyInstance ti = topologyManager.getCurrentInstance(tunnelsEnabled); @@ -145,7 +147,7 @@ public class TopologyInstanceTest { else if (r[4] == TUNNEL_LINK) type = ILinkDiscovery.LinkType.TUNNEL; - topologyManager.addOrUpdateLink((long)r[0], (short)r[1], (long)r[2], (short)r[3], type); + topologyManager.addOrUpdateLink(DatapathId.of(r[0]), OFPort.of((short)r[1]), DatapathId.of(r[2]), OFPort.of((short)r[3]), type); } topologyManager.createNewInstance(); } @@ -258,8 +260,8 @@ public class TopologyInstanceTest { // Test 3. Remove links { - tm.removeLink((long)5,(short)3,(long)6,(short)1); - tm.removeLink((long)6,(short)1,(long)5,(short)3); + tm.removeLink(DatapathId.of(5), OFPort.of((short)3), DatapathId.of(6), OFPort.of((short)1)); + tm.removeLink(DatapathId.of(6), OFPort.of((short)1), DatapathId.of(5), OFPort.of((short)3)); int [][] expectedClusters = { {1,2,3,4,5}, @@ -270,7 +272,7 @@ public class TopologyInstanceTest { // Remove Switch { - tm.removeSwitch(4); + tm.removeSwitch(DatapathId.of(4)); int [][] expectedClusters = { {1,2,3,5}, }; diff --git a/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java b/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java index b1027349cfc203a744a9cc18e828fe5d981064d1..2ff76ee513484b72b78e677b5dd689c84165410e 100644 --- a/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java +++ b/src/test/java/net/floodlightcontroller/topology/TopologyManagerTest.java @@ -16,6 +16,7 @@ package net.floodlightcontroller.topology; +import static org.junit.Assert.*; import net.floodlightcontroller.core.IFloodlightProviderService; import net.floodlightcontroller.core.module.FloodlightModuleContext; import net.floodlightcontroller.core.test.MockThreadPoolService; @@ -26,6 +27,8 @@ import net.floodlightcontroller.topology.TopologyManager; import org.junit.Before; import org.junit.Test; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFPort; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,7 +53,7 @@ public class TopologyManagerTest extends FloodlightTestCase { @Test public void testBasic1() throws Exception { - tm.addOrUpdateLink(1, (short)1, 2, (short)1, ILinkDiscovery.LinkType.DIRECT_LINK); + tm.addOrUpdateLink(DatapathId.of(1), OFPort.of((short)1), DatapathId.of(2), OFPort.of((short)1), ILinkDiscovery.LinkType.DIRECT_LINK); assertTrue(tm.getSwitchPorts().size() == 2); // for two nodes. assertTrue(tm.getSwitchPorts().get((long)1).size()==1); assertTrue(tm.getSwitchPorts().get((long)2).size()==1); @@ -58,7 +61,7 @@ public class TopologyManagerTest extends FloodlightTestCase { assertTrue(tm.getPortBroadcastDomainLinks().size()==0); assertTrue(tm.getTunnelPorts().size()==0); - tm.addOrUpdateLink(1, (short)2, 2, (short)2, ILinkDiscovery.LinkType.MULTIHOP_LINK); + tm.addOrUpdateLink(DatapathId.of(1), OFPort.of((short)2), DatapathId.of(2), OFPort.of((short)2), ILinkDiscovery.LinkType.MULTIHOP_LINK); assertTrue(tm.getSwitchPorts().size() == 2); // for two nodes. assertTrue(tm.getSwitchPorts().get((long)1).size()==2); assertTrue(tm.getSwitchPorts().get((long)2).size()==2); @@ -66,14 +69,14 @@ public class TopologyManagerTest extends FloodlightTestCase { assertTrue(tm.getPortBroadcastDomainLinks().size()==2); assertTrue(tm.getTunnelPorts().size()==0); - tm.removeLink(1, (short)2, 2, (short)2); + tm.removeLink(DatapathId.of(1), OFPort.of((short)2), DatapathId.of(2), OFPort.of((short)2)); assertTrue(tm.getSwitchPorts().get((long)1).size()==1); assertTrue(tm.getSwitchPorts().get((long)2).size()==1); assertTrue(tm.getSwitchPorts().size() == 2); assertTrue(tm.getSwitchPortLinks().size()==2); assertTrue(tm.getPortBroadcastDomainLinks().size()==0); - tm.removeLink(1, (short)1, 2, (short)1); + tm.removeLink(DatapathId.of(1), OFPort.of((short)1), DatapathId.of(2), OFPort.of((short)1)); assertTrue(tm.getSwitchPorts().size() == 0); assertTrue(tm.getSwitchPortLinks().size()==0); assertTrue(tm.getPortBroadcastDomainLinks().size()==0); @@ -81,8 +84,8 @@ public class TopologyManagerTest extends FloodlightTestCase { @Test public void testBasic2() throws Exception { - tm.addOrUpdateLink(1, (short)1, 2, (short)1, ILinkDiscovery.LinkType.DIRECT_LINK); - tm.addOrUpdateLink(2, (short)2, 3, (short)1, ILinkDiscovery.LinkType.MULTIHOP_LINK); + tm.addOrUpdateLink(DatapathId.of(1), OFPort.of((short)1), DatapathId.of(2), OFPort.of((short)1), ILinkDiscovery.LinkType.DIRECT_LINK); + tm.addOrUpdateLink(DatapathId.of(2), OFPort.of((short)2), DatapathId.of(3), OFPort.of((short)1), ILinkDiscovery.LinkType.MULTIHOP_LINK); assertTrue(tm.getSwitchPorts().size() == 3); // for two nodes. assertTrue(tm.getSwitchPorts().get((long)1).size()==1); assertTrue(tm.getSwitchPorts().get((long)2).size()==2); @@ -90,7 +93,7 @@ public class TopologyManagerTest extends FloodlightTestCase { assertTrue(tm.getSwitchPortLinks().size()==4); assertTrue(tm.getPortBroadcastDomainLinks().size()==2); - tm.removeLink(1, (short)1, 2, (short)1); + tm.removeLink(DatapathId.of(1), OFPort.of((short)1), DatapathId.of(2), OFPort.of((short)1)); assertTrue(tm.getSwitchPorts().size() == 2); assertTrue(tm.getSwitchPorts().get((long)1) == null); assertTrue(tm.getSwitchPorts().get((long)2).size()==1); @@ -99,7 +102,7 @@ public class TopologyManagerTest extends FloodlightTestCase { assertTrue(tm.getPortBroadcastDomainLinks().size()==2); // nonexistent link // no null pointer exceptions. - tm.removeLink(3, (short)1, 2, (short)2); + tm.removeLink(DatapathId.of(3), OFPort.of((short)1), DatapathId.of(2), OFPort.of((short)2)); assertTrue(tm.getSwitchPorts().size() == 2); assertTrue(tm.getSwitchPorts().get((long)1) == null); assertTrue(tm.getSwitchPorts().get((long)2).size()==1); @@ -107,7 +110,7 @@ public class TopologyManagerTest extends FloodlightTestCase { assertTrue(tm.getSwitchPortLinks().size()==2); assertTrue(tm.getPortBroadcastDomainLinks().size()==2); - tm.removeLink(3, (short)2, 1, (short)2); + tm.removeLink(DatapathId.of(3), OFPort.of((short)2), DatapathId.of(1), OFPort.of((short)2)); assertTrue(tm.getSwitchPorts().size() == 2); assertTrue(tm.getSwitchPorts().get((long)1)==null); assertTrue(tm.getSwitchPorts().get((long)2).size()==1); @@ -115,7 +118,7 @@ public class TopologyManagerTest extends FloodlightTestCase { assertTrue(tm.getSwitchPortLinks().size()==2); assertTrue(tm.getPortBroadcastDomainLinks().size()==2); - tm.removeLink(2, (short)2, 3, (short)1); + tm.removeLink(DatapathId.of(2), OFPort.of((short)2), DatapathId.of(3), OFPort.of((short)1)); assertTrue(tm.getSwitchPorts().size() == 0); // for two nodes. assertTrue(tm.getSwitchPortLinks().size()==0); assertTrue(tm.getPortBroadcastDomainLinks().size()==0); diff --git a/src/test/java/net/floodlightcontroller/util/MACAddressTest.java b/src/test/java/net/floodlightcontroller/util/MACAddressTest.java deleted file mode 100644 index 0846f691de0f753a268bf1611b23e0bd54a51ec8..0000000000000000000000000000000000000000 --- a/src/test/java/net/floodlightcontroller/util/MACAddressTest.java +++ /dev/null @@ -1,101 +0,0 @@ -/** - * 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.util; - -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * @author Sho Shimizu (sho.shimizu@gmail.com) - */ -public class MACAddressTest { - @Test - public void testValueOf() { - MACAddress address = MACAddress.valueOf("00:01:02:03:04:05"); - assertEquals(address, - MACAddress.valueOf(new byte[]{0x00, 0x01, 0x02, 0x03, 0x04, 0x05})); - assertEquals("00:01:02:03:04:05", address.toString()); - - address = MACAddress.valueOf("FF:FE:FD:10:20:30"); - assertEquals(address, - MACAddress.valueOf(new byte[]{(byte) 0xFF, (byte) 0xFE, (byte) 0xFD, 0x10, 0x20, 0x30})); - assertEquals("FF:FE:FD:10:20:30", address.toString()); - - address = MACAddress.valueOf("00:11:22:aa:bb:cc"); - assertEquals(address, - MACAddress.valueOf(new byte[]{0x00, 0x11, 0x22, (byte)0xaa, (byte)0xbb, (byte)0xcc})); - } - - @Test(expected=NumberFormatException.class) - public void testIllegalFormat() { - MACAddress.valueOf("0T:00:01:02:03:04"); - } - - @Test(expected=IllegalArgumentException.class) - public void testLongStringFields() { - MACAddress.valueOf("00:01:02:03:04:05:06"); - } - - @Test(expected=IllegalArgumentException.class) - public void testShortStringFields() { - MACAddress.valueOf("00:01:02:03:04"); - } - - @Test(expected=IllegalArgumentException.class) - public void testLongByteFields() { - MACAddress.valueOf(new byte[]{0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}); - } - - @Test(expected=IllegalArgumentException.class) - public void testShortByteField() { - MACAddress.valueOf(new byte[]{0x01, 0x01, 0x02, 0x03, 0x04}); - } - - // Test data is imported from net.floodlightcontroller.packet.EthernetTest - @Test - public void testToLong() { - assertEquals( - 281474976710655L, - MACAddress.valueOf(new byte[]{(byte) 0xff, (byte) 0xff, - (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}).toLong()); - - assertEquals( - 1103823438081L, - MACAddress.valueOf(new byte[] { (byte) 0x01, (byte) 0x01, - (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01 }).toLong()); - - assertEquals( - 141289400074368L, - MACAddress.valueOf(new byte[] { (byte) 0x80, (byte) 0x80, - (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80 }).toLong()); - - } - - @Test - public void testIsBroadcast() { - assertTrue(MACAddress.valueOf("FF:FF:FF:FF:FF:FF").isBroadcast()); - assertFalse(MACAddress.valueOf("11:22:33:44:55:66").isBroadcast()); - } - - @Test - public void testIsMulticast() { - assertTrue(MACAddress.valueOf("01:80:C2:00:00:00").isMulticast()); - assertFalse(MACAddress.valueOf("FF:FF:FF:FF:FF:FF").isMulticast()); - assertFalse(MACAddress.valueOf("11:22:33:44:55:66").isBroadcast()); - } -} diff --git a/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java b/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java index 547371cc0ba2e3694c2c810d8dd928f5f12059c0..75ee145acd13b24504e1766689715b067838b728 100644 --- a/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java +++ b/src/test/java/net/floodlightcontroller/util/OFMessageDamperMockSwitch.java @@ -17,30 +17,47 @@ package net.floodlightcontroller.util; import static org.junit.Assert.*; + import java.io.IOException; import java.net.SocketAddress; - import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.Future; + import net.floodlightcontroller.core.FloodlightContext; +import net.floodlightcontroller.core.IOFConnection; import net.floodlightcontroller.core.IOFMessageListener; import net.floodlightcontroller.core.IOFSwitch; import net.floodlightcontroller.core.HARole; +import net.floodlightcontroller.core.LogicalOFMessageCategory; +import net.floodlightcontroller.core.OFConnection; +import net.floodlightcontroller.core.SwitchDescription; import net.floodlightcontroller.core.internal.Controller; import net.floodlightcontroller.debugcounter.IDebugCounterService; import net.floodlightcontroller.threadpool.IThreadPoolService; import org.jboss.netty.channel.Channel; +import org.projectfloodlight.openflow.protocol.OFActionType; +import org.projectfloodlight.openflow.protocol.OFCapabilities; +import org.projectfloodlight.openflow.protocol.OFControllerRole; +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.OFPortStatus; +import org.projectfloodlight.openflow.protocol.OFRequest; import org.projectfloodlight.openflow.protocol.OFStatsReply; import org.projectfloodlight.openflow.protocol.OFStatsRequest; import org.projectfloodlight.openflow.protocol.OFDescStatsReply; import org.projectfloodlight.openflow.protocol.OFDescStatsRequest; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.OFPort; + +import com.google.common.collect.ImmutableList; +import com.google.common.util.concurrent.ListenableFuture; /** @@ -95,86 +112,11 @@ public class OFMessageDamperMockSwitch implements IOFSwitch { //------------------------------------------------------- // IOFSwitch: mocked methods - @Override - public void write(OFMessage m, FloodlightContext bc) throws IOException { - assertNull("write() called but already have message", writtenMessage); - assertNull("write() called but already have context", writtenContext); - writtenContext = bc; - writtenMessage = m; - } - @Override - public void writeThrottled(OFMessage msg, FloodlightContext cntx) - throws IOException { - write(msg, cntx); - } //------------------------------------------------------- // IOFSwitch: not-implemented methods - @Override - public void writeThrottled(List<OFMessage> msglist, FloodlightContext bc) - throws IOException { - assertTrue("Unexpected method call", false); - } - - @Override - public void write(List<OFMessage> msglist, FloodlightContext bc) - throws IOException { - assertTrue("Unexpected method call", false); - } - - @Override - public void disconnectOutputStream() { - assertTrue("Unexpected method call", false); - } - - @Override - public void setFeaturesReply(OFFeaturesReply featuresReply) { - assertTrue("Unexpected method call", false); - } - - @Override - public void setSwitchProperties(OFDescriptionStatistics description) { - assertTrue("Unexpected method call", false); - // TODO Auto-generated method stub - } - - @Override - public Collection<ImmutablePort> getEnabledPorts() { - assertTrue("Unexpected method call", false); - return null; - } - - @Override - public Collection<Short> getEnabledPortNumbers() { - assertTrue("Unexpected method call", false); - return null; - } - - @Override - public ImmutablePort getPort(short portNumber) { - assertTrue("Unexpected method call", false); - return null; - } - - @Override - public ImmutablePort getPort(String portName) { - assertTrue("Unexpected method call", false); - return null; - } - - @Override - public Collection<ImmutablePort> getPorts() { - assertTrue("Unexpected method call", false); - return null; - } - - @Override - public boolean portEnabled(short portName) { - assertTrue("Unexpected method call", false); - return false; - } @Override public boolean portEnabled(String portName) { @@ -183,15 +125,9 @@ public class OFMessageDamperMockSwitch implements IOFSwitch { } @Override - public long getId() { + public DatapathId getId() { assertTrue("Unexpected method call", false); - return 0; - } - - @Override - public String getStringId() { - assertTrue("Unexpected method call", false); - return null; + return DatapathId.NONE; } @Override @@ -212,51 +148,12 @@ public class OFMessageDamperMockSwitch implements IOFSwitch { return null; } - @Override - public int getNextTransactionId() { - assertTrue("Unexpected method call", false); - return 0; - } - - @Override - public Future<List<OFStatistics>> - queryStatistics(OFStatisticsRequest request) throws IOException { - assertTrue("Unexpected method call", false); - return null; - } - @Override public boolean isConnected() { assertTrue("Unexpected method call", false); return false; } - @Override - public void setConnected(boolean connected) { - assertTrue("Unexpected method call", false); - } - - @Override - public Role getHARole() { - assertTrue("Unexpected method call", false); - return null; - } - - @Override - public void deliverStatisticsReply(OFStatisticsReply reply) { - assertTrue("Unexpected method call", false); - } - - @Override - public void cancelStatisticsReply(int transactionId) { - assertTrue("Unexpected method call", false); - } - - @Override - public void cancelAllStatisticsReplies() { - assertTrue("Unexpected method call", false); - } - @Override public boolean hasAttribute(String name) { assertTrue("Unexpected method call", false); @@ -280,108 +177,33 @@ public class OFMessageDamperMockSwitch implements IOFSwitch { return null; } - @Override - public void clearAllFlowMods() { - assertTrue("Unexpected method call", false); - } - - @Override - public boolean updateBroadcastCache(Long entry, Short port) { - assertTrue("Unexpected method call", false); - return false; - } - - @Override - public Map<Short, Long> getPortBroadcastHits() { - assertTrue("Unexpected method call", false); - return null; - } - - @Override - public void sendStatsQuery(OFStatisticsRequest request, int xid, - IOFMessageListener caller) - throws IOException { - assertTrue("Unexpected method call", false); - } - @Override public void flush() { assertTrue("Unexpected method call", false); } @Override - public Future<OFFeaturesReply> querySwitchFeaturesReply() - throws IOException { - fail("Unexpected method call"); - return null; - } - - @Override - public void deliverOFFeaturesReply(OFMessage reply) { - fail("Unexpected method call"); - } - - @Override - public void cancelFeaturesReply(int transactionId) { - fail("Unexpected method call"); - } - - @Override - public int getBuffers() { - fail("Unexpected method call"); - return 0; - } - - @Override - public int getActions() { + public long getBuffers() { fail("Unexpected method call"); return 0; } @Override - public int getCapabilities() { - fail("Unexpected method call"); - return 0; - } - - @Override - public byte getTables() { - fail("Unexpected method call"); - return 0; - } - - @Override - public void setChannel(Channel channel) { - fail("Unexpected method call"); - } - - @Override - public void setFloodlightProvider(OLD__Controller controller) { - fail("Unexpected method call"); - // TODO Auto-generated method stub - - } - - @Override - public void setThreadPoolService(IThreadPoolService threadPool) { - fail("Unexpected method call"); - } - - @Override - public void setHARole(Role role) { + public Set<OFActionType> getActions() { fail("Unexpected method call"); + return null; } @Override - public OFPortType getPortType(short port_num) { + public Set<OFCapabilities> getCapabilities() { fail("Unexpected method call"); return null; } @Override - public boolean isFastPort(short port_num) { + public short getTables() { fail("Unexpected method call"); - return false; + return 0; } @Override @@ -390,103 +212,147 @@ public class OFMessageDamperMockSwitch implements IOFSwitch { return false; } - @Override - public OFDescriptionStatistics getDescriptionStatistics() { - fail("Unexpected method call"); - return null; - } - @Override public boolean isActive() { fail("Unexpected method call"); return false; // never reached } - @Override - public boolean inputThrottled(OFMessage ofm) { - fail("Unexpected method call"); - return false; - } - - @Override - public boolean isOverloaded() { - fail("Unexpected method call"); - return false; - } - - @Override - public boolean isWriteThrottleEnabled() { - fail("Unexpected method call"); - return false; - } - - @Override - public void setDebugCounterService(IDebugCounterService debugCounters) { - fail("Unexpected method call"); - } - - @Override - public OrderedCollection<PortChangeEvent> - processOFPortStatus(OFPortStatus ps) { - fail("Unexpected method call"); - return null; - } - - @Override - public OrderedCollection<PortChangeEvent> - comparePorts(Collection<ImmutablePort> ports) { - fail("Unexpected method call"); - return null; - } - - @Override - public OrderedCollection<PortChangeEvent> - setPorts(Collection<ImmutablePort> ports) { - fail("Unexpected method call"); - return null; - } - - @Override - public void setTableFull(boolean isFull) { - fail("Unexpected method call"); - // TODO Auto-generated method stub - } - - @Override - public void setAccessFlowPriority(short prio) { - fail("Unexpected method call"); - } - - @Override - public void setCoreFlowPriority(short prio) { - fail("Unexpected method call"); - } - - @Override - public short getAccessFlowPriority() { - fail("Unexpected method call"); - return 0; - } - - @Override - public short getCoreFlowPriority() { - fail("Unexpected method call"); - return 0; - } - - @Override - public void startDriverHandshake() { - fail("Unexpected method call"); - } - - @Override - public boolean isDriverHandshakeComplete() { - fail("Unexpected method call"); - return false; - } - - @Override - public void processDriverHandshakeMessage(OFMessage m) { - fail("Unexpected method call"); - } + @Override + public void write(OFMessage m) { + // TODO Auto-generated method stub + + } + + @Override + public void write(Iterable<OFMessage> msglist) { + // TODO Auto-generated method stub + + } + + @Override + public <R extends OFMessage> ListenableFuture<R> writeRequest( + OFRequest<R> request) { + // TODO Auto-generated method stub + return null; + } + + @Override + public <REPLY extends OFStatsReply> ListenableFuture<List<REPLY>> writeStatsRequest( + OFStatsRequest<REPLY> request) { + // TODO Auto-generated method stub + return null; + } + + @Override + public SwitchStatus getStatus() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void disconnect() { + // TODO Auto-generated method stub + + } + + @Override + public SwitchDescription getSwitchDescription() { + // TODO Auto-generated method stub + return null; + } + + @Override + public OFPortDesc getPort(OFPort portNumber) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection<OFPortDesc> getSortedPorts() { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean portEnabled(OFPort portNumber) { + // TODO Auto-generated method stub + return false; + } + + @Override + public OFControllerRole getControllerRole() { + // TODO Auto-generated method stub + return null; + } + + @Override + public OFFactory getOFFactory() { + // TODO Auto-generated method stub + return null; + } + + @Override + public ImmutableList<IOFConnection> getConnections() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void write(OFMessage m, LogicalOFMessageCategory category) { + // TODO Auto-generated method stub + + } + + @Override + public void write(Iterable<OFMessage> msglist, + LogicalOFMessageCategory category) { + // TODO Auto-generated method stub + + } + + @Override + public OFConnection getConnectionByCategory( + LogicalOFMessageCategory category) { + // TODO Auto-generated method stub + return null; + } + + @Override + public <REPLY extends OFStatsReply> ListenableFuture<List<REPLY>> writeStatsRequest( + OFStatsRequest<REPLY> request, LogicalOFMessageCategory category) { + // TODO Auto-generated method stub + return null; + } + + @Override + public <R extends OFMessage> ListenableFuture<R> writeRequest( + OFRequest<R> request, LogicalOFMessageCategory category) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection<OFPortDesc> getEnabledPorts() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection<OFPort> getEnabledPortNumbers() { + // TODO Auto-generated method stub + return null; + } + + @Override + public OFPortDesc getPort(String portName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection<OFPortDesc> getPorts() { + // TODO Auto-generated method stub + return null; + } } diff --git a/src/test/java/net/floodlightcontroller/util/OFMessageDamperTest.java b/src/test/java/net/floodlightcontroller/util/OFMessageDamperTest.java index 84db817f747542c1d5b5ef3f04e2d0061657dd5f..acd32e1e60c5f0d7cfb2fe47c4c94c882d71b3dd 100644 --- a/src/test/java/net/floodlightcontroller/util/OFMessageDamperTest.java +++ b/src/test/java/net/floodlightcontroller/util/OFMessageDamperTest.java @@ -17,23 +17,23 @@ package net.floodlightcontroller.util; import static org.junit.Assert.*; - import net.floodlightcontroller.core.FloodlightContext; import org.junit.Before; import org.junit.Test; -import org.openflow.protocol.OFEchoRequest; -import org.openflow.protocol.OFHello; -import org.openflow.protocol.OFMessage; -import org.openflow.protocol.OFType; -import org.openflow.protocol.factory.BasicFactory; -import org.openflow.protocol.factory.OFMessageFactory; +import org.projectfloodlight.openflow.protocol.OFEchoRequest; +import org.projectfloodlight.openflow.protocol.OFFactory; +import org.projectfloodlight.openflow.protocol.OFHello; +import org.projectfloodlight.openflow.protocol.OFMessage; +import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.OFFactories; +import org.projectfloodlight.openflow.protocol.OFVersion; import java.io.IOException; import java.util.EnumSet; public class OFMessageDamperTest { - OFMessageFactory factory; + OFFactory factory; OFMessageDamper damper; FloodlightContext cntx; @@ -50,25 +50,18 @@ public class OFMessageDamperTest { @Before public void setUp() throws IOException { - factory = BasicFactory.getInstance(); + factory = OFFactories.getFactory(OFVersion.OF_13); cntx = new FloodlightContext(); sw1 = new OFMessageDamperMockSwitch(); sw2 = new OFMessageDamperMockSwitch(); - echoRequst1 = (OFEchoRequest)factory.getMessage(OFType.ECHO_REQUEST); - echoRequst1.setPayload(new byte[] { 1 }); - echoRequst1Clone = (OFEchoRequest) - factory.getMessage(OFType.ECHO_REQUEST); - echoRequst1Clone.setPayload(new byte[] { 1 }); - echoRequst2 = (OFEchoRequest)factory.getMessage(OFType.ECHO_REQUEST); - echoRequst2.setPayload(new byte[] { 2 }); - - hello1 = (OFHello)factory.getMessage(OFType.HELLO); - hello1.setXid(1); - hello2 = (OFHello)factory.getMessage(OFType.HELLO); - hello2.setXid(2); + echoRequst1 = factory.buildEchoRequest().setData(new byte[] { 1 }).build(); + echoRequst1Clone = echoRequst1.createBuilder().build(); + echoRequst2 = factory.buildEchoRequest().setData(new byte[] { 2 }).build(); + hello1 = factory.buildHello().setXid(1L).build(); + hello2 = factory.buildHello().setXid(2L).build(); } protected void doWrite(boolean expectWrite, diff --git a/src/test/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilterTest.java b/src/test/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilterTest.java index d8dc143617beb40454ce9b67c7ea1940ea79a8f2..2eafde2369fcc60d7467fab673388743b153d199 100644 --- a/src/test/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilterTest.java +++ b/src/test/java/net/floodlightcontroller/virtualnetwork/VirtualNetworkFilterTest.java @@ -17,16 +17,23 @@ package net.floodlightcontroller.virtualnetwork; import static org.easymock.EasyMock.*; +import static org.junit.Assert.*; import java.util.List; import org.easymock.EasyMock; import org.junit.Before; import org.junit.Test; -import org.openflow.protocol.OFMatch; -import org.openflow.protocol.OFPacketIn; -import org.openflow.protocol.OFType; -import org.openflow.protocol.OFPacketIn.OFPacketInReason; +import org.projectfloodlight.openflow.protocol.OFFactories; +import org.projectfloodlight.openflow.protocol.OFPacketIn; +import org.projectfloodlight.openflow.protocol.OFType; +import org.projectfloodlight.openflow.protocol.OFPacketInReason; +import org.projectfloodlight.openflow.protocol.OFVersion; +import org.projectfloodlight.openflow.types.DatapathId; +import org.projectfloodlight.openflow.types.IPv4Address; +import org.projectfloodlight.openflow.types.MacAddress; +import org.projectfloodlight.openflow.types.OFBufferId; +import org.projectfloodlight.openflow.types.OFPort; import org.sdnplatform.sync.ISyncService; import org.sdnplatform.sync.test.MockSyncService; @@ -54,7 +61,6 @@ import net.floodlightcontroller.restserver.RestApiServer; import net.floodlightcontroller.test.FloodlightTestCase; import net.floodlightcontroller.threadpool.IThreadPoolService; import net.floodlightcontroller.topology.ITopologyService; -import net.floodlightcontroller.util.MACAddress; import net.floodlightcontroller.virtualnetwork.VirtualNetworkFilter; public class VirtualNetworkFilterTest extends FloodlightTestCase { @@ -70,14 +76,10 @@ public class VirtualNetworkFilterTest extends FloodlightTestCase { protected static String net3 = "net3"; protected static String gw2 = "2.2.2.2"; - protected static MACAddress mac1 = - new MACAddress(Ethernet.toMACAddress("00:11:22:33:44:55")); - protected static MACAddress mac2 = - new MACAddress(Ethernet.toMACAddress("00:11:22:33:44:66")); - protected static MACAddress mac3 = - new MACAddress(Ethernet.toMACAddress("00:11:22:33:44:77")); - protected static MACAddress mac4 = - new MACAddress(Ethernet.toMACAddress("00:11:22:33:44:88")); + protected static MacAddress mac1 = MacAddress.of("00:11:22:33:44:55"); + protected static MacAddress mac2 = MacAddress.of("00:11:22:33:44:66"); + protected static MacAddress mac3 = MacAddress.of("00:11:22:33:44:77"); + protected static MacAddress mac4 = MacAddress.of("00:11:22:33:44:88"); protected static String hostPort1 = "port1"; protected static String hostPort2 = "port2"; protected static String hostPort3 = "port3"; @@ -142,25 +144,16 @@ public class VirtualNetworkFilterTest extends FloodlightTestCase { replay(topology); // Mock switches //fastWilcards mocked as this constant - int fastWildcards = - OFMatch.OFPFW_IN_PORT | - OFMatch.OFPFW_NW_PROTO | - OFMatch.OFPFW_TP_SRC | - OFMatch.OFPFW_TP_DST | - OFMatch.OFPFW_NW_SRC_ALL | - OFMatch.OFPFW_NW_DST_ALL | - OFMatch.OFPFW_NW_TOS; sw1 = EasyMock.createNiceMock(IOFSwitch.class); - expect(sw1.getId()).andReturn(1L).anyTimes(); - expect(sw1.getAttribute(IOFSwitch.PROP_FASTWILDCARDS)).andReturn(fastWildcards).anyTimes(); + expect(sw1.getId()).andReturn(DatapathId.of(1L)).anyTimes(); expect(sw1.hasAttribute(IOFSwitch.PROP_SUPPORTS_OFPP_TABLE)).andReturn(true).anyTimes(); replay(sw1); // Mock packets // Mock from MAC1 -> MAC2 mac1ToMac2PacketIntestPacket = new Ethernet() - .setDestinationMACAddress(mac2.toBytes()) - .setSourceMACAddress(mac1.toBytes()) + .setDestinationMACAddress(mac2.getBytes()) + .setSourceMACAddress(mac1.getBytes()) .setEtherType(Ethernet.TYPE_IPv4) .setPayload( new IPv4() @@ -172,19 +165,16 @@ public class VirtualNetworkFilterTest extends FloodlightTestCase { .setDestinationPort((short) 5001) .setPayload(new Data(new byte[] {0x01})))); mac1ToMac2PacketIntestPacketSerialized = mac1ToMac2PacketIntestPacket.serialize(); - mac1ToMac2PacketIn = - ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory(). - getMessage(OFType.PACKET_IN)) - .setBufferId(-1) - .setInPort((short) 1) - .setPacketData(mac1ToMac2PacketIntestPacketSerialized) + mac1ToMac2PacketIn = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn() + .setBufferId(OFBufferId.NO_BUFFER) + .setInPort(OFPort.of(1)) + .setData(mac1ToMac2PacketIntestPacketSerialized) .setReason(OFPacketInReason.NO_MATCH) - .setTotalLength((short) mac1ToMac2PacketIntestPacketSerialized.length); - + .build(); // Mock from MAC1 -> MAC4 mac1ToMac4PacketIntestPacket = new Ethernet() - .setDestinationMACAddress(mac4.toBytes()) - .setSourceMACAddress(mac1.toBytes()) + .setDestinationMACAddress(mac4.getBytes()) + .setSourceMACAddress(mac1.getBytes()) .setEtherType(Ethernet.TYPE_IPv4) .setPayload( new IPv4() @@ -195,20 +185,17 @@ public class VirtualNetworkFilterTest extends FloodlightTestCase { .setSourcePort((short) 5000) .setDestinationPort((short) 5001) .setPayload(new Data(new byte[] {0x01})))); - mac1ToMac4PacketIntestPacketSerialized = mac1ToMac4PacketIntestPacket.serialize(); - mac1ToMac4PacketIn = - ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory(). - getMessage(OFType.PACKET_IN)) - .setBufferId(-1) - .setInPort((short) 1) - .setPacketData(mac1ToMac4PacketIntestPacketSerialized) + mac1ToMac4PacketIntestPacketSerialized = mac1ToMac4PacketIntestPacket.serialize(); + mac1ToMac4PacketIn = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn() + .setBufferId(OFBufferId.NO_BUFFER) + .setInPort(OFPort.of(1)) + .setData(mac1ToMac4PacketIntestPacketSerialized) .setReason(OFPacketInReason.NO_MATCH) - .setTotalLength((short) mac1ToMac4PacketIntestPacketSerialized.length); - + .build(); // Mock from MAC1 to gateway1 mac1ToGwPacketIntestPacket = new Ethernet() - .setDestinationMACAddress("00:11:33:33:44:55") // mac shouldn't matter, can't be other host - .setSourceMACAddress(mac1.toBytes()) + .setDestinationMACAddress("00:11:33:33:44:55") + .setSourceMACAddress(mac1.getBytes()) .setEtherType(Ethernet.TYPE_IPv4) .setPayload( new IPv4() @@ -220,23 +207,21 @@ public class VirtualNetworkFilterTest extends FloodlightTestCase { .setDestinationPort((short) 5001) .setPayload(new Data(new byte[] {0x01})))); mac1ToGwPacketIntestPacketSerialized = mac1ToGwPacketIntestPacket.serialize(); - mac1ToGwPacketIn = - ((OFPacketIn) mockFloodlightProvider.getOFMessageFactory(). - getMessage(OFType.PACKET_IN)) - .setBufferId(-1) - .setInPort((short) 1) - .setPacketData(mac1ToGwPacketIntestPacketSerialized) + mac1ToGwPacketIn = OFFactories.getFactory(OFVersion.OF_13).buildPacketIn() + .setBufferId(OFBufferId.NO_BUFFER) + .setInPort(OFPort.of(1)) + .setData(mac1ToGwPacketIntestPacketSerialized) .setReason(OFPacketInReason.NO_MATCH) - .setTotalLength((short) mac1ToGwPacketIntestPacketSerialized.length); + .build(); } @Test public void testCreateNetwork() { // Test creating a network with all parameters - vns.createNetwork(guid1, net1, IPv4.toIPv4Address(gw1)); - assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid1)); + vns.createNetwork(guid1, net1, IPv4Address.of(gw1)); + assertTrue(vns.gatewayToGuid.get(IPv4Address.of(gw1)).contains(guid1)); assertTrue(vns.nameToGuid.get(net1).equals(guid1)); - assertTrue(vns.guidToGateway.get(guid1).equals(IPv4.toIPv4Address(gw1))); + assertTrue(vns.guidToGateway.get(guid1).equals(IPv4Address.of(gw1))); assertTrue(vns.vNetsByGuid.get(guid1).name.equals(net1)); assertTrue(vns.vNetsByGuid.get(guid1).guid.equals(guid1)); assertTrue(vns.vNetsByGuid.get(guid1).gateway.equals(gw1)); @@ -246,19 +231,19 @@ public class VirtualNetworkFilterTest extends FloodlightTestCase { vns.createNetwork(guid2, net2, null); assertTrue(vns.nameToGuid.get(net2).equals(guid2)); assertTrue(vns.guidToGateway.get(guid2) == null); - assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).size() == 1); + assertTrue(vns.gatewayToGuid.get(IPv4Address.of(gw1)).size() == 1); assertTrue(vns.vNetsByGuid.get(guid2).name.equals(net2)); assertTrue(vns.vNetsByGuid.get(guid2).guid.equals(guid2)); assertTrue(vns.vNetsByGuid.get(guid2).gateway == null); assertTrue(vns.vNetsByGuid.get(guid2).portToMac.size()==0); // Test creating a network that shares the gateway with net1 - vns.createNetwork(guid3, net3, IPv4.toIPv4Address(gw1)); - assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid1)); - assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid3)); - assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).size() == 2); + vns.createNetwork(guid3, net3, IPv4Address.of(gw1)); + assertTrue(vns.gatewayToGuid.get(IPv4Address.of(gw1)).contains(guid1)); + assertTrue(vns.gatewayToGuid.get(IPv4Address.of(gw1)).contains(guid3)); + assertTrue(vns.gatewayToGuid.get(IPv4Address.of(gw1)).size() == 2); assertTrue(vns.nameToGuid.get(net3).equals(guid3)); - assertTrue(vns.guidToGateway.get(guid3).equals(IPv4.toIPv4Address(gw1))); + assertTrue(vns.guidToGateway.get(guid3).equals(IPv4Address.of(gw1))); assertTrue(vns.vNetsByGuid.get(guid3).name.equals(net3)); assertTrue(vns.vNetsByGuid.get(guid3).guid.equals(guid3)); assertTrue(vns.vNetsByGuid.get(guid3).gateway.equals(gw1)); @@ -272,17 +257,17 @@ public class VirtualNetworkFilterTest extends FloodlightTestCase { testCreateNetwork(); // Modify net2 to add a gateway - vns.createNetwork(guid2, net2, IPv4.toIPv4Address(gw1)); + vns.createNetwork(guid2, net2, IPv4Address.of(gw1)); assertTrue(vns.nameToGuid.get(net2).equals(guid2)); - assertTrue(vns.guidToGateway.get(guid2).equals(IPv4.toIPv4Address(gw1))); - assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid1)); - assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid2)); - assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid3)); - assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).size() == 3); + assertTrue(vns.guidToGateway.get(guid2).equals(IPv4Address.of(gw1))); + assertTrue(vns.gatewayToGuid.get(IPv4Address.of(gw1)).contains(guid1)); + assertTrue(vns.gatewayToGuid.get(IPv4Address.of(gw1)).contains(guid2)); + assertTrue(vns.gatewayToGuid.get(IPv4Address.of(gw1)).contains(guid3)); + assertTrue(vns.gatewayToGuid.get(IPv4Address.of(gw1)).size() == 3); // Modify net2 to change it's name vns.createNetwork(guid2, "newnet2", null); // Make sure the gateway is still there - assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid2)); + assertTrue(vns.gatewayToGuid.get(IPv4Address.of(gw1)).contains(guid2)); assertTrue(vns.vNetsByGuid.get(guid2).gateway.equals(gw1)); // make sure the new name mapping was learned assertTrue(vns.nameToGuid.get("newnet2").equals(guid2)); @@ -296,9 +281,9 @@ public class VirtualNetworkFilterTest extends FloodlightTestCase { testModifyNetwork(); // Delete newnet2 vns.deleteNetwork(guid2); - assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid1)); - assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).contains(guid3)); - assertTrue(vns.gatewayToGuid.get(IPv4.toIPv4Address(gw1)).size() == 2); + assertTrue(vns.gatewayToGuid.get(IPv4Address.of(gw1)).contains(guid1)); + assertTrue(vns.gatewayToGuid.get(IPv4Address.of(gw1)).contains(guid3)); + assertTrue(vns.gatewayToGuid.get(IPv4Address.of(gw1)).size() == 2); assertFalse(vns.nameToGuid.containsKey(net2)); assertFalse(vns.guidToGateway.containsKey(net2)); assertTrue(vns.vNetsByGuid.get(guid2)==null); @@ -372,7 +357,7 @@ public class VirtualNetworkFilterTest extends FloodlightTestCase { IFloodlightProviderService.bcStore.put(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD, (Ethernet)mac1ToGwPacketIntestPacket); - deviceService.learnEntity(((Ethernet)mac1ToGwPacketIntestPacket).getDestinationMAC().toLong(), + deviceService.learnEntity(((Ethernet)mac1ToGwPacketIntestPacket).getDestinationMACAddress().getLong(), null, IPv4.toIPv4Address(gw1), null, null); Command ret = listener.receive(sw1, mac1ToGwPacketIn, cntx); assertTrue(ret == Command.CONTINUE); @@ -382,7 +367,7 @@ public class VirtualNetworkFilterTest extends FloodlightTestCase { public void testDhcp() { IOFMessageListener listener = getVirtualNetworkListener(); Ethernet dhcpPacket = PacketFactory.DhcpDiscoveryRequestEthernet(mac1); - OFPacketIn dhcpPacketOf = PacketFactory.DhcpDiscoveryRequestOFPacketIn(mac1); + OFPacketIn dhcpPacketOf = PacketFactory.DhcpDiscoveryRequestOFPacketIn(sw1, mac1); cntx = new FloodlightContext(); IFloodlightProviderService.bcStore.put(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD, diff --git a/src/test/java/org/sdnplatform/sync/client/ClientTest.java b/src/test/java/org/sdnplatform/sync/client/ClientTest.java index d9c291e428cfff58f0808a01e183f98b82bb5125..a4182ad3895c63e5ef19021f920753782d2af7e7 100644 --- a/src/test/java/org/sdnplatform/sync/client/ClientTest.java +++ b/src/test/java/org/sdnplatform/sync/client/ClientTest.java @@ -8,8 +8,6 @@ import java.io.PrintStream; import java.util.ArrayList; import net.floodlightcontroller.core.module.FloodlightModuleContext; -import net.floodlightcontroller.debugcounter.IDebugCounterService; -import net.floodlightcontroller.debugcounter.NullDebugCounter; import net.floodlightcontroller.threadpool.IThreadPoolService; import net.floodlightcontroller.threadpool.ThreadPool; @@ -58,7 +56,6 @@ public class ClientTest { FloodlightModuleContext fmc = new FloodlightModuleContext(); fmc.addService(IThreadPoolService.class, tp); - fmc.addService(IDebugCounterService.class, new NullDebugCounter()); fmc.addConfigParam(syncManager, "nodes", nodeString); fmc.addConfigParam(syncManager, "thisNode", ""+1); diff --git a/src/test/java/org/sdnplatform/sync/internal/BootstrapTest.java b/src/test/java/org/sdnplatform/sync/internal/BootstrapTest.java index 5a9c40b4e1347e418c26620678ec6203b85e5cf5..d04cdaa4b8246d9c0b5a9217b924c46b082786ba 100644 --- a/src/test/java/org/sdnplatform/sync/internal/BootstrapTest.java +++ b/src/test/java/org/sdnplatform/sync/internal/BootstrapTest.java @@ -3,8 +3,6 @@ package org.sdnplatform.sync.internal; import java.io.File; import java.util.ArrayList; import net.floodlightcontroller.core.module.FloodlightModuleContext; -import net.floodlightcontroller.debugcounter.IDebugCounterService; -import net.floodlightcontroller.debugcounter.NullDebugCounter; import net.floodlightcontroller.threadpool.IThreadPoolService; import net.floodlightcontroller.threadpool.ThreadPool; @@ -61,7 +59,6 @@ public class BootstrapTest { syncManagers.add(syncManager); fmc.addService(IThreadPoolService.class, tp); - fmc.addService(IDebugCounterService.class, new NullDebugCounter()); String dbPath = new File(dbFolder.getRoot(), "server" + i).getAbsolutePath(); diff --git a/src/test/java/org/sdnplatform/sync/internal/SyncManagerTest.java b/src/test/java/org/sdnplatform/sync/internal/SyncManagerTest.java index 88a9e876661770dccc9c8362e6eeb6b710094bed..c9201b47948c498e35bbe36f7593019ade1c43c9 100644 --- a/src/test/java/org/sdnplatform/sync/internal/SyncManagerTest.java +++ b/src/test/java/org/sdnplatform/sync/internal/SyncManagerTest.java @@ -13,8 +13,6 @@ import java.util.List; import java.util.Map.Entry; import net.floodlightcontroller.core.module.FloodlightModuleContext; -import net.floodlightcontroller.debugcounter.IDebugCounterService; -import net.floodlightcontroller.debugcounter.NullDebugCounter; import net.floodlightcontroller.threadpool.IThreadPoolService; import net.floodlightcontroller.threadpool.ThreadPool; @@ -70,7 +68,6 @@ public class SyncManagerTest { SyncManager syncManager, Node thisNode) throws Exception { fmc.addService(IThreadPoolService.class, tp); - fmc.addService(IDebugCounterService.class, new NullDebugCounter()); fmc.addConfigParam(syncManager, "configProviders", PropertyCCProvider.class.getName()); fmc.addConfigParam(syncManager, "nodes", nodeString); diff --git a/src/test/java/org/sdnplatform/sync/internal/store/RemoteStoreTest.java b/src/test/java/org/sdnplatform/sync/internal/store/RemoteStoreTest.java index c269e7ed29e20d6b80577b37c5091c264757221d..1ee7f8eefa3acbdf8ee4fa0f0b30a4fa5c424950 100644 --- a/src/test/java/org/sdnplatform/sync/internal/store/RemoteStoreTest.java +++ b/src/test/java/org/sdnplatform/sync/internal/store/RemoteStoreTest.java @@ -4,8 +4,6 @@ import java.util.ArrayList; import java.util.List; import net.floodlightcontroller.core.module.FloodlightModuleContext; -import net.floodlightcontroller.debugcounter.IDebugCounterService; -import net.floodlightcontroller.debugcounter.NullDebugCounter; import net.floodlightcontroller.threadpool.IThreadPoolService; import net.floodlightcontroller.threadpool.ThreadPool; @@ -35,7 +33,6 @@ public class RemoteStoreTest extends AbstractStoreT<ByteArray,byte[]> { remoteSyncManager = new RemoteSyncManager(); fmc.addService(IThreadPoolService.class, tp); - fmc.addService(IDebugCounterService.class, new NullDebugCounter()); fmc.addConfigParam(syncManager, "persistenceEnabled", "false"); tp.init(fmc); diff --git a/src/test/java/org/sdnplatform/sync/internal/version/VectorClockInconsistencyResolverTest.java b/src/test/java/org/sdnplatform/sync/internal/version/VectorClockInconsistencyResolverTest.java index 1ad45ec9cd15400658c48085d8003a82415ce0fd..eca321f7f2bee00d6932c97171cfe14a2fc1e78b 100644 --- a/src/test/java/org/sdnplatform/sync/internal/version/VectorClockInconsistencyResolverTest.java +++ b/src/test/java/org/sdnplatform/sync/internal/version/VectorClockInconsistencyResolverTest.java @@ -58,7 +58,6 @@ public class VectorClockInconsistencyResolverTest { assertEquals(0, resolver.resolveConflicts(new ArrayList<Versioned<String>>()).size()); } - @SuppressWarnings("unchecked") @Test public void testDuplicatesResolve() { assertEquals(2, resolver.resolveConflicts(Arrays.asList(concurrent, @@ -68,7 +67,6 @@ public class VectorClockInconsistencyResolverTest { current)).size()); } - @SuppressWarnings("unchecked") @Test public void testResolveNormal() { assertEquals(later, resolver.resolveConflicts(Arrays.asList(current, prior, later)).get(0)); @@ -76,7 +74,6 @@ public class VectorClockInconsistencyResolverTest { assertEquals(later, resolver.resolveConflicts(Arrays.asList(later, current, prior)).get(0)); } - @SuppressWarnings("unchecked") @Test public void testResolveConcurrent() { List<Versioned<String>> resolved = resolver.resolveConflicts(Arrays.asList(current, @@ -87,7 +84,6 @@ public class VectorClockInconsistencyResolverTest { assertTrue("Version not found", resolved.contains(concurrent)); } - @SuppressWarnings("unchecked") @Test public void testResolveLargerConcurrent() { assertEquals(3, resolver.resolveConflicts(Arrays.asList(concurrent, @@ -99,7 +95,6 @@ public class VectorClockInconsistencyResolverTest { current)).size()); } - @SuppressWarnings("unchecked") @Test public void testResolveConcurrentPairWithLater() { Versioned<String> later2 = getVersioned(1, 2, 3, 3, 4, 4);